From: drh Date: Fri, 5 Nov 2004 17:17:50 +0000 (+0000) Subject: Create table now works with sqlite3NestedParse. This changed uncovered X-Git-Tag: version-3.6.10~4081 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4794f73524086ae8d7a0c2a43dfa9f0797f639d9;p=thirdparty%2Fsqlite.git Create table now works with sqlite3NestedParse. This changed uncovered a latent bug in xprintf which is also fixed. (CVS 2069) FossilOrigin-Name: b0506bdd701339d63166ada065445776dd499588 --- diff --git a/manifest b/manifest index b0963e30c5..67f06c3615 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\struncate\sa\sdatabase\sfile\suntil\safter\sfsync()\shas\sbeen\scalled\son\sthe\sjournal.\s(CVS\s2068) -D 2004-11-05T16:37:03 +C Create\stable\snow\sworks\swith\ssqlite3NestedParse.\s\sThis\schanged\suncovered\na\slatent\sbug\sin\sxprintf\swhich\sis\salso\sfixed.\s(CVS\s2069) +D 2004-11-05T17:17:50 F Makefile.in c4d2416860f472a1e3393714d0372074197565df F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1 @@ -31,14 +31,14 @@ F src/attach.c e49d09dad9f5f9fb10b4b0c1be5a70ae4c45e689 F src/auth.c 3b81f2a42f48a62c2c9c9b0eda31a157c681edea F src/btree.c bf0d3d59ec076f0a37378f8ac6090d157d925c24 F src/btree.h 861e40b759a195ba63819740e484390012cf81ab -F src/build.c dc8b9ab836f2323d9b313c2d703b00b2e9441382 +F src/build.c f204aebf587f4543102dc6ea7c9283cb5949d7f0 F src/date.c 34bdb0082db7ec2a83ef00063f7b44e61ee19dad -F src/delete.c 6a54fd9f0fa6b93e13e40368a8b7206e3aae760c +F src/delete.c f0af21a1ede15524a5edd59fe10ef486283a1ee9 F src/expr.c be18081d2959a2cc53846d0fbedfec40fbfa1d6e F src/func.c 600e506bccf7648df8ad03efb417560d0f7ad4c1 F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84 -F src/insert.c b6ad8e90153ffb0c03bb7a0e04b14f8ddf096d92 +F src/insert.c 3fd6e00c9f62ad14daa94c75ae9971c32119f97e F src/legacy.c d58ea507bce885298a2c8c3cbb0f4bff5d47830b F src/main.c ba1b26f03af4b7f8be3394748123dd671b9ea147 F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070 @@ -56,12 +56,12 @@ F src/pager.c 868c67e4ff8a1785c06caaf483fddb5a95013af0 F src/pager.h 9eba8c53dd91eae7f3f90743b2ee242da02a9862 F src/parse.y 97247c0a89ca1667729db5035f1ee60140960984 F src/pragma.c 6a0ae7721e614c5a921e918ab5206d5e654f1a6f -F src/printf.c 7a92adc00b758cd5ce087dae80181a8bbdb70ed2 +F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 F src/select.c 156990c636102bb6b8de85e7ff3396a62568476b F src/shell.c 55adda3cf3c1cc2f6c1919aac17b2318f9c2a96f F src/sqlite.h.in 4f97b5907acfd2a5068cb0cec9d5178816734db7 -F src/sqliteInt.h 14b36d195ad418fc3d390e36a59ec0e3d0a1bdc7 +F src/sqliteInt.h 5d26b41b2ab7eeab1bd9db330ed7b7929d2ae875 F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9 F src/tclsqlite.c 0302e3f42f015d132d1291f3388c06e86c24a008 F src/test1.c df1d1ca2c40cafefb9a29860f072c4d0fee1a7b5 @@ -71,7 +71,7 @@ F src/test4.c 7c6b9fc33dd1f3f93c7f1ee6e5e6d016afa6c1df F src/test5.c b001fa7f1b9e2dc5c2331de62fc641b5ab2bd7a1 F src/tokenize.c c48221284e729be067237a8cfd7848fb62ee4a92 F src/trigger.c f9a0a8d3a87238de1a934eeb7d0b6b1f13e6a55b -F src/update.c 50ac56ab8109846eda843591d63527c94e862bc3 +F src/update.c 3cc67f6053495152e82a6a48c93ed331218e936e F src/utf.c f4f83acd73389090e32d6589d307fc55d794c7ed F src/util.c 005fdf2d008f3429d081766ad6098fdd86d8d8e6 F src/vacuum.c ecb4a2c6f1ac5cc9b394dc64d3bb14ca650c4f60 @@ -79,7 +79,7 @@ F src/vdbe.c b324acdaff3b1f21cd369bbb0df30e1c3fa828f4 F src/vdbe.h 067ca8d6750ba4f69a50284765e5883dee860181 F src/vdbeInt.h 6017100adff362b8dfa37a69e3f1431f084bfa5b F src/vdbeapi.c 3965bf4678ae32c05f73550c1b5be3268f9f3006 -F src/vdbeaux.c 544ff66308d3184b519decc731abb65c5233bc2d +F src/vdbeaux.c c6da55e0096e141211f918837eca98e0be6400b4 F src/vdbemem.c ef9ac7d32acfe4bce5c5b408b1294c8d9e0cdb56 F src/where.c 6e637a6b3e61fe3104adc4e5caa4738bf6570daa F test/all.test 929bfa932b55e75c96fe2203f7650ba451c1862c @@ -252,7 +252,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/whentouse.tcl fdacb0ba2d39831e8a6240d05a490026ad4c4e4c -P b9d5f007fc32d4f471e0e11cc4baadb100612878 -R 18a567bb56395dc74db3aa4daaced6ab -U danielk1977 -Z 17328cbcaecb7be2165f3f20c069642c +P cfee7f4a004c5e57d58edcf9de3ded0a199940a3 +R ec15467724d6da43213b204975fda018 +U drh +Z 4e4b37ba057c6cd50535fae2a97094d4 diff --git a/manifest.uuid b/manifest.uuid index 0978fc9774..f3fad82afe 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cfee7f4a004c5e57d58edcf9de3ded0a199940a3 \ No newline at end of file +b0506bdd701339d63166ada065445776dd499588 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 1a30b0101c..5d9f9c0e86 100644 --- a/src/build.c +++ b/src/build.c @@ -24,9 +24,9 @@ ** PRAGMA ** <<<<<<< build.c -** $Id: build.c,v 1.267 2004/11/05 09:19:28 danielk1977 Exp $ +** $Id: build.c,v 1.268 2004/11/05 17:17:50 drh Exp $ ======= -** $Id: build.c,v 1.267 2004/11/05 09:19:28 danielk1977 Exp $ +** $Id: build.c,v 1.268 2004/11/05 17:17:50 drh Exp $ >>>>>>> 1.262 */ #include "sqliteInt.h" @@ -719,6 +719,17 @@ void sqlite3StartTable( if( pParse->pNewTable ) sqlite3DeleteTable(db, pParse->pNewTable); pParse->pNewTable = pTable; + /* If this is the magic sqlite_sequence table used by autoincrement, + ** then record a pointer to this table in the main database structure + ** so that INSERT can find the table easily. + */ +#ifndef SQLITE_OMIT_AUTOINCREMENT + if( strcmp(zName, "sqlite_sequence")==0 ){ + assert( db->aDb[iDb].pSeqTab==0 ); + db->aDb[iDb].pSeqTab = pTable; + } +#endif + /* Begin generating the code that will insert the table record into ** the SQLITE_MASTER table. Note in particular that we must go ahead ** and allocate the record number for the table entry now. Before any @@ -738,6 +749,10 @@ void sqlite3StartTable( sqlite3VdbeAddOp(v, OP_Integer, db->enc, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 4); + /* This just creates a place-holder record in the sqlite_master table. + ** The record created does not contain anything yet. It will be replaced + ** by the real entry in code generated at sqlite3EndTable(). + */ sqlite3OpenMasterTable(v, iDb); sqlite3VdbeAddOp(v, OP_NewRecno, 0, 0); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); @@ -913,8 +928,10 @@ void sqlite3AddPrimaryKey( pTab->keyConf = onError; pTab->autoInc = autoInc; }else if( autoInc ){ +#ifndef SQLITE_OMIT_AUTOINCREMENT sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an " "INTEGER PRIMARY KEY"); +#endif }else{ sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0); pList = 0; @@ -1350,16 +1367,27 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){ if( !db->init.busy ){ int n; Vdbe *v; + char *zType; /* "view" or "table" */ + char *zType2; /* "VIEW" or "TABLE" */ + char *zStmt; /* Text of the CREATE TABLE or CREATE VIEW statement */ v = sqlite3GetVdbe(pParse); if( v==0 ) return; + /* Create the rootpage for the new table and push it onto the stack. + ** A view has no rootpage, so just push a zero onto the stack for + ** views. Initialize zType at the same time. + */ if( p->pSelect==0 ){ /* A regular table */ sqlite3VdbeAddOp(v, OP_CreateTable, p->iDb, 0); + zType = "table"; + zType2 = "TABLE"; }else{ /* A view */ sqlite3VdbeAddOp(v, OP_Integer, 0, 0); + zType = "view"; + zType2 = "VIEW"; } sqlite3VdbeAddOp(v, OP_Close, 0, 0); @@ -1391,7 +1419,8 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){ sqlite3DeleteTable(0, pSelTab); } } - + +#if 0 sqlite3OpenMasterTable(v, p->iDb); sqlite3VdbeOp3(v, OP_String8, 0, 0, p->pSelect==0?"table":"view",P3_STATIC); @@ -1421,6 +1450,36 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){ sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0); sqlite3ChangeCookie(db, v, p->iDb); sqlite3VdbeAddOp(v, OP_Close, 0, 0); +#endif + + /* Compute the complete text of the CREATE statement */ + if( pSelect ){ + zStmt = createTableStmt(p); + }else{ + n = Addr(pEnd->z) - Addr(pParse->sNameToken.z) + 1; + zStmt = sqlite3MPrintf("CREATE %s %.*s", zType2, n, pParse->sNameToken.z); + } + + /* A slot for the record has already been allocated in the + ** SQLITE_MASTER table. We just need to update that slot with all + ** the information we've collected. The rowid for the preallocated + ** slot is the 2nd item on the stack. The top of the stack is the + ** root page for the new table (or a 0 if this is a view). + */ + sqlite3NestedParse(pParse, + "UPDATE %Q.%s " + "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#0, sql=%Q " + "WHERE rowid=#1", + db->aDb[p->iDb].zName, SCHEMA_TABLE(p->iDb), + zType, + p->zName, + p->zName, + zStmt + ); + sqliteFree(zStmt); + + /* Reparse everything to update our internal data structures */ + sqlite3ChangeCookie(db, v, p->iDb); sqlite3VdbeOp3(v, OP_ParseSchema, p->iDb, 0, sqlite3MPrintf("tbl_name='%q'",p->zName), P3_DYNAMIC); } @@ -1648,7 +1707,7 @@ static void destroyRootPage(Parse *pParse, int iTable, int iDb){ ** is on the top of the stack. See sqlite3RegisterExpr(). */ sqlite3NestedParse(pParse, - "UPDATE %Q.%Q SET rootpage=%d WHERE #0 AND rootpage=#0", + "UPDATE %Q.%s SET rootpage=%d WHERE #0 AND rootpage=#0", pParse->db->aDb[iDb].zName, SCHEMA_TABLE(iDb), iTable); #endif } @@ -1793,7 +1852,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){ ** database. */ sqlite3NestedParse(pParse, - "DELETE FROM %Q.%Q WHERE tbl_name=%Q and type!='trigger'", + "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'", db->aDb[pTab->iDb].zName, SCHEMA_TABLE(pTab->iDb), pTab->zName); if( !isView ){ destroyTable(pParse, pTab); diff --git a/src/delete.c b/src/delete.c index da140c58f4..0ed2a7d175 100644 --- a/src/delete.c +++ b/src/delete.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle DELETE FROM statements. ** -** $Id: delete.c,v 1.87 2004/11/05 06:02:07 danielk1977 Exp $ +** $Id: delete.c,v 1.88 2004/11/05 17:17:50 drh Exp $ */ #include "sqliteInt.h" @@ -170,7 +170,7 @@ void sqlite3DeleteFrom( if( v==0 ){ goto delete_from_cleanup; } - sqlite3VdbeCountChanges(v); + if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, row_triggers_exist, pTab->iDb); /* If we are trying to delete from a view, construct that view into @@ -295,7 +295,7 @@ void sqlite3DeleteFrom( } /* Delete the row */ - sqlite3GenerateRowDelete(db, v, pTab, iCur, 1); + sqlite3GenerateRowDelete(db, v, pTab, iCur, pParse->nested==0); } /* If there are row triggers, close all cursors then invoke diff --git a/src/insert.c b/src/insert.c index e061b590ab..887d5f1df1 100644 --- a/src/insert.c +++ b/src/insert.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.122 2004/11/05 06:02:07 danielk1977 Exp $ +** $Id: insert.c,v 1.123 2004/11/05 17:17:50 drh Exp $ */ #include "sqliteInt.h" @@ -262,7 +262,7 @@ void sqlite3Insert( */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto insert_cleanup; - sqlite3VdbeCountChanges(v); + if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, pSelect || row_triggers_exist, pTab->iDb); /* if there are row triggers, allocate a temp table for new.* references. */ @@ -999,7 +999,11 @@ void sqlite3CompleteInsertion( sqlite3VdbeAddOp(v, OP_Dup, 1, 0); sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0); } - pik_flags = (OPFLAG_NCHANGE|(isUpdate?0:OPFLAG_LASTROWID)); + if( pParse->nested ){ + pik_flags = 0; + }else{ + pik_flags = (OPFLAG_NCHANGE|(isUpdate?0:OPFLAG_LASTROWID)); + } sqlite3VdbeAddOp(v, OP_PutIntKey, base, pik_flags); if( isUpdate && recnoChng ){ diff --git a/src/printf.c b/src/printf.c index 43e1286372..6e700771b4 100644 --- a/src/printf.c +++ b/src/printf.c @@ -99,6 +99,7 @@ typedef struct et_info { /* Information about each format field */ */ #define FLAG_SIGNED 1 /* True if the value to convert is signed */ #define FLAG_INTERN 2 /* True if for internal use only */ +#define FLAG_STRING 4 /* Allow infinity precision */ /* @@ -109,10 +110,10 @@ static const char aDigits[] = "0123456789ABCDEF0123456789abcdef"; static const char aPrefix[] = "-x0\000X0"; static const et_info fmtinfo[] = { { 'd', 10, 1, etRADIX, 0, 0 }, - { 's', 0, 0, etSTRING, 0, 0 }, - { 'z', 0, 2, etDYNSTRING, 0, 0 }, - { 'q', 0, 0, etSQLESCAPE, 0, 0 }, - { 'Q', 0, 0, etSQLESCAPE2, 0, 0 }, + { 's', 0, 4, etSTRING, 0, 0 }, + { 'z', 0, 6, etDYNSTRING, 0, 0 }, + { 'q', 0, 4, etSQLESCAPE, 0, 0 }, + { 'Q', 0, 4, etSQLESCAPE2, 0, 0 }, { 'c', 0, 0, etCHARX, 0, 0 }, { 'o', 8, 0, etRADIX, 0, 2 }, { 'u', 10, 0, etRADIX, 0, 0 }, @@ -296,8 +297,6 @@ static int vxprintf( c = *++fmt; } } - /* Limit the precision to prevent overflowing buf[] during conversion */ - if( precision>etBUFSIZE-40 ) precision = etBUFSIZE-40; }else{ precision = -1; } @@ -328,6 +327,11 @@ static int vxprintf( } zExtra = 0; + /* Limit the precision to prevent overflowing buf[] during conversion */ + if( precision>etBUFSIZE-40 && (infop->flags & FLAG_STRING)==0 ){ + precision = etBUFSIZE-40; + } + /* ** At this point, variables are initialized as follows: ** @@ -563,13 +567,15 @@ static int vxprintf( case etSQLESCAPE2: { int i, j, n, c, isnull; + int needQuote; char *arg = va_arg(ap,char*); isnull = arg==0; if( isnull ) arg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)"); for(i=n=0; (c=arg[i])!=0; i++){ if( c=='\'' ) n++; } - n += i + 1 + ((!isnull && xtype==etSQLESCAPE2) ? 2 : 0); + needQuote = !isnull && xtype==etSQLESCAPE2; + n += i + 1 + needQuote*2; if( n>etBUFSIZE ){ bufpt = zExtra = sqliteMalloc( n ); if( bufpt==0 ) return -1; @@ -577,12 +583,12 @@ static int vxprintf( bufpt = buf; } j = 0; - if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\''; + if( needQuote ) bufpt[j++] = '\''; for(i=0; (c=arg[i])!=0; i++){ bufpt[j++] = c; if( c=='\'' ) bufpt[j++] = c; } - if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\''; + if( needQuote ) bufpt[j++] = '\''; bufpt[j] = 0; length = j; if( precision>=0 && precisionnested==0 ) sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, 1, pTab->iDb); /* If we are trying to update a view, construct that view into diff --git a/src/vdbeaux.c b/src/vdbeaux.c index b2fad8e39a..44c9c3f21f 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1806,6 +1806,6 @@ void sqlite3VdbeSetChanges(sqlite3 *db, int nChange){ ** Set a flag in the vdbe to update the change counter when it is finalised ** or reset. */ -void sqlite3VdbeCountChanges(Vdbe *p){ - p->changeCntOn = 1; +void sqlite3VdbeCountChanges(Vdbe *v){ + v->changeCntOn = 1; }