Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Prevent collation sequences and user functions from being deleted or changed while SQL statements are executing. (CVS 2275) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
cabab62bc10568d435806a7059fad727 |
User & Date: | danielk1977 2005-01-25 04:27:55.000 |
Context
2005-01-26
| ||
03:58 | Allow GROUP BY on non-aggregate queries. Ticket #1064 (CVS 2276) (check-in: 0642d3e3d6 user: danielk1977 tags: trunk) | |
2005-01-25
| ||
04:27 | Prevent collation sequences and user functions from being deleted or changed while SQL statements are executing. (CVS 2275) (check-in: cabab62bc1 user: danielk1977 tags: trunk) | |
2005-01-24
| ||
23:27 | Clarify documentation of DEFAULT CURRENT_TIME etc. (version 3.1.0 and greater only). (CVS 2274) (check-in: 557eb2ec9d user: danielk1977 tags: trunk) | |
Changes
Changes to src/main.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.275 2005/01/25 04:27:55 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** The following constant value is used by the SQLITE_BIGENDIAN and |
︙ | ︙ | |||
732 733 734 735 736 737 738 739 740 741 742 743 744 745 | pUserData, xFunc, xStep, xFinal); if( rc!=SQLITE_OK ) return rc; enc = SQLITE_UTF16BE; } #else enc = SQLITE_UTF8; #endif p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1); if( p==0 ) return SQLITE_NOMEM; p->xFunc = xFunc; p->xStep = xStep; p->xFinalize = xFinal; p->pUserData = pUserData; | > > > > > > > > > > > > > > > > | 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 | pUserData, xFunc, xStep, xFinal); if( rc!=SQLITE_OK ) return rc; enc = SQLITE_UTF16BE; } #else enc = SQLITE_UTF8; #endif /* Check if an existing function is being overridden or deleted. If so, ** and there are active VMs, then return SQLITE_BUSY. If a function ** is being overridden/deleted but there are no active VMs, allow the ** operation to continue but invalidate all precompiled statements. */ p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 0); if( p && p->iPrefEnc==enc && p->nArg==nArg ){ if( db->activeVdbeCnt ){ sqlite3Error(db, SQLITE_BUSY, "Unable to delete/modify user-function due to active statements"); return SQLITE_BUSY; }else{ sqlite3ExpirePreparedStatements(db); } } p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1); if( p==0 ) return SQLITE_NOMEM; p->xFunc = xFunc; p->xStep = xStep; p->xFinalize = xFinal; p->pUserData = pUserData; |
︙ | ︙ | |||
1284 1285 1286 1287 1288 1289 1290 | sqlite3Error(db, SQLITE_ERROR, "Param 3 to sqlite3_create_collation() must be one of " "SQLITE_UTF8, SQLITE_UTF16, SQLITE_UTF16LE or SQLITE_UTF16BE" ); return SQLITE_ERROR; } | | > | > | > > > > > | 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 | sqlite3Error(db, SQLITE_ERROR, "Param 3 to sqlite3_create_collation() must be one of " "SQLITE_UTF8, SQLITE_UTF16, SQLITE_UTF16LE or SQLITE_UTF16BE" ); return SQLITE_ERROR; } /* Check if this call is removing or replacing an existing collation ** sequence. If so, and there are active VMs, return busy. If there ** are no active VMs, invalidate any pre-compiled statements. */ pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 0); if( pColl && pColl->xCmp ){ if( db->activeVdbeCnt ){ sqlite3Error(db, SQLITE_BUSY, "Unable to delete/modify collation sequence due to active statements"); return SQLITE_BUSY; } sqlite3ExpirePreparedStatements(db); } pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 1); if( 0==pColl ){ rc = SQLITE_NOMEM; }else{ |
︙ | ︙ |
Changes to src/tclsqlite.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** 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. ** ************************************************************************* ** A TCL Interface to SQLite ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** 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. ** ************************************************************************* ** A TCL Interface to SQLite ** ** $Id: tclsqlite.c,v 1.118 2005/01/25 04:27:55 danielk1977 Exp $ */ #ifndef NO_TCL /* Omit this whole file if TCL is unavailable */ #include "sqliteInt.h" #include "hash.h" #include "tcl.h" #include <stdlib.h> |
︙ | ︙ | |||
692 693 694 695 696 697 698 699 700 701 702 703 704 705 | pCollate->interp = interp; pCollate->pNext = pDb->pCollate; pCollate->zScript = (char*)&pCollate[1]; pDb->pCollate = pCollate; strcpy(pCollate->zScript, zScript); if( sqlite3_create_collation(pDb->db, zName, SQLITE_UTF8, pCollate, tclSqlCollate) ){ return TCL_ERROR; } break; } /* ** $db collation_needed SCRIPT | > | 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 | pCollate->interp = interp; pCollate->pNext = pDb->pCollate; pCollate->zScript = (char*)&pCollate[1]; pDb->pCollate = pCollate; strcpy(pCollate->zScript, zScript); if( sqlite3_create_collation(pDb->db, zName, SQLITE_UTF8, pCollate, tclSqlCollate) ){ Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE); return TCL_ERROR; } break; } /* ** $db collation_needed SCRIPT |
︙ | ︙ | |||
1124 1125 1126 1127 1128 1129 1130 | pFunc->pNext = pDb->pFunc; pFunc->zScript = (char*)&pFunc[1]; pDb->pFunc = pFunc; strcpy(pFunc->zScript, zScript); rc = sqlite3_create_function(pDb->db, zName, -1, SQLITE_UTF8, pFunc, tclSqlFunc, 0, 0); if( rc!=SQLITE_OK ){ | | > | 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 | pFunc->pNext = pDb->pFunc; pFunc->zScript = (char*)&pFunc[1]; pDb->pFunc = pFunc; strcpy(pFunc->zScript, zScript); rc = sqlite3_create_function(pDb->db, zName, -1, SQLITE_UTF8, pFunc, tclSqlFunc, 0, 0); if( rc!=SQLITE_OK ){ rc = TCL_ERROR; Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE); }else{ /* Must flush any cached statements */ flushStmtCache( pDb ); } break; } |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing the printf() interface to SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing the printf() interface to SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** ** $Id: test1.c,v 1.128 2005/01/25 04:27:55 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include "os.h" #include <stdlib.h> #include <string.h> |
︙ | ︙ | |||
2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ms", 0); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_sleep(atoi(argv[1])))); return TCL_OK; } #endif /* ** Usage: tcl_variable_type VARIABLENAME ** ** Return the name of the internal representation for the ** value of the given variable. */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ms", 0); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_sleep(atoi(argv[1])))); return TCL_OK; } #endif /* ** Usage: sqlite_delete_function DB function-name ** ** Delete the user function 'function-name' from database handle DB. It ** is assumed that the user function was created as UTF8, any number of ** arguments (the way the TCL interface does it). */ static int delete_function( void * clientData, Tcl_Interp *interp, int argc, char **argv ){ int rc; sqlite3 *db; if( argc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB function-name", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0); Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); return TCL_OK; } /* ** Usage: sqlite_delete_collation DB collation-name ** ** Delete the collation sequence 'collation-name' from database handle ** DB. It is assumed that the collation sequence was created as UTF8 (the ** way the TCL interface does it). */ static int delete_collation( void * clientData, Tcl_Interp *interp, int argc, char **argv ){ int rc; sqlite3 *db; if( argc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB function-name", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0); Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC); return TCL_OK; } /* ** Usage: tcl_variable_type VARIABLENAME ** ** Return the name of the internal representation for the ** value of the given variable. */ |
︙ | ︙ | |||
2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 | { "sqlite3_key", (Tcl_CmdProc*)test_key }, { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey }, { "sqlite_set_magic", (Tcl_CmdProc*)sqlite_set_magic }, { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt }, #if 0 { "sqlite3_sleep", (Tcl_CmdProc*)test_sleep }, #endif }; static struct { char *zName; Tcl_ObjCmdProc *xProc; void *clientData; } aObjCmd[] = { { "sqlite3_bind_int", test_bind_int, 0 }, | > > | 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 | { "sqlite3_key", (Tcl_CmdProc*)test_key }, { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey }, { "sqlite_set_magic", (Tcl_CmdProc*)sqlite_set_magic }, { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt }, #if 0 { "sqlite3_sleep", (Tcl_CmdProc*)test_sleep }, #endif { "sqlite_delete_function", (Tcl_CmdProc*)delete_function }, { "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation } }; static struct { char *zName; Tcl_ObjCmdProc *xProc; void *clientData; } aObjCmd[] = { { "sqlite3_bind_int", test_bind_int, 0 }, |
︙ | ︙ |
Changes to test/schema.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 | # 2005 Jan 24 # # 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 implements regression tests for SQLite library. # # This file tests the various conditions under which an SQLITE_SCHEMA # error should be returned. # # $Id: schema.test,v 1.3 2005/01/25 04:27:55 danielk1977 Exp $ #--------------------------------------------------------------------- # When any of the following types of SQL statements or actions are # executed, all pre-compiled statements are invalidated. An attempt # to execute an invalidated statement always returns SQLITE_SCHEMA. # # CREATE/DROP TABLE...................................schema-1.* # CREATE/DROP VIEW....................................schema-2.* # CREATE/DROP TRIGGER.................................schema-3.* # CREATE/DROP INDEX...................................schema-4.* # DETACH..............................................schema-5.* # Deleting a user-function............................schema-6.* # Deleting a collation sequence.......................schema-7.* # Setting or changing the authorization function......schema-8.* # # Note: Test cases schema-6.* are missing right now. # # Test cases schema-9.* and schema-10.* test some specific bugs # that came up during development. # # Test cases schema-11.* test that it is impossible to delete or # change a collation sequence or user-function while SQL statements # are executing. Adding new collations or functions is allowed. # # Note: Test cases schema-11.* are also missing right now. set testdir [file dirname $argv0] source $testdir/tester.tcl do_test schema-1.1 { set ::STMT [sqlite3_prepare $::DB {SELECT * FROM sqlite_master} -1 TAIL] execsql { |
︙ | ︙ | |||
148 149 150 151 152 153 154 155 156 157 158 159 160 161 | DETACH aux; } sqlite3_step $::STMT } {SQLITE_ERROR} do_test schema-5.4 { sqlite3_finalize $::STMT } {SQLITE_SCHEMA} #--------------------------------------------------------------------- # Tests 7.* check that prepared statements are invalidated when # a collation sequence is deleted (but not when one is added). # do_test schema-7.1 { set sql {SELECT * FROM abc;} | > > > > > > > > > > > > > > > > > > > > | 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | DETACH aux; } sqlite3_step $::STMT } {SQLITE_ERROR} do_test schema-5.4 { sqlite3_finalize $::STMT } {SQLITE_SCHEMA} #--------------------------------------------------------------------- # Tests 6.* check that prepared statements are invalidated when # a user-function is deleted (but not when one is added). do_test schema-6.1 { set sql {SELECT * FROM abc;} set ::STMT [sqlite3_prepare $::DB $sql -1 TAIL] db function hello_function {} sqlite3_step $::STMT } {SQLITE_DONE} do_test schema-6.2 { sqlite3_reset $::STMT } {SQLITE_OK} do_test schema-6.3 { sqlite_delete_function $::DB hello_function sqlite3_step $::STMT } {SQLITE_ERROR} do_test schema-6.4 { sqlite3_finalize $::STMT } {SQLITE_SCHEMA} #--------------------------------------------------------------------- # Tests 7.* check that prepared statements are invalidated when # a collation sequence is deleted (but not when one is added). # do_test schema-7.1 { set sql {SELECT * FROM abc;} |
︙ | ︙ | |||
250 251 252 253 254 255 256 257 258 259 | execsql { SELECT * FROM abc } db2 } {1 2 3} do_test schema-10.5 { db2 close } {} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 | execsql { SELECT * FROM abc } db2 } {1 2 3} do_test schema-10.5 { db2 close } {} #--------------------------------------------------------------------- # Attempting to delete or replace a user-function or collation sequence # while there are active statements returns an SQLITE_BUSY error. # # schema-11.1 - 11.4: User function. # schema-11.5 - 11.8: Collation sequence. # do_test schema-11.1 { db function tstfunc {} set sql {SELECT * FROM abc} set ::STMT [sqlite3_prepare $::DB $sql -1 TAIL] sqlite3_step $::STMT } {SQLITE_ROW} do_test schema-11.2 { sqlite_delete_function $::DB tstfunc } {SQLITE_BUSY} do_test schema-11.3 { set rc [catch { db function tstfunc {} } msg] list $rc $msg } {1 {Unable to delete/modify user-function due to active statements}} do_test schema-11.4 { sqlite3_finalize $::STMT } {SQLITE_OK} do_test schema-11.5 { db collate tstcollate {} set sql {SELECT * FROM abc} set ::STMT [sqlite3_prepare $::DB $sql -1 TAIL] sqlite3_step $::STMT } {SQLITE_ROW} do_test schema-11.6 { sqlite_delete_collation $::DB tstcollate } {SQLITE_BUSY} do_test schema-11.7 { set rc [catch { db collate tstcollate {} } msg] list $rc $msg } {1 {Unable to delete/modify collation sequence due to active statements}} do_test schema-11.8 { sqlite3_finalize $::STMT } {SQLITE_OK} finish_test |
Changes to test/select2.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # 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 implements regression tests for SQLite library. The # focus of this file is testing the SELECT statement. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2001 September 15 # # 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 implements regression tests for SQLite library. The # focus of this file is testing the SELECT statement. # # $Id: select2.test,v 1.24 2005/01/25 04:27:55 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Create a table with some data # execsql {CREATE TABLE tbl1(f1 int, f2 int)} |
︙ | ︙ | |||
67 68 69 70 71 72 73 | for {set i 1} {$i<=30000} {incr i} { set i2 [expr {$i*2}] set i3 [expr {$i*3}] db eval {INSERT INTO tbl2 VALUES($i,$i2,$i3)} } execsql {COMMIT} }] | | | | 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 | for {set i 1} {$i<=30000} {incr i} { set i2 [expr {$i*2}] set i3 [expr {$i*3}] db eval {INSERT INTO tbl2 VALUES($i,$i2,$i3)} } execsql {COMMIT} }] list } {} puts "time with cache: $::t1" } catch {execsql {DROP TABLE tbl2}} do_test select2-2.0.2 { set t2 [time { execsql {CREATE TABLE tbl2(f1 int, f2 int, f3 int); BEGIN;} for {set i 1} {$i<=30000} {incr i} { set i2 [expr {$i*2}] set i3 [expr {$i*3}] execsql "INSERT INTO tbl2 VALUES($i,$i2,$i3)" } execsql {COMMIT} }] list } {} puts "time without cache: $t2" ifcapable tclvar { do_test select2-2.0.3 { expr {[lindex $t1 0]<[lindex $t2 0]} } 1 } |
︙ | ︙ |