From 176f4d23c1ce6e298a516fdbdf883fed627edfc6 Mon Sep 17 00:00:00 2001 From: danielk1977 Date: Thu, 15 Jun 2006 10:41:15 +0000 Subject: [PATCH] Add tests (and modify test code) for writing to virtual tables. (CVS 3253) FossilOrigin-Name: 6380a9b118cf972c3c7d4886ecdb62c44f2208ca --- manifest | 14 ++-- manifest.uuid | 2 +- src/test8.c | 195 ++++++++++++++++++++++-------------------------- test/vtab1.test | 56 +++++++++++++- 4 files changed, 151 insertions(+), 116 deletions(-) diff --git a/manifest b/manifest index df09f47782..9143d629e8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Simple\stests\sand\sfixes\sfor\swriting\sto\svirtual\stables.\s(CVS\s3252) -D 2006-06-15T07:29:01 +C Add\stests\s(and\smodify\stest\scode)\sfor\swriting\sto\svirtual\stables.\s(CVS\s3253) +D 2006-06-15T10:41:16 F Makefile.in 200f6dc376ecfd9b01e5359c4e0c10c02f649b34 F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -84,7 +84,7 @@ F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25 F src/test5.c 7162f8526affb771c4ed256826eee7bb9eca265f F src/test6.c 60a02961ceb7b3edc25f5dc5c1ac2556622a76de F src/test7.c 03fa8d787f6aebc6d1f72504d52f33013ad2c8e3 -F src/test8.c e88baeff5530fbf0d028a48fbffab71440a5b953 +F src/test8.c f3082601d4eae6284b33a36fcfe00c8d8d17ee47 F src/test_async.c e3deaedd4d86a56391b81808fde9e44fbd92f1d3 F src/test_loadext.c 22065d601a18878e5542191001f0eaa5d77c0ed8 F src/test_md5.c 6c42bc0a3c0b54be34623ff77a0eec32b2fa96e3 @@ -290,7 +290,7 @@ F test/vacuum.test 37f998b841cb335397c26d9bbc3457182af2565f F test/vacuum2.test 5aea8c88a65cb29f7d175296e7c819c6158d838c F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102 F test/view.test 16e2774fe35e47a07ac4471b7f0bcc948b1aa6d5 -F test/vtab1.test 89937da89d774b9174b93a327330e4ea3fb0f03a +F test/vtab1.test 519f360d15b8009845e7957789801807346286ff F test/where.test ee7c9a6659b07e1ee61177f6e7ff71565ee2c9df F test/where2.test a16476a5913e75cf65b38f2daa6157a6b7791394 F test/where3.test 3b5ad2c58069e12be2bd86bc5e211a82810521aa @@ -366,7 +366,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P 470a3a0b20775be1226fb4d477c798d8da2d5708 -R 2a51dd29d0ce74e2c7cf789f7bd17241 +P 88fa510e4c684513bbb59031d034fdb5c51a6a15 +R 9f300784595c0ed5be31e8d13114f756 U danielk1977 -Z 0d507f27fec3f378ea4bc0c20801973d +Z 6d8c84f1329cd866e4eca1550fa6f4bb diff --git a/manifest.uuid b/manifest.uuid index 8a20fa80a2..0f1589e240 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -88fa510e4c684513bbb59031d034fdb5c51a6a15 \ No newline at end of file +6380a9b118cf972c3c7d4886ecdb62c44f2208ca \ No newline at end of file diff --git a/src/test8.c b/src/test8.c index 5a8eaeee2f..f3d788a3b0 100644 --- a/src/test8.c +++ b/src/test8.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test8.c,v 1.21 2006/06/15 07:29:01 danielk1977 Exp $ +** $Id: test8.c,v 1.22 2006/06/15 10:41:16 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -428,6 +428,9 @@ static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ if( pVtab->aIndex[iCol] ){ char *zCol = pVtab->aCol[iCol]; char *zOp = 0; + if( iCol<0 ){ + zCol = "rowid"; + } switch( pConstraint->op ){ case SQLITE_INDEX_CONSTRAINT_EQ: zOp = "="; break; @@ -479,139 +482,121 @@ static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ return SQLITE_OK; } +static void string_concat(char **pzStr, char *zAppend, int doFree){ + char *zIn = *pzStr; + if( zIn ){ + char *zTemp = zIn; + zIn = sqlite3_mprintf("%s%s", zIn, zAppend); + sqlite3_free(zTemp); + }else{ + zIn = sqlite3_mprintf("%s", zAppend); + } + *pzStr = zIn; + if( doFree ){ + sqlite3_free(zAppend); + } +} + +/* +** apData[0] apData[1] apData[2..] +** +** INTEGER DELETE +** +** INTEGER NULL (nCol args) UPDATE (do not set rowid) +** INTEGER INTEGER (nCol args) UPDATE (with SET rowid = ) +** +** NULL NULL (nCol args) INSERT INTO (automatic rowid value) +** NULL INTEGER (nCol args) INSERT (incl. rowid value) +** +*/ int echoUpdate(sqlite3_vtab *tab, int nData, sqlite3_value **apData){ echo_vtab *pVtab = (echo_vtab *)tab; sqlite3 *db = pVtab->db; int rc = SQLITE_OK; + sqlite3_stmt *pStmt; + char *z = 0; /* SQL statement to execute */ + int bindArgZero = 0; /* True to bind apData[0] to sql var no. nData */ + int bindArgOne = 0; /* True to bind apData[1] to sql var no. 1 */ + int i; /* Counter variable used by for loops */ + assert( nData==pVtab->nCol+2 || nData==1 ); /* If apData[0] is an integer and nData>1 then do an UPDATE */ if( nData>1 && sqlite3_value_type(apData[0])==SQLITE_INTEGER ){ - char *zUpdate = sqlite3_mprintf("UPDATE %Q", pVtab->zTableName); + z = sqlite3_mprintf("UPDATE %Q", pVtab->zTableName); char *zSep = " SET"; - char *zTemp; - int i, j; - sqlite3_stmt *pStmt; - - if( apData[1] && sqlite3_value_type(apData[1]) && - sqlite3_value_int64(apData[0])!=sqlite3_value_int64(apData[1]) ){ - zTemp = sqlite3_mprintf("%s SET rowid=%lld", zUpdate, zSep, - sqlite3_value_int64(apData[1])); - sqlite3_free(zUpdate); - zUpdate = zTemp; + + bindArgOne = (apData[1] && sqlite3_value_type(apData[1])==SQLITE_INTEGER); + bindArgZero = 1; + + if( bindArgOne ){ + string_concat(&z, " SET rowid=?1 ", 0); zSep = ","; } for(i=2; iaCol[i-2]); - sqlite3_free(zUpdate); - zUpdate = zTemp; + string_concat(&z, sqlite3_mprintf( + "%s %Q=?%d", zSep, pVtab->aCol[i-2], i), 1); zSep = ","; } - zTemp = sqlite3_mprintf("%s WHERE rowid=%lld", zUpdate, - sqlite3_value_int64(apData[0])); - sqlite3_free(zUpdate); - zUpdate = zTemp; - rc = sqlite3_prepare(db, zUpdate, -1, &pStmt, 0); - assert( rc!=SQLITE_OK || pStmt ); - if( rc ) return rc; - for(i=2, j=1; izTableName); - if( !zDelete ){ - rc = SQLITE_NOMEM; - }else{ - sqlite3_stmt *pStmt = 0; - rc = sqlite3_prepare(db, zDelete, -1, &pStmt, 0); - assert( rc!=SQLITE_OK || pStmt ); - if( rc==SQLITE_OK ){ - sqlite3_bind_value(pStmt, 1, apData[0]); - sqlite3_step(pStmt); - rc = sqlite3_finalize(pStmt); - } - } + /* If apData[0] is an integer and nData==1 then do a DELETE */ + else if( nData==1 && sqlite3_value_type(apData[0])==SQLITE_INTEGER ){ + z = sqlite3_mprintf("DELETE FROM %Q WHERE rowid = ?1", pVtab->zTableName); + bindArgZero = 1; } - /* If there is more than a single argument, INSERT a new row */ - if( rc==SQLITE_OK && nData>1 ){ + /* If the first argument is NULL and there are more than two args, INSERT */ + else if( nData>2 && sqlite3_value_type(apData[0])==SQLITE_NULL ){ int ii; char *zInsert = 0; char *zValues = 0; - char *zQuery = 0; - const char *zTab = pVtab->zTableName; - zInsert = sqlite3_mprintf("INSERT OR REPLACE INTO %Q (rowid", zTab); - zValues = sqlite3_mprintf("?"); - - for(ii=0; iinCol && zInsert && zValues; ii++){ - char *zNew = sqlite3_mprintf("%s, %Q", zInsert, pVtab->aCol[ii]); - sqlite3_free(zInsert); - zInsert = zNew; - - zNew = sqlite3_mprintf("%s, ?", zValues); - sqlite3_free(zValues); - zValues = zNew; + zInsert = sqlite3_mprintf("INSERT OR REPLACE INTO %Q (", pVtab->zTableName); + if( sqlite3_value_type(apData[1])==SQLITE_INTEGER ){ + bindArgOne = 1; + zValues = sqlite3_mprintf("?"); + string_concat(&zInsert, "rowid", 0); } - if( zInsert && zValues ){ - zQuery = sqlite3_mprintf("%s) VALUES(%s)", zInsert, zValues); - } - if( zQuery ){ - sqlite3_stmt *pStmt = 0; - rc = sqlite3_prepare(db, zQuery, -1, &pStmt, 0); - for(ii=1; rc==SQLITE_OK && iinCol+2)==nData); + for(ii=2; iiaCol[ii-2]), 1); + string_concat(&zValues, + sqlite3_mprintf("%s?%d", zValues?", ":"", ii), 1); } - sqlite3_free(zValues); - sqlite3_free(zInsert); - sqlite3_free(zQuery); - if( rc==SQLITE_OK && (!zValues || !zInsert || !zQuery) ){ - sqlite3FailedMalloc(); - rc = SQLITE_NOMEM; + string_concat(&z, zInsert, 1); + string_concat(&z, ") VALUES(", 0); + string_concat(&z, zValues, 1); + string_concat(&z, ")", 0); + } + + /* Anything else is an error */ + else{ + assert(0); + return SQLITE_ERROR; + } + + rc = sqlite3_prepare(db, z, -1, &pStmt, 0); + assert( rc!=SQLITE_OK || pStmt ); + sqlite3_free(z); + if( rc==SQLITE_OK ) { + if( bindArgZero ){ + sqlite3_bind_value(pStmt, nData, apData[0]); } + if( bindArgOne ){ + sqlite3_bind_value(pStmt, 1, apData[1]); + } + for(i=2; i