Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Return an error if an attempt is made to create a trigger with an SQL variable embedded within it. If such a variable reference is found within a trigger definition loaded from the sqlite_master table, silently replace it with a NULL. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
f35f6ae3da77dbdf5f7a4a9927475659 |
User & Date: | dan 2013-10-03 12:29:38.279 |
Context
2013-10-03
| ||
14:08 | Rework the PRAGMA implementation to only call sqlite3ReadSchema() from a single place, based on a flag in the pragma table, rather than separately from each case which needs the schema. (check-in: 8338232a11 user: drh tags: trunk) | |
12:29 | Return an error if an attempt is made to create a trigger with an SQL variable embedded within it. If such a variable reference is found within a trigger definition loaded from the sqlite_master table, silently replace it with a NULL. (check-in: f35f6ae3da user: dan tags: trunk) | |
11:27 | Remove unnecessary memset() calls from test code. (check-in: eec3187bc6 user: drh tags: trunk) | |
Changes
Changes to src/attach.c.
︙ | ︙ | |||
426 427 428 429 430 431 432 | Parse *pParse, /* Error messages will be written here */ int iDb, /* This is the database that must be used */ const char *zType, /* "view", "trigger", or "index" */ const Token *pName /* Name of the view, trigger, or index */ ){ sqlite3 *db; | | > | 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 | Parse *pParse, /* Error messages will be written here */ int iDb, /* This is the database that must be used */ const char *zType, /* "view", "trigger", or "index" */ const Token *pName /* Name of the view, trigger, or index */ ){ sqlite3 *db; if( NEVER(iDb<0) ) return 0; db = pParse->db; assert( db->nDb>iDb ); pFix->pParse = pParse; pFix->zDb = db->aDb[iDb].zName; pFix->pSchema = db->aDb[iDb].pSchema; pFix->zType = zType; pFix->pName = pName; pFix->bVarOnly = (iDb==1); return 1; } /* ** The following set of routines walk through the parse tree and assign ** a specific database to all table references where the database name ** was left unspecified in the original SQL statement. The pFix structure |
︙ | ︙ | |||
462 463 464 465 466 467 468 | int i; const char *zDb; struct SrcList_item *pItem; if( NEVER(pList==0) ) return 0; zDb = pFix->zDb; for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){ | > | | | | | | | | | > | 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 | int i; const char *zDb; struct SrcList_item *pItem; if( NEVER(pList==0) ) return 0; zDb = pFix->zDb; for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){ if( pFix->bVarOnly==0 ){ if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){ sqlite3ErrorMsg(pFix->pParse, "%s %T cannot reference objects in database %s", pFix->zType, pFix->pName, pItem->zDatabase); return 1; } sqlite3DbFree(pFix->pParse->db, pItem->zDatabase); pItem->zDatabase = 0; pItem->pSchema = pFix->pSchema; } #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1; if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1; #endif } return 0; } |
︙ | ︙ | |||
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 | return 1; } if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){ return 1; } if( sqlite3FixExpr(pFix, pSelect->pWhere) ){ return 1; } if( sqlite3FixExpr(pFix, pSelect->pHaving) ){ return 1; } pSelect = pSelect->pPrior; } return 0; } int sqlite3FixExpr( DbFixer *pFix, /* Context of the fixation */ Expr *pExpr /* The expression to be fixed to one database */ ){ while( pExpr ){ if( ExprHasProperty(pExpr, EP_TokenOnly) ) break; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1; }else{ if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1; } if( sqlite3FixExpr(pFix, pExpr->pRight) ){ | > > > > > > > > > > > > > > > > > > > > | 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 | return 1; } if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){ return 1; } if( sqlite3FixExpr(pFix, pSelect->pWhere) ){ return 1; } if( sqlite3FixExprList(pFix, pSelect->pGroupBy) ){ return 1; } if( sqlite3FixExpr(pFix, pSelect->pHaving) ){ return 1; } if( sqlite3FixExprList(pFix, pSelect->pOrderBy) ){ return 1; } if( sqlite3FixExpr(pFix, pSelect->pLimit) ){ return 1; } if( sqlite3FixExpr(pFix, pSelect->pOffset) ){ return 1; } pSelect = pSelect->pPrior; } return 0; } int sqlite3FixExpr( DbFixer *pFix, /* Context of the fixation */ Expr *pExpr /* The expression to be fixed to one database */ ){ while( pExpr ){ if( pExpr->op==TK_VARIABLE ){ if( pFix->pParse->db->init.busy ){ pExpr->op = TK_NULL; }else{ sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType); return 1; } } if( ExprHasProperty(pExpr, EP_TokenOnly) ) break; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1; }else{ if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1; } if( sqlite3FixExpr(pFix, pExpr->pRight) ){ |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 | ** routines as they walk the parse tree to make database references ** explicit. */ typedef struct DbFixer DbFixer; struct DbFixer { Parse *pParse; /* The parsing context. Error messages written here */ Schema *pSchema; /* Fix items to this schema */ const char *zDb; /* Make sure all objects are contained in this database */ const char *zType; /* Type of the container - used for error messages */ const Token *pName; /* Name of the container - used for error messages */ }; /* ** An objected used to accumulate the text of a string where we | > | 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 | ** routines as they walk the parse tree to make database references ** explicit. */ typedef struct DbFixer DbFixer; struct DbFixer { Parse *pParse; /* The parsing context. Error messages written here */ Schema *pSchema; /* Fix items to this schema */ int bVarOnly; /* Check for variable references only */ const char *zDb; /* Make sure all objects are contained in this database */ const char *zType; /* Type of the container - used for error messages */ const Token *pName; /* Name of the container - used for error messages */ }; /* ** An objected used to accumulate the text of a string where we |
︙ | ︙ |
Changes to src/trigger.c.
︙ | ︙ | |||
287 288 289 290 291 292 293 | pTrig->step_list = pStepList; while( pStepList ){ pStepList->pTrig = pTrig; pStepList = pStepList->pNext; } nameToken.z = pTrig->zName; nameToken.n = sqlite3Strlen30(nameToken.z); | | | > > | 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 | pTrig->step_list = pStepList; while( pStepList ){ pStepList->pTrig = pTrig; pStepList = pStepList->pNext; } nameToken.z = pTrig->zName; nameToken.n = sqlite3Strlen30(nameToken.z); if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken) && ( sqlite3FixTriggerStep(&sFix, pTrig->step_list) || sqlite3FixExpr(&sFix, pTrig->pWhen) )){ goto triggerfinish_cleanup; } /* if we are not initializing, ** build the sqlite_master entry */ if( !db->init.busy ){ |
︙ | ︙ |
Added test/triggerE.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 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 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | # 2009 December 29 # # The author disclaims copyright to this source code. In place of # a legal notice', here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # This file tests the effects of SQL variable references embedded in # triggers. If the user attempts to create such a trigger, it is an # error. However, if an existing trigger definition is read from # the sqlite_master table, the variable reference always evaluates # to NULL. # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable {!trigger} { finish_test return } set testprefix triggerE do_execsql_test 1.0 { CREATE TABLE t1(a, b); CREATE TABLE t2(c, d); CREATE TABLE t3(e, f); } # forcedelete test.db2 # do_execsql_test 1.1 { # ATTACH 'test.db2' AS aux; # CREATE TABLE aux.t4(x); # INSERT INTO aux.t4 VALUES(5); # # CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN new.a IN (SELECT x FROM aux.t4) # BEGIN # SELECT 1; # END; # } # do_execsql_test 1.2 { INSERT INTO t1 VALUES(1,1); } # do_execsql_test 1.3 { INSERT INTO t1 VALUES(5,5); } #------------------------------------------------------------------------- # Attempt to create various triggers that use bound variables. # set errmsg "trigger cannot use variables" foreach {tn defn} { 1 { AFTER INSERT ON t1 WHEN new.a = ? BEGIN SELECT 1; END; } 2 { BEFORE DELETE ON t1 BEGIN SELECT ?; END; } 3 { BEFORE DELETE ON t1 BEGIN SELECT * FROM (SELECT * FROM (SELECT ?)); END; } 5 { BEFORE DELETE ON t1 BEGIN SELECT * FROM t2 GROUP BY ?; END; } 6 { BEFORE DELETE ON t1 BEGIN SELECT * FROM t2 LIMIT ?; END; } 7 { BEFORE DELETE ON t1 BEGIN SELECT * FROM t2 ORDER BY ?; END; } 8 { BEFORE UPDATE ON t1 BEGIN UPDATE t2 SET c = ?; END; } 9 { BEFORE UPDATE ON t1 BEGIN UPDATE t2 SET c = 1 WHERE d = ?; END; } } { catchsql {drop trigger tr1} do_catchsql_test 1.1.$tn "CREATE TRIGGER tr1 $defn" [list 1 $errmsg] do_catchsql_test 1.2.$tn "CREATE TEMP TRIGGER tr1 $defn" [list 1 $errmsg] } #------------------------------------------------------------------------- # Test that variable references within trigger definitions loaded from # the sqlite_master table are automatically converted to NULL. # do_execsql_test 2.1 { PRAGMA writable_schema = 1; INSERT INTO sqlite_master VALUES('trigger', 'tr1', 't1', 0, 'CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN INSERT INTO t2 VALUES(?1, ?2); END' ); INSERT INTO sqlite_master VALUES('trigger', 'tr2', 't3', 0, 'CREATE TRIGGER tr2 AFTER INSERT ON t3 WHEN ?1 IS NULL BEGIN UPDATE t2 SET c=d WHERE c IS ?2; END' ); } db close sqlite3 db test.db do_execsql_test 2.2.1 { INSERT INTO t1 VALUES(1, 2); SELECT * FROM t2; } {{} {}} do_test 2.2.2 { set one 3 execsql { DELETE FROM t2; INSERT INTO t1 VALUES($one, ?1); SELECT * FROM t2; } } {{} {}} do_execsql_test 2.2.3 { SELECT * FROM t1 } {1 2 3 3} do_execsql_test 2.3 { DELETE FROM t2; INSERT INTO t2 VALUES('x', 'y'); INSERT INTO t2 VALUES(NULL, 'z'); INSERT INTO t3 VALUES(1, 2); SELECT * FROM t3; SELECT * FROM t2; } {1 2 x y z z} finish_test |