do_execsql_test 5.0 {
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(a COLLATE NOCASE);
+ INSERT INTO t1 VALUES(1, 1);
+ INSERT INTO t1 VALUES(2, 2);
}
-#puts [intck_sql db i1]
+do_test 5.1 {
+ set ic [sqlite3_intck db nosuchdb]
+ $ic step
+} {SQLITE_ERROR}
+
+do_test 5.2 {
+ $ic close
+ set ic [sqlite3_intck db {}]
+ while {[$ic step]=="SQLITE_OK"} {}
+ set res [$ic error]
+ $ic close
+ set res
+} {SQLITE_OK {}}
+
+do_test 5.3 { test_do_intck db "main" } {}
+
+do_test 5.4 {
+ set ret {}
+ set ic [sqlite3_intck db main]
+ db eval [$ic test_sql t1] {
+ if {$error_message!=""} { lappend ret $error_message }
+ }
+ $ic close
+ set ret
+} {}
+
+do_test 5.5 {
+ set ret {}
+ set ic [sqlite3_intck db main]
+ db eval [$ic test_sql {}] {
+ if {$error_message!=""} { lappend ret $error_message }
+ }
+ $ic close
+ set ret
+} {}
+
+db cache flush
+
+do_test 5.6 {
+ set ret {}
+ set ic [sqlite3_intck db main]
+ $ic step
+ db eval [$ic test_sql {}] {
+ if {$error_message!=""} { lappend ret $error_message }
+ }
+ $ic close
+ set ret
+} {}
+
+#-------------------------------------------------------------------------
+reset_db
+
+do_execsql_test 6.0 {
+ CREATE TABLE t1(x, y, PRIMARY KEY(x)) WITHOUT ROWID;
+ CREATE INDEX i1 ON t1(y, x);
+ INSERT INTO t1 VALUES(X'0000', X'1111');
+}
+
+do_intck_test 6.1 {}
+
+do_execsql_test 6.2.1 {
+ PRAGMA writable_schema = 1;
+ UPDATE sqlite_schema SET sql = 'CREATE INDEX i1' WHERE name='i1';
+} {}
+do_intck_test 6.2.2 {}
+
+do_execsql_test 6.3.1 {
+ UPDATE sqlite_schema SET sql = 'CREATE INDEX i1(y' WHERE name='i1';
+} {}
+do_intck_test 6.3.2 {}
+
+do_execsql_test 6.4.1 {
+ UPDATE sqlite_schema
+ SET sql = 'CREATE INDEX i1(y) hello world'
+ WHERE name='i1';
+} {}
+do_intck_test 6.4.2 {}
+
+do_execsql_test 6.5.1 {
+ UPDATE sqlite_schema
+ SET sql = 'CREATE INDEX i1(y, x) WHERE 1 '
+ WHERE name='i1';
+} {}
+do_intck_test 6.5.2 {}
+
+do_execsql_test 6.6.1 {
+ UPDATE sqlite_schema
+ SET sql = 'CREATE INDEX i1( , ) WHERE 1 '
+ WHERE name='i1';
+} {}
+
+do_test 6.7.2 {
+ set ic [sqlite3_intck db main]
+ $ic step
+} {SQLITE_ERROR}
+do_test 6.5.3 {
+ $ic error
+} {SQLITE_ERROR {near "AS": syntax error}}
+$ic close
+
+do_execsql_test 6.6.1 {
+ UPDATE sqlite_schema
+ SET sql = 'CREATE INDEX i1([y'
+ WHERE name='i1';
+} {}
+do_intck_test 6.6.2 {}
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 7.0 {
+ CREATE TABLE x1("1", "22", "3333", four);
+ CREATE INDEX i1 ON x1( "1" , "22", NULL);
+ INSERT INTO x1 VALUES(1, 22, 3333, NULL);
+ INSERT INTO x1 VALUES(1, 22, 3333, NULL);
+}
+do_execsql_test 7.1 " CREATE INDEX i2 ON x1( \"1\"\r\n\t ) "
+do_execsql_test 7.2 { CREATE INDEX i3 ON x1( "22" || 'abc''def' || `1` ) }
+do_execsql_test 7.3 { CREATE INDEX i4 ON x1( [22] + [1] ) }
+do_execsql_test 7.4 { CREATE INDEX i5 ON x1( four||'hello' ) }
+
+do_intck_test 7.5 {}
+
finish_test
--- /dev/null
+# 2024 February 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.
+#
+#***********************************************************************
+#
+
+source [file join [file dirname [info script]] intck_common.tcl]
+set testprefix intckbusy
+
+
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
+ INSERT INTO t1 VALUES(1, 2, 3);
+ INSERT INTO t1 VALUES(2, 'two', 'three');
+ INSERT INTO t1 VALUES(3, NULL, NULL);
+ CREATE INDEX i1 ON t1(b, c);
+}
+
+sqlite3 db2 test.db
+
+do_execsql_test -db db2 1.1 {
+ BEGIN EXCLUSIVE;
+ INSERT INTO t1 VALUES(4, 5, 6);
+}
+
+do_test 1.2 {
+ set ic [sqlite3_intck db main]
+ $ic step
+} {SQLITE_BUSY}
+do_test 1.3 {
+ $ic unlock
+} {SQLITE_BUSY}
+do_test 1.4 {
+ $ic error
+} {SQLITE_BUSY {database is locked}}
+do_test 1.4 {
+ $ic close
+} {}
+
+finish_test
+
** and error code currently held by the database handle in p->rc and p->zErr.
*/
static void intckSaveErrmsg(sqlite3_intck *p){
- const char *zDberr = sqlite3_errmsg(p->db);
p->rc = sqlite3_errcode(p->db);
- if( zDberr ){
- sqlite3_free(p->zErr);
- p->zErr = sqlite3_mprintf("%s", zDberr);
- }
+ sqlite3_free(p->zErr);
+ p->zErr = sqlite3_mprintf("%s", sqlite3_errmsg(p->db));
}
/*
}
}
+/*
+** If there is already an error in handle p, return it. Otherwise, call
+** sqlite3_step() on the statement handle and return that value.
+*/
+static int intckStep(sqlite3_intck *p, sqlite3_stmt *pStmt){
+ if( p->rc ) return p->rc;
+ return sqlite3_step(pStmt);
+}
+
/*
** Execute SQL statement zSql. There is no way to obtain any results
** returned by the statement. This function uses the sqlite3_intck error
static void intckExec(sqlite3_intck *p, const char *zSql){
sqlite3_stmt *pStmt = 0;
pStmt = intckPrepare(p, zSql);
- while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) );
+ intckStep(p, pStmt);
intckFinalize(p, pStmt);
}
-/*
-** Wrapper around sqlite3_malloc64() that uses the sqlite3_intck error
-** code convention.
-*/
-static void *intckMalloc(sqlite3_intck *p, sqlite3_int64 nByte){
- void *pRet = 0;
- assert( nByte>0 );
- if( p->rc==SQLITE_OK ){
- pRet = sqlite3_malloc64(nByte);
- if( pRet==0 ){
- p->rc = SQLITE_NOMEM;
- }
- }
- return pRet;
-}
-
-/*
-** Like strdup(), but uses the sqlite3_intck error code convention. Any
-** returned buffer should eventually be freed using sqlite3_free().
-*/
-static char *intckStrdup(sqlite3_intck *p, const char *zIn){
- char *zOut = 0;
- if( zIn ){
- int nIn = strlen(zIn);
- zOut = (char*)intckMalloc(p, nIn+1);
- if( zOut ){
- memcpy(zOut, zIn, nIn+1);
- }
- }
- return zOut;
-}
-
/*
** A wrapper around sqlite3_mprintf() that uses the sqlite3_intck error
** code convention.
sqlite3_bind_value(pStmt, ii+1, sqlite3_column_value(p->pCheck, ii+1));
}
if( SQLITE_ROW==sqlite3_step(pStmt) ){
- p->zKey = intckStrdup(p, (const char*)sqlite3_column_text(pStmt, 0));
+ p->zKey = intckMprintf(p,"%s",(const char*)sqlite3_column_text(pStmt, 0));
}
intckFinalize(p, pStmt);
}
if( p->rc==SQLITE_OK ){
sqlite3_bind_text(pStmt, 1, zPrev, -1, SQLITE_TRANSIENT);
if( sqlite3_step(pStmt)==SQLITE_ROW ){
- p->zObj = intckStrdup(p, (const char*)sqlite3_column_text(pStmt, 0));
+ p->zObj = intckMprintf(p,"%s",(const char*)sqlite3_column_text(pStmt, 0));
}
}
intckFinalize(p, pStmt);
while( 1 ){
if( z[iRet]==c ){
iRet++;
- if( z[iRet+1]!=c ) break;
+ if( z[iRet]!=c ) break;
}
iRet++;
}
int bRet = 0;
sqlite3_stmt *pStmt = 0;
pStmt = intckPrepare(p, "PRAGMA automatic_index");
- if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
+ if( SQLITE_ROW==intckStep(p, pStmt) ){
bRet = sqlite3_column_int(pStmt, 0);
}
intckFinalize(p, pStmt);
}
while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
- zRet = intckStrdup(p, (const char*)sqlite3_column_text(pStmt, 0));
+ zRet = intckMprintf(p, "%s", (const char*)sqlite3_column_text(pStmt, 0));
if( pnKeyVal ){
*pnKeyVal = sqlite3_column_int(pStmt, 1);
}
*/
void sqlite3_intck_close(sqlite3_intck *p){
if( p ){
- if( p->db ){
- sqlite3_create_function(
- p->db, "parse_create_index", 1, SQLITE_UTF8, 0, 0, 0, 0
- );
- }
+ sqlite3_finalize(p->pCheck);
+ sqlite3_create_function(
+ p->db, "parse_create_index", 1, SQLITE_UTF8, 0, 0, 0, 0
+ );
sqlite3_free(p->zObj);
sqlite3_free(p->zKey);
sqlite3_free(p->zTestSql);
sqlite3_free(p->zErr);
+ sqlite3_free(p->zMessage);
sqlite3_free(p);
}
}
}
}else if( p->rc==SQLITE_CORRUPT ){
p->rc = SQLITE_OK;
- p->zMessage = intckStrdup(p,
+ p->zMessage = intckMprintf(p, "%s",
"corruption found while reading database schema"
);
p->bCorruptSchema = 1;
** on the database.
*/
int sqlite3_intck_unlock(sqlite3_intck *p){
- if( p->pCheck && p->rc==SQLITE_OK ){
+ if( p->rc==SQLITE_OK && p->pCheck ){
assert( p->zKey==0 && p->nKeyVal>0 );
intckSaveKey(p);
intckFinalize(p, p->pCheck);
case 3: assert( 0==strcmp("error", aCmd[iIdx].zName) ); {
const char *zErr = 0;
- int rc = sqlite3_intck_error(p->intck, &zErr);
+ int rc = sqlite3_intck_error(p->intck, 0);
Tcl_Obj *pRes = Tcl_NewObj();
-
Tcl_ListObjAppendElement(
interp, pRes, Tcl_NewStringObj(sqlite3ErrName(rc), -1)
);
+ sqlite3_intck_error(p->intck, &zErr);
Tcl_ListObjAppendElement(
interp, pRes, Tcl_NewStringObj(zErr ? zErr : 0, -1)
);
return TCL_ERROR;
}
zDb = Tcl_GetString(objv[2]);
+ if( zDb[0]=='\0' ) zDb = 0;
rc = sqlite3_intck_open(db, zDb, &p->intck);
if( rc!=SQLITE_OK ){
}
do {
- sprintf(zName, "intck%d", iName);
+ sprintf(zName, "intck%d", iName++);
}while( Tcl_GetCommandInfo(interp, zName, &info)!=0 );
Tcl_CreateObjCommand(interp, zName, testIntckCmd, (void*)p, testIntckFree);
Tcl_SetObjResult(interp, Tcl_NewStringObj(zName, -1));
}
Tcl_DecrRefCount(pRet);
sqlite3_intck_close(pCk);
+ sqlite3_intck_close(0);
return rc ? TCL_ERROR : TCL_OK;
}
-C Add\stests\sfor\sthe\snew\scode\son\sthis\sbranch.
-D 2024-02-23T20:51:06.837
+C Add\sfurther\stests\sfor\sthe\sintck\smodule.
+D 2024-02-24T16:26:15.674
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f400fc9
F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
-F ext/intck/intck1.test e73c4f87b54176291b9a01b52dbc9dd88f42f3ec8aea48c8e0bd7f87a1440a40
+F ext/intck/intck1.test 866f0937911bf3a10491af6ce319b75bcd587c39dc8decf2444746b946aa4f3e
F ext/intck/intck2.test 97daaf43b8a3c870ba7c2fd421dc1887053f5b30188896fa64677ce8174c206f
F ext/intck/intck_common.tcl 9e51458126576783f11051ac0fd25bea3f6b17f570a55884223737f3200b214b
+F ext/intck/intckbusy.test 0732fe3efbb9e0a53ffdcc240073f6ff2777ea82c3e08812b16494f650763fe1
F ext/intck/intckcorrupt.test 3211ef68ac53e83951b6c8f6a8d2396506d123fe5898f97f848a25837744ec56
F ext/intck/intckfault.test ba0213c9c8dce08d519d5251268a3bab076a184b4d07acdea23b65e89c9ae03c
-F ext/intck/sqlite3intck.c 642f57a4604580513547df9d8489cdb49b8f5f3af1981c7ffb87bc37e5ce1439
+F ext/intck/sqlite3intck.c 52381a627637504a49e93400814b36e99afa0b972a9a24ef1732b8268bb27fa8
F ext/intck/sqlite3intck.h 2b40c38e7063ab822c974c0bd4aed97dabb579ccfe2e180a4639bb3bbef0f1c9
-F ext/intck/test_intck.c dec07fc82e2626a1450e58be474e351643627b04ee08ce8fae6495a533b87e85
+F ext/intck/test_intck.c d63f1707432802f5db125ee40b794923af77d4686869bd8d3a7eb43332344267
F ext/jni/GNUmakefile 59eb05f2a363bdfac8d15d66bed624bfe1ff289229184f3861b95f98a19cf4b2
F ext/jni/README.md d899789a9082a07b99bf30b1bbb6204ae57c060efcaa634536fa669323918f42
F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P cfd051836b72f7d4e38cc9614f6ae5c003de4ce377359fd391adf06fe1ddf6b9
-R aa9167c841a6524a2987fc0088c3a9be
+P 351d46b2373f08bc8033d0902d9f67cd6c8bcc16c0d9f787e4fb279c0a76da87
+R 38b420c887519ac9a48b5a886e5c9758
U dan
-Z 2a1b98d11090580141aae0cbd3e3021e
+Z 449a9c9353165606d5987b5f74af35a1
# Remove this line to create a well-formed Fossil manifest.
-351d46b2373f08bc8033d0902d9f67cd6c8bcc16c0d9f787e4fb279c0a76da87
\ No newline at end of file
+c253e276b29de28a18270d01b60d95157ce3fc4b37e246d991f9119d26e718d7
\ No newline at end of file