diff --git a/manifest b/manifest index 03bfe4ae1c..abda9195f2 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,5 @@ ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -C Fix\san\soff-by-one\serror\sin\sthe\sscratch\smemory\sallocator. -D 2010-09-02T18:13:01 +C Move\sthe\stest\sfor\san\s(illegal)\sscalar\ssub-query\sthat\sreturns\smore\sthan\sone\scolumn\sto\searlier\sin\sSELECT\sprocessing\sin\sorder\sto\savoid\san\sassert()\sthat\scan\shappen\slater\son. +D 2010-09-02T19:01:16 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in c599a15d268b1db2aeadea19df2adc3bf2eb6bee F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -174,7 +171,7 @@ F src/printf.c 8ae5082dd38a1b5456030c3755ec3a392cd51506 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 -F src/select.c fb7008115d9ccd85f6b6934c15c204b7fe6bfc38 +F src/select.c eb57331a0f37fbfff0b24824555ac70dbc996c4d F src/shell.c 8517fc1f9c59ae4007e6cc8b9af91ab231ea2056 F src/sqlite.h.in b77b914f5f4c301ca00b2fc0fe253240ec177503 F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89 @@ -349,7 +346,7 @@ F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d F test/descidx3.test fe720e8b37d59f4cef808b0bf4e1b391c2e56b6f F test/diskfull.test 0cede7ef9d8f415d9d3944005c76be7589bb5ebb F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376 -F test/e_expr.test 1d4437a740dcffa675aa33d50d3440be9805f922 +F test/e_expr.test 1aef3ba4a140487cf5b452f04e261f26e99f9fe5 F test/e_fkey.test 6721a741c6499b3ab7e5385923233343c8f1ad05 F test/e_fts3.test 75bb0aee26384ef586165e21018a17f7cd843469 F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea @@ -443,7 +440,7 @@ F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test dd7001ac86d09c154a7dff064f4739c60e2b312c F test/hook.test f04c3412463f8ec117c1c704c74ca0f627ce733a F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 -F test/in.test d49419c6df515852f477fa513f3317181d46bc92 +F test/in.test 19b642bb134308980a92249750ea4ce3f6c75c2d F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0 F test/in4.test 64f3cc1acde1b9161ccdd8e5bde3daefdb5b2617 @@ -856,14 +853,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 2211486b69cf53f5efb1334aff8b403b26596102 -R 58aa05496d4c88e93839c30ad7f0f12f -U drh -Z 9ab20b082ef4d5eb3039a58dec067745 ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.6 (GNU/Linux) - -iD8DBQFMf+kwoxKgR168RlERArAIAJ44f+KasgThCWlpaivQQWtOA27OrACeL7/e -Ym5tzUVAgx/gSuZ7kCIQ05g= -=rGma ------END PGP SIGNATURE----- +P 5a9591607a0a5ba4527bf2a90179651053244953 +R 7b514d804097129d93b3bae4d77340bd +U dan +Z b5e46a0ab42bf67eb22bcfbf65812650 diff --git a/manifest.uuid b/manifest.uuid index 47194d7291..f7f92e7c1d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5a9591607a0a5ba4527bf2a90179651053244953 \ No newline at end of file +a55842cfb56b659c88832dce9ce7bafb50258211 \ No newline at end of file diff --git a/src/select.c b/src/select.c index 55d771ecf4..b0de29a83f 100644 --- a/src/select.c +++ b/src/select.c @@ -3626,6 +3626,15 @@ int sqlite3Select( v = sqlite3GetVdbe(pParse); if( v==0 ) goto select_end; + /* If writing to memory or generating a set + ** only a single column may be output. + */ +#ifndef SQLITE_OMIT_SUBQUERY + if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){ + goto select_end; + } +#endif + /* Generate code for all sub-queries in the FROM clause */ #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) @@ -3699,15 +3708,6 @@ int sqlite3Select( } #endif - /* If writing to memory or generating a set - ** only a single column may be output. - */ -#ifndef SQLITE_OMIT_SUBQUERY - if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){ - goto select_end; - } -#endif - /* If possible, rewrite the query to use GROUP BY instead of DISTINCT. ** GROUP BY might use an index, DISTINCT never does. */ diff --git a/test/e_expr.test b/test/e_expr.test index b0999e1f88..74024cd9bd 100644 --- a/test/e_expr.test +++ b/test/e_expr.test @@ -1729,11 +1729,56 @@ foreach {tn e1 e2} { do_expr_test e_expr-34.5.${tn}b $e2 integer $res } - - #------------------------------------------------------------------------- -# Test statements related to the IN and NOT IN operators. +# Test statements related to scalar sub-queries. # +catch { db close } +file delete -force test.db +sqlite3 db test.db +do_test e_expr-35.0 { + execsql { + CREATE TABLE t2(a, b); + INSERT INTO t2 VALUES('one', 'two'); + INSERT INTO t2 VALUES('three', NULL); + INSERT INTO t2 VALUES(4, 5.0); + } +} {} + +# EVIDENCE-OF: R-00980-39256 A SELECT statement enclosed in parentheses +# may appear as a scalar quantity. +# +# EVIDENCE-OF: R-56294-03966 All types of SELECT statement, including +# aggregate and compound SELECT queries (queries with keywords like +# UNION or EXCEPT) are allowed as scalar subqueries. +# +do_expr_test e_expr-35.1.1 { (SELECT 35) } integer 35 +do_expr_test e_expr-35.1.2 { (SELECT NULL) } null {} + +do_expr_test e_expr-35.1.3 { (SELECT count(*) FROM t2) } integer 3 +do_expr_test e_expr-35.1.4 { (SELECT 4 FROM t2) } integer 4 + +do_expr_test e_expr-35.1.5 { + (SELECT b FROM t2 UNION SELECT a+1 FROM t2) +} null {} +do_expr_test e_expr-35.1.6 { + (SELECT a FROM t2 UNION SELECT COALESCE(b, 55) FROM t2 ORDER BY 1) +} integer 4 + +# EVIDENCE-OF: R-46899-53765 A SELECT used as a scalar quantity must +# return a result set with a single column. +# +set M {only a single result allowed for a SELECT that is part of an expression} +foreach {tn sql} { + 1 { SELECT (SELECT * FROM t2 UNION SELECT a+1, b+1 FROM t2) } + 2 { SELECT (SELECT * FROM t2 UNION SELECT a+1, b+1 FROM t2 ORDER BY 1) } + 3 { SELECT (SELECT 1, 2) } + 4 { SELECT (SELECT NULL, NULL, NULL) } + 5 { SELECT (SELECT * FROM t2) } + 6 { SELECT (SELECT * FROM (SELECT 1, 2, 3)) } +} { + do_catchsql_test e_expr-35.2.$tn $sql [list 1 $M] +} + finish_test diff --git a/test/in.test b/test/in.test index 8fbfbed8f6..2c38a0f4ca 100644 --- a/test/in.test +++ b/test/in.test @@ -404,33 +404,62 @@ do_test in-12.5 { do_test in-12.6 { catchsql { SELECT * FROM t2 WHERE a IN ( - SELECT a FROM t3 UNION ALL SELECT a, b FROM t2 + SELECT a, b FROM t3 UNION ALL SELECT a FROM t2 ); } } {1 {SELECTs to the left and right of UNION ALL do not have the same number of result columns}} do_test in-12.7 { catchsql { SELECT * FROM t2 WHERE a IN ( - SELECT a FROM t3 UNION SELECT a, b FROM t2 + SELECT a, b FROM t3 UNION SELECT a FROM t2 ); } } {1 {SELECTs to the left and right of UNION do not have the same number of result columns}} do_test in-12.8 { catchsql { SELECT * FROM t2 WHERE a IN ( - SELECT a FROM t3 EXCEPT SELECT a, b FROM t2 + SELECT a, b FROM t3 EXCEPT SELECT a FROM t2 ); } } {1 {SELECTs to the left and right of EXCEPT do not have the same number of result columns}} do_test in-12.9 { catchsql { SELECT * FROM t2 WHERE a IN ( - SELECT a FROM t3 INTERSECT SELECT a, b FROM t2 + SELECT a, b FROM t3 INTERSECT SELECT a FROM t2 ); } } {1 {SELECTs to the left and right of INTERSECT do not have the same number of result columns}} } +do_test in-12.10 { + catchsql { + SELECT * FROM t2 WHERE a IN ( + SELECT a FROM t3 UNION ALL SELECT a, b FROM t2 + ); + } +} {1 {only a single result allowed for a SELECT that is part of an expression}} +do_test in-12.11 { + catchsql { + SELECT * FROM t2 WHERE a IN ( + SELECT a FROM t3 UNION SELECT a, b FROM t2 + ); + } +} {1 {only a single result allowed for a SELECT that is part of an expression}} +do_test in-12.12 { + catchsql { + SELECT * FROM t2 WHERE a IN ( + SELECT a FROM t3 EXCEPT SELECT a, b FROM t2 + ); + } +} {1 {only a single result allowed for a SELECT that is part of an expression}} +do_test in-12.13 { + catchsql { + SELECT * FROM t2 WHERE a IN ( + SELECT a FROM t3 INTERSECT SELECT a, b FROM t2 + ); + } +} {1 {only a single result allowed for a SELECT that is part of an expression}} + #------------------------------------------------------------------------ # The following tests check that NULL is handled correctly when it