]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Refactor the name resolution procedures in the code generator. (CVS 5569)
authordrh <drh@noemail.net>
Wed, 20 Aug 2008 16:35:10 +0000 (16:35 +0000)
committerdrh <drh@noemail.net>
Wed, 20 Aug 2008 16:35:10 +0000 (16:35 +0000)
FossilOrigin-Name: daf730d1defa78fb8b80a78f9108ac35a13e09f6

29 files changed:
Makefile.in
addopcodes.awk
main.mk
manifest
manifest.uuid
src/attach.c
src/build.c
src/delete.c
src/expr.c
src/insert.c
src/main.c
src/parse.y
src/prepare.c
src/resolve.c [new file with mode: 0644]
src/select.c
src/sqliteInt.h
src/trigger.c
src/update.c
src/vdbeaux.c
src/vtab.c
src/walker.c [new file with mode: 0644]
src/where.c
test/collate2.test
test/collate3.test
test/fuzz_malloc.test
test/select5.test
test/select6.test
test/tkt2822.test
tool/mksqlite3c.tcl

index f59fab9ab195200539e771912d7e6b0148a35cbd..96068770a4bc2b816475754b1477a9ecfc02c079 100644 (file)
@@ -163,10 +163,11 @@ OBJS0 = alter.lo analyze.lo attach.lo auth.lo bitvec.lo btmutex.lo \
         mutex.lo mutex_os2.lo mutex_unix.lo mutex_w32.lo \
         opcodes.lo os.lo os_unix.lo os_win.lo os_os2.lo \
         pager.lo parse.lo pcache.lo pragma.lo prepare.lo printf.lo random.lo \
-        select.lo status.lo table.lo tokenize.lo trigger.lo update.lo \
+        resolve.lo select.lo status.lo \
+        table.lo tokenize.lo trigger.lo update.lo \
         util.lo vacuum.lo \
         vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbefifo.lo vdbemem.lo \
-        where.lo utf.lo legacy.lo vtab.lo
+        walker.lo where.lo utf.lo vtab.lo
 
 # Object files for the amalgamation.
 #
@@ -233,6 +234,7 @@ SRC = \
   $(TOP)/src/prepare.c \
   $(TOP)/src/printf.c \
   $(TOP)/src/random.c \
+  $(TOP)/src/resolve.c \
   $(TOP)/src/select.c \
   $(TOP)/src/status.c \
   $(TOP)/src/shell.c \
@@ -257,6 +259,7 @@ SRC = \
   $(TOP)/src/vdbemem.c \
   $(TOP)/src/vdbeInt.h \
   $(TOP)/src/vtab.c \
+  $(TOP)/src/walker.c \
   $(TOP)/src/where.c
 
 # Generated source code files
@@ -630,6 +633,9 @@ printf.lo:  $(TOP)/src/printf.c $(HDR)
 random.lo:     $(TOP)/src/random.c $(HDR)
        $(LTCOMPILE) -c $(TOP)/src/random.c
 
+resolve.lo:    $(TOP)/src/resolve.c $(HDR)
+       $(LTCOMPILE) -c $(TOP)/src/resolve.c
+
 select.lo:     $(TOP)/src/select.c $(HDR)
        $(LTCOMPILE) -c $(TOP)/src/select.c
 
@@ -689,6 +695,9 @@ vdbemem.lo: $(TOP)/src/vdbemem.c $(HDR)
 vtab.lo:       $(TOP)/src/vtab.c $(HDR)
        $(LTCOMPILE) -c $(TOP)/src/vtab.c
 
+walker.lo:     $(TOP)/src/walker.c $(HDR)
+       $(LTCOMPILE) -c $(TOP)/src/walker.c
+
 where.lo:      $(TOP)/src/where.c $(HDR)
        $(LTCOMPILE) -c $(TOP)/src/where.c
 
index f6f8927e2470b63ade8480abb71d9ba0164345ae..9c21417190a3bec6b4209e09e2169cb22720aa6c 100644 (file)
@@ -14,18 +14,18 @@ BEGIN {
   if( max<$3 ) max = $3
 }
 END {
-  printf "#define TK_%-29s %4d\n", "TO_TEXT",         max+1
-  printf "#define TK_%-29s %4d\n", "TO_BLOB",         max+2
-  printf "#define TK_%-29s %4d\n", "TO_NUMERIC",      max+3
-  printf "#define TK_%-29s %4d\n", "TO_INT",          max+4
-  printf "#define TK_%-29s %4d\n", "TO_REAL",         max+5
-  printf "#define TK_%-29s %4d\n", "END_OF_FILE",     max+6
-  printf "#define TK_%-29s %4d\n", "ILLEGAL",         max+7
-  printf "#define TK_%-29s %4d\n", "SPACE",           max+8
-  printf "#define TK_%-29s %4d\n", "UNCLOSED_STRING", max+9
-  printf "#define TK_%-29s %4d\n", "FUNCTION",        max+10
-  printf "#define TK_%-29s %4d\n", "COLUMN",          max+11
-  printf "#define TK_%-29s %4d\n", "AGG_FUNCTION",    max+12
-  printf "#define TK_%-29s %4d\n", "AGG_COLUMN",      max+13
-  printf "#define TK_%-29s %4d\n", "CONST_FUNC",      max+14
+  printf "#define TK_%-29s %4d\n", "TO_TEXT",         ++max
+  printf "#define TK_%-29s %4d\n", "TO_BLOB",         ++max
+  printf "#define TK_%-29s %4d\n", "TO_NUMERIC",      ++max
+  printf "#define TK_%-29s %4d\n", "TO_INT",          ++max
+  printf "#define TK_%-29s %4d\n", "TO_REAL",         ++max
+  printf "#define TK_%-29s %4d\n", "END_OF_FILE",     ++max
+  printf "#define TK_%-29s %4d\n", "ILLEGAL",         ++max
+  printf "#define TK_%-29s %4d\n", "SPACE",           ++max
+  printf "#define TK_%-29s %4d\n", "UNCLOSED_STRING", ++max
+  printf "#define TK_%-29s %4d\n", "FUNCTION",        ++max
+  printf "#define TK_%-29s %4d\n", "COLUMN",          ++max
+  printf "#define TK_%-29s %4d\n", "AGG_FUNCTION",    ++max
+  printf "#define TK_%-29s %4d\n", "AGG_COLUMN",      ++max
+  printf "#define TK_%-29s %4d\n", "CONST_FUNC",      ++max
 }
diff --git a/main.mk b/main.mk
index 1b23afc131a3067bb79367daecd9793f0c45c5d3..d96773fb0d6f5ae54c7e5b613501583dc032ab21 100644 (file)
--- a/main.mk
+++ b/main.mk
@@ -48,36 +48,21 @@ TCCX = $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP) -I$(TOP)/ext/rtree
 
 # Object files for the SQLite library.
 #
-LIBOBJ+= alter.o analyze.o attach.o auth.o bitvec.o btmutex.o btree.o build.o \
+LIBOBJ+= alter.o analyze.o attach.o auth.o \
+         bitvec.o btmutex.o btree.o build.o \
          callback.o complete.o date.o delete.o \
-         expr.o fault.o func2.o global.o hash.o insert.o journal.o loadext.o \
+         expr.o fault.o func2.o global.o hash.o \
+         icu.o insert.o journal.o legacy.o loadext.o \
          main.o malloc.o mem1.o mem2.o mem3.o mem4.o mem5.o mem6.o \
          mutex.o mutex_os2.o mutex_unix.o mutex_w32.o \
          opcodes.o os.o os_os2.o os_unix.o os_win.o \
-         pager.o parse.o pragma.o prepare.o printf.o random.o \
-         select.o status.o table.o $(TCLOBJ) tokenize.o trigger.o \
+         pager.o parse.o pcache.o pragma.o prepare.o printf.o \
+         random.o resolve.o rtree.o select.o status.o \
+         table.o tokenize.o trigger.o \
          update.o util.o vacuum.o \
          vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbefifo.o vdbemem.o \
-         where.o utf.o legacy.o vtab.o rtree.o icu.o pcache.o
-
-EXTOBJ = icu.o
-EXTOBJ += fts1.o \
-         fts1_hash.o \
-         fts1_tokenizer1.o \
-         fts1_porter.o
-EXTOBJ += fts2.o \
-         fts2_hash.o \
-         fts2_icu.o \
-         fts2_porter.o \
-          fts2_tokenizer.o \
-         fts2_tokenizer1.o
-EXTOBJ += fts3.o \
-         fts3_hash.o \
-         fts3_icu.o \
-         fts3_porter.o \
-          fts3_tokenizer.o \
-         fts3_tokenizer1.o
-EXTOBJ += rtree.o
+         walker.o where.o utf.o vtab.o
+
 
 # All of the source code files.
 #
@@ -128,10 +113,13 @@ SRC = \
   $(TOP)/src/pager.c \
   $(TOP)/src/pager.h \
   $(TOP)/src/parse.y \
+  $(TOP)/src/pcache.c \
+  $(TOP)/src/pcache.h \
   $(TOP)/src/pragma.c \
   $(TOP)/src/prepare.c \
   $(TOP)/src/printf.c \
   $(TOP)/src/random.c \
+  $(TOP)/src/resolve.c \
   $(TOP)/src/select.c \
   $(TOP)/src/status.c \
   $(TOP)/src/shell.c \
@@ -157,6 +145,7 @@ SRC = \
   $(TOP)/src/pcache.c \
   $(TOP)/src/vdbeInt.h \
   $(TOP)/src/vtab.c \
+  $(TOP)/src/walker.c \
   $(TOP)/src/where.c
 
 # Source code for extensions
index 5412048800c627d87213d86bae80d199376694ee..2d7de04eaa1d9188869fc061101dd01862c12fe1 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,12 +1,12 @@
-C When\sa\s"pragma\smain.table_info(...)"\sis\sissued,\sconsider\sonly\stables\sfrom\sthe\smain\sdatabase,\snot\sthe\stemp\sdb.\sTicket\s#3320.\s(CVS\s5568)
-D 2008-08-20T16:34:24
+C Refactor\sthe\sname\sresolution\sprocedures\sin\sthe\scode\sgenerator.\s(CVS\s5569)
+D 2008-08-20T16:35:10
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
-F Makefile.in e277c1f6dee97c18ef2f64db608da63eea4cc933
+F Makefile.in 6682017e315b9c518b5c49dbe8bd19164146abe6
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
 F README b974cdc3f9f12b87e851b04e75996d720ebf81ac
 F VERSION 1d5b2c9192236ed2c6bad659a7c2d1662e39e7b9
 F aclocal.m4 7d02b11fed45174e11156144227278deb6236eea
-F addopcodes.awk 48a2ffae0a6fb191ae9e42e69a90b15d973e0339
+F addopcodes.awk 215333be9d99c260e076c3080a81dba3ae928c45
 F art/2005osaward.gif 0d1851b2a7c1c9d0ccce545f3e14bca42d7fd248
 F art/SQLite.eps 9b43cc99cfd2be687d386faea6862ea68d6a72b2
 F art/SQLite.gif 1bbb94484963f1382e27e1c5e86dd0c1061eba2b
@@ -76,7 +76,7 @@ F ext/rtree/rtree_util.tcl ee0a0311eb12175319d78bfb37302320496cee6e
 F ext/rtree/viewrtree.tcl 09526398dae87a5a87c5aac2b3854dbaf8376869
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
 F ltmain.sh 09fe5815427dc7d0abb188bbcdf0e34896577210
-F main.mk ec8a5d47c4cb447dc666472528a7e8da91384a57
+F main.mk 4bb354f1e952a13ee8a02b42837b37c4b198d9a7
 F mkdll.sh 79d1ed6ae221c10589dd969f130f8a3cccfffbb7
 F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
 F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac
@@ -92,30 +92,30 @@ F sqlite3.def a1be7b9a4b8b51ac41c6ff6e8e44a14ef66b338b
 F sqlite3.pc.in 32b8a014799c2028c8e0c9cc5659718262fc493f
 F src/alter.c f462b637bac6c6576a9b7bc6da59c7a82ed5aab2
 F src/analyze.c 747ce8cb6b318bb0d0576cfb5277aed98cbbeb5c
-F src/attach.c a85c14612e7e3410e0c3d2e0241832fa9688bd14
+F src/attach.c db3f4a60538733c1e4dcb9d0217a6e0d6ccd615b
 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
 F src/bitvec.c 95c86bd18d8fedf0533f5af196192546e10a7e7d
 F src/btmutex.c 709cad2cdca0afd013f0f612363810e53f59ec53
 F src/btree.c c536edea3dd8a9f5f56101ca66cd5dfe699a5d7b
 F src/btree.h 6371c5e599fab391a150c96afbc10062b276d107
 F src/btreeInt.h ab18c7b4980314e9e4b402e5dcde09f3c2545576
-F src/build.c 931ed94fd3bbd67b6ac9d5ac6a45dc01e9f01726
+F src/build.c 160c71acca8f643f436ed6c1ee2f684c88df4dfe
 F src/callback.c 1b1a5c580cdf7d83db24001bf8e5c09e2b08658f
 F src/complete.c cb14e06dbe79dee031031f0d9e686ff306afe07c
 F src/date.c 52a54811218a76da6235420f532ece841159a96d
-F src/delete.c 0d115c173863b3c688c3083ef7857c7f2e9f7a18
-F src/expr.c 278d3950f55e04a2486e7b8dede3713a2ed6c0e1
+F src/delete.c 5105c67c741f934379722de5e11fdd73ea4d82b5
+F src/expr.c 4651d08422474f7e4bcb9a35da00c33ebe719a2d
 F src/fault.c 3638519d1e0b82bccfafcb9f5ff491918b28f8e1
 F src/func.c d97ff7b72f3ddcd88970048e2894954a3f5b01d8
 F src/global.c b9c96ee2317a6e1391763c7db1098a6473a91863
 F src/hash.c eb64e48f3781100e5934f759fbe72a63a8fe78cb
 F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
 F src/hwtime.h 4a1d45f4cae1f402ea19686acf24acf4f0cb53cb
-F src/insert.c 89cd9af52a5ea6fb7d0cfc9c3b935d6406c360c4
+F src/insert.c 110cca7845ed5a66c08fdd413b02e706ae34455f
 F src/journal.c cffd2cd214e58c0e99c3ff632b3bee6c7cbb260e
 F src/legacy.c aac57bd984e666059011ea01ec4383892a253be3
 F src/loadext.c eb1fe4f44d7c8ff53fc0c6a4388ab79fbd34cd64
-F src/main.c 64df39151a77bf521cee8ef54efc3c71328d8bb4
+F src/main.c aaf5af6ffe2c05f8ea4d75a850581a68ac529fa0
 F src/malloc.c 56918cddc4da7a0590eef4a2497e97b781f5c25f
 F src/md5.c 008216bbb5d34c6fbab5357aa68575ad8a31516a
 F src/mem1.c 3a7fe31d8290baa3bb203af72f7dfd6323966bcd
@@ -137,18 +137,19 @@ F src/os_unix.c fe0dbc35bcd3de49e46b132abfc0f45d6dd6a864
 F src/os_win.c aefe9ee26430678a19a058a874e4e2bd91398142
 F src/pager.c 9f813a8f26680ff510335e2bbd01910b2a77277b
 F src/pager.h fb9376af5ba8e1eb78ee3b4f15eb0f60658ffd65
-F src/parse.y 84003422b2862f82bd187dfa2399557fd1f4ecbe
+F src/parse.y d0f76d2cb8d6883d5600dc20beb961a6022b94b8
 F src/pcache.c c1a9abb5e2aa3d1d52a2995c8e0a36535d4d1bc2
 F src/pcache.h 71ade7a84ed87d9d20507315260b1d91808d7c9a
 F src/pragma.c f5b271b090af7fcedd308d7c5807a5503f7a853d
-F src/prepare.c fceb567b359daaa6c6e2a4d04a01dec01ac0c907
+F src/prepare.c c197041e0c4770672cda75e6bfe10242f885e510
 F src/printf.c 2e984b2507291a7e16d89dc9bb60582904f6247d
 F src/random.c 5c754319d38abdd6acd74601ee0105504adc508a
-F src/select.c defdb8cdf7d2d8e1e0df117e50af6378fdaf1329
+F src/resolve.c e688f240bdacf4003047c2b023c3a4ee3a3eca98
+F src/select.c 0a0ed2d14bfa216c1584fa8516e8820115b1047b
 F src/shell.c d83b578a8ccdd3e0e7fef4388a0887ce9f810967
 F src/sqlite.h.in 54e51c22e2294c5989156b0aec87aa44168ac1f0
 F src/sqlite3ext.h 1e3887c9bd3ae66cb599e922824b04cd0d0f2c3e
-F src/sqliteInt.h e49782bc45092732795297d83331b1855eb234b3
+F src/sqliteInt.h d1ddf30df8d7eb3e15e7d70ebe347e0c17255165
 F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
 F src/status.c 8caa772cd9310bc297280f7cf0ede4d69ed5b801
 F src/table.c 22744786199c9195720c15a7a42cb97b2e2728d8
@@ -180,8 +181,8 @@ F src/test_server.c f0a403b5f699c09bd2b1236b6f69830fd6221f6b
 F src/test_tclvar.c 9e42fa59d3d2f064b7ab8628e7ab2dc8a9fe93d4
 F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730
 F src/tokenize.c d16ca0e9944161c76d2e4c11dc379ec88189b93b
-F src/trigger.c b61aaf7bff8e3763b234dbf46a1a64fb88a34e64
-F src/update.c 79b77a3cc8ed5f8903a7f37055fcedd69388dcae
+F src/trigger.c 649940b5bf5838a33721fb72372e7c9d1faf56a9
+F src/update.c 9e3786e76825bd7fa22528556cc1c467cd428075
 F src/utf.c c63e6f69082f85c19ab88d62dedaf91d71ac1a50
 F src/util.c afe659ccc05d1f8af9e8631dabfec3ee3a7144af
 F src/vacuum.c ef342828002debc97514617af3424aea8ef8522c
@@ -189,12 +190,13 @@ F src/vdbe.c e2dd0c78c5579e23db49ed8265f0b44d7b22c51d
 F src/vdbe.h 17bcc2b41082f9b99718b3757cbf97145a72023a
 F src/vdbeInt.h b48c74d86a9fb62b707a3186ccca76bb32f1c6be
 F src/vdbeapi.c f21971516880fd3a10821b2cdd0e64a5a63952c9
-F src/vdbeaux.c 3e2e1f36c25eae32bdd605456c8be99f73e71eaf
+F src/vdbeaux.c ba13cc1e663d3dd12a720d108eac14d792ad7680
 F src/vdbeblob.c f93110888ddc246215e9ba1f831d3d375bfd8355
 F src/vdbefifo.c 20fda2a7c4c0bcee1b90eb7e545fefcdbf2e1de7
 F src/vdbemem.c c37b2a266a49eaf0c0f5080157f9f1a908fdaac3
-F src/vtab.c edf8edb55dc93ec4bfe8b3f10213cf6c025edb9c
-F src/where.c a800184a2d023b15d6f2758b7a6c7ab011258fee
+F src/vtab.c 527c180e9c5fca417c9167d02af4b5039f892b4b
+F src/walker.c 488c2660e13224ff70c0c82761118efb547f8f0d
+F src/where.c b156f2785538ed1783dbdd1f714d00ba21c1d5b1
 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/all.test 89e09ed0074083ac6f208dc3243429e8f89efb69
@@ -234,8 +236,8 @@ F test/capi3d.test 57d83b690d7364bde02cddbf8339a4b50d80ce23
 F test/cast.test ce8f14fc80f70b30ed984480cc0d8914a459e8f9
 F test/check.test 024ed399600b799160378cf9d9f436bdf5dfd184
 F test/collate1.test e3eaa48c21e150814be1a7b852d2a8af24458d04
-F test/collate2.test 701d9651c5707024fd86a20649af9ea55e2c0eb8
-F test/collate3.test 9ac82f7a3a7e839a245fc341ff1b7803d56cd41a
+F test/collate2.test 04cebe4a033be319d6ddbb3bbc69464e01700b49
+F test/collate3.test d28d2cfab2c3a3d4628ae4b2b7afc9965daa3b4c
 F test/collate4.test 4545554388daaa604e5b3def3aa2f7ed6d56e8da
 F test/collate5.test e54df13eb9e1140273680b3153c6e19b39e59888
 F test/collate6.test 8be65a182abaac8011a622131486dafb8076e907
@@ -348,7 +350,7 @@ F test/func.test 628dc9b321fc66dd6d055fca6525e157004744e1
 F test/fuzz.test 62fc19dd36a427777fd671b569df07166548628a
 F test/fuzz2.test ea38692ce2da99ad79fe0be5eb1a452c1c4d37bb
 F test/fuzz_common.tcl ff4bc2dfc465f6878f8e2d819620914365382731
-F test/fuzz_malloc.test 166b58dfd77cc04f6afeeaef0cfc1087abf134d1
+F test/fuzz_malloc.test 4eca9d345f06d5b0b0105f7a2ef9e7f22658827b
 F test/hook.test e17d4ed2843ba4ef9b234aa63e6f056bf88f9a19
 F test/icu.test f51d0f4407ff8bb1e872f51a0e8b08fdc5a6897e
 F test/in.test d49419c6df515852f477fa513f3317181d46bc92
@@ -463,8 +465,8 @@ F test/select1.test d0a4cad954fd41c030ec16ffbd2d08a4c0548742
 F test/select2.test 272a3d3e35b1d3a0760168ababf555e656357fc4
 F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
 F test/select4.test b64d5d248d008e1dc365f451c76090bde907e665
-F test/select5.test 1bddfe92ae0b00ca53dc2735d5d23ce6b9723c26
-F test/select6.test 1131113eb6ae398069a8bc2173eb6c9a2d8ff1cd
+F test/select5.test 2c5464283438e06531a1e8801c674279dd01dd04
+F test/select6.test faad87c6e691bf69a822b69cd6808137a34d19e8
 F test/select7.test 7906735805cfbee4dddc0bed4c14e68d7f5f9c5f
 F test/select8.test 391de11bdd52339c30580dabbbbe97e3e9a3c79d
 F test/select9.test b4007b15396cb7ba2615cab31e1973b572e43210
@@ -537,7 +539,7 @@ F test/tkt2686.test 08f0f584461bc4990376936daa0a9bd3e6e81671
 F test/tkt2767.test 2607e36e5577c699221b964e7bbc06dd794dd738
 F test/tkt2817.test 94646b604c7dbae7058782f6582c05e200700aa9
 F test/tkt2820.test 017fdee33aaef7abc092beab6088816f1942304b
-F test/tkt2822.test 202c169952e6cf285c45c1315b4cf4f30b845c69
+F test/tkt2822.test a2b27a58df62d1b2e712f91dbe42ad3b7e0e77cc
 F test/tkt2832.test 85cf382ff406de9de35534b86bc7227d609140c0
 F test/tkt2854.test a2bc584ac26bcebe174229e7a1ad4e6d43c3d569
 F test/tkt2920.test a8737380e4ae6424e00c0273dc12775704efbebf
@@ -606,7 +608,7 @@ F tool/memleak3.tcl 7707006ee908cffff210c98158788d85bb3fcdbf
 F tool/mkfunction.c a785a1970027bc7a833aa8afb43d6786a33c11ae
 F tool/mkkeywordhash.c ef93810fc41fb3d3dbacf9a33a29be88ea99ffa9
 F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
-F tool/mksqlite3c.tcl 5b4b6f974d9d761477dfb24e2a0c578b27419ef5
+F tool/mksqlite3c.tcl f5645b2e7ee71fa9633ca5c90ada3ae9120b4a3c
 F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87
 F tool/omittest.tcl 5a25ea687df5da8dd9b94bf1683f5cf2c210e51d
 F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
@@ -621,7 +623,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
-P 66ff55efd688703fe99143e4c17e8d5f119d0690
-R 0d247ce1493fb2ede2a50a5e354297e6
-U danielk1977
-Z 33cfa9a4ef54e991c9419dcc5b206894
+P d0cfbbbaeef7b8ce9f73c6cd58888989a2df5b1f
+R fc873a52e1600a91cb8096b210a57fcf
+U drh
+Z 6f25e8fa0d3669556e1fb27761e93a30
index 72d7e75fe387488cb8d75d9cde1662fe490c2822..ebc3306bdd94cf49c5b23830bdf6c1f6495c66e1 100644 (file)
@@ -1 +1 @@
-d0cfbbbaeef7b8ce9f73c6cd58888989a2df5b1f
\ No newline at end of file
+daf730d1defa78fb8b80a78f9108ac35a13e09f6
\ No newline at end of file
index b8668f52bb5a718c902a23326eaf9f2ecffec90c..9e7d5c79a37ff0b2caba54bb11e8342a8d4d00ea 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code used to implement the ATTACH and DETACH commands.
 **
-** $Id: attach.c,v 1.77 2008/07/28 19:34:53 drh Exp $
+** $Id: attach.c,v 1.78 2008/08/20 16:35:10 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -39,7 +39,7 @@ static int resolveAttachExpr(NameContext *pName, Expr *pExpr)
   int rc = SQLITE_OK;
   if( pExpr ){
     if( pExpr->op!=TK_ID ){
-      rc = sqlite3ExprResolveNames(pName, pExpr);
+      rc = sqlite3ResolveExprNames(pName, pExpr);
       if( rc==SQLITE_OK && !sqlite3ExprIsConstant(pExpr) ){
         sqlite3ErrorMsg(pName->pParse, "invalid name: \"%T\"", &pExpr->span);
         return SQLITE_ERROR;
index da4560a22bf86849eb53aa5e91422afeaff400ac..91c8323c7031e984b1a9dba7f92e4a8fe4e0183c 100644 (file)
@@ -22,7 +22,7 @@
 **     COMMIT
 **     ROLLBACK
 **
-** $Id: build.c,v 1.495 2008/08/11 18:44:58 drh Exp $
+** $Id: build.c,v 1.496 2008/08/20 16:35:10 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1140,12 +1140,12 @@ void sqlite3AddPrimaryKey(
   char *zType = 0;
   int iCol = -1, i;
   if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit;
-  if( pTab->hasPrimKey ){
+  if( pTab->tabFlags & TF_HasPrimaryKey ){
     sqlite3ErrorMsg(pParse, 
       "table \"%s\" has more than one primary key", pTab->zName);
     goto primary_key_exit;
   }
-  pTab->hasPrimKey = 1;
+  pTab->tabFlags |= TF_HasPrimaryKey;
   if( pList==0 ){
     iCol = pTab->nCol - 1;
     pTab->aCol[iCol].isPrimKey = 1;
@@ -1169,7 +1169,8 @@ void sqlite3AddPrimaryKey(
         && sortOrder==SQLITE_SO_ASC ){
     pTab->iPKey = iCol;
     pTab->keyConf = onError;
-    pTab->autoInc = autoInc;
+    assert( autoInc==0 || autoInc==1 );
+    pTab->tabFlags |= autoInc*TF_Autoincrement;
   }else if( autoInc ){
 #ifndef SQLITE_OMIT_AUTOINCREMENT
     sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an "
@@ -1456,7 +1457,7 @@ void sqlite3EndTable(
     sNC.pParse = pParse;
     sNC.pSrcList = &sSrc;
     sNC.isCheck = 1;
-    if( sqlite3ExprResolveNames(&sNC, p->pCheck) ){
+    if( sqlite3ResolveExprNames(&sNC, p->pCheck) ){
       return;
     }
   }
@@ -1529,10 +1530,10 @@ void sqlite3EndTable(
       sqlite3VdbeChangeP5(v, 1);
       pParse->nTab = 2;
       sqlite3SelectDestInit(&dest, SRT_Table, 1);
-      sqlite3Select(pParse, pSelect, &dest, 0, 0, 0);
+      sqlite3Select(pParse, pSelect, &dest);
       sqlite3VdbeAddOp1(v, OP_Close, 1);
       if( pParse->nErr==0 ){
-        pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSelect);
+        pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect);
         if( pSelTab==0 ) return;
         assert( p->aCol==0 );
         p->nCol = pSelTab->nCol;
@@ -1578,7 +1579,7 @@ void sqlite3EndTable(
     /* Check to see if we need to create an sqlite_sequence table for
     ** keeping track of autoincrement keys.
     */
-    if( p->autoInc ){
+    if( p->tabFlags & TF_Autoincrement ){
       Db *pDb = &db->aDb[iDb];
       if( pDb->pSchema->pSeqTab==0 ){
         sqlite3NestedParse(pParse,
@@ -1774,10 +1775,10 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
 #ifndef SQLITE_OMIT_AUTHORIZATION
     xAuth = db->xAuth;
     db->xAuth = 0;
-    pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel);
+    pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
     db->xAuth = xAuth;
 #else
-    pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel);
+    pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
 #endif
     pParse->nTab = n;
     if( pSelTab ){
@@ -2066,7 +2067,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
     ** at the btree level, in case the sqlite_sequence table needs to
     ** move as a result of the drop (can happen in auto-vacuum mode).
     */
-    if( pTab->autoInc ){
+    if( pTab->tabFlags & TF_Autoincrement ){
       sqlite3NestedParse(pParse,
         "DELETE FROM %s.sqlite_sequence WHERE name=%Q",
         pDb->zName, pTab->zName
@@ -2503,9 +2504,10 @@ void sqlite3CreateIndex(
   ** specified collation sequence names.
   */
   for(i=0; i<pList->nExpr; i++){
-    Expr *pExpr = pList->a[i].pExpr;
-    if( pExpr ){
-      nExtra += (1 + strlen(pExpr->pColl->zName));
+    Expr *pExpr;
+    CollSeq *pColl;
+    if( (pExpr = pList->a[i].pExpr)!=0 && (pColl = pExpr->pColl)!=0 ){
+      nExtra += (1 + strlen(pColl->zName));
     }
   }
 
@@ -2572,7 +2574,7 @@ void sqlite3CreateIndex(
     ** break backwards compatibility - it needs to be a warning.
     */
     pIndex->aiColumn[i] = j;
-    if( pListItem->pExpr ){
+    if( pListItem->pExpr && pListItem->pExpr->pColl ){
       assert( pListItem->pExpr->pColl );
       zColl = zExtra;
       sqlite3_snprintf(nExtra, zExtra, "%s", pListItem->pExpr->pColl->zName);
index 26824241e234c710adf821f81f18ecf5532121b7..40aeb468129673176c2626d03cf21797e75f30d4 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** in order to generate code for DELETE FROM statements.
 **
-** $Id: delete.c,v 1.171 2008/07/28 19:34:53 drh Exp $
+** $Id: delete.c,v 1.172 2008/08/20 16:35:10 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -42,7 +42,8 @@ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
 ** writable return 0;
 */
 int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
-  if( (pTab->readOnly && (pParse->db->flags & SQLITE_WriteSchema)==0
+  if( ((pTab->tabFlags & TF_Readonly)!=0
+        && (pParse->db->flags & SQLITE_WriteSchema)==0
         && pParse->nested==0) 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
       || (pTab->pMod && pTab->pMod->pModule->xUpdate==0)
@@ -106,7 +107,7 @@ void sqlite3MaterializeView(
     pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
   }
   sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
-  sqlite3Select(pParse, pDup, &dest, 0, 0, 0);
+  sqlite3Select(pParse, pDup, &dest);
   sqlite3SelectDelete(db, pDup);
 }
 #endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */
@@ -254,7 +255,7 @@ void sqlite3DeleteFrom(
   memset(&sNC, 0, sizeof(sNC));
   sNC.pParse = pParse;
   sNC.pSrcList = pTabList;
-  if( sqlite3ExprResolveNames(&sNC, pWhere) ){
+  if( sqlite3ResolveExprNames(&sNC, pWhere) ){
     goto delete_from_cleanup;
   }
 
index 074e3649cc36d652468108745ce134c96147d395..b650035222de2dbc9517c6281482c747ed08464a 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains routines used for analyzing expressions and
 ** for generating VDBE code that evaluates expressions in SQLite.
 **
-** $Id: expr.c,v 1.388 2008/08/07 13:05:35 drh Exp $
+** $Id: expr.c,v 1.389 2008/08/20 16:35:10 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -43,6 +43,14 @@ char sqlite3ExprAffinity(Expr *pExpr){
     return sqlite3AffinityType(&pExpr->token);
   }
 #endif
+  if( (op==TK_COLUMN || op==TK_REGISTER) && pExpr->pTab!=0 ){
+    /* op==TK_REGISTER && pExpr->pTab!=0 happens when pExpr was originally
+    ** a TK_COLUMN but was previously evaluated and cached in a register */
+    int j = pExpr->iColumn;
+    if( j<0 ) return SQLITE_AFF_INTEGER;
+    assert( pExpr->pTab && j<pExpr->pTab->nCol );
+    return pExpr->pTab->aCol[j].affinity;
+  }
   return pExpr->affinity;
 }
 
@@ -53,11 +61,11 @@ char sqlite3ExprAffinity(Expr *pExpr){
 ** flag.  An explicit collating sequence will override implicit
 ** collating sequences.
 */
-Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pName){
+Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pCollName){
   char *zColl = 0;            /* Dequoted name of collation sequence */
   CollSeq *pColl;
   sqlite3 *db = pParse->db;
-  zColl = sqlite3NameFromToken(db, pName);
+  zColl = sqlite3NameFromToken(db, pCollName);
   if( pExpr && zColl ){
     pColl = sqlite3LocateCollSeq(pParse, zColl, -1);
     if( pColl ){
@@ -75,13 +83,29 @@ Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pName){
 */
 CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
   CollSeq *pColl = 0;
-  if( pExpr ){
+  Expr *p = pExpr;
+  while( p ){
     int op;
-    pColl = pExpr->pColl;
-    op = pExpr->op;
-    if( (op==TK_CAST || op==TK_UPLUS) && !pColl ){
-      return sqlite3ExprCollSeq(pParse, pExpr->pLeft);
+    pColl = p->pColl;
+    if( pColl ) break;
+    op = p->op;
+    if( (op==TK_COLUMN || op==TK_REGISTER) && p->pTab!=0 ){
+      /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
+      ** a TK_COLUMN but was previously evaluated and cached in a register */
+      const char *zColl;
+      int j = p->iColumn;
+      if( j>=0 ){
+        sqlite3 *db = pParse->db;
+        zColl = p->pTab->aCol[j].zColl;
+        pColl = sqlite3FindCollSeq(db, ENC(db), zColl, -1, 0);
+        pExpr->pColl = pColl;
+      }
+      break;
+    }
+    if( op!=TK_CAST && op!=TK_UPLUS ){
+      break;
     }
+    p = p->pLeft;
   }
   if( sqlite3CheckCollSeq(pParse, pColl) ){ 
     pColl = 0;
@@ -260,7 +284,7 @@ static int codeCompare(
 ** expression depth allowed. If it is not, leave an error message in
 ** pParse.
 */
-static int checkExprHeight(Parse *pParse, int nHeight){
+int sqlite3ExprCheckHeight(Parse *pParse, int nHeight){
   int rc = SQLITE_OK;
   int mxHeight = pParse->db->aLimit[SQLITE_LIMIT_EXPR_DEPTH];
   if( nHeight>mxHeight ){
@@ -332,7 +356,7 @@ static void exprSetHeight(Expr *p){
 */
 void sqlite3ExprSetHeight(Parse *pParse, Expr *p){
   exprSetHeight(p);
-  checkExprHeight(pParse, p->nHeight);
+  sqlite3ExprCheckHeight(pParse, p->nHeight);
 }
 
 /*
@@ -345,7 +369,6 @@ int sqlite3SelectExprHeight(Select *p){
   return nHeight;
 }
 #else
-  #define checkExprHeight(x,y)
   #define exprSetHeight(y)
 #endif /* SQLITE_MAX_EXPR_DEPTH>0 */
 
@@ -413,7 +436,7 @@ Expr *sqlite3PExpr(
 ){
   Expr *p = sqlite3Expr(pParse->db, op, pLeft, pRight, pToken);
   if( p ){
-    checkExprHeight(pParse, p->nHeight);
+    sqlite3ExprCheckHeight(pParse, p->nHeight);
   }
   return p;
 }
@@ -606,7 +629,6 @@ void sqlite3DequoteExpr(sqlite3 *db, Expr *p){
   sqlite3Dequote((char*)p->token.z);
 }
 
-
 /*
 ** The following group of routines make deep copies of expressions,
 ** expression lists, ID lists, and select statements.  The copies can
@@ -677,8 +699,8 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p){
             || db->mallocFailed );
     pItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
     pItem->sortOrder = pOldItem->sortOrder;
-    pItem->isAgg = pOldItem->isAgg;
     pItem->done = 0;
+    pItem->iCol = pOldItem->iCol;
   }
   return pNew;
 }
@@ -746,7 +768,6 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *p){
   if( p==0 ) return 0;
   pNew = sqlite3DbMallocRaw(db, sizeof(*p) );
   if( pNew==0 ) return 0;
-  pNew->isDistinct = p->isDistinct;
   pNew->pEList = sqlite3ExprListDup(db, p->pEList);
   pNew->pSrc = sqlite3SrcListDup(db, p->pSrc);
   pNew->pWhere = sqlite3ExprDup(db, p->pWhere);
@@ -759,10 +780,7 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *p){
   pNew->pOffset = sqlite3ExprDup(db, p->pOffset);
   pNew->iLimit = 0;
   pNew->iOffset = 0;
-  pNew->isResolved = p->isResolved;
-  pNew->isAgg = p->isAgg;
-  pNew->usesEphm = 0;
-  pNew->disallowOrderBy = 0;
+  pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
   pNew->pRightmost = 0;
   pNew->addrOpenEphm[0] = -1;
   pNew->addrOpenEphm[1] = -1;
@@ -856,92 +874,33 @@ void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
 }
 
 /*
-** Walk an expression tree.  Call xFunc for each node visited.  xFunc
-** is called on the node before xFunc is called on the nodes children.
+** These routines are Walker callbacks.  Walker.u.pi is a pointer
+** to an integer.  These routines are checking an expression to see
+** if it is a constant.  Set *Walker.u.pi to 0 if the expression is
+** not constant.
 **
-** The return value from xFunc determines whether the tree walk continues.
-** 0 means continue walking the tree.  1 means do not walk children
-** of the current node but continue with siblings.  2 means abandon
-** the tree walk completely.
+** These callback routines are used to implement the following:
 **
-** The return value from this routine is 1 to abandon the tree walk
-** and 0 to continue.
+**     sqlite3ExprIsConstant()
+**     sqlite3ExprIsConstantNotJoin()
+**     sqlite3ExprIsConstantOrFunction()
 **
-** NOTICE:  This routine does *not* descend into subqueries.
-*/
-static int walkExprList(ExprList *, int (*)(void *, Expr*), void *);
-static int walkExprTree(Expr *pExpr, int (*xFunc)(void*,Expr*), void *pArg){
-  int rc;
-  if( pExpr==0 ) return 0;
-  rc = (*xFunc)(pArg, pExpr);
-  if( rc==0 ){
-    if( walkExprTree(pExpr->pLeft, xFunc, pArg) ) return 1;
-    if( walkExprTree(pExpr->pRight, xFunc, pArg) ) return 1;
-    if( walkExprList(pExpr->pList, xFunc, pArg) ) return 1;
-  }
-  return rc>1;
-}
-
-/*
-** Call walkExprTree() for every expression in list p.
 */
-static int walkExprList(ExprList *p, int (*xFunc)(void *, Expr*), void *pArg){
-  int i;
-  struct ExprList_item *pItem;
-  if( !p ) return 0;
-  for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){
-    if( walkExprTree(pItem->pExpr, xFunc, pArg) ) return 1;
-  }
-  return 0;
-}
-
-/*
-** Call walkExprTree() for every expression in Select p, not including
-** expressions that are part of sub-selects in any FROM clause or the LIMIT
-** or OFFSET expressions..
-*/
-static int walkSelectExpr(Select *p, int (*xFunc)(void *, Expr*), void *pArg){
-  walkExprList(p->pEList, xFunc, pArg);
-  walkExprTree(p->pWhere, xFunc, pArg);
-  walkExprList(p->pGroupBy, xFunc, pArg);
-  walkExprTree(p->pHaving, xFunc, pArg);
-  walkExprList(p->pOrderBy, xFunc, pArg);
-  if( p->pPrior ){
-    walkSelectExpr(p->pPrior, xFunc, pArg);
-  }
-  return 0;
-}
-
+static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
 
-/*
-** This routine is designed as an xFunc for walkExprTree().
-**
-** pArg is really a pointer to an integer.  If we can tell by looking
-** at pExpr that the expression that contains pExpr is not a constant
-** expression, then set *pArg to 0 and return 2 to abandon the tree walk.
-** If pExpr does does not disqualify the expression from being a constant
-** then do nothing.
-**
-** After walking the whole tree, if no nodes are found that disqualify
-** the expression as constant, then we assume the whole expression
-** is constant.  See sqlite3ExprIsConstant() for additional information.
-*/
-static int exprNodeIsConstant(void *pArg, Expr *pExpr){
-  int *pN = (int*)pArg;
-
-  /* If *pArg is 3 then any term of the expression that comes from
+  /* If pWalker->u.i is 3 then any term of the expression that comes from
   ** the ON or USING clauses of a join disqualifies the expression
   ** from being considered constant. */
-  if( (*pN)==3 && ExprHasAnyProperty(pExpr, EP_FromJoin) ){
-    *pN = 0;
-    return 2;
+  if( pWalker->u.i==3 && ExprHasAnyProperty(pExpr, EP_FromJoin) ){
+    pWalker->u.i = 0;
+    return WRC_Abort;
   }
 
   switch( pExpr->op ){
     /* Consider functions to be constant if all their arguments are constant
-    ** and *pArg==2 */
+    ** and pWalker->u.i==2 */
     case TK_FUNCTION:
-      if( (*pN)==2 ) return 0;
+      if( pWalker->u.i==2 ) return 0;
       /* Fall through */
     case TK_ID:
     case TK_COLUMN:
@@ -959,17 +918,29 @@ static int exprNodeIsConstant(void *pArg, Expr *pExpr){
       testcase( pExpr->op==TK_DOT );
       testcase( pExpr->op==TK_AGG_FUNCTION );
       testcase( pExpr->op==TK_AGG_COLUMN );
-      *pN = 0;
-      return 2;
+      pWalker->u.i = 0;
+      return WRC_Abort;
     case TK_IN:
       if( pExpr->pSelect ){
-        *pN = 0;
-        return 2;
+        pWalker->u.i = 0;
+        return WRC_Abort;
       }
     default:
-      return 0;
+      return WRC_Continue;
   }
 }
+static int selectNodeIsConstant(Walker *pWalker, Select *pSelect){
+  pWalker->u.i = 0;
+  return WRC_Abort;
+}
+static int exprIsConst(Expr *p, int initFlag){
+  Walker w;
+  w.u.i = initFlag;
+  w.xExprCallback = exprNodeIsConstant;
+  w.xSelectCallback = selectNodeIsConstant;
+  sqlite3WalkExpr(&w, p);
+  return w.u.i;
+}
 
 /*
 ** Walk an expression tree.  Return 1 if the expression is constant
@@ -980,9 +951,7 @@ static int exprNodeIsConstant(void *pArg, Expr *pExpr){
 ** a constant.
 */
 int sqlite3ExprIsConstant(Expr *p){
-  int isConst = 1;
-  walkExprTree(p, exprNodeIsConstant, &isConst);
-  return isConst;
+  return exprIsConst(p, 1);
 }
 
 /*
@@ -992,9 +961,7 @@ int sqlite3ExprIsConstant(Expr *p){
 ** an ON or USING clause.
 */
 int sqlite3ExprIsConstantNotJoin(Expr *p){
-  int isConst = 3;
-  walkExprTree(p, exprNodeIsConstant, &isConst);
-  return isConst!=0;
+  return exprIsConst(p, 3);
 }
 
 /*
@@ -1007,9 +974,7 @@ int sqlite3ExprIsConstantNotJoin(Expr *p){
 ** a constant.
 */
 int sqlite3ExprIsConstantOrFunction(Expr *p){
-  int isConst = 2;
-  walkExprTree(p, exprNodeIsConstant, &isConst);
-  return isConst!=0;
+  return exprIsConst(p, 2);
 }
 
 /*
@@ -1061,547 +1026,6 @@ int sqlite3IsRowid(const char *z){
   return 0;
 }
 
-/*
-** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
-** that name in the set of source tables in pSrcList and make the pExpr 
-** expression node refer back to that source column.  The following changes
-** are made to pExpr:
-**
-**    pExpr->iDb           Set the index in db->aDb[] of the database holding
-**                         the table.
-**    pExpr->iTable        Set to the cursor number for the table obtained
-**                         from pSrcList.
-**    pExpr->iColumn       Set to the column number within the table.
-**    pExpr->op            Set to TK_COLUMN.
-**    pExpr->pLeft         Any expression this points to is deleted
-**    pExpr->pRight        Any expression this points to is deleted.
-**
-** The pDbToken is the name of the database (the "X").  This value may be
-** NULL meaning that name is of the form Y.Z or Z.  Any available database
-** can be used.  The pTableToken is the name of the table (the "Y").  This
-** value can be NULL if pDbToken is also NULL.  If pTableToken is NULL it
-** means that the form of the name is Z and that columns from any table
-** can be used.
-**
-** If the name cannot be resolved unambiguously, leave an error message
-** in pParse and return non-zero.  Return zero on success.
-*/
-static int lookupName(
-  Parse *pParse,       /* The parsing context */
-  Token *pDbToken,     /* Name of the database containing table, or NULL */
-  Token *pTableToken,  /* Name of table containing column, or NULL */
-  Token *pColumnToken, /* Name of the column. */
-  NameContext *pNC,    /* The name context used to resolve the name */
-  Expr *pExpr          /* Make this EXPR node point to the selected column */
-){
-  char *zDb = 0;       /* Name of the database.  The "X" in X.Y.Z */
-  char *zTab = 0;      /* Name of the table.  The "Y" in X.Y.Z or Y.Z */
-  char *zCol = 0;      /* Name of the column.  The "Z" */
-  int i, j;            /* Loop counters */
-  int cnt = 0;         /* Number of matching column names */
-  int cntTab = 0;      /* Number of matching table names */
-  sqlite3 *db = pParse->db;  /* The database */
-  struct SrcList_item *pItem;       /* Use for looping over pSrcList items */
-  struct SrcList_item *pMatch = 0;  /* The matching pSrcList item */
-  NameContext *pTopNC = pNC;        /* First namecontext in the list */
-  Schema *pSchema = 0;              /* Schema of the expression */
-
-  assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */
-  zDb = sqlite3NameFromToken(db, pDbToken);
-  zTab = sqlite3NameFromToken(db, pTableToken);
-  zCol = sqlite3NameFromToken(db, pColumnToken);
-  if( db->mallocFailed ){
-    goto lookupname_end;
-  }
-
-  pExpr->iTable = -1;
-  while( pNC && cnt==0 ){
-    ExprList *pEList;
-    SrcList *pSrcList = pNC->pSrcList;
-
-    if( pSrcList ){
-      for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
-        Table *pTab;
-        int iDb;
-        Column *pCol;
-  
-        pTab = pItem->pTab;
-        assert( pTab!=0 );
-        iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
-        assert( pTab->nCol>0 );
-        if( zTab ){
-          if( pItem->zAlias ){
-            char *zTabName = pItem->zAlias;
-            if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
-          }else{
-            char *zTabName = pTab->zName;
-            if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
-            if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){
-              continue;
-            }
-          }
-        }
-        if( 0==(cntTab++) ){
-          pExpr->iTable = pItem->iCursor;
-          pSchema = pTab->pSchema;
-          pMatch = pItem;
-        }
-        for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
-          if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
-            const char *zColl = pTab->aCol[j].zColl;
-            IdList *pUsing;
-            cnt++;
-            pExpr->iTable = pItem->iCursor;
-            pMatch = pItem;
-            pSchema = pTab->pSchema;
-            /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
-            pExpr->iColumn = j==pTab->iPKey ? -1 : j;
-            pExpr->affinity = pTab->aCol[j].affinity;
-            if( (pExpr->flags & EP_ExpCollate)==0 ){
-              pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
-            }
-            if( i<pSrcList->nSrc-1 ){
-              if( pItem[1].jointype & JT_NATURAL ){
-                /* If this match occurred in the left table of a natural join,
-                ** then skip the right table to avoid a duplicate match */
-                pItem++;
-                i++;
-              }else if( (pUsing = pItem[1].pUsing)!=0 ){
-                /* If this match occurs on a column that is in the USING clause
-                ** of a join, skip the search of the right table of the join
-                ** to avoid a duplicate match there. */
-                int k;
-                for(k=0; k<pUsing->nId; k++){
-                  if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ){
-                    pItem++;
-                    i++;
-                    break;
-                  }
-                }
-              }
-            }
-            break;
-          }
-        }
-      }
-    }
-
-#ifndef SQLITE_OMIT_TRIGGER
-    /* If we have not already resolved the name, then maybe 
-    ** it is a new.* or old.* trigger argument reference
-    */
-    if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
-      TriggerStack *pTriggerStack = pParse->trigStack;
-      Table *pTab = 0;
-      u32 *piColMask;
-      if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){
-        pExpr->iTable = pTriggerStack->newIdx;
-        assert( pTriggerStack->pTab );
-        pTab = pTriggerStack->pTab;
-        piColMask = &(pTriggerStack->newColMask);
-      }else if( pTriggerStack->oldIdx != -1 && sqlite3StrICmp("old", zTab)==0 ){
-        pExpr->iTable = pTriggerStack->oldIdx;
-        assert( pTriggerStack->pTab );
-        pTab = pTriggerStack->pTab;
-        piColMask = &(pTriggerStack->oldColMask);
-      }
-
-      if( pTab ){ 
-        int iCol;
-        Column *pCol = pTab->aCol;
-
-        pSchema = pTab->pSchema;
-        cntTab++;
-        for(iCol=0; iCol < pTab->nCol; iCol++, pCol++) {
-          if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
-            const char *zColl = pTab->aCol[iCol].zColl;
-            cnt++;
-            pExpr->iColumn = iCol==pTab->iPKey ? -1 : iCol;
-            pExpr->affinity = pTab->aCol[iCol].affinity;
-            if( (pExpr->flags & EP_ExpCollate)==0 ){
-              pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
-            }
-            pExpr->pTab = pTab;
-            if( iCol>=0 ){
-              testcase( iCol==31 );
-              testcase( iCol==32 );
-              *piColMask |= ((u32)1<<iCol) | (iCol>=32?0xffffffff:0);
-            }
-            break;
-          }
-        }
-      }
-    }
-#endif /* !defined(SQLITE_OMIT_TRIGGER) */
-
-    /*
-    ** Perhaps the name is a reference to the ROWID
-    */
-    if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
-      cnt = 1;
-      pExpr->iColumn = -1;
-      pExpr->affinity = SQLITE_AFF_INTEGER;
-    }
-
-    /*
-    ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
-    ** might refer to an result-set alias.  This happens, for example, when
-    ** we are resolving names in the WHERE clause of the following command:
-    **
-    **     SELECT a+b AS x FROM table WHERE x<10;
-    **
-    ** In cases like this, replace pExpr with a copy of the expression that
-    ** forms the result set entry ("a+b" in the example) and return immediately.
-    ** Note that the expression in the result set should have already been
-    ** resolved by the time the WHERE clause is resolved.
-    */
-    if( cnt==0 && (pEList = pNC->pEList)!=0 && zTab==0 ){
-      for(j=0; j<pEList->nExpr; j++){
-        char *zAs = pEList->a[j].zName;
-        if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
-          Expr *pDup, *pOrig;
-          assert( pExpr->pLeft==0 && pExpr->pRight==0 );
-          assert( pExpr->pList==0 );
-          assert( pExpr->pSelect==0 );
-          pOrig = pEList->a[j].pExpr;
-          if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){
-            sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
-            sqlite3DbFree(db, zCol);
-            return 2;
-          }
-          pDup = sqlite3ExprDup(db, pOrig);
-          if( pExpr->flags & EP_ExpCollate ){
-            pDup->pColl = pExpr->pColl;
-            pDup->flags |= EP_ExpCollate;
-          }
-          if( pExpr->span.dyn ) sqlite3DbFree(db, (char*)pExpr->span.z);
-          if( pExpr->token.dyn ) sqlite3DbFree(db, (char*)pExpr->token.z);
-          memcpy(pExpr, pDup, sizeof(*pExpr));
-          sqlite3DbFree(db, pDup);
-          cnt = 1;
-          pMatch = 0;
-          assert( zTab==0 && zDb==0 );
-          goto lookupname_end_2;
-        }
-      } 
-    }
-
-    /* Advance to the next name context.  The loop will exit when either
-    ** we have a match (cnt>0) or when we run out of name contexts.
-    */
-    if( cnt==0 ){
-      pNC = pNC->pNext;
-    }
-  }
-
-  /*
-  ** If X and Y are NULL (in other words if only the column name Z is
-  ** supplied) and the value of Z is enclosed in double-quotes, then
-  ** Z is a string literal if it doesn't match any column names.  In that
-  ** case, we need to return right away and not make any changes to
-  ** pExpr.
-  **
-  ** Because no reference was made to outer contexts, the pNC->nRef
-  ** fields are not changed in any context.
-  */
-  if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){
-    sqlite3DbFree(db, zCol);
-    pExpr->op = TK_STRING;
-    return 0;
-  }
-
-  /*
-  ** cnt==0 means there was not match.  cnt>1 means there were two or
-  ** more matches.  Either way, we have an error.
-  */
-  if( cnt!=1 ){
-    const char *zErr;
-    zErr = cnt==0 ? "no such column" : "ambiguous column name";
-    if( zDb ){
-      sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol);
-    }else if( zTab ){
-      sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol);
-    }else{
-      sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
-    }
-    pTopNC->nErr++;
-  }
-
-  /* If a column from a table in pSrcList is referenced, then record
-  ** this fact in the pSrcList.a[].colUsed bitmask.  Column 0 causes
-  ** bit 0 to be set.  Column 1 sets bit 1.  And so forth.  If the
-  ** column number is greater than the number of bits in the bitmask
-  ** then set the high-order bit of the bitmask.
-  */
-  if( pExpr->iColumn>=0 && pMatch!=0 ){
-    int n = pExpr->iColumn;
-    testcase( n==sizeof(Bitmask)*8-1 );
-    if( n>=sizeof(Bitmask)*8 ){
-      n = sizeof(Bitmask)*8-1;
-    }
-    assert( pMatch->iCursor==pExpr->iTable );
-    pMatch->colUsed |= ((Bitmask)1)<<n;
-  }
-
-lookupname_end:
-  /* Clean up and return
-  */
-  sqlite3DbFree(db, zDb);
-  sqlite3DbFree(db, zTab);
-  sqlite3ExprDelete(db, pExpr->pLeft);
-  pExpr->pLeft = 0;
-  sqlite3ExprDelete(db, pExpr->pRight);
-  pExpr->pRight = 0;
-  pExpr->op = TK_COLUMN;
-lookupname_end_2:
-  sqlite3DbFree(db, zCol);
-  if( cnt==1 ){
-    assert( pNC!=0 );
-    sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
-    if( pMatch && !pMatch->pSelect ){
-      pExpr->pTab = pMatch->pTab;
-    }
-    /* Increment the nRef value on all name contexts from TopNC up to
-    ** the point where the name matched. */
-    for(;;){
-      assert( pTopNC!=0 );
-      pTopNC->nRef++;
-      if( pTopNC==pNC ) break;
-      pTopNC = pTopNC->pNext;
-    }
-    return 0;
-  } else {
-    return 1;
-  }
-}
-
-/*
-** This routine is designed as an xFunc for walkExprTree().
-**
-** Resolve symbolic names into TK_COLUMN operators for the current
-** node in the expression tree.  Return 0 to continue the search down
-** the tree or 2 to abort the tree walk.
-**
-** This routine also does error checking and name resolution for
-** function names.  The operator for aggregate functions is changed
-** to TK_AGG_FUNCTION.
-*/
-static int nameResolverStep(void *pArg, Expr *pExpr){
-  NameContext *pNC = (NameContext*)pArg;
-  Parse *pParse;
-
-  if( pExpr==0 ) return 1;
-  assert( pNC!=0 );
-  pParse = pNC->pParse;
-
-  if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return 1;
-  ExprSetProperty(pExpr, EP_Resolved);
-#ifndef NDEBUG
-  if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){
-    SrcList *pSrcList = pNC->pSrcList;
-    int i;
-    for(i=0; i<pNC->pSrcList->nSrc; i++){
-      assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab);
-    }
-  }
-#endif
-  switch( pExpr->op ){
-    /* A lone identifier is the name of a column.
-    */
-    case TK_ID: {
-      lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr);
-      return 1;
-    }
-  
-    /* A table name and column name:     ID.ID
-    ** Or a database, table and column:  ID.ID.ID
-    */
-    case TK_DOT: {
-      Token *pColumn;
-      Token *pTable;
-      Token *pDb;
-      Expr *pRight;
-
-      /* if( pSrcList==0 ) break; */
-      pRight = pExpr->pRight;
-      if( pRight->op==TK_ID ){
-        pDb = 0;
-        pTable = &pExpr->pLeft->token;
-        pColumn = &pRight->token;
-      }else{
-        assert( pRight->op==TK_DOT );
-        pDb = &pExpr->pLeft->token;
-        pTable = &pRight->pLeft->token;
-        pColumn = &pRight->pRight->token;
-      }
-      lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr);
-      return 1;
-    }
-
-    /* Resolve function names
-    */
-    case TK_CONST_FUNC:
-    case TK_FUNCTION: {
-      ExprList *pList = pExpr->pList;    /* The argument list */
-      int n = pList ? pList->nExpr : 0;  /* Number of arguments */
-      int no_such_func = 0;       /* True if no such function exists */
-      int wrong_num_args = 0;     /* True if wrong number of arguments */
-      int is_agg = 0;             /* True if is an aggregate function */
-      int i;
-      int auth;                   /* Authorization to use the function */
-      int nId;                    /* Number of characters in function name */
-      const char *zId;            /* The function name. */
-      FuncDef *pDef;              /* Information about the function */
-      int enc = ENC(pParse->db);  /* The database encoding */
-
-      zId = (char*)pExpr->token.z;
-      nId = pExpr->token.n;
-      pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
-      if( pDef==0 ){
-        pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0);
-        if( pDef==0 ){
-          no_such_func = 1;
-        }else{
-          wrong_num_args = 1;
-        }
-      }else{
-        is_agg = pDef->xFunc==0;
-      }
-#ifndef SQLITE_OMIT_AUTHORIZATION
-      if( pDef ){
-        auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0);
-        if( auth!=SQLITE_OK ){
-          if( auth==SQLITE_DENY ){
-            sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
-                                    pDef->zName);
-            pNC->nErr++;
-          }
-          pExpr->op = TK_NULL;
-          return 1;
-        }
-      }
-#endif
-      if( is_agg && !pNC->allowAgg ){
-        sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
-        pNC->nErr++;
-        is_agg = 0;
-      }else if( no_such_func ){
-        sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
-        pNC->nErr++;
-      }else if( wrong_num_args ){
-        sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
-             nId, zId);
-        pNC->nErr++;
-      }
-      if( is_agg ){
-        pExpr->op = TK_AGG_FUNCTION;
-        pNC->hasAgg = 1;
-      }
-      if( is_agg ) pNC->allowAgg = 0;
-      for(i=0; pNC->nErr==0 && i<n; i++){
-        walkExprTree(pList->a[i].pExpr, nameResolverStep, pNC);
-      }
-      if( is_agg ) pNC->allowAgg = 1;
-      /* FIX ME:  Compute pExpr->affinity based on the expected return
-      ** type of the function 
-      */
-      return is_agg;
-    }
-#ifndef SQLITE_OMIT_SUBQUERY
-    case TK_SELECT:
-    case TK_EXISTS:
-#endif
-    case TK_IN: {
-      if( pExpr->pSelect ){
-        int nRef = pNC->nRef;
-#ifndef SQLITE_OMIT_CHECK
-        if( pNC->isCheck ){
-          sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints");
-        }
-#endif
-        sqlite3SelectResolve(pParse, pExpr->pSelect, pNC);
-        assert( pNC->nRef>=nRef );
-        if( nRef!=pNC->nRef ){
-          ExprSetProperty(pExpr, EP_VarSelect);
-        }
-      }
-      break;
-    }
-#ifndef SQLITE_OMIT_CHECK
-    case TK_VARIABLE: {
-      if( pNC->isCheck ){
-        sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints");
-      }
-      break;
-    }
-#endif
-  }
-  return 0;
-}
-
-/*
-** This routine walks an expression tree and resolves references to
-** table columns.  Nodes of the form ID.ID or ID resolve into an
-** index to the table in the table list and a column offset.  The 
-** Expr.opcode for such nodes is changed to TK_COLUMN.  The Expr.iTable
-** value is changed to the index of the referenced table in pTabList
-** plus the "base" value.  The base value will ultimately become the
-** VDBE cursor number for a cursor that is pointing into the referenced
-** table.  The Expr.iColumn value is changed to the index of the column 
-** of the referenced table.  The Expr.iColumn value for the special
-** ROWID column is -1.  Any INTEGER PRIMARY KEY column is tried as an
-** alias for ROWID.
-**
-** Also resolve function names and check the functions for proper
-** usage.  Make sure all function names are recognized and all functions
-** have the correct number of arguments.  Leave an error message
-** in pParse->zErrMsg if anything is amiss.  Return the number of errors.
-**
-** If the expression contains aggregate functions then set the EP_Agg
-** property on the expression.
-*/
-int sqlite3ExprResolveNames( 
-  NameContext *pNC,       /* Namespace to resolve expressions in. */
-  Expr *pExpr             /* The expression to be analyzed. */
-){
-  int savedHasAgg;
-
-  if( pExpr==0 ) return 0;
-#if SQLITE_MAX_EXPR_DEPTH>0
-  {
-    if( checkExprHeight(pNC->pParse, pExpr->nHeight + pNC->pParse->nHeight) ){
-      return 1;
-    }
-    pNC->pParse->nHeight += pExpr->nHeight;
-  }
-#endif
-  savedHasAgg = pNC->hasAgg;
-  pNC->hasAgg = 0;
-  walkExprTree(pExpr, nameResolverStep, pNC);
-#if SQLITE_MAX_EXPR_DEPTH>0
-  pNC->pParse->nHeight -= pExpr->nHeight;
-#endif
-  if( pNC->nErr>0 ){
-    ExprSetProperty(pExpr, EP_Error);
-  }
-  if( pNC->hasAgg ){
-    ExprSetProperty(pExpr, EP_Agg);
-  }else if( savedHasAgg ){
-    pNC->hasAgg = 1;
-  }
-  return ExprHasProperty(pExpr, EP_Error);
-}
-
-/*
-** A pointer instance of this structure is used to pass information
-** through walkExprTree into codeSubqueryStep().
-*/
-typedef struct QueryCoder QueryCoder;
-struct QueryCoder {
-  Parse *pParse;       /* The parsing context */
-  NameContext *pNC;    /* Namespace of first enclosing query */
-};
-
 #ifdef SQLITE_TEST
   int sqlite3_enable_in_opt = 1;
 #else
@@ -1626,8 +1050,9 @@ static int isCandidateForInOpt(Select *p){
   if( !sqlite3_enable_in_opt ) return 0; /* IN optimization must be enabled */
   if( p==0 ) return 0;                   /* right-hand side of IN is SELECT */
   if( p->pPrior ) return 0;              /* Not a compound SELECT */
-  if( p->isDistinct ) return 0;          /* No DISTINCT keyword */
-  if( p->isAgg ) return 0;               /* Contains no aggregate functions */
+  if( p->selFlags & (SF_Distinct|SF_Aggregate) ){
+      return 0; /* No DISTINCT keyword and no aggregate functions */
+  }
   if( p->pGroupBy ) return 0;            /* Has no GROUP BY clause */
   if( p->pLimit ) return 0;              /* Has no LIMIT clause */
   if( p->pOffset ) return 0;
@@ -1882,7 +1307,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr, int rMayHaveNull){
         sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
         dest.affinity = (int)affinity;
         assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
-        if( sqlite3Select(pParse, pExpr->pSelect, &dest, 0, 0, 0) ){
+        if( sqlite3Select(pParse, pExpr->pSelect, &dest) ){
           return;
         }
         pEList = pExpr->pSelect->pEList;
@@ -1906,7 +1331,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr, int rMayHaveNull){
         if( !affinity ){
           affinity = SQLITE_AFF_NONE;
         }
-        keyInfo.aColl[0] = pExpr->pLeft->pColl;
+        keyInfo.aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
 
         /* Loop through each expression in <exprlist>. */
         r1 = sqlite3GetTempReg(pParse);
@@ -1963,7 +1388,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr, int rMayHaveNull){
       }
       sqlite3ExprDelete(pParse->db, pSel->pLimit);
       pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &one);
-      if( sqlite3Select(pParse, pSel, &dest, 0, 0, 0) ){
+      if( sqlite3Select(pParse, pSel, &dest) ){
         return;
       }
       pExpr->iColumn = dest.iParm;
@@ -2745,7 +2170,6 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
         cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, &regFree1);
         testcase( regFree1==0 );
         cacheX.op = TK_REGISTER;
-        cacheX.iColumn = 0;
         opCompare.op = TK_EQ;
         opCompare.pLeft = &cacheX;
         pTest = &opCompare;
@@ -2865,7 +2289,6 @@ int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
     iMem = ++pParse->nMem;
     sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem);
     pExpr->iTable = iMem;
-    pExpr->iColumn = pExpr->op;
     pExpr->op = TK_REGISTER;
   }
   return inReg;
@@ -2936,8 +2359,8 @@ static int isAppropriateForFactoring(Expr *p){
 ** into a register and convert the expression into a TK_REGISTER
 ** expression.
 */
-static int evalConstExpr(void *pArg, Expr *pExpr){
-  Parse *pParse = (Parse*)pArg;
+static int evalConstExpr(Walker *pWalker, Expr *pExpr){
+  Parse *pParse = pWalker->pParse;
   switch( pExpr->op ){
     case TK_REGISTER: {
       return 1;
@@ -2965,12 +2388,11 @@ static int evalConstExpr(void *pArg, Expr *pExpr){
     int r2;
     r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
     if( r1!=r2 ) sqlite3ReleaseTempReg(pParse, r1);
-    pExpr->iColumn = pExpr->op;
     pExpr->op = TK_REGISTER;
     pExpr->iTable = r2;
-    return 1;
+    return WRC_Prune;
   }
-  return 0;
+  return WRC_Continue;
 }
 
 /*
@@ -2979,7 +2401,11 @@ static int evalConstExpr(void *pArg, Expr *pExpr){
 ** are TK_REGISTER opcodes that refer to the precomputed values.
 */
 void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){
-   walkExprTree(pExpr, evalConstExpr, pParse);
+  Walker w;
+  w.xExprCallback = evalConstExpr;
+  w.xSelectCallback = 0;
+  w.pParse = pParse;
+  sqlite3WalkExpr(&w, pExpr);
 }
 
 
@@ -3379,15 +2805,13 @@ static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){
 }    
 
 /*
-** This is an xFunc for walkExprTree() used to implement 
-** sqlite3ExprAnalyzeAggregates().  See sqlite3ExprAnalyzeAggregates
+** This is the xExprCallback for a tree walker.  It is used to
+** implement sqlite3ExprAnalyzeAggregates().  See sqlite3ExprAnalyzeAggregates
 ** for additional information.
-**
-** This routine analyzes the aggregate function at pExpr.
 */
-static int analyzeAggregate(void *pArg, Expr *pExpr){
+static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
   int i;
-  NameContext *pNC = (NameContext *)pArg;
+  NameContext *pNC = pWalker->u.pNC;
   Parse *pParse = pNC->pParse;
   SrcList *pSrcList = pNC->pSrcList;
   AggInfo *pAggInfo = pNC->pAggInfo;
@@ -3456,7 +2880,7 @@ static int analyzeAggregate(void *pArg, Expr *pExpr){
           } /* endif pExpr->iTable==pItem->iCursor */
         } /* end loop over pSrcList */
       }
-      return 1;
+      return WRC_Prune;
     }
     case TK_AGG_FUNCTION: {
       /* The pNC->nDepth==0 test causes aggregate functions in subqueries
@@ -3494,21 +2918,22 @@ static int analyzeAggregate(void *pArg, Expr *pExpr){
         */
         pExpr->iAgg = i;
         pExpr->pAggInfo = pAggInfo;
-        return 1;
+        return WRC_Prune;
       }
     }
   }
-
-  /* Recursively walk subqueries looking for TK_COLUMN nodes that need
-  ** to be changed to TK_AGG_COLUMN.  But increment nDepth so that
-  ** TK_AGG_FUNCTION nodes in subqueries will be unchanged.
-  */
-  if( pExpr->pSelect ){
+  return WRC_Continue;
+}
+static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
+  NameContext *pNC = pWalker->u.pNC;
+  if( pNC->nDepth==0 ){
     pNC->nDepth++;
-    walkSelectExpr(pExpr->pSelect, analyzeAggregate, pNC);
+    sqlite3WalkSelect(pWalker, pSelect);
     pNC->nDepth--;
+    return WRC_Prune;
+  }else{
+    return WRC_Continue;
   }
-  return 0;
 }
 
 /*
@@ -3517,10 +2942,14 @@ static int analyzeAggregate(void *pArg, Expr *pExpr){
 ** Make additional entries to the pParse->aAgg[] array as necessary.
 **
 ** This routine should only be called after the expression has been
-** analyzed by sqlite3ExprResolveNames().
+** analyzed by sqlite3ResolveExprNames().
 */
 void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
-  walkExprTree(pExpr, analyzeAggregate, pNC);
+  Walker w;
+  w.xExprCallback = analyzeAggregate;
+  w.xSelectCallback = analyzeAggregatesInSelect;
+  w.u.pNC = pNC;
+  sqlite3WalkExpr(&w, pExpr);
 }
 
 /*
index 9a3d46f1b3db0535cb407f90c4a73640a736cb0e..de5c8d54c6f55fbeef748b2cb54fc6a036d2c289 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle INSERT statements in SQLite.
 **
-** $Id: insert.c,v 1.248 2008/07/28 19:34:53 drh Exp $
+** $Id: insert.c,v 1.249 2008/08/20 16:35:10 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -165,7 +165,7 @@ static int autoIncBegin(
   Table *pTab         /* The table we are writing to */
 ){
   int memId = 0;      /* Register holding maximum rowid */
-  if( pTab->autoInc ){
+  if( pTab->tabFlags & TF_Autoincrement ){
     Vdbe *v = pParse->pVdbe;
     Db *pDb = &pParse->db->aDb[iDb];
     int iCur = pParse->nTab;
@@ -216,7 +216,7 @@ static void autoIncEnd(
   Table *pTab,       /* Table we are inserting into */
   int memId          /* Memory cell holding the maximum rowid */
 ){
-  if( pTab->autoInc ){
+  if( pTab->tabFlags & TF_Autoincrement ){
     int iCur = pParse->nTab;
     Vdbe *v = pParse->pVdbe;
     Db *pDb = &pParse->db->aDb[iDb];
@@ -532,7 +532,7 @@ void sqlite3Insert(
     VdbeComment((v, "Jump over SELECT coroutine"));
 
     /* Resolve the expressions in the SELECT statement and execute it. */
-    rc = sqlite3Select(pParse, pSelect, &dest, 0, 0, 0);
+    rc = sqlite3Select(pParse, pSelect, &dest);
     if( rc || pParse->nErr || db->mallocFailed ){
       goto insert_cleanup;
     }
@@ -602,7 +602,7 @@ void sqlite3Insert(
     assert( useTempTable==0 );
     nColumn = pList ? pList->nExpr : 0;
     for(i=0; i<nColumn; i++){
-      if( sqlite3ExprResolveNames(&sNC, pList->a[i].pExpr) ){
+      if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
         goto insert_cleanup;
       }
     }
@@ -1535,7 +1535,7 @@ static int xferOptimization(
     return 0;   /* tab1 must not have triggers */
   }
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  if( pDest->isVirtual ){
+  if( pDest->tabFlags & TF_Virtual ){
     return 0;   /* tab1 must not be a virtual table */
   }
 #endif
@@ -1570,7 +1570,7 @@ static int xferOptimization(
   if( pSelect->pPrior ){
     return 0;   /* SELECT may not be a compound query */
   }
-  if( pSelect->isDistinct ){
+  if( pSelect->selFlags & SF_Distinct ){
     return 0;   /* SELECT may not be DISTINCT */
   }
   pEList = pSelect->pEList;
@@ -1596,7 +1596,7 @@ static int xferOptimization(
     return 0;   /* tab1 and tab2 may not be the same table */
   }
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  if( pSrc->isVirtual ){
+  if( pSrc->tabFlags & TF_Virtual ){
     return 0;   /* tab2 must not be a virtual table */
   }
 #endif
@@ -1687,7 +1687,7 @@ static int xferOptimization(
     addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
   }else{
     addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
-    assert( pDest->autoInc==0 );
+    assert( (pDest->tabFlags & TF_Autoincrement)==0 );
   }
   sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);
   sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid);
index 626641b3c51e8b97d52bfd0514a0daca49d0bcae..42ca5cc13a1c2fef8eecb8031efc535c84a86b78 100644 (file)
@@ -14,7 +14,7 @@
 ** other files are for internal use by SQLite and should not be
 ** accessed by users of the library.
 **
-** $Id: main.c,v 1.490 2008/08/20 16:21:12 danielk1977 Exp $
+** $Id: main.c,v 1.491 2008/08/20 16:35:10 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1890,7 +1890,7 @@ int sqlite3_table_column_metadata(
     zCollSeq = pCol->zColl;
     notnull = pCol->notNull!=0;
     primarykey  = pCol->isPrimKey!=0;
-    autoinc = pTab->iPKey==iCol && pTab->autoInc;
+    autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0;
   }else{
     zDataType = "INTEGER";
     primarykey = 1;
index f00c5415a872a22023220decae06284451af3bbe..7ec63431776a6948aa8ff8b3ffd66e039f3da71a 100644 (file)
@@ -14,7 +14,7 @@
 ** the parser.  Lemon will also generate a header file containing
 ** numeric codes for all of the tokens.
 **
-** @(#) $Id: parse.y,v 1.251 2008/08/11 14:26:35 drh Exp $
+** @(#) $Id: parse.y,v 1.252 2008/08/20 16:35:10 drh Exp $
 */
 
 // All token codes are small integers with #defines that begin with "TK_"
@@ -360,8 +360,8 @@ cmd ::= DROP VIEW ifexists(E) fullname(X). {
 //////////////////////// The SELECT statement /////////////////////////////////
 //
 cmd ::= select(X).  {
-  SelectDest dest = {SRT_Callback, 0, 0, 0, 0};
-  sqlite3Select(pParse, X, &dest, 0, 0, 0);
+  SelectDest dest = {SRT_Output, 0, 0, 0, 0};
+  sqlite3Select(pParse, X, &dest);
   sqlite3SelectDelete(pParse->db, X);
 }
 
index e61c6fc5cfc531acd74bda6825fdebf915699e4a..c7fc343b1c6859b31f1b5e693a7158c120984000 100644 (file)
@@ -13,7 +13,7 @@
 ** interface, and routines that contribute to loading the database schema
 ** from disk.
 **
-** $Id: prepare.c,v 1.92 2008/08/11 18:44:58 drh Exp $
+** $Id: prepare.c,v 1.93 2008/08/20 16:35:10 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -203,7 +203,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
   }
   pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName);
   if( pTab ){
-    pTab->readOnly = 1;
+    pTab->tabFlags |= TF_Readonly;
   }
 
   /* Create a cursor to hold the database open
diff --git a/src/resolve.c b/src/resolve.c
new file mode 100644 (file)
index 0000000..dbc97da
--- /dev/null
@@ -0,0 +1,1125 @@
+/*
+** 2008 August 18
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains routines used for walking the parser tree and
+** resolve all identifiers by associating them with a particular
+** table and column.
+**
+** $Id: resolve.c,v 1.1 2008/08/20 16:35:10 drh Exp $
+*/
+#include "sqliteInt.h"
+#include <stdlib.h>
+#include <string.h>
+
+/*
+** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
+** that name in the set of source tables in pSrcList and make the pExpr 
+** expression node refer back to that source column.  The following changes
+** are made to pExpr:
+**
+**    pExpr->iDb           Set the index in db->aDb[] of the database X
+**                         (even if X is implied).
+**    pExpr->iTable        Set to the cursor number for the table obtained
+**                         from pSrcList.
+**    pExpr->pTab          Points to the Table structure of X.Y (even if
+**                         X and/or Y are implied.)
+**    pExpr->iColumn       Set to the column number within the table.
+**    pExpr->op            Set to TK_COLUMN.
+**    pExpr->pLeft         Any expression this points to is deleted
+**    pExpr->pRight        Any expression this points to is deleted.
+**
+** The pDbToken is the name of the database (the "X").  This value may be
+** NULL meaning that name is of the form Y.Z or Z.  Any available database
+** can be used.  The pTableToken is the name of the table (the "Y").  This
+** value can be NULL if pDbToken is also NULL.  If pTableToken is NULL it
+** means that the form of the name is Z and that columns from any table
+** can be used.
+**
+** If the name cannot be resolved unambiguously, leave an error message
+** in pParse and return non-zero.  Return zero on success.
+*/
+static int lookupName(
+  Parse *pParse,       /* The parsing context */
+  Token *pDbToken,     /* Name of the database containing table, or NULL */
+  Token *pTableToken,  /* Name of table containing column, or NULL */
+  Token *pColumnToken, /* Name of the column. */
+  NameContext *pNC,    /* The name context used to resolve the name */
+  Expr *pExpr          /* Make this EXPR node point to the selected column */
+){
+  char *zDb = 0;       /* Name of the database.  The "X" in X.Y.Z */
+  char *zTab = 0;      /* Name of the table.  The "Y" in X.Y.Z or Y.Z */
+  char *zCol = 0;      /* Name of the column.  The "Z" */
+  int i, j;            /* Loop counters */
+  int cnt = 0;                      /* Number of matching column names */
+  int cntTab = 0;                   /* Number of matching table names */
+  sqlite3 *db = pParse->db;         /* The database connection */
+  struct SrcList_item *pItem;       /* Use for looping over pSrcList items */
+  struct SrcList_item *pMatch = 0;  /* The matching pSrcList item */
+  NameContext *pTopNC = pNC;        /* First namecontext in the list */
+  Schema *pSchema = 0;              /* Schema of the expression */
+
+  assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */
+
+  /* Dequote and zero-terminate the names */
+  zDb = sqlite3NameFromToken(db, pDbToken);
+  zTab = sqlite3NameFromToken(db, pTableToken);
+  zCol = sqlite3NameFromToken(db, pColumnToken);
+  if( db->mallocFailed ){
+    goto lookupname_end;
+  }
+
+  /* Initialize the node to no-match */
+  pExpr->iTable = -1;
+  pExpr->pTab = 0;
+
+  /* Start at the inner-most context and move outward until a match is found */
+  while( pNC && cnt==0 ){
+    ExprList *pEList;
+    SrcList *pSrcList = pNC->pSrcList;
+
+    if( pSrcList ){
+      for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
+        Table *pTab;
+        int iDb;
+        Column *pCol;
+  
+        pTab = pItem->pTab;
+        assert( pTab!=0 );
+        iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+        assert( pTab->nCol>0 );
+        if( zTab ){
+          if( pItem->zAlias ){
+            char *zTabName = pItem->zAlias;
+            if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
+          }else{
+            char *zTabName = pTab->zName;
+            if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
+            if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){
+              continue;
+            }
+          }
+        }
+        if( 0==(cntTab++) ){
+          pExpr->iTable = pItem->iCursor;
+          pExpr->pTab = pTab;
+          pSchema = pTab->pSchema;
+          pMatch = pItem;
+        }
+        for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
+          if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
+            IdList *pUsing;
+            cnt++;
+            pExpr->iTable = pItem->iCursor;
+            pExpr->pTab = pTab;
+            pMatch = pItem;
+            pSchema = pTab->pSchema;
+            /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
+            pExpr->iColumn = j==pTab->iPKey ? -1 : j;
+            if( i<pSrcList->nSrc-1 ){
+              if( pItem[1].jointype & JT_NATURAL ){
+                /* If this match occurred in the left table of a natural join,
+                ** then skip the right table to avoid a duplicate match */
+                pItem++;
+                i++;
+              }else if( (pUsing = pItem[1].pUsing)!=0 ){
+                /* If this match occurs on a column that is in the USING clause
+                ** of a join, skip the search of the right table of the join
+                ** to avoid a duplicate match there. */
+                int k;
+                for(k=0; k<pUsing->nId; k++){
+                  if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ){
+                    pItem++;
+                    i++;
+                    break;
+                  }
+                }
+              }
+            }
+            break;
+          }
+        }
+      }
+    }
+
+#ifndef SQLITE_OMIT_TRIGGER
+    /* If we have not already resolved the name, then maybe 
+    ** it is a new.* or old.* trigger argument reference
+    */
+    if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
+      TriggerStack *pTriggerStack = pParse->trigStack;
+      Table *pTab = 0;
+      u32 *piColMask;
+      if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){
+        pExpr->iTable = pTriggerStack->newIdx;
+        assert( pTriggerStack->pTab );
+        pTab = pTriggerStack->pTab;
+        piColMask = &(pTriggerStack->newColMask);
+      }else if( pTriggerStack->oldIdx != -1 && sqlite3StrICmp("old", zTab)==0 ){
+        pExpr->iTable = pTriggerStack->oldIdx;
+        assert( pTriggerStack->pTab );
+        pTab = pTriggerStack->pTab;
+        piColMask = &(pTriggerStack->oldColMask);
+      }
+
+      if( pTab ){ 
+        int iCol;
+        Column *pCol = pTab->aCol;
+
+        pSchema = pTab->pSchema;
+        cntTab++;
+        for(iCol=0; iCol < pTab->nCol; iCol++, pCol++) {
+          if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
+            cnt++;
+            pExpr->iColumn = iCol==pTab->iPKey ? -1 : iCol;
+            pExpr->pTab = pTab;
+            if( iCol>=0 ){
+              testcase( iCol==31 );
+              testcase( iCol==32 );
+              *piColMask |= ((u32)1<<iCol) | (iCol>=32?0xffffffff:0);
+            }
+            break;
+          }
+        }
+      }
+    }
+#endif /* !defined(SQLITE_OMIT_TRIGGER) */
+
+    /*
+    ** Perhaps the name is a reference to the ROWID
+    */
+    if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
+      cnt = 1;
+      pExpr->iColumn = -1;
+      pExpr->affinity = SQLITE_AFF_INTEGER;
+    }
+
+    /*
+    ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
+    ** might refer to an result-set alias.  This happens, for example, when
+    ** we are resolving names in the WHERE clause of the following command:
+    **
+    **     SELECT a+b AS x FROM table WHERE x<10;
+    **
+    ** In cases like this, replace pExpr with a copy of the expression that
+    ** forms the result set entry ("a+b" in the example) and return immediately.
+    ** Note that the expression in the result set should have already been
+    ** resolved by the time the WHERE clause is resolved.
+    */
+    if( cnt==0 && (pEList = pNC->pEList)!=0 && zTab==0 ){
+      for(j=0; j<pEList->nExpr; j++){
+        char *zAs = pEList->a[j].zName;
+        if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
+          Expr *pDup, *pOrig;
+          assert( pExpr->pLeft==0 && pExpr->pRight==0 );
+          assert( pExpr->pList==0 );
+          assert( pExpr->pSelect==0 );
+          pOrig = pEList->a[j].pExpr;
+          if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){
+            sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
+            sqlite3DbFree(db, zCol);
+            return 2;
+          }
+          pDup = sqlite3ExprDup(db, pOrig);
+          if( pExpr->flags & EP_ExpCollate ){
+            pDup->pColl = pExpr->pColl;
+            pDup->flags |= EP_ExpCollate;
+          }
+          if( pExpr->span.dyn ) sqlite3DbFree(db, (char*)pExpr->span.z);
+          if( pExpr->token.dyn ) sqlite3DbFree(db, (char*)pExpr->token.z);
+          memcpy(pExpr, pDup, sizeof(*pExpr));
+          sqlite3DbFree(db, pDup);
+          cnt = 1;
+          pMatch = 0;
+          assert( zTab==0 && zDb==0 );
+          goto lookupname_end_2;
+        }
+      } 
+    }
+
+    /* Advance to the next name context.  The loop will exit when either
+    ** we have a match (cnt>0) or when we run out of name contexts.
+    */
+    if( cnt==0 ){
+      pNC = pNC->pNext;
+    }
+  }
+
+  /*
+  ** If X and Y are NULL (in other words if only the column name Z is
+  ** supplied) and the value of Z is enclosed in double-quotes, then
+  ** Z is a string literal if it doesn't match any column names.  In that
+  ** case, we need to return right away and not make any changes to
+  ** pExpr.
+  **
+  ** Because no reference was made to outer contexts, the pNC->nRef
+  ** fields are not changed in any context.
+  */
+  if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){
+    sqlite3DbFree(db, zCol);
+    pExpr->op = TK_STRING;
+    return 0;
+  }
+
+  /*
+  ** cnt==0 means there was not match.  cnt>1 means there were two or
+  ** more matches.  Either way, we have an error.
+  */
+  if( cnt!=1 ){
+    const char *zErr;
+    zErr = cnt==0 ? "no such column" : "ambiguous column name";
+    if( zDb ){
+      sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol);
+    }else if( zTab ){
+      sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol);
+    }else{
+      sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
+    }
+    pTopNC->nErr++;
+  }
+
+  /* If a column from a table in pSrcList is referenced, then record
+  ** this fact in the pSrcList.a[].colUsed bitmask.  Column 0 causes
+  ** bit 0 to be set.  Column 1 sets bit 1.  And so forth.  If the
+  ** column number is greater than the number of bits in the bitmask
+  ** then set the high-order bit of the bitmask.
+  */
+  if( pExpr->iColumn>=0 && pMatch!=0 ){
+    int n = pExpr->iColumn;
+    testcase( n==sizeof(Bitmask)*8-1 );
+    if( n>=sizeof(Bitmask)*8 ){
+      n = sizeof(Bitmask)*8-1;
+    }
+    assert( pMatch->iCursor==pExpr->iTable );
+    pMatch->colUsed |= ((Bitmask)1)<<n;
+  }
+
+lookupname_end:
+  /* Clean up and return
+  */
+  sqlite3DbFree(db, zDb);
+  sqlite3DbFree(db, zTab);
+  sqlite3ExprDelete(db, pExpr->pLeft);
+  pExpr->pLeft = 0;
+  sqlite3ExprDelete(db, pExpr->pRight);
+  pExpr->pRight = 0;
+  pExpr->op = TK_COLUMN;
+lookupname_end_2:
+  sqlite3DbFree(db, zCol);
+  if( cnt==1 ){
+    assert( pNC!=0 );
+    sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
+    /* Increment the nRef value on all name contexts from TopNC up to
+    ** the point where the name matched. */
+    for(;;){
+      assert( pTopNC!=0 );
+      pTopNC->nRef++;
+      if( pTopNC==pNC ) break;
+      pTopNC = pTopNC->pNext;
+    }
+    return 0;
+  } else {
+    return 1;
+  }
+}
+
+/*
+** This routine is callback for sqlite3WalkExpr().
+**
+** Resolve symbolic names into TK_COLUMN operators for the current
+** node in the expression tree.  Return 0 to continue the search down
+** the tree or 2 to abort the tree walk.
+**
+** This routine also does error checking and name resolution for
+** function names.  The operator for aggregate functions is changed
+** to TK_AGG_FUNCTION.
+*/
+static int resolveExprStep(Walker *pWalker, Expr *pExpr){
+  NameContext *pNC;
+  Parse *pParse;
+
+  if( pExpr==0 ) return WRC_Continue;
+  pNC = pWalker->u.pNC;
+  assert( pNC!=0 );
+  pParse = pNC->pParse;
+  assert( pParse==pWalker->pParse );
+
+  if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return WRC_Prune;
+  ExprSetProperty(pExpr, EP_Resolved);
+#ifndef NDEBUG
+  if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){
+    SrcList *pSrcList = pNC->pSrcList;
+    int i;
+    for(i=0; i<pNC->pSrcList->nSrc; i++){
+      assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab);
+    }
+  }
+#endif
+  switch( pExpr->op ){
+    /* A lone identifier is the name of a column.
+    */
+    case TK_ID: {
+      lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr);
+      return WRC_Prune;
+    }
+  
+    /* A table name and column name:     ID.ID
+    ** Or a database, table and column:  ID.ID.ID
+    */
+    case TK_DOT: {
+      Token *pColumn;
+      Token *pTable;
+      Token *pDb;
+      Expr *pRight;
+
+      /* if( pSrcList==0 ) break; */
+      pRight = pExpr->pRight;
+      if( pRight->op==TK_ID ){
+        pDb = 0;
+        pTable = &pExpr->pLeft->token;
+        pColumn = &pRight->token;
+      }else{
+        assert( pRight->op==TK_DOT );
+        pDb = &pExpr->pLeft->token;
+        pTable = &pRight->pLeft->token;
+        pColumn = &pRight->pRight->token;
+      }
+      lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr);
+      return WRC_Prune;
+    }
+
+    /* Resolve function names
+    */
+    case TK_CONST_FUNC:
+    case TK_FUNCTION: {
+      ExprList *pList = pExpr->pList;    /* The argument list */
+      int n = pList ? pList->nExpr : 0;  /* Number of arguments */
+      int no_such_func = 0;       /* True if no such function exists */
+      int wrong_num_args = 0;     /* True if wrong number of arguments */
+      int is_agg = 0;             /* True if is an aggregate function */
+      int auth;                   /* Authorization to use the function */
+      int nId;                    /* Number of characters in function name */
+      const char *zId;            /* The function name. */
+      FuncDef *pDef;              /* Information about the function */
+      int enc = ENC(pParse->db);  /* The database encoding */
+
+      zId = (char*)pExpr->token.z;
+      nId = pExpr->token.n;
+      pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
+      if( pDef==0 ){
+        pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0);
+        if( pDef==0 ){
+          no_such_func = 1;
+        }else{
+          wrong_num_args = 1;
+        }
+      }else{
+        is_agg = pDef->xFunc==0;
+      }
+#ifndef SQLITE_OMIT_AUTHORIZATION
+      if( pDef ){
+        auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0);
+        if( auth!=SQLITE_OK ){
+          if( auth==SQLITE_DENY ){
+            sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
+                                    pDef->zName);
+            pNC->nErr++;
+          }
+          pExpr->op = TK_NULL;
+          return WRC_Prune;
+        }
+      }
+#endif
+      if( is_agg && !pNC->allowAgg ){
+        sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
+        pNC->nErr++;
+        is_agg = 0;
+      }else if( no_such_func ){
+        sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
+        pNC->nErr++;
+      }else if( wrong_num_args ){
+        sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
+             nId, zId);
+        pNC->nErr++;
+      }
+      if( is_agg ){
+        pExpr->op = TK_AGG_FUNCTION;
+        pNC->hasAgg = 1;
+      }
+      if( is_agg ) pNC->allowAgg = 0;
+      sqlite3WalkExprList(pWalker, pList);
+      if( is_agg ) pNC->allowAgg = 1;
+      /* FIX ME:  Compute pExpr->affinity based on the expected return
+      ** type of the function 
+      */
+      return WRC_Prune;
+    }
+#ifndef SQLITE_OMIT_SUBQUERY
+    case TK_SELECT:
+    case TK_EXISTS:
+#endif
+    case TK_IN: {
+      if( pExpr->pSelect ){
+        int nRef = pNC->nRef;
+#ifndef SQLITE_OMIT_CHECK
+        if( pNC->isCheck ){
+          sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints");
+        }
+#endif
+        sqlite3WalkSelect(pWalker, pExpr->pSelect);
+        assert( pNC->nRef>=nRef );
+        if( nRef!=pNC->nRef ){
+          ExprSetProperty(pExpr, EP_VarSelect);
+        }
+      }
+      break;
+    }
+#ifndef SQLITE_OMIT_CHECK
+    case TK_VARIABLE: {
+      if( pNC->isCheck ){
+        sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints");
+      }
+      break;
+    }
+#endif
+  }
+  return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue;
+}
+
+/*
+** pEList is a list of expressions which are really the result set of the
+** a SELECT statement.  pE is a term in an ORDER BY or GROUP BY clause.
+** This routine checks to see if pE is a simple identifier which corresponds
+** to the AS-name of one of the terms of the expression list.  If it is,
+** this routine return an integer between 1 and N where N is the number of
+** elements in pEList, corresponding to the matching entry.  If there is
+** no match, or if pE is not a simple identifier, then this routine
+** return 0.
+**
+** pEList has been resolved.  pE has not.
+*/
+static int resolveAsName(
+  Parse *pParse,     /* Parsing context for error messages */
+  ExprList *pEList,  /* List of expressions to scan */
+  Expr *pE           /* Expression we are trying to match */
+){
+  int i;             /* Loop counter */
+
+  if( pE->op==TK_ID || (pE->op==TK_STRING && pE->token.z[0]!='\'') ){
+    sqlite3 *db = pParse->db;
+    char *zCol = sqlite3NameFromToken(db, &pE->token);
+    if( zCol==0 ){
+      return -1;
+    }
+    for(i=0; i<pEList->nExpr; i++){
+      char *zAs = pEList->a[i].zName;
+      if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
+        sqlite3DbFree(db, zCol);
+        return i+1;
+      }
+    }
+    sqlite3DbFree(db, zCol);
+  }
+  return 0;
+}
+
+/*
+** pE is a pointer to an expression which is a single term in the
+** ORDER BY of a compound SELECT.  The expression has not been
+** name resolved.
+**
+** At the point this routine is called, we already know that the
+** ORDER BY term is not an integer index into the result set.  That
+** case is handled by the calling routine.
+**
+** Attempt to match pE against result set columns in the left-most
+** SELECT statement.  Return the index i of the matching column,
+** as an indication to the caller that it should sort by the i-th column.
+** The left-most column is 1.  In other words, the value returned is the
+** same integer value that would be used in the SQL statement to indicate
+** the column.
+**
+** If there is no match, return 0.  Return -1 if an error occurs.
+*/
+static int resolveOrderByTermToExprList(
+  Parse *pParse,     /* Parsing context for error messages */
+  Select *pSelect,   /* The SELECT statement with the ORDER BY clause */
+  Expr *pE           /* The specific ORDER BY term */
+){
+  int i;             /* Loop counter */
+  ExprList *pEList;  /* The columns of the result set */
+  NameContext nc;    /* Name context for resolving pE */
+
+  assert( sqlite3ExprIsInteger(pE, &i)==0 );
+  pEList = pSelect->pEList;
+
+  /* Resolve all names in the ORDER BY term expression
+  */
+  memset(&nc, 0, sizeof(nc));
+  nc.pParse = pParse;
+  nc.pSrcList = pSelect->pSrc;
+  nc.pEList = pEList;
+  nc.allowAgg = 1;
+  nc.nErr = 0;
+  if( sqlite3ResolveExprNames(&nc, pE) ){
+    sqlite3ErrorClear(pParse);
+    return 0;
+  }
+
+  /* Try to match the ORDER BY expression against an expression
+  ** in the result set.  Return an 1-based index of the matching
+  ** result-set entry.
+  */
+  for(i=0; i<pEList->nExpr; i++){
+    if( sqlite3ExprCompare(pEList->a[i].pExpr, pE) ){
+      return i+1;
+    }
+  }
+
+  /* If no match, return 0. */
+  return 0;
+}
+
+/*
+** Generate an ORDER BY or GROUP BY term out-of-range error.
+*/
+static void resolveOutOfRangeError(
+  Parse *pParse,         /* The error context into which to write the error */
+  const char *zType,     /* "ORDER" or "GROUP" */
+  int i,                 /* The index (1-based) of the term out of range */
+  int mx                 /* Largest permissible value of i */
+){
+  sqlite3ErrorMsg(pParse, 
+    "%r %s BY term out of range - should be "
+    "between 1 and %d", i, zType, mx);
+}
+
+/*
+** Analyze the ORDER BY clause in a compound SELECT statement.   Modify
+** each term of the ORDER BY clause is a constant integer between 1
+** and N where N is the number of columns in the compound SELECT.
+**
+** ORDER BY terms that are already an integer between 1 and N are
+** unmodified.  ORDER BY terms that are integers outside the range of
+** 1 through N generate an error.  ORDER BY terms that are expressions
+** are matched against result set expressions of compound SELECT
+** beginning with the left-most SELECT and working toward the right.
+** At the first match, the ORDER BY expression is transformed into
+** the integer column number.
+**
+** Return the number of errors seen.
+*/
+static int resolveCompoundOrderBy(
+  Parse *pParse,        /* Parsing context.  Leave error messages here */
+  Select *pSelect       /* The SELECT statement containing the ORDER BY */
+){
+  int i;
+  ExprList *pOrderBy;
+  ExprList *pEList;
+  sqlite3 *db;
+  int moreToDo = 1;
+
+  pOrderBy = pSelect->pOrderBy;
+  if( pOrderBy==0 ) return 0;
+  db = pParse->db;
+#if SQLITE_MAX_COLUMN
+  if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
+    sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause");
+    return 1;
+  }
+#endif
+  for(i=0; i<pOrderBy->nExpr; i++){
+    pOrderBy->a[i].done = 0;
+  }
+  pSelect->pNext = 0;
+  while( pSelect->pPrior ){
+    pSelect->pPrior->pNext = pSelect;
+    pSelect = pSelect->pPrior;
+  }
+  while( pSelect && moreToDo ){
+    struct ExprList_item *pItem;
+    moreToDo = 0;
+    pEList = pSelect->pEList;
+    if( pEList==0 ){
+      return 1;
+    }
+    for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
+      int iCol = -1;
+      Expr *pE, *pDup;
+      if( pItem->done ) continue;
+      pE = pItem->pExpr;
+      if( sqlite3ExprIsInteger(pE, &iCol) ){
+        if( iCol<0 || iCol>pEList->nExpr ){
+          resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
+          return 1;
+        }
+      }else{
+        iCol = resolveAsName(pParse, pEList, pE);
+        if( iCol==0 ){
+          pDup = sqlite3ExprDup(db, pE);
+          if( !db->mallocFailed ){
+            assert(pDup);
+            iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup);
+          }
+          sqlite3ExprDelete(db, pDup);
+        }
+        if( iCol<0 ){
+          return 1;
+        }
+      }
+      if( iCol>0 ){
+        CollSeq *pColl = pE->pColl;
+        int flags = pE->flags & EP_ExpCollate;
+        sqlite3ExprDelete(db, pE);
+        pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0, 0, 0);
+        if( pE==0 ) return 1;
+        pE->pColl = pColl;
+        pE->flags |= EP_IntValue | flags;
+        pE->iTable = iCol;
+        pItem->iCol = iCol;
+        pItem->done = 1;
+      }else{
+        moreToDo = 1;
+      }
+    }
+    pSelect = pSelect->pNext;
+  }
+  for(i=0; i<pOrderBy->nExpr; i++){
+    if( pOrderBy->a[i].done==0 ){
+      sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any "
+            "column in the result set", i+1);
+      return 1;
+    }
+  }
+  return 0;
+}
+
+/*
+** Check every term in the ORDER BY or GROUP BY clause pOrderBy of
+** the SELECT statement pSelect.  If any term is reference to a
+** result set expression (as determined by the ExprList.a.iCol field)
+** then convert that term into a copy of the corresponding result set
+** column.
+**
+** If any errors are detected, add an error message to pParse and
+** return non-zero.  Return zero if no errors are seen.
+*/
+int sqlite3ResolveOrderGroupBy(
+  Parse *pParse,        /* Parsing context.  Leave error messages here */
+  Select *pSelect,      /* The SELECT statement containing the clause */
+  ExprList *pOrderBy,   /* The ORDER BY or GROUP BY clause to be processed */
+  const char *zType     /* "ORDER" or "GROUP" */
+){
+  int i;
+  sqlite3 *db = pParse->db;
+  ExprList *pEList;
+  struct ExprList_item *pItem;
+
+  if( pOrderBy==0 || pParse->db->mallocFailed ) return 0;
+#if SQLITE_MAX_COLUMN
+  if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
+    sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType);
+    return 1;
+  }
+#endif
+  pEList = pSelect->pEList;
+  if( pEList==0 ){
+    return 0;
+  }
+  for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
+    if( pItem->iCol ){
+      Expr *pE;
+      CollSeq *pColl;
+      int flags;
+
+      if( pItem->iCol>pEList->nExpr ){
+        resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
+        return 1;
+      }
+      pE = pItem->pExpr;
+      pColl = pE->pColl;
+      flags = pE->flags & EP_ExpCollate;
+      sqlite3ExprDelete(db, pE);
+      pE = sqlite3ExprDup(db, pEList->a[pItem->iCol-1].pExpr);
+      pItem->pExpr = pE;
+      if( pE && pColl && flags ){
+        pE->pColl = pColl;
+        pE->flags |= flags;
+      }
+    }
+  }
+  return 0;
+}
+
+/*
+** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect.
+** The Name context of the SELECT statement is pNC.  zType is either
+** "ORDER" or "GROUP" depending on which type of clause pOrderBy is.
+**
+** This routine resolves each term of the clause into an expression.
+** If the order-by term is an integer I between 1 and N (where N is the
+** number of columns in the result set of the SELECT) then the expression
+** in the resolution is a copy of the I-th result-set expression.  If
+** the order-by term is an identify that corresponds to the AS-name of
+** a result-set expression, then the term resolves to a copy of the
+** result-set expression.  Otherwise, the expression is resolved in
+** the usual way - using sqlite3ResolveExprNames().
+**
+** This routine returns the number of errors.  If errors occur, then
+** an appropriate error message might be left in pParse.  (OOM errors
+** excepted.)
+*/
+static int resolveOrderGroupBy(
+  NameContext *pNC,     /* The name context of the SELECT statement */
+  Select *pSelect,      /* The SELECT statement holding pOrderBy */
+  ExprList *pOrderBy,   /* An ORDER BY or GROUP BY clause to resolve */
+  const char *zType     /* Either "ORDER" or "GROUP", as appropriate */
+){
+  int i;                         /* Loop counter */
+  int iCol;                      /* Column number */
+  struct ExprList_item *pItem;   /* A term of the ORDER BY clause */
+  Parse *pParse;                 /* Parsing context */
+  int nResult;                   /* Number of terms in the result set */
+
+  if( pOrderBy==0 ) return 0;
+  nResult = pSelect->pEList->nExpr;
+  pParse = pNC->pParse;
+  for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
+    Expr *pE = pItem->pExpr;
+    iCol = resolveAsName(pParse, pSelect->pEList, pE);
+    if( iCol<0 ){
+      return 1;  /* OOM error */
+    }
+    if( iCol>0 ){
+      /* If an AS-name match is found, mark this ORDER BY column as being
+      ** a copy of the iCol-th result-set column.  The subsequent call to
+      ** sqlite3ResolveOrderGroupBy() will convert the expression to a
+      ** copy of the iCol-th result-set expression. */
+      pItem->iCol = iCol;
+      continue;
+    }
+    if( sqlite3ExprIsInteger(pE, &iCol) ){
+      /* The ORDER BY term is an integer constant.  Again, set the column
+      ** number so that sqlite3ResolveOrderGroupBy() will convert the
+      ** order-by term to a copy of the result-set expression */
+      if( iCol<1 || iCol>nResult ){
+        resolveOutOfRangeError(pParse, zType, i+1, nResult);
+        return 1;
+      }
+      pItem->iCol = iCol;
+      continue;
+    }
+
+    /* Otherwise, treat the ORDER BY term as an ordinary expression */
+    pItem->iCol = 0;
+    if( sqlite3ResolveExprNames(pNC, pE) ){
+      return 1;
+    }
+  }
+  return sqlite3ResolveOrderGroupBy(pParse, pSelect, pOrderBy, zType);
+}
+
+/*
+** Resolve names in the SELECT statement p and all of its descendents.
+*/
+static int resolveSelectStep(Walker *pWalker, Select *p){
+  NameContext *pOuterNC;  /* Context that contains this SELECT */
+  NameContext sNC;        /* Name context of this SELECT */
+  int isCompound;         /* True if p is a compound select */
+  int nCompound;          /* Number of compound terms processed so far */
+  Parse *pParse;          /* Parsing context */
+  ExprList *pEList;       /* Result set expression list */
+  int i;                  /* Loop counter */
+  ExprList *pGroupBy;     /* The GROUP BY clause */
+  Select *pLeftmost;      /* Left-most of SELECT of a compound */
+  sqlite3 *db;            /* Database connection */
+  
+
+  if( p==0 ) return WRC_Continue;
+  if( p->selFlags & SF_Resolved ){
+    return WRC_Prune;
+  }
+  pOuterNC = pWalker->u.pNC;
+  pParse = pWalker->pParse;
+  db = pParse->db;
+
+  /* Normally sqlite3SelectExpand() will be called first and will have
+  ** already expanded this SELECT.  However, if this is a subquery within
+  ** an expression, sqlite3ResolveExprNames() will be called without a
+  ** prior call to sqlite3SelectExpand().  When that happens, let
+  ** sqlite3SelectPrep() do all of the processing for this SELECT.
+  ** sqlite3SelectPrep() will invoke both sqlite3SelectExpand() and
+  ** this routine in the correct order.
+  */
+  if( (p->selFlags & SF_Expanded)==0 ){
+    sqlite3SelectPrep(pParse, p, pOuterNC);
+    return (pParse->nErr || db->mallocFailed) ? WRC_Abort : WRC_Prune;
+  }
+
+  isCompound = p->pPrior!=0;
+  nCompound = 0;
+  pLeftmost = p;
+  while( p ){
+    assert( (p->selFlags & SF_Expanded)!=0 );
+    assert( (p->selFlags & SF_Resolved)==0 );
+    p->selFlags |= SF_Resolved;
+
+    /* Resolve the expressions in the LIMIT and OFFSET clauses. These
+    ** are not allowed to refer to any names, so pass an empty NameContext.
+    */
+    memset(&sNC, 0, sizeof(sNC));
+    sNC.pParse = pParse;
+    if( sqlite3ResolveExprNames(&sNC, p->pLimit) ||
+        sqlite3ResolveExprNames(&sNC, p->pOffset) ){
+      return WRC_Abort;
+    }
+  
+    /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
+    ** resolve the result-set expression list.
+    */
+    sNC.allowAgg = 1;
+    sNC.pSrcList = p->pSrc;
+    sNC.pNext = pOuterNC;
+  
+    /* Resolve names in the result set. */
+    pEList = p->pEList;
+    if( !pEList ) return WRC_Abort;
+    for(i=0; i<pEList->nExpr; i++){
+      Expr *pX = pEList->a[i].pExpr;
+      if( sqlite3ResolveExprNames(&sNC, pX) ){
+        return WRC_Abort;
+      }
+    }
+  
+    /* Recursively resolve names in all subqueries
+    */
+    for(i=0; i<p->pSrc->nSrc; i++){
+      struct SrcList_item *pItem = &p->pSrc->a[i];
+      if( pItem->pSelect ){
+        const char *zSavedContext = pParse->zAuthContext;
+        if( pItem->zName ) pParse->zAuthContext = pItem->zName;
+        sqlite3ResolveSelectNames(pParse, pItem->pSelect, &sNC);
+        pParse->zAuthContext = zSavedContext;
+        if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
+      }
+    }
+  
+    /* If there are no aggregate functions in the result-set, and no GROUP BY 
+    ** expression, do not allow aggregates in any of the other expressions.
+    */
+    assert( (p->selFlags & SF_Aggregate)==0 );
+    pGroupBy = p->pGroupBy;
+    if( pGroupBy || sNC.hasAgg ){
+      p->selFlags |= SF_Aggregate;
+    }else{
+      sNC.allowAgg = 0;
+    }
+  
+    /* If a HAVING clause is present, then there must be a GROUP BY clause.
+    */
+    if( p->pHaving && !pGroupBy ){
+      sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
+      return WRC_Abort;
+    }
+  
+    /* Add the expression list to the name-context before parsing the
+    ** other expressions in the SELECT statement. This is so that
+    ** expressions in the WHERE clause (etc.) can refer to expressions by
+    ** aliases in the result set.
+    **
+    ** Minor point: If this is the case, then the expression will be
+    ** re-evaluated for each reference to it.
+    */
+    sNC.pEList = p->pEList;
+    if( sqlite3ResolveExprNames(&sNC, p->pWhere) ||
+       sqlite3ResolveExprNames(&sNC, p->pHaving)
+    ){
+      return WRC_Abort;
+    }
+
+    /* The ORDER BY and GROUP BY clauses may not refer to terms in
+    ** outer queries 
+    */
+    sNC.pNext = 0;
+    sNC.allowAgg = 1;
+
+    /* Process the ORDER BY clause for singleton SELECT statements.
+    ** The ORDER BY clause for compounds SELECT statements is handled
+    ** below, after all of the result-sets for all of the elements of
+    ** the compound have been resolved.
+    */
+    if( !isCompound && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") ){
+      return WRC_Abort;
+    }
+    if( db->mallocFailed ){
+      return WRC_Abort;
+    }
+  
+    /* Resolve the GROUP BY clause.  At the same time, make sure 
+    ** the GROUP BY clause does not contain aggregate functions.
+    */
+    if( pGroupBy ){
+      struct ExprList_item *pItem;
+    
+      if( resolveOrderGroupBy(&sNC, p, pGroupBy, "GROUP") || db->mallocFailed ){
+        return WRC_Abort;
+      }
+      for(i=0, pItem=pGroupBy->a; i<pGroupBy->nExpr; i++, pItem++){
+        if( ExprHasProperty(pItem->pExpr, EP_Agg) ){
+          sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
+              "the GROUP BY clause");
+          return WRC_Abort;
+        }
+      }
+    }
+
+    /* Advance to the next term of the compound
+    */
+    p = p->pPrior;
+    nCompound++;
+  }
+
+  /* Resolve the ORDER BY on a compound SELECT after all terms of
+  ** the compound have been resolved.
+  */
+  if( isCompound && resolveCompoundOrderBy(pParse, pLeftmost) ){
+    return WRC_Abort;
+  }
+
+  return WRC_Prune;
+}
+
+/*
+** This routine walks an expression tree and resolves references to
+** table columns and result-set columns.  At the same time, do error
+** checking on function usage and set a flag if any aggregate functions
+** are seen.
+**
+** To resolve table columns references we look for nodes (or subtrees) of the 
+** form X.Y.Z or Y.Z or just Z where
+**
+**      X:   The name of a database.  Ex:  "main" or "temp" or
+**           the symbolic name assigned to an ATTACH-ed database.
+**
+**      Y:   The name of a table in a FROM clause.  Or in a trigger
+**           one of the special names "old" or "new".
+**
+**      Z:   The name of a column in table Y.
+**
+** The node at the root of the subtree is modified as follows:
+**
+**    Expr.op        Changed to TK_COLUMN
+**    Expr.pTab      Points to the Table object for X.Y
+**    Expr.iColumn   The column index in X.Y.  -1 for the rowid.
+**    Expr.iTable    The VDBE cursor number for X.Y
+**
+**
+** To resolve result-set references, look for expression nodes of the
+** form Z (with no X and Y prefix) where the Z matches the right-hand
+** size of an AS clause in the result-set of a SELECT.  The Z expression
+** is replaced by a copy of the left-hand side of the result-set expression.
+** Table-name and function resolution occurs on the substituted expression
+** tree.  For example, in:
+**
+**      SELECT a+b AS x, c+d AS y FROM t1 ORDER BY x;
+**
+** The "x" term of the order by is replaced by "a+b" to render:
+**
+**      SELECT a+b AS x, c+d AS y FROM t1 ORDER BY a+b;
+**
+** Function calls are checked to make sure that the function is 
+** defined and that the correct number of arguments are specified.
+** If the function is an aggregate function, then the pNC->hasAgg is
+** set and the opcode is changed from TK_FUNCTION to TK_AGG_FUNCTION.
+** If an expression contains aggregate functions then the EP_Agg
+** property on the expression is set.
+**
+** An error message is left in pParse if anything is amiss.  The number
+** if errors is returned.
+*/
+int sqlite3ResolveExprNames( 
+  NameContext *pNC,       /* Namespace to resolve expressions in. */
+  Expr *pExpr             /* The expression to be analyzed. */
+){
+  int savedHasAgg;
+  Walker w;
+
+  if( pExpr==0 ) return 0;
+#if SQLITE_MAX_EXPR_DEPTH>0
+  {
+    Parse *pParse = pNC->pParse;
+    if( sqlite3ExprCheckHeight(pParse, pExpr->nHeight+pNC->pParse->nHeight) ){
+      return 1;
+    }
+    pParse->nHeight += pExpr->nHeight;
+  }
+#endif
+  savedHasAgg = pNC->hasAgg;
+  pNC->hasAgg = 0;
+  w.xExprCallback = resolveExprStep;
+  w.xSelectCallback = resolveSelectStep;
+  w.pParse = pNC->pParse;
+  w.u.pNC = pNC;
+  sqlite3WalkExpr(&w, pExpr);
+#if SQLITE_MAX_EXPR_DEPTH>0
+  pNC->pParse->nHeight -= pExpr->nHeight;
+#endif
+  if( pNC->nErr>0 ){
+    ExprSetProperty(pExpr, EP_Error);
+  }
+  if( pNC->hasAgg ){
+    ExprSetProperty(pExpr, EP_Agg);
+  }else if( savedHasAgg ){
+    pNC->hasAgg = 1;
+  }
+  return ExprHasProperty(pExpr, EP_Error);
+}
+int sqlite3ResolveExprListNames( 
+  NameContext *pNC,       /* Namespace to resolve expressions in. */
+  ExprList *pList         /* List of expressions to be analyzed. */
+){
+  int i;
+  struct ExprList_item *pItem;
+  if( pList==0 ) return 0;
+  for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
+    if( sqlite3ResolveExprNames(pNC, pItem->pExpr) ) return 1;
+  }
+  return 0;
+}
+
+
+/*
+** Resolve all names in all expressions of a SELECT and in all
+** decendents of the SELECT, including compounds off of p->pPrior,
+** subqueries in expressions, and subqueries used as FROM clause
+** terms.
+**
+** See sqlite3ResolveExprNames() for a description of the kinds of
+** transformations that occur.
+**
+** All SELECT statements should have been expanded using
+** sqlite3SelectExpand() prior to invoking this routine.
+*/
+void sqlite3ResolveSelectNames(
+  Parse *pParse,         /* The parser context */
+  Select *p,             /* The SELECT statement being coded. */
+  NameContext *pOuterNC  /* Name context for parent SELECT statement */
+){
+  Walker w;
+
+  if( p ){
+    w.xExprCallback = resolveExprStep;
+    w.xSelectCallback = resolveSelectStep;
+    w.pParse = pParse;
+    w.u.pNC = pOuterNC;
+    sqlite3WalkSelect(&w, p);
+  }
+}
index 7de282e55cae44befcfde018e006549a666f0f4d..e4eb186e74a482c8733f441d7743624ee391e008 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle SELECT statements in SQLite.
 **
-** $Id: select.c,v 1.465 2008/08/14 00:19:49 drh Exp $
+** $Id: select.c,v 1.466 2008/08/20 16:35:10 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -79,7 +79,7 @@ Select *sqlite3SelectNew(
   pNew->pGroupBy = pGroupBy;
   pNew->pHaving = pHaving;
   pNew->pOrderBy = pOrderBy;
-  pNew->isDistinct = isDistinct;
+  pNew->selFlags = isDistinct ? SF_Distinct : 0;
   pNew->op = TK_SELECT;
   assert( pOffset==0 || pLimit!=0 );
   pNew->pLimit = pLimit;
@@ -573,7 +573,7 @@ static void selectInnerLoop(
     /* If the destination is an EXISTS(...) expression, the actual
     ** values returned by the SELECT are not required.
     */
-    sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Callback);
+    sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Output);
   }
   nColumn = nResultCol;
 
@@ -690,7 +690,7 @@ static void selectInnerLoop(
     ** popping the data from the stack.
     */
     case SRT_Coroutine:
-    case SRT_Callback: {
+    case SRT_Output: {
       if( pOrderBy ){
         int r1 = sqlite3GetTempReg(pParse);
         sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
@@ -797,10 +797,10 @@ static void generateSortTail(
   int regRowid;
 
   iTab = pOrderBy->iECursor;
-  if( eDest==SRT_Callback || eDest==SRT_Coroutine ){
+  if( eDest==SRT_Output || eDest==SRT_Coroutine ){
     pseudoTab = pParse->nTab++;
     sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, nColumn);
-    sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, eDest==SRT_Callback);
+    sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, eDest==SRT_Output);
   }
   addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, brk);
   codeOffset(v, p, cont);
@@ -830,7 +830,7 @@ static void generateSortTail(
       break;
     }
 #endif
-    case SRT_Callback:
+    case SRT_Output:
     case SRT_Coroutine: {
       int i;
       sqlite3VdbeAddOp2(v, OP_Integer, 1, regRowid);
@@ -839,7 +839,7 @@ static void generateSortTail(
         assert( regRow!=pDest->iMem+i );
         sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iMem+i);
       }
-      if( eDest==SRT_Callback ){
+      if( eDest==SRT_Output ){
         sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn);
         sqlite3ExprCacheAffinityChange(pParse, pDest->iMem, nColumn);
       }else{
@@ -864,7 +864,7 @@ static void generateSortTail(
   sqlite3VdbeResolveLabel(v, cont);
   sqlite3VdbeAddOp2(v, OP_Next, iTab, addr);
   sqlite3VdbeResolveLabel(v, brk);
-  if( eDest==SRT_Callback || eDest==SRT_Coroutine ){
+  if( eDest==SRT_Output || eDest==SRT_Coroutine ){
     sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0);
   }
 
@@ -1128,58 +1128,36 @@ static const char *selectOpName(int id){
 #endif /* SQLITE_OMIT_COMPOUND_SELECT */
 
 /*
-** Forward declaration
-*/
-static int prepSelectStmt(Parse*, Select*);
-
-/*
-** Given a SELECT statement, generate a Table structure that describes
-** the result set of that SELECT.
+** Given a an expression list (which is really the list of expressions
+** that form the result set of a SELECT statement) compute appropriate
+** column names for a table that would hold the expression list.
+**
+** All column names will be unique.
+**
+** Only the column names are computed.  Column.zType, Column.zColl,
+** and other fields of Column are zeroed.
+**
+** Return SQLITE_OK on success.  If a memory allocation error occurs,
+** store NULL in *paCol and 0 in *pnCol and return SQLITE_NOMEM.
 */
-Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
-  Table *pTab;
-  int i, j, rc;
-  ExprList *pEList;
-  Column *aCol, *pCol;
+static int selectColumnsFromExprList(
+  Parse *pParse,          /* Parsing context */
+  ExprList *pEList,       /* Expr list from which to derive column names */
+  int *pnCol,             /* Write the number of columns here */
+  Column **paCol          /* Write the new column list here */
+){
   sqlite3 *db = pParse->db;
-  int savedFlags;
-
-  savedFlags = db->flags;
-  db->flags &= ~SQLITE_FullColNames;
-  db->flags |= SQLITE_ShortColNames;
-  rc = sqlite3SelectResolve(pParse, pSelect, 0);
-  if( rc==SQLITE_OK ){
-    while( pSelect->pPrior ) pSelect = pSelect->pPrior;
-    rc = prepSelectStmt(pParse, pSelect);
-    if( rc==SQLITE_OK ){
-      rc = sqlite3SelectResolve(pParse, pSelect, 0);
-    }
-  }
-  db->flags = savedFlags;
-  if( rc ){
-    return 0;
-  }
-  pTab = sqlite3DbMallocZero(db, sizeof(Table) );
-  if( pTab==0 ){
-    return 0;
-  }
-  pTab->db = db;
-  pTab->nRef = 1;
-  pTab->zName = zTabName ? sqlite3DbStrDup(db, zTabName) : 0;
-  pEList = pSelect->pEList;
-  pTab->nCol = pEList->nExpr;
-  assert( pTab->nCol>0 );
-  pTab->aCol = aCol = sqlite3DbMallocZero(db, sizeof(pTab->aCol[0])*pTab->nCol);
-  testcase( aCol==0 );
-  for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){
-    Expr *p;
-    char *zType;
-    char *zName;
-    int nName;
-    CollSeq *pColl;
-    int cnt;
-    NameContext sNC;
-    
+  int i, j, cnt;
+  Column *aCol, *pCol;
+  int nCol;
+  Expr *p;
+  char *zName;
+  int nName;
+
+  *pnCol = nCol = pEList->nExpr;
+  aCol = *paCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol);
+  if( aCol==0 ) return SQLITE_NOMEM;
+  for(i=0, pCol=aCol; i<nCol; i++, pCol++){
     /* Get an appropriate name for the column
     */
     p = pEList->a[i].pExpr;
@@ -1187,14 +1165,18 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
     if( (zName = pEList->a[i].zName)!=0 ){
       /* If the column contains an "AS <name>" phrase, use <name> as the name */
       zName = sqlite3DbStrDup(db, zName);
-    }else if( p->op==TK_COLUMN && p->pTab ){
-      /* For columns use the column name name */
-      int iCol = p->iColumn;
-      if( iCol<0 ) iCol = p->pTab->iPKey;
-      zName = sqlite3MPrintf(db, "%s", p->pTab->aCol[iCol].zName);
     }else{
-      /* Use the original text of the column expression as its name */
-      zName = sqlite3MPrintf(db, "%T", &p->span);
+      Expr *pCol = p;
+      while( pCol->op==TK_DOT ) pCol = pCol->pRight;
+      if( pCol->op==TK_COLUMN && pCol->pTab ){
+        /* For columns use the column name name */
+        int iCol = pCol->iColumn;
+        if( iCol<0 ) iCol = pCol->pTab->iPKey;
+        zName = sqlite3MPrintf(db, "%s", pCol->pTab->aCol[iCol].zName);
+      }else{
+        /* Use the original text of the column expression as its name */
+        zName = sqlite3MPrintf(db, "%T", &pCol->span);
+      }
     }
     if( db->mallocFailed ){
       sqlite3DbFree(db, zName);
@@ -1218,518 +1200,94 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
       }
     }
     pCol->zName = zName;
-
-    /* Get the typename, type affinity, and collating sequence for the
-    ** column.
-    */
-    memset(&sNC, 0, sizeof(sNC));
-    sNC.pSrcList = pSelect->pSrc;
-    zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
-    pCol->zType = zType;
-    pCol->affinity = sqlite3ExprAffinity(p);
-    pColl = sqlite3ExprCollSeq(pParse, p);
-    if( pColl ){
-      pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
-    }
   }
-  pTab->iPKey = -1;
   if( db->mallocFailed ){
-    sqlite3DeleteTable(pTab);
-    return 0;
-  }
-  return pTab;
-}
-
-/*
-** Prepare a SELECT statement for processing by doing the following
-** things:
-**
-**    (1)  Make sure VDBE cursor numbers have been assigned to every
-**         element of the FROM clause.
-**
-**    (2)  Fill in the pTabList->a[].pTab fields in the SrcList that 
-**         defines FROM clause.  When views appear in the FROM clause,
-**         fill pTabList->a[].pSelect with a copy of the SELECT statement
-**         that implements the view.  A copy is made of the view's SELECT
-**         statement so that we can freely modify or delete that statement
-**         without worrying about messing up the presistent representation
-**         of the view.
-**
-**    (3)  Add terms to the WHERE clause to accomodate the NATURAL keyword
-**         on joins and the ON and USING clause of joins.
-**
-**    (4)  Scan the list of columns in the result set (pEList) looking
-**         for instances of the "*" operator or the TABLE.* operator.
-**         If found, expand each "*" to be every column in every table
-**         and TABLE.* to be every column in TABLE.
-**
-** Return 0 on success.  If there are problems, leave an error message
-** in pParse and return non-zero.
-*/
-static int prepSelectStmt(Parse *pParse, Select *p){
-  int i, j, k, rc;
-  SrcList *pTabList;
-  ExprList *pEList;
-  struct SrcList_item *pFrom;
-  sqlite3 *db = pParse->db;
-
-  if( p==0 || p->pSrc==0 || db->mallocFailed ){
-    return 1;
-  }
-  pTabList = p->pSrc;
-  pEList = p->pEList;
-
-  /* Make sure cursor numbers have been assigned to all entries in
-  ** the FROM clause of the SELECT statement.
-  */
-  sqlite3SrcListAssignCursors(pParse, p->pSrc);
-
-  /* Look up every table named in the FROM clause of the select.  If
-  ** an entry of the FROM clause is a subquery instead of a table or view,
-  ** then create a transient table structure to describe the subquery.
-  */
-  for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
-    Table *pTab;
-    if( pFrom->pTab!=0 ){
-      /* This statement has already been prepared.  There is no need
-      ** to go further. */
-      assert( i==0 );
-      return 0;
-    }
-    if( pFrom->zName==0 ){
-#ifndef SQLITE_OMIT_SUBQUERY
-      /* A sub-query in the FROM clause of a SELECT */
-      assert( pFrom->pSelect!=0 );
-      if( pFrom->zAlias==0 ){
-        pFrom->zAlias =
-          sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pFrom->pSelect);
-      }
-      assert( pFrom->pTab==0 );
-      pFrom->pTab = pTab = 
-        sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect);
-      if( pTab==0 ){
-        return 1;
-      }
-      /* The isEphem flag indicates that the Table structure has been
-      ** dynamically allocated and may be freed at any time.  In other words,
-      ** pTab is not pointing to a persistent table structure that defines
-      ** part of the schema. */
-      pTab->isEphem = 1;
-#endif
-    }else{
-      /* An ordinary table or view name in the FROM clause */
-      assert( pFrom->pTab==0 );
-      pFrom->pTab = pTab = 
-        sqlite3LocateTable(pParse,0,pFrom->zName,pFrom->zDatabase);
-      if( pTab==0 ){
-        return 1;
-      }
-      pTab->nRef++;
-#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
-      if( pTab->pSelect || IsVirtual(pTab) ){
-        /* We reach here if the named table is a really a view */
-        if( sqlite3ViewGetColumnNames(pParse, pTab) ){
-          return 1;
-        }
-        /* If pFrom->pSelect!=0 it means we are dealing with a
-        ** view within a view.  The SELECT structure has already been
-        ** copied by the outer view so we can skip the copy step here
-        ** in the inner view.
-        */
-        if( pFrom->pSelect==0 ){
-          pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect);
-        }
-      }
-#endif
+    int j;
+    for(j=0; j<i; j++){
+      sqlite3DbFree(db, aCol[j].zName);
     }
+    sqlite3DbFree(db, aCol);
+    *paCol = 0;
+    *pnCol = 0;
+    return SQLITE_NOMEM;
   }
-
-  /* Process NATURAL keywords, and ON and USING clauses of joins.
-  */
-  if( sqliteProcessJoin(pParse, p) ) return 1;
-
-  /* For every "*" that occurs in the column list, insert the names of
-  ** all columns in all tables.  And for every TABLE.* insert the names
-  ** of all columns in TABLE.  The parser inserted a special expression
-  ** with the TK_ALL operator for each "*" that it found in the column list.
-  ** The following code just has to locate the TK_ALL expressions and expand
-  ** each one to the list of all columns in all tables.
-  **
-  ** The first loop just checks to see if there are any "*" operators
-  ** that need expanding.
-  */
-  for(k=0; k<pEList->nExpr; k++){
-    Expr *pE = pEList->a[k].pExpr;
-    if( pE->op==TK_ALL ) break;
-    if( pE->op==TK_DOT && pE->pRight && pE->pRight->op==TK_ALL
-         && pE->pLeft && pE->pLeft->op==TK_ID ) break;
-  }
-  rc = 0;
-  if( k<pEList->nExpr ){
-    /*
-    ** If we get here it means the result set contains one or more "*"
-    ** operators that need to be expanded.  Loop through each expression
-    ** in the result set and expand them one by one.
-    */
-    struct ExprList_item *a = pEList->a;
-    ExprList *pNew = 0;
-    int flags = pParse->db->flags;
-    int longNames = (flags & SQLITE_FullColNames)!=0
-                      && (flags & SQLITE_ShortColNames)==0;
-
-    for(k=0; k<pEList->nExpr; k++){
-      Expr *pE = a[k].pExpr;
-      if( pE->op!=TK_ALL &&
-           (pE->op!=TK_DOT || pE->pRight==0 || pE->pRight->op!=TK_ALL) ){
-        /* This particular expression does not need to be expanded.
-        */
-        pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr, 0);
-        if( pNew ){
-          pNew->a[pNew->nExpr-1].zName = a[k].zName;
-        }else{
-          rc = 1;
-        }
-        a[k].pExpr = 0;
-        a[k].zName = 0;
-      }else{
-        /* This expression is a "*" or a "TABLE.*" and needs to be
-        ** expanded. */
-        int tableSeen = 0;      /* Set to 1 when TABLE matches */
-        char *zTName;            /* text of name of TABLE */
-        if( pE->op==TK_DOT && pE->pLeft ){
-          zTName = sqlite3NameFromToken(db, &pE->pLeft->token);
-        }else{
-          zTName = 0;
-        }
-        for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
-          Table *pTab = pFrom->pTab;
-          char *zTabName = pFrom->zAlias;
-          if( zTabName==0 || zTabName[0]==0 ){ 
-            zTabName = pTab->zName;
-          }
-          assert( zTabName );
-          if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
-            continue;
-          }
-          tableSeen = 1;
-          for(j=0; j<pTab->nCol; j++){
-            Expr *pExpr, *pRight;
-            char *zName = pTab->aCol[j].zName;
-
-            /* If a column is marked as 'hidden' (currently only possible
-            ** for virtual tables), do not include it in the expanded
-            ** result-set list.
-            */
-            if( IsHiddenColumn(&pTab->aCol[j]) ){
-              assert(IsVirtual(pTab));
-              continue;
-            }
-
-            if( i>0 ){
-              struct SrcList_item *pLeft = &pTabList->a[i-1];
-              if( (pLeft[1].jointype & JT_NATURAL)!=0 &&
-                        columnIndex(pLeft->pTab, zName)>=0 ){
-                /* In a NATURAL join, omit the join columns from the 
-                ** table on the right */
-                continue;
-              }
-              if( sqlite3IdListIndex(pLeft[1].pUsing, zName)>=0 ){
-                /* In a join with a USING clause, omit columns in the
-                ** using clause from the table on the right. */
-                continue;
-              }
-            }
-            pRight = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
-            if( pRight==0 ) break;
-            setQuotedToken(pParse, &pRight->token, zName);
-            if( longNames || pTabList->nSrc>1 ){
-              Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
-              pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
-              if( pExpr==0 ) break;
-              setQuotedToken(pParse, &pLeft->token, zTabName);
-#if 1
-              setToken(&pExpr->span, 
-                  sqlite3MPrintf(db, "%s.%s", zTabName, zName));
-              pExpr->span.dyn = 1;
-#else
-              pExpr->span = pRight->token;
-              pExpr->span.dyn = 0;
-#endif
-              pExpr->token.z = 0;
-              pExpr->token.n = 0;
-              pExpr->token.dyn = 0;
-            }else{
-              pExpr = pRight;
-              pExpr->span = pExpr->token;
-              pExpr->span.dyn = 0;
-            }
-            if( longNames ){
-              pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pExpr->span);
-            }else{
-              pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pRight->token);
-            }
-          }
-        }
-        if( !tableSeen ){
-          if( zTName ){
-            sqlite3ErrorMsg(pParse, "no such table: %s", zTName);
-          }else{
-            sqlite3ErrorMsg(pParse, "no tables specified");
-          }
-          rc = 1;
-        }
-        sqlite3DbFree(db, zTName);
-      }
-    }
-    sqlite3ExprListDelete(db, pEList);
-    p->pEList = pNew;
-  }
-#if SQLITE_MAX_COLUMN
-  if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
-    sqlite3ErrorMsg(pParse, "too many columns in result set");
-    rc = SQLITE_ERROR;
-  }
-#endif
-  if( db->mallocFailed ){
-    rc = SQLITE_NOMEM;
-  }
-  return rc;
+  return SQLITE_OK;
 }
 
 /*
-** pE is a pointer to an expression which is a single term in
-** ORDER BY or GROUP BY clause.
-**
-** At the point this routine is called, we already know that the
-** ORDER BY term is not an integer index into the result set.  That
-** casee is handled by the calling routine.
-**
-** If pE is a well-formed expression and the SELECT statement
-** is not compound, then return 0.  This indicates to the
-** caller that it should sort by the value of the ORDER BY
-** expression.
+** 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.
 **
-** If the SELECT is compound, then attempt to match pE against
-** result set columns in the left-most SELECT statement.  Return
-** the index i of the matching column, as an indication to the 
-** caller that it should sort by the i-th column.  If there is
-** no match, return -1 and leave an error message in pParse.
+** This routine requires that all indentifiers in the SELECT
+** statement be resolved.
 */
-static int matchOrderByTermToExprList(
-  Parse *pParse,     /* Parsing context for error messages */
-  Select *pSelect,   /* The SELECT statement with the ORDER BY clause */
-  Expr *pE,          /* The specific ORDER BY term */
-  int idx,           /* When ORDER BY term is this */
-  int isCompound,    /* True if this is a compound SELECT */
-  u8 *pHasAgg        /* True if expression contains aggregate functions */
+static void selectAddColumnTypeAndCollation(
+  Parse *pParse,        /* Parsing contexts */
+  int nCol,             /* Number of columns */
+  Column *aCol,         /* List of columns */
+  Select *pSelect       /* SELECT used to determine types and collations */
 ){
-  int i;             /* Loop counter */
-  ExprList *pEList;  /* The columns of the result set */
-  NameContext nc;    /* Name context for resolving pE */
-
-  assert( sqlite3ExprIsInteger(pE, &i)==0 );
-  pEList = pSelect->pEList;
-
-  /* If the term is a simple identifier that try to match that identifier
-  ** against a column name in the result set.
-  */
-  if( pE->op==TK_ID || (pE->op==TK_STRING && pE->token.z[0]!='\'') ){
-    sqlite3 *db = pParse->db;
-    char *zCol = sqlite3NameFromToken(db, &pE->token);
-    if( zCol==0 ){
-      return -1;
-    }
-    for(i=0; i<pEList->nExpr; i++){
-      char *zAs = pEList->a[i].zName;
-      if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
-        sqlite3DbFree(db, zCol);
-        return i+1;
-      }
-    }
-    sqlite3DbFree(db, zCol);
-  }
-
-  /* Resolve all names in the ORDER BY term expression
-  */
-  memset(&nc, 0, sizeof(nc));
-  nc.pParse = pParse;
-  nc.pSrcList = pSelect->pSrc;
-  nc.pEList = pEList;
-  nc.allowAgg = 1;
-  nc.nErr = 0;
-  if( sqlite3ExprResolveNames(&nc, pE) ){
-    if( isCompound ){
-      sqlite3ErrorClear(pParse);
-      return 0;
-    }else{
-      return -1;
-    }
-  }
-  if( nc.hasAgg && pHasAgg ){
-    *pHasAgg = 1;
-  }
+  sqlite3 *db = pParse->db;
+  NameContext sNC;
+  Column *pCol;
+  CollSeq *pColl;
+  int i;
+  Expr *p;
+  struct ExprList_item *a;
 
-  /* For a compound SELECT, we need to try to match the ORDER BY
-  ** expression against an expression in the result set
-  */
-  if( isCompound ){
-    for(i=0; i<pEList->nExpr; i++){
-      if( sqlite3ExprCompare(pEList->a[i].pExpr, pE) ){
-        return i+1;
-      }
+  assert( pSelect!=0 );
+  assert( (pSelect->selFlags & SF_Resolved)!=0 );
+  assert( nCol==pSelect->pEList->nExpr || db->mallocFailed );
+  if( db->mallocFailed ) return;
+  memset(&sNC, 0, sizeof(sNC));
+  sNC.pSrcList = pSelect->pSrc;
+  a = pSelect->pEList->a;
+  for(i=0, pCol=aCol; i<nCol; i++, pCol++){
+    p = a[i].pExpr;
+    pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
+    pCol->affinity = sqlite3ExprAffinity(p);
+    pColl = sqlite3ExprCollSeq(pParse, p);
+    if( pColl ){
+      pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
     }
   }
-  return 0;
 }
 
-
 /*
-** Analyze and ORDER BY or GROUP BY clause in a simple SELECT statement.
-** Return the number of errors seen.
-**
-** Every term of the ORDER BY or GROUP BY clause needs to be an
-** expression.  If any expression is an integer constant, then
-** that expression is replaced by the corresponding 
-** expression from the result set.
+** Given a SELECT statement, generate a Table structure that describes
+** the result set of that SELECT.
 */
-static int processOrderGroupBy(
-  Parse *pParse,        /* Parsing context.  Leave error messages here */
-  Select *pSelect,      /* The SELECT statement containing the clause */
-  ExprList *pOrderBy,   /* The ORDER BY or GROUP BY clause to be processed */
-  int isOrder,          /* 1 for ORDER BY.  0 for GROUP BY */
-  u8 *pHasAgg           /* Set to TRUE if any term contains an aggregate */
-){
-  int i;
+Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
+  Table *pTab;
   sqlite3 *db = pParse->db;
-  ExprList *pEList;
+  int savedFlags;
 
-  if( pOrderBy==0 || pParse->db->mallocFailed ) return 0;
-#if SQLITE_MAX_COLUMN
-  if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
-    const char *zType = isOrder ? "ORDER" : "GROUP";
-    sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType);
-    return 1;
-  }
-#endif
-  pEList = pSelect->pEList;
-  if( pEList==0 ){
+  savedFlags = db->flags;
+  db->flags &= ~SQLITE_FullColNames;
+  db->flags |= SQLITE_ShortColNames;
+  sqlite3SelectPrep(pParse, pSelect, 0);
+  if( pParse->nErr ) return 0;
+  while( pSelect->pPrior ) pSelect = pSelect->pPrior;
+  db->flags = savedFlags;
+  pTab = sqlite3DbMallocZero(db, sizeof(Table) );
+  if( pTab==0 ){
     return 0;
   }
-  for(i=0; i<pOrderBy->nExpr; i++){
-    int iCol;
-    Expr *pE = pOrderBy->a[i].pExpr;
-    if( sqlite3ExprIsInteger(pE, &iCol) ){
-      if( iCol<=0 || iCol>pEList->nExpr ){
-        const char *zType = isOrder ? "ORDER" : "GROUP";
-        sqlite3ErrorMsg(pParse, 
-           "%r %s BY term out of range - should be "
-           "between 1 and %d", i+1, zType, pEList->nExpr);
-        return 1;
-      }
-    }else{
-      iCol = matchOrderByTermToExprList(pParse, pSelect, pE, i+1, 0, pHasAgg);
-      if( iCol<0 ){
-        return 1;
-      }
-    }
-    if( iCol>0 ){
-      CollSeq *pColl = pE->pColl;
-      int flags = pE->flags & EP_ExpCollate;
-      sqlite3ExprDelete(db, pE);
-      pE = sqlite3ExprDup(db, pEList->a[iCol-1].pExpr);
-      pOrderBy->a[i].pExpr = pE;
-      if( pE && pColl && flags ){
-        pE->pColl = pColl;
-        pE->flags |= flags;
-      }
-    }
-  }
-  return 0;
-}
-
-/*
-** Analyze and ORDER BY or GROUP BY clause in a SELECT statement.  Return
-** the number of errors seen.
-**
-** If iTable>0 then make the N-th term of the ORDER BY clause refer to
-** the N-th column of table iTable.
-**
-** If iTable==0 then transform each term of the ORDER BY clause to refer
-** to a column of the result set by number.
-*/
-static int processCompoundOrderBy(
-  Parse *pParse,        /* Parsing context.  Leave error messages here */
-  Select *pSelect       /* The SELECT statement containing the ORDER BY */
-){
-  int i;
-  ExprList *pOrderBy;
-  ExprList *pEList;
-  sqlite3 *db;
-  int moreToDo = 1;
-
-  pOrderBy = pSelect->pOrderBy;
-  if( pOrderBy==0 ) return 0;
-  db = pParse->db;
-#if SQLITE_MAX_COLUMN
-  if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
-    sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause");
-    return 1;
-  }
-#endif
-  for(i=0; i<pOrderBy->nExpr; i++){
-    pOrderBy->a[i].done = 0;
-  }
-  while( pSelect->pPrior ){
-    pSelect = pSelect->pPrior;
-  }
-  while( pSelect && moreToDo ){
-    moreToDo = 0;
-    pEList = pSelect->pEList;
-    if( pEList==0 ){
-      return 1;
-    }
-    for(i=0; i<pOrderBy->nExpr; i++){
-      int iCol = -1;
-      Expr *pE, *pDup;
-      if( pOrderBy->a[i].done ) continue;
-      pE = pOrderBy->a[i].pExpr;
-      if( sqlite3ExprIsInteger(pE, &iCol) ){
-        if( iCol<0 || iCol>pEList->nExpr ){
-          sqlite3ErrorMsg(pParse, 
-             "%r ORDER BY term out of range - should be "
-             "between 1 and %d", i+1, pEList->nExpr);
-          return 1;
-        }
-      }else{
-        pDup = sqlite3ExprDup(db, pE);
-        if( !db->mallocFailed ){
-          assert(pDup);
-          iCol = matchOrderByTermToExprList(pParse, pSelect, pDup, i+1, 1, 0);
-        }
-        sqlite3ExprDelete(db, pDup);
-        if( iCol<0 ){
-          return 1;
-        }
-      }
-      if( iCol>0 ){
-        pE->op = TK_INTEGER;
-        pE->flags |= EP_IntValue;
-        pE->iTable = iCol;
-        pOrderBy->a[i].done = 1;
-      }else{
-        moreToDo = 1;
-      }
-    }
-    pSelect = pSelect->pNext;
-  }
-  for(i=0; i<pOrderBy->nExpr; i++){
-    if( pOrderBy->a[i].done==0 ){
-      sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any "
-            "column in the result set", i+1);
-      return 1;
-    }
+  pTab->db = db;
+  pTab->nRef = 1;
+  pTab->zName = 0;
+  selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
+  selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);
+  pTab->iPKey = -1;
+  if( db->mallocFailed ){
+    sqlite3DeleteTable(pTab);
+    return 0;
   }
-  return 0;
+  return pTab;
 }
 
 /*
@@ -1946,7 +1504,7 @@ static int multiSelect(
       assert( !pPrior->pLimit );
       pPrior->pLimit = p->pLimit;
       pPrior->pOffset = p->pOffset;
-      rc = sqlite3Select(pParse, pPrior, &dest, 0, 0, 0);
+      rc = sqlite3Select(pParse, pPrior, &dest);
       p->pLimit = 0;
       p->pOffset = 0;
       if( rc ){
@@ -1959,7 +1517,7 @@ static int multiSelect(
         addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit);
         VdbeComment((v, "Jump ahead if LIMIT reached"));
       }
-      rc = sqlite3Select(pParse, p, &dest, 0, 0, 0);
+      rc = sqlite3Select(pParse, p, &dest);
       pDelete = p->pPrior;
       p->pPrior = pPrior;
       if( rc ){
@@ -1994,7 +1552,7 @@ static int multiSelect(
         addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0);
         assert( p->addrOpenEphm[0] == -1 );
         p->addrOpenEphm[0] = addr;
-        p->pRightmost->usesEphm = 1;
+        p->pRightmost->selFlags |= SF_UsesEphemeral;
         assert( p->pEList );
       }
 
@@ -2002,7 +1560,7 @@ static int multiSelect(
       */
       assert( !pPrior->pOrderBy );
       sqlite3SelectDestInit(&uniondest, priorOp, unionTab);
-      rc = sqlite3Select(pParse, pPrior, &uniondest, 0, 0, 0);
+      rc = sqlite3Select(pParse, pPrior, &uniondest);
       if( rc ){
         goto multi_select_end;
       }
@@ -2016,13 +1574,12 @@ static int multiSelect(
         op = SRT_Union;
       }
       p->pPrior = 0;
-      p->disallowOrderBy = 0;
       pLimit = p->pLimit;
       p->pLimit = 0;
       pOffset = p->pOffset;
       p->pOffset = 0;
       uniondest.eDest = op;
-      rc = sqlite3Select(pParse, p, &uniondest, 0, 0, 0);
+      rc = sqlite3Select(pParse, p, &uniondest);
       /* Query flattening in sqlite3Select() might refill p->pOrderBy.
       ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */
       sqlite3ExprListDelete(db, p->pOrderBy);
@@ -2045,7 +1602,7 @@ static int multiSelect(
       if( dest.eDest!=priorOp || unionTab!=dest.iParm ){
         int iCont, iBreak, iStart;
         assert( p->pEList );
-        if( dest.eDest==SRT_Callback ){
+        if( dest.eDest==SRT_Output ){
           Select *pFirst = p;
           while( pFirst->pPrior ) pFirst = pFirst->pPrior;
           generateColumnNames(pParse, 0, pFirst->pEList);
@@ -2083,13 +1640,13 @@ static int multiSelect(
       addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0);
       assert( p->addrOpenEphm[0] == -1 );
       p->addrOpenEphm[0] = addr;
-      p->pRightmost->usesEphm = 1;
+      p->pRightmost->selFlags |= SF_UsesEphemeral;
       assert( p->pEList );
 
       /* Code the SELECTs to our left into temporary table "tab1".
       */
       sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
-      rc = sqlite3Select(pParse, pPrior, &intersectdest, 0, 0, 0);
+      rc = sqlite3Select(pParse, pPrior, &intersectdest);
       if( rc ){
         goto multi_select_end;
       }
@@ -2105,7 +1662,7 @@ static int multiSelect(
       pOffset = p->pOffset;
       p->pOffset = 0;
       intersectdest.iParm = tab2;
-      rc = sqlite3Select(pParse, p, &intersectdest, 0, 0, 0);
+      rc = sqlite3Select(pParse, p, &intersectdest);
       pDelete = p->pPrior;
       p->pPrior = pPrior;
       sqlite3ExprDelete(db, p->pLimit);
@@ -2119,7 +1676,7 @@ static int multiSelect(
       ** tables.
       */
       assert( p->pEList );
-      if( dest.eDest==SRT_Callback ){
+      if( dest.eDest==SRT_Output ){
         Select *pFirst = p;
         while( pFirst->pPrior ) pFirst = pFirst->pPrior;
         generateColumnNames(pParse, 0, pFirst->pEList);
@@ -2152,7 +1709,7 @@ static int multiSelect(
   ** SELECT might also skip this part if it has no ORDER BY clause and
   ** no temp tables are required.
   */
-  if( p->usesEphm ){
+  if( p->selFlags & SF_UsesEphemeral ){
     int i;                        /* Loop counter */
     KeyInfo *pKeyInfo;            /* Collating sequence for the result set */
     Select *pLoop;                /* For looping through SELECT statements */
@@ -2315,9 +1872,8 @@ static int generateOutputSubroutine(
     }
 #endif /* #ifndef SQLITE_OMIT_SUBQUERY */
 
-    /* Send the data to the callback function or to a subroutine.  In the
-    ** case of a subroutine, the subroutine itself is responsible for
-    ** popping the data from the stack.
+    /* The results are stored in a sequence of registers
+    ** starting at pDest->iMem.  Then the co-routine yields.
     */
     case SRT_Coroutine: {
       if( pDest->iMem==0 ){
@@ -2329,7 +1885,11 @@ static int generateOutputSubroutine(
       break;
     }
 
-    case SRT_Callback: {
+    /* Results are stored in a sequence of registers.  Then the
+    ** OP_ResultRow opcode is used to cause sqlite3_step() to return
+    ** the next row of result.
+    */
+    case SRT_Output: {
       sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iMem, pIn->nMem);
       sqlite3ExprCacheAffinityChange(pParse, pIn->iMem, pIn->nMem);
       break;
@@ -2488,7 +2048,6 @@ static int multiSelectOrderBy(
   ExprList *pOrderBy;   /* The ORDER BY clause */
   int nOrderBy;         /* Number of terms in the ORDER BY clause */
   int *aPermute;        /* Mapping from ORDER BY terms to result set columns */
-  u8 NotUsed;           /* Dummy variables */
 
   assert( p->pOrderBy!=0 );
   db = pParse->db;
@@ -2505,9 +2064,6 @@ static int multiSelectOrderBy(
   assert( pPrior->pOrderBy==0 );
   pOrderBy = p->pOrderBy;
   assert( pOrderBy );
-  if( processCompoundOrderBy(pParse, p) ){
-    return SQLITE_ERROR;
-  }
   nOrderBy = pOrderBy->nExpr;
 
   /* For operators other than UNION ALL we have to make sure that
@@ -2516,11 +2072,10 @@ static int multiSelectOrderBy(
   */
   if( op!=TK_ALL ){
     for(i=1; db->mallocFailed==0 && i<=p->pEList->nExpr; i++){
-      for(j=0; j<nOrderBy; j++){
-        Expr *pTerm = pOrderBy->a[j].pExpr;
-        assert( pTerm->op==TK_INTEGER );
-        assert( (pTerm->flags & EP_IntValue)!=0 );
-        if( pTerm->iTable==i ) break;
+      struct ExprList_item *pItem;
+      for(j=0, pItem=pOrderBy->a; j<nOrderBy; j++, pItem++){
+        assert( pItem->iCol>0 );
+        if( pItem->iCol==i ) break;
       }
       if( j==nOrderBy ){
         Expr *pNew = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, 0);
@@ -2528,7 +2083,7 @@ static int multiSelectOrderBy(
         pNew->flags |= EP_IntValue;
         pNew->iTable = i;
         pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew, 0);
-        nOrderBy++;
+        pOrderBy->a[nOrderBy++].iCol = i;
       }
     }
   }
@@ -2542,12 +2097,10 @@ static int multiSelectOrderBy(
   */
   aPermute = sqlite3DbMallocRaw(db, sizeof(int)*nOrderBy);
   if( aPermute ){
-    for(i=0; i<nOrderBy; i++){
-      Expr *pTerm = pOrderBy->a[i].pExpr;
-      assert( pTerm->op==TK_INTEGER );
-      assert( (pTerm->flags & EP_IntValue)!=0 );
-      aPermute[i] = pTerm->iTable-1;
-      assert( aPermute[i]>=0 && aPermute[i]<p->pEList->nExpr );
+    struct ExprList_item *pItem;
+    for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
+      assert( pItem->iCol>0  && pItem->iCol<=p->pEList->nExpr );
+      aPermute[i] = pItem->iCol - 1;
     }
     pKeyMerge =
       sqlite3DbMallocRaw(db, sizeof(*pKeyMerge)+nOrderBy*(sizeof(CollSeq*)+1));
@@ -2606,9 +2159,9 @@ static int multiSelectOrderBy(
   */
   p->pPrior = 0;
   pPrior->pRightmost = 0;
-  processOrderGroupBy(pParse, p, p->pOrderBy, 1, &NotUsed);
+  sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER");
   if( pPrior->pPrior==0 ){
-    processOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, 1, &NotUsed);
+    sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER");
   }
 
   /* Compute the limit registers */
@@ -2648,7 +2201,7 @@ static int multiSelectOrderBy(
   */
   VdbeNoopComment((v, "Begin coroutine for left SELECT"));
   pPrior->iLimit = regLimitA;
-  sqlite3Select(pParse, pPrior, &destA, 0, 0, 0);
+  sqlite3Select(pParse, pPrior, &destA);
   sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofA);
   sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
   VdbeNoopComment((v, "End coroutine for left SELECT"));
@@ -2662,7 +2215,7 @@ static int multiSelectOrderBy(
   savedOffset = p->iOffset;
   p->iLimit = regLimitB;
   p->iOffset = 0;  
-  sqlite3Select(pParse, p, &destB, 0, 0, 0);
+  sqlite3Select(pParse, p, &destB);
   p->iLimit = savedLimit;
   p->iOffset = savedOffset;
   sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofB);
@@ -2777,7 +2330,7 @@ static int multiSelectOrderBy(
 
   /* Set the number of output columns
   */
-  if( pDest->eDest==SRT_Callback ){
+  if( pDest->eDest==SRT_Output ){
     Select *pFirst = pPrior;
     while( pFirst->pPrior ) pFirst = pFirst->pPrior;
     generateColumnNames(pParse, 0, pFirst->pEList);
@@ -3023,12 +2576,14 @@ static int flattenSubquery(
     return 0;                                            /* Restriction (15) */
   }
   if( pSubSrc->nSrc==0 ) return 0;                       /* Restriction (7)  */
-  if( (pSub->isDistinct || pSub->pLimit) 
+  if( ((pSub->selFlags & SF_Distinct)!=0 || pSub->pLimit) 
          && (pSrc->nSrc>1 || isAgg) ){          /* Restrictions (4)(5)(8)(9) */
      return 0;       
   }
-  if( p->isDistinct && subqueryIsAgg ) return 0;         /* Restriction (6)  */
-  if( (p->disallowOrderBy || p->pOrderBy) && pSub->pOrderBy ){
+  if( (p->selFlags & SF_Distinct)!=0 && subqueryIsAgg ){
+     return 0;         /* Restriction (6)  */
+  }
+  if( p->pOrderBy && pSub->pOrderBy ){
      return 0;                                           /* Restriction (11) */
   }
   if( isAgg && pSub->pOrderBy ) return 0;                /* Restriction (16) */
@@ -3075,11 +2630,11 @@ static int flattenSubquery(
   ** queries.
   */
   if( pSub->pPrior ){
-    if( p->pPrior || isAgg || p->isDistinct || pSrc->nSrc!=1 ){
+    if( p->pPrior || isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){
       return 0;
     }
     for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){
-      if( pSub1->isAgg || pSub1->isDistinct 
+      if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0
        || (pSub1->pPrior && pSub1->op!=TK_ALL) 
        || !pSub1->pSrc || pSub1->pSrc->nSrc!=1
       ){
@@ -3091,20 +2646,21 @@ static int flattenSubquery(
     if( p->pOrderBy ){
       int ii;
       for(ii=0; ii<p->pOrderBy->nExpr; ii++){
-        Expr *pExpr = p->pOrderBy->a[ii].pExpr;
-        if( pExpr->op!=TK_COLUMN || pExpr->iTable!=iParent ){ 
-          return 0;
-        }
+        if( p->pOrderBy->a[ii].iCol==0 ) return 0;
       }
     }
   }
 
+  /***** If we reach this point, flattening is permitted. *****/
+
+  /* Authorize the subquery */
   pParse->zAuthContext = pSubitem->zName;
   sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0);
   pParse->zAuthContext = zSavedAuthContext;
 
-  /* If the sub-query is a compound SELECT statement, then it must be
-  ** a UNION ALL and the parent query must be of the form:
+  /* If the sub-query is a compound SELECT statement, then (by restrictions
+  ** 17 and 18 above) it must be a UNION ALL and the parent query must 
+  ** be of the form:
   **
   **     SELECT <expr-list> FROM (<sub-query>) <where-clause> 
   **
@@ -3136,8 +2692,8 @@ static int flattenSubquery(
     pNew->pRightmost = 0;
   }
 
-  /* If we reach this point, it means flattening is permitted for the
-  ** iFrom-th entry of the FROM clause in the outer query.
+  /* Begin flattening the iFrom-th entry of the FROM clause 
+  ** in the outer query.
   */
   pSub = pSub1 = pSubitem->pSelect;
   for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
@@ -3241,7 +2797,7 @@ static int flattenSubquery(
     /* The flattened query is distinct if either the inner or the
     ** outer query is distinct. 
     */
-    pParent->isDistinct = pParent->isDistinct || pSub->isDistinct;
+    pParent->selFlags |= pSub->selFlags & SF_Distinct;
   
     /*
     ** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y;
@@ -3294,133 +2850,373 @@ static int minMaxQuery(Parse *pParse, Select *p){
 }
 
 /*
-** This routine resolves any names used in the result set of the
-** supplied SELECT statement. If the SELECT statement being resolved
-** is a sub-select, then pOuterNC is a pointer to the NameContext 
-** of the parent SELECT.
+** This routine is a Walker callback for "expanding" a SELECT statement.
+** "Expanding" means to do the following:
+**
+**    (1)  Make sure VDBE cursor numbers have been assigned to every
+**         element of the FROM clause.
+**
+**    (2)  Fill in the pTabList->a[].pTab fields in the SrcList that 
+**         defines FROM clause.  When views appear in the FROM clause,
+**         fill pTabList->a[].pSelect with a copy of the SELECT statement
+**         that implements the view.  A copy is made of the view's SELECT
+**         statement so that we can freely modify or delete that statement
+**         without worrying about messing up the presistent representation
+**         of the view.
+**
+**    (3)  Add terms to the WHERE clause to accomodate the NATURAL keyword
+**         on joins and the ON and USING clause of joins.
+**
+**    (4)  Scan the list of columns in the result set (pEList) looking
+**         for instances of the "*" operator or the TABLE.* operator.
+**         If found, expand each "*" to be every column in every table
+**         and TABLE.* to be every column in TABLE.
+**
 */
-int sqlite3SelectResolve(
-  Parse *pParse,         /* The parser context */
-  Select *p,             /* The SELECT statement being coded. */
-  NameContext *pOuterNC  /* The outer name context. May be NULL. */
-){
-  ExprList *pEList;          /* Result set. */
-  int i;                     /* For-loop variable used in multiple places */
-  NameContext sNC;           /* Local name-context */
-  ExprList *pGroupBy;        /* The group by clause */
-
-  /* If this routine has run before, return immediately. */
-  if( p->isResolved ){
-    assert( !pOuterNC );
-    return SQLITE_OK;
-  }
-  p->isResolved = 1;
+static int selectExpander(Walker *pWalker, Select *p){
+  Parse *pParse = pWalker->pParse;
+  int i, j, k;
+  SrcList *pTabList;
+  ExprList *pEList;
+  struct SrcList_item *pFrom;
+  sqlite3 *db = pParse->db;
 
-  /* If there have already been errors, do nothing. */
-  if( pParse->nErr>0 ){
-    return SQLITE_ERROR;
+  if( db->mallocFailed  ){
+    return WRC_Abort;
   }
-
-  /* Prepare the select statement. This call will allocate all cursors
-  ** required to handle the tables and subqueries in the FROM clause.
-  */
-  if( prepSelectStmt(pParse, p) ){
-    return SQLITE_ERROR;
+  if( p->pSrc==0 || (p->selFlags & SF_Expanded)!=0 ){
+    return WRC_Prune;
   }
+  p->selFlags |= SF_Expanded;
+  pTabList = p->pSrc;
+  pEList = p->pEList;
 
-  /* Resolve the expressions in the LIMIT and OFFSET clauses. These
-  ** are not allowed to refer to any names, so pass an empty NameContext.
+  /* Make sure cursor numbers have been assigned to all entries in
+  ** the FROM clause of the SELECT statement.
   */
-  memset(&sNC, 0, sizeof(sNC));
-  sNC.pParse = pParse;
-  if( sqlite3ExprResolveNames(&sNC, p->pLimit) ||
-      sqlite3ExprResolveNames(&sNC, p->pOffset) ){
-    return SQLITE_ERROR;
-  }
+  sqlite3SrcListAssignCursors(pParse, pTabList);
 
-  /* Set up the local name-context to pass to ExprResolveNames() to
-  ** resolve the expression-list.
+  /* Look up every table named in the FROM clause of the select.  If
+  ** an entry of the FROM clause is a subquery instead of a table or view,
+  ** then create a transient table structure to describe the subquery.
   */
-  sNC.allowAgg = 1;
-  sNC.pSrcList = p->pSrc;
-  sNC.pNext = pOuterNC;
-
-  /* Resolve names in the result set. */
-  pEList = p->pEList;
-  if( !pEList ) return SQLITE_ERROR;
-  for(i=0; i<pEList->nExpr; i++){
-    Expr *pX = pEList->a[i].pExpr;
-    if( sqlite3ExprResolveNames(&sNC, pX) ){
-      return SQLITE_ERROR;
+  for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
+    Table *pTab;
+    if( pFrom->pTab!=0 ){
+      /* This statement has already been prepared.  There is no need
+      ** to go further. */
+      assert( i==0 );
+      return WRC_Prune;
     }
-  }
+    if( pFrom->zName==0 ){
+#ifndef SQLITE_OMIT_SUBQUERY
+      Select *pSel = pFrom->pSelect;
+      /* A sub-query in the FROM clause of a SELECT */
+      assert( pSel!=0 );
+      assert( pFrom->pTab==0 );
+      sqlite3WalkSelect(pWalker, pSel);
+      pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
+      if( pTab==0 ) return WRC_Abort;
+      pTab->db = db;
+      pTab->nRef = 1;
+      pTab->zName = sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pTab);
+      while( pSel->pPrior ){ pSel = pSel->pPrior; }
+      selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
+      pTab->iPKey = -1;
+      pTab->tabFlags |= TF_Ephemeral;
+#endif
+    }else{
+      /* An ordinary table or view name in the FROM clause */
+      assert( pFrom->pTab==0 );
+      pFrom->pTab = pTab = 
+        sqlite3LocateTable(pParse,0,pFrom->zName,pFrom->zDatabase);
+      if( pTab==0 ) return WRC_Abort;
+      pTab->nRef++;
+#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
+      if( pTab->pSelect || IsVirtual(pTab) ){
+        /* We reach here if the named table is a really a view */
+        if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
 
-  /* If there are no aggregate functions in the result-set, and no GROUP BY 
-  ** expression, do not allow aggregates in any of the other expressions.
-  */
-  assert( !p->isAgg );
-  pGroupBy = p->pGroupBy;
-  if( pGroupBy || sNC.hasAgg ){
-    p->isAgg = 1;
-  }else{
-    sNC.allowAgg = 0;
+        /* If pFrom->pSelect!=0 it means we are dealing with a
+        ** view within a view.  The SELECT structure has already been
+        ** copied by the outer view so we can skip the copy step here
+        ** in the inner view.
+        */
+        if( pFrom->pSelect==0 ){
+          pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect);
+          sqlite3WalkSelect(pWalker, pFrom->pSelect);
+        }
+      }
+#endif
+    }
   }
 
-  /* If a HAVING clause is present, then there must be a GROUP BY clause.
+  /* Process NATURAL keywords, and ON and USING clauses of joins.
   */
-  if( p->pHaving && !pGroupBy ){
-    sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
-    return SQLITE_ERROR;
+  if( db->mallocFailed || sqliteProcessJoin(pParse, p) ){
+    return WRC_Abort;
   }
 
-  /* Add the expression list to the name-context before parsing the
-  ** other expressions in the SELECT statement. This is so that
-  ** expressions in the WHERE clause (etc.) can refer to expressions by
-  ** aliases in the result set.
+  /* For every "*" that occurs in the column list, insert the names of
+  ** all columns in all tables.  And for every TABLE.* insert the names
+  ** of all columns in TABLE.  The parser inserted a special expression
+  ** with the TK_ALL operator for each "*" that it found in the column list.
+  ** The following code just has to locate the TK_ALL expressions and expand
+  ** each one to the list of all columns in all tables.
   **
-  ** Minor point: If this is the case, then the expression will be
-  ** re-evaluated for each reference to it.
+  ** The first loop just checks to see if there are any "*" operators
+  ** that need expanding.
   */
-  sNC.pEList = p->pEList;
-  if( sqlite3ExprResolveNames(&sNC, p->pWhere) ||
-     sqlite3ExprResolveNames(&sNC, p->pHaving) ){
-    return SQLITE_ERROR;
+  for(k=0; k<pEList->nExpr; k++){
+    Expr *pE = pEList->a[k].pExpr;
+    if( pE->op==TK_ALL ) break;
+    if( pE->op==TK_DOT && pE->pRight && pE->pRight->op==TK_ALL
+         && pE->pLeft && pE->pLeft->op==TK_ID ) break;
   }
-  if( p->pPrior==0 ){
-    if( processOrderGroupBy(pParse, p, p->pOrderBy, 1, &sNC.hasAgg) ){
-      return SQLITE_ERROR;
+  if( k<pEList->nExpr ){
+    /*
+    ** If we get here it means the result set contains one or more "*"
+    ** operators that need to be expanded.  Loop through each expression
+    ** in the result set and expand them one by one.
+    */
+    struct ExprList_item *a = pEList->a;
+    ExprList *pNew = 0;
+    int flags = pParse->db->flags;
+    int longNames = (flags & SQLITE_FullColNames)!=0
+                      && (flags & SQLITE_ShortColNames)==0;
+
+    for(k=0; k<pEList->nExpr; k++){
+      Expr *pE = a[k].pExpr;
+      if( pE->op!=TK_ALL &&
+           (pE->op!=TK_DOT || pE->pRight==0 || pE->pRight->op!=TK_ALL) ){
+        /* This particular expression does not need to be expanded.
+        */
+        pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr, 0);
+        if( pNew ){
+          pNew->a[pNew->nExpr-1].zName = a[k].zName;
+        }
+        a[k].pExpr = 0;
+        a[k].zName = 0;
+      }else{
+        /* This expression is a "*" or a "TABLE.*" and needs to be
+        ** expanded. */
+        int tableSeen = 0;      /* Set to 1 when TABLE matches */
+        char *zTName;            /* text of name of TABLE */
+        if( pE->op==TK_DOT && pE->pLeft ){
+          zTName = sqlite3NameFromToken(db, &pE->pLeft->token);
+        }else{
+          zTName = 0;
+        }
+        for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
+          Table *pTab = pFrom->pTab;
+          char *zTabName = pFrom->zAlias;
+          if( zTabName==0 || zTabName[0]==0 ){ 
+            zTabName = pTab->zName;
+          }
+          if( db->mallocFailed ) break;
+          if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
+            continue;
+          }
+          tableSeen = 1;
+          for(j=0; j<pTab->nCol; j++){
+            Expr *pExpr, *pRight;
+            char *zName = pTab->aCol[j].zName;
+
+            /* If a column is marked as 'hidden' (currently only possible
+            ** for virtual tables), do not include it in the expanded
+            ** result-set list.
+            */
+            if( IsHiddenColumn(&pTab->aCol[j]) ){
+              assert(IsVirtual(pTab));
+              continue;
+            }
+
+            if( i>0 ){
+              struct SrcList_item *pLeft = &pTabList->a[i-1];
+              if( (pLeft[1].jointype & JT_NATURAL)!=0 &&
+                        columnIndex(pLeft->pTab, zName)>=0 ){
+                /* In a NATURAL join, omit the join columns from the 
+                ** table on the right */
+                continue;
+              }
+              if( sqlite3IdListIndex(pLeft[1].pUsing, zName)>=0 ){
+                /* In a join with a USING clause, omit columns in the
+                ** using clause from the table on the right. */
+                continue;
+              }
+            }
+            pRight = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
+            if( pRight==0 ) break;
+            setQuotedToken(pParse, &pRight->token, zName);
+            if( longNames || pTabList->nSrc>1 ){
+              Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
+              pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
+              if( pExpr==0 ) break;
+              setQuotedToken(pParse, &pLeft->token, zTabName);
+              setToken(&pExpr->span, 
+                  sqlite3MPrintf(db, "%s.%s", zTabName, zName));
+              pExpr->span.dyn = 1;
+              pExpr->token.z = 0;
+              pExpr->token.n = 0;
+              pExpr->token.dyn = 0;
+            }else{
+              pExpr = pRight;
+              pExpr->span = pExpr->token;
+              pExpr->span.dyn = 0;
+            }
+            if( longNames ){
+              pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pExpr->span);
+            }else{
+              pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pRight->token);
+            }
+          }
+        }
+        if( !tableSeen ){
+          if( zTName ){
+            sqlite3ErrorMsg(pParse, "no such table: %s", zTName);
+          }else{
+            sqlite3ErrorMsg(pParse, "no tables specified");
+          }
+        }
+        sqlite3DbFree(db, zTName);
+      }
     }
+    sqlite3ExprListDelete(db, pEList);
+    p->pEList = pNew;
   }
-  if( processOrderGroupBy(pParse, p, pGroupBy, 0, &sNC.hasAgg) ){
-    return SQLITE_ERROR;
+#if SQLITE_MAX_COLUMN
+  if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
+    sqlite3ErrorMsg(pParse, "too many columns in result set");
   }
+#endif
+  return WRC_Continue;
+}
 
-  if( pParse->db->mallocFailed ){
-    return SQLITE_NOMEM;
-  }
+/*
+** No-op routine for the parse-tree walker.
+**
+** When this routine is the Walker.xExprCallback then expression trees
+** are walked without any actions being taken at each node.  Presumably,
+** when this routine is used for Walker.xExprCallback then 
+** Walker.xSelectCallback is set to do something useful for every 
+** subquery in the parser tree.
+*/
+static int exprWalkNoop(Walker *pWalker, Expr *pExpr){
+  return WRC_Continue;
+}
 
-  /* Make sure the GROUP BY clause does not contain aggregate functions.
-  */
-  if( pGroupBy ){
-    struct ExprList_item *pItem;
-  
-    for(i=0, pItem=pGroupBy->a; i<pGroupBy->nExpr; i++, pItem++){
-      if( ExprHasProperty(pItem->pExpr, EP_Agg) ){
-        sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
-            "the GROUP BY clause");
-        return SQLITE_ERROR;
+/*
+** This routine "expands" a SELECT statement and all of its subqueries.
+** For additional information on what it means to "expand" a SELECT
+** statement, see the comment on the selectExpand worker callback above.
+**
+** Expanding a SELECT statement is the first step in processing a
+** SELECT statement.  The SELECT statement must be expanded before
+** name resolution is performed.
+**
+** If anything goes wrong, an error message is written into pParse.
+** The calling function can detect the problem by looking at pParse->nErr
+** and/or pParse->db->mallocFailed.
+*/
+static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
+  Walker w;
+  w.xSelectCallback = selectExpander;
+  w.xExprCallback = exprWalkNoop;
+  w.pParse = pParse;
+  sqlite3WalkSelect(&w, pSelect);
+}
+
+
+#ifndef SQLITE_OMIT_SUBQUERY
+/*
+** 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.
+**
+** 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.
+*/
+static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
+  Parse *pParse;
+  int i;
+  SrcList *pTabList;
+  struct SrcList_item *pFrom;
+
+  if( (p->selFlags & SF_Resolved)==0 ){
+    /* If the ORDER BY clause of a compound SELECT contains a subquery,
+    ** that subquery will not yet have been resolved. */
+    return WRC_Prune;
+  }
+  if( (p->selFlags & SF_HasTypeInfo)==0 ){
+    p->selFlags |= SF_HasTypeInfo;
+    pParse = pWalker->pParse;
+    pTabList = p->pSrc;
+    for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
+      Table *pTab = pFrom->pTab;
+      if( pTab && (pTab->tabFlags & TF_Ephemeral)!=0 ){
+        /* A sub-query in the FROM clause of a SELECT */
+        Select *pSel = pFrom->pSelect;
+        assert( pSel );
+        while( pSel->pPrior ) pSel = pSel->pPrior;
+        selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel);
       }
     }
   }
+  return WRC_Continue;
+}
+#endif
 
-  /* If this is one SELECT of a compound, be sure to resolve names
-  ** in the other SELECTs.
-  */
-  if( p->pPrior ){
-    return sqlite3SelectResolve(pParse, p->pPrior, pOuterNC);
-  }else{
-    return SQLITE_OK;
-  }
+
+/*
+** This routine adds datatype and collating sequence information to
+** the Table structures of all FROM-clause subqueries in a
+** SELECT statement.
+**
+** Use this routine after name resolution.
+*/
+static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){
+#ifndef SQLITE_OMIT_SUBQUERY
+  Walker w;
+  w.xSelectCallback = selectAddSubqueryTypeInfo;
+  w.xExprCallback = exprWalkNoop;
+  w.pParse = pParse;
+  sqlite3WalkSelect(&w, pSelect);
+#endif
+}
+
+
+/*
+** This routine sets of a SELECT statement for processing.  The
+** following is accomplished:
+**
+**     *  VDBE Cursor numbers are assigned to all FROM-clause terms.
+**     *  Ephemeral Table objects are created for all FROM-clause subqueries.
+**     *  ON and USING clauses are shifted into WHERE statements
+**     *  Wildcards "*" and "TABLE.*" in result sets are expanded.
+**     *  Identifiers in expression are matched to tables.
+**
+** This routine acts recursively on all subqueries within the SELECT.
+*/
+void sqlite3SelectPrep(
+  Parse *pParse,         /* The parser context */
+  Select *p,             /* The SELECT statement being coded. */
+  NameContext *pOuterNC  /* Name context for container */
+){
+  sqlite3 *db;
+  if( p==0 ) return;
+  db = pParse->db;
+  if( p->selFlags & SF_HasTypeInfo ) return;
+  if( pParse->nErr || db->mallocFailed ) return;
+  sqlite3SelectExpand(pParse, p);
+  if( pParse->nErr || db->mallocFailed ) return;
+  sqlite3ResolveSelectNames(pParse, p, pOuterNC);
+  if( pParse->nErr || db->mallocFailed ) return;
+  sqlite3SelectAddTypeInfo(pParse, p);
 }
 
 /*
@@ -3530,7 +3326,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
 }
 
 /*
-** Generate code for the given SELECT statement.
+** Generate code for the SELECT statement given in the p argument.  
 **
 ** The results are distributed in various ways depending on the
 ** contents of the SelectDest structure pointed to by argument pDest
@@ -3538,33 +3334,43 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
 **
 **     pDest->eDest    Result
 **     ------------    -------------------------------------------
-**     SRT_Callback    Invoke the callback for each row of the result.
+**     SRT_Output      Generate a row of output (using the OP_ResultRow
+**                     opcode) for each row in the result set.
 **
-**     SRT_Mem         Store first result in memory cell pDest->iParm
+**     SRT_Mem         Only valid if the result is a single column.
+**                     Store the first column of the first result row
+**                     in register pDest->iParm then abandon the rest
+**                     of the query.  This destination implies "LIMIT 1".
 **
-**     SRT_Set         Store results as keys of table pDest->iParm. 
-**                     Apply the affinity pDest->affinity before storing them.
+**     SRT_Set         The result must be a single column.  Store each
+**                     row of result as the key in table pDest->iParm. 
+**                     Apply the affinity pDest->affinity before storing
+**                     results.  Used to implement "IN (SELECT ...)".
 **
 **     SRT_Union       Store results as a key in a temporary table pDest->iParm.
 **
 **     SRT_Except      Remove results from the temporary table pDest->iParm.
 **
-**     SRT_Table       Store results in temporary table pDest->iParm
+**     SRT_Table       Store results in temporary table pDest->iParm.
+**                     This is like SRT_EphemTab except that the table
+**                     is assumed to already be open.
 **
 **     SRT_EphemTab    Create an temporary table pDest->iParm and store
 **                     the result there. The cursor is left open after
-**                     returning.
+**                     returning.  This is like SRT_Table except that
+**                     this destination uses OP_OpenEphemeral to create
+**                     the table first.
 **
-**     SRT_Coroutine   Invoke a co-routine to compute a single row of 
-**                     the result
+**     SRT_Coroutine   Generate a co-routine that returns a new row of
+**                     results each time it is invoked.  The entry point
+**                     of the co-routine is stored in register pDest->iParm.
 **
 **     SRT_Exists      Store a 1 in memory cell pDest->iParm if the result
 **                     set is not empty.
 **
-**     SRT_Discard     Throw the results away.
-**
-** See the selectInnerLoop() function for a canonical listing of the 
-** allowed values of eDest and their meanings.
+**     SRT_Discard     Throw the results away.  This is used by SELECT
+**                     statements within triggers whose only purpose is
+**                     the side-effects of functions.
 **
 ** This routine returns the number of errors.  If any errors are
 ** encountered, then an appropriate error message is left in
@@ -3572,35 +3378,11 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
 **
 ** This routine does NOT free the Select structure passed in.  The
 ** calling function needs to do that.
-**
-** The pParent, parentTab, and *pParentAgg fields are filled in if this
-** SELECT is a subquery.  This routine may try to combine this SELECT
-** with its parent to form a single flat query.  In so doing, it might
-** change the parent query from a non-aggregate to an aggregate query.
-** For that reason, the pParentAgg flag is passed as a pointer, so it
-** can be changed.
-**
-** Example 1:   The meaning of the pParent parameter.
-**
-**    SELECT * FROM t1 JOIN (SELECT x, count(*) FROM t2) JOIN t3;
-**    \                      \_______ subquery _______/        /
-**     \                                                      /
-**      \____________________ outer query ___________________/
-**
-** This routine is called for the outer query first.   For that call,
-** pParent will be NULL.  During the processing of the outer query, this 
-** routine is called recursively to handle the subquery.  For the recursive
-** call, pParent will point to the outer query.  Because the subquery is
-** the second element in a three-way join, the parentTab parameter will
-** be 1 (the 2nd value of a 0-indexed array.)
 */
 int sqlite3Select(
   Parse *pParse,         /* The parser context */
   Select *p,             /* The SELECT statement being coded. */
-  SelectDest *pDest,     /* What to do with the query results */
-  Select *pParent,       /* Another SELECT for which this is a sub-query */
-  int parentTab,         /* Index in pParent->pSrc of this query */
-  int *pParentAgg        /* True if pParent uses aggregate functions */
+  SelectDest *pDest      /* What to do with the query results */
 ){
   int i, j;              /* Loop counters */
   WhereInfo *pWInfo;     /* Return from sqlite3WhereBegin() */
@@ -3636,9 +3418,10 @@ int sqlite3Select(
     */
     assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union || 
            pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard);
-    p->isDistinct = 0;
+    p->selFlags &= ~SF_Distinct;
   }
-  if( sqlite3SelectResolve(pParse, p, 0) ){
+  sqlite3SelectPrep(pParse, p, 0);
+  if( pParse->nErr ){
     goto select_end;
   }
   p->pOrderBy = pOrderBy;
@@ -3647,7 +3430,7 @@ int sqlite3Select(
   /* Make local copies of the parameters for this query.
   */
   pTabList = p->pSrc;
-  isAgg = p->isAgg;
+  isAgg = (p->selFlags & SF_Aggregate)!=0;
   pEList = p->pEList;
   if( pEList==0 ) goto select_end;
 
@@ -3676,18 +3459,8 @@ int sqlite3Select(
     SelectDest dest;
     Select *pSub = pItem->pSelect;
     int isAggSub;
-    char *zName = pItem->zName;
 
     if( pSub==0 || pItem->isPopulated ) continue;
-    if( zName!=0 ){   /* An sql view */
-      const char *zSavedAuthContext = pParse->zAuthContext;
-      pParse->zAuthContext = zName;
-      rc = sqlite3SelectResolve(pParse, pSub, 0);
-      pParse->zAuthContext = zSavedAuthContext;
-      if( rc ){
-        goto select_end;
-      }
-    }
 
     /* Increment Parse.nHeight by the height of the largest expression
     ** tree refered to by this, the parent select. The child select
@@ -3699,15 +3472,18 @@ int sqlite3Select(
     pParse->nHeight += sqlite3SelectExprHeight(p);
 
     /* Check to see if the subquery can be absorbed into the parent. */
-    isAggSub = pSub->isAgg;
+    isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
     if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
       if( isAggSub ){
-        p->isAgg = isAgg = 1;
+        isAgg = 1;
+        p->selFlags |= SF_Aggregate;
       }
       i = -1;
     }else{
       sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
-      sqlite3Select(pParse, pSub, &dest, p, i, &isAgg);
+      assert( pItem->isPopulated==0 );
+      sqlite3Select(pParse, pSub, &dest);
+      pItem->isPopulated = 1;
     }
     if( pParse->nErr || db->mallocFailed ){
       goto select_end;
@@ -3723,7 +3499,7 @@ int sqlite3Select(
   pWhere = p->pWhere;
   pGroupBy = p->pGroupBy;
   pHaving = p->pHaving;
-  isDistinct = p->isDistinct;
+  isDistinct = (p->selFlags & SF_Distinct)!=0;
 
 #ifndef SQLITE_OMIT_COMPOUND_SELECT
   /* If there is are a sequence of queries, do the earlier ones first.
@@ -3758,12 +3534,12 @@ int sqlite3Select(
 #endif
 
   /* If possible, rewrite the query to use GROUP BY instead of DISTINCT.
-  ** GROUP BY may use an index, DISTINCT never does.
+  ** GROUP BY might use an index, DISTINCT never does.
   */
-  if( p->isDistinct && !p->isAgg && !p->pGroupBy ){
+  if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct && !p->pGroupBy ){
     p->pGroupBy = sqlite3ExprListDup(db, p->pEList);
     pGroupBy = p->pGroupBy;
-    p->isDistinct = 0;
+    p->selFlags &= ~SF_Distinct;
     isDistinct = 0;
   }
 
@@ -4159,19 +3935,6 @@ int sqlite3Select(
     generateSortTail(pParse, p, v, pEList->nExpr, pDest);
   }
 
-#ifndef SQLITE_OMIT_SUBQUERY
-  /* If this was a subquery, we have now converted the subquery into a
-  ** temporary table.  So set the SrcList_item.isPopulated flag to prevent
-  ** this subquery from being evaluated again and to force the use of
-  ** the temporary table.
-  */
-  if( pParent ){
-    assert( pParent->pSrc->nSrc>parentTab );
-    assert( pParent->pSrc->a[parentTab].pSelect==p );
-    pParent->pSrc->a[parentTab].isPopulated = 1;
-  }
-#endif
-
   /* Jump here to skip this query
   */
   sqlite3VdbeResolveLabel(v, iEnd);
@@ -4186,10 +3949,9 @@ int sqlite3Select(
   */
 select_end:
 
-  /* Identify column names if we will be using them in a callback.  This
-  ** step is skipped if the output is going to some other destination.
+  /* Identify column names if results of the SELECT are to be output.
   */
-  if( rc==SQLITE_OK && pDest->eDest==SRT_Callback ){
+  if( rc==SQLITE_OK && pDest->eDest==SRT_Output ){
     generateColumnNames(pParse, pTabList, pEList);
   }
 
index 455aec62b8e9e6e9eb2306945d29f4c96641bec7..1d1474a285ab3225581b6d6786cda4c98266d3a0 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.756 2008/08/20 14:49:25 danielk1977 Exp $
+** @(#) $Id: sqliteInt.h,v 1.757 2008/08/20 16:35:10 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
 #  define _XOPEN_SOURCE 500  /* Needed to enable pthread recursive mutexes */
 #endif
 
+/*
+** The TCL headers are only needed when compiling the TCL bindings.
+*/
 #if defined(SQLITE_TCL) || defined(TCLSH)
 # include <tcl.h>
 #endif
@@ -471,6 +474,7 @@ typedef struct TriggerStack TriggerStack;
 typedef struct TriggerStep TriggerStep;
 typedef struct Trigger Trigger;
 typedef struct UnpackedRecord UnpackedRecord;
+typedef struct Walker Walker;
 typedef struct WhereInfo WhereInfo;
 typedef struct WhereLevel WhereLevel;
 
@@ -580,7 +584,7 @@ struct Lookaside {
   u8 bMalloced;           /* True if pStart obtained from sqlite3_malloc() */
   int nOut;               /* Number of buffers currently checked out */
   int mxOut;              /* Highwater mark for nOut */
-  LookasideSlot *pFree;   /* List if available buffers */
+  LookasideSlot *pFree;   /* List of available buffers */
   void *pStart;           /* First byte of available memory space */
   void *pEnd;             /* First byte past end of available space */
 };
@@ -761,6 +765,13 @@ struct FuncDef {
   char *zName;         /* SQL name of the function. */
 };
 
+/*
+** Possible values for FuncDef.flags
+*/
+#define SQLITE_FUNC_LIKE   0x01  /* Candidate for the LIKE optimization */
+#define SQLITE_FUNC_CASE   0x02  /* Case-sensitive LIKE-type function */
+#define SQLITE_FUNC_EPHEM  0x04  /* Ephermeral.  Delete with VDBE */
+
 /*
 ** Each SQLite module (virtual table definition) is defined by an
 ** instance of the following structure, stored in the sqlite3.aModule
@@ -773,13 +784,6 @@ struct Module {
   void (*xDestroy)(void *);            /* Module destructor function */
 };
 
-/*
-** Possible values for FuncDef.flags
-*/
-#define SQLITE_FUNC_LIKE   0x01  /* Candidate for the LIKE optimization */
-#define SQLITE_FUNC_CASE   0x02  /* Case-sensitive LIKE-type function */
-#define SQLITE_FUNC_EPHEM  0x04  /* Ephermeral.  Delete with VDBE */
-
 /*
 ** information about each column of an SQL table is held in an instance
 ** of this structure.
@@ -828,7 +832,7 @@ struct CollSeq {
 };
 
 /*
-** Allowed values of CollSeq flags:
+** Allowed values of CollSeq.type:
 */
 #define SQLITE_COLL_BINARY  1  /* The default memcmp() collating sequence */
 #define SQLITE_COLL_NOCASE  2  /* The built-in NOCASE collating sequence */
@@ -846,7 +850,7 @@ struct CollSeq {
 **
 ** These used to have mnemonic name like 'i' for SQLITE_AFF_INTEGER and
 ** 't' for SQLITE_AFF_TEXT.  But we can save a little space and improve
-** the speed a little by number the values consecutively.  
+** the speed a little by numbering the values consecutively.  
 **
 ** But rather than start with 0 or 1, we begin with 'a'.  That way,
 ** when multiple affinity types are concatenated into a string and
@@ -892,14 +896,14 @@ struct CollSeq {
 ** that the datatype of the PRIMARY KEY must be INTEGER for this field to
 ** be set.  An INTEGER PRIMARY KEY is used as the rowid for each row of
 ** the table.  If a table has no INTEGER PRIMARY KEY, then a random rowid
-** is generated for each row of the table.  Table.hasPrimKey is true if
+** is generated for each row of the table.  TF_HasPrimaryKey is set if
 ** the table has any PRIMARY KEY, INTEGER or otherwise.
 **
 ** Table.tnum is the page number for the root BTree page of the table in the
 ** database file.  If Table.iDb is the index of the database table backend
 ** in sqlite.aDb[].  0 is for the main database and 1 is for the file that
-** holds temporary tables and indices.  If Table.isEphem
-** is true, then the table is stored in a file that is automatically deleted
+** holds temporary tables and indices.  If TF_Ephemeral is set
+** then the table is stored in a file that is automatically deleted
 ** when the VDBE cursor to the table is closed.  In this case Table.tnum 
 ** refers VDBE cursor number that holds the table open, not to the root
 ** page number.  Transient tables are used to hold the results of a
@@ -907,47 +911,54 @@ struct CollSeq {
 ** of a SELECT statement.
 */
 struct Table {
-  sqlite3 *db;     /* Associated database connection.  Might be NULL. */
-  char *zName;     /* Name of the table */
-  int nCol;        /* Number of columns in this table */
-  Column *aCol;    /* Information about each column */
-  int iPKey;       /* If not less then 0, use aCol[iPKey] as the primary key */
-  Index *pIndex;   /* List of SQL indexes on this table. */
-  int tnum;        /* Root BTree node for this table (see note above) */
-  Select *pSelect; /* NULL for tables.  Points to definition if a view. */
-  int nRef;          /* Number of pointers to this Table */
-  Trigger *pTrigger; /* List of SQL triggers on this table */
-  FKey *pFKey;       /* Linked list of all foreign keys in this table */
-  char *zColAff;     /* String defining the affinity of each column */
+  sqlite3 *db;         /* Associated database connection.  Might be NULL. */
+  char *zName;         /* Name of the table or view */
+  int iPKey;           /* If not negative, use aCol[iPKey] as the primary key */
+  int nCol;            /* Number of columns in this table */
+  Column *aCol;        /* Information about each column */
+  Index *pIndex;       /* List of SQL indexes on this table. */
+  int tnum;            /* Root BTree node for this table (see note above) */
+  Select *pSelect;     /* NULL for tables.  Points to definition if a view. */
+  u16 nRef;            /* Number of pointers to this Table */
+  u8 tabFlags;         /* Mask of TF_* values */
+  u8 keyConf;          /* What to do in case of uniqueness conflict on iPKey */
+  Trigger *pTrigger;   /* List of SQL triggers on this table */
+  FKey *pFKey;         /* Linked list of all foreign keys in this table */
+  char *zColAff;       /* String defining the affinity of each column */
 #ifndef SQLITE_OMIT_CHECK
-  Expr *pCheck;      /* The AND of all CHECK constraints */
+  Expr *pCheck;        /* The AND of all CHECK constraints */
 #endif
 #ifndef SQLITE_OMIT_ALTERTABLE
-  int addColOffset;  /* Offset in CREATE TABLE statement to add a new column */
+  int addColOffset;    /* Offset in CREATE TABLE stmt to add a new column */
 #endif
-  u8 readOnly;     /* True if this table should not be written by the user */
-  u8 isEphem;      /* True if created using OP_OpenEphermeral */
-  u8 hasPrimKey;   /* True if there exists a primary key */
-  u8 keyConf;      /* What to do in case of uniqueness conflict on iPKey */
-  u8 autoInc;      /* True if the integer primary key is autoincrement */
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  u8 isVirtual;             /* True if this is a virtual table */
-  u8 isCommit;              /* True once the CREATE TABLE has been committed */
-  Module *pMod;             /* Pointer to the implementation of the module */
-  sqlite3_vtab *pVtab;      /* Pointer to the module instance */
-  int nModuleArg;           /* Number of arguments to the module */
-  char **azModuleArg;       /* Text of all module args. [0] is module name */
-#endif
-  Schema *pSchema;          /* Schema that contains this table */
+  Module *pMod;        /* Pointer to the implementation of the module */
+  sqlite3_vtab *pVtab; /* Pointer to the module instance */
+  int nModuleArg;      /* Number of arguments to the module */
+  char **azModuleArg;  /* Text of all module args. [0] is module name */
+#endif
+  Schema *pSchema;     /* Schema that contains this table */
 };
 
+/*
+** Allowed values for Tabe.tabFlags.
+*/
+#define TF_Readonly        0x01    /* Read-only system table */
+#define TF_Ephemeral       0x02    /* An emphermal table */
+#define TF_HasPrimaryKey   0x04    /* Table has a primary key */
+#define TF_Autoincrement   0x08    /* Integer primary key is autoincrement */
+#define TF_Virtual         0x10    /* Is a virtual table */
+#define TF_NeedMetadata    0x20    /* aCol[].zType and aCol[].pColl missing */
+
+
+
 /*
 ** Test to see whether or not a table is a virtual table.  This is
 ** done as a macro so that it will be optimized out when virtual
 ** table support is omitted from the build.
 */
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-#  define IsVirtual(X)      ((X)->isVirtual)
+#  define IsVirtual(X)      (((X)->tabFlags & TF_Virtual)!=0)
 #  define IsHiddenColumn(X) ((X)->isHidden)
 #else
 #  define IsVirtual(X)      0
@@ -1241,7 +1252,7 @@ struct Expr {
   int iRightJoinTable;   /* If EP_FromJoin, the right table of the join */
   Select *pSelect;       /* When the expression is a sub-select.  Also the
                          ** right side of "<expr> IN (<select>)" */
-  Table *pTab;           /* Table for OP_Column expressions. */
+  Table *pTab;           /* Table for TK_COLUMN expressions. */
 #if SQLITE_MAX_EXPR_DEPTH>0
   int nHeight;           /* Height of the tree headed by this node */
 #endif
@@ -1287,8 +1298,8 @@ struct ExprList {
     Expr *pExpr;           /* The list of expressions */
     char *zName;           /* Token associated with this expression */
     u8 sortOrder;          /* 1 for DESC or 0 for ASC */
-    u8 isAgg;              /* True if this is an aggregate like count(*) */
     u8 done;               /* A flag to indicate when processing is finished */
+    u16 iCol;              /* For ORDER BY, column number in result set */
   } *a;                  /* One entry for each expression */
 };
 
@@ -1502,12 +1513,8 @@ struct NameContext {
 struct Select {
   ExprList *pEList;      /* The fields of the result */
   u8 op;                 /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
-  u8 isDistinct;         /* True if the DISTINCT keyword is present */
-  u8 isResolved;         /* True once sqlite3SelectResolve() has run. */
-  u8 isAgg;              /* True if this is an aggregate query */
-  u8 usesEphm;           /* True if uses an OpenEphemeral opcode */
-  u8 disallowOrderBy;    /* Do not allow an ORDER BY to be attached if TRUE */
   char affinity;         /* MakeRecord with this affinity for SRT_Set */
+  u16 selFlags;          /* Various SF_* values */
   SrcList *pSrc;         /* The FROM clause */
   Expr *pWhere;          /* The WHERE clause */
   ExprList *pGroupBy;    /* The GROUP BY clause */
@@ -1523,7 +1530,20 @@ struct Select {
 };
 
 /*
-** The results of a select can be distributed in several ways.
+** Allowed values for Select.selFlags.  The "SF" prefix stands for
+** "Select Flag".
+*/
+#define SF_Distinct        0x0001  /* Output should be DISTINCT */
+#define SF_Resolved        0x0002  /* Identifiers have been resolved */
+#define SF_Aggregate       0x0004  /* Contains aggregate functions */
+#define SF_UsesEphemeral   0x0008  /* Uses the OpenEphemeral opcode */
+#define SF_Expanded        0x0010  /* sqlite3SelectExpand() called on this */
+#define SF_HasTypeInfo     0x0020  /* FROM subqueries have Table metadata */
+
+
+/*
+** The results of a select can be distributed in several ways.  The
+** "SRT" prefix means "SELECT Result Type".
 */
 #define SRT_Union        1  /* Store result as keys in an index */
 #define SRT_Except       2  /* Remove result from a UNION index */
@@ -1533,7 +1553,7 @@ struct Select {
 /* The ORDER BY clause is ignored for all of the above */
 #define IgnorableOrderby(X) ((X->eDest)<=SRT_Discard)
 
-#define SRT_Callback     5  /* Invoke a callback with each row of result */
+#define SRT_Output       5  /* Output each row of result */
 #define SRT_Mem          6  /* Store result in a memory cell */
 #define SRT_Set          7  /* Store results as keys in an index */
 #define SRT_Table        8  /* Store result as data with an automatic rowid */
@@ -1862,6 +1882,34 @@ struct Sqlite3Config {
   int mxParserStack;                /* maximum depth of the parser stack */
 };
 
+/*
+** Context pointer passed down through the tree-walk.
+*/
+struct Walker {
+  int (*xExprCallback)(Walker*, Expr*);     /* Callback for expressions */
+  int (*xSelectCallback)(Walker*,Select*);  /* Callback for SELECTs */
+  Parse *pParse;                            /* Parser context.  */
+  union {                                   /* Extra data for callback */
+    NameContext *pNC;                          /* Naming context */
+    int i;                                     /* Integer value */
+  } u;
+};
+
+/* Forward declarations */
+int sqlite3WalkExpr(Walker*, Expr*);
+int sqlite3WalkExprList(Walker*, ExprList*);
+int sqlite3WalkSelect(Walker*, Select*);
+int sqlite3WalkSelectExpr(Walker*, Select*);
+int sqlite3WalkSelectFrom(Walker*, Select*);
+
+/*
+** Return code from the parse-tree walking primitives and their
+** callbacks.
+*/
+#define WRC_Continue    0
+#define WRC_Prune       1
+#define WRC_Abort       2
+
 /*
 ** Assuming zIn points to the first byte of a UTF-8 character,
 ** advance zIn to point to the first byte of the next UTF-8 character.
@@ -1970,7 +2018,7 @@ void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
 void sqlite3ResetInternalSchema(sqlite3*, int);
 void sqlite3BeginParse(Parse*,int);
 void sqlite3CommitInternalChanges(sqlite3*);
-Table *sqlite3ResultSetOfSelect(Parse*,char*,Select*);
+Table *sqlite3ResultSetOfSelect(Parse*,Select*);
 void sqlite3OpenMasterTable(Parse *, int);
 void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
 void sqlite3AddColumn(Parse*,Token*);
@@ -2013,7 +2061,7 @@ void sqlite3SrcListDelete(sqlite3*, SrcList*);
 void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
                         Token*, int, int);
 void sqlite3DropIndex(Parse*, SrcList*, int);
-int sqlite3Select(Parse*, Select*, SelectDest*, Select*, int, int*);
+int sqlite3Select(Parse*, Select*, SelectDest*);
 Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
                          Expr*,ExprList*,int,Expr*,Expr*);
 void sqlite3SelectDelete(sqlite3*, Select*);
@@ -2048,7 +2096,6 @@ void sqlite3Vacuum(Parse*);
 int sqlite3RunVacuum(char**, sqlite3*);
 char *sqlite3NameFromToken(sqlite3*, Token*);
 int sqlite3ExprCompare(Expr*, Expr*);
-int sqlite3ExprResolveNames(NameContext *, Expr *);
 void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
 void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
 Vdbe *sqlite3GetVdbe(Parse*);
@@ -2230,7 +2277,11 @@ int sqlite3GetToken(const unsigned char *, int *);
 void sqlite3NestedParse(Parse*, const char*, ...);
 void sqlite3ExpirePreparedStatements(sqlite3*);
 void sqlite3CodeSubselect(Parse *, Expr *, int);
-int sqlite3SelectResolve(Parse *, Select *, NameContext *);
+void sqlite3SelectPrep(Parse*, Select*, NameContext*);
+int sqlite3ResolveExprNames(NameContext*, Expr*);
+int sqlite3ResolveExprListNames(NameContext*, ExprList*);
+void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
+int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
 void sqlite3ColumnDefault(Vdbe *, Table *, int);
 void sqlite3AlterFinishAddColumn(Parse *, Token *);
 void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
@@ -2352,9 +2403,11 @@ int sqlite3FindInIndex(Parse *, Expr *, int*);
 #if SQLITE_MAX_EXPR_DEPTH>0
   void sqlite3ExprSetHeight(Parse *pParse, Expr *p);
   int sqlite3SelectExprHeight(Select *);
+  int sqlite3ExprCheckHeight(Parse*, int);
 #else
   #define sqlite3ExprSetHeight(x,y)
   #define sqlite3SelectExprHeight(x) 0
+  #define sqlite3ExprCheckHeight(x,y)
 #endif
 
 u32 sqlite3Get4byte(const u8*);
index 760c708c616ba091d71f9f12662708f8c76e50be..8010fda293ca6e0f6a59e26548b4c72158a9f205 100644 (file)
@@ -10,7 +10,7 @@
 *************************************************************************
 **
 **
-** $Id: trigger.c,v 1.128 2008/07/28 19:34:54 drh Exp $
+** $Id: trigger.c,v 1.129 2008/08/20 16:35:10 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -679,8 +679,7 @@ static int codeTriggerProgram(
           SelectDest dest;
 
           sqlite3SelectDestInit(&dest, SRT_Discard, 0);
-          sqlite3SelectResolve(pParse, ss, 0);
-          sqlite3Select(pParse, ss, &dest, 0, 0, 0);
+          sqlite3Select(pParse, ss, &dest);
           sqlite3SelectDelete(db, ss);
         }
         break;
@@ -829,7 +828,7 @@ int sqlite3CodeRowTrigger(
       /* code the WHEN clause */
       endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe);
       whenExpr = sqlite3ExprDup(db, p->pWhen);
-      if( db->mallocFailed || sqlite3ExprResolveNames(&sNC, whenExpr) ){
+      if( db->mallocFailed || sqlite3ResolveExprNames(&sNC, whenExpr) ){
         pParse->trigStack = trigStackEntry.pNext;
         sqlite3ExprDelete(db, whenExpr);
         return 1;
index 7647d4a7e2e6f275bf718cf20799460c78d71102..eb715dfc9d12640c33033140dad6480d7610fecc 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle UPDATE statements.
 **
-** $Id: update.c,v 1.181 2008/07/28 19:34:54 drh Exp $
+** $Id: update.c,v 1.182 2008/08/20 16:35:10 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -194,7 +194,7 @@ void sqlite3Update(
   */
   chngRowid = 0;
   for(i=0; i<pChanges->nExpr; i++){
-    if( sqlite3ExprResolveNames(&sNC, pChanges->a[i].pExpr) ){
+    if( sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
       goto update_cleanup;
     }
     for(j=0; j<pTab->nCol; j++){
@@ -335,7 +335,7 @@ void sqlite3Update(
   /* Resolve the column names in all the expressions in the
   ** WHERE clause.
   */
-  if( sqlite3ExprResolveNames(&sNC, pWhere) ){
+  if( sqlite3ResolveExprNames(&sNC, pWhere) ){
     goto update_cleanup;
   }
 
@@ -649,7 +649,7 @@ static void updateVirtualTable(
   /* fill the ephemeral table 
   */
   sqlite3SelectDestInit(&dest, SRT_Table, ephemTab);
-  sqlite3Select(pParse, pSelect, &dest, 0, 0, 0);
+  sqlite3Select(pParse, pSelect, &dest);
 
   /* Generate code to scan the ephemeral table and call VUpdate. */
   iReg = ++pParse->nMem;
index 2d8d2a835d014d61e26f2e7e43886b415b3a2126..d1bd0e8cf128b91315bd540a9cb36062c97bdc88 100644 (file)
@@ -14,7 +14,7 @@
 ** to version 2.8.7, all this code was combined into the vdbe.c source file.
 ** But that file was getting too big so this subroutines were split out.
 **
-** $Id: vdbeaux.c,v 1.407 2008/08/13 19:11:48 drh Exp $
+** $Id: vdbeaux.c,v 1.408 2008/08/20 16:35:10 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -2238,6 +2238,7 @@ UnpackedRecord *sqlite3VdbeRecordUnpack(
     pMem++;
     u++;
   }
+  assert( u<=pKeyInfo->nField + 1 );
   p->nField = u;
   return (void*)p;
 }
index 6013f61de141e813cb63e15f38b926cefabf5c89..50e609ba227fb0739218f3b7336075b20ba46233 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code used to help implement virtual tables.
 **
-** $Id: vtab.c,v 1.75 2008/08/20 14:49:25 danielk1977 Exp $
+** $Id: vtab.c,v 1.76 2008/08/20 16:35:10 drh Exp $
 */
 #ifndef SQLITE_OMIT_VIRTUALTABLE
 #include "sqliteInt.h"
@@ -186,7 +186,7 @@ void sqlite3VtabBeginParse(
   iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
   assert( iDb>=0 );
 
-  pTable->isVirtual = 1;
+  pTable->tabFlags |= TF_Virtual;
   pTable->nModuleArg = 0;
   addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName));
   addModuleArgument(db, pTable, sqlite3DbStrDup(db, db->aDb[iDb].zName));
@@ -442,7 +442,7 @@ int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
   Module *pMod;
   int rc = SQLITE_OK;
 
-  if( !pTab || !pTab->isVirtual || pTab->pVtab ){
+  if( !pTab || (pTab->tabFlags & TF_Virtual)==0 || pTab->pVtab ){
     return SQLITE_OK;
   }
 
@@ -503,7 +503,7 @@ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
   const char *zModule;
 
   pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
-  assert(pTab && pTab->isVirtual && !pTab->pVtab);
+  assert(pTab && (pTab->tabFlags & TF_Virtual)!=0 && !pTab->pVtab);
   pMod = pTab->pMod;
   zModule = pTab->azModuleArg[0];
 
@@ -544,7 +544,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
     sqlite3_mutex_leave(db->mutex);
     return SQLITE_MISUSE;
   }
-  assert(pTab->isVirtual && pTab->nCol==0 && pTab->aCol==0);
+  assert((pTab->tabFlags & TF_Virtual)!=0 && pTab->nCol==0 && pTab->aCol==0);
 
   memset(&sParse, 0, sizeof(Parse));
   sParse.declareVtab = 1;
@@ -554,7 +554,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
       SQLITE_OK == sqlite3RunParser(&sParse, zCreateTable, &zErr) && 
       sParse.pNewTable && 
       !sParse.pNewTable->pSelect && 
-      !sParse.pNewTable->isVirtual 
+      (sParse.pNewTable->tabFlags & TF_Virtual)==0
   ){
     pTab->aCol = sParse.pNewTable->aCol;
     pTab->nCol = sParse.pNewTable->nCol;
@@ -773,7 +773,7 @@ FuncDef *sqlite3VtabOverloadFunction(
   if( pExpr->op!=TK_COLUMN ) return pDef;
   pTab = pExpr->pTab;
   if( pTab==0 ) return pDef;
-  if( !pTab->isVirtual ) return pDef;
+  if( (pTab->tabFlags & TF_Virtual)==0 ) return pDef;
   pVtab = pTab->pVtab;
   assert( pVtab!=0 );
   assert( pVtab->pModule!=0 );
diff --git a/src/walker.c b/src/walker.c
new file mode 100644 (file)
index 0000000..9a3a9c2
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+** 2008 August 16
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains routines used for walking the parser tree for
+** an SQL statement.
+**
+** $Id: walker.c,v 1.1 2008/08/20 16:35:10 drh Exp $
+*/
+#include "sqliteInt.h"
+#include <stdlib.h>
+#include <string.h>
+
+
+/*
+** Walk an expression tree.  Invoke the callback once for each node
+** of the expression, while decending.  (In other words, the callback
+** is invoked before visiting children.)
+**
+** The return value from the callback should be one of the WRC_*
+** constants to specify how to proceed with the walk.
+**
+**    WRC_Continue      Continue descending down the tree.
+**
+**    WRC_Prune         Do not descend into child nodes.  But allow
+**                      the walk to continue with sibling nodes.
+**
+**    WRC_Abort         Do no more callbacks.  Unwind the stack and
+**                      return the top-level walk call.
+**
+** The return value from this routine is WRC_Abort to abandon the tree walk
+** and WRC_Continue to continue.
+*/
+int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
+  int rc;
+  if( pExpr==0 ) return WRC_Continue;
+  rc = pWalker->xExprCallback(pWalker, pExpr);
+  if( rc==WRC_Continue ){
+    if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
+    if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
+    if( sqlite3WalkExprList(pWalker, pExpr->pList) ) return WRC_Abort;
+    if( sqlite3WalkSelect(pWalker, pExpr->pSelect) ){
+      return WRC_Abort;
+    }
+  }
+  return rc & WRC_Abort;
+}
+
+/*
+** Call sqlite3WalkExpr() for every expression in list p or until
+** an abort request is seen.
+*/
+int sqlite3WalkExprList(Walker *pWalker, ExprList *p){
+  int i, rc = WRC_Continue;
+  struct ExprList_item *pItem;
+  if( p ){
+    for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){
+      if( sqlite3WalkExpr(pWalker, pItem->pExpr) ) return WRC_Abort;
+    }
+  }
+  return rc & WRC_Continue;
+}
+
+/*
+** Walk all expressions associated with SELECT statement p.  Do
+** not invoke the SELECT callback on p, but do (of course) invoke
+** any expr callbacks and SELECT callbacks that come from subqueries.
+** Return WRC_Abort or WRC_Continue.
+*/
+int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
+  if( sqlite3WalkExprList(pWalker, p->pEList) ) return WRC_Abort;
+  if( sqlite3WalkExpr(pWalker, p->pWhere) ) return WRC_Abort;
+  if( sqlite3WalkExprList(pWalker, p->pGroupBy) ) return WRC_Abort;
+  if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
+  if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
+  if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
+  if( sqlite3WalkExpr(pWalker, p->pOffset) ) return WRC_Abort;
+  return WRC_Continue;
+}
+
+/*
+** Walk the parse trees associated with all subqueries in the
+** FROM clause of SELECT statement p.  Do not invoke the select
+** callback on p, but do invoke it on each FROM clause subquery
+** and on any subqueries further down in the tree.  Return 
+** WRC_Abort or WRC_Continue;
+*/
+int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
+  SrcList *pSrc;
+  int i;
+  struct SrcList_item *pItem;
+
+  pSrc = p->pSrc;
+  if( pSrc ){
+    for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
+      if( sqlite3WalkSelect(pWalker, pItem->pSelect) ){
+        return WRC_Abort;
+      }
+    }
+  }
+  return WRC_Continue;
+} 
+
+/*
+** Call sqlite3WalkExpr() for every expression in Select statement p.
+** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and
+** on the compound select chain, p->pPrior.
+**
+** Return WRC_Continue under normal conditions.  Return WRC_Abort if
+** there is an abort request.
+**
+** If the Walker does not have an xSelectCallback() then this routine
+** is a no-op returning WRC_Continue.
+*/
+int sqlite3WalkSelect(Walker *pWalker, Select *p){
+  int rc;
+  if( p==0 || pWalker->xSelectCallback==0 ) return WRC_Continue;
+  rc = WRC_Continue;
+  while( p  ){
+    rc = pWalker->xSelectCallback(pWalker, p);
+    if( rc ) break;
+    if( sqlite3WalkSelectExpr(pWalker, p) ) return WRC_Abort;
+    if( sqlite3WalkSelectFrom(pWalker, p) ) return WRC_Abort;
+    p = p->pPrior;
+  }
+  return rc & WRC_Abort;
+}
index 9c70c31abdc429831167aab07adc5c79d3698aed..758db3d3b31a5acd872b669cb11a10e425123575 100644 (file)
@@ -16,7 +16,7 @@
 ** so is applicable.  Because this module is responsible for selecting
 ** indices, you might also think of this module as the "query optimizer".
 **
-** $Id: where.c,v 1.319 2008/08/01 17:37:41 danielk1977 Exp $
+** $Id: where.c,v 1.320 2008/08/20 16:35:10 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -320,9 +320,9 @@ static void createMask(ExprMaskSet *pMaskSet, int iCursor){
 ** tree.
 **
 ** In order for this routine to work, the calling function must have
-** previously invoked sqlite3ExprResolveNames() on the expression.  See
+** previously invoked sqlite3ResolveExprNames() on the expression.  See
 ** the header comment on that routine for additional information.
-** The sqlite3ExprResolveNames() routines looks for column names and
+** The sqlite3ResolveExprNames() routines looks for column names and
 ** sets their opcodes to TK_COLUMN and their Expr.iTable fields to
 ** the VDBE cursor number of the table.  This routine just has to
 ** translate the cursor numbers into bitmask values and OR all
@@ -396,10 +396,12 @@ static int allowedOp(int op){
 ** attached to the right. For the same reason the EP_ExpCollate flag
 ** is not commuted.
 */
-static void exprCommute(Expr *pExpr){
+static void exprCommute(Parse *pParse, Expr *pExpr){
   u16 expRight = (pExpr->pRight->flags & EP_ExpCollate);
   u16 expLeft = (pExpr->pLeft->flags & EP_ExpCollate);
   assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
+  pExpr->pRight->pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight);
+  pExpr->pLeft->pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
   SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl);
   pExpr->pRight->flags = (pExpr->pRight->flags & ~EP_ExpCollate) | expLeft;
   pExpr->pLeft->flags = (pExpr->pLeft->flags & ~EP_ExpCollate) | expRight;
@@ -519,7 +521,7 @@ static void exprAnalyzeAll(
 ** literal that does not begin with a wildcard.  
 */
 static int isLikeOrGlob(
-  sqlite3 *db,      /* The database */
+  Parse *pParse,    /* Parsing and code generating context */
   Expr *pExpr,      /* Test this expression */
   int *pnPattern,   /* Number of non-wildcard prefix characters */
   int *pisComplete, /* True if the only wildcard is % in the last character */
@@ -531,6 +533,7 @@ static int isLikeOrGlob(
   int c, cnt;
   char wc[3];
   CollSeq *pColl;
+  sqlite3 *db = pParse->db;
 
   if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, wc) ){
     return 0;
@@ -548,7 +551,7 @@ static int isLikeOrGlob(
   if( pLeft->op!=TK_COLUMN ){
     return 0;
   }
-  pColl = pLeft->pColl;
+  pColl = sqlite3ExprCollSeq(pParse, pLeft);
   assert( pColl!=0 || pLeft->iColumn==-1 );
   if( pColl==0 ){
     /* No collation is defined for the ROWID.  Use the default. */
@@ -788,7 +791,7 @@ static void exprAnalyze(
         pDup = pExpr;
         pNew = pTerm;
       }
-      exprCommute(pDup);
+      exprCommute(pParse, pDup);
       pLeft = pDup->pLeft;
       pNew->leftCursor = pLeft->iTable;
       pNew->leftColumn = pLeft->iColumn;
@@ -909,7 +912,7 @@ or_not_possible:
   ** The last character of the prefix "abc" is incremented to form the
   ** termination condition "abd".
   */
-  if( isLikeOrGlob(db, pExpr, &nPattern, &isComplete, &noCase) ){
+  if( isLikeOrGlob(pParse, pExpr, &nPattern, &isComplete, &noCase) ){
     Expr *pLeft, *pRight;
     Expr *pStr1, *pStr2;
     Expr *pNewExpr1, *pNewExpr2;
@@ -2278,7 +2281,7 @@ WhereInfo *sqlite3WhereBegin(
     pTabItem = &pTabList->a[pLevel->iFrom];
     pTab = pTabItem->pTab;
     iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
-    if( pTab->isEphem || pTab->pSelect ) continue;
+    if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ) continue;
 #ifndef SQLITE_OMIT_VIRTUALTABLE
     if( pLevel->pBestIdx ){
       int iCur = pTabItem->iCursor;
@@ -2837,7 +2840,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
     struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
     Table *pTab = pTabItem->pTab;
     assert( pTab!=0 );
-    if( pTab->isEphem || pTab->pSelect ) continue;
+    if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ) continue;
     if( !pWInfo->okOnePass && (pLevel->flags & WHERE_IDX_ONLY)==0 ){
       sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
     }
index 28f4a913ee7f8ecf9d3638d1826ec1355970f7c2..bf619231da1ff4d3f1eac981a0ee39332cb9216d 100644 (file)
@@ -12,7 +12,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this script is page cache subsystem.
 #
-# $Id: collate2.test,v 1.5 2007/02/01 23:02:46 drh Exp $
+# $Id: collate2.test,v 1.6 2008/08/20 16:35:10 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -136,6 +136,26 @@ do_test collate2-1.2.3 {
      ORDER BY 1, oid;
   }
 } {ab aB Ab AB ba bA Ba BA bb bB Bb BB}
+do_test collate2-1.2.4 {
+  execsql {
+    SELECT b FROM collate2t1 WHERE b > 'aa' ORDER BY +b;
+  }
+} {ab aB Ab AB ba bA Ba BA bb bB Bb BB}
+do_test collate2-1.2.5 {
+  execsql {
+    SELECT b FROM collate2t1 WHERE a COLLATE nocase > 'aa' ORDER BY +b;
+  }
+} {ab aB Ab AB ba bA Ba BA bb bB Bb BB}
+do_test collate2-1.2.6 {
+  execsql {
+    SELECT b FROM collate2t1 WHERE b COLLATE nocase > 'aa' ORDER BY +b;
+  }
+} {ab aB Ab AB ba bA Ba BA bb bB Bb BB}
+do_test collate2-1.2.7 {
+  execsql {
+    SELECT b FROM collate2t1 WHERE c COLLATE nocase > 'aa' ORDER BY +b;
+  }
+} {ab aB Ab AB ba bA Ba BA bb bB Bb BB}
 do_test collate2-1.3 {
   execsql {
     SELECT c FROM collate2t1 WHERE c > 'aa' ORDER BY 1;
@@ -169,6 +189,11 @@ do_test collate2-1.5 {
     SELECT b FROM collate2t1 WHERE b < 'aa' ORDER BY 1, oid;
   }
 } {}
+do_test collate2-1.5.1 {
+  execsql {
+    SELECT b FROM collate2t1 WHERE b < 'aa' ORDER BY +b;
+  }
+} {}
 do_test collate2-1.6 {
   execsql {
     SELECT c FROM collate2t1 WHERE c < 'aa' ORDER BY 1;
@@ -229,6 +254,11 @@ do_test collate2-1.17 {
     SELECT b FROM collate2t1 WHERE b BETWEEN 'Aa' AND 'Bb' ORDER BY 1, oid;
   }
 } {aa aA Aa AA ab aB Ab AB ba bA Ba BA bb bB Bb BB}
+do_test collate2-1.17.1 {
+  execsql {
+    SELECT b FROM collate2t1 WHERE b BETWEEN 'Aa' AND 'Bb' ORDER BY +b;
+  }
+} {aa aA Aa AA ab aB Ab AB ba bA Ba BA bb bB Bb BB}
 do_test collate2-1.18 {
   execsql {
     SELECT c FROM collate2t1 WHERE c BETWEEN 'Aa' AND 'Bb' ORDER BY 1;
index 1a26ab865b0747993a09de65690976dc093ec8c8..c4dbfbe4cf344c7e1c3abb0cf57453b5ab0d7713 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this script is page cache subsystem.
 #
-# $Id: collate3.test,v 1.12 2008/07/12 14:52:20 drh Exp $
+# $Id: collate3.test,v 1.13 2008/08/20 16:35:10 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -292,19 +292,19 @@ do_test collate3-4.7 {
     SELECT * FROM collate3t1 ORDER BY a COLLATE user_defined;
   }
 } {1 {no such collation sequence: user_defined}}
-do_test collate3-4.8 {
+do_test collate3-4.8.1 {
   db collate user_defined "string compare"
   catchsql {
     SELECT * FROM collate3t1 ORDER BY a COLLATE user_defined;
   }
 } {0 {hello {}}}
-do_test collate3-4.8 {
+do_test collate3-4.8.2 {
   db close
   lindex [catch {
     sqlite3 db test.db
   }] 0
 } {0}
-do_test collate3-4.8 {
+do_test collate3-4.8.3 {
   execsql {
     DROP TABLE collate3t1;
   }
index 2d78807cc0de15ae16e864fb357343ba93d42a06..b9b7dd1ab4af9083e5b069743077a3604cb70399 100644 (file)
@@ -12,7 +12,7 @@
 #
 # This file tests malloc failures in concert with fuzzy SQL generation.
 #
-# $Id: fuzz_malloc.test,v 1.9 2007/09/03 15:42:48 drh Exp $
+# $Id: fuzz_malloc.test,v 1.10 2008/08/20 16:35:10 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -56,6 +56,7 @@ proc do_fuzzy_malloc_test {testname args} {
     expr srand($jj)
     incr jj
     set ::sql [subst $::fuzzyopts(-template)]
+    # puts fuzyy-sql=\[$::sql\]; flush stdout
     foreach {rc res} [catchsql "$::sql"] {}
     if {$rc==0} {
       do_malloc_test $testname-$ii -sqlbody $::sql -sqlprep $::prep
index 08b730924c3e3ae69d362cbad906cbd38d4469dc..f38efcf38fc7cd1411e70e86f72b7f4b0aecf128 100644 (file)
@@ -12,7 +12,7 @@
 # focus of this file is testing aggregate functions and the
 # GROUP BY and HAVING clauses of SELECT statements.
 #
-# $Id: select5.test,v 1.18 2008/08/02 03:50:40 drh Exp $
+# $Id: select5.test,v 1.19 2008/08/20 16:35:10 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -159,7 +159,6 @@ do_test select5-5.5 {
 # Test rendering of columns for the GROUP BY clause.
 #
 do_test select5-5.11 {
-breakpoint
   execsql {
     SELECT max(c), b*a, b, a FROM t2 GROUP BY b*a, b, a
   }
index 7223b5ee1b1728529672bc06df4ee58af328811b..9d83f7d4548ae54f077f69dcf15867efef8015cf 100644 (file)
@@ -12,7 +12,7 @@
 # focus of this file is testing SELECT statements that contain
 # subqueries in their FROM clause.
 #
-# $Id: select6.test,v 1.27 2008/07/12 14:52:20 drh Exp $
+# $Id: select6.test,v 1.28 2008/08/20 16:35:10 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -300,7 +300,7 @@ do_test select6-5.2 {
 
 # Tests of compound sub-selects
 #
-do_test select5-6.1 {
+do_test select6-6.1 {
   execsql {
     DELETE FROM t1 WHERE x>4;
     SELECT * FROM t1
index fbb300205754063c1dad4c187d8f0b73eb690dce..281e5dc91fc3adf9dc6610958b99247a774f0290 100644 (file)
@@ -13,7 +13,7 @@
 # ORDER BY clauses on compound SELECT statements raised by ticket
 # #2822 have been dealt with.
 #
-# $Id: tkt2822.test,v 1.5 2008/08/04 03:51:24 danielk1977 Exp $
+# $Id: tkt2822.test,v 1.6 2008/08/20 16:35:10 drh Exp $
 #
 
 set testdir [file dirname $argv0]
@@ -134,12 +134,12 @@ do_test tkt2822-3.2 {
 # Test that if a match cannot be found in the leftmost SELECT, an
 # attempt is made to find a match in subsequent SELECT statements.
 #
-do_test tkt2822-3.1 {
+do_test tkt2822-3.3 {
   execsql {
     SELECT a, b, c FROM t1 UNION ALL SELECT a AS x, b, c FROM t2 ORDER BY x;
   }
 } {1 3 9 2 6 18 3 9 27 4 12 36 5 15 45 6 18 54}
-do_test tkt2822-3.2 {
+do_test tkt2822-3.4 {
   # But the leftmost SELECT takes precedence.
   execsql {
     SELECT a AS b, CAST (b AS TEXT) AS a, c FROM t1 
@@ -148,7 +148,7 @@ do_test tkt2822-3.2 {
       ORDER BY a;
   }
 } {2 6 18 4 12 36 6 18 54 5 15 45 1 3 9 3 9 27}
-do_test tkt2822-3.3 {
+do_test tkt2822-3.5 {
   execsql {
     SELECT a, b, c FROM t2 
       UNION ALL 
index e3b8a777c56d3cf683d70b6794d4faaa9949d6b3..fbad3f6d73aeb80aa67492bcd99d166d9fdf9788 100644 (file)
@@ -246,6 +246,8 @@ foreach file {
    vdbeblob.c
    journal.c
 
+   walker.c
+   resolve.c
    expr.c
    alter.c
    analyze.c