Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix compilation with OMIT_TRIGGER defined. Ticket [1ff6d29030]. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
fb6ceed388f6d75bdc2ac2f43e5c98da |
User & Date: | dan 2009-09-21 16:06:04.000 |
Context
2009-09-21
| ||
16:34 | Fix compilation with both OMIT_UTF16 and ENABLE_STAT2 defined. Ticket [56928bd084]. (check-in: cd850d49a1 user: dan tags: trunk) | |
16:06 | Fix compilation with OMIT_TRIGGER defined. Ticket [1ff6d29030]. (check-in: fb6ceed388 user: dan tags: trunk) | |
2009-09-19
| ||
17:59 | Add fkey.c to the autoconf and amalgamation build systems. (check-in: aab7a4b3c9 user: dan tags: trunk) | |
Changes
Changes to src/delete.c.
︙ | ︙ | |||
435 436 437 438 439 440 441 442 443 444 445 446 447 448 | delete_from_cleanup: sqlite3AuthContextPop(&sContext); sqlite3SrcListDelete(db, pTabList); sqlite3ExprDelete(db, pWhere); return; } /* ** This routine generates VDBE code that causes a single row of a ** single table to be deleted. ** ** The VDBE must be in a particular state when this routine is called. ** These are the requirements: | > > > > > > > > > | 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 | delete_from_cleanup: sqlite3AuthContextPop(&sContext); sqlite3SrcListDelete(db, pTabList); sqlite3ExprDelete(db, pWhere); return; } /* Make sure "isView" and other macros defined above are undefined. Otherwise ** thely may interfere with compilation of other functions in this file ** (or in another file, if this file becomes part of the amalgamation). */ #ifdef isView #undef isView #endif #ifdef pTrigger #undef pTrigger #endif /* ** This routine generates VDBE code that causes a single row of a ** single table to be deleted. ** ** The VDBE must be in a particular state when this routine is called. ** These are the requirements: |
︙ | ︙ | |||
622 623 624 625 626 627 628 | sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), 0); sqlite3ExprCacheAffinityChange(pParse, regBase, nCol+1); } sqlite3ReleaseTempRange(pParse, regBase, nCol+1); return regBase; } | < < < < | 631 632 633 634 635 636 637 | sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), 0); sqlite3ExprCacheAffinityChange(pParse, regBase, nCol+1); } sqlite3ReleaseTempRange(pParse, regBase, nCol+1); return regBase; } |
Changes to src/fkey.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ************************************************************************* ** This file contains code used by the compiler to add foreign key ** support to compiled SQL statements. */ #include "sqliteInt.h" #ifndef SQLITE_OMIT_FOREIGN_KEY /* ** Deferred and Immediate FKs ** -------------------------- ** ** Foreign keys in SQLite come in two flavours: deferred and immediate. ** If an immediate foreign key constraint is violated, an OP_Halt is | > | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ************************************************************************* ** This file contains code used by the compiler to add foreign key ** support to compiled SQL statements. */ #include "sqliteInt.h" #ifndef SQLITE_OMIT_FOREIGN_KEY #ifndef SQLITE_OMIT_TRIGGER /* ** Deferred and Immediate FKs ** -------------------------- ** ** Foreign keys in SQLite come in two flavours: deferred and immediate. ** If an immediate foreign key constraint is violated, an OP_Halt is |
︙ | ︙ | |||
382 383 384 385 386 387 388 389 390 391 392 393 394 395 | ** "t2". Calling this function with "t2" as the argument would return a ** NULL pointer (as there are no FK constraints that refer to t2). */ static FKey *fkRefering(Table *pTab){ int nName = sqlite3Strlen30(pTab->zName); return (FKey *)sqlite3HashFind(&pTab->pSchema->fkeyHash, pTab->zName, nName); } void sqlite3FkCheck( Parse *pParse, /* Parse context */ Table *pTab, /* Row is being deleted from this table */ ExprList *pChanges, /* Changed columns if this is an UPDATE */ int regOld, /* Previous row data is stored here */ int regNew /* New row data is stored here */ | > > > > > > > > > | 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 | ** "t2". Calling this function with "t2" as the argument would return a ** NULL pointer (as there are no FK constraints that refer to t2). */ static FKey *fkRefering(Table *pTab){ int nName = sqlite3Strlen30(pTab->zName); return (FKey *)sqlite3HashFind(&pTab->pSchema->fkeyHash, pTab->zName, nName); } static void fkTriggerDelete(sqlite3 *dbMem, Trigger *p){ if( p ){ TriggerStep *pStep = p->step_list; sqlite3ExprDelete(dbMem, pStep->pWhere); sqlite3ExprListDelete(dbMem, pStep->pExprList); sqlite3DbFree(dbMem, p); } } void sqlite3FkCheck( Parse *pParse, /* Parse context */ Table *pTab, /* Row is being deleted from this table */ ExprList *pChanges, /* Changed columns if this is an UPDATE */ int regOld, /* Previous row data is stored here */ int regNew /* New row data is stored here */ |
︙ | ︙ | |||
710 711 712 713 714 715 716 | pStep->op = (action==OE_Cascade)?TK_DELETE:TK_UPDATE; } } return pTrigger; } | < < < < < < < < < | 720 721 722 723 724 725 726 727 728 729 730 731 732 733 | pStep->op = (action==OE_Cascade)?TK_DELETE:TK_UPDATE; } } return pTrigger; } /* ** This function is called when deleting or updating a row to implement ** any required CASCADE, SET NULL or SET DEFAULT actions. */ void sqlite3FkActions( Parse *pParse, /* Parse context */ Table *pTab, /* Table being updated or deleted from */ |
︙ | ︙ | |||
743 744 745 746 747 748 749 750 751 752 753 754 755 756 | Trigger *pAction = fkActionTrigger(pParse, pTab, pFKey, pChanges); if( pAction ){ sqlite3CodeRowTriggerDirect(pParse, pAction, pTab, regOld, OE_Abort, 0); } } } } /* ** Free all memory associated with foreign key definitions attached to ** table pTab. Remove the deleted foreign keys from the Schema.fkeyHash ** hash table. */ void sqlite3FkDelete(Table *pTab){ | > > | 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 | Trigger *pAction = fkActionTrigger(pParse, pTab, pFKey, pChanges); if( pAction ){ sqlite3CodeRowTriggerDirect(pParse, pAction, pTab, regOld, OE_Abort, 0); } } } } #endif /* ifndef SQLITE_OMIT_TRIGGER */ /* ** Free all memory associated with foreign key definitions attached to ** table pTab. Remove the deleted foreign keys from the Schema.fkeyHash ** hash table. */ void sqlite3FkDelete(Table *pTab){ |
︙ | ︙ | |||
768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 | sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, sqlite3Strlen30(z), data); } if( pFKey->pNextTo ){ pFKey->pNextTo->pPrevTo = pFKey->pPrevTo; } /* Delete any triggers created to implement actions for this FK. */ fkTriggerDelete(pTab->dbMem, pFKey->pOnDelete); fkTriggerDelete(pTab->dbMem, pFKey->pOnUpdate); /* Delete the memory allocated for the FK structure. */ pNext = pFKey->pNextFrom; sqlite3DbFree(pTab->dbMem, pFKey); } } | > > < | | 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 | sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, sqlite3Strlen30(z), data); } if( pFKey->pNextTo ){ pFKey->pNextTo->pPrevTo = pFKey->pPrevTo; } /* Delete any triggers created to implement actions for this FK. */ #ifndef SQLITE_OMIT_TRIGGER fkTriggerDelete(pTab->dbMem, pFKey->pOnDelete); fkTriggerDelete(pTab->dbMem, pFKey->pOnUpdate); #endif /* Delete the memory allocated for the FK structure. */ pNext = pFKey->pNextFrom; sqlite3DbFree(pTab->dbMem, pFKey); } } #endif /* ifndef SQLITE_OMIT_FOREIGN_KEY */ |
Changes to src/insert.c.
︙ | ︙ | |||
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 | insert_cleanup: sqlite3SrcListDelete(db, pTabList); sqlite3ExprListDelete(db, pList); sqlite3SelectDelete(db, pSelect); sqlite3IdListDelete(db, pColumn); sqlite3DbFree(db, aRegIdx); } /* ** Generate code to do constraint checks prior to an INSERT or an UPDATE. ** ** The input is a range of consecutive registers as follows: ** ** 1. The rowid of the row after the update. | > > > > > > > > > > > > > > | 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 | insert_cleanup: sqlite3SrcListDelete(db, pTabList); sqlite3ExprListDelete(db, pList); sqlite3SelectDelete(db, pSelect); sqlite3IdListDelete(db, pColumn); sqlite3DbFree(db, aRegIdx); } /* Make sure "isView" and other macros defined above are undefined. Otherwise ** thely may interfere with compilation of other functions in this file ** (or in another file, if this file becomes part of the amalgamation). */ #ifdef isView #undef isView #endif #ifdef pTrigger #undef pTrigger #endif #ifdef tmask #undef tmask #endif /* ** Generate code to do constraint checks prior to an INSERT or an UPDATE. ** ** The input is a range of consecutive registers as follows: ** ** 1. The rowid of the row after the update. |
︙ | ︙ | |||
1797 1798 1799 1800 1801 1802 1803 | sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); return 0; }else{ return 1; } } #endif /* SQLITE_OMIT_XFER_OPT */ | < < < < < | 1811 1812 1813 1814 1815 1816 1817 | sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); return 0; }else{ return 1; } } #endif /* SQLITE_OMIT_XFER_OPT */ |
Changes to src/parse.y.
︙ | ︙ | |||
321 322 323 324 325 326 327 | refarg(A) ::= ON DELETE refact(X). { A.value = X; A.mask = 0x0000ff; } refarg(A) ::= ON UPDATE refact(X). { A.value = X<<8; A.mask = 0x00ff00; } %type refact {int} refact(A) ::= SET NULL. { A = OE_SetNull; } refact(A) ::= SET DEFAULT. { A = OE_SetDflt; } refact(A) ::= CASCADE. { A = OE_Cascade; } refact(A) ::= RESTRICT. { A = OE_Restrict; } | | | 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 | refarg(A) ::= ON DELETE refact(X). { A.value = X; A.mask = 0x0000ff; } refarg(A) ::= ON UPDATE refact(X). { A.value = X<<8; A.mask = 0x00ff00; } %type refact {int} refact(A) ::= SET NULL. { A = OE_SetNull; } refact(A) ::= SET DEFAULT. { A = OE_SetDflt; } refact(A) ::= CASCADE. { A = OE_Cascade; } refact(A) ::= RESTRICT. { A = OE_Restrict; } refact(A) ::= NO ACTION. { A = OE_Restrict; } %type defer_subclause {int} defer_subclause(A) ::= NOT DEFERRABLE init_deferred_pred_opt. {A = 0;} defer_subclause(A) ::= DEFERRABLE init_deferred_pred_opt(X). {A = X;} %type init_deferred_pred_opt {int} init_deferred_pred_opt(A) ::= . {A = 0;} init_deferred_pred_opt(A) ::= INITIALLY DEFERRED. {A = 1;} init_deferred_pred_opt(A) ::= INITIALLY IMMEDIATE. {A = 0;} |
︙ | ︙ |
Changes to src/pragma.c.
︙ | ︙ | |||
188 189 190 191 192 193 194 | { "omit_readlock", SQLITE_NoReadlock }, /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted ** flag if there are any active statements. */ { "read_uncommitted", SQLITE_ReadUncommitted }, { "recursive_triggers", SQLITE_RecTriggers }, | | > > > > > > > > > > | | | 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | { "omit_readlock", SQLITE_NoReadlock }, /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted ** flag if there are any active statements. */ { "read_uncommitted", SQLITE_ReadUncommitted }, { "recursive_triggers", SQLITE_RecTriggers }, /* This flag may only be set if both foreign-key and trigger support ** are present in the build. */ #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) { "foreign_keys", SQLITE_ForeignKeys }, #endif }; int i; const struct sPragmaType *p; for(i=0, p=aPragma; i<ArraySize(aPragma); i++, p++){ if( sqlite3StrICmp(zLeft, p->zName)==0 ){ sqlite3 *db = pParse->db; Vdbe *v; v = sqlite3GetVdbe(pParse); assert( v!=0 ); /* Already allocated by sqlite3Pragma() */ if( ALWAYS(v) ){ if( zRight==0 ){ returnSingleInt(pParse, p->zName, (db->flags & p->mask)!=0 ); }else{ int mask = p->mask; /* Mask of bits to set or clear. */ if( db->autoCommit==0 ){ /* Foreign key support may not be enabled or disabled while not ** in auto-commit mode. */ mask &= ~(SQLITE_ForeignKeys); } if( getBoolean(zRight) ){ db->flags |= mask; }else{ db->flags &= ~mask; } /* Many of the flag-pragmas modify the code generated by the SQL ** compiler (eg. count_changes). So add an opcode to expire all ** compiled SQL statements after modifying a pragma value. */ sqlite3VdbeAddOp2(v, OP_Expire, 0, 0); |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 | # define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p)) #else # define sqlite3TriggersExist(B,C,D,E,F) 0 # define sqlite3DeleteTrigger(A,B) # define sqlite3DropTriggerPtr(A,B) # define sqlite3UnlinkAndDeleteTrigger(A,B,C) # define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I,J) # define sqlite3TriggerList(X, Y) 0 # define sqlite3ParseToplevel(p) p # define sqlite3TriggerOldmask(A,B,C,D,E) 0 #endif int sqlite3JoinType(Parse*, Token*, Token*, Token*); void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); | > | 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 | # define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p)) #else # define sqlite3TriggersExist(B,C,D,E,F) 0 # define sqlite3DeleteTrigger(A,B) # define sqlite3DropTriggerPtr(A,B) # define sqlite3UnlinkAndDeleteTrigger(A,B,C) # define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I,J) # define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F) # define sqlite3TriggerList(X, Y) 0 # define sqlite3ParseToplevel(p) p # define sqlite3TriggerOldmask(A,B,C,D,E) 0 #endif int sqlite3JoinType(Parse*, Token*, Token*, Token*); void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); |
︙ | ︙ | |||
2938 2939 2940 2941 2942 2943 2944 | int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); int sqlite3Reprepare(Vdbe*); void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); int sqlite3TempInMemory(const sqlite3*); VTable *sqlite3GetVTable(sqlite3*, Table*); | > > > > > > > | < < > > > > > > | 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 | int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); int sqlite3Reprepare(Vdbe*); void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); int sqlite3TempInMemory(const sqlite3*); VTable *sqlite3GetVTable(sqlite3*, Table*); /* Declarations for functions in fkey.c. All of these are replaced by ** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign ** key functionality is available. If OMIT_TRIGGER is defined but ** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In ** this case foreign keys are parsed, but no other functionality is ** provided (enforcement of FK constraints requires the triggers sub-system). */ #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) void sqlite3FkCheck(Parse*, Table*, ExprList*, int, int); void sqlite3FkActions(Parse*, Table*, ExprList*, int); int sqlite3FkRequired(Parse*, Table*, ExprList*); u32 sqlite3FkOldmask(Parse*, Table*, ExprList*); #else #define sqlite3FkCheck(a,b,c,d,e) #define sqlite3FkActions(a,b,c,d) #define sqlite3FkRequired(a,b,c) 0 #define sqlite3FkOldmask(a,b,c) 0 #endif #ifndef SQLITE_OMIT_FOREIGN_KEY void sqlite3FkDelete(Table*); #else #define sqlite3FkDelete(a) #endif /* ** Available fault injectors. Should be numbered beginning with 0. */ #define SQLITE_FAULTINJECTOR_MALLOC 0 #define SQLITE_FAULTINJECTOR_COUNT 1 |
︙ | ︙ |
Changes to src/update.c.
︙ | ︙ | |||
513 514 515 516 517 518 519 520 521 522 523 524 525 526 | sqlite3DbFree(db, aRegIdx); sqlite3DbFree(db, aXRef); sqlite3SrcListDelete(db, pTabList); sqlite3ExprListDelete(db, pChanges); sqlite3ExprDelete(db, pWhere); return; } #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Generate code for an UPDATE of a virtual table. ** ** The strategy is that we create an ephemerial table that contains ** for each row to be changed: | > > > > > > > > > | 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 | sqlite3DbFree(db, aRegIdx); sqlite3DbFree(db, aXRef); sqlite3SrcListDelete(db, pTabList); sqlite3ExprListDelete(db, pChanges); sqlite3ExprDelete(db, pWhere); return; } /* Make sure "isView" and other macros defined above are undefined. Otherwise ** thely may interfere with compilation of other functions in this file ** (or in another file, if this file becomes part of the amalgamation). */ #ifdef isView #undef isView #endif #ifdef pTrigger #undef pTrigger #endif #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Generate code for an UPDATE of a virtual table. ** ** The strategy is that we create an ephemerial table that contains ** for each row to be changed: |
︙ | ︙ | |||
607 608 609 610 611 612 613 | sqlite3VdbeJumpHere(v, addr); sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); /* Cleanup */ sqlite3SelectDelete(db, pSelect); } #endif /* SQLITE_OMIT_VIRTUALTABLE */ | < < < < < | 616 617 618 619 620 621 622 | sqlite3VdbeJumpHere(v, addr); sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); /* Cleanup */ sqlite3SelectDelete(db, pSelect); } #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
Changes to src/vacuum.c.
︙ | ︙ | |||
93 94 95 96 97 98 99 | int nRes; if( !db->autoCommit ){ sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction"); return SQLITE_ERROR; } | | > > > | 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | int nRes; if( !db->autoCommit ){ sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction"); return SQLITE_ERROR; } /* Save the current value of the database flags so that it can be ** restored before returning. Then set the writable-schema flag, and ** disable CHECK and foreign key constraints. */ saved_flags = db->flags; saved_nChange = db->nChange; saved_nTotalChange = db->nTotalChange; db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks; db->flags &= ~SQLITE_ForeignKeys; pMain = db->aDb[0].pBt; isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain)); /* Attach the temporary database as 'vacuum_db'. The synchronous pragma ** can be set to 'off' for this file, as it is not recovered if a crash ** occurs anyway. The integrity of the database is maintained by a |
︙ | ︙ |
Changes to test/autoinc.test.
︙ | ︙ | |||
554 555 556 557 558 559 560 | CREATE TABLE t3(a INTEGER PRIMARY KEY AUTOINCREMENT, b); INSERT INTO t3 SELECT * FROM t2 WHERE y>1; SELECT * FROM sqlite_sequence WHERE name='t3'; } } {t3 0} | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 | CREATE TABLE t3(a INTEGER PRIMARY KEY AUTOINCREMENT, b); INSERT INTO t3 SELECT * FROM t2 WHERE y>1; SELECT * FROM sqlite_sequence WHERE name='t3'; } } {t3 0} ifcapable trigger { catchsql { pragma recursive_triggers = off } # Ticket #3928. Make sure that triggers to not make extra slots in # the SQLITE_SEQUENCE table. # do_test autoinc-3928.1 { db eval { CREATE TABLE t3928(a INTEGER PRIMARY KEY AUTOINCREMENT, b); CREATE TRIGGER t3928r1 BEFORE INSERT ON t3928 BEGIN INSERT INTO t3928(b) VALUES('before1'); INSERT INTO t3928(b) VALUES('before2'); END; CREATE TRIGGER t3928r2 AFTER INSERT ON t3928 BEGIN INSERT INTO t3928(b) VALUES('after1'); INSERT INTO t3928(b) VALUES('after2'); END; INSERT INTO t3928(b) VALUES('test'); SELECT * FROM t3928 ORDER BY a; } } {1 before1 2 after1 3 after2 4 before2 5 after1 6 after2 7 test 8 before1 9 before2 10 after1 11 before1 12 before2 13 after2} do_test autoinc-3928.2 { db eval { SELECT * FROM sqlite_sequence WHERE name='t3928' } } {t3928 13} do_test autoinc-3928.3 { db eval { DROP TRIGGER t3928r1; DROP TRIGGER t3928r2; CREATE TRIGGER t3928r3 BEFORE UPDATE ON t3928 WHEN typeof(new.b)=='integer' BEGIN INSERT INTO t3928(b) VALUES('before-int-' || new.b); END; CREATE TRIGGER t3928r4 AFTER UPDATE ON t3928 WHEN typeof(new.b)=='integer' BEGIN INSERT INTO t3928(b) VALUES('after-int-' || new.b); END; DELETE FROM t3928 WHERE a!=1; UPDATE t3928 SET b=456 WHERE a=1; SELECT * FROM t3928 ORDER BY a; } } {1 456 14 before-int-456 15 after-int-456} do_test autoinc-3928.4 { db eval { SELECT * FROM sqlite_sequence WHERE name='t3928' } } {t3928 15} do_test autoinc-3928.5 { db eval { CREATE TABLE t3928b(x); INSERT INTO t3928b VALUES(100); INSERT INTO t3928b VALUES(200); INSERT INTO t3928b VALUES(300); DELETE FROM t3928; CREATE TABLE t3928c(y INTEGER PRIMARY KEY AUTOINCREMENT, z); CREATE TRIGGER t3928br1 BEFORE DELETE ON t3928b BEGIN INSERT INTO t3928(b) VALUES('before-del-'||old.x); INSERT INTO t3928c(z) VALUES('before-del-'||old.x); END; CREATE TRIGGER t3928br2 AFTER DELETE ON t3928b BEGIN INSERT INTO t3928(b) VALUES('after-del-'||old.x); INSERT INTO t3928c(z) VALUES('after-del-'||old.x); END; DELETE FROM t3928b; SELECT * FROM t3928 ORDER BY a; } } {16 before-del-100 17 after-del-100 18 before-del-200 19 after-del-200 20 before-del-300 21 after-del-300} do_test autoinc-3928.6 { db eval { SELECT * FROM t3928c ORDER BY y; } } {1 before-del-100 2 after-del-100 3 before-del-200 4 after-del-200 5 before-del-300 6 after-del-300} do_test autoinc-3928.7 { db eval { SELECT * FROM sqlite_sequence WHERE name LIKE 't3928%' ORDER BY name; } } {t3928 21 t3928c 6} # Ticket [a696379c1f0886615541a48b35bd8181a80e88f8] do_test autoinc-a69637.1 { db eval { CREATE TABLE ta69637_1(x INTEGER PRIMARY KEY AUTOINCREMENT, y); CREATE TABLE ta69637_2(z); CREATE TRIGGER ra69637_1 AFTER INSERT ON ta69637_2 BEGIN INSERT INTO ta69637_1(y) VALUES(new.z+1); END; INSERT INTO ta69637_2 VALUES(123); SELECT * FROM ta69637_1; } } {1 124} do_test autoinc-a69637.2 { db eval { CREATE VIEW va69637_2 AS SELECT * FROM ta69637_2; CREATE TRIGGER ra69637_2 INSTEAD OF INSERT ON va69637_2 BEGIN INSERT INTO ta69637_1(y) VALUES(new.z+10000); END; INSERT INTO va69637_2 VALUES(123); SELECT * FROM ta69637_1; } } {1 124 2 10123} } finish_test |
Changes to test/fkey2.test.
︙ | ︙ | |||
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 | # This file implements regression tests for SQLite library. # # This file implements tests for foreign keys. # set testdir [file dirname $argv0] source $testdir/tester.tcl #------------------------------------------------------------------------- # Test structure: # # fkey2-1.*: Simple tests to check that immediate and deferred foreign key # constraints work when not inside a transaction. # # fkey2-2.*: Tests to verify that deferred foreign keys work inside # explicit transactions (i.e that processing really is deferred). # # fkey2-3.*: Tests that a statement transaction is rolled back if an # immediate foreign key constraint is violated. # # fkey2-4.*: Test that FK actions may recurse even when recursive triggers # are disabled. # # fkey2-5.*: Check that if foreign-keys are enabled, it is not possible # to write to an FK column using the incremental blob API. # # fkey2-genfkey.*: Tests that were used with the shell tool .genfkey # command. Recycled to test the built-in implementation. # proc drop_all_tables {{db db}} { | > > > > > > > > | 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 | # This file implements regression tests for SQLite library. # # This file implements tests for foreign keys. # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable {!foreignkey||!trigger} { finish_test return } #------------------------------------------------------------------------- # Test structure: # # fkey2-1.*: Simple tests to check that immediate and deferred foreign key # constraints work when not inside a transaction. # # fkey2-2.*: Tests to verify that deferred foreign keys work inside # explicit transactions (i.e that processing really is deferred). # # fkey2-3.*: Tests that a statement transaction is rolled back if an # immediate foreign key constraint is violated. # # fkey2-4.*: Test that FK actions may recurse even when recursive triggers # are disabled. # # fkey2-5.*: Check that if foreign-keys are enabled, it is not possible # to write to an FK column using the incremental blob API. # # fkey2-6.*: Test that FK processing is automatically disabled when # running VACUUM. # # fkey2-genfkey.*: Tests that were used with the shell tool .genfkey # command. Recycled to test the built-in implementation. # proc drop_all_tables {{db db}} { |
︙ | ︙ | |||
355 356 357 358 359 360 361 | } {} #------------------------------------------------------------------------- # Test cases fkey2-5.* verify that the incremental blob API may not # write to a foreign key column while foreign-keys are enabled. # drop_all_tables | > | | | | | | | | | | | | | | | | | | | | | | | | | | > > > > > > > > > > > > > > | 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 | } {} #------------------------------------------------------------------------- # Test cases fkey2-5.* verify that the incremental blob API may not # write to a foreign key column while foreign-keys are enabled. # drop_all_tables ifcapable incrblob { do_test fkey2-5.1 { execsql { CREATE TABLE t1(a PRIMARY KEY, b); CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1(a)); INSERT INTO t1 VALUES('hello', 'world'); INSERT INTO t2 VALUES('key', 'hello'); } } {} do_test fkey2-5.2 { set rc [catch { set fd [db incrblob t2 b 1] } msg] list $rc $msg } {1 {cannot open foreign key column for writing}} do_test fkey2-5.3 { set rc [catch { set fd [db incrblob -readonly t2 b 1] } msg] close $fd set rc } {0} do_test fkey2-5.4 { execsql { PRAGMA foreign_keys = off } set rc [catch { set fd [db incrblob t2 b 1] } msg] close $fd set rc } {0} do_test fkey2-5.5 { execsql { PRAGMA foreign_keys = on } } {} } drop_all_tables ifcapable vacuum { do_test fkey2-6.1 { execsql { CREATE TABLE t1(a REFERENCES t2(c), b); CREATE TABLE t2(c UNIQUE, b); INSERT INTO t2 VALUES(1, 2); INSERT INTO t1 VALUES(1, 2); VACUUM; } } {} } #------------------------------------------------------------------------- # The following block of tests, those prefixed with "fkey2-genfkey.", are # the same tests that were used to test the ".genfkey" command provided # by the shell tool. So these tests show that the built-in foreign key # implementation is more or less compatible with the triggers generated # by genfkey. |
︙ | ︙ |
Changes to test/selectC.test.
︙ | ︙ | |||
147 148 149 150 151 152 153 | FROM t1 ORDER BY x DESC } } {CCC AAA AAA} # The following query used to leak memory. Verify that has been fixed. # | > | | | | | | | | | | | | > | 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | FROM t1 ORDER BY x DESC } } {CCC AAA AAA} # The following query used to leak memory. Verify that has been fixed. # ifcapable trigger { do_test selectC-2.1 { catchsql { CREATE TABLE t21a(a,b); INSERT INTO t21a VALUES(1,2); CREATE TABLE t21b(n); CREATE TRIGGER r21 AFTER INSERT ON t21b BEGIN SELECT a FROM t21a WHERE a>new.x UNION ALL SELECT b FROM t21a WHERE b>new.x ORDER BY 1 LIMIT 2; END; INSERT INTO t21b VALUES(6); } } {1 {no such column: new.x}} } finish_test |
Changes to test/tkt3201.test.
︙ | ︙ | |||
68 69 70 71 72 73 74 | do_test tkt3201-7 { execsql { SELECT a, b, c, d FROM t1, t3 WHERE a < c } } {1 one 2 two} # Ticket [efc02f977919] # | > | | | | | | | | | | | | | | | | | | | | | | | > | 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 | do_test tkt3201-7 { execsql { SELECT a, b, c, d FROM t1, t3 WHERE a < c } } {1 one 2 two} # Ticket [efc02f977919] # ifcapable trigger { do_test tkt3201-4.0 { db eval { CREATE TABLE t4(x); CREATE TABLE t4_log(x); CREATE TRIGGER r4_1 AFTER INSERT ON t4 WHEN new.x=1 BEGIN INSERT INTO t4_log(x) VALUES(new.x); END; CREATE TRIGGER r4_2 AFTER INSERT ON t4 WHEN new.x=2 BEGIN INSERT INTO t4_log(x) VALUES(new.x); END; CREATE TRIGGER r4_3 AFTER INSERT ON t4 WHEN new.x=3 BEGIN INSERT INTO t4_log(x) VALUES(new.x); END; CREATE TRIGGER r4_4 AFTER INSERT ON t4 WHEN new.x=4 BEGIN INSERT INTO t4_log(x) VALUES(new.x); END; INSERT INTO t4 VALUES(1); INSERT INTO t4 VALUES(2); INSERT INTO t4 VALUES(3); INSERT INTO t4 VALUES(4); SELECT * FROM t4_log; } } {1 2 3 4} } finish_test |
Changes to test/tkt3810.test.
︙ | ︙ | |||
11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # # Tests to make sure #3810 is fixed. # # $Id: tkt3810.test,v 1.4 2009/08/06 17:43:31 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Create a table using the first database connection. # do_test tkt3810-1.1 { execsql { CREATE TABLE t1(x); INSERT INTO t1 VALUES(123); | > > > > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | # # Tests to make sure #3810 is fixed. # # $Id: tkt3810.test,v 1.4 2009/08/06 17:43:31 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable {!trigger} { finish_test return } # Create a table using the first database connection. # do_test tkt3810-1.1 { execsql { CREATE TABLE t1(x); INSERT INTO t1 VALUES(123); |
︙ | ︙ |
Changes to test/tkt3832.test.
︙ | ︙ | |||
14 15 16 17 18 19 20 21 22 23 24 25 26 27 | # A segfault when using a BEFORE trigger on an INSERT and inserting # a NULL into the INTEGER PRIMARY KEY. # # $Id: tkt3832.test,v 1.1 2009/05/01 02:08:04 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl do_test tkt3832-1.1 { db eval { CREATE TABLE t1(a INT, b INTEGER PRIMARY KEY); CREATE TABLE log(x); CREATE TRIGGER t1r1 BEFORE INSERT ON t1 BEGIN | > > > > | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # A segfault when using a BEFORE trigger on an INSERT and inserting # a NULL into the INTEGER PRIMARY KEY. # # $Id: tkt3832.test,v 1.1 2009/05/01 02:08:04 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable {!trigger} { finish_test return } do_test tkt3832-1.1 { db eval { CREATE TABLE t1(a INT, b INTEGER PRIMARY KEY); CREATE TABLE log(x); CREATE TRIGGER t1r1 BEFORE INSERT ON t1 BEGIN |
︙ | ︙ |
Changes to test/tkt3929.test.
︙ | ︙ | |||
11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # # Tests to verify ticket #3929 is fixed. # # $Id: tkt3929.test,v 1.1 2009/06/23 11:53:09 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl do_test tkt3929-1.0 { execsql { PRAGMA page_size = 1024; CREATE TABLE t1(a, b); CREATE INDEX i1 ON t1(a, b); CREATE TRIGGER t1_t1 AFTER INSERT ON t1 BEGIN | > > > > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | # # Tests to verify ticket #3929 is fixed. # # $Id: tkt3929.test,v 1.1 2009/06/23 11:53:09 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable {!trigger} { finish_test return } do_test tkt3929-1.0 { execsql { PRAGMA page_size = 1024; CREATE TABLE t1(a, b); CREATE INDEX i1 ON t1(a, b); CREATE TRIGGER t1_t1 AFTER INSERT ON t1 BEGIN |
︙ | ︙ |
Changes to test/tkt3992.test.
︙ | ︙ | |||
55 56 57 58 59 60 61 | do_test tkt3992-2.2 { execsql { UPDATE t1 SET a = 'one'; SELECT * FROM t1; } } {one 2 3} | > | | | | | | | | | | | | | > | 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 | do_test tkt3992-2.2 { execsql { UPDATE t1 SET a = 'one'; SELECT * FROM t1; } } {one 2 3} ifcapable trigger { db function tcl eval do_test tkt3992-2.3 { execsql { CREATE TABLE t2(a REAL, b REAL, c REAL); INSERT INTO t2 VALUES(1, 2, 3); CREATE TRIGGER tr2 BEFORE UPDATE ON t2 BEGIN SELECT tcl('set res', typeof(new.c)); END; UPDATE t2 SET a = 'I'; } set res } {real} } finish_test |
Changes to tool/mkkeywordhash.c.
︙ | ︙ | |||
140 141 142 143 144 145 146 147 148 149 150 151 152 153 | #endif /* ** These are the keywords */ static Keyword aKeywordTable[] = { { "ABORT", "TK_ABORT", CONFLICT|TRIGGER }, { "ADD", "TK_ADD", ALTER }, { "AFTER", "TK_AFTER", TRIGGER }, { "ALL", "TK_ALL", ALWAYS }, { "ALTER", "TK_ALTER", ALTER }, { "ANALYZE", "TK_ANALYZE", ANALYZE }, { "AND", "TK_AND", ALWAYS }, { "AS", "TK_AS", ALWAYS }, | > | 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | #endif /* ** These are the keywords */ static Keyword aKeywordTable[] = { { "ABORT", "TK_ABORT", CONFLICT|TRIGGER }, { "ACTION", "TK_ACTION", FKEY }, { "ADD", "TK_ADD", ALTER }, { "AFTER", "TK_AFTER", TRIGGER }, { "ALL", "TK_ALL", ALWAYS }, { "ALTER", "TK_ALTER", ALTER }, { "ANALYZE", "TK_ANALYZE", ANALYZE }, { "AND", "TK_AND", ALWAYS }, { "AS", "TK_AS", ALWAYS }, |
︙ | ︙ | |||
214 215 216 217 218 219 220 221 222 223 224 225 226 227 | { "JOIN", "TK_JOIN", ALWAYS }, { "KEY", "TK_KEY", ALWAYS }, { "LEFT", "TK_JOIN_KW", ALWAYS }, { "LIKE", "TK_LIKE_KW", ALWAYS }, { "LIMIT", "TK_LIMIT", ALWAYS }, { "MATCH", "TK_MATCH", ALWAYS }, { "NATURAL", "TK_JOIN_KW", ALWAYS }, { "NOT", "TK_NOT", ALWAYS }, { "NOTNULL", "TK_NOTNULL", ALWAYS }, { "NULL", "TK_NULL", ALWAYS }, { "OF", "TK_OF", ALWAYS }, { "OFFSET", "TK_OFFSET", ALWAYS }, { "ON", "TK_ON", ALWAYS }, { "OR", "TK_OR", ALWAYS }, | > | 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 | { "JOIN", "TK_JOIN", ALWAYS }, { "KEY", "TK_KEY", ALWAYS }, { "LEFT", "TK_JOIN_KW", ALWAYS }, { "LIKE", "TK_LIKE_KW", ALWAYS }, { "LIMIT", "TK_LIMIT", ALWAYS }, { "MATCH", "TK_MATCH", ALWAYS }, { "NATURAL", "TK_JOIN_KW", ALWAYS }, { "NO", "TK_NO", FKEY }, { "NOT", "TK_NOT", ALWAYS }, { "NOTNULL", "TK_NOTNULL", ALWAYS }, { "NULL", "TK_NULL", ALWAYS }, { "OF", "TK_OF", ALWAYS }, { "OFFSET", "TK_OFFSET", ALWAYS }, { "ON", "TK_ON", ALWAYS }, { "OR", "TK_OR", ALWAYS }, |
︙ | ︙ |