]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
When commands such as ALTER TABLE and VACUUM use SQL internally, make sure
authordrh <drh@noemail.net>
Sat, 24 Apr 2010 14:02:59 +0000 (14:02 +0000)
committerdrh <drh@noemail.net>
Sat, 24 Apr 2010 14:02:59 +0000 (14:02 +0000)
they use only the built-in functions and not application-defined overrides
for those functions.

FossilOrigin-Name: 0291ed974d5bf1e344e2c38422530cc961b897da

manifest
manifest.uuid
src/alter.c
src/callback.c
src/func.c
src/sqliteInt.h
src/vacuum.c
test/alter.test
test/alter2.test
test/vacuum.test

index b2b561671023ceb04b37bf3576d8135c4ad31460..2c22758bdf5e0a0b39c0b86c12ea1b3a04a5bed6 100644 (file)
--- a/manifest
+++ b/manifest
@@ -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-----
index 80f48ee22218b85ff515a146da4b782c15ca0c57..d37c175bb596472a98962f9f4d30a76ad97a811f 100644 (file)
@@ -1 +1 @@
-e79dac3c2f723ed7cc62fcef468f53952711f242
\ No newline at end of file
+0291ed974d5bf1e344e2c38422530cc961b897da
\ No newline at end of file
index 694b243bd3d5eb6257a5a35abf09adc8a1c81e0a..359c4e73787cd81fb1cc3509a729a5ea18284239 100644 (file)
@@ -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
index e6c51bccdbc67d121793ac9d4eda0344555e63d9..c016959fd0ad92ab063001d5786916235d900a6d 100644 (file)
@@ -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);
index 7ff1fecb0a63a22fe2cd1cb034e48f8343bc0635..7bd3d58fa49051a0f97d1d4b03db422175b3f78a 100644 (file)
@@ -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
 }
index 6007b8af9924f41dadcefc940b928979c59fe401..6e6ec72ac2aaf876ac810d78821f11290726f77d 100644 (file)
@@ -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*, ...);
index 1d3b998c662e60150c4e01f749ab61eeb635c32d..12a07e9c87c1abaaa0c01bdacb013bc5ac169866 100644 (file)
@@ -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;
 
index 2db82dd4293f9844c037abf0b91c22e8c7151f64..bf7cf006241b920f8ee1bf70872bc1c96990a070 100644 (file)
@@ -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}
 
index 0ce023b8fdcb069b9abf400da295dcdb777fa455..94c7d26a6fa691ff0f0cc53ba0a3876cfc7def02 100644 (file)
@@ -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.
 #
index 4b1cd5a3e60366f41bbbaad282920e94d1dd3171..256730b3cf6114853104119be57f5c0cfb6b68e8 100644 (file)
@@ -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;