diff options
author | drh <drh@noemail.net> | 2010-04-24 14:02:59 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2010-04-24 14:02:59 +0000 |
commit | 545f587fc8564075dafeb6a324fde43079b87a11 (patch) | |
tree | a181c9e2d9078412105b37c69e6a95e2a1df31b0 | |
parent | 9a6e897328371a17f4ead1cd72c12240d372a81a (diff) | |
download | sqlite-545f587fc8564075dafeb6a324fde43079b87a11.tar.gz sqlite-545f587fc8564075dafeb6a324fde43079b87a11.zip |
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.
FossilOrigin-Name: 0291ed974d5bf1e344e2c38422530cc961b897da
-rw-r--r-- | manifest | 38 | ||||
-rw-r--r-- | manifest.uuid | 2 | ||||
-rw-r--r-- | src/alter.c | 29 | ||||
-rw-r--r-- | src/callback.c | 7 | ||||
-rw-r--r-- | src/func.c | 6 | ||||
-rw-r--r-- | src/sqliteInt.h | 3 | ||||
-rw-r--r-- | src/vacuum.c | 2 | ||||
-rw-r--r-- | test/alter.test | 31 | ||||
-rw-r--r-- | test/alter2.test | 15 | ||||
-rw-r--r-- | test/vacuum.test | 13 |
10 files changed, 109 insertions, 37 deletions
@@ -1,5 +1,8 @@ -C Merge\sof\snotify.c\schanges\sfrom\sexperimental.\s\s\nReset\sstored\sblocking\sconnection\swhen\sregistered\sunlock_notify\scallback\sis\scleared. -D 2010-04-23T14:29:04 +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +C When\scommands\ssuch\sas\sALTER\sTABLE\sand\sVACUUM\suse\sSQL\sinternally,\smake\ssure\nthey\suse\sonly\sthe\sbuilt-in\sfunctions\sand\snot\sapplication-defined\soverrides\nfor\sthose\sfunctions. +D 2010-04-24T14:02:59 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 4f2f967b7e58a35bb74fb7ec8ae90e0f4ca7868b F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -102,7 +105,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad -F src/alter.c e6f4d11b1c0b23642fc46bac9abe0753c4294e05 +F src/alter.c a9ff6f14b3935502537e90194b66c7bc79bed317 F src/analyze.c 8dfd781ac326496746ecdfc3e099250ed5d79be5 F src/attach.c 7abe1607c2054585377cdba3c219e8572f84ca5e F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 @@ -113,7 +116,7 @@ F src/btree.c 01559397cbd4a5aa62a822e8ca9ac94b6db14743 F src/btree.h ad6cff92286f9b02ec32f0b97136e9a544249f37 F src/btreeInt.h 22447d259639271774a931cbf66aa55112846681 F src/build.c 11100b66fb97638d2d874c1d34d8db90650bb1d7 -F src/callback.c 908f3e0172c3d4058f4ca0acd42c637c52e9669f +F src/callback.c 01843bdf4b0420fd28046525d150fcd9802931a9 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 51553a859994d01d8bf3500747f66a890c459774 F src/date.c 485a4409a384310e6d93fd1104a9d0a8658becd9 @@ -121,7 +124,7 @@ F src/delete.c 610dc008e88a9599f905f5cbe9577ac9c36e0581 F src/expr.c 6baed2a0448d494233d9c0a610eea018ab386a32 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c e2116672a6bd610dc888e27df292ebc7999c9bb0 -F src/func.c 5dca069d98eca0ff70c9a8fb8ab9e1d6467187b5 +F src/func.c b4af81088b1ad2ceea42d70a7aa048a48d18733f F src/global.c 5a9c1e3c93213ca574786ac1caa976ce8f709105 F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970 @@ -168,7 +171,7 @@ F src/select.c b7c9a40bc1567bceff52ad4b73108734ee4bf268 F src/shell.c c40427c7245535a04a9cb4a417b6cc05c022e6a4 F src/sqlite.h.in dc98616304e3e776008655671d81e3ad3028ada7 F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89 -F src/sqliteInt.h bd7ff54663bdd5b57e0eb8b49aca5a3a3c60119a +F src/sqliteInt.h 15339730eeeb571ed515d125e3446ae80ec3b4ef F src/sqliteLimit.h 3afab2291762b5d09ae20c18feb8e9fa935a60a6 F src/status.c 4df6fe7dce2d256130b905847c6c60055882bdbe F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -211,7 +214,7 @@ F src/trigger.c 8927588cb9e6d47f933b53bfe74200fbb504100d F src/update.c c0dc6b75ad28b76b619042d934f337b02acee208 F src/utf.c 1baeeac91707a4df97ccc6141ec0f808278af685 F src/util.c 32aebf04c10e51ad3977a928b7416bed671b620b -F src/vacuum.c b1d542c8919d4d11119f78069e1906a1ad07e0ee +F src/vacuum.c 8e7d9a6fd076774bb6e211cad335c7337948a164 F src/vdbe.c 2abd931ea2aec3eacc6426677f40cc5a1071d34e F src/vdbe.h 471f6a3dcec4817ca33596fe7f6654d56c0e75f3 F src/vdbeInt.h 19ebc8c2a2e938340051ee65af3f377fb99102d1 @@ -226,8 +229,8 @@ F src/where.c faadd9c2bf08868e5135192b44e0d753e363a885 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87 F test/all.test 14165b3e32715b700b5f0cbf8f6e3833dda0be45 -F test/alter.test 645b2e8d23c9936f9494af9d2fa7f8351a248c6e -F test/alter2.test d0133bfa7a0a24aa84c034051410b95217d24a35 +F test/alter.test 15f9224868b290d6bf7a63f31437f31aee070636 +F test/alter2.test 0266160d61b0f7156b7e7a9905dbf85ebe067c63 F test/alter3.test 25b95a136708f22b87184fa6a4309eea03d65153 F test/alter4.test 9386ffd1e9c7245f43eca412b2058d747509cc1f F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc @@ -731,7 +734,7 @@ F test/types3.test a0f66bf12f80fad89493535474f7a6d16fa58150 F test/unique.test 083c7fff74695bcc27a71d75699deba3595bc9c2 F test/update.test 8bc86fd7ef1a00014f76dc6a6a7c974df4aef172 F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae -F test/vacuum.test 68e39b2228b4b772166debef4a82accf6ddd32f3 +F test/vacuum.test 15ae6784e70428b8db64e95c92d84b19e507b719 F test/vacuum2.test ec57f21d394b7b72249b11f8e4b5d487bab56539 F test/vacuum3.test f39ad1428347c5808cd2da7578c470f186a4d0ce F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9 @@ -798,7 +801,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 3e646e3f4cd0ca288e444561e951cecfdaee2ab5 95ff76ef67d6189f54375973fa485d6eb464b029 -R 7c539ea1b6c4af52a0f9e1df86aac19e -U shaneh -Z bd2044fda76be379d81bb4e3c420d2ab +P e79dac3c2f723ed7cc62fcef468f53952711f242 +R f7b3f2f2586b016425d2ff4d0aa6d5e4 +U drh +Z 60e8a7849ac5e43c2a7c878285e8be5d +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.6 (GNU/Linux) + +iD8DBQFL0voooxKgR168RlERAuygAJ9JZEPkPJWwA9gu3SJJpCJ6uLWSCACfXJK2 +t7ZFFTqEHyFHDlhkRqjBdIY= +=45i3 +-----END PGP SIGNATURE----- diff --git a/manifest.uuid b/manifest.uuid index 80f48ee22..d37c175bb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e79dac3c2f723ed7cc62fcef468f53952711f242
\ No newline at end of file +0291ed974d5bf1e344e2c38422530cc961b897da
\ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 694b243bd..359c4e737 100644 --- a/src/alter.c +++ b/src/alter.c @@ -226,17 +226,23 @@ static void renameTriggerFunc( /* ** Register built-in functions used to help implement ALTER TABLE */ -void sqlite3AlterFunctions(sqlite3 *db){ - sqlite3CreateFunc(db, "sqlite_rename_table", 2, SQLITE_UTF8, 0, - renameTableFunc, 0, 0); +void sqlite3AlterFunctions(void){ + static SQLITE_WSD FuncDef aAlterTableFuncs[] = { + FUNCTION(sqlite_rename_table, 2, 0, 0, renameTableFunc), #ifndef SQLITE_OMIT_TRIGGER - sqlite3CreateFunc(db, "sqlite_rename_trigger", 2, SQLITE_UTF8, 0, - renameTriggerFunc, 0, 0); + FUNCTION(sqlite_rename_trigger, 2, 0, 0, renameTriggerFunc), #endif #ifndef SQLITE_OMIT_FOREIGN_KEY - sqlite3CreateFunc(db, "sqlite_rename_parent", 3, SQLITE_UTF8, 0, - renameParentFunc, 0, 0); + 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]); + } } /* @@ -380,7 +386,9 @@ void sqlite3AlterRenameTable( 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) ); @@ -389,6 +397,7 @@ void sqlite3AlterRenameTable( 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); @@ -556,6 +565,7 @@ void sqlite3AlterRenameTable( exit_rename_table: sqlite3SrcListDelete(db, pSrc); sqlite3DbFree(db, zName); + db->flags = savedDbFlags; } @@ -675,9 +685,11 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ 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) " @@ -686,6 +698,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ zTab ); sqlite3DbFree(db, zCol); + db->flags = savedDbFlags; } /* If the default value of the new column is NULL, then set the file diff --git a/src/callback.c b/src/callback.c index e6c51bccd..c016959fd 100644 --- a/src/callback.c +++ b/src/callback.c @@ -353,14 +353,19 @@ FuncDef *sqlite3FindFunction( /* 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 ){ + 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); diff --git a/src/func.c b/src/func.c index 7ff1fecb0..7bd3d58fa 100644 --- a/src/func.c +++ b/src/func.c @@ -1416,9 +1416,6 @@ static void groupConcatFinalize(sqlite3_context *context){ ** external linkage. */ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ -#ifndef SQLITE_OMIT_ALTERTABLE - sqlite3AlterFunctions(db); -#endif if( !db->mallocFailed ){ int rc = sqlite3_overload_function(db, "MATCH", 2); assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); @@ -1592,4 +1589,7 @@ void sqlite3RegisterGlobalFunctions(void){ sqlite3FuncDefInsert(pHash, &aFunc[i]); } sqlite3RegisterDateTimeFunctions(); +#ifndef SQLITE_OMIT_ALTERTABLE + sqlite3AlterFunctions(); +#endif } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 6007b8af9..6e6ec72ac 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -913,6 +913,7 @@ struct sqlite3 { #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 @@ -2881,7 +2882,7 @@ extern int sqlite3PendingByte; #endif void sqlite3RootPageMoved(Db*, int, int); void sqlite3Reindex(Parse*, Token*, Token*); -void sqlite3AlterFunctions(sqlite3*); +void sqlite3AlterFunctions(void); void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); int sqlite3GetToken(const unsigned char *, int *); void sqlite3NestedParse(Parse*, const char*, ...); diff --git a/src/vacuum.c b/src/vacuum.c index 1d3b998c6..12a07e9c8 100644 --- a/src/vacuum.c +++ b/src/vacuum.c @@ -117,7 +117,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ saved_nChange = db->nChange; saved_nTotalChange = db->nTotalChange; saved_xTrace = db->xTrace; - db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks; + db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_PreferBuiltin; db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder); db->xTrace = 0; diff --git a/test/alter.test b/test/alter.test index 2db82dd42..bf7cf0062 100644 --- a/test/alter.test +++ b/test/alter.test @@ -173,6 +173,20 @@ ifcapable tempdb { } } +# 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 # @@ -567,7 +581,8 @@ do_test alter-5.3 { } {} foreach tblname [execsql { - SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite%' + SELECT name FROM sqlite_master + WHERE type='table' AND name NOT GLOB 'sqlite*' }] { execsql "DROP TABLE \"$tblname\"" } @@ -688,17 +703,17 @@ do_test alter-9.2 { 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 LIKE 'xyz%'} + 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 LIKE 'sqlite_autoindex%'} + 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 LIKE 'xyz%'} + 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 LIKE 'sqlite_autoindex%'} + execsql {SELECT name FROM sqlite_master WHERE name GLOB 'sqlite_autoindex*'} } [list sqlite_autoindex_xyzabc_1] do_test alter-11.1 { @@ -795,19 +810,19 @@ do_test alter-13.1 { CREATE TABLE t3102b -- comment (y); CREATE INDEX t3102c ON t3102a(x); - SELECT name FROM sqlite_master WHERE name LIKE 't3102%' ORDER BY 1; + 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 LIKE 't3102%' ORDER BY 1; + 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 LIKE 't3102%' ORDER BY 1; + SELECT name FROM sqlite_master WHERE name GLOB 't3102*' ORDER BY 1; } } {t3102a_rename t3102b_rename t3102c} diff --git a/test/alter2.test b/test/alter2.test index 0ce023b8f..94c7d26a6 100644 --- a/test/alter2.test +++ b/test/alter2.test @@ -72,6 +72,21 @@ proc alter_table {tbl sql {file_format 2}} { 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. # diff --git a/test/vacuum.test b/test/vacuum.test index 4b1cd5a3e..256730b3c 100644 --- a/test/vacuum.test +++ b/test/vacuum.test @@ -54,6 +54,19 @@ do_test vacuum-1.1 { 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; |