diff --git a/manifest b/manifest index e13ac335e7..35df2843b3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Slight\sreformulation\sof\ssome\stest\scode\sto\stest\smulti-arg\swasm.peek()\scall\sform. -D 2022-12-14T16:40:17.727 +C Rework\sthe\scode\sthat\scomputes\sthe\sdatatypes\sand\saffinities\sfor\ssubqueries\nand\sviews.\s\sIf\sthe\ssubquery/view\sis\sconstructed\sfrom\sa\scompound\sSELECT\swhere\nthe\saffinity\svaries\sacross\sarms\sof\sthe\scompound,\sset\sthe\saffinity\sfor\sthe\ncorresponding\scolumn\sin\sthe\sconstructed\sview\sto\sbe\sBLOB\sso\sthat\sit\sis\sallowed\nto\stake\son\sany\sdata\stype. +D 2022-12-14T17:46:35.207 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -587,7 +587,7 @@ F src/btmutex.c 6ffb0a22c19e2f9110be0964d0731d2ef1c67b5f7fabfbaeb7b9dabc4b7740ca F src/btree.c 2f794c217e52fdf4322bf37ee7778331b4d93aed2c00b5d67f914c0239a9edcc F src/btree.h 49da925329574798be3cbb745a49d069a9e67c99900d8a0d04b1e934d60394ea F src/btreeInt.h 88ad499c92b489afedbfefc3f067c4d15023ec021afe622db240dc9d2277cfa5 -F src/build.c d3e43e950e4e377c1d451a4862556792acdef1faba14a03f899d30d09731c48b +F src/build.c 51b46b657d914877dc64d0f66e2d82021b6ff622f43287cebc105efee0165600 F src/callback.c 4cd7225b26a97f7de5fee5ae10464bed5a78f2adefe19534cc2095b3a8ca484a F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 20507cc0b0a6c19cd882fcd0eaeda32ae6a4229fb4b024cfdf3183043d9b703d @@ -595,7 +595,7 @@ F src/date.c 94ce83b4cd848a387680a5f920c9018c16655db778c4d36525af0a0f34679ac5 F src/dbpage.c f1a87f4ebcf22284e0aaf0697862f4ccfc120dcd6db3d8dfa3b049b2580c01d8 F src/dbstat.c a56a7ad1163a9888d46cd5820be2e65354fb1aa04ed6909f7c3e5831e0ee2c29 F src/delete.c 86573edae75e3d3e9a8b590d87db8e47222103029df4f3e11fa56044459b514e -F src/expr.c f77ab79af36e73d79a10ee479b1fb20f31e9c8ee7e095324f5f84ec3c92b6c56 +F src/expr.c c788575fc6a101b6360bc44eb6f973b8aa25f9af984a43a43e376fbceb19cb6c F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 722f20779f5342a787922deded3628d8c74b5249cab04098cf17ee2f2aaff002 F src/func.c 7e86074afc4dc702691a29b7801f6dcc191db092b52e8bbe69dcd2f7be52194d @@ -645,12 +645,12 @@ F src/printf.c e99ee9741e79ae3873458146f59644276657340385ade4e76a5f5d1c25793764 F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/resolve.c efea4e5fbecfd6d0a9071b0be0d952620991673391b6ffaaf4c277b0bb674633 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 -F src/select.c 39c4b0e23f3f1334ca3ff9b68014de0ec2c4ae5954186765d669893a8c7fc5a9 +F src/select.c 3b72630ae4f00a96abd5be49be67457d49b35eb8c9d97e4d4f05525f320c9d72 F src/shell.c.in 8d9dc02dd03f8fc93f3e3cdb17d8d16e8ddb985dddad213985c08186900a3ebb F src/sqlite.h.in e752f82b9d71f1d42b259b1900e4b1caf0965e844d756cd5cc91cc2cf45ed925 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c4b9fa7a7e2bcdf850cfeb4b8a91d5ec47b7a00033bc996fd2ee96cbf2741f5f -F src/sqliteInt.h 0c9934acd88e0fa14f0d4743233b4cd7bd7bbc84099ba3cad50d8e69676ce2b9 +F src/sqliteInt.h 0c93dfce0ee43fa3d0391f453b956b8f222f416a16d7dc275d6f9607ee7f7bdc F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -717,7 +717,7 @@ F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c 313f3154e2b85a447326f5dd15de8d31a4df6ab0c3579bd58f426ff634ec9050 F src/vacuum.c 84ce7f01f8a7a08748e107a441db83bcec13970190ddcb0c9ff522adbc1c23fd -F src/vdbe.c df9ff3fcaa3c60fa9b0bca340c3f3cfc63a51361901ca06fe18bdeadeb2a1a24 +F src/vdbe.c 705df5b079978ea98ae18db8ffcefbdf529f7465e9c8fa19b022530556fc68e1 F src/vdbe.h 73b904a6b3bb27f308c6cc287a5751ebc7f1f89456be0ed068a12b92844c6e8c F src/vdbeInt.h 8651e4c4e04d1860d0bdcf330cb8294e3778a9d4222be30ce4c490d9220af783 F src/vdbeapi.c df3f73a4d0a487f2068e3c84776cd6e3fba5ae80ff612659dcfda4307686420b @@ -739,7 +739,7 @@ F src/whereexpr.c 05295b44b54eea76d1ba766f0908928d0e20e990c249344c9521454d3d09c7 F src/window.c 14836767adb26573b50f528eb37f8b1336f2c430ab38de7cead1e5c546bb4d8c F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627 -F test/affinity3.test b5c19d504dec222c0dc66642673d23dce915d35737b68e74d9f237b80493eb53 +F test/affinity3.test f094773025eddf31135c7ad4cde722b7696f8eb07b97511f98585addf2a510a9 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 7269d07ac879fce161cb26c8fabe65cba5715742fac8a1fccac570dcdaf28f00 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87 @@ -863,7 +863,7 @@ F test/capi3c.test 54e2dc0c8fd7c34ad1590d1be6864397da2438c95a9f5aee2f8fbc60c112e F test/capi3d.test 8b778794af891b0dca3d900bd345fbc8ebd2aa2aae425a9dccdd10d5233dfbde F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe F test/carray01.test d55d57bf66b1af1c7ac55fae66ff4910884a8f5d21a90a18797ce386212a2634 -F test/cast.test 8e5ad129d44643f102498d87c241fb221314c20b5e270e6826bae3bacb8bc575 +F test/cast.test 46a5963a216c2b14220557b8636b968d6de9d3292d79616becbf7109ca00e1ad F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef F test/changes.test 9dd8e597d84072122fc8a4fcdea837f4a54a461e6e536053ea984303e8ca937b F test/changes2.test d222c0cbf5ab0ac4d7c180594e486c1bf20b2098d33e56ce33b8e12eba6823b9 @@ -1328,7 +1328,7 @@ F test/minmax.test fe638b55d77d2375531a8f549b338eafcd9adfbd2f72df37ed77d9b26ca0a F test/minmax2.test cf9311babb6f0518d04e42fd6a42c619531c4309a9dd790a2c4e9b3bc595e0de F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354 F test/minmax4.test 272ca395257f05937dc96441c9dde4bc9fbf116a8d4fa02baeb0d13d50e36c87 -F test/misc1.test 294c97185354030c4ce40e7141b72f7a589585f2a44b666825381eb3df98f07c +F test/misc1.test 9955e70cab5e284d77e358cfa1f1dd43f5e4bc00a421018581b0fbd62206a6a1 F test/misc2.test 71e746af479119386ac2ed7ab7d81d99970e75b49ffd3e8efffee100b4b5f350 F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d F test/misc4.test 10cd6addb2fa9093df4751a1b92b50440175dd5468a6ec84d0386e78f087db0e @@ -1409,7 +1409,7 @@ F test/printf.test 390d0d7fcffc3c4ea3c1bb4cbb267444e32b33b048ae21895f23a291844fe F test/printf2.test 3f55c1871a5a65507416076f6eb97e738d5210aeda7595a74ee895f2224cce60 F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc -F test/pushdown.test c69f0970ea17e0afc674b89741f60c172cb6f761d81665fc71015f674f0f66ba +F test/pushdown.test f270b8071c02efc218430e0d388c155e1962eaa1d3a3ab186dd38ad6d7e178a4 F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca F test/quick.test 1681febc928d686362d50057c642f77a02c62e57 F test/quota-glob.test 32901e9eed6705d68ca3faee2a06b73b57cb3c26 @@ -1782,7 +1782,7 @@ F test/tt3_vacuum.c 71b254cde1fc49d6c8c44efd54f4668f3e57d7b3a8f4601ade069f75a999 F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff F test/types2.test 1aeb81976841a91eef292723649b5c4fe3bc3cac F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a -F test/unionall.test bfeeea6c18c09a46f7e8bed69173e31c71336152e6253fb37c7257c76509f0e4 +F test/unionall.test eb9afa030897af75fd2f0dd28354ef63c8a5897b6c76aa1f15acae61a12eabcf F test/unionall2.test 71e8fa08d5699d50dc9f9dc0c9799c2e7a6bb7931a330d369307a4df7f157fa1 F test/unionallfault.test 652bfbb630e6c43135965dc1e8f0a9a791da83aec885d626a632fe1909c56f73 F test/unionvtab.test e1704ab1b4c1bb3ffc9da4681f8e85a0b909fd80b937984fc94b27415ac8e5a4 @@ -1819,7 +1819,7 @@ F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce0 F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 -F test/view.test a5662e9c7425d77b1e1eb4b07fb891fa15f20317013eddcb6f6bee009f2fccc9 +F test/view.test a7c463254fd7ce86e861b60ddf489d5c14f22e8052f5ab2f5ff57d3eb17ccdea F test/view2.test db32c8138b5b556f610b35dfddd38c5a58a292f07fda5281eedb0851b2672679 F test/view3.test ad8a8290ee2b55ff6ce66c9ef1ce3f1e47926273a3814e1c425293e128a95456 F test/vt02.c 33ecddc0832d4cd24e9e9fa83d868981b1e049462f4ec9080710353f6479a534 @@ -2067,8 +2067,9 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ef7b783552f7783a728837fcfc81e493b135a7aac59747397e7e3d28f4309f95 -R 69b57b7832989a3f15d31278da83eb54 -U stephan -Z 4a759f802ddd912d8f969c788a0a3db7 +P 349bb28f614bc210b3283ed1c1144c45fbc7d9e2ffc3dc6193ccb9932d347efb 6ebb178c6b688ebd632e91a5ec4c748567833037c679ab3d72fb770deb230fe1 +R f920a5948608f4bc33fea80bc8d67560 +T +closed 6ebb178c6b688ebd632e91a5ec4c748567833037c679ab3d72fb770deb230fe1 +U drh +Z 8100acbd11a7404ffd2194b46d0236b1 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 2ceff7e018..8326d613cb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -349bb28f614bc210b3283ed1c1144c45fbc7d9e2ffc3dc6193ccb9932d347efb \ No newline at end of file +27655c9353620aa58105e87d1e171d1f0a637deedde41c081824078385cd49ac \ No newline at end of file diff --git a/src/build.c b/src/build.c index effaeb7332..3e5abb7ee8 100644 --- a/src/build.c +++ b/src/build.c @@ -3140,8 +3140,7 @@ static SQLITE_NOINLINE int viewGetColumnNames(Parse *pParse, Table *pTable){ && pTable->nCol==pSel->pEList->nExpr ){ assert( db->mallocFailed==0 ); - sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel, - SQLITE_AFF_NONE); + sqlite3SubqueryColumnTypes(pParse, pTable, pSel, SQLITE_AFF_NONE); } }else{ /* CREATE VIEW name AS... without an argument list. Construct diff --git a/src/expr.c b/src/expr.c index 3d96868b6d..5608128ad2 100644 --- a/src/expr.c +++ b/src/expr.c @@ -89,6 +89,72 @@ char sqlite3ExprAffinity(const Expr *pExpr){ return pExpr->affExpr; } +/* +** Make a guess at all the possible datatypes of the result that could +** be returned by an expression. Return a bitmask indicating the answer: +** +** 0x01 Numeric +** 0x02 Text +** 0x04 Blob +** +** If the expression must return NULL, then 0x00 is returned. +*/ +int sqlite3ExprDataType(const Expr *pExpr){ + while( pExpr ){ + switch( pExpr->op ){ + case TK_COLLATE: + case TK_IF_NULL_ROW: + case TK_UPLUS: { + pExpr = pExpr->pLeft; + break; + } + case TK_NULL: { + return 0x00; + } + case TK_STRING: { + return 0x02; + } + case TK_BLOB: { + return 0x04; + } + case TK_CONCAT: { + return 0x06; + } + case TK_VARIABLE: + case TK_AGG_FUNCTION: + case TK_FUNCTION: { + return 0x07; + } + case TK_COLUMN: + case TK_AGG_COLUMN: + case TK_SELECT: + case TK_CAST: + case TK_SELECT_COLUMN: + case TK_VECTOR: { + int aff = sqlite3ExprAffinity(pExpr); + if( aff>=SQLITE_AFF_NUMERIC ) return 0x05; + if( aff==SQLITE_AFF_TEXT ) return 0x06; + return 0x07; + } + case TK_CASE: { + int res = 0; + int ii; + ExprList *pList = pExpr->x.pList; + assert( ExprUseXList(pExpr) && pList!=0 ); + assert( pList->nExpr > 0); + for(ii=1; iinExpr; ii+=2){ + res |= sqlite3ExprDataType(pList->a[ii].pExpr); + } + return res; + } + default: { + return 0x01; + } + } /* End of switch(op) */ + } /* End of while(pExpr) */ + return 0; +} + /* ** Set the collating sequence for expression pExpr to be the collating ** sequence named by pToken. Return a pointer to a new Expr node that diff --git a/src/select.c b/src/select.c index 5e2b30462e..f2441e490d 100644 --- a/src/select.c +++ b/src/select.c @@ -1298,9 +1298,6 @@ static void selectInnerLoop( testcase( eDest==SRT_Fifo ); testcase( eDest==SRT_DistFifo ); sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg); - if( pDest->zAffSdst ){ - sqlite3VdbeChangeP4(v, -1, pDest->zAffSdst, nResultCol); - } #ifndef SQLITE_OMIT_CTE if( eDest==SRT_DistFifo ){ /* If the destination is DistFifo, then cursor (iParm+1) is open @@ -2291,39 +2288,38 @@ int sqlite3ColumnsFromExprList( /* ** This bit, when added to the "aff" parameter of -** sqlite3SelectAddColumnTypeAndCollation() means that result set +** sqlite3ColumnTypeOfSubquery() means that result set ** expressions of the form "CAST(expr AS NUMERIC)" should result in ** NONE affinity rather than NUMERIC affinity. */ #define SQLITE_AFF_FLAG1 0x10 /* -** Add type and collation information to a column list based on -** a SELECT statement. -** -** The column list presumably came from selectColumnNamesFromExprList(). -** The column list has only names, not types or collations. This -** routine goes through and adds the types and collations. +** pTab is a transient Table object that represents a subquery of some +** kind (maybe a parenthesized subquery in the FROM clause of a larger +** query, or a VIEW, or a CTE). This routine computes type information +** for that Table object based on the Select object that implements the +** subquery. For the purposes of this routine, "type infomation" means: ** -** This routine requires that all identifiers in the SELECT -** statement be resolved. +** * The datatype name, as it might appear in a CREATE TABLE statement +** * Which collating sequence to use for the column +** * The affinity of the column ** ** The SQLITE_AFF_FLAG1 bit added to parameter aff means that a ** result set column of the form "CAST(expr AS NUMERIC)" should use ** NONE affinity rather than NUMERIC affinity. See the ** 2022-12-10 "reopen" of ticket https://sqlite.org/src/tktview/57c47526c3. */ -void sqlite3SelectAddColumnTypeAndCollation( - Parse *pParse, /* Parsing contexts */ - Table *pTab, /* Add column type information to this table */ - Select *pSelect, /* SELECT used to determine types and collations */ - char aff /* Default affinity. Maybe with SQLITE_AFF_FLAG1 too */ +void sqlite3SubqueryColumnTypes( + Parse *pParse, /* Parsing contexts */ + Table *pTab, /* Add column type information to this table */ + Select *pSelect, /* SELECT used to determine types and collations */ + char aff /* Default affinity. Maybe with SQLITE_AFF_FLAG1 too */ ){ sqlite3 *db = pParse->db; - NameContext sNC; Column *pCol; CollSeq *pColl; - int i; + int i,j; Expr *p; struct ExprList_item *a; @@ -2332,22 +2328,42 @@ void sqlite3SelectAddColumnTypeAndCollation( assert( pTab->nCol==pSelect->pEList->nExpr || db->mallocFailed ); if( db->mallocFailed ) return; while( pSelect->pPrior ) pSelect = pSelect->pPrior; - memset(&sNC, 0, sizeof(sNC)); - sNC.pSrcList = pSelect->pSrc; a = pSelect->pEList->a; for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ const char *zType; i64 n, m; pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT); p = a[i].pExpr; - zType = columnType(&sNC, p, 0, 0, 0); /* pCol->szEst = ... // Column size est for SELECT tables never used */ pCol->affinity = sqlite3ExprAffinity(p); - if( pCol->affinity==SQLITE_AFF_NUMERIC - && p->op==TK_CAST - && (aff & SQLITE_AFF_FLAG1)!=0 - ){ - pCol->affinity = SQLITE_AFF_NONE; + if( pCol->affinity<=SQLITE_AFF_NONE ){ + assert( (SQLITE_AFF_FLAG1 & SQLITE_AFF_MASK)==0 ); + pCol->affinity = aff & SQLITE_AFF_MASK; + } + if( aff & SQLITE_AFF_FLAG1 ){ + if( pCol->affinity==SQLITE_AFF_NUMERIC && p->op==TK_CAST ){ + pCol->affinity = SQLITE_AFF_NONE; + } + } + if( pCol->affinity>=SQLITE_AFF_TEXT && pSelect->pNext ){ + int m = 0; + Select *pS2; + for(m=0, pS2=pSelect->pNext; pS2; pS2=pS2->pNext){ + m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr); + } + if( pCol->affinity==SQLITE_AFF_TEXT && (m&0x01)!=0 ){ + pCol->affinity = SQLITE_AFF_BLOB; + }else + if( pCol->affinity>=SQLITE_AFF_NUMERIC && (m&0x02)!=0 ){ + pCol->affinity = SQLITE_AFF_BLOB; + } + } + zType = 0; + for(j=0; jaffinity ){ + zType = sqlite3StdType[j]; + break; + } } if( zType ){ m = sqlite3Strlen30(zType); @@ -2361,10 +2377,6 @@ void sqlite3SelectAddColumnTypeAndCollation( pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL); } } - if( pCol->affinity<=SQLITE_AFF_NONE ){ - assert( (SQLITE_AFF_FLAG1 & SQLITE_AFF_MASK)==0 ); - pCol->affinity = aff & SQLITE_AFF_MASK; - } pColl = sqlite3ExprCollSeq(pParse, p); if( pColl ){ assert( pTab->pIndex==0 ); @@ -2398,7 +2410,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect, char aff){ pTab->zName = 0; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); - sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect, aff); + sqlite3SubqueryColumnTypes(pParse, pTab, pSelect, aff); pTab->iPKey = -1; if( db->mallocFailed ){ sqlite3DeleteTable(db, pTab); @@ -6209,14 +6221,14 @@ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){ ** This is a Walker.xSelectCallback callback for the sqlite3SelectTypeInfo() ** interface. ** -** For each FROM-clause subquery, add Column.zType and Column.zColl -** information to the Table structure that represents the result set -** of that subquery. +** For each FROM-clause subquery, add Column.zType, Column.zColl, and +** Column.affinity information to the Table structure that represents +** the result set of that subquery. ** ** The Table structure that represents the result set was constructed -** by selectExpander() but the type and collation information was omitted -** at that point because identifiers had not yet been resolved. This -** routine is called after identifier resolution. +** by selectExpander() but the type and collation and affinity information +** was omitted at that point because identifiers had not yet been resolved. +** This routine is called after identifier resolution. */ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ Parse *pParse; @@ -6236,9 +6248,8 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ /* A sub-query in the FROM clause of a SELECT */ Select *pSel = pFrom->pSelect; if( pSel ){ - while( pSel->pPrior ) pSel = pSel->pPrior; - sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSel, - SQLITE_AFF_NONE|SQLITE_AFF_FLAG1); + sqlite3SubqueryColumnTypes(pParse, pTab, pSel, + SQLITE_AFF_NONE|SQLITE_AFF_FLAG1); } } } @@ -7350,10 +7361,7 @@ int sqlite3Select( sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); ExplainQueryPlan2(addrExplain, (pParse, 1, "MATERIALIZE %!S", pItem)); - dest.zAffSdst = sqlite3TableAffinityStr(db, pItem->pTab); sqlite3Select(pParse, pSub, &dest); - sqlite3DbFree(db, dest.zAffSdst); - dest.zAffSdst = 0; pItem->pTab->nRowLogEst = pSub->nSelectRow; if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr); sqlite3VdbeAddOp2(v, OP_Return, pItem->regReturn, topAddr+1); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5a19058bd1..21b23d2ad4 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3573,7 +3573,7 @@ struct SelectDest { int iSDParm2; /* A second parameter for the eDest disposal method */ int iSdst; /* Base register where results are written */ int nSdst; /* Number of registers allocated */ - char *zAffSdst; /* Affinity used for SRT_Set, SRT_Table, and similar */ + char *zAffSdst; /* Affinity used for SRT_Set */ ExprList *pOrderBy; /* Key columns for SRT_Queue and SRT_DistQueue */ }; @@ -4678,7 +4678,7 @@ const char *sqlite3ColumnColl(Column*); void sqlite3DeleteColumnNames(sqlite3*,Table*); void sqlite3GenerateColumnNames(Parse *pParse, Select *pSelect); int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**); -void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*,char); +void sqlite3SubqueryColumnTypes(Parse*,Table*,Select*,char); Table *sqlite3ResultSetOfSelect(Parse*,Select*,char); void sqlite3OpenSchemaTable(Parse *, int); Index *sqlite3PrimaryKeyIndex(Table*); @@ -5049,6 +5049,7 @@ char sqlite3CompareAffinity(const Expr *pExpr, char aff2); int sqlite3IndexAffinityOk(const Expr *pExpr, char idx_affinity); char sqlite3TableColumnAffinity(const Table*,int); char sqlite3ExprAffinity(const Expr *pExpr); +int sqlite3ExprDataType(const Expr *pExpr); int sqlite3Atoi64(const char*, i64*, int, u8); int sqlite3DecOrHexToI64(const char*, i64*); void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...); diff --git a/src/vdbe.c b/src/vdbe.c index 12b22992b9..82a9938477 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2115,7 +2115,6 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ flags1 = pIn1->flags; flags3 = pIn3->flags; if( (flags1 & flags3 & MEM_Int)!=0 ){ - assert( (pOp->p5 & SQLITE_AFF_MASK)!=SQLITE_AFF_TEXT || CORRUPT_DB ); /* Common case of comparison of two integers */ if( pIn3->u.i > pIn1->u.i ){ if( sqlite3aGTb[pOp->opcode] ){ @@ -2183,7 +2182,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ applyNumericAffinity(pIn3,0); } } - }else if( affinity==SQLITE_AFF_TEXT ){ + }else if( affinity==SQLITE_AFF_TEXT && ((flags1 | flags3) & MEM_Str)!=0 ){ if( (flags1 & MEM_Str)==0 && (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){ testcase( pIn1->flags & MEM_Int ); testcase( pIn1->flags & MEM_Real ); diff --git a/test/affinity3.test b/test/affinity3.test index 48942de72e..3695ea8479 100644 --- a/test/affinity3.test +++ b/test/affinity3.test @@ -104,20 +104,20 @@ do_execsql_test affinity3-200 { CREATE TABLE mzed AS SELECT * FROM idmap; } -#do_execsql_test affinity3-210 { - #PRAGMA automatic_index=ON; - #SELECT * FROM data JOIN idmap USING(id); -#} {1 abc a 4 xyz e} +do_execsql_test affinity3-210 { + PRAGMA automatic_index=ON; + SELECT * FROM data JOIN idmap USING(id); +} {4 xyz e} do_execsql_test affinity3-220 { SELECT * FROM data JOIN mzed USING(id); -} {1 abc a 4 xyz e} +} {4 xyz e} do_execsql_test affinity3-250 { PRAGMA automatic_index=OFF; SELECT * FROM data JOIN idmap USING(id); -} {1 abc a 4 xyz e} +} {4 xyz e} do_execsql_test affinity3-260 { SELECT * FROM data JOIN mzed USING(id); -} {1 abc a 4 xyz e} +} {4 xyz e} finish_test diff --git a/test/cast.test b/test/cast.test index 9eaacecc95..c4c0d8908d 100644 --- a/test/cast.test +++ b/test/cast.test @@ -481,7 +481,7 @@ do_execsql_test cast-9.0 { CREATE VIEW v1(c0, c1) AS SELECT CAST(0.0 AS NUMERIC), COUNT(*) OVER () FROM t0; SELECT v1.c0 FROM v1, t0 WHERE v1.c0=0; -} {0} +} {0.0} # Set the 2022-12-10 "reopen" of ticket [https://sqlite.org/src/tktview/57c47526c3] # diff --git a/test/misc1.test b/test/misc1.test index b1b1b083c3..44914156cb 100644 --- a/test/misc1.test +++ b/test/misc1.test @@ -605,14 +605,17 @@ do_execsql_test misc1-19.2 { SELECT * FROM t19b; } {4 5 6} -# 2015-05-20: CREATE TABLE AS should not store INT value is a TEXT +# 2015-05-20: CREATE TABLE AS should not store INT value in a TEXT # column. # +# 2022-12-14: Change: The column is not TEXT if the AS SELECT is +# a compound with different types on each arm. +# do_execsql_test misc1-19.3 { CREATE TABLE t19c(x TEXT); CREATE TABLE t19d AS SELECT * FROM t19c UNION ALL SELECT 1234; SELECT x, typeof(x) FROM t19d; -} {1234 text} +} {1234 integer} # 2014-05-16: Tests for the SQLITE_TESTCTRL_FAULT_INSTALL feature. # @@ -622,11 +625,11 @@ proc fault_callback {n} { lappend ::fault_callbacks $n return 0 } -do_test misc1-19.1 { +do_test misc1-19.11 { sqlite3_test_control_fault_install fault_callback set fault_callbacks } {0} -do_test misc1-19.2 { +do_test misc1-19.12 { sqlite3_test_control_fault_install set fault_callbacks } {0} diff --git a/test/pushdown.test b/test/pushdown.test index 7c9b107841..ca816fb213 100644 --- a/test/pushdown.test +++ b/test/pushdown.test @@ -95,22 +95,32 @@ do_execsql_test 3.1 { CREATE TABLE t0(c0 INT); INSERT INTO t0 VALUES(0); CREATE TABLE t1_a(a INTEGER PRIMARY KEY, b TEXT); - INSERT INTO t1_a VALUES(1,'one'); --,(4,'four'); + INSERT INTO t1_a VALUES(1,'one'); CREATE TABLE t1_b(c INTEGER PRIMARY KEY, d TEXT); - INSERT INTO t1_b VALUES(2,'two'); --,(5,'five'); + INSERT INTO t1_b VALUES(2,'two'); CREATE VIEW v0 AS SELECT CAST(t0.c0 AS INTEGER) AS c0 FROM t0; - CREATE VIEW t1 AS SELECT a, b FROM t1_a UNION ALL SELECT c, 0 FROM t1_b; - SELECT t1.a, quote(t1.b), t0.c0 AS cd FROM t0 LEFT JOIN v0 ON v0.c0!=0,t1; + CREATE VIEW v1(a,b) AS SELECT a, b FROM t1_a UNION ALL SELECT c, 0 FROM t1_b; + SELECT v1.a, quote(v1.b), t0.c0 AS cd FROM t0 LEFT JOIN v0 ON v0.c0!=0,v1; } { 1 'one' 0 - 2 '0' 0 + 2 0 0 } do_execsql_test 3.2 { SELECT a, quote(b), cd FROM ( - SELECT t1.a, t1.b, t0.c0 AS cd FROM t0 LEFT JOIN v0 ON v0.c0!=0,t1 + SELECT v1.a, v1.b, t0.c0 AS cd FROM t0 LEFT JOIN v0 ON v0.c0!=0, v1 ) WHERE a=2 AND b='0' AND cd=0; +} {} +do_execsql_test 3.3 { + SELECT a, quote(b), cd FROM ( + SELECT v1.a, v1.b, t0.c0 AS cd FROM t0 LEFT JOIN v0 ON v0.c0!=0, v1 + ) WHERE a=1 AND b='one' AND cd=0; +} {1 'one' 0} +do_execsql_test 3.4 { + SELECT a, quote(b), cd FROM ( + SELECT v1.a, v1.b, t0.c0 AS cd FROM t0 LEFT JOIN v0 ON v0.c0!=0, v1 + ) WHERE a=2 AND b=0 AND cd=0; } { - 2 '0' 0 + 2 0 0 } finish_test diff --git a/test/unionall.test b/test/unionall.test index 7783c04a67..32fc76543a 100644 --- a/test/unionall.test +++ b/test/unionall.test @@ -408,37 +408,39 @@ do_execsql_test 8.1 { SELECT a, b FROM t1_a UNION ALL SELECT c, c FROM t1_b UNION ALL SELECT e, f FROM t1_c; -} + SELECT t1.a, t1.b, t0.c0 AS c, v0.c0 AS d FROM t0 LEFT JOIN v0 ON v0.c0>'0',t1; +} {1 one 0 {} 4 four 0 {} 2 2 0 {} 5 5 0 {} 3 three 0 {} 6 six 0 {}} + optimization_control db all 1 do_execsql_test 8.2 { SELECT * FROM (SELECT t1.a, t1.b, t0.c0 AS c, v0.c0 AS d FROM t0 LEFT JOIN v0 ON v0.c0>'0',t1) WHERE b=2; } {2 2 0 {}} do_execsql_test 8.3 { SELECT * FROM (SELECT t1.a, t1.b, t0.c0 AS c, v0.c0 AS d FROM t0 LEFT JOIN v0 ON v0.c0>'0',t1) WHERE b=2.0; -} {} +} {2 2 0 {}} do_execsql_test 8.4 { SELECT * FROM (SELECT t1.a, t1.b, t0.c0 AS c, v0.c0 AS d FROM t0 LEFT JOIN v0 ON v0.c0>'0',t1) WHERE b='2'; -} {2 2 0 {}} +} {} optimization_control db query-flattener,push-down 0 do_execsql_test 8.5 { SELECT * FROM (SELECT t1.a, t1.b, t0.c0 AS c, v0.c0 AS d FROM t0 LEFT JOIN v0 ON v0.c0>'0',t1) WHERE b=2; } {2 2 0 {}} do_execsql_test 8.6 { SELECT * FROM (SELECT t1.a, t1.b, t0.c0 AS c, v0.c0 AS d FROM t0 LEFT JOIN v0 ON v0.c0>'0',t1) WHERE b=2.0; -} {} +} {2 2 0 {}} do_execsql_test 8.7 { SELECT * FROM (SELECT t1.a, t1.b, t0.c0 AS c, v0.c0 AS d FROM t0 LEFT JOIN v0 ON v0.c0>'0',t1) WHERE b='2'; -} {2 2 0 {}} +} {} optimization_control db all 0 do_execsql_test 8.8 { SELECT * FROM (SELECT t1.a, t1.b, t0.c0 AS c, v0.c0 AS d FROM t0 LEFT JOIN v0 ON v0.c0>'0',t1) WHERE b=2; } {2 2 0 {}} do_execsql_test 8.9 { SELECT * FROM (SELECT t1.a, t1.b, t0.c0 AS c, v0.c0 AS d FROM t0 LEFT JOIN v0 ON v0.c0>'0',t1) WHERE b=2.0; -} {} +} {2 2 0 {}} do_execsql_test 8.10 { SELECT * FROM (SELECT t1.a, t1.b, t0.c0 AS c, v0.c0 AS d FROM t0 LEFT JOIN v0 ON v0.c0>'0',t1) WHERE b='2'; -} {2 2 0 {}} +} {} finish_test diff --git a/test/view.test b/test/view.test index 446ee3edea..60eb7e5277 100644 --- a/test/view.test +++ b/test/view.test @@ -123,16 +123,16 @@ do_execsql_test view-1.10 { } {} do_execsql_test view-1.11 { PRAGMA table_info(v9a); -} {0 x INTEGER 0 {} 0} +} {0 x INT 0 {} 0} do_execsql_test view-1.12 { PRAGMA table_info(v9b); -} {0 x INTEGER 0 {} 0} +} {0 x INT 0 {} 0} do_execsql_test view-1.13 { PRAGMA table_info(v9c); -} {0 x INTEGER 0 {} 0} +} {0 x INT 0 {} 0} do_execsql_test view-1.14 { PRAGMA table_info(v9d); -} {0 x INTEGER 0 {} 0} +} {0 x INT 0 {} 0} do_test view-2.1 { execsql { @@ -778,6 +778,10 @@ do_catchsql_test view-29.1 { #------------------------------------------------------------------------- # 2022-12-11. https://sqlite.org/src/info/679ed6a2 # +# 2022-12-14 change: If the AS SELECT of a VIEW is a compound where +# the datatypes on each arm of the compound are different, then the +# datatype of the overall column is BLOB (ANY). +# reset_db do_execsql_test view-30.0 { CREATE TABLE t0(a INT, b TEXT); @@ -791,11 +795,10 @@ do_execsql_test view-30.0 { ifcapable schema_pragmas { do_execsql_test view-30.1 { PRAGMA table_info = t1; - } { 0 a INT 0 {} 0 1 b TEXT 0 {} 0 } + } { 0 a INT 0 {} 0 1 b BLOB 0 {} 0 } do_execsql_test view-30.2 { PRAGMA table_info = t2; - } { 0 a INT 0 {} 0 1 b TEXT 0 {} 0 } + } { 0 a INT 0 {} 0 1 b BLOB 0 {} 0 } } finish_test -