From a21f78b93fab3fa00b594fcab91c1b8e599547f0 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 19 Apr 2015 18:32:43 +0000 Subject: [PATCH] Bring comments on the INSERT code generator up-to-date. Fix the INSERT code generator so that it correctly handles inserts from a SELECT into a virtual table with non-terminal hidden columns. FossilOrigin-Name: 4ac81fac6c6302c042be3df493a41630b733fff0 --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/insert.c | 33 +++++++++++++++++++-------------- src/sqliteInt.h | 7 +++++++ src/vtab.c | 9 ++++++++- test/vtabA.test | 23 +++++++++++++++++------ 6 files changed, 61 insertions(+), 31 deletions(-) diff --git a/manifest b/manifest index f1a2f3bac8..3f642604b2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\ssqlite3_trace()\scallback\sdoes\snot\stry\sto\sexpand\sparameters\sin\sstatements\nthat\shave\sno\sparameter. -D 2015-04-18T19:20:14.612 +C Bring\scomments\son\sthe\sINSERT\scode\sgenerator\sup-to-date.\s\sFix\sthe\sINSERT\scode\ngenerator\sso\sthat\sit\scorrectly\shandles\sinserts\sfrom\sa\sSELECT\sinto\sa\svirtual\ntable\swith\snon-terminal\shidden\scolumns. +D 2015-04-19T18:32:43.531 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in faaf75b89840659d74501bea269c7e33414761c1 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -190,7 +190,7 @@ F src/global.c 4f77cadbc5427d00139ba43d0f3979804cbb700e F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 305dd3f9539d0affa4bf1c14cc7dffb34867e040 +F src/insert.c 9f5f25a9d645089973d2f451711b7402bfde6ab5 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770 @@ -235,7 +235,7 @@ F src/shell.c 28b3e1174a7fc00155d7d00880a33589a88508c9 F src/sqlite.h.in ca27603a36fcacdaac5a19d8ee35aaff8ce8516f F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d -F src/sqliteInt.h af228df2a02bf1a608d678b312d46aa480470b3c +F src/sqliteInt.h 3a1fccc2bb62ab16750730b6f6f24305e686a0ce F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179 F src/table.c e7a09215315a978057fb42c640f890160dbcc45e @@ -302,7 +302,7 @@ F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90 F src/vdbemem.c c0dc81285b7571b0a31c40f17846fe2397ec1cd9 F src/vdbesort.c 2e7f683464fd5db3be4beaa1ff2d39e24fcb64b8 F src/vdbetrace.c f95c2dff9041fcf07f871789c22ebb0648ea0b7c -F src/vtab.c be741af2a377bd894104d62504796e7394a04916 +F src/vtab.c 4feb365e2688dd02474e671e37f27e35784d2cff F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb F src/wal.c 753995db83247f20361a8e8a874990b21a75abd9 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 @@ -1122,7 +1122,7 @@ F test/vtab6.test 5f5380c425e52993560ab4763db4f826d2ba7b09 F test/vtab7.test ae560ebea870ed04e9aa4177cc302f910faaabb5 F test/vtab8.test e19fa4a538fcd1bb66c22825fa8f71618fb13583 F test/vtab9.test ea58d2b95d61955f87226381716b2d0b1d4e4f9b -F test/vtabA.test c86e1990b7e1e2bb34602a06fffa4c69f2b516dc +F test/vtabA.test 1317f06a03597eee29f40a49b6c21e1aaba4285f F test/vtabB.test 04df5dc531b9f44d9ca65b9c1b79f12b5922a796 F test/vtabC.test 4528f459a13136f982e75614d120aef165f17292 F test/vtabD.test 05b3f1d77117271671089e48719524b676842e96 @@ -1251,7 +1251,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 2eed41fda068f2cbac55e63d7c1875ddaa331508 -R fe8a360bbce7dedd87d096d07c896e4c +P 917e3c36293a1bf052a16116c93e5037ed712f96 +R b611a70a7a5e6fee6ae7534de091ac22 U drh -Z 768a04b82f6060145bfe8edb7197ea08 +Z cc4a9846aabfd76674510baafeb05d26 diff --git a/manifest.uuid b/manifest.uuid index 98458ab03b..c59b152783 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -917e3c36293a1bf052a16116c93e5037ed712f96 \ No newline at end of file +4ac81fac6c6302c042be3df493a41630b733fff0 \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index fc8895bbd6..73c550b832 100644 --- a/src/insert.c +++ b/src/insert.c @@ -342,20 +342,23 @@ static int xferOptimization( /* ** This routine is called to handle SQL of the following forms: ** -** insert into TABLE (IDLIST) values(EXPRLIST) +** insert into TABLE (IDLIST) values(EXPRLIST),(EXPRLIST),... ** insert into TABLE (IDLIST) select +** insert into TABLE (IDLIST) default values ** ** The IDLIST following the table name is always optional. If omitted, -** then a list of all columns for the table is substituted. The IDLIST -** appears in the pColumn parameter. pColumn is NULL if IDLIST is omitted. +** then a list of all (non-hidden) columns for the table is substituted. +** The IDLIST appears in the pColumn parameter. pColumn is NULL if IDLIST +** is omitted. ** -** The pList parameter holds EXPRLIST in the first form of the INSERT -** statement above, and pSelect is NULL. For the second form, pList is -** NULL and pSelect is a pointer to the select statement used to generate -** data for the insert. +** For the pSelect parameter holds the values to be inserted for the +** first two forms shown above. A VALUES clause is really just short-hand +** for a SELECT statement that omits the FROM clause and everything else +** that follows. If the pSelect parameter is NULL, that means that the +** DEFAULT VALUES form of the INSERT statement is intended. ** ** The code generated follows one of four templates. For a simple -** insert with data coming from a VALUES clause, the code executes +** insert with data coming from a single-row VALUES clause, the code executes ** once straight down through. Pseudo-code follows (we call this ** the "1st template"): ** @@ -462,7 +465,7 @@ void sqlite3Insert( u8 useTempTable = 0; /* Store SELECT results in intermediate table */ u8 appendFlag = 0; /* True if the insert is likely to be an append */ u8 withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */ - u8 bIdListInOrder = 1; /* True if IDLIST is in table order */ + u8 bIdListInOrder; /* True if IDLIST is in table order */ ExprList *pList = 0; /* List of VALUES() to be inserted */ /* Register allocations */ @@ -487,8 +490,8 @@ void sqlite3Insert( } /* If the Select object is really just a simple VALUES() list with a - ** single row values (the common case) then keep that one row of values - ** and go ahead and discard the Select object + ** single row (the common case) then keep that one row of values + ** and discard the other (unused) parts of the pSelect object */ if( pSelect && (pSelect->selFlags & SF_Values)!=0 && pSelect->pPrior==0 ){ pList = pSelect->pEList; @@ -596,6 +599,7 @@ void sqlite3Insert( ** is appears in the original table. (The index of the INTEGER ** PRIMARY KEY in the original table is pTab->iPKey.) */ + bIdListInOrder = (pTab->tabFlags & TF_OOOHidden)==0; if( pColumn ){ for(i=0; inId; i++){ pColumn->a[i].idx = -1; @@ -631,7 +635,8 @@ void sqlite3Insert( ** co-routine is the common header to the 3rd and 4th templates. */ if( pSelect ){ - /* Data is coming from a SELECT. Generate a co-routine to run the SELECT */ + /* Data is coming from a SELECT or from a multi-row VALUES clause. + ** Generate a co-routine to run the SELECT. */ int regYield; /* Register holding co-routine entry-point */ int addrTop; /* Top of the co-routine */ int rc; /* Result code */ @@ -693,8 +698,8 @@ void sqlite3Insert( sqlite3ReleaseTempReg(pParse, regTempRowid); } }else{ - /* This is the case if the data for the INSERT is coming from a VALUES - ** clause + /* This is the case if the data for the INSERT is coming from a + ** single-row VALUES clause */ NameContext sNC; memset(&sNC, 0, sizeof(sNC)); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index b1a2db3a28..deab70fc48 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1622,6 +1622,12 @@ struct Table { /* ** Allowed values for Table.tabFlags. +** +** TF_OOOHidden applies to virtual tables that have hidden columns that are +** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING +** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden, +** the TF_OOOHidden attribute would apply in this case. Such tables require +** special handling during INSERT processing. */ #define TF_Readonly 0x01 /* Read-only system table */ #define TF_Ephemeral 0x02 /* An ephemeral table */ @@ -1629,6 +1635,7 @@ struct Table { #define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */ #define TF_Virtual 0x10 /* Is a virtual table */ #define TF_WithoutRowid 0x20 /* No rowid used. PRIMARY KEY is the key */ +#define TF_OOOHidden 0x40 /* Out-of-Order hidden columns */ /* diff --git a/src/vtab.c b/src/vtab.c index 530c3f305e..ad65cdf7f4 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -559,6 +559,7 @@ static int vtabCallConstructor( rc = SQLITE_ERROR; }else{ int iCol; + u8 oooHidden = 0; /* If everything went according to plan, link the new VTable structure ** into the linked list headed by pTab->pVTable. Then loop through the ** columns of the table to see if any of them contain the token "hidden". @@ -571,7 +572,10 @@ static int vtabCallConstructor( char *zType = pTab->aCol[iCol].zType; int nType; int i = 0; - if( !zType ) continue; + if( !zType ){ + pTab->tabFlags |= oooHidden; + continue; + } nType = sqlite3Strlen30(zType); if( sqlite3StrNICmp("hidden", zType, 6)||(zType[6] && zType[6]!=' ') ){ for(i=0; iaCol[iCol].colFlags |= COLFLAG_HIDDEN; + oooHidden = TF_OOOHidden; + }else{ + pTab->tabFlags |= oooHidden; } } } diff --git a/test/vtabA.test b/test/vtabA.test index 928cc2b703..eddaa70d1f 100644 --- a/test/vtabA.test +++ b/test/vtabA.test @@ -74,28 +74,39 @@ do_test vtabA-1.6 { SELECT * FROM t1e; } } {{value a} {value c}} +do_execsql_test vtabA-1.7 { + DELETE FROM t1e; + INSERT INTO t1e SELECT 'abc','def'; +} {} +do_execsql_test vtabA-1.8 { + INSERT INTO t1e VALUES('ghi','jkl'),('mno','pqr'),('stu','vwx'); +} {} +do_execsql_test vtabA-1.9 { + SELECT a,b,c, '|' FROM t1e ORDER BY 1; +} {abc {} def | ghi {} jkl | mno {} pqr | stu {} vwx |} + # Test that the expansion of a '*' expression in the result set of # a SELECT does not include the hidden column. # -do_test vtabA-1.7 { +do_test vtabA-1.20 { execsql { INSERT INTO t1e SELECT * FROM t1e; } } {} -do_test vtabA-1.8 { +do_test vtabA-1.21 { execsql { - SELECT * FROM t1e; + SELECT * FROM t1e ORDER BY 1; } -} {{value a} {value c} {value a} {value c}} +} {abc def abc def ghi jkl ghi jkl mno pqr mno pqr stu vwx stu vwx} # Test that the declaration type of the hidden column does not include # the token "HIDDEN". # -do_test vtabA-1.9 { +do_test vtabA-1.22 { get_decltype t1e b } {VARCHAR} -do_test vtabA-1.10 { +do_test vtabA-1.23 { get_collist t1e } {a c} -- 2.47.2