]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
If a subquery has a result column of the form "CAST(... AS NUMERIC)" then cast-to-numeric
authordrh <>
Mon, 12 Dec 2022 18:58:53 +0000 (18:58 +0000)
committerdrh <>
Mon, 12 Dec 2022 18:58:53 +0000 (18:58 +0000)
give that column no affinity rather than NUMERIC affinity.  This is because
casting to numeric preserves real values that could be integers but numeric
affinity does not.  By using no affinity on the column, we make the behavior
consistent if the subquery is implemented as a co-routine or is materialized.

FossilOrigin-Name: ece07d091c2ef3367a914187e0b6512c1f2390b8c34844536ad50e88c7e8c2f2

manifest
manifest.uuid
src/select.c
test/cast.test

index fb68b355138fbb600179d789af40c5137e88ab2f..80005c18552a8e7acc77d8d1d78ea142866eef4a 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Move\sJS-to-C\sbinding\ssignatures\sfrom\ssqlite3-api-prologue.js\sto\ssqlite3-api-glue.js\sto\sallow\sfor\suse\sof\sthe\snew/experimental\ssqlite3.wasm.xWrap()\sfeature\swhich\sautomatically\sbinds\sJS\sfunctions\sto\sWASM/C\sas\sneeded,\swhich\ssimplifies\screation\sof\sbindings\swhich\stake\sC\sfunction\spointers.\sReimplement\ssqlite3_exec(),\ssqlite3_create_collation(),\ssqlite3_progress_handler()\sto\suse\sthis\snew\sfeature.
-D 2022-12-12T14:31:38.581
+C If\sa\ssubquery\shas\sa\sresult\scolumn\sof\sthe\sform\s"CAST(...\sAS\sNUMERIC)"\sthen\ngive\sthat\scolumn\sno\saffinity\srather\sthan\sNUMERIC\saffinity.\s\sThis\sis\sbecause\ncasting\sto\snumeric\spreserves\sreal\svalues\sthat\scould\sbe\sintegers\sbut\snumeric\naffinity\sdoes\snot.\s\sBy\susing\sno\saffinity\son\sthe\scolumn,\swe\smake\sthe\sbehavior\nconsistent\sif\sthe\ssubquery\sis\simplemented\sas\sa\sco-routine\sor\sis\smaterialized.
+D 2022-12-12T18:58:53.208
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -645,7 +645,7 @@ F src/printf.c e99ee9741e79ae3873458146f59644276657340385ade4e76a5f5d1c25793764
 F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
 F src/resolve.c efea4e5fbecfd6d0a9071b0be0d952620991673391b6ffaaf4c277b0bb674633
 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
-F src/select.c 9a687883032642054b8f400aa3bcb6019c2c30f890850480975e95568f290c52
+F src/select.c 39c4b0e23f3f1334ca3ff9b68014de0ec2c4ae5954186765d669893a8c7fc5a9
 F src/shell.c.in 8d9dc02dd03f8fc93f3e3cdb17d8d16e8ddb985dddad213985c08186900a3ebb
 F src/sqlite.h.in 97e8021f5db6bab8646d9c2d4231d3bab1204a2e88e5f187eca11dc7eab33ef8
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
@@ -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 6064022ba9af31a8a2ff7bb345e5bd0e74172ffad85bdab5898a42d8227c7585
+F test/cast.test 4f14da6ed96af8b3124cd2cda2ff8cda0946a8a0d0d32ae76905795c6e3ac7bc
 F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
 F test/changes.test 9dd8e597d84072122fc8a4fcdea837f4a54a461e6e536053ea984303e8ca937b
 F test/changes2.test d222c0cbf5ab0ac4d7c180594e486c1bf20b2098d33e56ce33b8e12eba6823b9
@@ -2067,8 +2067,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P d557015208f504c6d5d20ebf1e451b3f07b19590d76371b16a9f4b54e9645282
-R 5a61f05e144f2d7b8121b7e697a724d0
-U stephan
-Z 82382106256d8062d011dc4fe2d4d001
+P 9386d6f634680b4e0fa5487c34c63acb29f0b7a6ae738b8f6164ad084a229b62
+R b147605f598862d0859edce8eb970ae1
+T *branch * cast-to-numeric
+T *sym-cast-to-numeric *
+T -sym-trunk *
+U drh
+Z 8d98f09634c2da9d51008460bd14d1a6
 # Remove this line to create a well-formed Fossil manifest.
index de9a05d4f35abe684d92bf58fe8297598a681ea7..e5d9e2b58384b0fc611037bef671d9a8f6c5b630 100644 (file)
@@ -1 +1 @@
-9386d6f634680b4e0fa5487c34c63acb29f0b7a6ae738b8f6164ad084a229b62
\ No newline at end of file
+ece07d091c2ef3367a914187e0b6512c1f2390b8c34844536ad50e88c7e8c2f2
\ No newline at end of file
index 3752aaef7126dcbd44c73d5c2a104f5701f6a898..5e2b30462ebd69e705dce7e2819b7e1c0b5dc0eb 100644 (file)
@@ -2289,6 +2289,14 @@ int sqlite3ColumnsFromExprList(
   return SQLITE_OK;
 }
 
+/*
+** This bit, when added to the "aff" parameter of 
+** sqlite3SelectAddColumnTypeAndCollation() 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.
@@ -2299,12 +2307,17 @@ int sqlite3ColumnsFromExprList(
 **
 ** This routine requires that all identifiers in the SELECT
 ** statement be resolved.
+**
+** 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 for columns */
+  char aff              /* Default affinity.  Maybe with SQLITE_AFF_FLAG1 too */
 ){
   sqlite3 *db = pParse->db;
   NameContext sNC;
@@ -2330,6 +2343,12 @@ void sqlite3SelectAddColumnTypeAndCollation(
     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( zType ){
       m = sqlite3Strlen30(zType);
       n = sqlite3Strlen30(pCol->zCnName);
@@ -2342,7 +2361,10 @@ void sqlite3SelectAddColumnTypeAndCollation(
         pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL);
       }
     }
-    if( pCol->affinity<=SQLITE_AFF_NONE ) pCol->affinity = aff;
+    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 );
@@ -6216,7 +6238,7 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
       if( pSel ){
         while( pSel->pPrior ) pSel = pSel->pPrior;
         sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSel,
-                                               SQLITE_AFF_NONE);
+                                     SQLITE_AFF_NONE|SQLITE_AFF_FLAG1);
       }
     }
   }
index cbeec47c9d3b60d1343a4d1a0a0e1cb92fe99d6a..cd3f1cad15e0790220fedd91d4fef437d18dbd4c 100644 (file)
@@ -483,5 +483,36 @@ do_execsql_test cast-9.0 {
   SELECT v1.c0 FROM v1, t0 WHERE v1.c0=0; 
 } {0}
 
+# Set the 2022-12-10 "reopen" of ticket [https://sqlite.org/src/tktview/57c47526c3]
+#
+do_execsql_test cast-9.1 {
+  CREATE TABLE dual(dummy TEXT);
+  INSERT INTO dual VALUES('X');
+  SELECT CAST(4 AS NUMERIC);
+} {4}
+do_execsql_test cast-9.2 {
+  SELECT CAST(4.0 AS NUMERIC);
+} {4.0}
+do_execsql_test cast-9.3 {
+  SELECT CAST(4.5 AS NUMERIC);
+} {4.5}
+do_execsql_test cast-9.4 {
+  SELECT x, typeof(x) FROM (SELECT CAST(4 AS NUMERIC) AS x) JOIN dual;
+} {4 integer}
+do_execsql_test cast-9.5 {
+  SELECT x, typeof(x) FROM (SELECT CAST(4 AS NUMERIC) AS x) CROSS JOIN dual;
+} {4 integer}
+do_execsql_test cast-9.10 {
+  SELECT x, typeof(x) FROM (SELECT CAST(4.0 AS NUMERIC) AS x) JOIN dual;
+} {4.0 real}
+do_execsql_test cast-9.11 {
+  SELECT x, typeof(x) FROM (SELECT CAST(4.0 AS NUMERIC) AS x) CROSS JOIN dual;
+} {4.0 real}
+do_execsql_test cast-9.12 {
+  SELECT x, typeof(x) FROM (SELECT CAST(4.5 AS NUMERIC) AS x) JOIN dual;
+} {4.5 real}
+do_execsql_test cast-9.13 {
+  SELECT x, typeof(x) FROM (SELECT CAST(4.5 AS NUMERIC) AS x) CROSS JOIN dual;
+} {4.5 real}
 
 finish_test