Commit 48d7497d902f22cafcf5642919f74fbf921bdf7f

Authored by Cédric RICARD
1 parent 44c1a078

Improved low level SQLite API

anubis_dev/compiler/src/predef.anubis
... ... @@ -3244,11 +3244,11 @@ define List(String)
3244 3244  
3245 3245  
3246 3246 Reseting a statement.
3247   -type £SQLite3ResetResult:
  3247 + type £SQLite3ResetResult:
3248 3248 error(Word32 error_code, String error_msg),
3249 3249 ok.
3250 3250  
3251   -define £SQLite3ResetResult
  3251 +define SQLite3Result
3252 3252 £do_reset
3253 3253 (
3254 3254 £StructPtr(SQLite3Stmt) stmt,
... ... @@ -3258,7 +3258,7 @@ define £SQLite3ResetResult
3258 3258  
3259 3259 Binding values to parameters.
3260 3260  
3261   -define Word32
  3261 +define SQLite3Result
3262 3262 £bind_Int
3263 3263 (
3264 3264 £StructPtr(SQLite3Stmt) stmt,
... ... @@ -3266,7 +3266,7 @@ define Word32
3266 3266 Int value
3267 3267 ) = £avm{ sqlite3_bind_Int }.
3268 3268  
3269   -define Word32
  3269 +define SQLite3Result
3270 3270 £bind_Float
3271 3271 (
3272 3272 £StructPtr(SQLite3Stmt) stmt,
... ... @@ -3274,7 +3274,7 @@ define Word32
3274 3274 Float value
3275 3275 ) = £avm{ sqlite3_bind_Float }.
3276 3276  
3277   -define Word32
  3277 +define SQLite3Result
3278 3278 £bind_String
3279 3279 (
3280 3280 £StructPtr(SQLite3Stmt) stmt,
... ... @@ -3282,7 +3282,7 @@ define Word32
3282 3282 String value
3283 3283 ) = £avm{ sqlite3_bind_String }.
3284 3284  
3285   -define Word32
  3285 +define SQLite3Result
3286 3286 £bind_ByteArray
3287 3287 (
3288 3288 £StructPtr(SQLite3Stmt) stmt,
... ... @@ -3290,7 +3290,7 @@ define Word32
3290 3290 ByteArray value
3291 3291 ) = £avm{ sqlite3_bind_ByteArray }.
3292 3292  
3293   -define Word32
  3293 +define SQLite3Result
3294 3294 £bind_NULL
3295 3295 (
3296 3296 £StructPtr(SQLite3Stmt) stmt,
... ... @@ -3308,7 +3308,6 @@ define Word32
3308 3308 define SQLite3Result
3309 3309 £do_bind
3310 3310 (
3311   - £StructPtr(SQLite3) db,
3312 3311 £StructPtr(SQLite3Stmt) stmt,
3313 3312 List(SQLite3Bind) bindings
3314 3313 ) =
... ... @@ -3320,42 +3319,47 @@ define SQLite3Result
3320 3319 bind_Int(name,value) then with index = £parameter_index(stmt,name),
3321 3320 if index = 0
3322 3321 then error(sqlite3(12,"Parameter name not found: '"+name+"'."))
3323   - else with code = £bind_Int(stmt,index,value),
3324   - if code = 0
3325   - then £do_bind(db,stmt,t)
3326   - else error(sqlite3(code,£sqlite3_errmsg(db))),
3327   -
  3322 + else if(£bind_Int(stmt,index,value)) is
  3323 + {
  3324 + error(e) then error(e),
  3325 + ok then £do_bind(stmt,t)
  3326 + },
  3327 +
3328 3328 bind_Float(name,value) then with index = £parameter_index(stmt,name),
3329 3329 if index = 0
3330 3330 then error(sqlite3(12,"Parameter name not found: '"+name+"'."))
3331   - else with code = £bind_Float(stmt,index,value),
3332   - if code = 0
3333   - then £do_bind(db,stmt,t)
3334   - else error(sqlite3(code,£sqlite3_errmsg(db))),
  3331 + else if £bind_Float(stmt,index,value) is
  3332 + {
  3333 + error(e) then error(e),
  3334 + ok then £do_bind(stmt,t)
  3335 + },
3335 3336  
3336 3337 bind_String(name,value) then with index = £parameter_index(stmt,name),
3337 3338 if index = 0
3338 3339 then error(sqlite3(12,"Parameter name not found: '"+name+"'."))
3339   - else with code = £bind_String(stmt,index,value),
3340   - if code = 0
3341   - then £do_bind(db,stmt,t)
3342   - else error(sqlite3(code,£sqlite3_errmsg(db))),
  3340 + else if £bind_String(stmt,index,value) is
  3341 + {
  3342 + error(e) then error(e),
  3343 + ok then £do_bind(stmt,t)
  3344 + },
3343 3345  
3344 3346 bind_ByteArray(name,value) then with index = £parameter_index(stmt,name),
3345 3347 if index = 0
3346 3348 then error(sqlite3(12,"Parameter name not found: '"+name+"'."))
3347   - else with code = £bind_ByteArray(stmt,index,value),
3348   - if code = 0
3349   - then £do_bind(db,stmt,t)
3350   - else error(sqlite3(code,£sqlite3_errmsg(db))),
  3349 + else if £bind_ByteArray(stmt,index,value) is
  3350 + {
  3351 + error(e) then error(e),
  3352 + ok then £do_bind(stmt,t)
  3353 + },
3351 3354  
3352 3355 bind_NULL(name) then with index = £parameter_index(stmt,name),
3353 3356 if index = 0
3354 3357 then error(sqlite3(12,"Parameter name not found: '"+name+"'."))
3355   - else with code = £bind_NULL(stmt,index),
3356   - if code = 0
3357   - then £do_bind(db,stmt,t)
3358   - else error(sqlite3(code,£sqlite3_errmsg(db)))
  3358 + else if £bind_NULL(stmt,index) is
  3359 + {
  3360 + error(e) then error(e),
  3361 + ok then £do_bind(stmt,t)
  3362 + },
3359 3363 }
3360 3364 }.
3361 3365  
... ... @@ -3402,7 +3406,7 @@ public define SQLite3QueryResult
3402 3406 {
3403 3407 error(i) then error(sqlite3(i,£sqlite3_errmsg(db1))),
3404 3408 ok(stmt) then
3405   - if £do_bind(db1,stmt,initial_bindings) is
  3409 + if £do_bind(stmt,initial_bindings) is
3406 3410 {
3407 3411 error(msg) then error(msg),
3408 3412 ok then if £go_to_next_row(stmt) is
... ... @@ -3411,12 +3415,12 @@ public define SQLite3QueryResult
3411 3415 no_more_row then ok((One u) |-> £list_headers(stmt,£column_count(stmt),0),
3412 3416 (One u) |-> no_more_row,
3413 3417 (List(SQLite3Bind) bindings) |->
3414   - forget(£do_reset(stmt)); £do_bind(db1,stmt,bindings)),
  3418 + forget(£do_reset(stmt)); £do_bind(stmt,bindings)),
3415 3419 /* the first row exists */
3416 3420 row then ok((One u) |-> £list_headers(stmt,£column_count(stmt),0),
3417 3421 £make_new_cursor(db1,stmt,true),
3418 3422 (List(SQLite3Bind) bindings) |->
3419   - forget(£do_reset(stmt)); £do_bind(db1,stmt,bindings)),
  3423 + forget(£do_reset(stmt)); £do_bind(stmt,bindings)),
3420 3424 /* error */
3421 3425 error(c,m) then error(sqlite3(c,m))
3422 3426 }
... ... @@ -3446,14 +3450,12 @@ public define Result(SQLite3Error, SQLite3Stmt)
3446 3450 public define SQLite3Result
3447 3451 sqlite3_bind
3448 3452 (
3449   - SQLite3DataBase db,
3450 3453 SQLite3Stmt stmt,
3451 3454 List(SQLite3Bind) bindings
3452 3455 ) =
3453   - if db is £database(db1) then
3454 3456 if stmt is £statement(stmt1) then
3455 3457 protect
3456   - £do_bind(db1, stmt1, bindings).
  3458 + £do_bind(stmt1, bindings).
3457 3459  
3458 3460 public define SQLite3Row
3459 3461 sqlite3_step
... ... @@ -3477,11 +3479,7 @@ public define SQLite3Result
3477 3479 SQLite3Stmt stmt,
3478 3480 ) =
3479 3481 if stmt is £statement(stmt1) then
3480   - if £do_reset(stmt1) is
3481   - {
3482   - error(c,m) then error(sqlite3(c,m))
3483   - ok then ok
3484   - }.
  3482 + £do_reset(stmt1).
3485 3483  
3486 3484  
3487 3485  
... ...
anubis_dev/library/predefined.anubis
... ... @@ -4152,16 +4152,6 @@ public define SQLite3QueryResult
4152 4152 List(SQLite3Bind) initial_bindings // initial parameter bindings
4153 4153 ).
4154 4154  
4155   - You can just prepare the query (but not begin its execution) with the following:
4156   -
4157   -public define SQLite3QueryResult
4158   - sqlite3_prepare
4159   - (
4160   - SQLite3DataBase db, // the database
4161   - String sql_command, // the SQL query
4162   - List(SQLite3Bind) initial_bindings // initial parameter bindings
4163   - ).
4164   -
4165 4155 For your convenience, we also provide the following variant to be used when no
4166 4156 parameter binding is needed. This is the case whenever the SQL query does not contain
4167 4157 any parameter name. In this case the reset function returned by sqlite3_query is also
... ...
anubis_dev/library/test/predefined/sqlite.unit_test.anubis
... ... @@ -265,13 +265,13 @@ define One
265 265 {
266 266 error(err) then println("SQL ERROR: " + err.code + " - " + err.text); assertIsTrue (ut, false, "SELECT datum"),
267 267 ok(stmt) then
268   - assertIsSame(ut, sqlite3_bind(db, stmt, [bind_String("@val", "Line 3")]), ok, "binding");
  268 + assertIsSame(ut, sqlite3_bind(stmt, [bind_String("@val", "Line 3")]), ok, "binding");
269 269 if sqlite3_step(stmt) is row(r) then
270 270 assertIsSameString(ut, if r(0) is text(val) then val else "X", "Line 3");
271 271 assertIsSame(ut, sqlite3_step(stmt), no_more_row,"No more row");
272 272  
273 273 assertIsSame(ut, sqlite3_reset(stmt), ok, "reseting statement");
274   - assertIsSame(ut, sqlite3_bind(db, stmt, [bind_String("@val", "Line 1")]), ok, "binding again");
  274 + assertIsSame(ut, sqlite3_bind(stmt, [bind_String("@val", "Line 1")]), ok, "binding again");
275 275 if sqlite3_step(stmt) is row(r) then
276 276 assertIsSameString(ut, if r(0) is text(val) then val else "X", "Line 1");
277 277 assertIsSame(ut, sqlite3_step(stmt), no_more_row,"No more row")
... ...
anubis_dev/vm/src/AnubisProcess.h
... ... @@ -15,6 +15,7 @@
15 15 #include "vm.h"
16 16 #include "bytecode.h"
17 17 #include "Profiling.h"
  18 +#include "sqlite3.h"
18 19  
19 20 BEGIN_NAMESPACE(CM);
20 21 //class AnubisAllocator;
... ... @@ -105,6 +106,9 @@ public:
105 106 static FunctionSummary * GetFunction(int32 label);
106 107 FunctionCall * CurrentFunction() const { return m_current_function; }
107 108  
  109 +private:
  110 + bool MakeSQLite3Result(sqlite3_stmt * stmt, int error_code);
  111 +
108 112 protected:
109 113 private:
110 114 U32 m_pid; /* process unique id */
... ...
anubis_dev/vm/src/syscall.cpp
... ... @@ -261,7 +261,93 @@ U32 allocate_list(AnubisAllocator *allocator,
261 261 return result;
262 262 }
263 263  
264   -
  264 +// code factorization for all SQLite3 instruction returning a SQLite3Result
  265 +// Returns true if the instruction has finished.
  266 +bool AnubisProcess::MakeSQLite3Result(sqlite3_stmt * stmt, int error_code)
  267 +{
  268 + switch(error_code)
  269 + {
  270 + case SQLITE_OK:
  271 + m_R = 1;
  272 + break;
  273 +
  274 + default: //otherwise error
  275 + {
  276 + U32 error_seg = NULL, string_seg = NULL;;
  277 + const char *msg = NULL;
  278 + if(m_duc_non_empty)
  279 + msg = (const char*)m_DUC2;
  280 + else
  281 + {
  282 + sqlite3 *db = sqlite3_db_handle( stmt );
  283 + msg = sqlite3_errmsg(db);
  284 + }
  285 + if(msg == NULL)
  286 + {
  287 + msg = "OUT OF MEMORY";
  288 + }
  289 +
  290 + /* get the SQlite3Result memory segment */
  291 + if ((m_R = m_allocator->AllocateDataSegment(2)) == 0)
  292 + {
  293 + if(!m_duc_non_empty)
  294 + {
  295 + m_DUC1 = error_code;
  296 + m_DUC2 = (U32)strdup(msg);
  297 + m_duc_non_empty = 1;
  298 + }
  299 + m_status = need_more_memory;
  300 + { m_steps = 0; return false; }
  301 + }
  302 +
  303 + /* get the SQLite3Error memory segment */
  304 + if ((error_seg = m_allocator->AllocateDataSegment(3)) == 0)
  305 + {
  306 + if(!m_duc_non_empty)
  307 + {
  308 + m_DUC1 = error_code;
  309 + m_DUC2 = (U32)strdup(msg);
  310 + m_duc_non_empty = 1;
  311 + }
  312 + m_allocator->FreeDataSegment((U32 *)(m_R));
  313 + m_status = need_more_memory;
  314 + { m_steps = 0; return false; }
  315 + }
  316 +
  317 + /* get the string memory segment */
  318 + if (( string_seg = m_allocator->AllocateDataSegment(byte_size_to_word_size(strlen(msg)+5))) == 0)
  319 + {
  320 + if(!m_duc_non_empty)
  321 + {
  322 + m_DUC1 = error_code;
  323 + m_DUC2 = (U32)strdup(msg);
  324 + m_duc_non_empty = 1;
  325 + }
  326 + m_allocator->FreeDataSegment((U32 *)(m_R));
  327 + m_allocator->FreeDataSegment((U32 *)(error_seg));
  328 + m_status = need_more_memory;
  329 + { m_steps = 0; return false; }
  330 + }
  331 +
  332 + int i = 0;
  333 + while (msg[i] != 0) { ((char *)(string_seg))[i+4] = msg[i]; i++; }
  334 + ((char *)(string_seg))[i+4] = 0;
  335 +
  336 + ((U32 *)(m_R))[1] = error_seg;
  337 + ((U32 *)(error_seg))[1] = error_code;
  338 + ((U32 *)(error_seg))[2] = string_seg;
  339 +
  340 + if(m_duc_non_empty)
  341 + {
  342 + if(m_DUC2)
  343 + free((void*)m_DUC2);
  344 + m_duc_non_empty = 0;
  345 + }
  346 +
  347 + }
  348 + }
  349 + return true;
  350 +}
265 351  
266 352  
267 353 /* The 'syscall' instruction. */
... ... @@ -8697,74 +8783,9 @@ ci_decl(syscall)
8697 8783 else
8698 8784 value = sqlite3_reset(stmt);
8699 8785  
8700   - switch(value)
8701   - {
8702   - case SQLITE_OK: //no_more_row
8703   - MAM(m_R) = 1;
8704   - break;
8705   -
8706   - default: //otherwise error
8707   - {
8708   - U32 second_seg = NULL;
8709   - const char *msg = NULL;
8710   - if(MAM(m_duc_non_empty))
8711   - msg = (const char*)MAM(m_DUC2);
8712   - else
8713   - {
8714   - sqlite3 *db = sqlite3_db_handle( stmt );
8715   - msg = sqlite3_errmsg(db);
8716   - }
8717   - if(msg == NULL)
8718   - {
8719   - msg = "OUT OF MEMORY";
8720   - }
8721   -
8722   - /* get the fist memory segment */
8723   - if ((MAM(m_R) = MAM(m_allocator)->AllocateDataSegment(3)) == 0)
8724   - {
8725   - if(!MAM(m_duc_non_empty))
8726   - {
8727   - MAM(m_DUC1) = value;
8728   - MAM(m_DUC2) = (U32)strdup(msg);
8729   - MAM(m_duc_non_empty) = 1;
8730   - }
8731   - MAM(m_status) = need_more_memory;
8732   - { MAM(m_steps) = 0; return; }
8733   - }
8734   -
8735   - /* get the second memory segment */
8736   - if (( second_seg = MAM(m_allocator)->AllocateDataSegment(byte_size_to_word_size(strlen(msg)+5))) == 0)
8737   - {
8738   - if(!MAM(m_duc_non_empty))
8739   - {
8740   - MAM(m_DUC1) = value;
8741   - MAM(m_DUC2) = (U32)strdup(msg);
8742   - MAM(m_duc_non_empty) = 1;
8743   - }
8744   - MAM(m_allocator)->FreeDataSegment((U32 *)(MAM(m_R)));
8745   - MAM(m_status) = need_more_memory;
8746   - { MAM(m_steps) = 0; return; }
8747   - }
8748   -
8749   - int i = 0;
8750   - while (msg[i] != 0) { ((char *)(second_seg))[i+4] = msg[i]; i++; }
8751   - ((char *)(second_seg))[i+4] = 0;
8752   -
8753   - ((U32 *)(MAM(m_R)))[1] = value;
8754   - ((U32 *)(MAM(m_R)))[2] = second_seg;
8755   -
8756   - if(MAM(m_duc_non_empty))
8757   - {
8758   - if(MAM(m_DUC2))
8759   - free((void*)MAM(m_DUC2));
8760   - MAM(m_duc_non_empty) = 0;
8761   - }
8762   -
8763   - }
8764   - }
8765   -
  8786 + if(MAM(MakeSQLite3Result(stmt, value)))
  8787 + MAM(m_IP) += 1+2;
8766 8788 }
8767   - MAM(m_IP) += 1+2;
8768 8789 return;
8769 8790  
8770 8791 /* Expects: at *(SP-1): £StructPtr(SQLite3Stmt) stmt
... ... @@ -8782,7 +8803,12 @@ ci_decl(syscall)
8782 8803 /* must transform the value into an Int64 */
8783 8804 int64 val64 = Anubis_Int_to_int64(value);
8784 8805  
8785   - MAM(m_R) = sqlite3_bind_int64(stmt,index,val64);
  8806 + int result = 0;
  8807 + if(MAM(m_duc_non_empty))
  8808 + result = MAM(m_DUC1);
  8809 + else
  8810 + result = sqlite3_bind_int64(stmt,index,val64);
  8811 +
8786 8812 /* According to Sqlite3 doc, sqlite3_int64 is long long int, the same as our
8787 8813 int64. The following is copy pasted from that doc:
8788 8814  
... ... @@ -8800,8 +8826,9 @@ ci_decl(syscall)
8800 8826 typedef sqlite_uint64 sqlite3_uint64;
8801 8827  
8802 8828 */
  8829 + if(MAM(MakeSQLite3Result(stmt, result)))
  8830 + MAM(m_IP) += 1+2;
8803 8831 }
8804   - MAM(m_IP) += 1+2;
8805 8832 return;
8806 8833  
8807 8834  
... ... @@ -8827,9 +8854,15 @@ ci_decl(syscall)
8827 8854 +---------+---------+---------+
8828 8855  
8829 8856 */
8830   - MAM(m_R) = sqlite3_bind_double(stmt,index,value);
  8857 + int result = 0;
  8858 + if(MAM(m_duc_non_empty))
  8859 + result = MAM(m_DUC1);
  8860 + else
  8861 + result = sqlite3_bind_double(stmt,index,value);
  8862 +
  8863 + if(MAM(MakeSQLite3Result(stmt, result)))
  8864 + MAM(m_IP) += 1+2;
8831 8865 }
8832   - MAM(m_IP) += 1+2;
8833 8866 return;
8834 8867  
8835 8868  
... ... @@ -8845,7 +8878,11 @@ ci_decl(syscall)
8845 8878 U32 index = *(MAM(m_SP)-2);
8846 8879 const char * value = ((char *)(*(MAM(m_SP)-3)))+4;
8847 8880  
8848   - MAM(m_R) = sqlite3_bind_text(stmt,index,value,-1,SQLITE_TRANSIENT);
  8881 + int result = 0;
  8882 + if(MAM(m_duc_non_empty))
  8883 + result = MAM(m_DUC1);
  8884 + else
  8885 + result = sqlite3_bind_text(stmt,index,value,-1,SQLITE_TRANSIENT);
8849 8886 /* Extracted from Sqlite3 doc (http://www.sqlite.org):
8850 8887  
8851 8888 If the fourth parameter is negative, the length of the string is the number of
... ... @@ -8855,8 +8892,10 @@ ci_decl(syscall)
8855 8892 private copy of the data immediately, before the sqlite3_bind_*() routine
8856 8893 returns.
8857 8894 */
  8895 +
  8896 + if(MAM(MakeSQLite3Result(stmt, result)))
  8897 + MAM(m_IP) += 1+2;
8858 8898 }
8859   - MAM(m_IP) += 1+2;
8860 8899 return;
8861 8900  
8862 8901  
... ... @@ -8874,7 +8913,11 @@ ci_decl(syscall)
8874 8913 const void * value = (void *)(((char *)(*(MAM(m_SP)-3)))+8);
8875 8914 U32 size = ((U32 *)(*(MAM(m_SP)-3)))[1]; /* size of the byte array */
8876 8915  
8877   - MAM(m_R) = sqlite3_bind_blob(stmt,index,value,size,SQLITE_TRANSIENT);
  8916 + int result = 0;
  8917 + if(MAM(m_duc_non_empty))
  8918 + result = MAM(m_DUC1);
  8919 + else
  8920 + result = sqlite3_bind_blob(stmt,index,value,size,SQLITE_TRANSIENT);
8878 8921 /* Extracted from Sqlite3 doc (http://www.sqlite.org):
8879 8922  
8880 8923 If the fourth parameter is negative, the length of the string is the number of
... ... @@ -8884,8 +8927,10 @@ ci_decl(syscall)
8884 8927 private copy of the data immediately, before the sqlite3_bind_*() routine
8885 8928 returns.
8886 8929 */
  8930 +
  8931 + if(MAM(MakeSQLite3Result(stmt, result)))
  8932 + MAM(m_IP) += 1+2;
8887 8933 }
8888   - MAM(m_IP) += 1+2;
8889 8934 return;
8890 8935  
8891 8936  
... ... @@ -8899,9 +8944,15 @@ ci_decl(syscall)
8899 8944 sqlite3_stmt * stmt = (sqlite3_stmt *)(((U32 *)(*(MAM(m_SP)-1)))[1]);
8900 8945 U32 index = *(MAM(m_SP)-2);
8901 8946  
8902   - MAM(m_R) = sqlite3_bind_null(stmt,index);
  8947 + int result = 0;
  8948 + if(MAM(m_duc_non_empty))
  8949 + result = MAM(m_DUC1);
  8950 + else
  8951 + result = sqlite3_bind_null(stmt,index);
  8952 +
  8953 + if(MAM(MakeSQLite3Result(stmt, result)))
  8954 + MAM(m_IP) += 1+2;
8903 8955 }
8904   - MAM(m_IP) += 1+2;
8905 8956 return;
8906 8957  
8907 8958  
... ...