From: drh Date: Thu, 7 Apr 2016 21:29:04 +0000 (+0000) Subject: Carry table column types through into VIEW definitions, where possible. X-Git-Tag: version-3.12.1~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1f2e0e0a4b1711de9f41ac1c1a5a152dbf11853d;p=thirdparty%2Fsqlite.git Carry table column types through into VIEW definitions, where possible. FossilOrigin-Name: 3360ab098a374d2eea433ca2a8278ca866957326 --- diff --git a/manifest b/manifest index cc7bc0dbb3..ea9d92f045 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Prevent\sthe\sin-memory\sjournal\sread\scursor\sfrom\sentering\san\sinconsistent\sstate\nwhen\sit\sreads\sthe\slast\sfew\sbytes\sout\sof\sthe\sjournal\sfile.\s\sFix\sfor\nticket\s[7f7f8026eda38]. -D 2016-04-07T21:22:16.307 +C Carry\stable\scolumn\stypes\sthrough\sinto\sVIEW\sdefinitions,\swhere\spossible. +D 2016-04-07T21:29:04.297 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc b00bcf0ec7001857aea81ee39fae45d20f5f4e59 @@ -300,7 +300,7 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btree.c 577fb5674e2f0aa0a38246afc19e1885a0b8c9b0 F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c 39faaaeecb77eb3936d4bd5024e865e3836ca323 +F src/build.c 84fb5a66c8f38f96b5b2c600b42a649e8cf4dbde F src/callback.c 2e76147783386374bf01b227f752c81ec872d730 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 @@ -353,12 +353,12 @@ F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20 F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e -F src/select.c 7849cee0a01952a9c93cd28989daedfa57731143 +F src/select.c d9b8628acb98f1a38921888d823a6b70c7a7774b F src/shell.c 5e0ab1e708dc294330ccd8230536e1801f60822e F src/sqlite.h.in e877f141b15ef68ef28f84714e69d7234f9a071e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2 -F src/sqliteInt.h 3a68b48967a7d62fcb38572d27fd21ab4e4bcca3 +F src/sqliteInt.h c4dbe726f4ed1d14469a3cb256cff0e6ed24e0c5 F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -1285,7 +1285,7 @@ F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9 F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 -F test/view.test f6c3a39e0c819891265e1d0754e99960d81ef6c9 +F test/view.test 765802c7a66d37fabd5ac8e2f2dbe572b43eb9ab F test/vtab1.test 7c4b81abd88361ada9cbe414c459efca26be6bda F test/vtab2.test f8cd1bb9aba7143eba97812d9617880a36d247ad F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e @@ -1459,8 +1459,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ea4de04d67aea5102fc640833cd0ec494990c109 -Q +c4b9c611bdcd85f31d68aaf114ee34a9f27eba6d -R 5945c0680345e67d7d967acfb4c9368b +P c232b99e65397725076b3b11311c46f5bcf51d33 +Q +fb555c3c2af7f5e62ff839658f4fba7b645d3a68 +R ddbf6beee55570353e0e2c25f60d2091 U drh -Z e67f9905999b6698f873c3efc43111f0 +Z 02710ecf260c912f3d45e40e3709adfe diff --git a/manifest.uuid b/manifest.uuid index 8e9bce6600..26e169bc21 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c232b99e65397725076b3b11311c46f5bcf51d33 \ No newline at end of file +3360ab098a374d2eea433ca2a8278ca866957326 \ No newline at end of file diff --git a/src/build.c b/src/build.c index d4d0c173cc..eca0fc3c74 100644 --- a/src/build.c +++ b/src/build.c @@ -2176,44 +2176,55 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ ** statement that defines the view. */ assert( pTable->pSelect ); - if( pTable->pCheck ){ + pSel = sqlite3SelectDup(db, pTable->pSelect, 0); + if( pSel ){ + n = pParse->nTab; + sqlite3SrcListAssignCursors(pParse, pSel->pSrc); + pTable->nCol = -1; db->lookaside.bDisable++; - sqlite3ColumnsFromExprList(pParse, pTable->pCheck, - &pTable->nCol, &pTable->aCol); - db->lookaside.bDisable--; - }else{ - pSel = sqlite3SelectDup(db, pTable->pSelect, 0); - if( pSel ){ - n = pParse->nTab; - sqlite3SrcListAssignCursors(pParse, pSel->pSrc); - pTable->nCol = -1; - db->lookaside.bDisable++; #ifndef SQLITE_OMIT_AUTHORIZATION - xAuth = db->xAuth; - db->xAuth = 0; - pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); - db->xAuth = xAuth; + xAuth = db->xAuth; + db->xAuth = 0; + pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); + db->xAuth = xAuth; #else - pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); + pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); #endif - db->lookaside.bDisable--; - pParse->nTab = n; - if( pSelTab ){ - assert( pTable->aCol==0 ); - pTable->nCol = pSelTab->nCol; - pTable->aCol = pSelTab->aCol; - pSelTab->nCol = 0; - pSelTab->aCol = 0; - sqlite3DeleteTable(db, pSelTab); - assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) ); - }else{ - pTable->nCol = 0; - nErr++; + pParse->nTab = n; + if( pTable->pCheck ){ + /* CREATE VIEW name(arglist) AS ... + ** The names of the columns in the table are taken from + ** arglist which is stored in pTable->pCheck. The pCheck field + ** normally holds CHECK constraints on an ordinary table, but for + ** a VIEW it holds the list of column names. + */ + sqlite3ColumnsFromExprList(pParse, pTable->pCheck, + &pTable->nCol, &pTable->aCol); + if( db->mallocFailed==0 + && pParse->nErr==0 + && pTable->nCol==pSel->pEList->nExpr + ){ + sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel); } - sqlite3SelectDelete(db, pSel); - } else { + }else if( pSelTab ){ + /* CREATE VIEW name AS... without an argument list. Construct + ** the column names from the SELECT statement that defines the view. + */ + assert( pTable->aCol==0 ); + pTable->nCol = pSelTab->nCol; + pTable->aCol = pSelTab->aCol; + pSelTab->nCol = 0; + pSelTab->aCol = 0; + assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) ); + }else{ + pTable->nCol = 0; nErr++; } + if( pSelTab ) sqlite3DeleteTable(db, pSelTab); + sqlite3SelectDelete(db, pSel); + db->lookaside.bDisable--; + } else { + nErr++; } pTable->pSchema->schemaFlags |= DB_UnresetViews; #endif /* SQLITE_OMIT_VIEW */ diff --git a/src/select.c b/src/select.c index ed76f621f9..9a2d4d22cd 100644 --- a/src/select.c +++ b/src/select.c @@ -1704,7 +1704,7 @@ int sqlite3ColumnsFromExprList( ** This routine requires that all identifiers in the SELECT ** statement be resolved. */ -static void selectAddColumnTypeAndCollation( +void sqlite3SelectAddColumnTypeAndCollation( Parse *pParse, /* Parsing contexts */ Table *pTab, /* Add column type information to this table */ Select *pSelect /* SELECT used to determine types and collations */ @@ -1726,10 +1726,20 @@ static void selectAddColumnTypeAndCollation( sNC.pSrcList = pSelect->pSrc; a = pSelect->pEList->a; for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ + const char *zType; + int n, m; p = a[i].pExpr; - columnType(&sNC, p, 0, 0, 0, &pCol->szEst); + zType = columnType(&sNC, p, 0, 0, 0, &pCol->szEst); szAll += pCol->szEst; pCol->affinity = sqlite3ExprAffinity(p); + if( zType && (m = sqlite3Strlen30(zType))>0 ){ + n = sqlite3Strlen30(pCol->zName); + pCol->zName = sqlite3DbReallocOrFree(db, pCol->zName, n+m+2); + if( pCol->zName ){ + memcpy(&pCol->zName[n+1], zType, m+1); + pCol->colFlags |= COLFLAG_HASTYPE; + } + } if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_BLOB; pColl = sqlite3ExprCollSeq(pParse, p); if( pColl && pCol->zColl==0 ){ @@ -1766,7 +1776,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){ pTab->zName = 0; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); - selectAddColumnTypeAndCollation(pParse, pTab, pSelect); + sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect); pTab->iPKey = -1; if( db->mallocFailed ){ sqlite3DeleteTable(db, pTab); @@ -4550,7 +4560,7 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ Select *pSel = pFrom->pSelect; if( pSel ){ while( pSel->pPrior ) pSel = pSel->pPrior; - selectAddColumnTypeAndCollation(pParse, pTab, pSel); + sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSel); } } } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 242ae8e2cf..7300fd57d7 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3457,6 +3457,7 @@ void sqlite3CollapseDatabaseArray(sqlite3*); void sqlite3CommitInternalChanges(sqlite3*); void sqlite3DeleteColumnNames(sqlite3*,Table*); int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**); +void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*); Table *sqlite3ResultSetOfSelect(Parse*,Select*); void sqlite3OpenMasterTable(Parse *, int); Index *sqlite3PrimaryKeyIndex(Table*); diff --git a/test/view.test b/test/view.test index 235f8605ac..694b3c6abd 100644 --- a/test/view.test +++ b/test/view.test @@ -92,6 +92,26 @@ do_test view-1.8 { } } {2 3 5 6 8 9} +do_execsql_test view-1.10 { + CREATE TABLE t9(x INTEGER); + CREATE VIEW v9a AS SELECT x FROM t9; + CREATE VIEW v9b AS SELECT * FROM t9; + CREATE VIEW v9c(x) AS SELECT x FROM t9; + CREATE VIEW v9d(x) AS SELECT * FROM t9; +} {} +do_execsql_test view-1.11 { + PRAGMA table_info(v9a); +} {0 x INTEGER 0 {} 0} +do_execsql_test view-1.12 { + PRAGMA table_info(v9b); +} {0 x INTEGER 0 {} 0} +do_execsql_test view-1.13 { + PRAGMA table_info(v9c); +} {0 x INTEGER 0 {} 0} +do_execsql_test view-1.14 { + PRAGMA table_info(v9d); +} {0 x INTEGER 0 {} 0} + do_test view-2.1 { execsql { CREATE VIEW v2 AS SELECT * FROM t1 WHERE a>5