Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Permit sqlite_exec() to be called from within user-defined functions. (CVS 1166) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
03636c94a542b1f90a3acfbe65a9c297 |
User & Date: | drh 2004-01-07 19:24:48.000 |
Context
2004-01-07
| ||
20:37 | Rework the fix to ticket #461 so that we do not have to do redundant tests of WHERE clause terms looking for NULLs. See also check-in (1103). (CVS 1167) (check-in: 5fd581787e user: drh tags: trunk) | |
19:24 | Permit sqlite_exec() to be called from within user-defined functions. (CVS 1166) (check-in: 03636c94a5 user: drh tags: trunk) | |
18:52 | Defer the {quote: MoveTo} opcode in VDBE until the data is actually needed. Sometimes the data is never needed, resulting in a performance increase. On an indexed order search with a large OFFSET, queries times can be an order of magnitude faster. (CVS 1165) (check-in: d3e96da20d user: drh tags: trunk) | |
Changes
Changes to src/test1.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing the printf() interface to SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing the printf() interface to SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** ** $Id: test1.c,v 1.32 2004/01/07 19:24:48 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include "os.h" #include <stdlib.h> #include <string.h> |
︙ | ︙ | |||
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 | for(i=0; i<argc; i++){ if( argv[i] ){ sqlite_set_result_string(context, argv[i], -1); break; } } } /* ** Implementation of the x_sqlite_exec() function. This function takes ** a single argument and attempts to execute that argument as SQL code. ** This is illegal and should set the SQLITE_MISUSE flag on the database. ** ** This routine simulates the effect of having two threads attempt to ** use the same database at the same time. */ static void sqliteExecFunc(sqlite_func *context, int argc, const char **argv){ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > | 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 | for(i=0; i<argc; i++){ if( argv[i] ){ sqlite_set_result_string(context, argv[i], -1); break; } } } /* ** A structure into which to accumulate text. */ struct dstr { int nAlloc; /* Space allocated */ int nUsed; /* Space used */ char *z; /* The space */ }; /* ** Append text to a dstr */ static void dstrAppend(struct dstr *p, const char *z, int divider){ int n = strlen(z); if( p->nUsed + n + 2 > p->nAlloc ){ char *zNew; p->nAlloc = p->nAlloc*2 + n + 200; zNew = sqliteRealloc(p->z, p->nAlloc); if( zNew==0 ){ sqliteFree(p->z); memset(p, 0, sizeof(*p)); return; } p->z = zNew; } if( divider && p->nUsed>0 ){ p->z[p->nUsed++] = divider; } memcpy(&p->z[p->nUsed], z, n+1); p->nUsed += n; } /* ** Invoked for each callback from sqliteExecFunc */ static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){ struct dstr *p = (struct dstr*)pData; int i; for(i=0; i<argc; i++){ if( argv[i]==0 ){ dstrAppend(p, "NULL", ' '); }else{ dstrAppend(p, argv[i], ' '); } } return 0; } /* ** Implementation of the x_sqlite_exec() function. This function takes ** a single argument and attempts to execute that argument as SQL code. ** This is illegal and should set the SQLITE_MISUSE flag on the database. ** ** 2004-Jan-07: We have changed this to make it legal to call sqlite_exec() ** from within a function call. ** ** This routine simulates the effect of having two threads attempt to ** use the same database at the same time. */ static void sqliteExecFunc(sqlite_func *context, int argc, const char **argv){ struct dstr x; memset(&x, 0, sizeof(x)); sqlite_exec((sqlite*)sqlite_user_data(context), argv[0], execFuncCallback, &x, 0); sqlite_set_result_string(context, x.z, x.nUsed); sqliteFree(x.z); } /* ** Usage: sqlite_test_create_function DB ** ** Call the sqlite_create_function API on the given database in order ** to create a function named "x_coalesce". This function does the same thing |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** ** $Id: vdbe.c,v 1.248 2004/01/07 19:24:48 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 | } } ctx.pFunc = (FuncDef*)pOp->p3; ctx.s.flags = STK_Null; ctx.z = 0; ctx.isError = 0; ctx.isStep = 0; (*ctx.pFunc->xFunc)(&ctx, n, (const char**)&zStack[p->tos-n+1]); sqliteVdbePopStack(p, n); p->tos++; aStack[p->tos] = ctx.s; if( ctx.s.flags & STK_Dyn ){ zStack[p->tos] = ctx.z; }else if( ctx.s.flags & STK_Str ){ zStack[p->tos] = aStack[p->tos].z; | > > | 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 | } } ctx.pFunc = (FuncDef*)pOp->p3; ctx.s.flags = STK_Null; ctx.z = 0; ctx.isError = 0; ctx.isStep = 0; if( sqliteSafetyOff(db) ) goto abort_due_to_misuse; (*ctx.pFunc->xFunc)(&ctx, n, (const char**)&zStack[p->tos-n+1]); if( sqliteSafetyOn(db) ) goto abort_due_to_misuse; sqliteVdbePopStack(p, n); p->tos++; aStack[p->tos] = ctx.s; if( ctx.s.flags & STK_Dyn ){ zStack[p->tos] = ctx.z; }else if( ctx.s.flags & STK_Str ){ zStack[p->tos] = aStack[p->tos].z; |
︙ | ︙ |
Changes to test/misuse.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 | # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for the SQLITE_MISUSE detection logic. # This test file leaks memory and file descriptors. # | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for the SQLITE_MISUSE detection logic. # This test file leaks memory and file descriptors. # # $Id: misuse.test,v 1.4 2004/01/07 19:24:48 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Make sure the test logic works # do_test misuse-1.1 { |
︙ | ︙ | |||
36 37 38 39 40 41 42 43 44 45 | do_test misuse-1.3 { sqlite_create_function $::DB sqlite_exec_printf $::DB {SELECT x_coalesce(NULL,a) AS 'xyz' FROM t1} {} } {0 {xyz 1}} # Use the x_sqlite_exec() SQL function to simulate the effect of two # threads trying to use the same database at the same time. # do_test misuse-1.4 { sqlite_exec_printf $::DB { | > > > > | | | | | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | do_test misuse-1.3 { sqlite_create_function $::DB sqlite_exec_printf $::DB {SELECT x_coalesce(NULL,a) AS 'xyz' FROM t1} {} } {0 {xyz 1}} # Use the x_sqlite_exec() SQL function to simulate the effect of two # threads trying to use the same database at the same time. # # It used to be prohibited to invoke sqlite_exec() from within a function, # but that has changed. The following tests used to cause errors but now # they do not. # do_test misuse-1.4 { sqlite_exec_printf $::DB { SELECT x_sqlite_exec('SELECT * FROM t1') AS xyz; } {} } {0 {xyz {1 2}}} do_test misuse-1.5 { sqlite_exec_printf $::DB {SELECT * FROM t1} {} } {0 {a b 1 2}} do_test misuse-1.6 { catchsql { SELECT * FROM t1 } } {0 {1 2}} # Attempt to register a new SQL function while an sqlite_exec() is active. # do_test misuse-2.1 { db close set ::DB [sqlite db test2.db] execsql { |
︙ | ︙ |