Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge with [0291ed974d]. Merge with [0291ed974d]. Merge with [0291ed974d]. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | wal |
Files: | files | file ages | folders |
SHA1: |
a352f6285e33a806fbe4475e720e763f |
User & Date: | dan 2010-04-24 14:33:08.000 |
Context
2010-04-24
| ||
18:44 | Fix bugs in WAL mode rollback. (check-in: 31215969f5 user: dan tags: wal) | |
14:33 | Merge with [0291ed974d]. Merge with [0291ed974d]. Merge with [0291ed974d]. (check-in: a352f6285e user: dan tags: wal) | |
14:02 | When commands such as ALTER TABLE and VACUUM use SQL internally, make sure they use only the built-in functions and not application-defined overrides for those functions. (check-in: 0291ed974d user: drh tags: trunk) | |
04:53 | Merge with [e79dac3c2f]. (check-in: 1e793d3a6d user: dan tags: wal) | |
Changes
Changes to src/alter.c.
︙ | ︙ | |||
222 223 224 225 226 227 228 | } } #endif /* !SQLITE_OMIT_TRIGGER */ /* ** Register built-in functions used to help implement ALTER TABLE */ | | | | | < | < > > > > > > > > | 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 | } } #endif /* !SQLITE_OMIT_TRIGGER */ /* ** Register built-in functions used to help implement ALTER TABLE */ void sqlite3AlterFunctions(void){ static SQLITE_WSD FuncDef aAlterTableFuncs[] = { FUNCTION(sqlite_rename_table, 2, 0, 0, renameTableFunc), #ifndef SQLITE_OMIT_TRIGGER FUNCTION(sqlite_rename_trigger, 2, 0, 0, renameTriggerFunc), #endif #ifndef SQLITE_OMIT_FOREIGN_KEY FUNCTION(sqlite_rename_parent, 3, 0, 0, renameParentFunc), #endif }; int i; FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aAlterTableFuncs); for(i=0; i<ArraySize(aAlterTableFuncs); i++){ sqlite3FuncDefInsert(pHash, &aFunc[i]); } } /* ** This function is used to create the text of expressions of the form: ** ** name=<constant1> OR name=<constant2> OR ... ** |
︙ | ︙ | |||
376 377 378 379 380 381 382 | int nTabName; /* Number of UTF-8 characters in zTabName */ const char *zTabName; /* Original name of the table */ Vdbe *v; #ifndef SQLITE_OMIT_TRIGGER char *zWhere = 0; /* Where clause to locate temp triggers */ #endif VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */ | > | > > | 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 | int nTabName; /* Number of UTF-8 characters in zTabName */ const char *zTabName; /* Original name of the table */ Vdbe *v; #ifndef SQLITE_OMIT_TRIGGER char *zWhere = 0; /* Where clause to locate temp triggers */ #endif VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */ int savedDbFlags; /* Saved value of db->flags */ savedDbFlags = db->flags; if( NEVER(db->mallocFailed) ) goto exit_rename_table; assert( pSrc->nSrc==1 ); assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); pTab = sqlite3LocateTable(pParse, 0, pSrc->a[0].zName, pSrc->a[0].zDatabase); if( !pTab ) goto exit_rename_table; iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); zDb = db->aDb[iDb].zName; db->flags |= SQLITE_PreferBuiltin; /* Get a NULL terminated version of the new table name. */ zName = sqlite3NameFromToken(db, pName); if( !zName ) goto exit_rename_table; /* Check that a table or index named 'zName' does not already exist ** in database iDb. If so, this is an error. |
︙ | ︙ | |||
552 553 554 555 556 557 558 559 560 561 562 563 564 565 | /* Drop and reload the internal table schema. */ reloadTableSchema(pParse, pTab, zName); exit_rename_table: sqlite3SrcListDelete(db, pSrc); sqlite3DbFree(db, zName); } /* ** Generate code to make sure the file format number is at least minFormat. ** The generated code will increase the file format number if necessary. */ | > | 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 | /* Drop and reload the internal table schema. */ reloadTableSchema(pParse, pTab, zName); exit_rename_table: sqlite3SrcListDelete(db, pSrc); sqlite3DbFree(db, zName); db->flags = savedDbFlags; } /* ** Generate code to make sure the file format number is at least minFormat. ** The generated code will increase the file format number if necessary. */ |
︙ | ︙ | |||
671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 | sqlite3ValueFree(pVal); } /* Modify the CREATE TABLE statement. */ zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n); if( zCol ){ char *zEnd = &zCol[pColDef->n-1]; while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){ *zEnd-- = '\0'; } sqlite3NestedParse(pParse, "UPDATE \"%w\".%s SET " "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) " "WHERE type = 'table' AND name = %Q", zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1, zTab ); sqlite3DbFree(db, zCol); } /* If the default value of the new column is NULL, then set the file ** format to 2. If the default value of the new column is not NULL, ** the file format becomes 3. */ sqlite3MinimumFileFormat(pParse, iDb, pDflt ? 3 : 2); | > > > | 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 | sqlite3ValueFree(pVal); } /* Modify the CREATE TABLE statement. */ zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n); if( zCol ){ char *zEnd = &zCol[pColDef->n-1]; int savedDbFlags = db->flags; while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){ *zEnd-- = '\0'; } db->flags |= SQLITE_PreferBuiltin; sqlite3NestedParse(pParse, "UPDATE \"%w\".%s SET " "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) " "WHERE type = 'table' AND name = %Q", zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1, zTab ); sqlite3DbFree(db, zCol); db->flags = savedDbFlags; } /* If the default value of the new column is NULL, then set the file ** format to 2. If the default value of the new column is not NULL, ** the file format becomes 3. */ sqlite3MinimumFileFormat(pParse, iDb, pDflt ? 3 : 2); |
︙ | ︙ |
Changes to src/callback.c.
︙ | ︙ | |||
348 349 350 351 352 353 354 355 356 357 358 359 360 361 | pBest = p; bestScore = score; } p = p->pNext; } /* If no match is found, search the built-in functions. ** ** Except, if createFlag is true, that means that we are trying to ** install a new function. Whatever FuncDef structure is returned will ** have fields overwritten with new information appropriate for the ** new function. But the FuncDefs for built-in functions are read-only. ** So we must not search for built-ins when creating a new function. */ | > > > > | > | 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 | pBest = p; bestScore = score; } p = p->pNext; } /* If no match is found, search the built-in functions. ** ** If the SQLITE_PreferBuiltin flag is set, then search the built-in ** functions even if a prior app-defined function was found. And give ** priority to built-in functions. ** ** Except, if createFlag is true, that means that we are trying to ** install a new function. Whatever FuncDef structure is returned will ** have fields overwritten with new information appropriate for the ** new function. But the FuncDefs for built-in functions are read-only. ** So we must not search for built-ins when creating a new function. */ if( !createFlag && (pBest==0 || (db->flags & SQLITE_PreferBuiltin)!=0) ){ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); bestScore = 0; p = functionSearch(pHash, h, zName, nName); while( p ){ int score = matchQuality(p, nArg, enc); if( score>bestScore ){ pBest = p; bestScore = score; } |
︙ | ︙ |
Changes to src/func.c.
︙ | ︙ | |||
1412 1413 1414 1415 1416 1417 1418 | /* ** This function registered all of the above C functions as SQL ** functions. This should be the only routine in this file with ** external linkage. */ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ | < < < | 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 | /* ** This function registered all of the above C functions as SQL ** functions. This should be the only routine in this file with ** external linkage. */ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ if( !db->mallocFailed ){ int rc = sqlite3_overload_function(db, "MATCH", 2); assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); if( rc==SQLITE_NOMEM ){ db->mallocFailed = 1; } } |
︙ | ︙ | |||
1588 1589 1590 1591 1592 1593 1594 1595 | FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aBuiltinFunc); for(i=0; i<ArraySize(aBuiltinFunc); i++){ sqlite3FuncDefInsert(pHash, &aFunc[i]); } sqlite3RegisterDateTimeFunctions(); } | > > > | 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 | FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aBuiltinFunc); for(i=0; i<ArraySize(aBuiltinFunc); i++){ sqlite3FuncDefInsert(pHash, &aFunc[i]); } sqlite3RegisterDateTimeFunctions(); #ifndef SQLITE_OMIT_ALTERTABLE sqlite3AlterFunctions(); #endif } |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
911 912 913 914 915 916 917 918 919 920 921 922 923 924 | #define SQLITE_FullFSync 0x00200000 /* Use full fsync on the backend */ #define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */ #define SQLITE_RecoveryMode 0x00800000 /* Ignore schema errors */ #define SQLITE_ReverseOrder 0x01000000 /* Reverse unordered SELECTs */ #define SQLITE_RecTriggers 0x02000000 /* Enable recursive triggers */ #define SQLITE_ForeignKeys 0x04000000 /* Enforce foreign key constraints */ #define SQLITE_AutoIndex 0x08000000 /* Enable automatic indexes */ /* ** Bits of the sqlite3.flags field that are used by the ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface. ** These must be the low-order bits of the flags field. */ #define SQLITE_QueryFlattener 0x01 /* Disable query flattening */ | > | 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 | #define SQLITE_FullFSync 0x00200000 /* Use full fsync on the backend */ #define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */ #define SQLITE_RecoveryMode 0x00800000 /* Ignore schema errors */ #define SQLITE_ReverseOrder 0x01000000 /* Reverse unordered SELECTs */ #define SQLITE_RecTriggers 0x02000000 /* Enable recursive triggers */ #define SQLITE_ForeignKeys 0x04000000 /* Enforce foreign key constraints */ #define SQLITE_AutoIndex 0x08000000 /* Enable automatic indexes */ #define SQLITE_PreferBuiltin 0x10000000 /* Preference to built-in funcs */ /* ** Bits of the sqlite3.flags field that are used by the ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface. ** These must be the low-order bits of the flags field. */ #define SQLITE_QueryFlattener 0x01 /* Disable query flattening */ |
︙ | ︙ | |||
2879 2880 2881 2882 2883 2884 2885 | extern const unsigned char sqlite3CtypeMap[]; extern SQLITE_WSD struct Sqlite3Config sqlite3Config; extern SQLITE_WSD FuncDefHash sqlite3GlobalFunctions; extern int sqlite3PendingByte; #endif void sqlite3RootPageMoved(Db*, int, int); void sqlite3Reindex(Parse*, Token*, Token*); | | | 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 | extern const unsigned char sqlite3CtypeMap[]; extern SQLITE_WSD struct Sqlite3Config sqlite3Config; extern SQLITE_WSD FuncDefHash sqlite3GlobalFunctions; extern int sqlite3PendingByte; #endif void sqlite3RootPageMoved(Db*, int, int); void sqlite3Reindex(Parse*, Token*, Token*); void sqlite3AlterFunctions(void); void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); int sqlite3GetToken(const unsigned char *, int *); void sqlite3NestedParse(Parse*, const char*, ...); void sqlite3ExpirePreparedStatements(sqlite3*); int sqlite3CodeSubselect(Parse *, Expr *, int, int); void sqlite3SelectPrep(Parse*, Select*, NameContext*); int sqlite3ResolveExprNames(NameContext*, Expr*); |
︙ | ︙ |
Changes to src/vacuum.c.
︙ | ︙ | |||
113 114 115 116 117 118 119 | /* 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; saved_xTrace = db->xTrace; | | | 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | /* 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; saved_xTrace = db->xTrace; db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_PreferBuiltin; db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder); db->xTrace = 0; pMain = db->aDb[0].pBt; isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain)); /* Attach the temporary database as 'vacuum_db'. The synchronous pragma |
︙ | ︙ |
Changes to test/alter.test.
︙ | ︙ | |||
168 169 170 171 172 173 174 175 176 177 178 179 180 181 | index {sqlite_autoindex_T2_2} T2 \ ] } else { execsql { DROP TABLE TempTab; } } # Make sure the ALTER TABLE statements work with the # non-callback API # do_test alter-1.7 { stepsql $DB { ALTER TABLE [-t1-] RENAME to [*t1*]; | > > > > > > > > > > > > > > | 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | index {sqlite_autoindex_T2_2} T2 \ ] } else { execsql { DROP TABLE TempTab; } } # Create bogus application-defined functions for functions used # internally by ALTER TABLE, to ensure that ALTER TABLE falls back # to the built-in functions. # proc failing_app_func {args} {error "bad function"} do_test alter-1.7-prep { db func substr failing_app_func db func like failing_app_func db func sqlite_rename_table failing_app_func db func sqlite_rename_trigger failing_app_func db func sqlite_rename_parent failing_app_func catchsql {SELECT substr(name,1,3) FROM sqlite_master} } {1 {bad function}} # Make sure the ALTER TABLE statements work with the # non-callback API # do_test alter-1.7 { stepsql $DB { ALTER TABLE [-t1-] RENAME to [*t1*]; |
︙ | ︙ | |||
563 564 565 566 567 568 569 | } db2 } {x y z} do_test alter-5.3 { db2 close } {} foreach tblname [execsql { | | > | 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 | } db2 } {x y z} do_test alter-5.3 { db2 close } {} foreach tblname [execsql { SELECT name FROM sqlite_master WHERE type='table' AND name NOT GLOB 'sqlite*' }] { execsql "DROP TABLE \"$tblname\"" } set ::tbl_name "abc\uABCDdef" do_test alter-6.1 { string length $::tbl_name |
︙ | ︙ | |||
684 685 686 687 688 689 690 | #------------------------------------------------------------------------ # alter-10.X - Make sure ALTER TABLE works with multi-byte UTF-8 characters # in the names. # do_test alter-10.1 { execsql "CREATE TABLE xyz(x UNIQUE)" execsql "ALTER TABLE xyz RENAME TO xyz\u1234abc" | | | | | | 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 | #------------------------------------------------------------------------ # alter-10.X - Make sure ALTER TABLE works with multi-byte UTF-8 characters # in the names. # do_test alter-10.1 { execsql "CREATE TABLE xyz(x UNIQUE)" execsql "ALTER TABLE xyz RENAME TO xyz\u1234abc" execsql {SELECT name FROM sqlite_master WHERE name GLOB 'xyz*'} } [list xyz\u1234abc] do_test alter-10.2 { execsql {SELECT name FROM sqlite_master WHERE name GLOB 'sqlite_autoindex*'} } [list sqlite_autoindex_xyz\u1234abc_1] do_test alter-10.3 { execsql "ALTER TABLE xyz\u1234abc RENAME TO xyzabc" execsql {SELECT name FROM sqlite_master WHERE name GLOB 'xyz*'} } [list xyzabc] do_test alter-10.4 { execsql {SELECT name FROM sqlite_master WHERE name GLOB 'sqlite_autoindex*'} } [list sqlite_autoindex_xyzabc_1] do_test alter-11.1 { sqlite3_exec db {CREATE TABLE t11(%c6%c6)} execsql { ALTER TABLE t11 ADD COLUMN abc; } |
︙ | ︙ | |||
791 792 793 794 795 796 797 | # do_test alter-13.1 { execsql { CREATE TABLE /* hi */ t3102a(x); CREATE TABLE t3102b -- comment (y); CREATE INDEX t3102c ON t3102a(x); | | | | | 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 | # do_test alter-13.1 { execsql { CREATE TABLE /* hi */ t3102a(x); CREATE TABLE t3102b -- comment (y); CREATE INDEX t3102c ON t3102a(x); SELECT name FROM sqlite_master WHERE name GLOB 't3102*' ORDER BY 1; } } {t3102a t3102b t3102c} do_test alter-13.2 { execsql { ALTER TABLE t3102a RENAME TO t3102a_rename; SELECT name FROM sqlite_master WHERE name GLOB 't3102*' ORDER BY 1; } } {t3102a_rename t3102b t3102c} do_test alter-13.3 { execsql { ALTER TABLE t3102b RENAME TO t3102b_rename; SELECT name FROM sqlite_master WHERE name GLOB 't3102*' ORDER BY 1; } } {t3102a_rename t3102b_rename t3102c} # Ticket #3651 do_test alter-14.1 { catchsql { CREATE TABLE t3651(a UNIQUE); |
︙ | ︙ |
Changes to test/alter2.test.
︙ | ︙ | |||
67 68 69 70 71 72 73 74 75 76 77 78 79 80 | PRAGMA writable_schema = 1; UPDATE sqlite_master SET sql = '$s' WHERE name = '$t' AND type = 'table'; PRAGMA writable_schema = 0; }] dbat close set_file_format 2 } #----------------------------------------------------------------------- # Some basic tests to make sure short rows are handled. # do_test alter2-1.1 { execsql { CREATE TABLE abc(a, b); | > > > > > > > > > > > > > > > | 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 | PRAGMA writable_schema = 1; UPDATE sqlite_master SET sql = '$s' WHERE name = '$t' AND type = 'table'; PRAGMA writable_schema = 0; }] dbat close set_file_format 2 } # Create bogus application-defined functions for functions used # internally by ALTER TABLE, to ensure that ALTER TABLE falls back # to the built-in functions. # proc failing_app_func {args} {error "bad function"} do_test alter2-1.0 { db func substr failing_app_func db func like failing_app_func db func sqlite_rename_table failing_app_func db func sqlite_rename_trigger failing_app_func db func sqlite_rename_parent failing_app_func catchsql {SELECT substr('abcdefg',1,3)} } {1 {bad function}} #----------------------------------------------------------------------- # Some basic tests to make sure short rows are handled. # do_test alter2-1.1 { execsql { CREATE TABLE abc(a, b); |
︙ | ︙ |
Changes to test/vacuum.test.
︙ | ︙ | |||
50 51 52 53 54 55 56 57 58 59 60 61 62 63 | COMMIT; DROP TABLE t2; } set ::size1 [file size test.db] set ::cksum [cksum] expr {$::cksum!=""} } {1} do_test vacuum-1.2 { execsql { VACUUM; } cksum } $cksum ifcapable vacuum { | > > > > > > > > > > > > > | 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 | COMMIT; DROP TABLE t2; } set ::size1 [file size test.db] set ::cksum [cksum] expr {$::cksum!=""} } {1} # Create bogus application-defined functions for functions used # internally by VACUUM, to ensure that VACUUM falls back # to the built-in functions. # proc failing_app_func {args} {error "bad function"} do_test vacuum-1.1b { db func substr failing_app_func db func like failing_app_func db func quote failing_app_func catchsql {SELECT substr(name,1,3) FROM sqlite_master} } {1 {bad function}} do_test vacuum-1.2 { execsql { VACUUM; } cksum } $cksum ifcapable vacuum { |
︙ | ︙ |