Tarantool development patches archive
 help / color / mirror / Atom feed
* [tarantool-patches] [PATCH 0/3] sql: move column's default value to Tarantool's core
@ 2018-03-29  6:42 Kirill Yukhin
  2018-03-29  6:42 ` [tarantool-patches] [PATCH 1/3] Add value field to _schema space Kirill Yukhin
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Kirill Yukhin @ 2018-03-29  6:42 UTC (permalink / raw)
  To: v.shpilevoy; +Cc: tarantool-patches, Kirill Yukhin

This patches-set consists of 3 almost independent patches:
 1. It adds a nullable field to space _schema, which will make it easier
    to use from within SQL engine.
 2. [tiny] Remove couple of dead functions from SQL engine.
 3. [main] Moves DEFAULT values, both string and compiled AST to Tarantool's
    core. New routine which will allow to compile SQL-context free expressions
    was introduced. Compiled AST is stored inside space_def and allocated
    using single top-most malloc().

NB1: It should be mentioned, that duplication routines for expressions are not elegant
enough to do single malloc(), it allocates nodes on demand and this may and will
be refactored. Issue to be submitted.

NB2: Handle `struct sqlite3 *` use used only for regacy memory allocation. And should
be removed from all API parameters, after we'll choose right allocator and emply it.
Another issue to be submitted.

Branch: https://github.com/tarantool/tarantool/tree/kyukhin/gh-3235-move-default
Issue: https://github.com/tarantool/tarantool/issues/3235

Kirill Yukhin (3):
  Add value field to _schema space
  sql: remove dead find DB functions.
  sql: move default col values to Tarantool's core

 src/CMakeLists.txt           |   2 +-
 src/box/alter.cc             |  17 +
 src/box/bootstrap.snap       | Bin 1638 -> 1657 bytes
 src/box/box.cc               |   3 +-
 src/box/field_def.c          |   5 +-
 src/box/field_def.h          |   4 +
 src/box/lua/upgrade.lua      |  14 +-
 src/box/space_def.c          | 105 ++++--
 src/box/space_def.h          |  10 +-
 src/box/sql.c                |  64 +++-
 src/box/sql.h                |  30 ++
 src/box/sql/build.c          |  48 +--
 src/box/sql/delete.c         |  12 +-
 src/box/sql/expr.c           | 114 +++---
 src/box/sql/fkey.c           |  13 +-
 src/box/sql/insert.c         |  32 +-
 src/box/sql/main.c           |  15 -
 src/box/sql/parse.c          | 876 ++++++++++++++++++++++---------------------
 src/box/sql/parse.y          |  32 +-
 src/box/sql/resolve.c        |  12 +-
 src/box/sql/select.c         |  28 +-
 src/box/sql/sqliteInt.h      |  11 +-
 src/box/sql/tokenize.c       | 121 ++++++
 src/box/sql/trigger.c        |  12 +-
 src/box/sql/update.c         |   2 +-
 src/box/sql/wherecode.c      |   2 +-
 src/box/sql/whereexpr.c      |   6 +-
 test/box-py/bootstrap.result |   3 +-
 test/box/access_misc.result  |   3 +-
 test/xlog/upgrade.result     |   3 +-
 30 files changed, 948 insertions(+), 651 deletions(-)

-- 
2.11.0

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [tarantool-patches] [PATCH 1/3] Add value field to _schema space
  2018-03-29  6:42 [tarantool-patches] [PATCH 0/3] sql: move column's default value to Tarantool's core Kirill Yukhin
@ 2018-03-29  6:42 ` Kirill Yukhin
  2018-03-29  6:42 ` [tarantool-patches] [PATCH 2/3] sql: remove dead find DB functions Kirill Yukhin
  2018-03-29  6:42 ` [tarantool-patches] [PATCH 3/3] sql: move default col values to Tarantool's core Kirill Yukhin
  2 siblings, 0 replies; 8+ messages in thread
From: Kirill Yukhin @ 2018-03-29  6:42 UTC (permalink / raw)
  To: v.shpilevoy; +Cc: tarantool-patches, Kirill Yukhin

_schema represented as key-value storage for various
values common for Tarantool, like next id for space creation.
SQL requires format to be fully specified for columns being
access. Unfortunatelly, _schema is inserted into _space
before _space's format is set and since DD triggers are
disabled during upgrade, format for _schema tuple in _space
stays the same. So, set value nullable field in upgrade,
regenerate initial snap, update tests.
Also, as far as _schema's tuple in _space is not updated:
relax fieldno check in sql.c
---
 src/box/bootstrap.snap       | Bin 1638 -> 1657 bytes
 src/box/lua/upgrade.lua      |  14 ++++++++++++--
 src/box/sql.c                |   5 ++---
 test/box-py/bootstrap.result |   3 ++-
 test/box/access_misc.result  |   3 ++-
 test/xlog/upgrade.result     |   3 ++-
 6 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/src/box/bootstrap.snap b/src/box/bootstrap.snap
index cf481f9a708e29f680d074ddf755ef6659cdadd4..783aa88995318726e7a93a403a729210d18a39c9 100644
GIT binary patch
literal 1657
zcmV-<28Q`lPC-x#FfK7O3RY!ub7^mGIv_GGFfKGLF*h+SXE-x6Fl97j3Q2BrbYX5|
zWjY`>IbkwoGh;X{Ib}6rEi_|fVJ%{1Wi~A^V`MO5IAk?rF*r90RzqxWV{1Afdoem7
zFntON)w&D1%?14c&O{PINTmP(0000ewJ-euP^B*bnn6SkNYEHJ0f0S>Qi)TFUQI%s
z7R+K1LD)oM^Z*C#FSwWPm}t><N}AkEF-elXq={xia_vI#%;}aApx)dpLU&&k)k>C7
zOqR-&QqKUy0NenteZ=#74Q8&%*_W391!*z&8-^nGnADK~&C+tpho~Edr1p3odNRDM
zv!(B=Y`u`zudarHI`7V7Kejpy$Q(j{`s!EbUA+o(PgY$j5t5A*K(n-L?Yqi*l&LzX
ze|J73lCj6c0?;fihbYmZ0>-QUC*rJ0Sq<7onr3MUfI!t^=KEQ)BbudUQ6>7a_j6aV
zs##k8P3rqlpAAlpsVjXb)TxB?aWy5*raP55%yIbi;S5;zcTR>_W^OK((kd=MTCAkD
zWN~suhYA2ofdZ!nnx*A~A7)nGqmb9}2SJHL|6<p7gECg$qj%Phfone}ITy{+Qq{@p
z+RsVvtfmD=uqIP1FIHz1XqJ{_e|`jOGUc6BCPC1KVBhh~ub`j*boOF3=0Lxn=cH0F
zpjle#`=KbJLfm>4zWD6>c7Fa`oma2@;CG#6<97~AqMz(}?g>?x0zRKvyv1cKPgY+D
z+`aF4S6fWQz#FE{u1OJlU-&sSq%){LhUD=bxfiRX0h*=dcvmmpM-diYEQYbM)psh)
zA1P*)M~5e82gQpMHOE9wi4%#_h||f8*{-7<j%I18nMS%B&W5YuM3_RDIFo4x#0<?$
zN#=u$2hGy5h)joV#@u9LIG8aTRQ#$aXn@H8g8}Bk%k~oUV!>Kcg=!X&Qb`m@Ftv^*
zXqJ{E3Dhhy<;k9`$rzFU-C@+F5(RBBFPf$0zTw5=>hjnZ>Q~R}S5OTQQs=OrFTX-m
ze{ubG?u9+vV^V)a_`cu$`azH9CPPM^R2~SLrKQ;~*5vM<P~CZ;Sz3Z%-rbwk7bDHm
zk~F<p&2hlWdki=ohi$$NW%{tGbn}lY-4EB4uFaoH9TxE+?&&52mTGP}JuL9pk)!Fb
zJ3OZx9FCbAn~nNXL$kEBqe^sI8dZzAV@;-Jwz{@%Mp02wl}?6cX-T5b_p`DlXE7|T
zuC3eIKa%{c7GU5Uj=zVh_Tocv!*C8!<QS{gwV7P#y!!50YYWZN(gc`NjV&JP#Aty%
z-0<-}EgIc4#_)NTiWP;sDqb3|3JVe0&q-M4Pl9KquFb?kv$WLFA>&oWl+HB!IY~qF
zBch<x>e^&h1Tc*N34u7M;aFr43CsWhfB+}}0R~4Y$7~)FfWSD4!!V427=~j23}ORE
z03av`2Q)yn0GKQ-LyH^(01_wK?6!60k_bZZd=P>c1wJdax}iF?E8}Zhby9>ZB0_jr
zpa(z(?z+Uv4eXngMojh=6Rk@!DJseVR^KdRX+y#@$0xYw?Py>*l?O75dms48Q=b-4
zQJEVw!KaX=ZHUuHA&*q^{1P#SUiKF<kQI>Z_Ltd8{U>=~P?BFqrWcP>g#i(%SNpZE
z|L0*G54n<zMrPD-r4&rzK)A@29e9?GxkKA59dn1aS?TDqx1Ku`seIZ3A_&e=(_l-2
z6TvtII??WIxT(LJSV#)u0&I{J#0A(GF+{YfwBv!^3h=@$4!zevHt(^1!VLodpQgq8
zG~P!&ziy~!TFPiq`u1R0Tt3_I)e`=K#)hfv7Hp+ao09d1GyQKWI+``7$4rb||Bv>;
zlX*zA$hzggJU=3x8Z!jFkc94>pbX0^Yk6XQnEEJmhijo|lF*KWp;@46hiDAd!CYXN
zPDZUHN7{jIMLeGX@xZR$9(<wYp-6C-uH_HP42e`nK`!(X5qCR^hK4^X3(P%IJ32%1
zAU17-(lK4jvqapes2QLX!Y&D#7Q?ZQ`w>9<@Ba`Rit7Ym1n~z$@a?4jY+MK*VE|W_
z3}c#kIEVtm!vN}}uxUzfrQeo;U*t8u>JNBMzDIVj_ywgC;YluBB|jv4Jhdb0&#~rG
zl;O!dl=%u43}<_wKnrSzdIrn5Vml~ywJOlFj{c2WClwJ6%c_nbz*l5FNwBya)ex=i
D_yrEc

literal 1638
zcmV-s2ATO&PC-x#FfK7O3RY!ub7^mGIv_DFI4(0SGcq|XXJRvDWH>NoWH<^*ZgX^D
zZewLSAT?t+Fk&`lW-T*gIc6<1WjHu3Ib$_8Eihp;VmC2mVmLB4H40WkY;R+0Iv{&}
z3JTS_3%bn(>;TRrd}U9i0000004TLD{QyuMF92#l7!F6^*th|3gfPY!V+g{|Vd9WO
z<bH2NiNe7cmm8S;mG~QIWy(Y;$+~PQx$>-uIW^+64IUcKZAzsJYwU7Yoz$-)G?Nii
zN-50%!vNO+1Msb9nOiacOHwxGj~r*^>vzp>$Q0CE+@6~?a5Kr-;pF~#9LcY1VnG75
zkeF^|E))6g-_LaU`m!9IAr<GhbSup*&H8*tvn|#K$rcKLZ#`c<w{|aStS@rizpoM5
zU)SUUz_*@5l;}_aBW5*7ew&*#yR(5XzV!q^z;bf?u3fYv_}25s`hdH`$*q~ix1Ojl
z#i>+Y49J;OCD03VNoNmLQl(TON--!e6{<v}GGOWYdvp9~=+<IuwbGK4rN==L9!svw
zQ~_{nPF>B)IB@M=t{UK5Pc7<kyLK;my8r1Q9@(Qc`FZXl&9!^krIup=>)M;A7JTc;
z`euf8?aeN=rUgenZicRIW=RV0t*805Kk{)i>{2^Qu(KiPxlDI#2S<Z^cQgBP0N;9=
zV|JzJ&tUh&QZRsTJ$cq6NqXb=(yT9k>F@db6esiDighjO&o`~q-^-G4ZQ5wx@mQAv
zH+sAL%hOyP&58)*-gBB;oeXDU9>er=ll(ex)I03qTjY9%M1Q&T-OPpp0Z=1ARG>dn
z)NIX6jSLNn7bmQY37HZr5~~rb6*{{dS2-2F^~9(VE_I4Ip-v)9AxtNei3EZKLn@6v
zj6C35Pn}VRjf8Ha7Y^vl2A0n(3L0E8xL|O(AlgJPA`AD1Dp*u!iVaZ+xmXLDfNwoP
z5-O@gMVmI8n=>L>_b;n0)@NsX5#d|Up2z%^t?Xyu$YVB|$97OaLf^}9z#SXCA3Od0
zeK*?pu8I8-0n|Tt&9&J1?WD&D6k7uU-+H1yf86Z9<FPak@U5pP?*6-)eF4I^o+cVG
zst}x~Pbv?UO{G-Kw<>X*MwP<VC!!RFDbK`xF&VH}bd%{}fyWLRtmD$uta6-ikZx=?
ztf&UQ^}HbKlU^E@lly<%3~SfIHg3kx&yN*O2EO$SRqeZWZEn_L+-hMPN7Hp_`qWy0
z@$IqHy~pAgdL+B-+oNZeGkam1$pzmnFsIhGz_*?z#E@0K{5TV%#pmIM4}J5Z@l9on
z8|`Abq?|I#m&(lgc!+fEP1*O_6jNJan~4R!^_<ZmBWB5vZ<wyV2?K*edQq%}ZKD+d
zfi<Y%RAi76m;nF)0Z;((1xG38Y#tJTz&MKIFpPm1hGPH>;sQqiATS6Chyc|Bm@I2T
zFV+AyjGK5Fx+20r^o_mIH~Pv253pN{QKuG<n%E=c*c>ZFVhs#*0*FB0by&fH<x`S~
zOCNZmby+y0BJsrRC5E3i)IW3F&mC=_IL)b4BdXHj;LpnXa{#{`+)y^&KQ9deLQfO9
zYN%?GNSo>FzM!F50Ksn8J6k3g0s9y3)N9W6qSCA|h$3~gU)$%r^Nr&jSMzAhMQxNo
zA155((@dqaReqgO>9G7dqtam+FS<BcA2)POKH&-(4&fru;B@jOCo2Vpq8(@$K<F;|
zE+5XQY*>DsQR#RhBZamXb~e!4oT@U{)Y}cj?p{PERKofHxPkB4_!j^Cx}narG|`Ip
z?VDZvKik&Tx$cbK4r<s98%mQzpY<<i`X5r{$>p3Lo){Va-}yrUkKyQ%b<Tl#|9BZS
z{u25i3DsO<5!N`?lFRsn`d~DKYiVqfq=7*=?MqFcY7Esh=V{n1M!6*C%pu&1c%K;k
z)vey1eWB&_NZ>AQd{bqz*piMCE;kba40;qA3~*E{Kj=~82}9x$c-qDqWjfY`U0hOZ
z4nVnvT`LqH4@U?0Ta5N!oFW^fXN?1pTkxqOKUo$)Qkc)LBx{;xIj5m|cxX+XFxRc<
zbwTYi@DzF7q%zH;8T}Cq7IBg2Cp?J?SM7&nziI7U6)>wALgIhU54CWu6!m6b3(#7P
k&cB;FNloBtT%ms(>pViJVcFJ^Gx&N^Pm;nd2h|X*?Mu=RQ2+n{

diff --git a/src/box/lua/upgrade.lua b/src/box/lua/upgrade.lua
index a514d12..7c8f38b 100644
--- a/src/box/lua/upgrade.lua
+++ b/src/box/lua/upgrade.lua
@@ -479,10 +479,11 @@ local function upgrade_to_1_8_4()
                       {name='nlt', type='string'},
                       {name='ndlt', type='string'},
                       {name='sample', type='scalar'}}
+    local MAP = setmap({})
 
     log.info("create space _sql_stat1")
     _space:insert{box.schema.SQL_STAT1_ID, ADMIN, '_sql_stat1', 'memtx', 0,
-                  setmap({}), stat1_ft}
+                  MAP, stat1_ft}
 
     log.info("create index primary on _sql_stat1")
     _index:insert{box.schema.SQL_STAT1_ID, 0, 'primary', 'tree',
@@ -490,12 +491,21 @@ local function upgrade_to_1_8_4()
 
     log.info("create space _sql_stat4")
     _space:insert{box.schema.SQL_STAT4_ID, ADMIN, '_sql_stat4', 'memtx', 0,
-                  setmap({}), stat4_ft}
+                  MAP, stat4_ft}
 
     log.info("create index primary on _sql_stat4")
     _index:insert{box.schema.SQL_STAT4_ID, 0, 'primary', 'tree',
                   {unique = true}, {{0, 'string'}, {1, 'string'},
                   {5, 'scalar'}}}
+
+    -- Nullability wasn't skipable. This was fixed in 1-7.
+    -- Now, abscent field means NULL, so we can safely set second
+    -- field in format, marking it nullable.
+    log.info("Add nullable value field to space _schema")
+    local format = {}
+    format[1] = {type='string', name='key'}
+    format[2] = {type='any', name='value', is_nullable=true}
+    box.space._schema:format(format)
 end
 
 --------------------------------------------------------------------------------
diff --git a/src/box/sql.c b/src/box/sql.c
index a13f2f8..6d8ef9a 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -220,9 +220,8 @@ tarantoolSqlite3TupleColumnFast(BtCursor *pCur, u32 fieldno, u32 *field_size)
 	assert(c != NULL);
 	assert(c->tuple_last != NULL);
 	struct tuple_format *format = tuple_format(c->tuple_last);
-	assert(format->exact_field_count == 0
-	       || fieldno < format->exact_field_count);
-	if (format->fields[fieldno].offset_slot == TUPLE_OFFSET_SLOT_NIL)
+	if (fieldno < format->field_count
+	    || format->fields[fieldno].offset_slot == TUPLE_OFFSET_SLOT_NIL)
 		return NULL;
 	const char *field = tuple_field(c->tuple_last, fieldno);
 	const char *end = field;
diff --git a/test/box-py/bootstrap.result b/test/box-py/bootstrap.result
index f310326..e6c01fe 100644
--- a/test/box-py/bootstrap.result
+++ b/test/box-py/bootstrap.result
@@ -13,7 +13,8 @@ box.space._cluster:select{}
 ...
 box.space._space:select{}
 ---
-- - [272, 1, '_schema', 'memtx', 0, {}, [{'type': 'string', 'name': 'key'}]]
+- - [272, 1, '_schema', 'memtx', 0, {}, [{'type': 'string', 'name': 'key'}, {'type': 'any',
+        'name': 'value', 'is_nullable': true}]]
   - [276, 1, '_collation', 'memtx', 0, {}, [{'name': 'id', 'type': 'unsigned'}, {
         'name': 'name', 'type': 'string'}, {'name': 'owner', 'type': 'unsigned'},
       {'name': 'type', 'type': 'string'}, {'name': 'locale', 'type': 'string'}, {
diff --git a/test/box/access_misc.result b/test/box/access_misc.result
index 1bbc8a3..9b3c5c0 100644
--- a/test/box/access_misc.result
+++ b/test/box/access_misc.result
@@ -732,7 +732,8 @@ box.space._user:select()
 ...
 box.space._space:select()
 ---
-- - [272, 1, '_schema', 'memtx', 0, {}, [{'type': 'string', 'name': 'key'}]]
+- - [272, 1, '_schema', 'memtx', 0, {}, [{'type': 'string', 'name': 'key'}, {'type': 'any',
+        'name': 'value', 'is_nullable': true}]]
   - [276, 1, '_collation', 'memtx', 0, {}, [{'name': 'id', 'type': 'unsigned'}, {
         'name': 'name', 'type': 'string'}, {'name': 'owner', 'type': 'unsigned'},
       {'name': 'type', 'type': 'string'}, {'name': 'locale', 'type': 'string'}, {
diff --git a/test/xlog/upgrade.result b/test/xlog/upgrade.result
index 710ca40..5a6bd05 100644
--- a/test/xlog/upgrade.result
+++ b/test/xlog/upgrade.result
@@ -40,7 +40,8 @@ box.space._schema:select()
 ...
 box.space._space:select()
 ---
-- - [272, 1, '_schema', 'memtx', 0, {}, [{'type': 'string', 'name': 'key'}]]
+- - [272, 1, '_schema', 'memtx', 0, {}, [{'type': 'string', 'name': 'key'}, {'type': 'any',
+        'name': 'value', 'is_nullable': true}]]
   - [276, 1, '_collation', 'memtx', 0, {}, [{'name': 'id', 'type': 'unsigned'}, {
         'name': 'name', 'type': 'string'}, {'name': 'owner', 'type': 'unsigned'},
       {'name': 'type', 'type': 'string'}, {'name': 'locale', 'type': 'string'}, {
-- 
2.11.0

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [tarantool-patches] [PATCH 2/3] sql: remove dead find DB functions.
  2018-03-29  6:42 [tarantool-patches] [PATCH 0/3] sql: move column's default value to Tarantool's core Kirill Yukhin
  2018-03-29  6:42 ` [tarantool-patches] [PATCH 1/3] Add value field to _schema space Kirill Yukhin
@ 2018-03-29  6:42 ` Kirill Yukhin
  2018-03-29  6:42 ` [tarantool-patches] [PATCH 3/3] sql: move default col values to Tarantool's core Kirill Yukhin
  2 siblings, 0 replies; 8+ messages in thread
From: Kirill Yukhin @ 2018-03-29  6:42 UTC (permalink / raw)
  To: v.shpilevoy; +Cc: tarantool-patches, Kirill Yukhin

Remove functions to find DB by name. Not used anymore,
was used by SQL legacy code.
---
 src/box/sql/build.c | 30 ------------------------------
 1 file changed, 30 deletions(-)

diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 0efd5a6..05a7cc9 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -523,36 +523,6 @@ sqlite3NameFromToken(sqlite3 * db, Token * pName)
 }
 
 /*
- * Parameter zName points to a nul-terminated buffer containing the name
- * of a database ("main", "temp" or the name of an attached db). This
- * function returns the index of the named database in db->aDb[], or
- * -1 if the named db cannot be found.
- */
-int
-sqlite3FindDbName(const char *zName MAYBE_UNUSED)
-{
-	assert(0 == sqlite3_stricmp("main", zName));
-	return 0;
-}
-
-/*
- * The token *pName contains the name of a database (either "main" or
- * "temp" or the name of an attached db). This routine returns the
- * index of the named database in db->aDb[], or -1 if the named db
- * does not exist.
- */
-int
-sqlite3FindDb(sqlite3 * db, Token * pName)
-{
-	int i;			/* Database number */
-	char *zName;		/* Name we are searching for */
-	zName = sqlite3NameFromToken(db, pName);
-	i = sqlite3FindDbName(zName);
-	sqlite3DbFree(db, zName);
-	return i;
-}
-
-/*
  * This routine is used to check if the UTF-8 string zName is a legal
  * unqualified name for an identifier.
  * Some objects may not be checked, because they are validated in Tarantool.
-- 
2.11.0

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [tarantool-patches] [PATCH 3/3] sql: move default col values to Tarantool's core
  2018-03-29  6:42 [tarantool-patches] [PATCH 0/3] sql: move column's default value to Tarantool's core Kirill Yukhin
  2018-03-29  6:42 ` [tarantool-patches] [PATCH 1/3] Add value field to _schema space Kirill Yukhin
  2018-03-29  6:42 ` [tarantool-patches] [PATCH 2/3] sql: remove dead find DB functions Kirill Yukhin
@ 2018-03-29  6:42 ` Kirill Yukhin
  2018-03-29 14:00   ` [tarantool-patches] " v.shpilevoy
  2 siblings, 1 reply; 8+ messages in thread
From: Kirill Yukhin @ 2018-03-29  6:42 UTC (permalink / raw)
  To: v.shpilevoy; +Cc: tarantool-patches, Kirill Yukhin

Extract expressions parsing into separate routine to
allow Tarantool's backend compile DEFAULT statements w/o
SQL machinery at all. So far, for DEFAULT values no context
is needed: only constant expressions and built-ins are allowed.
In future, table context will be added to allow use column
values for CHECK constraint expressions.

Move DEFAULT string value to space_def. Move compiled expresion
to field_def as well. Reason not to move compiled expression
to tuple_field as follows: we do not want to engage parser
during tuple validation. So, do it in alter.cc.

In order to allow expression duplication in alter.cc: expose
those routines from expr.c and make their names correspond to
coding style.

Since recovery is performed before SQL fronend initialization:
split it into two pieces: 1. create SQL handler, enable
all subsystems 2. Do recovery.  This will allow to run
parser during recovery, since it needs db handle so far.

Part of #3235
---
 src/CMakeLists.txt      |   2 +-
 src/box/alter.cc        |  17 +
 src/box/box.cc          |   3 +-
 src/box/field_def.c     |   5 +-
 src/box/field_def.h     |   4 +
 src/box/space_def.c     | 105 ++++--
 src/box/space_def.h     |  10 +-
 src/box/sql.c           |  59 +++-
 src/box/sql.h           |  30 ++
 src/box/sql/build.c     |  18 +-
 src/box/sql/delete.c    |  12 +-
 src/box/sql/expr.c      | 114 ++++---
 src/box/sql/fkey.c      |  13 +-
 src/box/sql/insert.c    |  32 +-
 src/box/sql/main.c      |  15 -
 src/box/sql/parse.c     | 876 ++++++++++++++++++++++++------------------------
 src/box/sql/parse.y     |  32 +-
 src/box/sql/resolve.c   |  12 +-
 src/box/sql/select.c    |  28 +-
 src/box/sql/sqliteInt.h |  11 +-
 src/box/sql/tokenize.c  | 121 +++++++
 src/box/sql/trigger.c   |  12 +-
 src/box/sql/update.c    |   2 +-
 src/box/sql/wherecode.c |   2 +-
 src/box/sql/whereexpr.c |   6 +-
 25 files changed, 928 insertions(+), 613 deletions(-)

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 8ab09e9..eae40c3 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -268,7 +268,7 @@ add_executable(
 	${LIBUTIL_FREEBSD_SRC}/flopen.c
 	${LIBUTIL_FREEBSD_SRC}/pidfile.c)
 
-add_dependencies(tarantool build_bundled_libs preprocess_exports)
+add_dependencies(tarantool build_bundled_libs preprocess_exports sql)
 
 # Re-link if exports changed
 set_target_properties(tarantool PROPERTIES LINK_DEPENDS ${exports_file})
diff --git a/src/box/alter.cc b/src/box/alter.cc
index 299dcb0..b976d0f 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -52,6 +52,7 @@
 #include "memtx_tuple.h"
 #include "version.h"
 #include "sequence.h"
+#include "sql.h"
 
 /**
  * chap-sha1 of empty string, i.e.
@@ -403,6 +404,22 @@ field_def_decode(struct field_def *field, const char **data,
 			  tt_sprintf("collation is reasonable only for "
 				     "string, scalar and any fields"));
 	}
+
+	if (field->default_value != NULL) {
+		struct Expr *expr = NULL;
+		char *err = 0;
+		/* Recovery is performed before SQL FE is initialized.
+		 * Postpone AST compilation if in process of recovery.
+		 */
+		if (sql_get() != NULL) {
+			sql_compile_expr(sql_get(),
+					 field->default_value,
+					 &expr,
+					 &err);
+			assert(err == NULL);
+			field->default_value_ast = expr;
+		}
+	}
 }
 
 /**
diff --git a/src/box/box.cc b/src/box/box.cc
index a3bbdfc..290d18c 100644
--- a/src/box/box.cc
+++ b/src/box/box.cc
@@ -1731,6 +1731,7 @@ box_cfg_xc(void)
 	replication_init();
 	port_init();
 	iproto_init();
+	sql_init();
 	wal_thread_start();
 
 	title("loading");
@@ -1927,7 +1928,7 @@ box_cfg_xc(void)
 	/* Follow replica */
 	replicaset_follow();
 
-	sql_init();
+	sql_load_schema();
 
 	say_info("ready to accept requests");
 
diff --git a/src/box/field_def.c b/src/box/field_def.c
index 1510509..dc6270a 100644
--- a/src/box/field_def.c
+++ b/src/box/field_def.c
@@ -94,6 +94,7 @@ const struct opt_def field_def_reg[] = {
 	OPT_DEF_ENUM("nullable_action", on_conflict_action, struct field_def,
 		     nullable_action, NULL),
 	OPT_DEF("collation", OPT_UINT32, struct field_def, coll_id),
+	OPT_DEF("default", OPT_STRPTR, struct field_def, default_value),
 	OPT_END,
 };
 
@@ -102,7 +103,9 @@ const struct field_def field_def_default = {
 	.name = NULL,
 	.is_nullable = false,
 	.nullable_action = ON_CONFLICT_ACTION_DEFAULT,
-	.coll_id = COLL_NONE
+	.coll_id = COLL_NONE,
+	.default_value = NULL,
+	.default_value_ast = NULL
 };
 
 enum field_type
diff --git a/src/box/field_def.h b/src/box/field_def.h
index e7be06a..1390863 100644
--- a/src/box/field_def.h
+++ b/src/box/field_def.h
@@ -110,6 +110,10 @@ struct field_def {
 	enum on_conflict_action nullable_action;
 	/** Collation ID for string comparison. */
 	uint32_t coll_id;
+	/** 0-terminated SQL expression for DEFAULT value. */
+	char *default_value;
+	/** AST for parsed default value. */
+	struct Expr *default_value_ast;
 };
 
 #if defined(__cplusplus)
diff --git a/src/box/space_def.c b/src/box/space_def.c
index 1b3c305..7b9a664 100644
--- a/src/box/space_def.c
+++ b/src/box/space_def.c
@@ -32,6 +32,7 @@
 #include "space_def.h"
 #include "diag.h"
 #include "error.h"
+#include "sql.h"
 
 const struct space_opts space_opts_default = {
 	/* .temporary = */ false,
@@ -49,7 +50,7 @@ const struct opt_def space_opts_reg[] = {
 /**
  * Size of the space_def.
  * @param name_len Length of the space name.
- * @param field_names_size Size of all names.
+ * @param fields Fields array of space format.
  * @param field_count Space field count.
  * @param[out] names_offset Offset from the beginning of a def to
  *             a field names memory.
@@ -58,25 +59,37 @@ const struct opt_def space_opts_reg[] = {
  * @retval Size in bytes.
  */
 static inline size_t
-space_def_sizeof(uint32_t name_len, uint32_t field_names_size,
+space_def_sizeof(uint32_t name_len, const struct field_def *fields,
 		 uint32_t field_count, uint32_t *names_offset,
-		 uint32_t *fields_offset)
+		 uint32_t *fields_offset, uint32_t *def_ast_offset)
 {
+	uint32_t field_strs_size = 0;
+	uint32_t def_exprs_size = 0;
+	for (uint32_t i = 0; i < field_count; ++i) {
+		field_strs_size += strlen(fields[i].name) + 1;
+		if (fields[i].default_value != NULL) {
+			int len = strlen(fields[i].default_value);
+			field_strs_size += len + 1;
+		}
+		if (fields[i].default_value_ast != NULL) {
+			struct Expr *expr = fields[i].default_value_ast;
+			def_exprs_size += sql_duped_expr_size(expr, 0);
+		}
+	}
+
 	*fields_offset = sizeof(struct space_def) + name_len + 1;
 	*names_offset = *fields_offset + field_count * sizeof(struct field_def);
-	return *names_offset + field_names_size;
+	*def_ast_offset = *names_offset + field_strs_size;
+	return *def_ast_offset + def_exprs_size;
 }
 
 struct space_def *
 space_def_dup(const struct space_def *src)
 {
-	uint32_t names_offset, fields_offset;
-	uint32_t field_names_size = 0;
-	for (uint32_t i = 0; i < src->field_count; ++i)
-		field_names_size += strlen(src->fields[i].name) + 1;
-	size_t size = space_def_sizeof(strlen(src->name), field_names_size,
-				       src->field_count, &names_offset,
-				       &fields_offset);
+	uint32_t strs_offset, fields_offset, def_ast_offset;
+	size_t size = space_def_sizeof(strlen(src->name), src->fields,
+				       src->field_count, &strs_offset,
+				       &fields_offset, &def_ast_offset);
 	struct space_def *ret = (struct space_def *) malloc(size);
 	if (ret == NULL) {
 		diag_set(OutOfMemory, size, "malloc", "ret");
@@ -92,12 +105,25 @@ space_def_dup(const struct space_def *src)
 			return NULL;
 		}
 	}
-	char *name_pos = (char *)ret + names_offset;
+	char *strs_pos = (char *)ret + strs_offset;
+	char *expr_pos = (char *)ret + def_ast_offset;
 	if (src->field_count > 0) {
 		ret->fields = (struct field_def *)((char *)ret + fields_offset);
 		for (uint32_t i = 0; i < src->field_count; ++i) {
-			ret->fields[i].name = name_pos;
-			name_pos += strlen(name_pos) + 1;
+			ret->fields[i].name = strs_pos;
+			strs_pos += strlen(strs_pos) + 1;
+			if (src->fields[i].default_value != NULL) {
+				ret->fields[i].default_value = strs_pos;
+				strs_pos += strlen(strs_pos) + 1;
+			}
+			struct Expr *def_expr_ast = src->fields[i].default_value_ast;
+			if (def_expr_ast != NULL) {
+				struct Expr *expr = NULL;
+				expr = sql_expr_dup(sql_get(), def_expr_ast,
+						    0, &expr_pos);
+				ret->fields[i].default_value_ast = expr;
+				expr_pos += sql_duped_expr_size(expr, 0);
+			}
 		}
 	}
 	tuple_dictionary_ref(ret->dict);
@@ -111,12 +137,10 @@ space_def_new(uint32_t id, uint32_t uid, uint32_t exact_field_count,
 	      const struct space_opts *opts, const struct field_def *fields,
 	      uint32_t field_count)
 {
-	uint32_t field_names_size = 0;
-	for (uint32_t i = 0; i < field_count; ++i)
-		field_names_size += strlen(fields[i].name) + 1;
-	uint32_t names_offset, fields_offset;
-	size_t size = space_def_sizeof(name_len, field_names_size, field_count,
-				       &names_offset, &fields_offset);
+	uint32_t strs_offset, fields_offset, def_ast_offset;
+	size_t size = space_def_sizeof(name_len, fields, field_count,
+				       &strs_offset, &fields_offset,
+				       &def_ast_offset);
 	struct space_def *def = (struct space_def *) malloc(size);
 	if (def == NULL) {
 		diag_set(OutOfMemory, size, "malloc", "def");
@@ -147,18 +171,35 @@ space_def_new(uint32_t id, uint32_t uid, uint32_t exact_field_count,
 		}
 	}
 	def->field_count = field_count;
-	if (field_count == 0) {
+	if (field_count == 0)
 		def->fields = NULL;
-	} else {
-		char *name_pos = (char *)def + names_offset;
+	else {
+		char *strs_pos = (char *)def + strs_offset;
+		char *expr_pos = (char *)def + def_ast_offset;
 		def->fields = (struct field_def *)((char *)def + fields_offset);
 		for (uint32_t i = 0; i < field_count; ++i) {
 			def->fields[i] = fields[i];
-			def->fields[i].name = name_pos;
+			def->fields[i].name = strs_pos;
 			uint32_t len = strlen(fields[i].name);
 			memcpy(def->fields[i].name, fields[i].name, len);
 			def->fields[i].name[len] = 0;
-			name_pos += len + 1;
+			strs_pos += len + 1;
+
+			if (fields[i].default_value != NULL) {
+				def->fields[i].default_value = strs_pos;
+				len = strlen(fields[i].default_value);
+				memcpy(def->fields[i].default_value, fields[i].default_value, len);
+				def->fields[i].default_value[len] = 0;
+				strs_pos += len + 1;
+			}
+			struct Expr *def_expr_ast = fields[i].default_value_ast;
+			if (def_expr_ast != NULL) {
+				struct Expr *expr = NULL;
+				expr = sql_expr_dup(sql_get(), def_expr_ast,
+						    0, &expr_pos);
+				def->fields[i].default_value_ast = expr;
+				expr_pos += sql_duped_expr_size(expr, 0);
+			}
 		}
 	}
 	return def;
@@ -217,3 +258,17 @@ space_def_check_compatibility(const struct space_def *old_def,
 	return 0;
 }
 
+void
+space_def_delete(struct space_def *def)
+{
+	space_opts_destroy(&def->opts);
+	tuple_dictionary_unref(def->dict);
+	for (uint32_t i = 0; i < def->field_count; ++i) {
+		if (def->fields[i].default_value_ast != NULL) {
+			sql_expr_free(sql_get(),
+				      def->fields[i].default_value_ast);
+		}
+	}
+	TRASH(def);
+	free(def);
+}
diff --git a/src/box/space_def.h b/src/box/space_def.h
index b8d0bf8..7722738 100644
--- a/src/box/space_def.h
+++ b/src/box/space_def.h
@@ -115,14 +115,8 @@ struct space_def {
  * Delete the space_def object.
  * @param def Def to delete.
  */
-static inline void
-space_def_delete(struct space_def *def)
-{
-	space_opts_destroy(&def->opts);
-	tuple_dictionary_unref(def->dict);
-	TRASH(def);
-	free(def);
-}
+void
+space_def_delete(struct space_def *def);
 
 /**
  * Duplicate space_def object.
diff --git a/src/box/sql.c b/src/box/sql.c
index 6d8ef9a..8606be6 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -56,7 +56,7 @@
 #include "xrow.h"
 #include "iproto_constants.h"
 
-static sqlite3 *db;
+static sqlite3 *db = 0;
 
 static const char nil_key[] = { 0x90 }; /* Empty MsgPack array. */
 
@@ -80,6 +80,27 @@ sql_init()
 }
 
 void
+sql_load_schema()
+{
+	int rc;
+	struct session *user_session = current_session();
+	int commit_internal = !(user_session->sql_flags
+				& SQLITE_InternChanges);
+
+	assert(db->init.busy == 0);
+	db->init.busy = 1;
+	db->pSchema = sqlite3SchemaCreate(db);
+	rc = sqlite3InitDatabase(db);
+	if (rc != SQLITE_OK) {
+		sqlite3SchemaClear(db);
+		panic("failed to initialize SQL subsystem");
+	}
+	db->init.busy = 0;
+	if (rc == SQLITE_OK && commit_internal)
+		sqlite3CommitInternalChanges();
+}
+
+void
 sql_free()
 {
 	sqlite3_close(db); db = NULL;
@@ -1546,11 +1567,17 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
 	for (i = 0; i < n; i++) {
 		const char *t;
 		struct coll *coll = NULL;
+		struct Expr *def = aCol[i].pDflt;
 		if (aCol[i].zColl != NULL &&
 		    strcasecmp(aCol[i].zColl, "binary") != 0) {
 			coll = sqlite3FindCollSeq(aCol[i].zColl);
 		}
-		p = enc->encode_map(p, coll ? 5 : 4);
+		int base_len = 4;
+		if (coll != NULL)
+			base_len += 1;
+		if (def != NULL)
+			base_len += 1;
+		p = enc->encode_map(p, base_len);
 		p = enc->encode_str(p, "name", 4);
 		p = enc->encode_str(p, aCol[i].zName, strlen(aCol[i].zName));
 		p = enc->encode_str(p, "type", 4);
@@ -1572,6 +1599,12 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
 			p = enc->encode_str(p, "collation", strlen("collation"));
 			p = enc->encode_uint(p, coll->id);
 		}
+		if (def != NULL) {
+		        assert((def->flags & EP_IntValue) == 0);
+			assert(def->u.zToken != NULL);
+			p = enc->encode_str(p, "default", strlen("default"));
+			p = enc->encode_str(p, def->u.zToken, strlen(def->u.zToken));
+		}
 	}
 	return (int)(p - base);
 }
@@ -1781,3 +1814,25 @@ tarantoolSqlGetMaxId(uint32_t space_id, uint32_t index_id, uint32_t fieldno,
 
 	return tuple_field_u64(tuple, fieldno, max_id);
 }
+
+/**
+ * Given space_id and field number, return default value
+ * for the field.
+ * @param space_id Space ID.
+ * @param fieldno Field index.
+ * @retval Pointer to AST corresponding to default value.
+ * Can be NULL if no DEFAULT specified or it is a view.
+ */
+struct Expr*
+space_get_column_default_expr(uint32_t space_id, uint32_t fieldno)
+{
+	struct space *space;
+	space = space_cache_find(space_id);
+	assert(space != NULL);
+	assert(space->def != NULL);
+	if (space->def->opts.is_view)
+		return NULL;
+	assert(space->def->field_count > fieldno);
+
+	return space->def->fields[fieldno].default_value_ast;
+}
diff --git a/src/box/sql.h b/src/box/sql.h
index 8a7c420..61c8617 100644
--- a/src/box/sql.h
+++ b/src/box/sql.h
@@ -31,6 +31,8 @@
  * SUCH DAMAGE.
  */
 
+#include <stdint.h>
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -39,6 +41,9 @@ void
 sql_init();
 
 void
+sql_load_schema();
+
+void
 sql_free();
 
 /*
@@ -55,6 +60,31 @@ sql_free();
 struct sqlite3 *
 sql_get();
 
+struct Expr;
+struct Parse;
+struct Select;
+
+int
+sql_compile_expr(struct sqlite3 *db,
+		 const char *expr,
+		 struct Expr **result,
+		 char **err);
+
+void
+sql_extract_select_expr(struct Parse *parser, struct Select *select);
+
+struct Expr*
+space_get_column_default_expr(uint32_t space_id, uint32_t fieldno);
+
+int
+sql_duped_expr_size(struct Expr *p, int flags);
+
+struct Expr *
+sql_expr_dup(struct sqlite3 *db, struct Expr *p, int flags, char **buffer);
+
+void
+sql_expr_free(struct sqlite3 *db, struct Expr *expr);
+
 #if defined(__cplusplus)
 } /* extern "C" { */
 #endif
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 05a7cc9..c3bd637 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -285,7 +285,7 @@ freeIndex(sqlite3 * db, Index * p)
 #ifndef SQLITE_OMIT_ANALYZE
 	sqlite3DeleteIndexSamples(db, p);
 #endif
-	sqlite3ExprDelete(db, p->pPartIdxWhere);
+	sql_expr_free(db, p->pPartIdxWhere);
 	sqlite3ExprListDelete(db, p->aColExpr);
 	sqlite3DbFree(db, p->zColAff);
 	sqlite3_free(p->aiRowEst);
@@ -365,7 +365,7 @@ sqlite3DeleteColumnNames(sqlite3 * db, Table * pTable)
 	if ((pCol = pTable->aCol) != 0) {
 		for (i = 0; i < pTable->nCol; i++, pCol++) {
 			sqlite3DbFree(db, pCol->zName);
-			sqlite3ExprDelete(db, pCol->pDflt);
+			sql_expr_free(db, pCol->pDflt);
 			sqlite3DbFree(db, pCol->zColl);
 		}
 		sqlite3DbFree(db, pTable->aCol);
@@ -892,7 +892,7 @@ sqlite3AddDefaultValue(Parse * pParse, ExprSpan * pSpan)
 			 * is required by pragma table_info.
 			 */
 			Expr x;
-			sqlite3ExprDelete(db, pCol->pDflt);
+			sql_expr_free(db, pCol->pDflt);
 			memset(&x, 0, sizeof(x));
 			x.op = TK_SPAN;
 			x.u.zToken = sqlite3DbStrNDup(db, (char *)pSpan->zStart,
@@ -904,7 +904,7 @@ sqlite3AddDefaultValue(Parse * pParse, ExprSpan * pSpan)
 			sqlite3DbFree(db, x.u.zToken);
 		}
 	}
-	sqlite3ExprDelete(db, pSpan->pExpr);
+	sql_expr_free(db, pSpan->pExpr);
 }
 
 
@@ -1018,9 +1018,7 @@ sqlite3AddCheckConstraint(Parse * pParse,	/* Parsing context */
 		}
 	} else
 #endif
-	{
-		sqlite3ExprDelete(pParse->db, pCheckExpr);
-	}
+		sql_expr_free(pParse->db, pCheckExpr);
 }
 
 /*
@@ -3268,7 +3266,7 @@ sqlite3CreateIndex(Parse * pParse,	/* All information about this parse */
  exit_create_index:
 	if (pIndex)
 		freeIndex(db, pIndex);
-	sqlite3ExprDelete(db, pPIWhere);
+	sql_expr_free(db, pPIWhere);
 	sqlite3ExprListDelete(db, pList);
 	sqlite3SrcListDelete(db, pTblName);
 	sqlite3DbFree(db, zName);
@@ -3734,7 +3732,7 @@ sqlite3SrcListDelete(sqlite3 * db, SrcList * pList)
 			sqlite3ExprListDelete(db, pItem->u1.pFuncArg);
 		sqlite3DeleteTable(db, pItem->pTab);
 		sqlite3SelectDelete(db, pItem->pSelect);
-		sqlite3ExprDelete(db, pItem->pOn);
+		sql_expr_free(db, pItem->pOn);
 		sqlite3IdListDelete(db, pItem->pUsing);
 	}
 	sqlite3DbFree(db, pList);
@@ -3790,7 +3788,7 @@ sqlite3SrcListAppendFromTerm(Parse * pParse,	/* Parsing context */
 
  append_from_error:
 	assert(p == 0);
-	sqlite3ExprDelete(db, pOn);
+	sql_expr_free(db, pOn);
 	sqlite3IdListDelete(db, pUsing);
 	sqlite3SelectDelete(db, pSubquery);
 	return 0;
diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
index 2e09d92..33bd29b 100644
--- a/src/box/sql/delete.c
+++ b/src/box/sql/delete.c
@@ -212,10 +212,10 @@ sqlite3LimitWhere(Parse * pParse,	/* The parser context */
 	return pInClause;
 
  limit_where_cleanup:
-	sqlite3ExprDelete(pParse->db, pWhere);
+	sql_expr_free(pParse->db, pWhere);
 	sqlite3ExprListDelete(pParse->db, pOrderBy);
-	sqlite3ExprDelete(pParse->db, pLimit);
-	sqlite3ExprDelete(pParse->db, pOffset);
+	sql_expr_free(pParse->db, pLimit);
+	sql_expr_free(pParse->db, pOffset);
 	return 0;
 }
 #endif				/* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) */
@@ -571,7 +571,7 @@ sqlite3DeleteFrom(Parse * pParse,	/* The parser context */
 
  delete_from_cleanup:
 	sqlite3SrcListDelete(db, pTabList);
-	sqlite3ExprDelete(db, pWhere);
+	sql_expr_free(db, pWhere);
 	sqlite3DbFree(db, aToOpen);
 	return;
 }
@@ -636,9 +636,9 @@ sqlite3DeleteByKey(Parse *pParse, char *zTab, const char **columns,
 	return;
 
  error:
-	sqlite3ExprDelete(pParse->db, where);
+	sql_expr_free(pParse->db, where);
 	for (int i = 0; i < nPairs; ++i)
-		sqlite3ExprDelete(pParse->db, values[i]);
+		sql_expr_free(pParse->db, values[i]);
 }
 
 /* Make sure "isView" and other macros defined above are undefined. Otherwise
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 89dcb23..093f99e 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -492,7 +492,7 @@ sqlite3ExprForVectorField(Parse * pParse,	/* Parsing context */
 		 * pLeft->iTable:   First in an array of register holding result, or 0
 		 *                  if the result is not yet computed.
 		 *
-		 * sqlite3ExprDelete() specifically skips the recursive delete of
+		 * sql_expr_free() specifically skips the recursive delete of
 		 * pLeft on TK_SELECT_COLUMN nodes.  But pRight is followed, so pVector
 		 * can be attached to pRight to cause this node to take ownership of
 		 * pVector.  Typically there will be multiple TK_SELECT_COLUMN nodes
@@ -935,8 +935,8 @@ sqlite3ExprAttachSubtrees(sqlite3 * db,
 {
 	if (pRoot == 0) {
 		assert(db->mallocFailed);
-		sqlite3ExprDelete(db, pLeft);
-		sqlite3ExprDelete(db, pRight);
+		sql_expr_free(db, pLeft);
+		sql_expr_free(db, pRight);
 	} else {
 		if (pRight) {
 			pRoot->pRight = pRight;
@@ -1052,8 +1052,8 @@ sqlite3ExprAnd(sqlite3 * db, Expr * pLeft, Expr * pRight)
 	} else if (pRight == 0) {
 		return pLeft;
 	} else if (exprAlwaysFalse(pLeft) || exprAlwaysFalse(pRight)) {
-		sqlite3ExprDelete(db, pLeft);
-		sqlite3ExprDelete(db, pRight);
+		sql_expr_free(db, pLeft);
+		sql_expr_free(db, pRight);
 		return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0],
 					0);
 	} else {
@@ -1189,7 +1189,7 @@ sqlite3ExprDeleteNN(sqlite3 * db, Expr * p)
 		assert(p->x.pList == 0 || p->pRight == 0);
 		if (p->pLeft && p->op != TK_SELECT_COLUMN)
 			sqlite3ExprDeleteNN(db, p->pLeft);
-		sqlite3ExprDelete(db, p->pRight);
+		sql_expr_free(db, p->pRight);
 		if (ExprHasProperty(p, EP_xIsSelect)) {
 			sqlite3SelectDelete(db, p->x.pSelect);
 		} else {
@@ -1203,11 +1203,16 @@ sqlite3ExprDeleteNN(sqlite3 * db, Expr * p)
 	}
 }
 
+/**
+ * Recursively free storage occupied by AST expr.
+ * @param db SQL handle.
+ * @param p Pointer to root node.
+ */
 void
-sqlite3ExprDelete(sqlite3 * db, Expr * p)
+sql_expr_free(sqlite3 *db, Expr *expr)
 {
-	if (p)
-		sqlite3ExprDeleteNN(db, p);
+	if (expr != NULL)
+		sqlite3ExprDeleteNN(db, expr);
 }
 
 /*
@@ -1298,7 +1303,7 @@ dupedExprNodeSize(Expr * p, int flags)
 	return ROUND8(nByte);
 }
 
-/*
+/**
  * Return the number of bytes required to create a duplicate of the
  * expression passed as the first argument. The second argument is a
  * mask containing EXPRDUP_XXX flags.
@@ -1310,49 +1315,56 @@ dupedExprNodeSize(Expr * p, int flags)
  * space to duplicate all Expr nodes in the tree formed by Expr.pLeft
  * and Expr.pRight variables (but not for any structures pointed to or
  * descended from the Expr.x.pList or Expr.x.pSelect variables).
+ * @param expr Root expression of AST.
+ * @param flags The only possible flag is REDUCED, 0 otherwise.
+ * @retval Size in bytes needed to duplicate AST and all private
+ * strings.
  */
-static int
-dupedExprSize(Expr * p, int flags)
+int
+sql_duped_expr_size(struct Expr *p, int flags)
 {
-	int nByte = 0;
-	if (p) {
-		nByte = dupedExprNodeSize(p, flags);
+	int size = 0;
+	if (p != NULL) {
+		size = dupedExprNodeSize(p, flags);
 		if (flags & EXPRDUP_REDUCE) {
-			nByte +=
-			    dupedExprSize(p->pLeft,
-					  flags) + dupedExprSize(p->pRight,
-								 flags);
+			size +=
+			    sql_duped_expr_size(p->pLeft, flags) +
+			    sql_duped_expr_size(p->pRight, flags);
 		}
 	}
-	return nByte;
+	return size;
 }
 
-/*
+/**
  * This function is similar to sqlite3ExprDup(), except that if pzBuffer
  * is not NULL then *pzBuffer is assumed to point to a buffer large enough
  * to store the copy of expression p, the copies of p->u.zToken
  * (if applicable), and the copies of the p->pLeft and p->pRight expressions,
  * if any. Before returning, *pzBuffer is set to the first byte past the
  * portion of the buffer copied into by this function.
+ * @param db SQL handle.
+ * @param p Root of expression's AST.
+ * @param dupFlags EXPRDUP_REDUCE or 0.
+ * @param pzBuffer If not NULL, then buffer to store duplicate.
  */
-static Expr *
-exprDup(sqlite3 * db, Expr * p, int dupFlags, u8 ** pzBuffer)
+struct Expr *
+sql_expr_dup(struct sqlite3 *db, struct Expr *p, int flags, char **buffer)
 {
 	Expr *pNew;		/* Value to return */
-	u8 *zAlloc;		/* Memory space from which to build Expr object */
-	u32 staticFlag;		/* EP_Static if space not obtained from malloc */
+	u32 staticFlag;         /* EP_Static if space not obtained from malloc */
+	char *zAlloc;		/* Memory space from which to build Expr object */
 
 	assert(db != 0);
 	assert(p);
-	assert(dupFlags == 0 || dupFlags == EXPRDUP_REDUCE);
-	assert(pzBuffer == 0 || dupFlags == EXPRDUP_REDUCE);
+	assert(flags == 0 || flags == EXPRDUP_REDUCE);
 
 	/* Figure out where to write the new Expr structure. */
-	if (pzBuffer) {
-		zAlloc = *pzBuffer;
+	if (buffer) {
+		zAlloc = *buffer;
 		staticFlag = EP_Static;
 	} else {
-		zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, dupFlags));
+		zAlloc = sqlite3DbMallocRawNN(db,
+					      sql_duped_expr_size(p, flags));
 		staticFlag = 0;
 	}
 	pNew = (Expr *) zAlloc;
@@ -1363,15 +1375,14 @@ exprDup(sqlite3 * db, Expr * p, int dupFlags, u8 ** pzBuffer)
 		 * EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed
 		 * by the copy of the p->u.zToken string (if any).
 		 */
-		const unsigned nStructSize = dupedExprStructSize(p, dupFlags);
+		const unsigned nStructSize = dupedExprStructSize(p, flags);
 		const int nNewSize = nStructSize & 0xfff;
 		int nToken;
-		if (!ExprHasProperty(p, EP_IntValue) && p->u.zToken) {
+		if (!ExprHasProperty(p, EP_IntValue) && p->u.zToken)
 			nToken = sqlite3Strlen30(p->u.zToken) + 1;
-		} else {
+		else
 			nToken = 0;
-		}
-		if (dupFlags) {
+		if (flags) {
 			assert(ExprHasProperty(p, EP_Reduced) == 0);
 			memcpy(zAlloc, p, nNewSize);
 		} else {
@@ -1401,29 +1412,28 @@ exprDup(sqlite3 * db, Expr * p, int dupFlags, u8 ** pzBuffer)
 			if (ExprHasProperty(p, EP_xIsSelect)) {
 				pNew->x.pSelect =
 				    sqlite3SelectDup(db, p->x.pSelect,
-						     dupFlags);
+						     flags);
 			} else {
 				pNew->x.pList =
 				    sqlite3ExprListDup(db, p->x.pList,
-						       dupFlags);
+						       flags);
 			}
 		}
 
 		/* Fill in pNew->pLeft and pNew->pRight. */
 		if (ExprHasProperty(pNew, EP_Reduced | EP_TokenOnly)) {
-			zAlloc += dupedExprNodeSize(p, dupFlags);
+			zAlloc += dupedExprNodeSize(p, flags);
 			if (!ExprHasProperty(pNew, EP_TokenOnly | EP_Leaf)) {
 				pNew->pLeft = p->pLeft ?
-				    exprDup(db, p->pLeft, EXPRDUP_REDUCE,
+				    sql_expr_dup(db, p->pLeft, EXPRDUP_REDUCE,
 					    &zAlloc) : 0;
 				pNew->pRight =
-				    p->pRight ? exprDup(db, p->pRight,
-							EXPRDUP_REDUCE,
-							&zAlloc) : 0;
-			}
-			if (pzBuffer) {
-				*pzBuffer = zAlloc;
+				    p->pRight ? sql_expr_dup(db, p->pRight,
+							     EXPRDUP_REDUCE,
+							     &zAlloc) : 0;
 			}
+			if (buffer)
+				*buffer = zAlloc;
 		} else {
 			if (!ExprHasProperty(p, EP_TokenOnly | EP_Leaf)) {
 				if (pNew->op == TK_SELECT_COLUMN) {
@@ -1496,7 +1506,7 @@ Expr *
 sqlite3ExprDup(sqlite3 * db, Expr * p, int flags)
 {
 	assert(flags == 0 || flags == EXPRDUP_REDUCE);
-	return p ? exprDup(db, p, flags, 0) : 0;
+	return p ? sql_expr_dup(db, p, flags, 0) : 0;
 }
 
 ExprList *
@@ -1726,7 +1736,7 @@ sqlite3ExprListAppend(Parse * pParse,	/* Parsing context */
 
  no_mem:
 	/* Avoid leaking memory if malloc has failed. */
-	sqlite3ExprDelete(db, pExpr);
+	sql_expr_free(db, pExpr);
 	sqlite3ExprListDelete(db, pList);
 	return 0;
 }
@@ -1802,7 +1812,7 @@ sqlite3ExprListAppendVector(Parse * pParse,	/* Parsing context */
 	}
 
  vector_append_error:
-	sqlite3ExprDelete(db, pExpr);
+	sql_expr_free(db, pExpr);
 	sqlite3IdListDelete(db, pColumns);
 	return pList;
 }
@@ -1908,7 +1918,7 @@ exprListDeleteNN(sqlite3 * db, ExprList * pList)
 	struct ExprList_item *pItem;
 	assert(pList->a != 0 || pList->nExpr == 0);
 	for (pItem = pList->a, i = 0; i < pList->nExpr; i++, pItem++) {
-		sqlite3ExprDelete(db, pItem->pExpr);
+		sql_expr_free(db, pItem->pExpr);
 		sqlite3DbFree(db, pItem->zName);
 		sqlite3DbFree(db, pItem->zSpan);
 	}
@@ -2991,7 +3001,7 @@ sqlite3CodeSubselect(Parse * pParse,	/* Parsing context */
 						  dest.iSDParm);
 				VdbeComment((v, "Init EXISTS result"));
 			}
-			sqlite3ExprDelete(pParse->db, pSel->pLimit);
+			sql_expr_free(pParse->db, pSel->pLimit);
 			pSel->pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER,
 							&sqlite3IntTokens[1],
 							0);
@@ -4597,7 +4607,7 @@ sqlite3ExprCodeCopy(Parse * pParse, Expr * pExpr, int target)
 	pExpr = sqlite3ExprDup(db, pExpr, 0);
 	if (!db->mallocFailed)
 		sqlite3ExprCode(pParse, pExpr, target);
-	sqlite3ExprDelete(db, pExpr);
+	sql_expr_free(db, pExpr);
 }
 
 /*
@@ -5157,7 +5167,7 @@ sqlite3ExprIfFalseDup(Parse * pParse, Expr * pExpr, int dest, int jumpIfNull)
 	if (db->mallocFailed == 0) {
 		sqlite3ExprIfFalse(pParse, pCopy, dest, jumpIfNull);
 	}
-	sqlite3ExprDelete(db, pCopy);
+	sql_expr_free(db, pCopy);
 }
 
 /*
diff --git a/src/box/sql/fkey.c b/src/box/sql/fkey.c
index 9286f4c..f79e59d 100644
--- a/src/box/sql/fkey.c
+++ b/src/box/sql/fkey.c
@@ -698,10 +698,9 @@ fkScanChildren(Parse * pParse,	/* Parse context */
 	}
 
 	/* Clean up the WHERE clause constructed above. */
-	sqlite3ExprDelete(db, pWhere);
-	if (iFkIfZero) {
+	sql_expr_free(db, pWhere);
+	if (iFkIfZero)
 		sqlite3VdbeJumpHere(v, iFkIfZero);
-	}
 }
 
 /*
@@ -737,10 +736,10 @@ fkTriggerDelete(sqlite3 * dbMem, Trigger * p)
 {
 	if (p) {
 		TriggerStep *pStep = p->step_list;
-		sqlite3ExprDelete(dbMem, pStep->pWhere);
+		sql_expr_free(dbMem, pStep->pWhere);
 		sqlite3ExprListDelete(dbMem, pStep->pExprList);
 		sqlite3SelectDelete(dbMem, pStep->pSelect);
-		sqlite3ExprDelete(dbMem, p->pWhen);
+		sql_expr_free(dbMem, p->pWhen);
 		sqlite3DbFree(dbMem, p);
 	}
 }
@@ -1424,8 +1423,8 @@ fkActionTrigger(Parse * pParse,	/* Parse context */
 		/* Re-enable the lookaside buffer, if it was disabled earlier. */
 		db->lookaside.bDisable--;
 
-		sqlite3ExprDelete(db, pWhere);
-		sqlite3ExprDelete(db, pWhen);
+		sql_expr_free(db, pWhere);
+		sql_expr_free(db, pWhen);
 		sqlite3ExprListDelete(db, pList);
 		sqlite3SelectDelete(db, pSelect);
 		if (db->mallocFailed == 1) {
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 42254dd..00e263a 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -33,8 +33,9 @@
  * This file contains C code routines that are called by the parser
  * to handle INSERT statements in SQLite.
  */
-#include "sqliteInt.h"
 #include "box/session.h"
+#include "sqliteInt.h"
+#include "tarantoolInt.h"
 
 /*
  * Generate code that will open pTab as cursor iCur.
@@ -340,6 +341,7 @@ sqlite3Insert(Parse * pParse,	/* Parser context */
 	int regTupleid;		/* registers holding insert tupleid */
 	int regData;		/* register holding first column to insert */
 	int *aRegIdx = 0;	/* One register allocated to each index */
+	uint32_t space_id = 0;
 
 #ifndef SQLITE_OMIT_TRIGGER
 	int isView;		/* True if attempting to insert into a view */
@@ -376,6 +378,8 @@ sqlite3Insert(Parse * pParse,	/* Parser context */
 		goto insert_cleanup;
 	}
 
+	space_id = SQLITE_PAGENO_TO_SPACEID(pTab->tnum);
+
 	/* Figure out if we have any triggers and if the table being
 	 * inserted into is a view
 	 */
@@ -674,10 +678,15 @@ sqlite3Insert(Parse * pParse,	/* Parser context */
 				if (i == pTab->iAutoIncPKey)
 					sqlite3VdbeAddOp2(v, OP_Integer, -1,
 							  regCols + i + 1);
-				else
+				else {
+					struct Expr *dflt = NULL;
+					dflt = space_get_column_default_expr(
+						space_id,
+						i);
 					sqlite3ExprCode(pParse,
-							pTab->aCol[i].pDflt,
+							dflt,
 							regCols + i + 1);
+				}
 			} else if (useTempTable) {
 				sqlite3VdbeAddOp3(v, OP_Column, srcTab, j,
 						  regCols + i + 1);
@@ -748,8 +757,12 @@ sqlite3Insert(Parse * pParse,	/* Parser context */
 							  iRegStore);
 					continue;
 				}
+				struct Expr *dflt = NULL;
+				dflt = space_get_column_default_expr(
+					space_id,
+					i);
 				sqlite3ExprCodeFactorable(pParse,
-							  pTab->aCol[i].pDflt,
+							  dflt,
 							  iRegStore);
 			} else if (useTempTable) {
 				if ((pTab->tabFlags & TF_Autoincrement)
@@ -1106,10 +1119,13 @@ sqlite3GenerateConstraintChecks(Parse * pParse,		/* The parser context */
 		} else if (onError == ON_CONFLICT_ACTION_DEFAULT) {
 			onError = ON_CONFLICT_ACTION_ABORT;
 		}
-		if (onError == ON_CONFLICT_ACTION_REPLACE
-		    && pTab->aCol[i].pDflt == 0) {
+		struct Expr *dflt = NULL;
+		dflt = space_get_column_default_expr(
+			SQLITE_PAGENO_TO_SPACEID(pTab->tnum),
+			i);
+		if (onError == ON_CONFLICT_ACTION_REPLACE && dflt == 0)
 			onError = ON_CONFLICT_ACTION_ABORT;
-		}
+
 		assert(onError == ON_CONFLICT_ACTION_ROLLBACK
 		       || onError == ON_CONFLICT_ACTION_ABORT
 		       || onError == ON_CONFLICT_ACTION_FAIL
@@ -1145,7 +1161,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse,		/* The parser context */
 				    sqlite3VdbeAddOp1(v, OP_NotNull,
 						      regNewData + 1 + i);
 				VdbeCoverage(v);
-				sqlite3ExprCode(pParse, pTab->aCol[i].pDflt,
+				sqlite3ExprCode(pParse, dflt,
 						regNewData + 1 + i);
 				sqlite3VdbeJumpHere(v, addr1);
 				break;
diff --git a/src/box/sql/main.c b/src/box/sql/main.c
index 1881e93..b77348c 100644
--- a/src/box/sql/main.c
+++ b/src/box/sql/main.c
@@ -2058,21 +2058,6 @@ sql_init_db(sqlite3 **out_db)
 	setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside,
 		       sqlite3GlobalConfig.nLookaside);
 
-	if (rc == SQLITE_OK) {
-		struct session *user_session = current_session();
-		int commit_internal = !(user_session->sql_flags
-					& SQLITE_InternChanges);
-
-		assert(db->init.busy == 0);
-		db->init.busy = 1;
-		db->pSchema = sqlite3SchemaCreate(db);
-		rc = sqlite3InitDatabase(db);
-		if (rc != SQLITE_OK)
-			sqlite3SchemaClear(db);
-		db->init.busy = 0;
-		if (rc == SQLITE_OK && commit_internal)
-			sqlite3CommitInternalChanges();
-	}
 opendb_out:
 	rc = sqlite3_errcode(db);
 	assert(db != 0 || rc == SQLITE_NOMEM);
diff --git a/src/box/sql/parse.c b/src/box/sql/parse.c
index 17ce309..155da3d 100644
--- a/src/box/sql/parse.c
+++ b/src/box/sql/parse.c
@@ -81,7 +81,7 @@ static void disableLookaside(Parse *pParse){
   pParse->db->lookaside.bDisable++;
 }
 
-#line 392 "parse.y"
+#line 398 "parse.y"
 
   /*
   ** For a compound SELECT statement, make sure p->pPrior->pNext==p for
@@ -104,7 +104,7 @@ static void disableLookaside(Parse *pParse){
       }
     }
   }
-#line 831 "parse.y"
+#line 837 "parse.y"
 
   /* This is a utility routine used to set the ExprSpan.zStart and
   ** ExprSpan.zEnd values of pOut so that the span covers the complete
@@ -140,7 +140,7 @@ static void disableLookaside(Parse *pParse){
     pOut->zStart = t.z;
     pOut->zEnd = &t.z[t.n];
   }
-#line 939 "parse.y"
+#line 945 "parse.y"
 
   /* This routine constructs a binary expression node out of two ExprSpan
   ** objects and uses the result to populate a new ExprSpan object.
@@ -163,7 +163,7 @@ static void disableLookaside(Parse *pParse){
       pSpan->pExpr = sqlite3PExpr(pParse, TK_NOT, pSpan->pExpr, 0);
     }
   }
-#line 1013 "parse.y"
+#line 1019 "parse.y"
 
   /* Construct an expression node for a unary postfix operator
   */
@@ -176,7 +176,7 @@ static void disableLookaside(Parse *pParse){
     pOperand->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0);
     pOperand->zEnd = &pPostOp->z[pPostOp->n];
   }                           
-#line 1030 "parse.y"
+#line 1036 "parse.y"
 
   /* A routine to convert a binary TK_IS or TK_ISNOT expression into a
   ** unary TK_ISNULL or TK_NOTNULL expression. */
@@ -184,11 +184,11 @@ static void disableLookaside(Parse *pParse){
     sqlite3 *db = pParse->db;
     if( pA && pY && pY->op==TK_NULL ){
       pA->op = (u8)op;
-      sqlite3ExprDelete(db, pA->pRight);
+      sql_expr_free(db, pA->pRight);
       pA->pRight = 0;
     }
   }
-#line 1058 "parse.y"
+#line 1064 "parse.y"
 
   /* Construct an expression node for a unary prefix operator
   */
@@ -203,7 +203,7 @@ static void disableLookaside(Parse *pParse){
     pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0);
     pOut->zEnd = pOperand->zEnd;
   }
-#line 1263 "parse.y"
+#line 1269 "parse.y"
 
   /* Add a single new term to an ExprList that is used to store a
   ** list of identifiers.  Report an error if the ID list contains
@@ -1468,7 +1468,7 @@ static void yy_destructor(
     case 183: /* oneselect */
     case 194: /* values */
 {
-#line 386 "parse.y"
+#line 392 "parse.y"
 sqlite3SelectDelete(pParse->db, (yypminor->yy279));
 #line 1474 "parse.c"
 }
@@ -1476,8 +1476,8 @@ sqlite3SelectDelete(pParse->db, (yypminor->yy279));
     case 160: /* term */
     case 161: /* expr */
 {
-#line 829 "parse.y"
-sqlite3ExprDelete(pParse->db, (yypminor->yy162).pExpr);
+#line 835 "parse.y"
+sql_expr_free(pParse->db, (yypminor->yy162).pExpr);
 #line 1482 "parse.c"
 }
       break;
@@ -1494,7 +1494,7 @@ sqlite3ExprDelete(pParse->db, (yypminor->yy162).pExpr);
     case 213: /* paren_exprlist */
     case 215: /* case_exprlist */
 {
-#line 1261 "parse.y"
+#line 1267 "parse.y"
 sqlite3ExprListDelete(pParse->db, (yypminor->yy382));
 #line 1500 "parse.c"
 }
@@ -1504,7 +1504,7 @@ sqlite3ExprListDelete(pParse->db, (yypminor->yy382));
     case 199: /* seltablist */
     case 200: /* stl_prefix */
 {
-#line 613 "parse.y"
+#line 619 "parse.y"
 sqlite3SrcListDelete(pParse->db, (yypminor->yy387));
 #line 1510 "parse.c"
 }
@@ -1512,7 +1512,7 @@ sqlite3SrcListDelete(pParse->db, (yypminor->yy387));
     case 184: /* with */
     case 229: /* wqlist */
 {
-#line 1511 "parse.y"
+#line 1517 "parse.y"
 sqlite3WithDelete(pParse->db, (yypminor->yy151));
 #line 1518 "parse.c"
 }
@@ -1524,8 +1524,8 @@ sqlite3WithDelete(pParse->db, (yypminor->yy151));
     case 216: /* case_else */
     case 225: /* when_clause */
 {
-#line 738 "parse.y"
-sqlite3ExprDelete(pParse->db, (yypminor->yy362));
+#line 744 "parse.y"
+sql_expr_free(pParse->db, (yypminor->yy362));
 #line 1530 "parse.c"
 }
       break;
@@ -1533,7 +1533,7 @@ sqlite3ExprDelete(pParse->db, (yypminor->yy362));
     case 206: /* idlist */
     case 209: /* idlist_opt */
 {
-#line 650 "parse.y"
+#line 656 "parse.y"
 sqlite3IdListDelete(pParse->db, (yypminor->yy40));
 #line 1539 "parse.c"
 }
@@ -1541,14 +1541,14 @@ sqlite3IdListDelete(pParse->db, (yypminor->yy40));
     case 221: /* trigger_cmd_list */
     case 226: /* trigger_cmd */
 {
-#line 1385 "parse.y"
+#line 1391 "parse.y"
 sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy427));
 #line 1547 "parse.c"
 }
       break;
     case 223: /* trigger_event */
 {
-#line 1371 "parse.y"
+#line 1377 "parse.y"
 sqlite3IdListDelete(pParse->db, (yypminor->yy10).b);
 #line 1554 "parse.c"
 }
@@ -2164,84 +2164,87 @@ static void yy_reduce(
         YYMINORTYPE yylhsminor;
       case 0: /* ecmd ::= explain cmdx SEMI */
 #line 111 "parse.y"
-{ sqlite3FinishCoding(pParse); }
-#line 2169 "parse.c"
+{
+	if (!pParse->parse_only)
+		sqlite3FinishCoding(pParse);
+}
+#line 2172 "parse.c"
         break;
       case 1: /* ecmd ::= SEMI */
-#line 112 "parse.y"
+#line 115 "parse.y"
 {
   sqlite3ErrorMsg(pParse, "syntax error: empty request");
 }
-#line 2176 "parse.c"
+#line 2179 "parse.c"
         break;
       case 2: /* explain ::= EXPLAIN */
-#line 117 "parse.y"
+#line 120 "parse.y"
 { pParse->explain = 1; }
-#line 2181 "parse.c"
+#line 2184 "parse.c"
         break;
       case 3: /* explain ::= EXPLAIN QUERY PLAN */
-#line 118 "parse.y"
+#line 121 "parse.y"
 { pParse->explain = 2; }
-#line 2186 "parse.c"
+#line 2189 "parse.c"
         break;
       case 4: /* cmd ::= BEGIN transtype trans_opt */
-#line 150 "parse.y"
+#line 153 "parse.y"
 {sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy52);}
-#line 2191 "parse.c"
+#line 2194 "parse.c"
         break;
       case 5: /* transtype ::= */
-#line 155 "parse.y"
+#line 158 "parse.y"
 {yymsp[1].minor.yy52 = TK_DEFERRED;}
-#line 2196 "parse.c"
+#line 2199 "parse.c"
         break;
       case 6: /* transtype ::= DEFERRED */
-#line 156 "parse.y"
+#line 159 "parse.y"
 {yymsp[0].minor.yy52 = yymsp[0].major; /*A-overwrites-X*/}
-#line 2201 "parse.c"
+#line 2204 "parse.c"
         break;
       case 7: /* cmd ::= COMMIT trans_opt */
       case 8: /* cmd ::= END trans_opt */ yytestcase(yyruleno==8);
-#line 157 "parse.y"
+#line 160 "parse.y"
 {sqlite3CommitTransaction(pParse);}
-#line 2207 "parse.c"
+#line 2210 "parse.c"
         break;
       case 9: /* cmd ::= ROLLBACK trans_opt */
-#line 159 "parse.y"
+#line 162 "parse.y"
 {sqlite3RollbackTransaction(pParse);}
-#line 2212 "parse.c"
+#line 2215 "parse.c"
         break;
       case 10: /* cmd ::= SAVEPOINT nm */
-#line 163 "parse.y"
+#line 166 "parse.y"
 {
   sqlite3Savepoint(pParse, SAVEPOINT_BEGIN, &yymsp[0].minor.yy0);
 }
-#line 2219 "parse.c"
+#line 2222 "parse.c"
         break;
       case 11: /* cmd ::= RELEASE savepoint_opt nm */
-#line 166 "parse.y"
+#line 169 "parse.y"
 {
   sqlite3Savepoint(pParse, SAVEPOINT_RELEASE, &yymsp[0].minor.yy0);
 }
-#line 2226 "parse.c"
+#line 2229 "parse.c"
         break;
       case 12: /* cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
-#line 169 "parse.y"
+#line 172 "parse.y"
 {
   sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &yymsp[0].minor.yy0);
 }
-#line 2233 "parse.c"
+#line 2236 "parse.c"
         break;
       case 13: /* create_table ::= createkw TABLE ifnotexists nm */
-#line 176 "parse.y"
+#line 179 "parse.y"
 {
    sqlite3StartTable(pParse,&yymsp[0].minor.yy0,yymsp[-1].minor.yy52);
 }
-#line 2240 "parse.c"
+#line 2243 "parse.c"
         break;
       case 14: /* createkw ::= CREATE */
-#line 179 "parse.y"
+#line 182 "parse.y"
 {disableLookaside(pParse);}
-#line 2245 "parse.c"
+#line 2248 "parse.c"
         break;
       case 15: /* ifnotexists ::= */
       case 38: /* autoinc ::= */ yytestcase(yyruleno==38);
@@ -2250,89 +2253,89 @@ static void yy_reduce(
       case 72: /* ifexists ::= */ yytestcase(yyruleno==72);
       case 86: /* distinct ::= */ yytestcase(yyruleno==86);
       case 208: /* collate ::= */ yytestcase(yyruleno==208);
-#line 182 "parse.y"
+#line 185 "parse.y"
 {yymsp[1].minor.yy52 = 0;}
-#line 2256 "parse.c"
+#line 2259 "parse.c"
         break;
       case 16: /* ifnotexists ::= IF NOT EXISTS */
-#line 183 "parse.y"
+#line 186 "parse.y"
 {yymsp[-2].minor.yy52 = 1;}
-#line 2261 "parse.c"
+#line 2264 "parse.c"
         break;
       case 17: /* create_table_args ::= LP columnlist conslist_opt RP */
-#line 185 "parse.y"
+#line 188 "parse.y"
 {
   sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0);
 }
-#line 2268 "parse.c"
+#line 2271 "parse.c"
         break;
       case 18: /* create_table_args ::= AS select */
-#line 188 "parse.y"
+#line 191 "parse.y"
 {
   sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy279);
   sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy279);
 }
-#line 2276 "parse.c"
+#line 2279 "parse.c"
         break;
       case 19: /* columnname ::= nm typetoken */
-#line 194 "parse.y"
+#line 197 "parse.y"
 {sqlite3AddColumn(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
-#line 2281 "parse.c"
+#line 2284 "parse.c"
         break;
       case 20: /* nm ::= ID|INDEXED */
-#line 225 "parse.y"
+#line 228 "parse.y"
 {
   if(yymsp[0].minor.yy0.isReserved) {
     sqlite3ErrorMsg(pParse, "keyword \"%T\" is reserved", &yymsp[0].minor.yy0);
   }
 }
-#line 2290 "parse.c"
+#line 2293 "parse.c"
         break;
       case 21: /* typetoken ::= */
       case 56: /* conslist_opt ::= */ yytestcase(yyruleno==56);
       case 92: /* as ::= */ yytestcase(yyruleno==92);
-#line 236 "parse.y"
+#line 239 "parse.y"
 {yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;}
-#line 2297 "parse.c"
+#line 2300 "parse.c"
         break;
       case 22: /* typetoken ::= typename LP signed RP */
-#line 238 "parse.y"
+#line 241 "parse.y"
 {
   yymsp[-3].minor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy0.z);
 }
-#line 2304 "parse.c"
+#line 2307 "parse.c"
         break;
       case 23: /* typetoken ::= typename LP signed COMMA signed RP */
-#line 241 "parse.y"
+#line 244 "parse.y"
 {
   yymsp[-5].minor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy0.z);
 }
-#line 2311 "parse.c"
+#line 2314 "parse.c"
         break;
       case 24: /* typename ::= typename ID|STRING */
-#line 246 "parse.y"
+#line 249 "parse.y"
 {yymsp[-1].minor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);}
-#line 2316 "parse.c"
+#line 2319 "parse.c"
         break;
       case 25: /* ccons ::= CONSTRAINT nm */
       case 58: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==58);
-#line 255 "parse.y"
+#line 258 "parse.y"
 {pParse->constraintName = yymsp[0].minor.yy0;}
-#line 2322 "parse.c"
+#line 2325 "parse.c"
         break;
       case 26: /* ccons ::= DEFAULT term */
       case 28: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==28);
-#line 256 "parse.y"
+#line 259 "parse.y"
 {sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy162);}
-#line 2328 "parse.c"
+#line 2331 "parse.c"
         break;
       case 27: /* ccons ::= DEFAULT LP expr RP */
-#line 257 "parse.y"
+#line 260 "parse.y"
 {sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy162);}
-#line 2333 "parse.c"
+#line 2336 "parse.c"
         break;
       case 29: /* ccons ::= DEFAULT MINUS term */
-#line 259 "parse.y"
+#line 262 "parse.y"
 {
   ExprSpan v;
   v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy162.pExpr, 0);
@@ -2340,222 +2343,225 @@ static void yy_reduce(
   v.zEnd = yymsp[0].minor.yy162.zEnd;
   sqlite3AddDefaultValue(pParse,&v);
 }
-#line 2344 "parse.c"
+#line 2347 "parse.c"
         break;
       case 30: /* ccons ::= DEFAULT ID|INDEXED */
-#line 266 "parse.y"
+#line 269 "parse.y"
 {
   ExprSpan v;
   spanExpr(&v, pParse, TK_STRING, yymsp[0].minor.yy0);
   sqlite3AddDefaultValue(pParse,&v);
 }
-#line 2353 "parse.c"
+#line 2356 "parse.c"
         break;
       case 31: /* ccons ::= NOT NULL onconf */
-#line 276 "parse.y"
+#line 279 "parse.y"
 {sqlite3AddNotNull(pParse, yymsp[0].minor.yy52);}
-#line 2358 "parse.c"
+#line 2361 "parse.c"
         break;
       case 32: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
-#line 278 "parse.y"
+#line 281 "parse.y"
 {sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy52,yymsp[0].minor.yy52,yymsp[-2].minor.yy52);}
-#line 2363 "parse.c"
+#line 2366 "parse.c"
         break;
       case 33: /* ccons ::= UNIQUE onconf */
-#line 279 "parse.y"
+#line 282 "parse.y"
 {sqlite3CreateIndex(pParse,0,0,0,yymsp[0].minor.yy52,0,0,0,0,
                                    SQLITE_IDXTYPE_UNIQUE);}
-#line 2369 "parse.c"
+#line 2372 "parse.c"
         break;
       case 34: /* ccons ::= CHECK LP expr RP */
-#line 281 "parse.y"
+#line 284 "parse.y"
 {sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy162.pExpr);}
-#line 2374 "parse.c"
+#line 2377 "parse.c"
         break;
       case 35: /* ccons ::= REFERENCES nm eidlist_opt refargs */
-#line 283 "parse.y"
+#line 286 "parse.y"
 {sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy382,yymsp[0].minor.yy52);}
-#line 2379 "parse.c"
+#line 2382 "parse.c"
         break;
       case 36: /* ccons ::= defer_subclause */
-#line 284 "parse.y"
+#line 287 "parse.y"
 {sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy52);}
-#line 2384 "parse.c"
+#line 2387 "parse.c"
         break;
       case 37: /* ccons ::= COLLATE ID|INDEXED */
-#line 285 "parse.y"
+#line 288 "parse.y"
 {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
-#line 2389 "parse.c"
+#line 2392 "parse.c"
         break;
       case 39: /* autoinc ::= AUTOINCR */
-#line 290 "parse.y"
+#line 293 "parse.y"
 {yymsp[0].minor.yy52 = 1;}
-#line 2394 "parse.c"
+#line 2397 "parse.c"
         break;
       case 40: /* refargs ::= */
-#line 298 "parse.y"
+#line 301 "parse.y"
 { yymsp[1].minor.yy52 = ON_CONFLICT_ACTION_NONE*0x0101; /* EV: R-19803-45884 */}
-#line 2399 "parse.c"
+#line 2402 "parse.c"
         break;
       case 41: /* refargs ::= refargs refarg */
-#line 299 "parse.y"
+#line 302 "parse.y"
 { yymsp[-1].minor.yy52 = (yymsp[-1].minor.yy52 & ~yymsp[0].minor.yy107.mask) | yymsp[0].minor.yy107.value; }
-#line 2404 "parse.c"
+#line 2407 "parse.c"
         break;
       case 42: /* refarg ::= MATCH nm */
-#line 301 "parse.y"
+#line 304 "parse.y"
 { yymsp[-1].minor.yy107.value = 0;     yymsp[-1].minor.yy107.mask = 0x000000; }
-#line 2409 "parse.c"
+#line 2412 "parse.c"
         break;
       case 43: /* refarg ::= ON INSERT refact */
-#line 302 "parse.y"
+#line 305 "parse.y"
 { yymsp[-2].minor.yy107.value = 0;     yymsp[-2].minor.yy107.mask = 0x000000; }
-#line 2414 "parse.c"
+#line 2417 "parse.c"
         break;
       case 44: /* refarg ::= ON DELETE refact */
-#line 303 "parse.y"
+#line 306 "parse.y"
 { yymsp[-2].minor.yy107.value = yymsp[0].minor.yy52;     yymsp[-2].minor.yy107.mask = 0x0000ff; }
-#line 2419 "parse.c"
+#line 2422 "parse.c"
         break;
       case 45: /* refarg ::= ON UPDATE refact */
-#line 304 "parse.y"
+#line 307 "parse.y"
 { yymsp[-2].minor.yy107.value = yymsp[0].minor.yy52<<8;  yymsp[-2].minor.yy107.mask = 0x00ff00; }
-#line 2424 "parse.c"
+#line 2427 "parse.c"
         break;
       case 46: /* refact ::= SET NULL */
-#line 306 "parse.y"
+#line 309 "parse.y"
 { yymsp[-1].minor.yy52 = OE_SetNull;  /* EV: R-33326-45252 */}
-#line 2429 "parse.c"
+#line 2432 "parse.c"
         break;
       case 47: /* refact ::= SET DEFAULT */
-#line 307 "parse.y"
+#line 310 "parse.y"
 { yymsp[-1].minor.yy52 = OE_SetDflt;  /* EV: R-33326-45252 */}
-#line 2434 "parse.c"
+#line 2437 "parse.c"
         break;
       case 48: /* refact ::= CASCADE */
-#line 308 "parse.y"
+#line 311 "parse.y"
 { yymsp[0].minor.yy52 = OE_Cascade;  /* EV: R-33326-45252 */}
-#line 2439 "parse.c"
+#line 2442 "parse.c"
         break;
       case 49: /* refact ::= RESTRICT */
-#line 309 "parse.y"
+#line 312 "parse.y"
 { yymsp[0].minor.yy52 = OE_Restrict; /* EV: R-33326-45252 */}
-#line 2444 "parse.c"
+#line 2447 "parse.c"
         break;
       case 50: /* refact ::= NO ACTION */
-#line 310 "parse.y"
+#line 313 "parse.y"
 { yymsp[-1].minor.yy52 = ON_CONFLICT_ACTION_NONE;     /* EV: R-33326-45252 */}
-#line 2449 "parse.c"
+#line 2452 "parse.c"
         break;
       case 51: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
-#line 312 "parse.y"
+#line 315 "parse.y"
 {yymsp[-2].minor.yy52 = 0;}
-#line 2454 "parse.c"
+#line 2457 "parse.c"
         break;
       case 52: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
       case 67: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==67);
       case 138: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==138);
-#line 313 "parse.y"
+#line 316 "parse.y"
 {yymsp[-1].minor.yy52 = yymsp[0].minor.yy52;}
-#line 2461 "parse.c"
+#line 2464 "parse.c"
         break;
       case 54: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
       case 71: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==71);
       case 180: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==180);
       case 183: /* in_op ::= NOT IN */ yytestcase(yyruleno==183);
       case 209: /* collate ::= COLLATE ID|INDEXED */ yytestcase(yyruleno==209);
-#line 316 "parse.y"
+#line 319 "parse.y"
 {yymsp[-1].minor.yy52 = 1;}
-#line 2470 "parse.c"
+#line 2473 "parse.c"
         break;
       case 55: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
-#line 317 "parse.y"
+#line 320 "parse.y"
 {yymsp[-1].minor.yy52 = 0;}
-#line 2475 "parse.c"
+#line 2478 "parse.c"
         break;
       case 57: /* tconscomma ::= COMMA */
-#line 323 "parse.y"
+#line 326 "parse.y"
 {pParse->constraintName.n = 0;}
-#line 2480 "parse.c"
+#line 2483 "parse.c"
         break;
       case 59: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
-#line 327 "parse.y"
+#line 330 "parse.y"
 {sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy382,yymsp[0].minor.yy52,yymsp[-2].minor.yy52,0);}
-#line 2485 "parse.c"
+#line 2488 "parse.c"
         break;
       case 60: /* tcons ::= UNIQUE LP sortlist RP onconf */
-#line 329 "parse.y"
+#line 332 "parse.y"
 {sqlite3CreateIndex(pParse,0,0,yymsp[-2].minor.yy382,yymsp[0].minor.yy52,0,0,0,0,
                                        SQLITE_IDXTYPE_UNIQUE);}
-#line 2491 "parse.c"
+#line 2494 "parse.c"
         break;
       case 61: /* tcons ::= CHECK LP expr RP onconf */
-#line 332 "parse.y"
+#line 335 "parse.y"
 {sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy162.pExpr);}
-#line 2496 "parse.c"
+#line 2499 "parse.c"
         break;
       case 62: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
-#line 334 "parse.y"
+#line 337 "parse.y"
 {
     sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy382, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy382, yymsp[-1].minor.yy52);
     sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy52);
 }
-#line 2504 "parse.c"
+#line 2507 "parse.c"
         break;
       case 64: /* onconf ::= */
       case 66: /* orconf ::= */ yytestcase(yyruleno==66);
-#line 348 "parse.y"
+#line 351 "parse.y"
 {yymsp[1].minor.yy52 = ON_CONFLICT_ACTION_DEFAULT;}
-#line 2510 "parse.c"
+#line 2513 "parse.c"
         break;
       case 65: /* onconf ::= ON CONFLICT resolvetype */
-#line 349 "parse.y"
+#line 352 "parse.y"
 {yymsp[-2].minor.yy52 = yymsp[0].minor.yy52;}
-#line 2515 "parse.c"
+#line 2518 "parse.c"
         break;
       case 68: /* resolvetype ::= IGNORE */
-#line 353 "parse.y"
+#line 356 "parse.y"
 {yymsp[0].minor.yy52 = ON_CONFLICT_ACTION_IGNORE;}
-#line 2520 "parse.c"
+#line 2523 "parse.c"
         break;
       case 69: /* resolvetype ::= REPLACE */
       case 139: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==139);
-#line 354 "parse.y"
+#line 357 "parse.y"
 {yymsp[0].minor.yy52 = ON_CONFLICT_ACTION_REPLACE;}
-#line 2526 "parse.c"
+#line 2529 "parse.c"
         break;
       case 70: /* cmd ::= DROP TABLE ifexists fullname */
-#line 358 "parse.y"
+#line 361 "parse.y"
 {
   sqlite3DropTable(pParse, yymsp[0].minor.yy387, 0, yymsp[-1].minor.yy52);
 }
-#line 2533 "parse.c"
+#line 2536 "parse.c"
         break;
       case 73: /* cmd ::= createkw VIEW ifnotexists nm eidlist_opt AS select */
-#line 369 "parse.y"
+#line 372 "parse.y"
 {
   sqlite3CreateView(pParse, &yymsp[-6].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy382, yymsp[0].minor.yy279, yymsp[-4].minor.yy52);
 }
-#line 2540 "parse.c"
+#line 2543 "parse.c"
         break;
       case 74: /* cmd ::= DROP VIEW ifexists fullname */
-#line 372 "parse.y"
+#line 375 "parse.y"
 {
   sqlite3DropTable(pParse, yymsp[0].minor.yy387, 1, yymsp[-1].minor.yy52);
 }
-#line 2547 "parse.c"
+#line 2550 "parse.c"
         break;
       case 75: /* cmd ::= select */
-#line 379 "parse.y"
+#line 382 "parse.y"
 {
   SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
-  sqlite3Select(pParse, yymsp[0].minor.yy279, &dest);
+  if(!pParse->parse_only)
+	  sqlite3Select(pParse, yymsp[0].minor.yy279, &dest);
+  else
+	  sql_extract_select_expr(pParse, yymsp[0].minor.yy279);
   sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy279);
 }
-#line 2556 "parse.c"
+#line 2562 "parse.c"
         break;
       case 76: /* select ::= with selectnowith */
-#line 416 "parse.y"
+#line 422 "parse.y"
 {
   Select *p = yymsp[0].minor.yy279;
   if( p ){
@@ -2566,10 +2572,10 @@ static void yy_reduce(
   }
   yymsp[-1].minor.yy279 = p; /*A-overwrites-W*/
 }
-#line 2570 "parse.c"
+#line 2576 "parse.c"
         break;
       case 77: /* selectnowith ::= selectnowith multiselect_op oneselect */
-#line 429 "parse.y"
+#line 435 "parse.y"
 {
   Select *pRhs = yymsp[0].minor.yy279;
   Select *pLhs = yymsp[-2].minor.yy279;
@@ -2592,21 +2598,21 @@ static void yy_reduce(
   }
   yymsp[-2].minor.yy279 = pRhs;
 }
-#line 2596 "parse.c"
+#line 2602 "parse.c"
         break;
       case 78: /* multiselect_op ::= UNION */
       case 80: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==80);
-#line 452 "parse.y"
+#line 458 "parse.y"
 {yymsp[0].minor.yy52 = yymsp[0].major; /*A-overwrites-OP*/}
-#line 2602 "parse.c"
+#line 2608 "parse.c"
         break;
       case 79: /* multiselect_op ::= UNION ALL */
-#line 453 "parse.y"
+#line 459 "parse.y"
 {yymsp[-1].minor.yy52 = TK_ALL;}
-#line 2607 "parse.c"
+#line 2613 "parse.c"
         break;
       case 81: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
-#line 457 "parse.y"
+#line 463 "parse.y"
 {
 #ifdef SELECTTRACE_ENABLED
   Token s = yymsp[-8].minor.yy0; /*A-overwrites-S*/
@@ -2637,17 +2643,17 @@ static void yy_reduce(
   }
 #endif /* SELECTRACE_ENABLED */
 }
-#line 2641 "parse.c"
+#line 2647 "parse.c"
         break;
       case 82: /* values ::= VALUES LP nexprlist RP */
-#line 491 "parse.y"
+#line 497 "parse.y"
 {
   yymsp[-3].minor.yy279 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy382,0,0,0,0,0,SF_Values,0,0);
 }
-#line 2648 "parse.c"
+#line 2654 "parse.c"
         break;
       case 83: /* values ::= values COMMA LP exprlist RP */
-#line 494 "parse.y"
+#line 500 "parse.y"
 {
   Select *pRight, *pLeft = yymsp[-4].minor.yy279;
   pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy382,0,0,0,0,0,SF_Values|SF_MultiValue,0,0);
@@ -2660,17 +2666,17 @@ static void yy_reduce(
     yymsp[-4].minor.yy279 = pLeft;
   }
 }
-#line 2664 "parse.c"
+#line 2670 "parse.c"
         break;
       case 84: /* distinct ::= DISTINCT */
-#line 511 "parse.y"
+#line 517 "parse.y"
 {yymsp[0].minor.yy52 = SF_Distinct;}
-#line 2669 "parse.c"
+#line 2675 "parse.c"
         break;
       case 85: /* distinct ::= ALL */
-#line 512 "parse.y"
+#line 518 "parse.y"
 {yymsp[0].minor.yy52 = SF_All;}
-#line 2674 "parse.c"
+#line 2680 "parse.c"
         break;
       case 87: /* sclp ::= */
       case 113: /* orderby_opt ::= */ yytestcase(yyruleno==113);
@@ -2678,94 +2684,94 @@ static void yy_reduce(
       case 196: /* exprlist ::= */ yytestcase(yyruleno==196);
       case 199: /* paren_exprlist ::= */ yytestcase(yyruleno==199);
       case 204: /* eidlist_opt ::= */ yytestcase(yyruleno==204);
-#line 525 "parse.y"
+#line 531 "parse.y"
 {yymsp[1].minor.yy382 = 0;}
-#line 2684 "parse.c"
+#line 2690 "parse.c"
         break;
       case 88: /* selcollist ::= sclp expr as */
-#line 526 "parse.y"
+#line 532 "parse.y"
 {
    yymsp[-2].minor.yy382 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy382, yymsp[-1].minor.yy162.pExpr);
    if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-2].minor.yy382, &yymsp[0].minor.yy0, 1);
    sqlite3ExprListSetSpan(pParse,yymsp[-2].minor.yy382,&yymsp[-1].minor.yy162);
 }
-#line 2693 "parse.c"
+#line 2699 "parse.c"
         break;
       case 89: /* selcollist ::= sclp STAR */
-#line 531 "parse.y"
+#line 537 "parse.y"
 {
   Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0);
   yymsp[-1].minor.yy382 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy382, p);
 }
-#line 2701 "parse.c"
+#line 2707 "parse.c"
         break;
       case 90: /* selcollist ::= sclp nm DOT STAR */
-#line 535 "parse.y"
+#line 541 "parse.y"
 {
   Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0);
   Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
   Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
   yymsp[-3].minor.yy382 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy382, pDot);
 }
-#line 2711 "parse.c"
+#line 2717 "parse.c"
         break;
       case 91: /* as ::= AS nm */
       case 218: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==218);
       case 219: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==219);
-#line 546 "parse.y"
+#line 552 "parse.y"
 {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;}
-#line 2718 "parse.c"
+#line 2724 "parse.c"
         break;
       case 93: /* from ::= */
-#line 560 "parse.y"
+#line 566 "parse.y"
 {yymsp[1].minor.yy387 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy387));}
-#line 2723 "parse.c"
+#line 2729 "parse.c"
         break;
       case 94: /* from ::= FROM seltablist */
-#line 561 "parse.y"
+#line 567 "parse.y"
 {
   yymsp[-1].minor.yy387 = yymsp[0].minor.yy387;
   sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy387);
 }
-#line 2731 "parse.c"
+#line 2737 "parse.c"
         break;
       case 95: /* stl_prefix ::= seltablist joinop */
-#line 569 "parse.y"
+#line 575 "parse.y"
 {
    if( ALWAYS(yymsp[-1].minor.yy387 && yymsp[-1].minor.yy387->nSrc>0) ) yymsp[-1].minor.yy387->a[yymsp[-1].minor.yy387->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy52;
 }
-#line 2738 "parse.c"
+#line 2744 "parse.c"
         break;
       case 96: /* stl_prefix ::= */
-#line 572 "parse.y"
+#line 578 "parse.y"
 {yymsp[1].minor.yy387 = 0;}
-#line 2743 "parse.c"
+#line 2749 "parse.c"
         break;
       case 97: /* seltablist ::= stl_prefix nm as indexed_opt on_opt using_opt */
-#line 574 "parse.y"
+#line 580 "parse.y"
 {
   yymsp[-5].minor.yy387 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy387,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy362,yymsp[0].minor.yy40);
   sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy387, &yymsp[-2].minor.yy0);
 }
-#line 2751 "parse.c"
+#line 2757 "parse.c"
         break;
       case 98: /* seltablist ::= stl_prefix nm LP exprlist RP as on_opt using_opt */
-#line 579 "parse.y"
+#line 585 "parse.y"
 {
   yymsp[-7].minor.yy387 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-7].minor.yy387,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy362,yymsp[0].minor.yy40);
   sqlite3SrcListFuncArgs(pParse, yymsp[-7].minor.yy387, yymsp[-4].minor.yy382);
 }
-#line 2759 "parse.c"
+#line 2765 "parse.c"
         break;
       case 99: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
-#line 585 "parse.y"
+#line 591 "parse.y"
 {
     yymsp[-6].minor.yy387 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy387,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy279,yymsp[-1].minor.yy362,yymsp[0].minor.yy40);
   }
-#line 2766 "parse.c"
+#line 2772 "parse.c"
         break;
       case 100: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
-#line 589 "parse.y"
+#line 595 "parse.y"
 {
     if( yymsp[-6].minor.yy387==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy362==0 && yymsp[0].minor.yy40==0 ){
       yymsp[-6].minor.yy387 = yymsp[-4].minor.yy387;
@@ -2787,135 +2793,135 @@ static void yy_reduce(
       yymsp[-6].minor.yy387 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy387,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy362,yymsp[0].minor.yy40);
     }
   }
-#line 2791 "parse.c"
+#line 2797 "parse.c"
         break;
       case 101: /* fullname ::= nm */
-#line 615 "parse.y"
+#line 621 "parse.y"
 {yymsp[0].minor.yy387 = sqlite3SrcListAppend(pParse->db,0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
-#line 2796 "parse.c"
+#line 2802 "parse.c"
         break;
       case 102: /* joinop ::= COMMA|JOIN */
-#line 621 "parse.y"
+#line 627 "parse.y"
 { yymsp[0].minor.yy52 = JT_INNER; }
-#line 2801 "parse.c"
+#line 2807 "parse.c"
         break;
       case 103: /* joinop ::= JOIN_KW JOIN */
-#line 623 "parse.y"
+#line 629 "parse.y"
 {yymsp[-1].minor.yy52 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0);  /*X-overwrites-A*/}
-#line 2806 "parse.c"
+#line 2812 "parse.c"
         break;
       case 104: /* joinop ::= JOIN_KW join_nm JOIN */
-#line 625 "parse.y"
+#line 631 "parse.y"
 {yymsp[-2].minor.yy52 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
-#line 2811 "parse.c"
+#line 2817 "parse.c"
         break;
       case 105: /* joinop ::= JOIN_KW join_nm join_nm JOIN */
-#line 627 "parse.y"
+#line 633 "parse.y"
 {yymsp[-3].minor.yy52 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
-#line 2816 "parse.c"
+#line 2822 "parse.c"
         break;
       case 106: /* on_opt ::= ON expr */
       case 123: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==123);
       case 130: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==130);
       case 192: /* case_else ::= ELSE expr */ yytestcase(yyruleno==192);
-#line 631 "parse.y"
+#line 637 "parse.y"
 {yymsp[-1].minor.yy362 = yymsp[0].minor.yy162.pExpr;}
-#line 2824 "parse.c"
+#line 2830 "parse.c"
         break;
       case 107: /* on_opt ::= */
       case 122: /* having_opt ::= */ yytestcase(yyruleno==122);
       case 129: /* where_opt ::= */ yytestcase(yyruleno==129);
       case 193: /* case_else ::= */ yytestcase(yyruleno==193);
       case 195: /* case_operand ::= */ yytestcase(yyruleno==195);
-#line 632 "parse.y"
+#line 638 "parse.y"
 {yymsp[1].minor.yy362 = 0;}
-#line 2833 "parse.c"
+#line 2839 "parse.c"
         break;
       case 108: /* indexed_opt ::= */
-#line 645 "parse.y"
+#line 651 "parse.y"
 {yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;}
-#line 2838 "parse.c"
+#line 2844 "parse.c"
         break;
       case 109: /* indexed_opt ::= INDEXED BY nm */
-#line 646 "parse.y"
+#line 652 "parse.y"
 {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;}
-#line 2843 "parse.c"
+#line 2849 "parse.c"
         break;
       case 110: /* indexed_opt ::= NOT INDEXED */
-#line 647 "parse.y"
+#line 653 "parse.y"
 {yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;}
-#line 2848 "parse.c"
+#line 2854 "parse.c"
         break;
       case 111: /* using_opt ::= USING LP idlist RP */
-#line 651 "parse.y"
+#line 657 "parse.y"
 {yymsp[-3].minor.yy40 = yymsp[-1].minor.yy40;}
-#line 2853 "parse.c"
+#line 2859 "parse.c"
         break;
       case 112: /* using_opt ::= */
       case 140: /* idlist_opt ::= */ yytestcase(yyruleno==140);
-#line 652 "parse.y"
+#line 658 "parse.y"
 {yymsp[1].minor.yy40 = 0;}
-#line 2859 "parse.c"
+#line 2865 "parse.c"
         break;
       case 114: /* orderby_opt ::= ORDER BY sortlist */
       case 121: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==121);
-#line 666 "parse.y"
+#line 672 "parse.y"
 {yymsp[-2].minor.yy382 = yymsp[0].minor.yy382;}
-#line 2865 "parse.c"
+#line 2871 "parse.c"
         break;
       case 115: /* sortlist ::= sortlist COMMA expr sortorder */
-#line 667 "parse.y"
+#line 673 "parse.y"
 {
   yymsp[-3].minor.yy382 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy382,yymsp[-1].minor.yy162.pExpr);
   sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy382,yymsp[0].minor.yy52);
 }
-#line 2873 "parse.c"
+#line 2879 "parse.c"
         break;
       case 116: /* sortlist ::= expr sortorder */
-#line 671 "parse.y"
+#line 677 "parse.y"
 {
   yymsp[-1].minor.yy382 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy162.pExpr); /*A-overwrites-Y*/
   sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy382,yymsp[0].minor.yy52);
 }
-#line 2881 "parse.c"
+#line 2887 "parse.c"
         break;
       case 117: /* sortorder ::= ASC */
-#line 678 "parse.y"
+#line 684 "parse.y"
 {yymsp[0].minor.yy52 = SQLITE_SO_ASC;}
-#line 2886 "parse.c"
+#line 2892 "parse.c"
         break;
       case 118: /* sortorder ::= DESC */
-#line 679 "parse.y"
+#line 685 "parse.y"
 {yymsp[0].minor.yy52 = SQLITE_SO_DESC;}
-#line 2891 "parse.c"
+#line 2897 "parse.c"
         break;
       case 119: /* sortorder ::= */
-#line 680 "parse.y"
+#line 686 "parse.y"
 {yymsp[1].minor.yy52 = SQLITE_SO_UNDEFINED;}
-#line 2896 "parse.c"
+#line 2902 "parse.c"
         break;
       case 124: /* limit_opt ::= */
-#line 705 "parse.y"
+#line 711 "parse.y"
 {yymsp[1].minor.yy384.pLimit = 0; yymsp[1].minor.yy384.pOffset = 0;}
-#line 2901 "parse.c"
+#line 2907 "parse.c"
         break;
       case 125: /* limit_opt ::= LIMIT expr */
-#line 706 "parse.y"
+#line 712 "parse.y"
 {yymsp[-1].minor.yy384.pLimit = yymsp[0].minor.yy162.pExpr; yymsp[-1].minor.yy384.pOffset = 0;}
-#line 2906 "parse.c"
+#line 2912 "parse.c"
         break;
       case 126: /* limit_opt ::= LIMIT expr OFFSET expr */
-#line 708 "parse.y"
+#line 714 "parse.y"
 {yymsp[-3].minor.yy384.pLimit = yymsp[-2].minor.yy162.pExpr; yymsp[-3].minor.yy384.pOffset = yymsp[0].minor.yy162.pExpr;}
-#line 2911 "parse.c"
+#line 2917 "parse.c"
         break;
       case 127: /* limit_opt ::= LIMIT expr COMMA expr */
-#line 710 "parse.y"
+#line 716 "parse.y"
 {yymsp[-3].minor.yy384.pOffset = yymsp[-2].minor.yy162.pExpr; yymsp[-3].minor.yy384.pLimit = yymsp[0].minor.yy162.pExpr;}
-#line 2916 "parse.c"
+#line 2922 "parse.c"
         break;
       case 128: /* cmd ::= with DELETE FROM fullname indexed_opt where_opt */
-#line 727 "parse.y"
+#line 733 "parse.y"
 {
   sqlite3WithPush(pParse, yymsp[-5].minor.yy151, 1);
   sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy387, &yymsp[-1].minor.yy0);
@@ -2924,10 +2930,10 @@ static void yy_reduce(
   pParse->initiateTTrans = true;
   sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy387,yymsp[0].minor.yy362);
 }
-#line 2928 "parse.c"
+#line 2934 "parse.c"
         break;
       case 131: /* cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */
-#line 760 "parse.y"
+#line 766 "parse.y"
 {
   sqlite3WithPush(pParse, yymsp[-7].minor.yy151, 1);
   sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy387, &yymsp[-3].minor.yy0);
@@ -2937,41 +2943,41 @@ static void yy_reduce(
   pParse->initiateTTrans = true;
   sqlite3Update(pParse,yymsp[-4].minor.yy387,yymsp[-1].minor.yy382,yymsp[0].minor.yy362,yymsp[-5].minor.yy52);
 }
-#line 2941 "parse.c"
+#line 2947 "parse.c"
         break;
       case 132: /* setlist ::= setlist COMMA nm EQ expr */
-#line 774 "parse.y"
+#line 780 "parse.y"
 {
   yymsp[-4].minor.yy382 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy382, yymsp[0].minor.yy162.pExpr);
   sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy382, &yymsp[-2].minor.yy0, 1);
 }
-#line 2949 "parse.c"
+#line 2955 "parse.c"
         break;
       case 133: /* setlist ::= setlist COMMA LP idlist RP EQ expr */
-#line 778 "parse.y"
+#line 784 "parse.y"
 {
   yymsp[-6].minor.yy382 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy382, yymsp[-3].minor.yy40, yymsp[0].minor.yy162.pExpr);
 }
-#line 2956 "parse.c"
+#line 2962 "parse.c"
         break;
       case 134: /* setlist ::= nm EQ expr */
-#line 781 "parse.y"
+#line 787 "parse.y"
 {
   yylhsminor.yy382 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy162.pExpr);
   sqlite3ExprListSetName(pParse, yylhsminor.yy382, &yymsp[-2].minor.yy0, 1);
 }
-#line 2964 "parse.c"
+#line 2970 "parse.c"
   yymsp[-2].minor.yy382 = yylhsminor.yy382;
         break;
       case 135: /* setlist ::= LP idlist RP EQ expr */
-#line 785 "parse.y"
+#line 791 "parse.y"
 {
   yymsp[-4].minor.yy382 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy40, yymsp[0].minor.yy162.pExpr);
 }
-#line 2972 "parse.c"
+#line 2978 "parse.c"
         break;
       case 136: /* cmd ::= with insert_cmd INTO fullname idlist_opt select */
-#line 791 "parse.y"
+#line 797 "parse.y"
 {
   sqlite3WithPush(pParse, yymsp[-5].minor.yy151, 1);
   sqlSubProgramsRemaining = SQL_MAX_COMPILING_TRIGGERS;
@@ -2979,10 +2985,10 @@ static void yy_reduce(
   pParse->initiateTTrans = true;
   sqlite3Insert(pParse, yymsp[-2].minor.yy387, yymsp[0].minor.yy279, yymsp[-1].minor.yy40, yymsp[-4].minor.yy52);
 }
-#line 2983 "parse.c"
+#line 2989 "parse.c"
         break;
       case 137: /* cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */
-#line 799 "parse.y"
+#line 805 "parse.y"
 {
   sqlite3WithPush(pParse, yymsp[-6].minor.yy151, 1);
   sqlSubProgramsRemaining = SQL_MAX_COMPILING_TRIGGERS;
@@ -2990,64 +2996,64 @@ static void yy_reduce(
   pParse->initiateTTrans = true;
   sqlite3Insert(pParse, yymsp[-3].minor.yy387, 0, yymsp[-2].minor.yy40, yymsp[-5].minor.yy52);
 }
-#line 2994 "parse.c"
+#line 3000 "parse.c"
         break;
       case 141: /* idlist_opt ::= LP idlist RP */
-#line 817 "parse.y"
+#line 823 "parse.y"
 {yymsp[-2].minor.yy40 = yymsp[-1].minor.yy40;}
-#line 2999 "parse.c"
+#line 3005 "parse.c"
         break;
       case 142: /* idlist ::= idlist COMMA nm */
-#line 819 "parse.y"
+#line 825 "parse.y"
 {yymsp[-2].minor.yy40 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy40,&yymsp[0].minor.yy0);}
-#line 3004 "parse.c"
+#line 3010 "parse.c"
         break;
       case 143: /* idlist ::= nm */
-#line 821 "parse.y"
+#line 827 "parse.y"
 {yymsp[0].minor.yy40 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
-#line 3009 "parse.c"
+#line 3015 "parse.c"
         break;
       case 144: /* expr ::= LP expr RP */
-#line 870 "parse.y"
+#line 876 "parse.y"
 {spanSet(&yymsp[-2].minor.yy162,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/  yymsp[-2].minor.yy162.pExpr = yymsp[-1].minor.yy162.pExpr;}
-#line 3014 "parse.c"
+#line 3020 "parse.c"
         break;
       case 145: /* term ::= NULL */
       case 149: /* term ::= FLOAT|BLOB */ yytestcase(yyruleno==149);
       case 150: /* term ::= STRING */ yytestcase(yyruleno==150);
-#line 871 "parse.y"
+#line 877 "parse.y"
 {spanExpr(&yymsp[0].minor.yy162,pParse,yymsp[0].major,yymsp[0].minor.yy0);/*A-overwrites-X*/}
-#line 3021 "parse.c"
+#line 3027 "parse.c"
         break;
       case 146: /* expr ::= ID|INDEXED */
       case 147: /* expr ::= JOIN_KW */ yytestcase(yyruleno==147);
-#line 872 "parse.y"
+#line 878 "parse.y"
 {spanExpr(&yymsp[0].minor.yy162,pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
-#line 3027 "parse.c"
+#line 3033 "parse.c"
         break;
       case 148: /* expr ::= nm DOT nm */
-#line 874 "parse.y"
+#line 880 "parse.y"
 {
   Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
   Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1);
   spanSet(&yymsp[-2].minor.yy162,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/
   yymsp[-2].minor.yy162.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
 }
-#line 3037 "parse.c"
+#line 3043 "parse.c"
         break;
       case 151: /* term ::= INTEGER */
-#line 882 "parse.y"
+#line 888 "parse.y"
 {
   yylhsminor.yy162.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1);
   yylhsminor.yy162.zStart = yymsp[0].minor.yy0.z;
   yylhsminor.yy162.zEnd = yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n;
   if( yylhsminor.yy162.pExpr ) yylhsminor.yy162.pExpr->flags |= EP_Leaf;
 }
-#line 3047 "parse.c"
+#line 3053 "parse.c"
   yymsp[0].minor.yy162 = yylhsminor.yy162;
         break;
       case 152: /* expr ::= VARIABLE */
-#line 888 "parse.y"
+#line 894 "parse.y"
 {
   if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){
     u32 n = yymsp[0].minor.yy0.n;
@@ -3069,27 +3075,27 @@ static void yy_reduce(
     }
   }
 }
-#line 3073 "parse.c"
+#line 3079 "parse.c"
         break;
       case 153: /* expr ::= expr COLLATE ID|INDEXED */
-#line 909 "parse.y"
+#line 915 "parse.y"
 {
   yymsp[-2].minor.yy162.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy162.pExpr, &yymsp[0].minor.yy0, 1);
   yymsp[-2].minor.yy162.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
 }
-#line 3081 "parse.c"
+#line 3087 "parse.c"
         break;
       case 154: /* expr ::= CAST LP expr AS typetoken RP */
-#line 914 "parse.y"
+#line 920 "parse.y"
 {
   spanSet(&yymsp[-5].minor.yy162,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/
   yymsp[-5].minor.yy162.pExpr = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
   sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy162.pExpr, yymsp[-3].minor.yy162.pExpr, 0);
 }
-#line 3090 "parse.c"
+#line 3096 "parse.c"
         break;
       case 155: /* expr ::= ID|INDEXED LP distinct exprlist RP */
-#line 920 "parse.y"
+#line 926 "parse.y"
 {
   if( yymsp[-1].minor.yy382 && yymsp[-1].minor.yy382->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
     sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
@@ -3100,29 +3106,29 @@ static void yy_reduce(
     yylhsminor.yy162.pExpr->flags |= EP_Distinct;
   }
 }
-#line 3104 "parse.c"
+#line 3110 "parse.c"
   yymsp[-4].minor.yy162 = yylhsminor.yy162;
         break;
       case 156: /* expr ::= ID|INDEXED LP STAR RP */
-#line 930 "parse.y"
+#line 936 "parse.y"
 {
   yylhsminor.yy162.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
   spanSet(&yylhsminor.yy162,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
 }
-#line 3113 "parse.c"
+#line 3119 "parse.c"
   yymsp[-3].minor.yy162 = yylhsminor.yy162;
         break;
       case 157: /* term ::= CTIME_KW */
-#line 934 "parse.y"
+#line 940 "parse.y"
 {
   yylhsminor.yy162.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0);
   spanSet(&yylhsminor.yy162, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
 }
-#line 3122 "parse.c"
+#line 3128 "parse.c"
   yymsp[0].minor.yy162 = yylhsminor.yy162;
         break;
       case 158: /* expr ::= LP nexprlist COMMA expr RP */
-#line 963 "parse.y"
+#line 969 "parse.y"
 {
   ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy382, yymsp[-1].minor.yy162.pExpr);
   yylhsminor.yy162.pExpr = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
@@ -3133,7 +3139,7 @@ static void yy_reduce(
     sqlite3ExprListDelete(pParse->db, pList);
   }
 }
-#line 3137 "parse.c"
+#line 3143 "parse.c"
   yymsp[-4].minor.yy162 = yylhsminor.yy162;
         break;
       case 159: /* expr ::= expr AND expr */
@@ -3144,22 +3150,22 @@ static void yy_reduce(
       case 164: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==164);
       case 165: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==165);
       case 166: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==166);
-#line 974 "parse.y"
+#line 980 "parse.y"
 {spanBinaryExpr(pParse,yymsp[-1].major,&yymsp[-2].minor.yy162,&yymsp[0].minor.yy162);}
-#line 3150 "parse.c"
+#line 3156 "parse.c"
         break;
       case 167: /* likeop ::= LIKE_KW|MATCH */
-#line 987 "parse.y"
+#line 993 "parse.y"
 {yymsp[0].minor.yy0=yymsp[0].minor.yy0;/*A-overwrites-X*/}
-#line 3155 "parse.c"
+#line 3161 "parse.c"
         break;
       case 168: /* likeop ::= NOT LIKE_KW|MATCH */
-#line 988 "parse.y"
+#line 994 "parse.y"
 {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/}
-#line 3160 "parse.c"
+#line 3166 "parse.c"
         break;
       case 169: /* expr ::= expr likeop expr */
-#line 989 "parse.y"
+#line 995 "parse.y"
 {
   ExprList *pList;
   int bNot = yymsp[-1].minor.yy0.n & 0x80000000;
@@ -3171,10 +3177,10 @@ static void yy_reduce(
   yymsp[-2].minor.yy162.zEnd = yymsp[0].minor.yy162.zEnd;
   if( yymsp[-2].minor.yy162.pExpr ) yymsp[-2].minor.yy162.pExpr->flags |= EP_InfixFunc;
 }
-#line 3175 "parse.c"
+#line 3181 "parse.c"
         break;
       case 170: /* expr ::= expr likeop expr ESCAPE expr */
-#line 1000 "parse.y"
+#line 1006 "parse.y"
 {
   ExprList *pList;
   int bNot = yymsp[-3].minor.yy0.n & 0x80000000;
@@ -3187,58 +3193,58 @@ static void yy_reduce(
   yymsp[-4].minor.yy162.zEnd = yymsp[0].minor.yy162.zEnd;
   if( yymsp[-4].minor.yy162.pExpr ) yymsp[-4].minor.yy162.pExpr->flags |= EP_InfixFunc;
 }
-#line 3191 "parse.c"
+#line 3197 "parse.c"
         break;
       case 171: /* expr ::= expr ISNULL|NOTNULL */
-#line 1027 "parse.y"
+#line 1033 "parse.y"
 {spanUnaryPostfix(pParse,yymsp[0].major,&yymsp[-1].minor.yy162,&yymsp[0].minor.yy0);}
-#line 3196 "parse.c"
+#line 3202 "parse.c"
         break;
       case 172: /* expr ::= expr NOT NULL */
-#line 1028 "parse.y"
+#line 1034 "parse.y"
 {spanUnaryPostfix(pParse,TK_NOTNULL,&yymsp[-2].minor.yy162,&yymsp[0].minor.yy0);}
-#line 3201 "parse.c"
+#line 3207 "parse.c"
         break;
       case 173: /* expr ::= expr IS expr */
-#line 1049 "parse.y"
+#line 1055 "parse.y"
 {
   spanBinaryExpr(pParse,TK_IS,&yymsp[-2].minor.yy162,&yymsp[0].minor.yy162);
   binaryToUnaryIfNull(pParse, yymsp[0].minor.yy162.pExpr, yymsp[-2].minor.yy162.pExpr, TK_ISNULL);
 }
-#line 3209 "parse.c"
+#line 3215 "parse.c"
         break;
       case 174: /* expr ::= expr IS NOT expr */
-#line 1053 "parse.y"
+#line 1059 "parse.y"
 {
   spanBinaryExpr(pParse,TK_ISNOT,&yymsp[-3].minor.yy162,&yymsp[0].minor.yy162);
   binaryToUnaryIfNull(pParse, yymsp[0].minor.yy162.pExpr, yymsp[-3].minor.yy162.pExpr, TK_NOTNULL);
 }
-#line 3217 "parse.c"
+#line 3223 "parse.c"
         break;
       case 175: /* expr ::= NOT expr */
       case 176: /* expr ::= BITNOT expr */ yytestcase(yyruleno==176);
-#line 1077 "parse.y"
+#line 1083 "parse.y"
 {spanUnaryPrefix(&yymsp[-1].minor.yy162,pParse,yymsp[-1].major,&yymsp[0].minor.yy162,&yymsp[-1].minor.yy0);/*A-overwrites-B*/}
-#line 3223 "parse.c"
+#line 3229 "parse.c"
         break;
       case 177: /* expr ::= MINUS expr */
-#line 1081 "parse.y"
+#line 1087 "parse.y"
 {spanUnaryPrefix(&yymsp[-1].minor.yy162,pParse,TK_UMINUS,&yymsp[0].minor.yy162,&yymsp[-1].minor.yy0);/*A-overwrites-B*/}
-#line 3228 "parse.c"
+#line 3234 "parse.c"
         break;
       case 178: /* expr ::= PLUS expr */
-#line 1083 "parse.y"
+#line 1089 "parse.y"
 {spanUnaryPrefix(&yymsp[-1].minor.yy162,pParse,TK_UPLUS,&yymsp[0].minor.yy162,&yymsp[-1].minor.yy0);/*A-overwrites-B*/}
-#line 3233 "parse.c"
+#line 3239 "parse.c"
         break;
       case 179: /* between_op ::= BETWEEN */
       case 182: /* in_op ::= IN */ yytestcase(yyruleno==182);
-#line 1086 "parse.y"
+#line 1092 "parse.y"
 {yymsp[0].minor.yy52 = 0;}
-#line 3239 "parse.c"
+#line 3245 "parse.c"
         break;
       case 181: /* expr ::= expr between_op expr AND expr */
-#line 1088 "parse.y"
+#line 1094 "parse.y"
 {
   ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy162.pExpr);
   pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy162.pExpr);
@@ -3251,10 +3257,10 @@ static void yy_reduce(
   exprNot(pParse, yymsp[-3].minor.yy52, &yymsp[-4].minor.yy162);
   yymsp[-4].minor.yy162.zEnd = yymsp[0].minor.yy162.zEnd;
 }
-#line 3255 "parse.c"
+#line 3261 "parse.c"
         break;
       case 184: /* expr ::= expr in_op LP exprlist RP */
-#line 1104 "parse.y"
+#line 1110 "parse.y"
 {
     if( yymsp[-1].minor.yy382==0 ){
       /* Expressions of the form
@@ -3265,7 +3271,7 @@ static void yy_reduce(
       ** simplify to constants 0 (false) and 1 (true), respectively,
       ** regardless of the value of expr1.
       */
-      sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy162.pExpr);
+      sql_expr_free(pParse->db, yymsp[-4].minor.yy162.pExpr);
       yymsp[-4].minor.yy162.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[yymsp[-3].minor.yy52],1);
     }else if( yymsp[-1].minor.yy382->nExpr==1 ){
       /* Expressions of the form:
@@ -3306,29 +3312,29 @@ static void yy_reduce(
     }
     yymsp[-4].minor.yy162.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
   }
-#line 3310 "parse.c"
+#line 3316 "parse.c"
         break;
       case 185: /* expr ::= LP select RP */
-#line 1155 "parse.y"
+#line 1161 "parse.y"
 {
     spanSet(&yymsp[-2].minor.yy162,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/
     yymsp[-2].minor.yy162.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
     sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy162.pExpr, yymsp[-1].minor.yy279);
   }
-#line 3319 "parse.c"
+#line 3325 "parse.c"
         break;
       case 186: /* expr ::= expr in_op LP select RP */
-#line 1160 "parse.y"
+#line 1166 "parse.y"
 {
     yymsp[-4].minor.yy162.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy162.pExpr, 0);
     sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy162.pExpr, yymsp[-1].minor.yy279);
     exprNot(pParse, yymsp[-3].minor.yy52, &yymsp[-4].minor.yy162);
     yymsp[-4].minor.yy162.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
   }
-#line 3329 "parse.c"
+#line 3335 "parse.c"
         break;
       case 187: /* expr ::= expr in_op nm paren_exprlist */
-#line 1166 "parse.y"
+#line 1172 "parse.y"
 {
     SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0);
     Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
@@ -3338,20 +3344,20 @@ static void yy_reduce(
     exprNot(pParse, yymsp[-2].minor.yy52, &yymsp[-3].minor.yy162);
     yymsp[-3].minor.yy162.zEnd = &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n];
   }
-#line 3342 "parse.c"
+#line 3348 "parse.c"
         break;
       case 188: /* expr ::= EXISTS LP select RP */
-#line 1175 "parse.y"
+#line 1181 "parse.y"
 {
     Expr *p;
     spanSet(&yymsp[-3].minor.yy162,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/
     p = yymsp[-3].minor.yy162.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
     sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy279);
   }
-#line 3352 "parse.c"
+#line 3358 "parse.c"
         break;
       case 189: /* expr ::= CASE case_operand case_exprlist case_else END */
-#line 1184 "parse.y"
+#line 1190 "parse.y"
 {
   spanSet(&yymsp[-4].minor.yy162,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);  /*A-overwrites-C*/
   yymsp[-4].minor.yy162.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy362, 0);
@@ -3360,140 +3366,140 @@ static void yy_reduce(
     sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy162.pExpr);
   }else{
     sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy382);
-    sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy362);
+    sql_expr_free(pParse->db, yymsp[-1].minor.yy362);
   }
 }
-#line 3367 "parse.c"
+#line 3373 "parse.c"
         break;
       case 190: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
-#line 1197 "parse.y"
+#line 1203 "parse.y"
 {
   yymsp[-4].minor.yy382 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy382, yymsp[-2].minor.yy162.pExpr);
   yymsp[-4].minor.yy382 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy382, yymsp[0].minor.yy162.pExpr);
 }
-#line 3375 "parse.c"
+#line 3381 "parse.c"
         break;
       case 191: /* case_exprlist ::= WHEN expr THEN expr */
-#line 1201 "parse.y"
+#line 1207 "parse.y"
 {
   yymsp[-3].minor.yy382 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy162.pExpr);
   yymsp[-3].minor.yy382 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy382, yymsp[0].minor.yy162.pExpr);
 }
-#line 3383 "parse.c"
+#line 3389 "parse.c"
         break;
       case 194: /* case_operand ::= expr */
-#line 1211 "parse.y"
+#line 1217 "parse.y"
 {yymsp[0].minor.yy362 = yymsp[0].minor.yy162.pExpr; /*A-overwrites-X*/}
-#line 3388 "parse.c"
+#line 3394 "parse.c"
         break;
       case 197: /* nexprlist ::= nexprlist COMMA expr */
-#line 1222 "parse.y"
+#line 1228 "parse.y"
 {yymsp[-2].minor.yy382 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy382,yymsp[0].minor.yy162.pExpr);}
-#line 3393 "parse.c"
+#line 3399 "parse.c"
         break;
       case 198: /* nexprlist ::= expr */
-#line 1224 "parse.y"
+#line 1230 "parse.y"
 {yymsp[0].minor.yy382 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy162.pExpr); /*A-overwrites-Y*/}
-#line 3398 "parse.c"
+#line 3404 "parse.c"
         break;
       case 200: /* paren_exprlist ::= LP exprlist RP */
       case 205: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==205);
-#line 1232 "parse.y"
+#line 1238 "parse.y"
 {yymsp[-2].minor.yy382 = yymsp[-1].minor.yy382;}
-#line 3404 "parse.c"
+#line 3410 "parse.c"
         break;
       case 201: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm ON nm LP sortlist RP where_opt */
-#line 1239 "parse.y"
+#line 1245 "parse.y"
 {
   sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, 
                      sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0), yymsp[-2].minor.yy382, yymsp[-9].minor.yy52,
                       &yymsp[-10].minor.yy0, yymsp[0].minor.yy362, SQLITE_SO_ASC, yymsp[-7].minor.yy52, SQLITE_IDXTYPE_APPDEF);
 }
-#line 3413 "parse.c"
+#line 3419 "parse.c"
         break;
       case 202: /* uniqueflag ::= UNIQUE */
       case 243: /* raisetype ::= ABORT */ yytestcase(yyruleno==243);
-#line 1246 "parse.y"
+#line 1252 "parse.y"
 {yymsp[0].minor.yy52 = ON_CONFLICT_ACTION_ABORT;}
-#line 3419 "parse.c"
+#line 3425 "parse.c"
         break;
       case 203: /* uniqueflag ::= */
-#line 1247 "parse.y"
+#line 1253 "parse.y"
 {yymsp[1].minor.yy52 = ON_CONFLICT_ACTION_NONE;}
-#line 3424 "parse.c"
+#line 3430 "parse.c"
         break;
       case 206: /* eidlist ::= eidlist COMMA nm collate sortorder */
-#line 1290 "parse.y"
+#line 1296 "parse.y"
 {
   yymsp[-4].minor.yy382 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy382, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy52, yymsp[0].minor.yy52);
 }
-#line 3431 "parse.c"
+#line 3437 "parse.c"
         break;
       case 207: /* eidlist ::= nm collate sortorder */
-#line 1293 "parse.y"
+#line 1299 "parse.y"
 {
   yymsp[-2].minor.yy382 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy52, yymsp[0].minor.yy52); /*A-overwrites-Y*/
 }
-#line 3438 "parse.c"
+#line 3444 "parse.c"
         break;
       case 210: /* cmd ::= DROP INDEX ifexists fullname ON nm */
-#line 1304 "parse.y"
+#line 1310 "parse.y"
 {
     sqlite3DropIndex(pParse, yymsp[-2].minor.yy387, &yymsp[0].minor.yy0, yymsp[-3].minor.yy52);
 }
-#line 3445 "parse.c"
+#line 3451 "parse.c"
         break;
       case 211: /* cmd ::= PRAGMA nm */
-#line 1311 "parse.y"
+#line 1317 "parse.y"
 {
     sqlite3Pragma(pParse,&yymsp[0].minor.yy0,0,0,0,0);
 }
-#line 3452 "parse.c"
+#line 3458 "parse.c"
         break;
       case 212: /* cmd ::= PRAGMA nm EQ nmnum */
-#line 1314 "parse.y"
+#line 1320 "parse.y"
 {
     sqlite3Pragma(pParse,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy0,0,0);
 }
-#line 3459 "parse.c"
+#line 3465 "parse.c"
         break;
       case 213: /* cmd ::= PRAGMA nm LP nmnum RP */
-#line 1317 "parse.y"
+#line 1323 "parse.y"
 {
     sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,0,&yymsp[-1].minor.yy0,0,0);
 }
-#line 3466 "parse.c"
+#line 3472 "parse.c"
         break;
       case 214: /* cmd ::= PRAGMA nm EQ minus_num */
-#line 1320 "parse.y"
+#line 1326 "parse.y"
 {
     sqlite3Pragma(pParse,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy0,0,1);
 }
-#line 3473 "parse.c"
+#line 3479 "parse.c"
         break;
       case 215: /* cmd ::= PRAGMA nm LP minus_num RP */
-#line 1323 "parse.y"
+#line 1329 "parse.y"
 {
     sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,0,&yymsp[-1].minor.yy0,0,1);
 }
-#line 3480 "parse.c"
+#line 3486 "parse.c"
         break;
       case 216: /* cmd ::= PRAGMA nm EQ nm DOT nm */
-#line 1326 "parse.y"
+#line 1332 "parse.y"
 {
     sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,0,&yymsp[0].minor.yy0,&yymsp[-2].minor.yy0,0);
 }
-#line 3487 "parse.c"
+#line 3493 "parse.c"
         break;
       case 217: /* cmd ::= PRAGMA */
-#line 1329 "parse.y"
+#line 1335 "parse.y"
 {
     sqlite3Pragma(pParse, 0,0,0,0,0);
 }
-#line 3494 "parse.c"
+#line 3500 "parse.c"
         break;
       case 220: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
-#line 1349 "parse.y"
+#line 1355 "parse.y"
 {
   Token all;
   all.z = yymsp[-3].minor.yy0.z;
@@ -3501,124 +3507,124 @@ static void yy_reduce(
   pParse->initiateTTrans = false;
   sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy427, &all);
 }
-#line 3505 "parse.c"
+#line 3511 "parse.c"
         break;
       case 221: /* trigger_decl ::= TRIGGER ifnotexists nm trigger_time trigger_event ON fullname foreach_clause when_clause */
-#line 1359 "parse.y"
+#line 1365 "parse.y"
 {
   sqlite3BeginTrigger(pParse, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy52, yymsp[-4].minor.yy10.a, yymsp[-4].minor.yy10.b, yymsp[-2].minor.yy387, yymsp[0].minor.yy362, yymsp[-7].minor.yy52);
   yymsp[-8].minor.yy0 = yymsp[-6].minor.yy0; /*yymsp[-8].minor.yy0-overwrites-T*/
 }
-#line 3513 "parse.c"
+#line 3519 "parse.c"
         break;
       case 222: /* trigger_time ::= BEFORE */
-#line 1365 "parse.y"
+#line 1371 "parse.y"
 { yymsp[0].minor.yy52 = TK_BEFORE; }
-#line 3518 "parse.c"
+#line 3524 "parse.c"
         break;
       case 223: /* trigger_time ::= AFTER */
-#line 1366 "parse.y"
+#line 1372 "parse.y"
 { yymsp[0].minor.yy52 = TK_AFTER;  }
-#line 3523 "parse.c"
+#line 3529 "parse.c"
         break;
       case 224: /* trigger_time ::= INSTEAD OF */
-#line 1367 "parse.y"
+#line 1373 "parse.y"
 { yymsp[-1].minor.yy52 = TK_INSTEAD;}
-#line 3528 "parse.c"
+#line 3534 "parse.c"
         break;
       case 225: /* trigger_time ::= */
-#line 1368 "parse.y"
+#line 1374 "parse.y"
 { yymsp[1].minor.yy52 = TK_BEFORE; }
-#line 3533 "parse.c"
+#line 3539 "parse.c"
         break;
       case 226: /* trigger_event ::= DELETE|INSERT */
       case 227: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==227);
-#line 1372 "parse.y"
+#line 1378 "parse.y"
 {yymsp[0].minor.yy10.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy10.b = 0;}
-#line 3539 "parse.c"
+#line 3545 "parse.c"
         break;
       case 228: /* trigger_event ::= UPDATE OF idlist */
-#line 1374 "parse.y"
+#line 1380 "parse.y"
 {yymsp[-2].minor.yy10.a = TK_UPDATE; yymsp[-2].minor.yy10.b = yymsp[0].minor.yy40;}
-#line 3544 "parse.c"
+#line 3550 "parse.c"
         break;
       case 229: /* when_clause ::= */
-#line 1381 "parse.y"
+#line 1387 "parse.y"
 { yymsp[1].minor.yy362 = 0; }
-#line 3549 "parse.c"
+#line 3555 "parse.c"
         break;
       case 230: /* when_clause ::= WHEN expr */
-#line 1382 "parse.y"
+#line 1388 "parse.y"
 { yymsp[-1].minor.yy362 = yymsp[0].minor.yy162.pExpr; }
-#line 3554 "parse.c"
+#line 3560 "parse.c"
         break;
       case 231: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
-#line 1386 "parse.y"
+#line 1392 "parse.y"
 {
   assert( yymsp[-2].minor.yy427!=0 );
   yymsp[-2].minor.yy427->pLast->pNext = yymsp[-1].minor.yy427;
   yymsp[-2].minor.yy427->pLast = yymsp[-1].minor.yy427;
 }
-#line 3563 "parse.c"
+#line 3569 "parse.c"
         break;
       case 232: /* trigger_cmd_list ::= trigger_cmd SEMI */
-#line 1391 "parse.y"
+#line 1397 "parse.y"
 { 
   assert( yymsp[-1].minor.yy427!=0 );
   yymsp[-1].minor.yy427->pLast = yymsp[-1].minor.yy427;
 }
-#line 3571 "parse.c"
+#line 3577 "parse.c"
         break;
       case 233: /* trnm ::= nm DOT nm */
-#line 1402 "parse.y"
+#line 1408 "parse.y"
 {
   yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;
   sqlite3ErrorMsg(pParse, 
         "qualified table names are not allowed on INSERT, UPDATE, and DELETE "
         "statements within triggers");
 }
-#line 3581 "parse.c"
+#line 3587 "parse.c"
         break;
       case 234: /* tridxby ::= INDEXED BY nm */
-#line 1414 "parse.y"
+#line 1420 "parse.y"
 {
   sqlite3ErrorMsg(pParse,
         "the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
         "within triggers");
 }
-#line 3590 "parse.c"
+#line 3596 "parse.c"
         break;
       case 235: /* tridxby ::= NOT INDEXED */
-#line 1419 "parse.y"
+#line 1425 "parse.y"
 {
   sqlite3ErrorMsg(pParse,
         "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
         "within triggers");
 }
-#line 3599 "parse.c"
+#line 3605 "parse.c"
         break;
       case 236: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */
-#line 1432 "parse.y"
+#line 1438 "parse.y"
 {yymsp[-6].minor.yy427 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy382, yymsp[0].minor.yy362, yymsp[-5].minor.yy52);}
-#line 3604 "parse.c"
+#line 3610 "parse.c"
         break;
       case 237: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */
-#line 1436 "parse.y"
+#line 1442 "parse.y"
 {yymsp[-4].minor.yy427 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy40, yymsp[0].minor.yy279, yymsp[-4].minor.yy52);/*A-overwrites-R*/}
-#line 3609 "parse.c"
+#line 3615 "parse.c"
         break;
       case 238: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */
-#line 1440 "parse.y"
+#line 1446 "parse.y"
 {yymsp[-4].minor.yy427 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy362);}
-#line 3614 "parse.c"
+#line 3620 "parse.c"
         break;
       case 239: /* trigger_cmd ::= select */
-#line 1444 "parse.y"
+#line 1450 "parse.y"
 {yymsp[0].minor.yy427 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy279); /*A-overwrites-X*/}
-#line 3619 "parse.c"
+#line 3625 "parse.c"
         break;
       case 240: /* expr ::= RAISE LP IGNORE RP */
-#line 1447 "parse.y"
+#line 1453 "parse.y"
 {
   spanSet(&yymsp[-3].minor.yy162,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);  /*A-overwrites-X*/
   yymsp[-3].minor.yy162.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0); 
@@ -3626,10 +3632,10 @@ static void yy_reduce(
     yymsp[-3].minor.yy162.pExpr->affinity = ON_CONFLICT_ACTION_IGNORE;
   }
 }
-#line 3630 "parse.c"
+#line 3636 "parse.c"
         break;
       case 241: /* expr ::= RAISE LP raisetype COMMA STRING RP */
-#line 1454 "parse.y"
+#line 1460 "parse.y"
 {
   spanSet(&yymsp[-5].minor.yy162,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);  /*A-overwrites-X*/
   yymsp[-5].minor.yy162.pExpr = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); 
@@ -3637,85 +3643,85 @@ static void yy_reduce(
     yymsp[-5].minor.yy162.pExpr->affinity = (char)yymsp[-3].minor.yy52;
   }
 }
-#line 3641 "parse.c"
+#line 3647 "parse.c"
         break;
       case 242: /* raisetype ::= ROLLBACK */
-#line 1464 "parse.y"
+#line 1470 "parse.y"
 {yymsp[0].minor.yy52 = ON_CONFLICT_ACTION_ROLLBACK;}
-#line 3646 "parse.c"
+#line 3652 "parse.c"
         break;
       case 244: /* raisetype ::= FAIL */
-#line 1466 "parse.y"
+#line 1472 "parse.y"
 {yymsp[0].minor.yy52 = ON_CONFLICT_ACTION_FAIL;}
-#line 3651 "parse.c"
+#line 3657 "parse.c"
         break;
       case 245: /* cmd ::= DROP TRIGGER ifexists fullname */
-#line 1471 "parse.y"
+#line 1477 "parse.y"
 {
   sqlite3DropTrigger(pParse,yymsp[0].minor.yy387,yymsp[-1].minor.yy52);
 }
-#line 3658 "parse.c"
+#line 3664 "parse.c"
         break;
       case 246: /* cmd ::= REINDEX */
-#line 1478 "parse.y"
+#line 1484 "parse.y"
 {sqlite3Reindex(pParse, 0, 0);}
-#line 3663 "parse.c"
+#line 3669 "parse.c"
         break;
       case 247: /* cmd ::= REINDEX nm */
-#line 1479 "parse.y"
+#line 1485 "parse.y"
 {sqlite3Reindex(pParse, &yymsp[0].minor.yy0, 0);}
-#line 3668 "parse.c"
+#line 3674 "parse.c"
         break;
       case 248: /* cmd ::= REINDEX nm ON nm */
-#line 1480 "parse.y"
+#line 1486 "parse.y"
 {sqlite3Reindex(pParse, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);}
-#line 3673 "parse.c"
+#line 3679 "parse.c"
         break;
       case 249: /* cmd ::= ANALYZE */
-#line 1485 "parse.y"
+#line 1491 "parse.y"
 {sqlite3Analyze(pParse, 0);}
-#line 3678 "parse.c"
+#line 3684 "parse.c"
         break;
       case 250: /* cmd ::= ANALYZE nm */
-#line 1486 "parse.y"
+#line 1492 "parse.y"
 {sqlite3Analyze(pParse, &yymsp[0].minor.yy0);}
-#line 3683 "parse.c"
+#line 3689 "parse.c"
         break;
       case 251: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
-#line 1491 "parse.y"
+#line 1497 "parse.y"
 {
   sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy387,&yymsp[0].minor.yy0);
 }
-#line 3690 "parse.c"
+#line 3696 "parse.c"
         break;
       case 252: /* with ::= */
-#line 1514 "parse.y"
+#line 1520 "parse.y"
 {yymsp[1].minor.yy151 = 0;}
-#line 3695 "parse.c"
+#line 3701 "parse.c"
         break;
       case 253: /* with ::= WITH wqlist */
-#line 1516 "parse.y"
+#line 1522 "parse.y"
 { yymsp[-1].minor.yy151 = yymsp[0].minor.yy151; }
-#line 3700 "parse.c"
+#line 3706 "parse.c"
         break;
       case 254: /* with ::= WITH RECURSIVE wqlist */
-#line 1517 "parse.y"
+#line 1523 "parse.y"
 { yymsp[-2].minor.yy151 = yymsp[0].minor.yy151; }
-#line 3705 "parse.c"
+#line 3711 "parse.c"
         break;
       case 255: /* wqlist ::= nm eidlist_opt AS LP select RP */
-#line 1519 "parse.y"
+#line 1525 "parse.y"
 {
   yymsp[-5].minor.yy151 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy382, yymsp[-1].minor.yy279); /*A-overwrites-X*/
 }
-#line 3712 "parse.c"
+#line 3718 "parse.c"
         break;
       case 256: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
-#line 1522 "parse.y"
+#line 1528 "parse.y"
 {
   yymsp[-7].minor.yy151 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy151, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy382, yymsp[-1].minor.yy279);
 }
-#line 3719 "parse.c"
+#line 3725 "parse.c"
         break;
       default:
       /* (257) input ::= ecmd */ yytestcase(yyruleno==257);
@@ -3826,7 +3832,7 @@ static void yy_syntax_error(
   } else {
     sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
   }
-#line 3830 "parse.c"
+#line 3836 "parse.c"
 /************ End %syntax_error code ******************************************/
   sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
 }
diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y
index e2acf24..09145a3 100644
--- a/src/box/sql/parse.y
+++ b/src/box/sql/parse.y
@@ -108,7 +108,10 @@ static void disableLookaside(Parse *pParse){
 
 // Input is a single SQL command
 input ::= ecmd.
-ecmd ::= explain cmdx SEMI.       { sqlite3FinishCoding(pParse); }
+ecmd ::= explain cmdx SEMI. {
+	if (!pParse->parse_only)
+		sqlite3FinishCoding(pParse);
+}
 ecmd ::= SEMI. {
   sqlite3ErrorMsg(pParse, "syntax error: empty request");
 }
@@ -378,7 +381,10 @@ cmd ::= DROP VIEW ifexists(E) fullname(X). {
 //
 cmd ::= select(X).  {
   SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
-  sqlite3Select(pParse, X, &dest);
+  if(!pParse->parse_only)
+	  sqlite3Select(pParse, X, &dest);
+  else
+	  sql_extract_select_expr(pParse, X);
   sqlite3SelectDelete(pParse->db, X);
 }
 
@@ -627,7 +633,7 @@ joinop(X) ::= JOIN_KW(A) join_nm(B) join_nm(C) JOIN.
                   {X = sqlite3JoinType(pParse,&A,&B,&C);/*X-overwrites-A*/}
 
 %type on_opt {Expr*}
-%destructor on_opt {sqlite3ExprDelete(pParse->db, $$);}
+%destructor on_opt {sql_expr_free(pParse->db, $$);}
 on_opt(N) ::= ON expr(E).   {N = E.pExpr;}
 on_opt(N) ::= .             {N = 0;}
 
@@ -685,7 +691,7 @@ groupby_opt(A) ::= .                      {A = 0;}
 groupby_opt(A) ::= GROUP BY nexprlist(X). {A = X;}
 
 %type having_opt {Expr*}
-%destructor having_opt {sqlite3ExprDelete(pParse->db, $$);}
+%destructor having_opt {sql_expr_free(pParse->db, $$);}
 having_opt(A) ::= .                {A = 0;}
 having_opt(A) ::= HAVING expr(X).  {A = X.pExpr;}
 
@@ -735,7 +741,7 @@ cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W). {
 %endif
 
 %type where_opt {Expr*}
-%destructor where_opt {sqlite3ExprDelete(pParse->db, $$);}
+%destructor where_opt {sql_expr_free(pParse->db, $$);}
 
 where_opt(A) ::= .                    {A = 0;}
 where_opt(A) ::= WHERE expr(X).       {A = X.pExpr;}
@@ -824,9 +830,9 @@ idlist(A) ::= nm(Y).
 //
 
 %type expr {ExprSpan}
-%destructor expr {sqlite3ExprDelete(pParse->db, $$.pExpr);}
+%destructor expr {sql_expr_free(pParse->db, $$.pExpr);}
 %type term {ExprSpan}
-%destructor term {sqlite3ExprDelete(pParse->db, $$.pExpr);}
+%destructor term {sql_expr_free(pParse->db, $$.pExpr);}
 
 %include {
   /* This is a utility routine used to set the ExprSpan.zStart and
@@ -1034,7 +1040,7 @@ expr(A) ::= expr(A) NOT NULL(E). {spanUnaryPostfix(pParse,TK_NOTNULL,&A,&E);}
     sqlite3 *db = pParse->db;
     if( pA && pY && pY->op==TK_NULL ){
       pA->op = (u8)op;
-      sqlite3ExprDelete(db, pA->pRight);
+      sql_expr_free(db, pA->pRight);
       pA->pRight = 0;
     }
   }
@@ -1111,7 +1117,7 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
       ** simplify to constants 0 (false) and 1 (true), respectively,
       ** regardless of the value of expr1.
       */
-      sqlite3ExprDelete(pParse->db, A.pExpr);
+      sql_expr_free(pParse->db, A.pExpr);
       A.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[N],1);
     }else if( Y->nExpr==1 ){
       /* Expressions of the form:
@@ -1189,7 +1195,7 @@ expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). {
     sqlite3ExprSetHeightAndFlags(pParse, A.pExpr);
   }else{
     sqlite3ExprListDelete(pParse->db, Y);
-    sqlite3ExprDelete(pParse->db, Z);
+    sql_expr_free(pParse->db, Z);
   }
 }
 %type case_exprlist {ExprList*}
@@ -1203,11 +1209,11 @@ case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). {
   A = sqlite3ExprListAppend(pParse,A, Z.pExpr);
 }
 %type case_else {Expr*}
-%destructor case_else {sqlite3ExprDelete(pParse->db, $$);}
+%destructor case_else {sql_expr_free(pParse->db, $$);}
 case_else(A) ::=  ELSE expr(X).         {A = X.pExpr;}
 case_else(A) ::=  .                     {A = 0;} 
 %type case_operand {Expr*}
-%destructor case_operand {sqlite3ExprDelete(pParse->db, $$);}
+%destructor case_operand {sql_expr_free(pParse->db, $$);}
 case_operand(A) ::= expr(X).            {A = X.pExpr; /*A-overwrites-X*/} 
 case_operand(A) ::= .                   {A = 0;} 
 
@@ -1377,7 +1383,7 @@ foreach_clause ::= .
 foreach_clause ::= FOR EACH ROW.
 
 %type when_clause {Expr*}
-%destructor when_clause {sqlite3ExprDelete(pParse->db, $$);}
+%destructor when_clause {sql_expr_free(pParse->db, $$);}
 when_clause(A) ::= .             { A = 0; }
 when_clause(A) ::= WHEN expr(X). { A = X.pExpr; }
 
diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c
index 18e25cf..3be0995 100644
--- a/src/box/sql/resolve.c
+++ b/src/box/sql/resolve.c
@@ -115,7 +115,7 @@ resolveAlias(Parse * pParse,	/* Parsing context */
 	}
 	ExprSetProperty(pDup, EP_Alias);
 
-	/* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
+	/* Before calling sql_expr_free(), set the EP_Static flag. This
 	 * prevents ExprDelete() from deleting the Expr structure itself,
 	 * allowing it to be repopulated by the memcpy() on the following line.
 	 * The pExpr->u.zToken might point into memory that will be freed by the
@@ -123,7 +123,7 @@ resolveAlias(Parse * pParse,	/* Parsing context */
 	 * make a copy of the token before doing the sqlite3DbFree().
 	 */
 	ExprSetProperty(pExpr, EP_Static);
-	sqlite3ExprDelete(db, pExpr);
+	sql_expr_free(db, pExpr);
 	memcpy(pExpr, pDup, sizeof(*pExpr));
 	if (!ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken != 0) {
 		assert((pExpr->flags & (EP_Reduced | EP_TokenOnly)) == 0);
@@ -462,9 +462,9 @@ lookupName(Parse * pParse,	/* The parsing context */
 
 	/* Clean up and return
 	 */
-	sqlite3ExprDelete(db, pExpr->pLeft);
+	sql_expr_free(db, pExpr->pLeft);
 	pExpr->pLeft = 0;
-	sqlite3ExprDelete(db, pExpr->pRight);
+	sql_expr_free(db, pExpr->pRight);
 	pExpr->pRight = 0;
 	pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN);
  lookupname_end:
@@ -1030,7 +1030,7 @@ resolveCompoundOrderBy(Parse * pParse,	/* Parsing context.  Leave error messages
 						    resolveOrderByTermToExprList
 						    (pParse, pSelect, pDup);
 					}
-					sqlite3ExprDelete(db, pDup);
+					sql_expr_free(db, pDup);
 				}
 			}
 			if (iCol > 0) {
@@ -1052,7 +1052,7 @@ resolveCompoundOrderBy(Parse * pParse,	/* Parsing context.  Leave error messages
 					assert(pParent->pLeft == pE);
 					pParent->pLeft = pNew;
 				}
-				sqlite3ExprDelete(db, pE);
+				sql_expr_free(db, pE);
 				pItem->u.x.iOrderByCol = (u16) iCol;
 				pItem->done = 1;
 			} else {
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index c14bd74..a201d1d 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -94,12 +94,12 @@ clearSelect(sqlite3 * db, Select * p, int bFree)
 		Select *pPrior = p->pPrior;
 		sqlite3ExprListDelete(db, p->pEList);
 		sqlite3SrcListDelete(db, p->pSrc);
-		sqlite3ExprDelete(db, p->pWhere);
+		sql_expr_free(db, p->pWhere);
 		sqlite3ExprListDelete(db, p->pGroupBy);
-		sqlite3ExprDelete(db, p->pHaving);
+		sql_expr_free(db, p->pHaving);
 		sqlite3ExprListDelete(db, p->pOrderBy);
-		sqlite3ExprDelete(db, p->pLimit);
-		sqlite3ExprDelete(db, p->pOffset);
+		sql_expr_free(db, p->pLimit);
+		sql_expr_free(db, p->pOffset);
 		if (p->pWith)
 			sqlite3WithDelete(db, p->pWith);
 		if (bFree)
@@ -2669,7 +2669,7 @@ multiSelect(Parse * pParse,	/* Parsing context */
 							     pPrior->
 							     nSelectRow);
 				}
-				sqlite3ExprDelete(db, p->pLimit);
+				sql_expr_free(db, p->pLimit);
 				p->pLimit = pLimit;
 				p->pOffset = pOffset;
 				p->iLimit = 0;
@@ -2768,7 +2768,7 @@ multiSelect(Parse * pParse,	/* Parsing context */
 				p->pPrior = pPrior;
 				if (p->nSelectRow > pPrior->nSelectRow)
 					p->nSelectRow = pPrior->nSelectRow;
-				sqlite3ExprDelete(db, p->pLimit);
+				sql_expr_free(db, p->pLimit);
 				p->pLimit = pLimit;
 				p->pOffset = pOffset;
 
@@ -3297,9 +3297,9 @@ multiSelectOrderBy(Parse * pParse,	/* Parsing context */
 	} else {
 		regLimitA = regLimitB = 0;
 	}
-	sqlite3ExprDelete(db, p->pLimit);
+	sql_expr_free(db, p->pLimit);
 	p->pLimit = 0;
-	sqlite3ExprDelete(db, p->pOffset);
+	sql_expr_free(db, p->pOffset);
 	p->pOffset = 0;
 
 	regAddrA = ++pParse->nMem;
@@ -3514,7 +3514,7 @@ substExpr(Parse * pParse,	/* Report errors here */
 					    pExpr->iRightJoinTable;
 					pNew->flags |= EP_FromJoin;
 				}
-				sqlite3ExprDelete(db, pExpr);
+				sql_expr_free(db, pExpr);
 				pExpr = pNew;
 			}
 		}
@@ -6334,3 +6334,13 @@ sqlite3Select(Parse * pParse,		/* The parser context */
 #endif
 	return rc;
 }
+
+void
+sql_extract_select_expr(struct Parse *parser, struct Select *select)
+{
+	struct ExprList *expr_list = select->pEList;
+	assert(expr_list->nExpr == 1);
+	parser->parsed_expr = sqlite3ExprDup(parser->db,
+					     expr_list->a->pExpr,
+					     EXPRDUP_REDUCE);
+}
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index e9c0b31..6d4ae7c 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -63,10 +63,12 @@
  * asterisks and the comment text.
  */
 
-#include <box/field_def.h>
 #include <stdbool.h>
-#include <trivia/util.h>
+
+#include "box/field_def.h"
+#include "box/sql.h"
 #include "box/txn.h"
+#include "trivia/util.h"
 
 /*
  * These #defines should enable >2GB file support on POSIX if the
@@ -3007,6 +3009,10 @@ struct Parse {
 	With *pWithToFree;	/* Free this WITH object at the end of the parse */
 
 	bool initiateTTrans;	/* Initiate Tarantool transaction */
+	/* If set - do not emit byte code at all, just parse.  */
+	bool parse_only;
+	/* If parse_only is set to true, store parsed expression. */
+	struct Expr *parsed_expr;
 };
 
 /*
@@ -3521,7 +3527,6 @@ void sqlite3PExprAddSelect(Parse *, Expr *, Select *);
 Expr *sqlite3ExprAnd(sqlite3 *, Expr *, Expr *);
 Expr *sqlite3ExprFunction(Parse *, ExprList *, Token *);
 void sqlite3ExprAssignVarNumber(Parse *, Expr *, u32);
-void sqlite3ExprDelete(sqlite3 *, Expr *);
 ExprList *sqlite3ExprListAppend(Parse *, ExprList *, Expr *);
 ExprList *sqlite3ExprListAppendVector(Parse *, ExprList *, IdList *, Expr *);
 void sqlite3ExprListSetSortOrder(ExprList *, int);
diff --git a/src/box/sql/tokenize.c b/src/box/sql/tokenize.c
index f810db4..ae52731 100644
--- a/src/box/sql/tokenize.c
+++ b/src/box/sql/tokenize.c
@@ -652,3 +652,124 @@ sqlite3RunParser(Parse * pParse, const char *zSql, char **pzErrMsg)
 	assert(nErr == 0 || pParse->rc != SQLITE_OK);
 	return nErr;
 }
+
+/**
+ * Perform parsing of provided expression. This is done by
+ * surrounding the expression w/ 'SELECT ' prefix and perform
+ * convetional parsing. Then extract result expression value from
+ * stuct Select and return it.
+ * @param db SQL context handle.
+ * @param expr Expression to parse.
+ * @param[out] result Result: AST structure.
+ * @param[out] err Error string if any.
+ *
+ * @retval Error code if any.
+ */
+int
+sql_compile_expr(sqlite3 *db,
+		 const char *expr,
+		 struct Expr **result,
+		 char **err)
+{
+	struct Parse parser;
+	int nErr = 0;		/* Number of errors encountered */
+	int i;			/* Loop counter */
+	void *engine;		/* The LEMON-generated LALR(1) parser */
+	int token_type;		/* type of the next token */
+	int last_token_type = -1;	/* type of the previous token */
+	int mxSqlLen;		/* Max length of an SQL string */
+
+	assert(expr != 0);
+	mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
+	memset(&parser, 0, sizeof(struct Parse));
+	parser.rc = SQLITE_OK;
+	parser.zTail = expr;
+	parser.db = db;
+	parser.pToplevel = NULL;
+	parser.parse_only = true;
+	i = 0;
+	assert(err != 0);
+	engine = sqlite3ParserAlloc(sqlite3Malloc);
+	if (engine == NULL) {
+		sqlite3OomFault(db);
+		return SQLITE_NOMEM_BKPT;
+	}
+
+	const char *outer = "SELECT ";
+	char *stmt = malloc(strlen(outer) + strlen(expr) + 1);
+	if (stmt == NULL) {
+		sqlite3OomFault(db);
+		return SQLITE_NOMEM_BKPT;
+	}
+	sprintf(stmt, "%s%s", outer, expr);
+	while (1) {
+		assert(i >= 0);
+		if (stmt[i] != 0) {
+			parser.sLastToken.z = &stmt[i];
+			parser.sLastToken.n =
+			    sqlite3GetToken((u8 *) & stmt[i], &token_type,
+					    &parser.sLastToken.isReserved);
+			i += parser.sLastToken.n;
+			if (i > mxSqlLen) {
+				parser.rc = SQLITE_TOOBIG;
+				break;
+			}
+		} else {
+			/* Upon reaching the end of input, call
+			 * the parser two more times with tokens
+			 * TK_SEMI and 0, in that order.
+			 */
+			if (last_token_type == TK_SEMI)
+				token_type = 0;
+			else if (last_token_type == 0)
+				break;
+			else
+				token_type = TK_SEMI;
+		}
+		if (token_type >= TK_SPACE) {
+			assert(token_type == TK_SPACE
+			       || token_type == TK_ILLEGAL);
+			if (token_type == TK_ILLEGAL) {
+				sqlite3ErrorMsg(&parser,
+						"unrecognized token: \"%T\"",
+						&parser.sLastToken);
+				break;
+			}
+		} else {
+			sqlite3Parser(engine, token_type, parser.sLastToken,
+				      &parser);
+			last_token_type = token_type;
+			if (parser.rc != SQLITE_OK || db->mallocFailed)
+				break;
+		}
+	}
+	assert(nErr == 0);
+	assert(stmt[i] == '\0');
+	sqlite3ParserFree(engine, sqlite3_free);
+	if (db->mallocFailed)
+		parser.rc = SQLITE_NOMEM_BKPT;
+	if (parser.rc != SQLITE_OK && parser.rc != SQLITE_DONE
+	    && parser.zErrMsg == 0) {
+		parser.zErrMsg =
+		    sqlite3MPrintf(db, "%s", sqlite3ErrStr(parser.rc));
+	}
+	assert(err != 0);
+	if (parser.zErrMsg) {
+		*err = parser.zErrMsg;
+		sqlite3_log(parser.rc, "%s", *err);
+		parser.zErrMsg = 0;
+		nErr++;
+	}
+
+	assert(parser.pVdbe == NULL);
+	assert(parser.pNewTable == NULL);
+	assert(parser.pWithToFree == NULL);
+	assert(parser.pAinc == NULL);
+	assert(parser.pZombieTab == NULL);
+	assert(parser.pNewTrigger == NULL);
+	assert(parser.pVList == NULL);
+
+	assert(nErr == 0 || parser.rc != SQLITE_OK);
+	*result = parser.parsed_expr;
+	return nErr;
+}
diff --git a/src/box/sql/trigger.c b/src/box/sql/trigger.c
index 5460d1a..690ffe3 100644
--- a/src/box/sql/trigger.c
+++ b/src/box/sql/trigger.c
@@ -52,7 +52,7 @@ sqlite3DeleteTriggerStep(sqlite3 * db, TriggerStep * pTriggerStep)
 		TriggerStep *pTmp = pTriggerStep;
 		pTriggerStep = pTriggerStep->pNext;
 
-		sqlite3ExprDelete(db, pTmp->pWhere);
+		sql_expr_free(db, pTmp->pWhere);
 		sqlite3ExprListDelete(db, pTmp->pExprList);
 		sqlite3SelectDelete(db, pTmp->pSelect);
 		sqlite3IdListDelete(db, pTmp->pIdList);
@@ -185,7 +185,7 @@ sqlite3BeginTrigger(Parse * pParse,	/* The parse context of the CREATE TRIGGER s
 	sqlite3DbFree(db, zName);
 	sqlite3SrcListDelete(db, pTableName);
 	sqlite3IdListDelete(db, pColumns);
-	sqlite3ExprDelete(db, pWhen);
+	sql_expr_free(db, pWhen);
 	if (!pParse->pNewTrigger) {
 		sqlite3DeleteTrigger(db, pTrigger);
 	} else {
@@ -447,7 +447,7 @@ sqlite3TriggerUpdateStep(sqlite3 * db,	/* The database connection */
 		pTriggerStep->orconf = orconf;
 	}
 	sqlite3ExprListDelete(db, pEList);
-	sqlite3ExprDelete(db, pWhere);
+	sql_expr_free(db, pWhere);
 	return pTriggerStep;
 }
 
@@ -470,7 +470,7 @@ sqlite3TriggerDeleteStep(sqlite3 * db,	/* Database connection */
 		    sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
 		pTriggerStep->orconf = ON_CONFLICT_ACTION_DEFAULT;
 	}
-	sqlite3ExprDelete(db, pWhere);
+	sql_expr_free(db, pWhere);
 	return pTriggerStep;
 }
 
@@ -485,7 +485,7 @@ sqlite3DeleteTrigger(sqlite3 * db, Trigger * pTrigger)
 	sqlite3DeleteTriggerStep(db, pTrigger->step_list);
 	sqlite3DbFree(db, pTrigger->zName);
 	sqlite3DbFree(db, pTrigger->table);
-	sqlite3ExprDelete(db, pTrigger->pWhen);
+	sql_expr_free(db, pTrigger->pWhen);
 	sqlite3IdListDelete(db, pTrigger->pColumns);
 	sqlite3DbFree(db, pTrigger);
 }
@@ -911,7 +911,7 @@ codeRowTrigger(Parse * pParse,	/* Current parse context */
 						   iEndTrigger,
 						   SQLITE_JUMPIFNULL);
 			}
-			sqlite3ExprDelete(db, pWhen);
+			sql_expr_free(db, pWhen);
 		}
 
 		/* Code the trigger program into the sub-vdbe. */
diff --git a/src/box/sql/update.c b/src/box/sql/update.c
index bf41325..797a265 100644
--- a/src/box/sql/update.c
+++ b/src/box/sql/update.c
@@ -667,7 +667,7 @@ sqlite3Update(Parse * pParse,		/* The parser context */
 	sqlite3DbFree(db, aXRef);	/* Also frees aRegIdx[] and aToOpen[] */
 	sqlite3SrcListDelete(db, pTabList);
 	sqlite3ExprListDelete(db, pChanges);
-	sqlite3ExprDelete(db, pWhere);
+	sql_expr_free(db, pWhere);
 	return;
 }
 
diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
index 568ef99..05643c4 100644
--- a/src/box/sql/wherecode.c
+++ b/src/box/sql/wherecode.c
@@ -1830,7 +1830,7 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo,	/* Complete information about t
 			pLevel->iIdxCur = iCovCur;
 		if (pAndExpr) {
 			pAndExpr->pLeft = 0;
-			sqlite3ExprDelete(db, pAndExpr);
+			sql_expr_free(db, pAndExpr);
 		}
 		sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
 		sqlite3VdbeGoto(v, pLevel->addrBrk);
diff --git a/src/box/sql/whereexpr.c b/src/box/sql/whereexpr.c
index 26dcd6a..0241c85 100644
--- a/src/box/sql/whereexpr.c
+++ b/src/box/sql/whereexpr.c
@@ -97,7 +97,7 @@ whereClauseInsert(WhereClause * pWC, Expr * p, u16 wtFlags)
 					 sizeof(pWC->a[0]) * pWC->nSlot * 2);
 		if (pWC->a == 0) {
 			if (wtFlags & TERM_DYNAMIC) {
-				sqlite3ExprDelete(db, p);
+				sql_expr_free(db, p);
 			}
 			pWC->a = pOld;
 			return 0;
@@ -1057,7 +1057,7 @@ exprAnalyze(SrcList * pSrc,	/* the FROM clause */
 				int idxNew;
 				pDup = sqlite3ExprDup(db, pExpr, 0);
 				if (db->mallocFailed) {
-					sqlite3ExprDelete(db, pDup);
+					sql_expr_free(db, pDup);
 					return;
 				}
 				idxNew =
@@ -1398,7 +1398,7 @@ sqlite3WhereClauseClear(WhereClause * pWC)
 	sqlite3 *db = pWC->pWInfo->pParse->db;
 	for (i = pWC->nTerm - 1, a = pWC->a; i >= 0; i--, a++) {
 		if (a->wtFlags & TERM_DYNAMIC) {
-			sqlite3ExprDelete(db, a->pExpr);
+			sql_expr_free(db, a->pExpr);
 		}
 		if (a->wtFlags & TERM_ORINFO) {
 			whereOrInfoDelete(db, a->u.pOrInfo);
-- 
2.11.0

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [tarantool-patches] Re: [PATCH 3/3] sql: move default col values to Tarantool's core
  2018-03-29  6:42 ` [tarantool-patches] [PATCH 3/3] sql: move default col values to Tarantool's core Kirill Yukhin
@ 2018-03-29 14:00   ` v.shpilevoy
  2018-03-31  3:55     ` Kirill Yukhin
  0 siblings, 1 reply; 8+ messages in thread
From: v.shpilevoy @ 2018-03-29 14:00 UTC (permalink / raw)
  To: tarantool-patches; +Cc: Kirill Yukhin

See below 20 comments.

> 29 марта 2018 г., в 9:42, Kirill Yukhin <kyukhin@tarantool.org> написал(а):
> 
> Extract expressions parsing into separate routine to
> allow Tarantool's backend compile DEFAULT statements w/o
> SQL machinery at all. So far, for DEFAULT values no context
> is needed: only constant expressions and built-ins are allowed.
> In future, table context will be added to allow use column
> values for CHECK constraint expressions.
> 
> Move DEFAULT string value to space_def. Move compiled expresion
> to field_def as well. Reason not to move compiled expression
> to tuple_field as follows: we do not want to engage parser
> during tuple validation. So, do it in alter.cc.
> 
> In order to allow expression duplication in alter.cc: expose
> those routines from expr.c and make their names correspond to
> coding style.
> 
> Since recovery is performed before SQL fronend initialization:
> split it into two pieces: 1. create SQL handler, enable
> all subsystems 2. Do recovery.  This will allow to run
> parser during recovery, since it needs db handle so far.
> 
> Part of #3235
> ---
> src/CMakeLists.txt      |   2 +-
> src/box/alter.cc        |  17 +
> src/box/box.cc          |   3 +-
> src/box/field_def.c     |   5 +-
> src/box/field_def.h     |   4 +
> src/box/space_def.c     | 105 ++++--
> src/box/space_def.h     |  10 +-
> src/box/sql.c           |  59 +++-
> src/box/sql.h           |  30 ++
> src/box/sql/build.c     |  18 +-
> src/box/sql/delete.c    |  12 +-
> src/box/sql/expr.c      | 114 ++++---
> src/box/sql/fkey.c      |  13 +-
> src/box/sql/insert.c    |  32 +-
> src/box/sql/main.c      |  15 -
> src/box/sql/parse.c     | 876 ++++++++++++++++++++++++------------------------
> src/box/sql/parse.y     |  32 +-
> src/box/sql/resolve.c   |  12 +-
> src/box/sql/select.c    |  28 +-
> src/box/sql/sqliteInt.h |  11 +-
> src/box/sql/tokenize.c  | 121 +++++++
> src/box/sql/trigger.c   |  12 +-
> src/box/sql/update.c    |   2 +-
> src/box/sql/wherecode.c |   2 +-
> src/box/sql/whereexpr.c |   6 +-
> 25 files changed, 928 insertions(+), 613 deletions(-)
> 
> diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
> index 8ab09e9..eae40c3 100644
> --- a/src/CMakeLists.txt
> +++ b/src/CMakeLists.txt
> @@ -268,7 +268,7 @@ add_executable(
> 	${LIBUTIL_FREEBSD_SRC}/flopen.c
> 	${LIBUTIL_FREEBSD_SRC}/pidfile.c)
> 
> -add_dependencies(tarantool build_bundled_libs preprocess_exports)
> +add_dependencies(tarantool build_bundled_libs preprocess_exports sql)
> 
> # Re-link if exports changed
> set_target_properties(tarantool PROPERTIES LINK_DEPENDS ${exports_file})
> diff --git a/src/box/alter.cc b/src/box/alter.cc
> index 299dcb0..b976d0f 100644
> --- a/src/box/alter.cc
> +++ b/src/box/alter.cc
> @@ -52,6 +52,7 @@
> #include "memtx_tuple.h"
> #include "version.h"
> #include "sequence.h"
> +#include "sql.h"
> 
> /**
>  * chap-sha1 of empty string, i.e.
> @@ -403,6 +404,22 @@ field_def_decode(struct field_def *field, const char **data,
> 			  tt_sprintf("collation is reasonable only for "
> 				     "string, scalar and any fields"));
> 	}
> +
> +	if (field->default_value != NULL) {
> +		struct Expr *expr = NULL;
> +		char *err = 0;

1. err = NUlL.

> +		/* Recovery is performed before SQL FE is initialized.
> +		 * Postpone AST compilation if in process of recovery.
> +		 */
> +		if (sql_get() != NULL) {

1. In the commit message you said: 
"Since recovery is performed before SQL fronend initialization:
split it into two pieces: 1. create SQL handler, enable
all subsystems 2. Do recovery.  This will allow to run
parser during recovery, since it needs db handle so far."

Why sql_get() can be NULL here?
And why do you ignore error?
In a case of error in one of next field definitions, or because of
OOM, or error further in space_def_new_from_tuple, the default_value_ast
leaks. Other field_def fields are not deleted explicitly here, because they
are on region memory, that is deleted on a transaction rollback.

> +			sql_compile_expr(sql_get(),
> +					 field->default_value,
> +					 &expr,
> +					 &err);
> +			assert(err == NULL);
> +			field->default_value_ast = expr;

2. How about another name? For example, default_value_expr? I know,
formally it is AST, but actually it is expr. Or lets rename struct Expr to
struct expr_ast, or struct sql_ast or something.

> +		}
> +	}
> }
> 
> /**
> 
> diff --git a/src/box/space_def.c b/src/box/space_def.c
> index 1b3c305..7b9a664 100644
> --- a/src/box/space_def.c
> +++ b/src/box/space_def.c
> @@ -32,6 +32,7 @@
> #include "space_def.h"
> #include "diag.h"
> #include "error.h"
> +#include "sql.h"
> 
> const struct space_opts space_opts_default = {
> 	/* .temporary = */ false,
> @@ -49,7 +50,7 @@ const struct opt_def space_opts_reg[] = {
> /**
>  * Size of the space_def.
>  * @param name_len Length of the space name.
> - * @param field_names_size Size of all names.
> + * @param fields Fields array of space format.
>  * @param field_count Space field count.
>  * @param[out] names_offset Offset from the beginning of a def to
>  *             a field names memory.

3. Add a comment about second out parameter, please.

> @@ -58,25 +59,37 @@ const struct opt_def space_opts_reg[] = {
>  * @retval Size in bytes.
>  */
> static inline size_t
> -space_def_sizeof(uint32_t name_len, uint32_t field_names_size,
> +space_def_sizeof(uint32_t name_len, const struct field_def *fields,
> 		 uint32_t field_count, uint32_t *names_offset,
> -		 uint32_t *fields_offset)
> +		 uint32_t *fields_offset, uint32_t *def_ast_offset)
> {
> +	uint32_t field_strs_size = 0;
> +	uint32_t def_exprs_size = 0;
> +	for (uint32_t i = 0; i < field_count; ++i) {
> +		field_strs_size += strlen(fields[i].name) + 1;
> +		if (fields[i].default_value != NULL) {
> +			int len = strlen(fields[i].default_value);
> +			field_strs_size += len + 1;
> +		}
> +		if (fields[i].default_value_ast != NULL) {

4. If I correctly understand, (fields[i].default_value != NULL) ==
                              (fields[i].default_value_ast != NULL).
So if a default_value != NULL, then it is guaranteed the
default_value_ast != NULL too. Please, correct me, or move this code
into the body of the previous 'if' and add an assertion.

> +			struct Expr *expr = fields[i].default_value_ast;
> +			def_exprs_size += sql_duped_expr_size(expr, 0);
> +		}
> +	}
> +
> 	*fields_offset = sizeof(struct space_def) + name_len + 1;
> 	*names_offset = *fields_offset + field_count * sizeof(struct field_def);
> -	return *names_offset + field_names_size;
> +	*def_ast_offset = *names_offset + field_strs_size;
> +	return *def_ast_offset + def_exprs_size;
> }
> 
> struct space_def *
> space_def_dup(const struct space_def *src)
> {
> -	uint32_t names_offset, fields_offset;
> -	uint32_t field_names_size = 0;
> -	for (uint32_t i = 0; i < src->field_count; ++i)
> -		field_names_size += strlen(src->fields[i].name) + 1;
> -	size_t size = space_def_sizeof(strlen(src->name), field_names_size,
> -				       src->field_count, &names_offset,
> -				       &fields_offset);
> +	uint32_t strs_offset, fields_offset, def_ast_offset;
> +	size_t size = space_def_sizeof(strlen(src->name), src->fields,
> +				       src->field_count, &strs_offset,
> +				       &fields_offset, &def_ast_offset);
> 	struct space_def *ret = (struct space_def *) malloc(size);
> 	if (ret == NULL) {
> 		diag_set(OutOfMemory, size, "malloc", "ret");
> @@ -92,12 +105,25 @@ space_def_dup(const struct space_def *src)
> 			return NULL;
> 		}
> 	}
> -	char *name_pos = (char *)ret + names_offset;
> +	char *strs_pos = (char *)ret + strs_offset;
> +	char *expr_pos = (char *)ret + def_ast_offset;
> 	if (src->field_count > 0) {
> 		ret->fields = (struct field_def *)((char *)ret + fields_offset);
> 		for (uint32_t i = 0; i < src->field_count; ++i) {
> -			ret->fields[i].name = name_pos;
> -			name_pos += strlen(name_pos) + 1;
> +			ret->fields[i].name = strs_pos;
> +			strs_pos += strlen(strs_pos) + 1;
> +			if (src->fields[i].default_value != NULL) {
> +				ret->fields[i].default_value = strs_pos;
> +				strs_pos += strlen(strs_pos) + 1;
> +			}

5. Same as 3.

> +			struct Expr *def_expr_ast = src->fields[i].default_value_ast;
> +			if (def_expr_ast != NULL) {
> +				struct Expr *expr = NULL;

6. Useless initialization.

> +				expr = sql_expr_dup(sql_get(), def_expr_ast,
> +						    0, &expr_pos);

7. If I correctly understand the sql_expr_dup, after the expression is duplicated,
expr_pos points the byte right after the duplicated Expr. Can you please check it?
If it is true, then you must skip this line "expr_pos += sql_duped_expr_size(expr, 0);",
and I can not understand why it works now.

> +				ret->fields[i].default_value_ast = expr;
> +				expr_pos += sql_duped_expr_size(expr, 0);
> +			}
> 		}
> 	}
> 	tuple_dictionary_ref(ret->dict);
> @@ -111,12 +137,10 @@ space_def_new(uint32_t id, uint32_t uid, uint32_t exact_field_count,
> 	      const struct space_opts *opts, const struct field_def *fields,
> 	      uint32_t field_count)
> {
> -	uint32_t field_names_size = 0;
> -	for (uint32_t i = 0; i < field_count; ++i)
> -		field_names_size += strlen(fields[i].name) + 1;
> -	uint32_t names_offset, fields_offset;
> -	size_t size = space_def_sizeof(name_len, field_names_size, field_count,
> -				       &names_offset, &fields_offset);
> +	uint32_t strs_offset, fields_offset, def_ast_offset;
> +	size_t size = space_def_sizeof(name_len, fields, field_count,
> +				       &strs_offset, &fields_offset,
> +				       &def_ast_offset);
> 	struct space_def *def = (struct space_def *) malloc(size);
> 	if (def == NULL) {
> 		diag_set(OutOfMemory, size, "malloc", "def");
> @@ -147,18 +171,35 @@ space_def_new(uint32_t id, uint32_t uid, uint32_t exact_field_count,
> 		}
> 	}
> 	def->field_count = field_count;
> -	if (field_count == 0) {
> +	if (field_count == 0)
> 		def->fields = NULL;
> -	} else {
> -		char *name_pos = (char *)def + names_offset;
> +	else {
> +		char *strs_pos = (char *)def + strs_offset;
> +		char *expr_pos = (char *)def + def_ast_offset;
> 		def->fields = (struct field_def *)((char *)def + fields_offset);
> 		for (uint32_t i = 0; i < field_count; ++i) {
> 			def->fields[i] = fields[i];
> -			def->fields[i].name = name_pos;
> +			def->fields[i].name = strs_pos;
> 			uint32_t len = strlen(fields[i].name);
> 			memcpy(def->fields[i].name, fields[i].name, len);
> 			def->fields[i].name[len] = 0;
> -			name_pos += len + 1;
> +			strs_pos += len + 1;
> +
> +			if (fields[i].default_value != NULL) {
> +				def->fields[i].default_value = strs_pos;
> +				len = strlen(fields[i].default_value);
> +				memcpy(def->fields[i].default_value, fields[i].default_value, len);
> +				def->fields[i].default_value[len] = 0;
> +				strs_pos += len + 1;
> +			}

8. Same as 5, 6, 7.

> +			struct Expr *def_expr_ast = fields[i].default_value_ast;
> +			if (def_expr_ast != NULL) {
> +				struct Expr *expr = NULL;
> +				expr = sql_expr_dup(sql_get(), def_expr_ast,
> +						    0, &expr_pos);
> +				def->fields[i].default_value_ast = expr;
> +				expr_pos += sql_duped_expr_size(expr, 0);
> +			}
> 		}
> 	}
> 	return def;
> @@ -217,3 +258,17 @@ space_def_check_compatibility(const struct space_def *old_def,
> 	return 0;
> }
> 
> +void
> +space_def_delete(struct space_def *def)
> +{
> +	space_opts_destroy(&def->opts);
> +	tuple_dictionary_unref(def->dict);
> +	for (uint32_t i = 0; i < def->field_count; ++i) {
> +		if (def->fields[i].default_value_ast != NULL) {
> +			sql_expr_free(sql_get(),
> +				      def->fields[i].default_value_ast);
> +		}

9. Why does it work, if your expressions are the part of megamallocs above?

> +	}
> +	TRASH(def);
> +	free(def);
> +}
> diff --git a/src/box/sql.c b/src/box/sql.c
> index 6d8ef9a..8606be6 100644
> --- a/src/box/sql.c
> +++ b/src/box/sql.c
> @@ -56,7 +56,7 @@
> #include "xrow.h"
> #include "iproto_constants.h"
> 
> -static sqlite3 *db;
> +static sqlite3 *db = 0;

10. Please, use NULL instead of 0. Common comment: assigning 0 in the
code, where the variable declaration is not strictly visible is very
confusing - it seems to be integer.

> @@ -1781,3 +1814,25 @@ tarantoolSqlGetMaxId(uint32_t space_id, uint32_t index_id, uint32_t fieldno,
> 
> 	return tuple_field_u64(tuple, fieldno, max_id);
> }
> +
> +/**
> + * Given space_id and field number, return default value
> + * for the field.
> + * @param space_id Space ID.
> + * @param fieldno Field index.
> + * @retval Pointer to AST corresponding to default value.
> + * Can be NULL if no DEFAULT specified or it is a view.
> + */

11. Please, put a function description above a declaration instead of implementation.
We put description above implementation only if a declaration is absent.

> +struct Expr*
> +space_get_column_default_expr(uint32_t space_id, uint32_t fieldno)
> +{
> +	struct space *space;
> +	space = space_cache_find(space_id);
> +	assert(space != NULL);
> +	assert(space->def != NULL);
> +	if (space->def->opts.is_view)
> +		return NULL;

12. How is it possible? Must not it be an assertion?

> +	assert(space->def->field_count > fieldno);
> +
> +	return space->def->fields[fieldno].default_value_ast;
> +}
> diff --git a/src/box/sql.h b/src/box/sql.h
> @@ -55,6 +60,31 @@ sql_free();
> struct sqlite3 *
> sql_get();
> 
> +struct Expr;
> +struct Parse;
> +struct Select;
> +
> +int
> +sql_compile_expr(struct sqlite3 *db,
> +		 const char *expr,
> +		 struct Expr **result,
> +		 char **err);
> +
> +void
> +sql_extract_select_expr(struct Parse *parser, struct Select *select);
> +
> +struct Expr*
> +space_get_column_default_expr(uint32_t space_id, uint32_t fieldno);
> +
> +int
> +sql_duped_expr_size(struct Expr *p, int flags);

13. How about simply expr_size, not duped? And please, name methods of a specific
struct using convention <struct_name>_<method_name>. And for struct size
methods use sizeof name (see space_def_sizeof, key_def_sizeof). For 'free' methods
we use name 'delete'. Delete means, that the struct's memory is freed. Also we
have 'destroy' methods, which frees only struct members, but not the struct itself.
Here it is expr_sizeof(), expr_delete(), expr_dup().

And please, do not use 'get' for getters. Here it is space_column_default_expr().

> +
> +struct Expr *
> +sql_expr_dup(struct sqlite3 *db, struct Expr *p, int flags, char **buffer);
> +
> +void
> +sql_expr_free(struct sqlite3 *db, struct Expr *expr);
> +
> #if defined(__cplusplus)
> } /* extern "C" { */
> #endif
> diff --git a/src/box/sql/build.c b/src/box/sql/build.c
> index 05a7cc9..c3bd637 100644
> --- a/src/box/sql/build.c
> +++ b/src/box/sql/build.c
> @@ -1018,9 +1018,7 @@ sqlite3AddCheckConstraint(Parse * pParse,	/* Parsing context */
> 		}
> 	} else
> #endif
> -	{
> -		sqlite3ExprDelete(pParse->db, pCheckExpr);
> -	}
> +		sql_expr_free(pParse->db, pCheckExpr);

14. Extra tab.

> diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
> index 89dcb23..093f99e 100644
> --- a/src/box/sql/expr.c
> +++ b/src/box/sql/expr.c
> @@ -492,7 +492,7 @@ sqlite3ExprForVectorField(Parse * pParse,	/* Parsing context */
> 		 * pLeft->iTable:   First in an array of register holding result, or 0
> 		 *                  if the result is not yet computed.
> 		 *
> -		 * sqlite3ExprDelete() specifically skips the recursive delete of
> +		 * sql_expr_free() specifically skips the recursive delete of
> 		 * pLeft on TK_SELECT_COLUMN nodes.  But pRight is followed, so pVector
> 		 * can be attached to pRight to cause this node to take ownership of
> 		 * pVector.  Typically there will be multiple TK_SELECT_COLUMN nodes
> @@ -935,8 +935,8 @@ sqlite3ExprAttachSubtrees(sqlite3 * db,
> {
> 	if (pRoot == 0) {
> 		assert(db->mallocFailed);
> -		sqlite3ExprDelete(db, pLeft);
> -		sqlite3ExprDelete(db, pRight);
> +		sql_expr_free(db, pLeft);
> +		sql_expr_free(db, pRight);
> 	} else {
> 		if (pRight) {
> 			pRoot->pRight = pRight;
> @@ -1052,8 +1052,8 @@ sqlite3ExprAnd(sqlite3 * db, Expr * pLeft, Expr * pRight)
> 	} else if (pRight == 0) {
> 		return pLeft;
> 	} else if (exprAlwaysFalse(pLeft) || exprAlwaysFalse(pRight)) {
> -		sqlite3ExprDelete(db, pLeft);
> -		sqlite3ExprDelete(db, pRight);
> +		sql_expr_free(db, pLeft);
> +		sql_expr_free(db, pRight);
> 		return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0],
> 					0);
> 	} else {
> @@ -1189,7 +1189,7 @@ sqlite3ExprDeleteNN(sqlite3 * db, Expr * p)
> 		assert(p->x.pList == 0 || p->pRight == 0);
> 		if (p->pLeft && p->op != TK_SELECT_COLUMN)
> 			sqlite3ExprDeleteNN(db, p->pLeft);
> -		sqlite3ExprDelete(db, p->pRight);
> +		sql_expr_free(db, p->pRight);
> 		if (ExprHasProperty(p, EP_xIsSelect)) {
> 			sqlite3SelectDelete(db, p->x.pSelect);
> 		} else {
> @@ -1203,11 +1203,16 @@ sqlite3ExprDeleteNN(sqlite3 * db, Expr * p)
> 	}
> }
> 
> +/**
> + * Recursively free storage occupied by AST expr.
> + * @param db SQL handle.
> + * @param p Pointer to root node.
> + */

15. Same as 11.

> void
> -sqlite3ExprDelete(sqlite3 * db, Expr * p)
> +sql_expr_free(sqlite3 *db, Expr *expr)
> {
> -	if (p)
> -		sqlite3ExprDeleteNN(db, p);
> +	if (expr != NULL)
> +		sqlite3ExprDeleteNN(db, expr);
> }
> 
> /*
> 
> @@ -1401,29 +1412,28 @@ exprDup(sqlite3 * db, Expr * p, int dupFlags, u8 ** pzBuffer)
> 			if (ExprHasProperty(p, EP_xIsSelect)) {
> 				pNew->x.pSelect =
> 				    sqlite3SelectDup(db, p->x.pSelect,
> -						     dupFlags);
> +						     flags);
> 			} else {
> 				pNew->x.pList =
> 				    sqlite3ExprListDup(db, p->x.pList,
> -						       dupFlags);
> +						       flags);
> 			}
> 		}
> 
> 		/* Fill in pNew->pLeft and pNew->pRight. */
> 		if (ExprHasProperty(pNew, EP_Reduced | EP_TokenOnly)) {
> -			zAlloc += dupedExprNodeSize(p, dupFlags);
> +			zAlloc += dupedExprNodeSize(p, flags);
> 			if (!ExprHasProperty(pNew, EP_TokenOnly | EP_Leaf)) {
> 				pNew->pLeft = p->pLeft ?
> -				    exprDup(db, p->pLeft, EXPRDUP_REDUCE,
> +				    sql_expr_dup(db, p->pLeft, EXPRDUP_REDUCE,
> 					    &zAlloc) : 0;

16. Bad alignment.
> 
> diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
> index 42254dd..00e263a 100644
> --- a/src/box/sql/insert.c
> +++ b/src/box/sql/insert.c
> @@ -674,10 +678,15 @@ sqlite3Insert(Parse * pParse,	/* Parser context */
> 				if (i == pTab->iAutoIncPKey)
> 					sqlite3VdbeAddOp2(v, OP_Integer, -1,
> 							  regCols + i + 1);
> -				else
> +				else {

17. If 'else' body is inside {}, then its 'if' body must be too, even if
consists of single line.
> 
> diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
> index e9c0b31..6d4ae7c 100644
> --- a/src/box/sql/sqliteInt.h
> +++ b/src/box/sql/sqliteInt.h
> @@ -63,10 +63,12 @@
>  * asterisks and the comment text.
>  */
> 
> -#include <box/field_def.h>
> #include <stdbool.h>
> -#include <trivia/util.h>
> +
> +#include "box/field_def.h"
> +#include "box/sql.h"
> #include "box/txn.h"
> +#include "trivia/util.h"
> 
> /*
>  * These #defines should enable >2GB file support on POSIX if the
> @@ -3007,6 +3009,10 @@ struct Parse {
> 	With *pWithToFree;	/* Free this WITH object at the end of the parse */
> 
> 	bool initiateTTrans;	/* Initiate Tarantool transaction */
> +	/* If set - do not emit byte code at all, just parse.  */
> +	bool parse_only;
> +	/* If parse_only is set to true, store parsed expression. */
> +	struct Expr *parsed_expr;

18. For struct members please use /** comments instead of /*.

> diff --git a/src/box/sql/tokenize.c b/src/box/sql/tokenize.c
> index f810db4..ae52731 100644
> --- a/src/box/sql/tokenize.c
> +++ b/src/box/sql/tokenize.c
> @@ -652,3 +652,124 @@ sqlite3RunParser(Parse * pParse, const char *zSql, char **pzErrMsg)
> 	assert(nErr == 0 || pParse->rc != SQLITE_OK);
> 	return nErr;
> }
> +
> +/**
> + * Perform parsing of provided expression. This is done by
> + * surrounding the expression w/ 'SELECT ' prefix and perform
> + * convetional parsing. Then extract result expression value from
> + * stuct Select and return it.
> + * @param db SQL context handle.
> + * @param expr Expression to parse.
> + * @param[out] result Result: AST structure.
> + * @param[out] err Error string if any.
> + *
> + * @retval Error code if any.
> + */
> +int
> +sql_compile_expr(sqlite3 *db,
> +		 const char *expr,
> +		 struct Expr **result,
> +		 char **err)
> +{
> +	struct Parse parser;
> +	int nErr = 0;		/* Number of errors encountered */
> +	int i;			/* Loop counter */
> +	void *engine;		/* The LEMON-generated LALR(1) parser */
> +	int token_type;		/* type of the next token */
> +	int last_token_type = -1;	/* type of the previous token */
> +	int mxSqlLen;		/* Max length of an SQL string */
> +
> +	assert(expr != 0);
> +	mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
> +	memset(&parser, 0, sizeof(struct Parse));
> +	parser.rc = SQLITE_OK;
> +	parser.zTail = expr;
> +	parser.db = db;
> +	parser.pToplevel = NULL;
> +	parser.parse_only = true;
> +	i = 0;
> +	assert(err != 0);
> +	engine = sqlite3ParserAlloc(sqlite3Malloc);
> +	if (engine == NULL) {
> +		sqlite3OomFault(db);
> +		return SQLITE_NOMEM_BKPT;
> +	}
> +
> +	const char *outer = "SELECT ";
> +	char *stmt = malloc(strlen(outer) + strlen(expr) + 1);

19. Please, use region. You do this in a DDL transaction only, so
region usage allows you to do not free this manually.

> +	if (stmt == NULL) {
> +		sqlite3OomFault(db);
> +		return SQLITE_NOMEM_BKPT;
> +	}
> +	sprintf(stmt, "%s%s", outer, expr);
> +	while (1) {

20. While (true). For boolean variables and constants please use
boolean values.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [tarantool-patches] Re: [PATCH 3/3] sql: move default col values to Tarantool's core
  2018-03-29 14:00   ` [tarantool-patches] " v.shpilevoy
@ 2018-03-31  3:55     ` Kirill Yukhin
  2018-03-31  4:24       ` [tarantool-patches] [PATCH] " Kirill Yukhin
  2018-04-03  6:29       ` [tarantool-patches] Re: [PATCH 3/3] " Kirill Yukhin
  0 siblings, 2 replies; 8+ messages in thread
From: Kirill Yukhin @ 2018-03-31  3:55 UTC (permalink / raw)
  To: v.shpilevoy; +Cc: tarantool-patches

Hello Vlad!
I've fixed most of your inputs.

On 29 мар 17:00, v.shpilevoy@tarantool.org wrote:
> See below 20 comments.
> 
> > 29 марта 2018 г., в 9:42, Kirill Yukhin <kyukhin@tarantool.org> написал(а):
> > 
> > Extract expressions parsing into separate routine to
> > allow Tarantool's backend compile DEFAULT statements w/o
> > SQL machinery at all. So far, for DEFAULT values no context
> > is needed: only constant expressions and built-ins are allowed.
> > In future, table context will be added to allow use column
> > values for CHECK constraint expressions.
> > 
> > Move DEFAULT string value to space_def. Move compiled expresion
> > to field_def as well. Reason not to move compiled expression
> > to tuple_field as follows: we do not want to engage parser
> > during tuple validation. So, do it in alter.cc.
> > 
> > In order to allow expression duplication in alter.cc: expose
> > those routines from expr.c and make their names correspond to
> > coding style.
> > 
> > Since recovery is performed before SQL fronend initialization:
> > split it into two pieces: 1. create SQL handler, enable
> > all subsystems 2. Do recovery.  This will allow to run
> > parser during recovery, since it needs db handle so far.
> > 
> > Part of #3235
> > ---
> > src/CMakeLists.txt      |   2 +-
> > src/box/alter.cc        |  17 +
> > src/box/box.cc          |   3 +-
> > src/box/field_def.c     |   5 +-
> > src/box/field_def.h     |   4 +
> > src/box/space_def.c     | 105 ++++--
> > src/box/space_def.h     |  10 +-
> > src/box/sql.c           |  59 +++-
> > src/box/sql.h           |  30 ++
> > src/box/sql/build.c     |  18 +-
> > src/box/sql/delete.c    |  12 +-
> > src/box/sql/expr.c      | 114 ++++---
> > src/box/sql/fkey.c      |  13 +-
> > src/box/sql/insert.c    |  32 +-
> > src/box/sql/main.c      |  15 -
> > src/box/sql/parse.c     | 876 ++++++++++++++++++++++++------------------------
> > src/box/sql/parse.y     |  32 +-
> > src/box/sql/resolve.c   |  12 +-
> > src/box/sql/select.c    |  28 +-
> > src/box/sql/sqliteInt.h |  11 +-
> > src/box/sql/tokenize.c  | 121 +++++++
> > src/box/sql/trigger.c   |  12 +-
> > src/box/sql/update.c    |   2 +-
> > src/box/sql/wherecode.c |   2 +-
> > src/box/sql/whereexpr.c |   6 +-
> > 25 files changed, 928 insertions(+), 613 deletions(-)
> > 
> > diff --git a/src/box/alter.cc b/src/box/alter.cc
> > index 299dcb0..b976d0f 100644
> > --- a/src/box/alter.cc
> > @@ -403,6 +404,22 @@ field_def_decode(struct field_def *field, const char **data,
> > 			  tt_sprintf("collation is reasonable only for "
> > 				     "string, scalar and any fields"));
> > 	}
> > +
> > +	if (field->default_value != NULL) {
> > +		struct Expr *expr = NULL;
> > +		char *err = 0;
> 
> 1. err = NUlL.
Fixed.

> > +		/* Recovery is performed before SQL FE is initialized.
> > +		 * Postpone AST compilation if in process of recovery.
> > +		 */
> > +		if (sql_get() != NULL) {
> 
> 1. In the commit message you said: 
> "Since recovery is performed before SQL fronend initialization:
> split it into two pieces: 1. create SQL handler, enable
> all subsystems 2. Do recovery.  This will allow to run
> parser during recovery, since it needs db handle so far."
> 
> Why sql_get() can be NULL here?
> And why do you ignore error?
> In a case of error in one of next field definitions, or because of
> OOM, or error further in space_def_new_from_tuple, the default_value_ast
> leaks. Other field_def fields are not deleted explicitly here, because they
> are on region memory, that is deleted on a transaction rollback.
As agreed verbally, I've put scope guard to free memory in case something
went wrong. The only place which I was managed to find was in
on_replace_dd_space(). It looks like already properly guarded everywhere
else.
Also, I've refactored tarantoolSqlite3EphemeralCreate, to avoid multiple
leaks there.
Vlad, this is new area to me, so could you pls put especial attention
to such stuff while reviewing my changes?

> > +			sql_compile_expr(sql_get(),
> > +					 field->default_value,
> > +					 &expr,
> > +					 &err);
> > +			assert(err == NULL);
> > +			field->default_value_ast = expr;
> 
> 2. How about another name? For example, default_value_expr? I know,
> formally it is AST, but actually it is expr. Or lets rename struct Expr to
> struct expr_ast, or struct sql_ast or something.
Rgr. Done, although I am still referencing in field def that the field is
actually AST.

> > diff --git a/src/box/space_def.c b/src/box/space_def.c
> > index 1b3c305..7b9a664 100644
> > --- a/src/box/space_def.c
> > +++ b/src/box/space_def.c
> > @@ -49,7 +50,7 @@ const struct opt_def space_opts_reg[] = {
> > /**
> >  * Size of the space_def.
> >  * @param name_len Length of the space name.
> > - * @param field_names_size Size of all names.
> > + * @param fields Fields array of space format.
> >  * @param field_count Space field count.
> >  * @param[out] names_offset Offset from the beginning of a def to
> >  *             a field names memory.
> 
> 3. Add a comment about second out parameter, please.
Done.

> > @@ -58,25 +59,37 @@ const struct opt_def space_opts_reg[] = {
> >  * @retval Size in bytes.
> >  */
> > static inline size_t
> > -space_def_sizeof(uint32_t name_len, uint32_t field_names_size,
> > +space_def_sizeof(uint32_t name_len, const struct field_def *fields,
> > 		 uint32_t field_count, uint32_t *names_offset,
> > -		 uint32_t *fields_offset)
> > +		 uint32_t *fields_offset, uint32_t *def_ast_offset)
> > {
> > +	uint32_t field_strs_size = 0;
> > +	uint32_t def_exprs_size = 0;
> > +	for (uint32_t i = 0; i < field_count; ++i) {
> > +		field_strs_size += strlen(fields[i].name) + 1;
> > +		if (fields[i].default_value != NULL) {
> > +			int len = strlen(fields[i].default_value);
> > +			field_strs_size += len + 1;
> > +		}
> > +		if (fields[i].default_value_ast != NULL) {
> 
> 4. If I correctly understand, (fields[i].default_value != NULL) ==
>                               (fields[i].default_value_ast != NULL).
> So if a default_value != NULL, then it is guaranteed the
> default_value_ast != NULL too. Please, correct me, or move this code
> into the body of the previous 'if' and add an assertion.
Done, although frankly speaking, I see no benefit from this.

> > @@ -92,12 +105,25 @@ space_def_dup(const struct space_def *src)
> > 			return NULL;
> > 		}
> > 	}
> > -	char *name_pos = (char *)ret + names_offset;
> > +	char *strs_pos = (char *)ret + strs_offset;
> > +	char *expr_pos = (char *)ret + def_ast_offset;
> > 	if (src->field_count > 0) {
> > 		ret->fields = (struct field_def *)((char *)ret + fields_offset);
> > 		for (uint32_t i = 0; i < src->field_count; ++i) {
> > -			ret->fields[i].name = name_pos;
> > -			name_pos += strlen(name_pos) + 1;
> > +			ret->fields[i].name = strs_pos;
> > +			strs_pos += strlen(strs_pos) + 1;
> > +			if (src->fields[i].default_value != NULL) {
> > +				ret->fields[i].default_value = strs_pos;
> > +				strs_pos += strlen(strs_pos) + 1;
> > +			}
> 
> 5. Same as 3.
Same as 4. I guess. Done.

> > +			struct Expr *def_expr_ast = src->fields[i].default_value_ast;
> > +			if (def_expr_ast != NULL) {
> > +				struct Expr *expr = NULL;
> 
> 6. Useless initialization.
Fixed.

> > +				expr = sql_expr_dup(sql_get(), def_expr_ast,
> > +						    0, &expr_pos);
> 
> 7. If I correctly understand the sql_expr_dup, after the expression is duplicated,
> expr_pos points the byte right after the duplicated Expr. Can you please check it?
> If it is true, then you must skip this line "expr_pos += sql_duped_expr_size(expr, 0);",
> and I can not understand why it works now.
This is total mess. I think, I've mentioned that in cover letter: Expr is not changed after
invocation of this routine. That's why I am explicitly promoting pointer's value few lines
later. All problems reside in fact, that memory management for ASTs in legacy SQL is
inconsistent: skeleton of the tree uses a buffer (if provided), everything else is
simply malloc'ed. Buffer pointer is promored only on non-reduced expressions, for
unknown reason. I'll submit separate issue asking move all allocations for AST to
region allocator. Also, I've put an assert that pointer wasn't promoted and commented
this piece of code.

> > @@ -147,18 +171,35 @@ space_def_new(uint32_t id, uint32_t uid, uint32_t exact_field_count,
> > 		}
> > 	}
> > 	def->field_count = field_count;
> > -	if (field_count == 0) {
> > +	if (field_count == 0)
> > 		def->fields = NULL;
> > -	} else {
> > -		char *name_pos = (char *)def + names_offset;
> > +	else {
> > +		char *strs_pos = (char *)def + strs_offset;
> > +		char *expr_pos = (char *)def + def_ast_offset;
> > 		def->fields = (struct field_def *)((char *)def + fields_offset);
> > 		for (uint32_t i = 0; i < field_count; ++i) {
> > 			def->fields[i] = fields[i];
> > -			def->fields[i].name = name_pos;
> > +			def->fields[i].name = strs_pos;
> > 			uint32_t len = strlen(fields[i].name);
> > 			memcpy(def->fields[i].name, fields[i].name, len);
> > 			def->fields[i].name[len] = 0;
> > -			name_pos += len + 1;
> > +			strs_pos += len + 1;
> > +
> > +			if (fields[i].default_value != NULL) {
> > +				def->fields[i].default_value = strs_pos;
> > +				len = strlen(fields[i].default_value);
> > +				memcpy(def->fields[i].default_value, fields[i].default_value, len);
> > +				def->fields[i].default_value[len] = 0;
> > +				strs_pos += len + 1;
> > +			}
> 
> 8. Same as 5, 6, 7.
Fixed/commented.

> > @@ -217,3 +258,17 @@ space_def_check_compatibility(const struct space_def *old_def,
> > 	return 0;
> > }
> > 
> > +void
> > +space_def_delete(struct space_def *def)
> > +{
> > +	space_opts_destroy(&def->opts);
> > +	tuple_dictionary_unref(def->dict);
> > +	for (uint32_t i = 0; i < def->field_count; ++i) {
> > +		if (def->fields[i].default_value_ast != NULL) {
> > +			sql_expr_free(sql_get(),
> > +				      def->fields[i].default_value_ast);
> > +		}
> 
> 9. Why does it work, if your expressions are the part of megamallocs above?
Fix is because of inconsistent allocation ficilities of AST. I've introduced
new flag designating if Expr's skeleton was allocated externally. In such a
case nothing is actually freed for skeleton, postponing deallocation to single
mega-free.
 
> > diff --git a/src/box/sql.c b/src/box/sql.c
> > index 6d8ef9a..8606be6 100644
> > --- a/src/box/sql.c
> > +++ b/src/box/sql.c
> > @@ -56,7 +56,7 @@
> > #include "xrow.h"
> > #include "iproto_constants.h"
> > 
> > -static sqlite3 *db;
> > +static sqlite3 *db = 0;
> 
> 10. Please, use NULL instead of 0. Common comment: assigning 0 in the
> code, where the variable declaration is not strictly visible is very
> confusing - it seems to be integer.
Done.
 
> > @@ -1781,3 +1814,25 @@ tarantoolSqlGetMaxId(uint32_t space_id, uint32_t index_id, uint32_t fieldno,
> > 
> > 	return tuple_field_u64(tuple, fieldno, max_id);
> > }
> > +
> > +/**
> > + * Given space_id and field number, return default value
> > + * for the field.
> > + * @param space_id Space ID.
> > + * @param fieldno Field index.
> > + * @retval Pointer to AST corresponding to default value.
> > + * Can be NULL if no DEFAULT specified or it is a view.
> > + */
> 
> 11. Please, put a function description above a declaration instead of implementation.
> We put description above implementation only if a declaration is absent.
Done. For all new routines in sql.h 

> > +struct Expr*
> > +space_get_column_default_expr(uint32_t space_id, uint32_t fieldno)
> > +{
> > +	struct space *space;
> > +	space = space_cache_find(space_id);
> > +	assert(space != NULL);
> > +	assert(space->def != NULL);
> > +	if (space->def->opts.is_view)
> > +		return NULL;
> 
> 12. How is it possible? Must not it be an assertion?
Yes, it's possible. 
Please, see example from sql-tap/triggerC-11.4:
            CREATE TABLE t2(a PRIMARY KEY, b);
            CREATE VIEW v2 AS SELECT * FROM t2;
            CREATE TRIGGER tv2 INSTEAD OF INSERT ON v2 BEGIN
              INSERT INTO log VALUES((SELECT coalesce(max(id),0) + 1 FROM log),
                                     new.a, new.b);
            END;
            INSERT INTO v2 DEFAULT VALUES;
In such a case, executor tries to retrieve default value column of a  VIEW,
however semantics is to return absent default value and do insert ""/NULLs.

> > diff --git a/src/box/sql.h b/src/box/sql.h
> > @@ -55,6 +60,31 @@ sql_free();
> > struct sqlite3 *
> > sql_get();
> > 
> > +struct Expr;
> > +struct Parse;
> > +struct Select;
> > +
> > +int
> > +sql_compile_expr(struct sqlite3 *db,
> > +		 const char *expr,
> > +		 struct Expr **result,
> > +		 char **err);
> > +
> > +void
> > +sql_extract_select_expr(struct Parse *parser, struct Select *select);
> > +
> > +struct Expr*
> > +space_get_column_default_expr(uint32_t space_id, uint32_t fieldno);
> > +
> > +int
> > +sql_duped_expr_size(struct Expr *p, int flags);
> 
> 13. How about simply expr_size, not duped? And please, name methods of a specific
> struct using convention <struct_name>_<method_name>. And for struct size
> methods use sizeof name (see space_def_sizeof, key_def_sizeof). For 'free' methods
> we use name 'delete'. Delete means, that the struct's memory is freed. Also we
> have 'destroy' methods, which frees only struct members, but not the struct itself.
> Here it is expr_sizeof(), expr_delete(), expr_dup().
> 
> And please, do not use 'get' for getters. Here it is space_column_default_expr().
Done.

> > diff --git a/src/box/sql/build.c b/src/box/sql/build.c
> > index 05a7cc9..c3bd637 100644
> > --- a/src/box/sql/build.c
> > +++ b/src/box/sql/build.c
> > @@ -1018,9 +1018,7 @@ sqlite3AddCheckConstraint(Parse * pParse,	/* Parsing context */
> > 		}
> > 	} else
> > #endif
> > -	{
> > -		sqlite3ExprDelete(pParse->db, pCheckExpr);
> > -	}
> > +		sql_expr_free(pParse->db, pCheckExpr);
> 
> 14. Extra tab.
Why? It belongs to `else`, which is under ifndef.

> > diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
> > index 89dcb23..093f99e 100644
> > --- a/src/box/sql/expr.c
> > +++ b/src/box/sql/expr.c
> > @@ -1203,11 +1203,16 @@ sqlite3ExprDeleteNN(sqlite3 * db, Expr * p)
> > 	}
> > }
> > 
> > +/**
> > + * Recursively free storage occupied by AST expr.
> > + * @param db SQL handle.
> > + * @param p Pointer to root node.
> > + */
> 
> 15. Same as 11.
Fixed.

> > @@ -1401,29 +1412,28 @@ exprDup(sqlite3 * db, Expr * p, int dupFlags, u8 ** pzBuffer)
> > 			if (ExprHasProperty(p, EP_xIsSelect)) {
> > 				pNew->x.pSelect =
> > 				    sqlite3SelectDup(db, p->x.pSelect,
> > -						     dupFlags);
> > +						     flags);
> > 			} else {
> > 				pNew->x.pList =
> > 				    sqlite3ExprListDup(db, p->x.pList,
> > -						       dupFlags);
> > +						       flags);
> > 			}
> > 		}
> > 
> > 		/* Fill in pNew->pLeft and pNew->pRight. */
> > 		if (ExprHasProperty(pNew, EP_Reduced | EP_TokenOnly)) {
> > -			zAlloc += dupedExprNodeSize(p, dupFlags);
> > +			zAlloc += dupedExprNodeSize(p, flags);
> > 			if (!ExprHasProperty(pNew, EP_TokenOnly | EP_Leaf)) {
> > 				pNew->pLeft = p->pLeft ?
> > -				    exprDup(db, p->pLeft, EXPRDUP_REDUCE,
> > +				    sql_expr_dup(db, p->pLeft, EXPRDUP_REDUCE,
> > 					    &zAlloc) : 0;
> 
> 16. Bad alignment.
Fixed.

> > diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
> > index 42254dd..00e263a 100644
> > --- a/src/box/sql/insert.c
> > +++ b/src/box/sql/insert.c
> > @@ -674,10 +678,15 @@ sqlite3Insert(Parse * pParse,	/* Parser context */
> > 				if (i == pTab->iAutoIncPKey)
> > 					sqlite3VdbeAddOp2(v, OP_Integer, -1,
> > 							  regCols + i + 1);
> > -				else
> > +				else {
> 
> 17. If 'else' body is inside {}, then its 'if' body must be too, even if
> consists of single line.
Huh. Okay.

> > diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
> > index e9c0b31..6d4ae7c 100644
> > --- a/src/box/sql/sqliteInt.h
> > +++ b/src/box/sql/sqliteInt.h
> > @@ -3007,6 +3009,10 @@ struct Parse {
> > 	With *pWithToFree;	/* Free this WITH object at the end of the parse */
> > 
> > 	bool initiateTTrans;	/* Initiate Tarantool transaction */
> > +	/* If set - do not emit byte code at all, just parse.  */
> > +	bool parse_only;
> > +	/* If parse_only is set to true, store parsed expression. */
> > +	struct Expr *parsed_expr;
> 
> 18. For struct members please use /** comments instead of /*.
Done.

> > diff --git a/src/box/sql/tokenize.c b/src/box/sql/tokenize.c
> > index f810db4..ae52731 100644
> > --- a/src/box/sql/tokenize.c
> > +++ b/src/box/sql/tokenize.c
> > @@ -652,3 +652,124 @@ sqlite3RunParser(Parse * pParse, const char *zSql, char **pzErrMsg)
> > 	assert(nErr == 0 || pParse->rc != SQLITE_OK);
> > 	return nErr;
> > }
> > +
> > +/**
> > + * Perform parsing of provided expression. This is done by
> > + * surrounding the expression w/ 'SELECT ' prefix and perform
> > + * convetional parsing. Then extract result expression value from
> > + * stuct Select and return it.
> > + * @param db SQL context handle.
> > + * @param expr Expression to parse.
> > + * @param[out] result Result: AST structure.
> > + * @param[out] err Error string if any.
> > + *
> > + * @retval Error code if any.
> > + */
> > +int
> > +sql_compile_expr(sqlite3 *db,
> > +		 const char *expr,
> > +		 struct Expr **result,
> > +		 char **err)
> > +{
> > +	struct Parse parser;
> > +	int nErr = 0;		/* Number of errors encountered */
> > +	int i;			/* Loop counter */
> > +	void *engine;		/* The LEMON-generated LALR(1) parser */
> > +	int token_type;		/* type of the next token */
> > +	int last_token_type = -1;	/* type of the previous token */
> > +	int mxSqlLen;		/* Max length of an SQL string */
> > +
> > +	assert(expr != 0);
> > +	mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
> > +	memset(&parser, 0, sizeof(struct Parse));
> > +	parser.rc = SQLITE_OK;
> > +	parser.zTail = expr;
> > +	parser.db = db;
> > +	parser.pToplevel = NULL;
> > +	parser.parse_only = true;
> > +	i = 0;
> > +	assert(err != 0);
> > +	engine = sqlite3ParserAlloc(sqlite3Malloc);
> > +	if (engine == NULL) {
> > +		sqlite3OomFault(db);
> > +		return SQLITE_NOMEM_BKPT;
> > +	}
> > +
> > +	const char *outer = "SELECT ";
> > +	char *stmt = malloc(strlen(outer) + strlen(expr) + 1);
> 
> 19. Please, use region. You do this in a DDL transaction only, so
> region usage allows you to do not free this manually.
Done.

> > +	if (stmt == NULL) {
> > +		sqlite3OomFault(db);
> > +		return SQLITE_NOMEM_BKPT;
> > +	}
> > +	sprintf(stmt, "%s%s", outer, expr);
> > +	while (1) {
> 
> 20. While (true). For boolean variables and constants please use
> boolean values.
Done.

--
Thanks, Kirill

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [tarantool-patches] [PATCH] sql: move default col values to Tarantool's core
  2018-03-31  3:55     ` Kirill Yukhin
@ 2018-03-31  4:24       ` Kirill Yukhin
  2018-04-03  6:29       ` [tarantool-patches] Re: [PATCH 3/3] " Kirill Yukhin
  1 sibling, 0 replies; 8+ messages in thread
From: Kirill Yukhin @ 2018-03-31  4:24 UTC (permalink / raw)
  To: v.shpilevoy; +Cc: tarantool-patches

Extract expressions parsing into separate routine to
allow Tarantool's backend compile DEFAULT statements w/o
SQL machinery at all. So far, for DEFAULT values no context
is needed: only constant expressions and built-ins are allowed.
In future, table context will be added to allow use column
values for CHECK constraint expressions.

Move DEFAULT string value to space_def. Move compiled expresion
to field_def as well. Reason not to move compiled expression
to tuple_field as follows: we do not want to engage parser
during tuple validation. So, do it in alter.cc.

In order to allow expression duplication in alter.cc: expose
those routines from expr.c and make their names correspond to
coding style.

Since recovery is performed before SQL fronend initialization:
split it into two pieces: 1. create SQL handler, enable
all subsystems 2. Do recovery.  This will allow to run
parser during recovery, since it needs db handle so far.

Part of #3235
---
 src/CMakeLists.txt      |   2 +-
 src/box/alter.cc        |  33 +-
 src/box/box.cc          |   3 +-
 src/box/field_def.c     |   5 +-
 src/box/field_def.h     |   4 +
 src/box/space_def.c     | 133 ++++++--
 src/box/space_def.h     |  10 +-
 src/box/sql.c           |  98 +++++-
 src/box/sql.h           |  96 +++++-
 src/box/sql/build.c     |  18 +-
 src/box/sql/delete.c    |  12 +-
 src/box/sql/expr.c      | 127 +++----
 src/box/sql/fkey.c      |  13 +-
 src/box/sql/insert.c    |  34 +-
 src/box/sql/main.c      |  15 -
 src/box/sql/parse.c     | 876 ++++++++++++++++++++++++------------------------
 src/box/sql/parse.y     |  32 +-
 src/box/sql/resolve.c   |  12 +-
 src/box/sql/select.c    |  28 +-
 src/box/sql/sqliteInt.h |  11 +-
 src/box/sql/tokenize.c  | 109 ++++++
 src/box/sql/trigger.c   |  12 +-
 src/box/sql/update.c    |   2 +-
 src/box/sql/wherecode.c |   2 +-
 src/box/sql/whereexpr.c |   6 +-
 25 files changed, 1032 insertions(+), 661 deletions(-)

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 8ab09e9..eae40c3 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -268,7 +268,7 @@ add_executable(
 	${LIBUTIL_FREEBSD_SRC}/flopen.c
 	${LIBUTIL_FREEBSD_SRC}/pidfile.c)
 
-add_dependencies(tarantool build_bundled_libs preprocess_exports)
+add_dependencies(tarantool build_bundled_libs preprocess_exports sql)
 
 # Re-link if exports changed
 set_target_properties(tarantool PROPERTIES LINK_DEPENDS ${exports_file})
diff --git a/src/box/alter.cc b/src/box/alter.cc
index f40290b..08c1220 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -52,6 +52,7 @@
 #include "memtx_tuple.h"
 #include "version.h"
 #include "sequence.h"
+#include "sql.h"
 
 /**
  * chap-sha1 of empty string, i.e.
@@ -403,6 +404,19 @@ field_def_decode(struct field_def *field, const char **data,
 			  tt_sprintf("collation is reasonable only for "
 				     "string, scalar and any fields"));
 	}
+
+	if (field->default_value != NULL) {
+		struct Expr *expr = NULL;
+		char *err = NULL;
+		sql_expr_compile(sql_get(),
+				 field->default_value,
+				 &expr,
+				 &err);
+		if (err != NULL)
+			tnt_raise(ClientError, ER_SQL_EXECUTE, field->default_value);
+		assert(expr != NULL);
+		field->default_value_expr = expr;
+	}
 }
 
 /**
@@ -1416,6 +1430,11 @@ on_replace_dd_space(struct trigger * /* trigger */, void *event)
 	struct tuple *old_tuple = stmt->old_tuple;
 	struct tuple *new_tuple = stmt->new_tuple;
 	struct region *region = &fiber()->gc;
+	struct space_def *def = NULL;
+ 	auto def_guard = make_scoped_guard([&] {
+			if (def != NULL)
+				space_def_delete(def);
+	});
 	/*
 	 * Things to keep in mind:
 	 * - old_tuple is set only in case of UPDATE.  For INSERT
@@ -1434,12 +1453,9 @@ on_replace_dd_space(struct trigger * /* trigger */, void *event)
 					     BOX_SPACE_FIELD_ID);
 	struct space *old_space = space_by_id(old_id);
 	if (new_tuple != NULL && old_space == NULL) { /* INSERT */
-		struct space_def *def =
-			space_def_new_from_tuple(new_tuple, ER_CREATE_SPACE,
-						 region);
+		def = space_def_new_from_tuple(new_tuple, ER_CREATE_SPACE,
+					       region);
 		access_check_ddl(def->name, def->uid, SC_SPACE, PRIV_C, true);
-		auto def_guard =
-			make_scoped_guard([=] { space_def_delete(def); });
 		RLIST_HEAD(empty_list);
 		struct space *space = space_new_xc(def, &empty_list);
 		/**
@@ -1494,12 +1510,9 @@ on_replace_dd_space(struct trigger * /* trigger */, void *event)
 		txn_on_rollback(txn, on_rollback);
 	} else { /* UPDATE, REPLACE */
 		assert(old_space != NULL && new_tuple != NULL);
-		struct space_def *def =
-			space_def_new_from_tuple(new_tuple, ER_ALTER_SPACE,
-						 region);
+		def = space_def_new_from_tuple(new_tuple, ER_ALTER_SPACE,
+					       region);
 		access_check_ddl(def->name, def->uid, SC_SPACE, PRIV_A, true);
-		auto def_guard =
-			make_scoped_guard([=] { space_def_delete(def); });
 		/*
 		 * Check basic options. Assume the space to be
 		 * empty, because we can not calculate here
diff --git a/src/box/box.cc b/src/box/box.cc
index a3bbdfc..290d18c 100644
--- a/src/box/box.cc
+++ b/src/box/box.cc
@@ -1731,6 +1731,7 @@ box_cfg_xc(void)
 	replication_init();
 	port_init();
 	iproto_init();
+	sql_init();
 	wal_thread_start();
 
 	title("loading");
@@ -1927,7 +1928,7 @@ box_cfg_xc(void)
 	/* Follow replica */
 	replicaset_follow();
 
-	sql_init();
+	sql_load_schema();
 
 	say_info("ready to accept requests");
 
diff --git a/src/box/field_def.c b/src/box/field_def.c
index 1510509..010b3b7 100644
--- a/src/box/field_def.c
+++ b/src/box/field_def.c
@@ -94,6 +94,7 @@ const struct opt_def field_def_reg[] = {
 	OPT_DEF_ENUM("nullable_action", on_conflict_action, struct field_def,
 		     nullable_action, NULL),
 	OPT_DEF("collation", OPT_UINT32, struct field_def, coll_id),
+	OPT_DEF("default", OPT_STRPTR, struct field_def, default_value),
 	OPT_END,
 };
 
@@ -102,7 +103,9 @@ const struct field_def field_def_default = {
 	.name = NULL,
 	.is_nullable = false,
 	.nullable_action = ON_CONFLICT_ACTION_DEFAULT,
-	.coll_id = COLL_NONE
+	.coll_id = COLL_NONE,
+	.default_value = NULL,
+	.default_value_expr = NULL
 };
 
 enum field_type
diff --git a/src/box/field_def.h b/src/box/field_def.h
index e7be06a..dfc1950 100644
--- a/src/box/field_def.h
+++ b/src/box/field_def.h
@@ -110,6 +110,10 @@ struct field_def {
 	enum on_conflict_action nullable_action;
 	/** Collation ID for string comparison. */
 	uint32_t coll_id;
+	/** 0-terminated SQL expression for DEFAULT value. */
+	char *default_value;
+	/** AST for parsed default value. */
+	struct Expr *default_value_expr;
 };
 
 #if defined(__cplusplus)
diff --git a/src/box/space_def.c b/src/box/space_def.c
index 1b3c305..d1bee16 100644
--- a/src/box/space_def.c
+++ b/src/box/space_def.c
@@ -32,6 +32,7 @@
 #include "space_def.h"
 #include "diag.h"
 #include "error.h"
+#include "sql.h"
 
 const struct space_opts space_opts_default = {
 	/* .temporary = */ false,
@@ -49,34 +50,48 @@ const struct opt_def space_opts_reg[] = {
 /**
  * Size of the space_def.
  * @param name_len Length of the space name.
- * @param field_names_size Size of all names.
+ * @param fields Fields array of space format.
  * @param field_count Space field count.
  * @param[out] names_offset Offset from the beginning of a def to
  *             a field names memory.
  * @param[out] fields_offset Offset from the beginning of a def to
  *             a fields array.
+ * @param[out] def_expr_offset Offset from the beginning of a def
+ *             to a def_value_expr array.
  * @retval Size in bytes.
  */
 static inline size_t
-space_def_sizeof(uint32_t name_len, uint32_t field_names_size,
+space_def_sizeof(uint32_t name_len, const struct field_def *fields,
 		 uint32_t field_count, uint32_t *names_offset,
-		 uint32_t *fields_offset)
+		 uint32_t *fields_offset, uint32_t *def_expr_offset)
 {
+	uint32_t field_strs_size = 0;
+	uint32_t def_exprs_size = 0;
+	for (uint32_t i = 0; i < field_count; ++i) {
+		field_strs_size += strlen(fields[i].name) + 1;
+		if (fields[i].default_value != NULL) {
+			int len = strlen(fields[i].default_value);
+			field_strs_size += len + 1;
+			if (fields[i].default_value_expr != NULL) {
+				struct Expr *e = fields[i].default_value_expr;
+				def_exprs_size += sql_expr_sizeof(e, 0);
+			}
+		}
+	}
+
 	*fields_offset = sizeof(struct space_def) + name_len + 1;
 	*names_offset = *fields_offset + field_count * sizeof(struct field_def);
-	return *names_offset + field_names_size;
+	*def_expr_offset = *names_offset + field_strs_size;
+	return *def_expr_offset + def_exprs_size;
 }
 
 struct space_def *
 space_def_dup(const struct space_def *src)
 {
-	uint32_t names_offset, fields_offset;
-	uint32_t field_names_size = 0;
-	for (uint32_t i = 0; i < src->field_count; ++i)
-		field_names_size += strlen(src->fields[i].name) + 1;
-	size_t size = space_def_sizeof(strlen(src->name), field_names_size,
-				       src->field_count, &names_offset,
-				       &fields_offset);
+	uint32_t strs_offset, fields_offset, def_expr_offset;
+	size_t size = space_def_sizeof(strlen(src->name), src->fields,
+				       src->field_count, &strs_offset,
+				       &fields_offset, &def_expr_offset);
 	struct space_def *ret = (struct space_def *) malloc(size);
 	if (ret == NULL) {
 		diag_set(OutOfMemory, size, "malloc", "ret");
@@ -92,12 +107,37 @@ space_def_dup(const struct space_def *src)
 			return NULL;
 		}
 	}
-	char *name_pos = (char *)ret + names_offset;
+	char *strs_pos = (char *)ret + strs_offset;
+	char *expr_pos = (char *)ret + def_expr_offset;
 	if (src->field_count > 0) {
 		ret->fields = (struct field_def *)((char *)ret + fields_offset);
 		for (uint32_t i = 0; i < src->field_count; ++i) {
-			ret->fields[i].name = name_pos;
-			name_pos += strlen(name_pos) + 1;
+			ret->fields[i].name = strs_pos;
+			strs_pos += strlen(strs_pos) + 1;
+			if (src->fields[i].default_value != NULL) {
+				ret->fields[i].default_value = strs_pos;
+				strs_pos += strlen(strs_pos) + 1;
+
+				struct Expr *def_expr;
+				def_expr = src->fields[i].default_value_expr;
+				if (def_expr != NULL) {
+					struct Expr *e = NULL;
+					char *expr_pos_old = expr_pos;
+					e = sql_expr_dup(sql_get(),
+							 def_expr,
+							 0, &expr_pos);
+					/* Note: due to SQL legacy
+					 * duplicactor pointer is
+					 * not promoted for
+					 * REDUCED exprs. Will be
+					 * fixed w/ Expt
+					 * allocation refactoring.
+					 */
+					assert(expr_pos_old == expr_pos);
+					expr_pos += sql_expr_sizeof(e, 0);
+					ret->fields[i].default_value_expr = e;
+				}
+			}
 		}
 	}
 	tuple_dictionary_ref(ret->dict);
@@ -111,12 +151,10 @@ space_def_new(uint32_t id, uint32_t uid, uint32_t exact_field_count,
 	      const struct space_opts *opts, const struct field_def *fields,
 	      uint32_t field_count)
 {
-	uint32_t field_names_size = 0;
-	for (uint32_t i = 0; i < field_count; ++i)
-		field_names_size += strlen(fields[i].name) + 1;
-	uint32_t names_offset, fields_offset;
-	size_t size = space_def_sizeof(name_len, field_names_size, field_count,
-				       &names_offset, &fields_offset);
+	uint32_t strs_offset, fields_offset, def_expr_offset;
+	size_t size = space_def_sizeof(name_len, fields, field_count,
+				       &strs_offset, &fields_offset,
+				       &def_expr_offset);
 	struct space_def *def = (struct space_def *) malloc(size);
 	if (def == NULL) {
 		diag_set(OutOfMemory, size, "malloc", "def");
@@ -147,18 +185,49 @@ space_def_new(uint32_t id, uint32_t uid, uint32_t exact_field_count,
 		}
 	}
 	def->field_count = field_count;
-	if (field_count == 0) {
+	if (field_count == 0)
 		def->fields = NULL;
-	} else {
-		char *name_pos = (char *)def + names_offset;
+	else {
+		char *strs_pos = (char *)def + strs_offset;
+		char *expr_pos = (char *)def + def_expr_offset;
 		def->fields = (struct field_def *)((char *)def + fields_offset);
 		for (uint32_t i = 0; i < field_count; ++i) {
 			def->fields[i] = fields[i];
-			def->fields[i].name = name_pos;
+			def->fields[i].name = strs_pos;
 			uint32_t len = strlen(fields[i].name);
 			memcpy(def->fields[i].name, fields[i].name, len);
 			def->fields[i].name[len] = 0;
-			name_pos += len + 1;
+			strs_pos += len + 1;
+
+			if (fields[i].default_value != NULL) {
+				def->fields[i].default_value = strs_pos;
+				len = strlen(fields[i].default_value);
+				memcpy(def->fields[i].default_value,
+				       fields[i].default_value, len);
+				def->fields[i].default_value[len] = 0;
+				strs_pos += len + 1;
+
+				struct Expr *def_expr_ast;
+				def_expr_ast = fields[i].default_value_expr;
+				if (def_expr_ast != NULL) {
+					struct Expr *expr;
+					char *expr_pos_old = expr_pos;
+					assert(sql_get() != NULL);
+					expr = sql_expr_dup(sql_get(),
+							    def_expr_ast,
+							    0, &expr_pos);
+					/* Note: due to SQL legacy
+					 * duplicactor pointer is
+					 * not promoted for
+					 * REDUCED exprs. Will be
+					 * fixed w/ Expt
+					 * allocation refactoring.
+					 */
+					assert(expr_pos_old == expr_pos);
+					expr_pos += sql_expr_sizeof(expr, 0);
+					def->fields[i].default_value_expr = expr;
+				}
+			}
 		}
 	}
 	return def;
@@ -217,3 +286,17 @@ space_def_check_compatibility(const struct space_def *old_def,
 	return 0;
 }
 
+void
+space_def_delete(struct space_def *def)
+{
+	space_opts_destroy(&def->opts);
+	tuple_dictionary_unref(def->dict);
+	for (uint32_t i = 0; i < def->field_count; ++i) {
+		if (def->fields[i].default_value_expr != NULL) {
+			sql_expr_free(sql_get(),
+				      def->fields[i].default_value_expr, true);
+		}
+	}
+	TRASH(def);
+	free(def);
+}
diff --git a/src/box/space_def.h b/src/box/space_def.h
index b8d0bf8..7722738 100644
--- a/src/box/space_def.h
+++ b/src/box/space_def.h
@@ -115,14 +115,8 @@ struct space_def {
  * Delete the space_def object.
  * @param def Def to delete.
  */
-static inline void
-space_def_delete(struct space_def *def)
-{
-	space_opts_destroy(&def->opts);
-	tuple_dictionary_unref(def->dict);
-	TRASH(def);
-	free(def);
-}
+void
+space_def_delete(struct space_def *def);
 
 /**
  * Duplicate space_def object.
diff --git a/src/box/sql.c b/src/box/sql.c
index 6d8ef9a..ffa488a 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -56,7 +56,7 @@
 #include "xrow.h"
 #include "iproto_constants.h"
 
-static sqlite3 *db;
+static sqlite3 *db = NULL;
 
 static const char nil_key[] = { 0x90 }; /* Empty MsgPack array. */
 
@@ -80,6 +80,27 @@ sql_init()
 }
 
 void
+sql_load_schema()
+{
+	int rc;
+	struct session *user_session = current_session();
+	int commit_internal = !(user_session->sql_flags
+				& SQLITE_InternChanges);
+
+	assert(db->init.busy == 0);
+	db->init.busy = 1;
+	db->pSchema = sqlite3SchemaCreate(db);
+	rc = sqlite3InitDatabase(db);
+	if (rc != SQLITE_OK) {
+		sqlite3SchemaClear(db);
+		panic("failed to initialize SQL subsystem");
+	}
+	db->init.busy = 0;
+	if (rc == SQLITE_OK && commit_internal)
+		sqlite3CommitInternalChanges();
+}
+
+void
 sql_free()
 {
 	sqlite3_close(db); db = NULL;
@@ -417,6 +438,9 @@ int tarantoolSqlite3EphemeralCreate(BtCursor *pCur, uint32_t field_count,
 {
 	assert(pCur);
 	assert(pCur->curFlags & BTCF_TEphemCursor);
+	struct key_def *ephemer_key_def = NULL;
+	struct index_def *ephemer_index_def = NULL;
+	struct space *ephemer_new_space = NULL;
 
 	struct space_def *ephemer_space_def =
 		space_def_new(0 /* space id */, 0 /* user id */, field_count,
@@ -425,8 +449,13 @@ int tarantoolSqlite3EphemeralCreate(BtCursor *pCur, uint32_t field_count,
 			      &space_opts_default, &field_def_default,
 			      0 /* length of field_def */);
 
-	struct key_def *ephemer_key_def = key_def_new(field_count);
-	assert(ephemer_key_def);
+	if (ephemer_space_def == NULL)
+		goto err;
+
+	ephemer_key_def = key_def_new(field_count);
+	if (ephemer_key_def == NULL)
+		goto err;
+
 	for (uint32_t part = 0; part < field_count; ++part) {
 		key_def_set_part(ephemer_key_def, part /* part no */,
 				 part /* filed no */,
@@ -435,32 +464,45 @@ int tarantoolSqlite3EphemeralCreate(BtCursor *pCur, uint32_t field_count,
 				 aColl /* coll */);
 	}
 
-	struct index_def *ephemer_index_def =
+	ephemer_index_def =
 		index_def_new(0 /*space id */, 0 /* index id */, "ephemer_idx",
 			      strlen("ephemer_idx"), TREE, &index_opts_default,
 			      ephemer_key_def, NULL /* pk def */);
 
+	if (ephemer_index_def == NULL)
+		goto err;
+
 	struct rlist key_list;
 	rlist_create(&key_list);
 	rlist_add_entry(&key_list, ephemer_index_def, link);
 
-	struct space *ephemer_new_space = space_new_ephemeral(ephemer_space_def,
-							      &key_list);
-	if (ephemer_new_space == NULL) {
-		diag_log();
-		return SQL_TARANTOOL_ERROR;
-	}
+	ephemer_new_space = space_new_ephemeral(ephemer_space_def, &key_list);
+	if (ephemer_new_space == NULL)
+		goto err;
+
 	struct ta_cursor *c = NULL;
 	c = cursor_create(c, field_count /* key size */);
-	if (!c) {
-		space_delete(ephemer_new_space);
-		return SQLITE_NOMEM;
-	}
+	if (!c)
+		goto err;
 	c->ephem_space = ephemer_new_space;
 	pCur->pTaCursor = c;
 
 	int unused;
 	return tarantoolSqlite3First(pCur, &unused);
+
+err:
+	if (ephemer_space_def != NULL)
+		space_def_delete(ephemer_space_def);
+	if (ephemer_key_def != NULL)
+		key_def_delete(ephemer_key_def);
+	if (ephemer_index_def != NULL)
+		index_def_delete(ephemer_index_def);
+	if(ephemer_space_def != NULL)
+		space_def_delete(ephemer_space_def);
+	if(ephemer_new_space != NULL)
+		space_delete(ephemer_new_space);
+	diag_log();
+	return SQL_TARANTOOL_ERROR;
 }
 
 /*
@@ -1546,11 +1588,17 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
 	for (i = 0; i < n; i++) {
 		const char *t;
 		struct coll *coll = NULL;
+		struct Expr *def = aCol[i].pDflt;
 		if (aCol[i].zColl != NULL &&
 		    strcasecmp(aCol[i].zColl, "binary") != 0) {
 			coll = sqlite3FindCollSeq(aCol[i].zColl);
 		}
-		p = enc->encode_map(p, coll ? 5 : 4);
+		int base_len = 4;
+		if (coll != NULL)
+			base_len += 1;
+		if (def != NULL)
+			base_len += 1;
+		p = enc->encode_map(p, base_len);
 		p = enc->encode_str(p, "name", 4);
 		p = enc->encode_str(p, aCol[i].zName, strlen(aCol[i].zName));
 		p = enc->encode_str(p, "type", 4);
@@ -1572,6 +1620,12 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
 			p = enc->encode_str(p, "collation", strlen("collation"));
 			p = enc->encode_uint(p, coll->id);
 		}
+		if (def != NULL) {
+		        assert((def->flags & EP_IntValue) == 0);
+			assert(def->u.zToken != NULL);
+			p = enc->encode_str(p, "default", strlen("default"));
+			p = enc->encode_str(p, def->u.zToken, strlen(def->u.zToken));
+		}
 	}
 	return (int)(p - base);
 }
@@ -1781,3 +1835,17 @@ tarantoolSqlGetMaxId(uint32_t space_id, uint32_t index_id, uint32_t fieldno,
 
 	return tuple_field_u64(tuple, fieldno, max_id);
 }
+
+struct Expr*
+space_column_default_expr(uint32_t space_id, uint32_t fieldno)
+{
+	struct space *space;
+	space = space_cache_find(space_id);
+	assert(space != NULL);
+	assert(space->def != NULL);
+	if (space->def->opts.is_view)
+		return NULL;
+	assert(space->def->field_count > fieldno);
+
+	return space->def->fields[fieldno].default_value_expr;
+}
diff --git a/src/box/sql.h b/src/box/sql.h
index 8a7c420..9dc218a 100644
--- a/src/box/sql.h
+++ b/src/box/sql.h
@@ -31,6 +31,9 @@
  * SUCH DAMAGE.
  */
 
+#include <stdbool.h>
+#include <stdint.h>
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -39,9 +42,12 @@ void
 sql_init();
 
 void
+sql_load_schema();
+
+void
 sql_free();
 
-/*
+/**
  * struct sqlite3 *
  * sql_get();
  *
@@ -51,10 +57,98 @@ sql_free();
  * don't do anything finicky like sqlite3_close.
  * Behind the scenes, this sqlite was rigged to use Tarantool
  * as a data source.
+ * @retval SQL handle.
  */
 struct sqlite3 *
 sql_get();
 
+struct Expr;
+struct Parse;
+struct Select;
+
+/**
+ * Perform parsing of provided expression. This is done by
+ * surrounding the expression w/ 'SELECT ' prefix and perform
+ * convetional parsing. Then extract result expression value from
+ * stuct Select and return it.
+ * @param db SQL context handle.
+ * @param expr Expression to parse.
+ * @param[out] result Result: AST structure.
+ * @param[out] err Error string if any.
+ *
+ * @retval Error code if any.
+ */
+int
+sql_expr_compile(struct sqlite3 *db,
+		 const char *expr,
+		 struct Expr **result,
+		 char **err);
+
+/**
+ * Recursively free storage occupied by AST expr.
+ * @param db SQL handle.
+ * @param p Pointer to root node.
+ * @param extern_alloc If true, pretend skeleton nodes to be
+ * allocated w/ external allocator, so do nothing for them.
+ */
+void
+sql_expr_extract_select(struct Parse *parser, struct Select *select);
+
+/**
+ * Given space_id and field number, return default value
+ * for the field.
+ * @param space_id Space ID.
+ * @param fieldno Field index.
+ * @retval Pointer to AST corresponding to default value.
+ * Can be NULL if no DEFAULT specified or it is a view.
+ */
+struct Expr*
+space_column_default_expr(uint32_t space_id, uint32_t fieldno);
+
+/**
+ * Return the number of bytes required to create a duplicate of the
+ * expression passed as the first argument. The second argument is a
+ * mask containing EXPRDUP_XXX flags.
+ *
+ * The value returned includes space to create a copy of the Expr struct
+ * itself and the buffer referred to by Expr.u.zToken, if any.
+ *
+ * If the EXPRDUP_REDUCE flag is set, then the return value includes
+ * space to duplicate all Expr nodes in the tree formed by Expr.pLeft
+ * and Expr.pRight variables (but not for any structures pointed to or
+ * descended from the Expr.x.pList or Expr.x.pSelect variables).
+ * @param expr Root expression of AST.
+ * @param flags The only possible flag is REDUCED, 0 otherwise.
+ * @retval Size in bytes needed to duplicate AST and all private
+ * strings.
+ */
+int
+sql_expr_sizeof(struct Expr *p, int flags);
+
+/**
+ * This function is similar to sqlite3ExprDup(), except that if pzBuffer
+ * is not NULL then *pzBuffer is assumed to point to a buffer large enough
+ * to store the copy of expression p, the copies of p->u.zToken
+ * (if applicable), and the copies of the p->pLeft and p->pRight expressions,
+ * if any. Before returning, *pzBuffer is set to the first byte past the
+ * portion of the buffer copied into by this function.
+ * @param db SQL handle.
+ * @param p Root of expression's AST.
+ * @param dupFlags EXPRDUP_REDUCE or 0.
+ * @param pzBuffer If not NULL, then buffer to store duplicate.
+ */
+struct Expr *
+sql_expr_dup(struct sqlite3 *db, struct Expr *p, int flags, char **buffer);
+
+/**
+ * Free AST pointed by expr.
+ * @param db SQL handle.
+ * @param expr Root pointer of ASR
+ * @param extern_alloc True if skeleton was allocated externally.
+ */
+void
+sql_expr_free(struct sqlite3 *db, struct Expr *expr, bool extern_alloc);
+
 #if defined(__cplusplus)
 } /* extern "C" { */
 #endif
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 05a7cc9..edcdc31 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -285,7 +285,7 @@ freeIndex(sqlite3 * db, Index * p)
 #ifndef SQLITE_OMIT_ANALYZE
 	sqlite3DeleteIndexSamples(db, p);
 #endif
-	sqlite3ExprDelete(db, p->pPartIdxWhere);
+	sql_expr_free(db, p->pPartIdxWhere, false);
 	sqlite3ExprListDelete(db, p->aColExpr);
 	sqlite3DbFree(db, p->zColAff);
 	sqlite3_free(p->aiRowEst);
@@ -365,7 +365,7 @@ sqlite3DeleteColumnNames(sqlite3 * db, Table * pTable)
 	if ((pCol = pTable->aCol) != 0) {
 		for (i = 0; i < pTable->nCol; i++, pCol++) {
 			sqlite3DbFree(db, pCol->zName);
-			sqlite3ExprDelete(db, pCol->pDflt);
+			sql_expr_free(db, pCol->pDflt, false);
 			sqlite3DbFree(db, pCol->zColl);
 		}
 		sqlite3DbFree(db, pTable->aCol);
@@ -892,7 +892,7 @@ sqlite3AddDefaultValue(Parse * pParse, ExprSpan * pSpan)
 			 * is required by pragma table_info.
 			 */
 			Expr x;
-			sqlite3ExprDelete(db, pCol->pDflt);
+			sql_expr_free(db, pCol->pDflt, false);
 			memset(&x, 0, sizeof(x));
 			x.op = TK_SPAN;
 			x.u.zToken = sqlite3DbStrNDup(db, (char *)pSpan->zStart,
@@ -904,7 +904,7 @@ sqlite3AddDefaultValue(Parse * pParse, ExprSpan * pSpan)
 			sqlite3DbFree(db, x.u.zToken);
 		}
 	}
-	sqlite3ExprDelete(db, pSpan->pExpr);
+	sql_expr_free(db, pSpan->pExpr, false);
 }
 
 
@@ -1018,9 +1018,7 @@ sqlite3AddCheckConstraint(Parse * pParse,	/* Parsing context */
 		}
 	} else
 #endif
-	{
-		sqlite3ExprDelete(pParse->db, pCheckExpr);
-	}
+		sql_expr_free(pParse->db, pCheckExpr, false);
 }
 
 /*
@@ -3268,7 +3266,7 @@ sqlite3CreateIndex(Parse * pParse,	/* All information about this parse */
  exit_create_index:
 	if (pIndex)
 		freeIndex(db, pIndex);
-	sqlite3ExprDelete(db, pPIWhere);
+	sql_expr_free(db, pPIWhere, false);
 	sqlite3ExprListDelete(db, pList);
 	sqlite3SrcListDelete(db, pTblName);
 	sqlite3DbFree(db, zName);
@@ -3734,7 +3732,7 @@ sqlite3SrcListDelete(sqlite3 * db, SrcList * pList)
 			sqlite3ExprListDelete(db, pItem->u1.pFuncArg);
 		sqlite3DeleteTable(db, pItem->pTab);
 		sqlite3SelectDelete(db, pItem->pSelect);
-		sqlite3ExprDelete(db, pItem->pOn);
+		sql_expr_free(db, pItem->pOn, false);
 		sqlite3IdListDelete(db, pItem->pUsing);
 	}
 	sqlite3DbFree(db, pList);
@@ -3790,7 +3788,7 @@ sqlite3SrcListAppendFromTerm(Parse * pParse,	/* Parsing context */
 
  append_from_error:
 	assert(p == 0);
-	sqlite3ExprDelete(db, pOn);
+	sql_expr_free(db, pOn, false);
 	sqlite3IdListDelete(db, pUsing);
 	sqlite3SelectDelete(db, pSubquery);
 	return 0;
diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
index 2e09d92..7d1d715 100644
--- a/src/box/sql/delete.c
+++ b/src/box/sql/delete.c
@@ -212,10 +212,10 @@ sqlite3LimitWhere(Parse * pParse,	/* The parser context */
 	return pInClause;
 
  limit_where_cleanup:
-	sqlite3ExprDelete(pParse->db, pWhere);
+	sql_expr_free(pParse->db, pWhere);
 	sqlite3ExprListDelete(pParse->db, pOrderBy);
-	sqlite3ExprDelete(pParse->db, pLimit);
-	sqlite3ExprDelete(pParse->db, pOffset);
+	sql_expr_free(pParse->db, pLimit);
+	sql_expr_free(pParse->db, pOffset);
 	return 0;
 }
 #endif				/* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) */
@@ -571,7 +571,7 @@ sqlite3DeleteFrom(Parse * pParse,	/* The parser context */
 
  delete_from_cleanup:
 	sqlite3SrcListDelete(db, pTabList);
-	sqlite3ExprDelete(db, pWhere);
+	sql_expr_free(db, pWhere, false);
 	sqlite3DbFree(db, aToOpen);
 	return;
 }
@@ -636,9 +636,9 @@ sqlite3DeleteByKey(Parse *pParse, char *zTab, const char **columns,
 	return;
 
  error:
-	sqlite3ExprDelete(pParse->db, where);
+	sql_expr_free(pParse->db, where, false);
 	for (int i = 0; i < nPairs; ++i)
-		sqlite3ExprDelete(pParse->db, values[i]);
+		sql_expr_free(pParse->db, values[i], false);
 }
 
 /* Make sure "isView" and other macros defined above are undefined. Otherwise
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 89dcb23..5ae0c9c 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -492,7 +492,7 @@ sqlite3ExprForVectorField(Parse * pParse,	/* Parsing context */
 		 * pLeft->iTable:   First in an array of register holding result, or 0
 		 *                  if the result is not yet computed.
 		 *
-		 * sqlite3ExprDelete() specifically skips the recursive delete of
+		 * sql_expr_free() specifically skips the recursive delete of
 		 * pLeft on TK_SELECT_COLUMN nodes.  But pRight is followed, so pVector
 		 * can be attached to pRight to cause this node to take ownership of
 		 * pVector.  Typically there will be multiple TK_SELECT_COLUMN nodes
@@ -935,8 +935,8 @@ sqlite3ExprAttachSubtrees(sqlite3 * db,
 {
 	if (pRoot == 0) {
 		assert(db->mallocFailed);
-		sqlite3ExprDelete(db, pLeft);
-		sqlite3ExprDelete(db, pRight);
+		sql_expr_free(db, pLeft, false);
+		sql_expr_free(db, pRight, false);
 	} else {
 		if (pRight) {
 			pRoot->pRight = pRight;
@@ -1052,8 +1052,8 @@ sqlite3ExprAnd(sqlite3 * db, Expr * pLeft, Expr * pRight)
 	} else if (pRight == 0) {
 		return pLeft;
 	} else if (exprAlwaysFalse(pLeft) || exprAlwaysFalse(pRight)) {
-		sqlite3ExprDelete(db, pLeft);
-		sqlite3ExprDelete(db, pRight);
+		sql_expr_free(db, pLeft, false);
+		sql_expr_free(db, pRight, false);
 		return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0],
 					0);
 	} else {
@@ -1172,7 +1172,7 @@ sqlite3ExprAssignVarNumber(Parse * pParse, Expr * pExpr, u32 n)
  * Recursively delete an expression tree.
  */
 static SQLITE_NOINLINE void
-sqlite3ExprDeleteNN(sqlite3 * db, Expr * p)
+sqlite3ExprDeleteNN(sqlite3 * db, Expr * p, bool extern_alloc)
 {
 	assert(p != 0);
 	/* Sanity check: Assert that the IntValue is non-negative if it exists */
@@ -1187,9 +1187,10 @@ sqlite3ExprDeleteNN(sqlite3 * db, Expr * p)
 	if (!ExprHasProperty(p, (EP_TokenOnly | EP_Leaf))) {
 		/* The Expr.x union is never used at the same time as Expr.pRight */
 		assert(p->x.pList == 0 || p->pRight == 0);
-		if (p->pLeft && p->op != TK_SELECT_COLUMN)
-			sqlite3ExprDeleteNN(db, p->pLeft);
-		sqlite3ExprDelete(db, p->pRight);
+		if (p->pLeft && p->op != TK_SELECT_COLUMN && !extern_alloc)
+			sqlite3ExprDeleteNN(db, p->pLeft, extern_alloc);
+		if (!extern_alloc)
+			sql_expr_free(db, p->pRight, extern_alloc);
 		if (ExprHasProperty(p, EP_xIsSelect)) {
 			sqlite3SelectDelete(db, p->x.pSelect);
 		} else {
@@ -1204,10 +1205,10 @@ sqlite3ExprDeleteNN(sqlite3 * db, Expr * p)
 }
 
 void
-sqlite3ExprDelete(sqlite3 * db, Expr * p)
+sql_expr_free(sqlite3 *db, Expr *expr, bool extern_alloc)
 {
-	if (p)
-		sqlite3ExprDeleteNN(db, p);
+	if (expr != NULL)
+		sqlite3ExprDeleteNN(db, expr, extern_alloc);
 }
 
 /*
@@ -1298,61 +1299,39 @@ dupedExprNodeSize(Expr * p, int flags)
 	return ROUND8(nByte);
 }
 
-/*
- * Return the number of bytes required to create a duplicate of the
- * expression passed as the first argument. The second argument is a
- * mask containing EXPRDUP_XXX flags.
- *
- * The value returned includes space to create a copy of the Expr struct
- * itself and the buffer referred to by Expr.u.zToken, if any.
- *
- * If the EXPRDUP_REDUCE flag is set, then the return value includes
- * space to duplicate all Expr nodes in the tree formed by Expr.pLeft
- * and Expr.pRight variables (but not for any structures pointed to or
- * descended from the Expr.x.pList or Expr.x.pSelect variables).
- */
-static int
-dupedExprSize(Expr * p, int flags)
+int
+sql_expr_sizeof(struct Expr *p, int flags)
 {
-	int nByte = 0;
-	if (p) {
-		nByte = dupedExprNodeSize(p, flags);
+	int size = 0;
+	if (p != NULL) {
+		size = dupedExprNodeSize(p, flags);
 		if (flags & EXPRDUP_REDUCE) {
-			nByte +=
-			    dupedExprSize(p->pLeft,
-					  flags) + dupedExprSize(p->pRight,
-								 flags);
+			size +=
+			    sql_expr_sizeof(p->pLeft, flags) +
+			    sql_expr_sizeof(p->pRight, flags);
 		}
 	}
-	return nByte;
+	return size;
 }
 
-/*
- * This function is similar to sqlite3ExprDup(), except that if pzBuffer
- * is not NULL then *pzBuffer is assumed to point to a buffer large enough
- * to store the copy of expression p, the copies of p->u.zToken
- * (if applicable), and the copies of the p->pLeft and p->pRight expressions,
- * if any. Before returning, *pzBuffer is set to the first byte past the
- * portion of the buffer copied into by this function.
- */
-static Expr *
-exprDup(sqlite3 * db, Expr * p, int dupFlags, u8 ** pzBuffer)
+struct Expr *
+sql_expr_dup(struct sqlite3 *db, struct Expr *p, int flags, char **buffer)
 {
 	Expr *pNew;		/* Value to return */
-	u8 *zAlloc;		/* Memory space from which to build Expr object */
-	u32 staticFlag;		/* EP_Static if space not obtained from malloc */
+	u32 staticFlag;         /* EP_Static if space not obtained from malloc */
+	char *zAlloc;		/* Memory space from which to build Expr object */
 
 	assert(db != 0);
 	assert(p);
-	assert(dupFlags == 0 || dupFlags == EXPRDUP_REDUCE);
-	assert(pzBuffer == 0 || dupFlags == EXPRDUP_REDUCE);
+	assert(flags == 0 || flags == EXPRDUP_REDUCE);
 
 	/* Figure out where to write the new Expr structure. */
-	if (pzBuffer) {
-		zAlloc = *pzBuffer;
+	if (buffer) {
+		zAlloc = *buffer;
 		staticFlag = EP_Static;
 	} else {
-		zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, dupFlags));
+		zAlloc = sqlite3DbMallocRawNN(db,
+					      sql_expr_sizeof(p, flags));
 		staticFlag = 0;
 	}
 	pNew = (Expr *) zAlloc;
@@ -1363,15 +1342,14 @@ exprDup(sqlite3 * db, Expr * p, int dupFlags, u8 ** pzBuffer)
 		 * EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed
 		 * by the copy of the p->u.zToken string (if any).
 		 */
-		const unsigned nStructSize = dupedExprStructSize(p, dupFlags);
+		const unsigned nStructSize = dupedExprStructSize(p, flags);
 		const int nNewSize = nStructSize & 0xfff;
 		int nToken;
-		if (!ExprHasProperty(p, EP_IntValue) && p->u.zToken) {
+		if (!ExprHasProperty(p, EP_IntValue) && p->u.zToken)
 			nToken = sqlite3Strlen30(p->u.zToken) + 1;
-		} else {
+		else
 			nToken = 0;
-		}
-		if (dupFlags) {
+		if (flags) {
 			assert(ExprHasProperty(p, EP_Reduced) == 0);
 			memcpy(zAlloc, p, nNewSize);
 		} else {
@@ -1401,29 +1379,28 @@ exprDup(sqlite3 * db, Expr * p, int dupFlags, u8 ** pzBuffer)
 			if (ExprHasProperty(p, EP_xIsSelect)) {
 				pNew->x.pSelect =
 				    sqlite3SelectDup(db, p->x.pSelect,
-						     dupFlags);
+						     flags);
 			} else {
 				pNew->x.pList =
 				    sqlite3ExprListDup(db, p->x.pList,
-						       dupFlags);
+						       flags);
 			}
 		}
 
 		/* Fill in pNew->pLeft and pNew->pRight. */
 		if (ExprHasProperty(pNew, EP_Reduced | EP_TokenOnly)) {
-			zAlloc += dupedExprNodeSize(p, dupFlags);
+			zAlloc += dupedExprNodeSize(p, flags);
 			if (!ExprHasProperty(pNew, EP_TokenOnly | EP_Leaf)) {
 				pNew->pLeft = p->pLeft ?
-				    exprDup(db, p->pLeft, EXPRDUP_REDUCE,
-					    &zAlloc) : 0;
+				    sql_expr_dup(db, p->pLeft, EXPRDUP_REDUCE,
+						 &zAlloc) : 0;
 				pNew->pRight =
-				    p->pRight ? exprDup(db, p->pRight,
-							EXPRDUP_REDUCE,
-							&zAlloc) : 0;
-			}
-			if (pzBuffer) {
-				*pzBuffer = zAlloc;
+				    p->pRight ? sql_expr_dup(db, p->pRight,
+							     EXPRDUP_REDUCE,
+							     &zAlloc) : 0;
 			}
+			if (buffer)
+				*buffer = zAlloc;
 		} else {
 			if (!ExprHasProperty(p, EP_TokenOnly | EP_Leaf)) {
 				if (pNew->op == TK_SELECT_COLUMN) {
@@ -1496,7 +1473,7 @@ Expr *
 sqlite3ExprDup(sqlite3 * db, Expr * p, int flags)
 {
 	assert(flags == 0 || flags == EXPRDUP_REDUCE);
-	return p ? exprDup(db, p, flags, 0) : 0;
+	return p ? sql_expr_dup(db, p, flags, 0) : 0;
 }
 
 ExprList *
@@ -1726,7 +1703,7 @@ sqlite3ExprListAppend(Parse * pParse,	/* Parsing context */
 
  no_mem:
 	/* Avoid leaking memory if malloc has failed. */
-	sqlite3ExprDelete(db, pExpr);
+	sql_expr_free(db, pExpr, false);
 	sqlite3ExprListDelete(db, pList);
 	return 0;
 }
@@ -1802,7 +1779,7 @@ sqlite3ExprListAppendVector(Parse * pParse,	/* Parsing context */
 	}
 
  vector_append_error:
-	sqlite3ExprDelete(db, pExpr);
+	sql_expr_free(db, pExpr, false);
 	sqlite3IdListDelete(db, pColumns);
 	return pList;
 }
@@ -1908,7 +1885,7 @@ exprListDeleteNN(sqlite3 * db, ExprList * pList)
 	struct ExprList_item *pItem;
 	assert(pList->a != 0 || pList->nExpr == 0);
 	for (pItem = pList->a, i = 0; i < pList->nExpr; i++, pItem++) {
-		sqlite3ExprDelete(db, pItem->pExpr);
+		sql_expr_free(db, pItem->pExpr, false);
 		sqlite3DbFree(db, pItem->zName);
 		sqlite3DbFree(db, pItem->zSpan);
 	}
@@ -2991,7 +2968,7 @@ sqlite3CodeSubselect(Parse * pParse,	/* Parsing context */
 						  dest.iSDParm);
 				VdbeComment((v, "Init EXISTS result"));
 			}
-			sqlite3ExprDelete(pParse->db, pSel->pLimit);
+			sql_expr_free(pParse->db, pSel->pLimit, false);
 			pSel->pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER,
 							&sqlite3IntTokens[1],
 							0);
@@ -4597,7 +4574,7 @@ sqlite3ExprCodeCopy(Parse * pParse, Expr * pExpr, int target)
 	pExpr = sqlite3ExprDup(db, pExpr, 0);
 	if (!db->mallocFailed)
 		sqlite3ExprCode(pParse, pExpr, target);
-	sqlite3ExprDelete(db, pExpr);
+	sql_expr_free(db, pExpr, false);
 }
 
 /*
@@ -5157,7 +5134,7 @@ sqlite3ExprIfFalseDup(Parse * pParse, Expr * pExpr, int dest, int jumpIfNull)
 	if (db->mallocFailed == 0) {
 		sqlite3ExprIfFalse(pParse, pCopy, dest, jumpIfNull);
 	}
-	sqlite3ExprDelete(db, pCopy);
+	sql_expr_free(db, pCopy, false);
 }
 
 /*
diff --git a/src/box/sql/fkey.c b/src/box/sql/fkey.c
index 9286f4c..aedfe94 100644
--- a/src/box/sql/fkey.c
+++ b/src/box/sql/fkey.c
@@ -698,10 +698,9 @@ fkScanChildren(Parse * pParse,	/* Parse context */
 	}
 
 	/* Clean up the WHERE clause constructed above. */
-	sqlite3ExprDelete(db, pWhere);
-	if (iFkIfZero) {
+	sql_expr_free(db, pWhere, false);
+	if (iFkIfZero)
 		sqlite3VdbeJumpHere(v, iFkIfZero);
-	}
 }
 
 /*
@@ -737,10 +736,10 @@ fkTriggerDelete(sqlite3 * dbMem, Trigger * p)
 {
 	if (p) {
 		TriggerStep *pStep = p->step_list;
-		sqlite3ExprDelete(dbMem, pStep->pWhere);
+		sql_expr_free(dbMem, pStep->pWhere, false);
 		sqlite3ExprListDelete(dbMem, pStep->pExprList);
 		sqlite3SelectDelete(dbMem, pStep->pSelect);
-		sqlite3ExprDelete(dbMem, p->pWhen);
+		sql_expr_free(dbMem, p->pWhen, false);
 		sqlite3DbFree(dbMem, p);
 	}
 }
@@ -1424,8 +1423,8 @@ fkActionTrigger(Parse * pParse,	/* Parse context */
 		/* Re-enable the lookaside buffer, if it was disabled earlier. */
 		db->lookaside.bDisable--;
 
-		sqlite3ExprDelete(db, pWhere);
-		sqlite3ExprDelete(db, pWhen);
+		sql_expr_free(db, pWhere, false);
+		sql_expr_free(db, pWhen, false);
 		sqlite3ExprListDelete(db, pList);
 		sqlite3SelectDelete(db, pSelect);
 		if (db->mallocFailed == 1) {
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 42254dd..5336e89 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -33,8 +33,9 @@
  * This file contains C code routines that are called by the parser
  * to handle INSERT statements in SQLite.
  */
-#include "sqliteInt.h"
 #include "box/session.h"
+#include "sqliteInt.h"
+#include "tarantoolInt.h"
 
 /*
  * Generate code that will open pTab as cursor iCur.
@@ -340,6 +341,7 @@ sqlite3Insert(Parse * pParse,	/* Parser context */
 	int regTupleid;		/* registers holding insert tupleid */
 	int regData;		/* register holding first column to insert */
 	int *aRegIdx = 0;	/* One register allocated to each index */
+	uint32_t space_id = 0;
 
 #ifndef SQLITE_OMIT_TRIGGER
 	int isView;		/* True if attempting to insert into a view */
@@ -376,6 +378,8 @@ sqlite3Insert(Parse * pParse,	/* Parser context */
 		goto insert_cleanup;
 	}
 
+	space_id = SQLITE_PAGENO_TO_SPACEID(pTab->tnum);
+
 	/* Figure out if we have any triggers and if the table being
 	 * inserted into is a view
 	 */
@@ -671,13 +675,18 @@ sqlite3Insert(Parse * pParse,	/* Parser context */
 			}
 			if ((!useTempTable && !pList)
 			    || (pColumn && j >= pColumn->nId)) {
-				if (i == pTab->iAutoIncPKey)
+				if (i == pTab->iAutoIncPKey) {
 					sqlite3VdbeAddOp2(v, OP_Integer, -1,
 							  regCols + i + 1);
-				else
+				} else {
+					struct Expr *dflt = NULL;
+					dflt = space_column_default_expr(
+						space_id,
+						i);
 					sqlite3ExprCode(pParse,
-							pTab->aCol[i].pDflt,
+							dflt,
 							regCols + i + 1);
+				}
 			} else if (useTempTable) {
 				sqlite3VdbeAddOp3(v, OP_Column, srcTab, j,
 						  regCols + i + 1);
@@ -748,8 +757,12 @@ sqlite3Insert(Parse * pParse,	/* Parser context */
 							  iRegStore);
 					continue;
 				}
+				struct Expr *dflt = NULL;
+				dflt = space_column_default_expr(
+					space_id,
+					i);
 				sqlite3ExprCodeFactorable(pParse,
-							  pTab->aCol[i].pDflt,
+							  dflt,
 							  iRegStore);
 			} else if (useTempTable) {
 				if ((pTab->tabFlags & TF_Autoincrement)
@@ -1106,10 +1119,13 @@ sqlite3GenerateConstraintChecks(Parse * pParse,		/* The parser context */
 		} else if (onError == ON_CONFLICT_ACTION_DEFAULT) {
 			onError = ON_CONFLICT_ACTION_ABORT;
 		}
-		if (onError == ON_CONFLICT_ACTION_REPLACE
-		    && pTab->aCol[i].pDflt == 0) {
+		struct Expr *dflt = NULL;
+		dflt = space_column_default_expr(
+			SQLITE_PAGENO_TO_SPACEID(pTab->tnum),
+			i);
+		if (onError == ON_CONFLICT_ACTION_REPLACE && dflt == 0)
 			onError = ON_CONFLICT_ACTION_ABORT;
-		}
+
 		assert(onError == ON_CONFLICT_ACTION_ROLLBACK
 		       || onError == ON_CONFLICT_ACTION_ABORT
 		       || onError == ON_CONFLICT_ACTION_FAIL
@@ -1145,7 +1161,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse,		/* The parser context */
 				    sqlite3VdbeAddOp1(v, OP_NotNull,
 						      regNewData + 1 + i);
 				VdbeCoverage(v);
-				sqlite3ExprCode(pParse, pTab->aCol[i].pDflt,
+				sqlite3ExprCode(pParse, dflt,
 						regNewData + 1 + i);
 				sqlite3VdbeJumpHere(v, addr1);
 				break;
diff --git a/src/box/sql/main.c b/src/box/sql/main.c
index 1881e93..b77348c 100644
--- a/src/box/sql/main.c
+++ b/src/box/sql/main.c
@@ -2058,21 +2058,6 @@ sql_init_db(sqlite3 **out_db)
 	setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside,
 		       sqlite3GlobalConfig.nLookaside);
 
-	if (rc == SQLITE_OK) {
-		struct session *user_session = current_session();
-		int commit_internal = !(user_session->sql_flags
-					& SQLITE_InternChanges);
-
-		assert(db->init.busy == 0);
-		db->init.busy = 1;
-		db->pSchema = sqlite3SchemaCreate(db);
-		rc = sqlite3InitDatabase(db);
-		if (rc != SQLITE_OK)
-			sqlite3SchemaClear(db);
-		db->init.busy = 0;
-		if (rc == SQLITE_OK && commit_internal)
-			sqlite3CommitInternalChanges();
-	}
 opendb_out:
 	rc = sqlite3_errcode(db);
 	assert(db != 0 || rc == SQLITE_NOMEM);
diff --git a/src/box/sql/parse.c b/src/box/sql/parse.c
index 17ce309..9f547d2 100644
--- a/src/box/sql/parse.c
+++ b/src/box/sql/parse.c
@@ -81,7 +81,7 @@ static void disableLookaside(Parse *pParse){
   pParse->db->lookaside.bDisable++;
 }
 
-#line 392 "parse.y"
+#line 398 "parse.y"
 
   /*
   ** For a compound SELECT statement, make sure p->pPrior->pNext==p for
@@ -104,7 +104,7 @@ static void disableLookaside(Parse *pParse){
       }
     }
   }
-#line 831 "parse.y"
+#line 837 "parse.y"
 
   /* This is a utility routine used to set the ExprSpan.zStart and
   ** ExprSpan.zEnd values of pOut so that the span covers the complete
@@ -140,7 +140,7 @@ static void disableLookaside(Parse *pParse){
     pOut->zStart = t.z;
     pOut->zEnd = &t.z[t.n];
   }
-#line 939 "parse.y"
+#line 945 "parse.y"
 
   /* This routine constructs a binary expression node out of two ExprSpan
   ** objects and uses the result to populate a new ExprSpan object.
@@ -163,7 +163,7 @@ static void disableLookaside(Parse *pParse){
       pSpan->pExpr = sqlite3PExpr(pParse, TK_NOT, pSpan->pExpr, 0);
     }
   }
-#line 1013 "parse.y"
+#line 1019 "parse.y"
 
   /* Construct an expression node for a unary postfix operator
   */
@@ -176,7 +176,7 @@ static void disableLookaside(Parse *pParse){
     pOperand->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0);
     pOperand->zEnd = &pPostOp->z[pPostOp->n];
   }                           
-#line 1030 "parse.y"
+#line 1036 "parse.y"
 
   /* A routine to convert a binary TK_IS or TK_ISNOT expression into a
   ** unary TK_ISNULL or TK_NOTNULL expression. */
@@ -184,11 +184,11 @@ static void disableLookaside(Parse *pParse){
     sqlite3 *db = pParse->db;
     if( pA && pY && pY->op==TK_NULL ){
       pA->op = (u8)op;
-      sqlite3ExprDelete(db, pA->pRight);
+      sql_expr_free(db, pA->pRight, false);
       pA->pRight = 0;
     }
   }
-#line 1058 "parse.y"
+#line 1064 "parse.y"
 
   /* Construct an expression node for a unary prefix operator
   */
@@ -203,7 +203,7 @@ static void disableLookaside(Parse *pParse){
     pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0);
     pOut->zEnd = pOperand->zEnd;
   }
-#line 1263 "parse.y"
+#line 1269 "parse.y"
 
   /* Add a single new term to an ExprList that is used to store a
   ** list of identifiers.  Report an error if the ID list contains
@@ -1468,7 +1468,7 @@ static void yy_destructor(
     case 183: /* oneselect */
     case 194: /* values */
 {
-#line 386 "parse.y"
+#line 392 "parse.y"
 sqlite3SelectDelete(pParse->db, (yypminor->yy279));
 #line 1474 "parse.c"
 }
@@ -1476,8 +1476,8 @@ sqlite3SelectDelete(pParse->db, (yypminor->yy279));
     case 160: /* term */
     case 161: /* expr */
 {
-#line 829 "parse.y"
-sqlite3ExprDelete(pParse->db, (yypminor->yy162).pExpr);
+#line 835 "parse.y"
+sql_expr_free(pParse->db, (yypminor->yy162).pExpr, false);
 #line 1482 "parse.c"
 }
       break;
@@ -1494,7 +1494,7 @@ sqlite3ExprDelete(pParse->db, (yypminor->yy162).pExpr);
     case 213: /* paren_exprlist */
     case 215: /* case_exprlist */
 {
-#line 1261 "parse.y"
+#line 1267 "parse.y"
 sqlite3ExprListDelete(pParse->db, (yypminor->yy382));
 #line 1500 "parse.c"
 }
@@ -1504,7 +1504,7 @@ sqlite3ExprListDelete(pParse->db, (yypminor->yy382));
     case 199: /* seltablist */
     case 200: /* stl_prefix */
 {
-#line 613 "parse.y"
+#line 619 "parse.y"
 sqlite3SrcListDelete(pParse->db, (yypminor->yy387));
 #line 1510 "parse.c"
 }
@@ -1512,7 +1512,7 @@ sqlite3SrcListDelete(pParse->db, (yypminor->yy387));
     case 184: /* with */
     case 229: /* wqlist */
 {
-#line 1511 "parse.y"
+#line 1517 "parse.y"
 sqlite3WithDelete(pParse->db, (yypminor->yy151));
 #line 1518 "parse.c"
 }
@@ -1524,8 +1524,8 @@ sqlite3WithDelete(pParse->db, (yypminor->yy151));
     case 216: /* case_else */
     case 225: /* when_clause */
 {
-#line 738 "parse.y"
-sqlite3ExprDelete(pParse->db, (yypminor->yy362));
+#line 744 "parse.y"
+sql_expr_free(pParse->db, (yypminor->yy362), false);
 #line 1530 "parse.c"
 }
       break;
@@ -1533,7 +1533,7 @@ sqlite3ExprDelete(pParse->db, (yypminor->yy362));
     case 206: /* idlist */
     case 209: /* idlist_opt */
 {
-#line 650 "parse.y"
+#line 656 "parse.y"
 sqlite3IdListDelete(pParse->db, (yypminor->yy40));
 #line 1539 "parse.c"
 }
@@ -1541,14 +1541,14 @@ sqlite3IdListDelete(pParse->db, (yypminor->yy40));
     case 221: /* trigger_cmd_list */
     case 226: /* trigger_cmd */
 {
-#line 1385 "parse.y"
+#line 1391 "parse.y"
 sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy427));
 #line 1547 "parse.c"
 }
       break;
     case 223: /* trigger_event */
 {
-#line 1371 "parse.y"
+#line 1377 "parse.y"
 sqlite3IdListDelete(pParse->db, (yypminor->yy10).b);
 #line 1554 "parse.c"
 }
@@ -2164,84 +2164,87 @@ static void yy_reduce(
         YYMINORTYPE yylhsminor;
       case 0: /* ecmd ::= explain cmdx SEMI */
 #line 111 "parse.y"
-{ sqlite3FinishCoding(pParse); }
-#line 2169 "parse.c"
+{
+	if (!pParse->parse_only)
+		sqlite3FinishCoding(pParse);
+}
+#line 2172 "parse.c"
         break;
       case 1: /* ecmd ::= SEMI */
-#line 112 "parse.y"
+#line 115 "parse.y"
 {
   sqlite3ErrorMsg(pParse, "syntax error: empty request");
 }
-#line 2176 "parse.c"
+#line 2179 "parse.c"
         break;
       case 2: /* explain ::= EXPLAIN */
-#line 117 "parse.y"
+#line 120 "parse.y"
 { pParse->explain = 1; }
-#line 2181 "parse.c"
+#line 2184 "parse.c"
         break;
       case 3: /* explain ::= EXPLAIN QUERY PLAN */
-#line 118 "parse.y"
+#line 121 "parse.y"
 { pParse->explain = 2; }
-#line 2186 "parse.c"
+#line 2189 "parse.c"
         break;
       case 4: /* cmd ::= BEGIN transtype trans_opt */
-#line 150 "parse.y"
+#line 153 "parse.y"
 {sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy52);}
-#line 2191 "parse.c"
+#line 2194 "parse.c"
         break;
       case 5: /* transtype ::= */
-#line 155 "parse.y"
+#line 158 "parse.y"
 {yymsp[1].minor.yy52 = TK_DEFERRED;}
-#line 2196 "parse.c"
+#line 2199 "parse.c"
         break;
       case 6: /* transtype ::= DEFERRED */
-#line 156 "parse.y"
+#line 159 "parse.y"
 {yymsp[0].minor.yy52 = yymsp[0].major; /*A-overwrites-X*/}
-#line 2201 "parse.c"
+#line 2204 "parse.c"
         break;
       case 7: /* cmd ::= COMMIT trans_opt */
       case 8: /* cmd ::= END trans_opt */ yytestcase(yyruleno==8);
-#line 157 "parse.y"
+#line 160 "parse.y"
 {sqlite3CommitTransaction(pParse);}
-#line 2207 "parse.c"
+#line 2210 "parse.c"
         break;
       case 9: /* cmd ::= ROLLBACK trans_opt */
-#line 159 "parse.y"
+#line 162 "parse.y"
 {sqlite3RollbackTransaction(pParse);}
-#line 2212 "parse.c"
+#line 2215 "parse.c"
         break;
       case 10: /* cmd ::= SAVEPOINT nm */
-#line 163 "parse.y"
+#line 166 "parse.y"
 {
   sqlite3Savepoint(pParse, SAVEPOINT_BEGIN, &yymsp[0].minor.yy0);
 }
-#line 2219 "parse.c"
+#line 2222 "parse.c"
         break;
       case 11: /* cmd ::= RELEASE savepoint_opt nm */
-#line 166 "parse.y"
+#line 169 "parse.y"
 {
   sqlite3Savepoint(pParse, SAVEPOINT_RELEASE, &yymsp[0].minor.yy0);
 }
-#line 2226 "parse.c"
+#line 2229 "parse.c"
         break;
       case 12: /* cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
-#line 169 "parse.y"
+#line 172 "parse.y"
 {
   sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &yymsp[0].minor.yy0);
 }
-#line 2233 "parse.c"
+#line 2236 "parse.c"
         break;
       case 13: /* create_table ::= createkw TABLE ifnotexists nm */
-#line 176 "parse.y"
+#line 179 "parse.y"
 {
    sqlite3StartTable(pParse,&yymsp[0].minor.yy0,yymsp[-1].minor.yy52);
 }
-#line 2240 "parse.c"
+#line 2243 "parse.c"
         break;
       case 14: /* createkw ::= CREATE */
-#line 179 "parse.y"
+#line 182 "parse.y"
 {disableLookaside(pParse);}
-#line 2245 "parse.c"
+#line 2248 "parse.c"
         break;
       case 15: /* ifnotexists ::= */
       case 38: /* autoinc ::= */ yytestcase(yyruleno==38);
@@ -2250,89 +2253,89 @@ static void yy_reduce(
       case 72: /* ifexists ::= */ yytestcase(yyruleno==72);
       case 86: /* distinct ::= */ yytestcase(yyruleno==86);
       case 208: /* collate ::= */ yytestcase(yyruleno==208);
-#line 182 "parse.y"
+#line 185 "parse.y"
 {yymsp[1].minor.yy52 = 0;}
-#line 2256 "parse.c"
+#line 2259 "parse.c"
         break;
       case 16: /* ifnotexists ::= IF NOT EXISTS */
-#line 183 "parse.y"
+#line 186 "parse.y"
 {yymsp[-2].minor.yy52 = 1;}
-#line 2261 "parse.c"
+#line 2264 "parse.c"
         break;
       case 17: /* create_table_args ::= LP columnlist conslist_opt RP */
-#line 185 "parse.y"
+#line 188 "parse.y"
 {
   sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0);
 }
-#line 2268 "parse.c"
+#line 2271 "parse.c"
         break;
       case 18: /* create_table_args ::= AS select */
-#line 188 "parse.y"
+#line 191 "parse.y"
 {
   sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy279);
   sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy279);
 }
-#line 2276 "parse.c"
+#line 2279 "parse.c"
         break;
       case 19: /* columnname ::= nm typetoken */
-#line 194 "parse.y"
+#line 197 "parse.y"
 {sqlite3AddColumn(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
-#line 2281 "parse.c"
+#line 2284 "parse.c"
         break;
       case 20: /* nm ::= ID|INDEXED */
-#line 225 "parse.y"
+#line 228 "parse.y"
 {
   if(yymsp[0].minor.yy0.isReserved) {
     sqlite3ErrorMsg(pParse, "keyword \"%T\" is reserved", &yymsp[0].minor.yy0);
   }
 }
-#line 2290 "parse.c"
+#line 2293 "parse.c"
         break;
       case 21: /* typetoken ::= */
       case 56: /* conslist_opt ::= */ yytestcase(yyruleno==56);
       case 92: /* as ::= */ yytestcase(yyruleno==92);
-#line 236 "parse.y"
+#line 239 "parse.y"
 {yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;}
-#line 2297 "parse.c"
+#line 2300 "parse.c"
         break;
       case 22: /* typetoken ::= typename LP signed RP */
-#line 238 "parse.y"
+#line 241 "parse.y"
 {
   yymsp[-3].minor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy0.z);
 }
-#line 2304 "parse.c"
+#line 2307 "parse.c"
         break;
       case 23: /* typetoken ::= typename LP signed COMMA signed RP */
-#line 241 "parse.y"
+#line 244 "parse.y"
 {
   yymsp[-5].minor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy0.z);
 }
-#line 2311 "parse.c"
+#line 2314 "parse.c"
         break;
       case 24: /* typename ::= typename ID|STRING */
-#line 246 "parse.y"
+#line 249 "parse.y"
 {yymsp[-1].minor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);}
-#line 2316 "parse.c"
+#line 2319 "parse.c"
         break;
       case 25: /* ccons ::= CONSTRAINT nm */
       case 58: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==58);
-#line 255 "parse.y"
+#line 258 "parse.y"
 {pParse->constraintName = yymsp[0].minor.yy0;}
-#line 2322 "parse.c"
+#line 2325 "parse.c"
         break;
       case 26: /* ccons ::= DEFAULT term */
       case 28: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==28);
-#line 256 "parse.y"
+#line 259 "parse.y"
 {sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy162);}
-#line 2328 "parse.c"
+#line 2331 "parse.c"
         break;
       case 27: /* ccons ::= DEFAULT LP expr RP */
-#line 257 "parse.y"
+#line 260 "parse.y"
 {sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy162);}
-#line 2333 "parse.c"
+#line 2336 "parse.c"
         break;
       case 29: /* ccons ::= DEFAULT MINUS term */
-#line 259 "parse.y"
+#line 262 "parse.y"
 {
   ExprSpan v;
   v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy162.pExpr, 0);
@@ -2340,222 +2343,225 @@ static void yy_reduce(
   v.zEnd = yymsp[0].minor.yy162.zEnd;
   sqlite3AddDefaultValue(pParse,&v);
 }
-#line 2344 "parse.c"
+#line 2347 "parse.c"
         break;
       case 30: /* ccons ::= DEFAULT ID|INDEXED */
-#line 266 "parse.y"
+#line 269 "parse.y"
 {
   ExprSpan v;
   spanExpr(&v, pParse, TK_STRING, yymsp[0].minor.yy0);
   sqlite3AddDefaultValue(pParse,&v);
 }
-#line 2353 "parse.c"
+#line 2356 "parse.c"
         break;
       case 31: /* ccons ::= NOT NULL onconf */
-#line 276 "parse.y"
+#line 279 "parse.y"
 {sqlite3AddNotNull(pParse, yymsp[0].minor.yy52);}
-#line 2358 "parse.c"
+#line 2361 "parse.c"
         break;
       case 32: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
-#line 278 "parse.y"
+#line 281 "parse.y"
 {sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy52,yymsp[0].minor.yy52,yymsp[-2].minor.yy52);}
-#line 2363 "parse.c"
+#line 2366 "parse.c"
         break;
       case 33: /* ccons ::= UNIQUE onconf */
-#line 279 "parse.y"
+#line 282 "parse.y"
 {sqlite3CreateIndex(pParse,0,0,0,yymsp[0].minor.yy52,0,0,0,0,
                                    SQLITE_IDXTYPE_UNIQUE);}
-#line 2369 "parse.c"
+#line 2372 "parse.c"
         break;
       case 34: /* ccons ::= CHECK LP expr RP */
-#line 281 "parse.y"
+#line 284 "parse.y"
 {sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy162.pExpr);}
-#line 2374 "parse.c"
+#line 2377 "parse.c"
         break;
       case 35: /* ccons ::= REFERENCES nm eidlist_opt refargs */
-#line 283 "parse.y"
+#line 286 "parse.y"
 {sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy382,yymsp[0].minor.yy52);}
-#line 2379 "parse.c"
+#line 2382 "parse.c"
         break;
       case 36: /* ccons ::= defer_subclause */
-#line 284 "parse.y"
+#line 287 "parse.y"
 {sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy52);}
-#line 2384 "parse.c"
+#line 2387 "parse.c"
         break;
       case 37: /* ccons ::= COLLATE ID|INDEXED */
-#line 285 "parse.y"
+#line 288 "parse.y"
 {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
-#line 2389 "parse.c"
+#line 2392 "parse.c"
         break;
       case 39: /* autoinc ::= AUTOINCR */
-#line 290 "parse.y"
+#line 293 "parse.y"
 {yymsp[0].minor.yy52 = 1;}
-#line 2394 "parse.c"
+#line 2397 "parse.c"
         break;
       case 40: /* refargs ::= */
-#line 298 "parse.y"
+#line 301 "parse.y"
 { yymsp[1].minor.yy52 = ON_CONFLICT_ACTION_NONE*0x0101; /* EV: R-19803-45884 */}
-#line 2399 "parse.c"
+#line 2402 "parse.c"
         break;
       case 41: /* refargs ::= refargs refarg */
-#line 299 "parse.y"
+#line 302 "parse.y"
 { yymsp[-1].minor.yy52 = (yymsp[-1].minor.yy52 & ~yymsp[0].minor.yy107.mask) | yymsp[0].minor.yy107.value; }
-#line 2404 "parse.c"
+#line 2407 "parse.c"
         break;
       case 42: /* refarg ::= MATCH nm */
-#line 301 "parse.y"
+#line 304 "parse.y"
 { yymsp[-1].minor.yy107.value = 0;     yymsp[-1].minor.yy107.mask = 0x000000; }
-#line 2409 "parse.c"
+#line 2412 "parse.c"
         break;
       case 43: /* refarg ::= ON INSERT refact */
-#line 302 "parse.y"
+#line 305 "parse.y"
 { yymsp[-2].minor.yy107.value = 0;     yymsp[-2].minor.yy107.mask = 0x000000; }
-#line 2414 "parse.c"
+#line 2417 "parse.c"
         break;
       case 44: /* refarg ::= ON DELETE refact */
-#line 303 "parse.y"
+#line 306 "parse.y"
 { yymsp[-2].minor.yy107.value = yymsp[0].minor.yy52;     yymsp[-2].minor.yy107.mask = 0x0000ff; }
-#line 2419 "parse.c"
+#line 2422 "parse.c"
         break;
       case 45: /* refarg ::= ON UPDATE refact */
-#line 304 "parse.y"
+#line 307 "parse.y"
 { yymsp[-2].minor.yy107.value = yymsp[0].minor.yy52<<8;  yymsp[-2].minor.yy107.mask = 0x00ff00; }
-#line 2424 "parse.c"
+#line 2427 "parse.c"
         break;
       case 46: /* refact ::= SET NULL */
-#line 306 "parse.y"
+#line 309 "parse.y"
 { yymsp[-1].minor.yy52 = OE_SetNull;  /* EV: R-33326-45252 */}
-#line 2429 "parse.c"
+#line 2432 "parse.c"
         break;
       case 47: /* refact ::= SET DEFAULT */
-#line 307 "parse.y"
+#line 310 "parse.y"
 { yymsp[-1].minor.yy52 = OE_SetDflt;  /* EV: R-33326-45252 */}
-#line 2434 "parse.c"
+#line 2437 "parse.c"
         break;
       case 48: /* refact ::= CASCADE */
-#line 308 "parse.y"
+#line 311 "parse.y"
 { yymsp[0].minor.yy52 = OE_Cascade;  /* EV: R-33326-45252 */}
-#line 2439 "parse.c"
+#line 2442 "parse.c"
         break;
       case 49: /* refact ::= RESTRICT */
-#line 309 "parse.y"
+#line 312 "parse.y"
 { yymsp[0].minor.yy52 = OE_Restrict; /* EV: R-33326-45252 */}
-#line 2444 "parse.c"
+#line 2447 "parse.c"
         break;
       case 50: /* refact ::= NO ACTION */
-#line 310 "parse.y"
+#line 313 "parse.y"
 { yymsp[-1].minor.yy52 = ON_CONFLICT_ACTION_NONE;     /* EV: R-33326-45252 */}
-#line 2449 "parse.c"
+#line 2452 "parse.c"
         break;
       case 51: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
-#line 312 "parse.y"
+#line 315 "parse.y"
 {yymsp[-2].minor.yy52 = 0;}
-#line 2454 "parse.c"
+#line 2457 "parse.c"
         break;
       case 52: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
       case 67: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==67);
       case 138: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==138);
-#line 313 "parse.y"
+#line 316 "parse.y"
 {yymsp[-1].minor.yy52 = yymsp[0].minor.yy52;}
-#line 2461 "parse.c"
+#line 2464 "parse.c"
         break;
       case 54: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
       case 71: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==71);
       case 180: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==180);
       case 183: /* in_op ::= NOT IN */ yytestcase(yyruleno==183);
       case 209: /* collate ::= COLLATE ID|INDEXED */ yytestcase(yyruleno==209);
-#line 316 "parse.y"
+#line 319 "parse.y"
 {yymsp[-1].minor.yy52 = 1;}
-#line 2470 "parse.c"
+#line 2473 "parse.c"
         break;
       case 55: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
-#line 317 "parse.y"
+#line 320 "parse.y"
 {yymsp[-1].minor.yy52 = 0;}
-#line 2475 "parse.c"
+#line 2478 "parse.c"
         break;
       case 57: /* tconscomma ::= COMMA */
-#line 323 "parse.y"
+#line 326 "parse.y"
 {pParse->constraintName.n = 0;}
-#line 2480 "parse.c"
+#line 2483 "parse.c"
         break;
       case 59: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
-#line 327 "parse.y"
+#line 330 "parse.y"
 {sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy382,yymsp[0].minor.yy52,yymsp[-2].minor.yy52,0);}
-#line 2485 "parse.c"
+#line 2488 "parse.c"
         break;
       case 60: /* tcons ::= UNIQUE LP sortlist RP onconf */
-#line 329 "parse.y"
+#line 332 "parse.y"
 {sqlite3CreateIndex(pParse,0,0,yymsp[-2].minor.yy382,yymsp[0].minor.yy52,0,0,0,0,
                                        SQLITE_IDXTYPE_UNIQUE);}
-#line 2491 "parse.c"
+#line 2494 "parse.c"
         break;
       case 61: /* tcons ::= CHECK LP expr RP onconf */
-#line 332 "parse.y"
+#line 335 "parse.y"
 {sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy162.pExpr);}
-#line 2496 "parse.c"
+#line 2499 "parse.c"
         break;
       case 62: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
-#line 334 "parse.y"
+#line 337 "parse.y"
 {
     sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy382, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy382, yymsp[-1].minor.yy52);
     sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy52);
 }
-#line 2504 "parse.c"
+#line 2507 "parse.c"
         break;
       case 64: /* onconf ::= */
       case 66: /* orconf ::= */ yytestcase(yyruleno==66);
-#line 348 "parse.y"
+#line 351 "parse.y"
 {yymsp[1].minor.yy52 = ON_CONFLICT_ACTION_DEFAULT;}
-#line 2510 "parse.c"
+#line 2513 "parse.c"
         break;
       case 65: /* onconf ::= ON CONFLICT resolvetype */
-#line 349 "parse.y"
+#line 352 "parse.y"
 {yymsp[-2].minor.yy52 = yymsp[0].minor.yy52;}
-#line 2515 "parse.c"
+#line 2518 "parse.c"
         break;
       case 68: /* resolvetype ::= IGNORE */
-#line 353 "parse.y"
+#line 356 "parse.y"
 {yymsp[0].minor.yy52 = ON_CONFLICT_ACTION_IGNORE;}
-#line 2520 "parse.c"
+#line 2523 "parse.c"
         break;
       case 69: /* resolvetype ::= REPLACE */
       case 139: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==139);
-#line 354 "parse.y"
+#line 357 "parse.y"
 {yymsp[0].minor.yy52 = ON_CONFLICT_ACTION_REPLACE;}
-#line 2526 "parse.c"
+#line 2529 "parse.c"
         break;
       case 70: /* cmd ::= DROP TABLE ifexists fullname */
-#line 358 "parse.y"
+#line 361 "parse.y"
 {
   sqlite3DropTable(pParse, yymsp[0].minor.yy387, 0, yymsp[-1].minor.yy52);
 }
-#line 2533 "parse.c"
+#line 2536 "parse.c"
         break;
       case 73: /* cmd ::= createkw VIEW ifnotexists nm eidlist_opt AS select */
-#line 369 "parse.y"
+#line 372 "parse.y"
 {
   sqlite3CreateView(pParse, &yymsp[-6].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy382, yymsp[0].minor.yy279, yymsp[-4].minor.yy52);
 }
-#line 2540 "parse.c"
+#line 2543 "parse.c"
         break;
       case 74: /* cmd ::= DROP VIEW ifexists fullname */
-#line 372 "parse.y"
+#line 375 "parse.y"
 {
   sqlite3DropTable(pParse, yymsp[0].minor.yy387, 1, yymsp[-1].minor.yy52);
 }
-#line 2547 "parse.c"
+#line 2550 "parse.c"
         break;
       case 75: /* cmd ::= select */
-#line 379 "parse.y"
+#line 382 "parse.y"
 {
   SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
-  sqlite3Select(pParse, yymsp[0].minor.yy279, &dest);
+  if(!pParse->parse_only)
+	  sqlite3Select(pParse, yymsp[0].minor.yy279, &dest);
+  else
+	  sql_expr_extract_select(pParse, yymsp[0].minor.yy279);
   sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy279);
 }
-#line 2556 "parse.c"
+#line 2562 "parse.c"
         break;
       case 76: /* select ::= with selectnowith */
-#line 416 "parse.y"
+#line 422 "parse.y"
 {
   Select *p = yymsp[0].minor.yy279;
   if( p ){
@@ -2566,10 +2572,10 @@ static void yy_reduce(
   }
   yymsp[-1].minor.yy279 = p; /*A-overwrites-W*/
 }
-#line 2570 "parse.c"
+#line 2576 "parse.c"
         break;
       case 77: /* selectnowith ::= selectnowith multiselect_op oneselect */
-#line 429 "parse.y"
+#line 435 "parse.y"
 {
   Select *pRhs = yymsp[0].minor.yy279;
   Select *pLhs = yymsp[-2].minor.yy279;
@@ -2592,21 +2598,21 @@ static void yy_reduce(
   }
   yymsp[-2].minor.yy279 = pRhs;
 }
-#line 2596 "parse.c"
+#line 2602 "parse.c"
         break;
       case 78: /* multiselect_op ::= UNION */
       case 80: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==80);
-#line 452 "parse.y"
+#line 458 "parse.y"
 {yymsp[0].minor.yy52 = yymsp[0].major; /*A-overwrites-OP*/}
-#line 2602 "parse.c"
+#line 2608 "parse.c"
         break;
       case 79: /* multiselect_op ::= UNION ALL */
-#line 453 "parse.y"
+#line 459 "parse.y"
 {yymsp[-1].minor.yy52 = TK_ALL;}
-#line 2607 "parse.c"
+#line 2613 "parse.c"
         break;
       case 81: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
-#line 457 "parse.y"
+#line 463 "parse.y"
 {
 #ifdef SELECTTRACE_ENABLED
   Token s = yymsp[-8].minor.yy0; /*A-overwrites-S*/
@@ -2637,17 +2643,17 @@ static void yy_reduce(
   }
 #endif /* SELECTRACE_ENABLED */
 }
-#line 2641 "parse.c"
+#line 2647 "parse.c"
         break;
       case 82: /* values ::= VALUES LP nexprlist RP */
-#line 491 "parse.y"
+#line 497 "parse.y"
 {
   yymsp[-3].minor.yy279 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy382,0,0,0,0,0,SF_Values,0,0);
 }
-#line 2648 "parse.c"
+#line 2654 "parse.c"
         break;
       case 83: /* values ::= values COMMA LP exprlist RP */
-#line 494 "parse.y"
+#line 500 "parse.y"
 {
   Select *pRight, *pLeft = yymsp[-4].minor.yy279;
   pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy382,0,0,0,0,0,SF_Values|SF_MultiValue,0,0);
@@ -2660,17 +2666,17 @@ static void yy_reduce(
     yymsp[-4].minor.yy279 = pLeft;
   }
 }
-#line 2664 "parse.c"
+#line 2670 "parse.c"
         break;
       case 84: /* distinct ::= DISTINCT */
-#line 511 "parse.y"
+#line 517 "parse.y"
 {yymsp[0].minor.yy52 = SF_Distinct;}
-#line 2669 "parse.c"
+#line 2675 "parse.c"
         break;
       case 85: /* distinct ::= ALL */
-#line 512 "parse.y"
+#line 518 "parse.y"
 {yymsp[0].minor.yy52 = SF_All;}
-#line 2674 "parse.c"
+#line 2680 "parse.c"
         break;
       case 87: /* sclp ::= */
       case 113: /* orderby_opt ::= */ yytestcase(yyruleno==113);
@@ -2678,94 +2684,94 @@ static void yy_reduce(
       case 196: /* exprlist ::= */ yytestcase(yyruleno==196);
       case 199: /* paren_exprlist ::= */ yytestcase(yyruleno==199);
       case 204: /* eidlist_opt ::= */ yytestcase(yyruleno==204);
-#line 525 "parse.y"
+#line 531 "parse.y"
 {yymsp[1].minor.yy382 = 0;}
-#line 2684 "parse.c"
+#line 2690 "parse.c"
         break;
       case 88: /* selcollist ::= sclp expr as */
-#line 526 "parse.y"
+#line 532 "parse.y"
 {
    yymsp[-2].minor.yy382 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy382, yymsp[-1].minor.yy162.pExpr);
    if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-2].minor.yy382, &yymsp[0].minor.yy0, 1);
    sqlite3ExprListSetSpan(pParse,yymsp[-2].minor.yy382,&yymsp[-1].minor.yy162);
 }
-#line 2693 "parse.c"
+#line 2699 "parse.c"
         break;
       case 89: /* selcollist ::= sclp STAR */
-#line 531 "parse.y"
+#line 537 "parse.y"
 {
   Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0);
   yymsp[-1].minor.yy382 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy382, p);
 }
-#line 2701 "parse.c"
+#line 2707 "parse.c"
         break;
       case 90: /* selcollist ::= sclp nm DOT STAR */
-#line 535 "parse.y"
+#line 541 "parse.y"
 {
   Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0);
   Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
   Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
   yymsp[-3].minor.yy382 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy382, pDot);
 }
-#line 2711 "parse.c"
+#line 2717 "parse.c"
         break;
       case 91: /* as ::= AS nm */
       case 218: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==218);
       case 219: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==219);
-#line 546 "parse.y"
+#line 552 "parse.y"
 {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;}
-#line 2718 "parse.c"
+#line 2724 "parse.c"
         break;
       case 93: /* from ::= */
-#line 560 "parse.y"
+#line 566 "parse.y"
 {yymsp[1].minor.yy387 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy387));}
-#line 2723 "parse.c"
+#line 2729 "parse.c"
         break;
       case 94: /* from ::= FROM seltablist */
-#line 561 "parse.y"
+#line 567 "parse.y"
 {
   yymsp[-1].minor.yy387 = yymsp[0].minor.yy387;
   sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy387);
 }
-#line 2731 "parse.c"
+#line 2737 "parse.c"
         break;
       case 95: /* stl_prefix ::= seltablist joinop */
-#line 569 "parse.y"
+#line 575 "parse.y"
 {
    if( ALWAYS(yymsp[-1].minor.yy387 && yymsp[-1].minor.yy387->nSrc>0) ) yymsp[-1].minor.yy387->a[yymsp[-1].minor.yy387->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy52;
 }
-#line 2738 "parse.c"
+#line 2744 "parse.c"
         break;
       case 96: /* stl_prefix ::= */
-#line 572 "parse.y"
+#line 578 "parse.y"
 {yymsp[1].minor.yy387 = 0;}
-#line 2743 "parse.c"
+#line 2749 "parse.c"
         break;
       case 97: /* seltablist ::= stl_prefix nm as indexed_opt on_opt using_opt */
-#line 574 "parse.y"
+#line 580 "parse.y"
 {
   yymsp[-5].minor.yy387 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy387,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy362,yymsp[0].minor.yy40);
   sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy387, &yymsp[-2].minor.yy0);
 }
-#line 2751 "parse.c"
+#line 2757 "parse.c"
         break;
       case 98: /* seltablist ::= stl_prefix nm LP exprlist RP as on_opt using_opt */
-#line 579 "parse.y"
+#line 585 "parse.y"
 {
   yymsp[-7].minor.yy387 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-7].minor.yy387,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy362,yymsp[0].minor.yy40);
   sqlite3SrcListFuncArgs(pParse, yymsp[-7].minor.yy387, yymsp[-4].minor.yy382);
 }
-#line 2759 "parse.c"
+#line 2765 "parse.c"
         break;
       case 99: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
-#line 585 "parse.y"
+#line 591 "parse.y"
 {
     yymsp[-6].minor.yy387 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy387,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy279,yymsp[-1].minor.yy362,yymsp[0].minor.yy40);
   }
-#line 2766 "parse.c"
+#line 2772 "parse.c"
         break;
       case 100: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
-#line 589 "parse.y"
+#line 595 "parse.y"
 {
     if( yymsp[-6].minor.yy387==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy362==0 && yymsp[0].minor.yy40==0 ){
       yymsp[-6].minor.yy387 = yymsp[-4].minor.yy387;
@@ -2787,135 +2793,135 @@ static void yy_reduce(
       yymsp[-6].minor.yy387 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy387,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy362,yymsp[0].minor.yy40);
     }
   }
-#line 2791 "parse.c"
+#line 2797 "parse.c"
         break;
       case 101: /* fullname ::= nm */
-#line 615 "parse.y"
+#line 621 "parse.y"
 {yymsp[0].minor.yy387 = sqlite3SrcListAppend(pParse->db,0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
-#line 2796 "parse.c"
+#line 2802 "parse.c"
         break;
       case 102: /* joinop ::= COMMA|JOIN */
-#line 621 "parse.y"
+#line 627 "parse.y"
 { yymsp[0].minor.yy52 = JT_INNER; }
-#line 2801 "parse.c"
+#line 2807 "parse.c"
         break;
       case 103: /* joinop ::= JOIN_KW JOIN */
-#line 623 "parse.y"
+#line 629 "parse.y"
 {yymsp[-1].minor.yy52 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0);  /*X-overwrites-A*/}
-#line 2806 "parse.c"
+#line 2812 "parse.c"
         break;
       case 104: /* joinop ::= JOIN_KW join_nm JOIN */
-#line 625 "parse.y"
+#line 631 "parse.y"
 {yymsp[-2].minor.yy52 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
-#line 2811 "parse.c"
+#line 2817 "parse.c"
         break;
       case 105: /* joinop ::= JOIN_KW join_nm join_nm JOIN */
-#line 627 "parse.y"
+#line 633 "parse.y"
 {yymsp[-3].minor.yy52 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
-#line 2816 "parse.c"
+#line 2822 "parse.c"
         break;
       case 106: /* on_opt ::= ON expr */
       case 123: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==123);
       case 130: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==130);
       case 192: /* case_else ::= ELSE expr */ yytestcase(yyruleno==192);
-#line 631 "parse.y"
+#line 637 "parse.y"
 {yymsp[-1].minor.yy362 = yymsp[0].minor.yy162.pExpr;}
-#line 2824 "parse.c"
+#line 2830 "parse.c"
         break;
       case 107: /* on_opt ::= */
       case 122: /* having_opt ::= */ yytestcase(yyruleno==122);
       case 129: /* where_opt ::= */ yytestcase(yyruleno==129);
       case 193: /* case_else ::= */ yytestcase(yyruleno==193);
       case 195: /* case_operand ::= */ yytestcase(yyruleno==195);
-#line 632 "parse.y"
+#line 638 "parse.y"
 {yymsp[1].minor.yy362 = 0;}
-#line 2833 "parse.c"
+#line 2839 "parse.c"
         break;
       case 108: /* indexed_opt ::= */
-#line 645 "parse.y"
+#line 651 "parse.y"
 {yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;}
-#line 2838 "parse.c"
+#line 2844 "parse.c"
         break;
       case 109: /* indexed_opt ::= INDEXED BY nm */
-#line 646 "parse.y"
+#line 652 "parse.y"
 {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;}
-#line 2843 "parse.c"
+#line 2849 "parse.c"
         break;
       case 110: /* indexed_opt ::= NOT INDEXED */
-#line 647 "parse.y"
+#line 653 "parse.y"
 {yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;}
-#line 2848 "parse.c"
+#line 2854 "parse.c"
         break;
       case 111: /* using_opt ::= USING LP idlist RP */
-#line 651 "parse.y"
+#line 657 "parse.y"
 {yymsp[-3].minor.yy40 = yymsp[-1].minor.yy40;}
-#line 2853 "parse.c"
+#line 2859 "parse.c"
         break;
       case 112: /* using_opt ::= */
       case 140: /* idlist_opt ::= */ yytestcase(yyruleno==140);
-#line 652 "parse.y"
+#line 658 "parse.y"
 {yymsp[1].minor.yy40 = 0;}
-#line 2859 "parse.c"
+#line 2865 "parse.c"
         break;
       case 114: /* orderby_opt ::= ORDER BY sortlist */
       case 121: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==121);
-#line 666 "parse.y"
+#line 672 "parse.y"
 {yymsp[-2].minor.yy382 = yymsp[0].minor.yy382;}
-#line 2865 "parse.c"
+#line 2871 "parse.c"
         break;
       case 115: /* sortlist ::= sortlist COMMA expr sortorder */
-#line 667 "parse.y"
+#line 673 "parse.y"
 {
   yymsp[-3].minor.yy382 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy382,yymsp[-1].minor.yy162.pExpr);
   sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy382,yymsp[0].minor.yy52);
 }
-#line 2873 "parse.c"
+#line 2879 "parse.c"
         break;
       case 116: /* sortlist ::= expr sortorder */
-#line 671 "parse.y"
+#line 677 "parse.y"
 {
   yymsp[-1].minor.yy382 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy162.pExpr); /*A-overwrites-Y*/
   sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy382,yymsp[0].minor.yy52);
 }
-#line 2881 "parse.c"
+#line 2887 "parse.c"
         break;
       case 117: /* sortorder ::= ASC */
-#line 678 "parse.y"
+#line 684 "parse.y"
 {yymsp[0].minor.yy52 = SQLITE_SO_ASC;}
-#line 2886 "parse.c"
+#line 2892 "parse.c"
         break;
       case 118: /* sortorder ::= DESC */
-#line 679 "parse.y"
+#line 685 "parse.y"
 {yymsp[0].minor.yy52 = SQLITE_SO_DESC;}
-#line 2891 "parse.c"
+#line 2897 "parse.c"
         break;
       case 119: /* sortorder ::= */
-#line 680 "parse.y"
+#line 686 "parse.y"
 {yymsp[1].minor.yy52 = SQLITE_SO_UNDEFINED;}
-#line 2896 "parse.c"
+#line 2902 "parse.c"
         break;
       case 124: /* limit_opt ::= */
-#line 705 "parse.y"
+#line 711 "parse.y"
 {yymsp[1].minor.yy384.pLimit = 0; yymsp[1].minor.yy384.pOffset = 0;}
-#line 2901 "parse.c"
+#line 2907 "parse.c"
         break;
       case 125: /* limit_opt ::= LIMIT expr */
-#line 706 "parse.y"
+#line 712 "parse.y"
 {yymsp[-1].minor.yy384.pLimit = yymsp[0].minor.yy162.pExpr; yymsp[-1].minor.yy384.pOffset = 0;}
-#line 2906 "parse.c"
+#line 2912 "parse.c"
         break;
       case 126: /* limit_opt ::= LIMIT expr OFFSET expr */
-#line 708 "parse.y"
+#line 714 "parse.y"
 {yymsp[-3].minor.yy384.pLimit = yymsp[-2].minor.yy162.pExpr; yymsp[-3].minor.yy384.pOffset = yymsp[0].minor.yy162.pExpr;}
-#line 2911 "parse.c"
+#line 2917 "parse.c"
         break;
       case 127: /* limit_opt ::= LIMIT expr COMMA expr */
-#line 710 "parse.y"
+#line 716 "parse.y"
 {yymsp[-3].minor.yy384.pOffset = yymsp[-2].minor.yy162.pExpr; yymsp[-3].minor.yy384.pLimit = yymsp[0].minor.yy162.pExpr;}
-#line 2916 "parse.c"
+#line 2922 "parse.c"
         break;
       case 128: /* cmd ::= with DELETE FROM fullname indexed_opt where_opt */
-#line 727 "parse.y"
+#line 733 "parse.y"
 {
   sqlite3WithPush(pParse, yymsp[-5].minor.yy151, 1);
   sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy387, &yymsp[-1].minor.yy0);
@@ -2924,10 +2930,10 @@ static void yy_reduce(
   pParse->initiateTTrans = true;
   sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy387,yymsp[0].minor.yy362);
 }
-#line 2928 "parse.c"
+#line 2934 "parse.c"
         break;
       case 131: /* cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */
-#line 760 "parse.y"
+#line 766 "parse.y"
 {
   sqlite3WithPush(pParse, yymsp[-7].minor.yy151, 1);
   sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy387, &yymsp[-3].minor.yy0);
@@ -2937,41 +2943,41 @@ static void yy_reduce(
   pParse->initiateTTrans = true;
   sqlite3Update(pParse,yymsp[-4].minor.yy387,yymsp[-1].minor.yy382,yymsp[0].minor.yy362,yymsp[-5].minor.yy52);
 }
-#line 2941 "parse.c"
+#line 2947 "parse.c"
         break;
       case 132: /* setlist ::= setlist COMMA nm EQ expr */
-#line 774 "parse.y"
+#line 780 "parse.y"
 {
   yymsp[-4].minor.yy382 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy382, yymsp[0].minor.yy162.pExpr);
   sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy382, &yymsp[-2].minor.yy0, 1);
 }
-#line 2949 "parse.c"
+#line 2955 "parse.c"
         break;
       case 133: /* setlist ::= setlist COMMA LP idlist RP EQ expr */
-#line 778 "parse.y"
+#line 784 "parse.y"
 {
   yymsp[-6].minor.yy382 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy382, yymsp[-3].minor.yy40, yymsp[0].minor.yy162.pExpr);
 }
-#line 2956 "parse.c"
+#line 2962 "parse.c"
         break;
       case 134: /* setlist ::= nm EQ expr */
-#line 781 "parse.y"
+#line 787 "parse.y"
 {
   yylhsminor.yy382 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy162.pExpr);
   sqlite3ExprListSetName(pParse, yylhsminor.yy382, &yymsp[-2].minor.yy0, 1);
 }
-#line 2964 "parse.c"
+#line 2970 "parse.c"
   yymsp[-2].minor.yy382 = yylhsminor.yy382;
         break;
       case 135: /* setlist ::= LP idlist RP EQ expr */
-#line 785 "parse.y"
+#line 791 "parse.y"
 {
   yymsp[-4].minor.yy382 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy40, yymsp[0].minor.yy162.pExpr);
 }
-#line 2972 "parse.c"
+#line 2978 "parse.c"
         break;
       case 136: /* cmd ::= with insert_cmd INTO fullname idlist_opt select */
-#line 791 "parse.y"
+#line 797 "parse.y"
 {
   sqlite3WithPush(pParse, yymsp[-5].minor.yy151, 1);
   sqlSubProgramsRemaining = SQL_MAX_COMPILING_TRIGGERS;
@@ -2979,10 +2985,10 @@ static void yy_reduce(
   pParse->initiateTTrans = true;
   sqlite3Insert(pParse, yymsp[-2].minor.yy387, yymsp[0].minor.yy279, yymsp[-1].minor.yy40, yymsp[-4].minor.yy52);
 }
-#line 2983 "parse.c"
+#line 2989 "parse.c"
         break;
       case 137: /* cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */
-#line 799 "parse.y"
+#line 805 "parse.y"
 {
   sqlite3WithPush(pParse, yymsp[-6].minor.yy151, 1);
   sqlSubProgramsRemaining = SQL_MAX_COMPILING_TRIGGERS;
@@ -2990,64 +2996,64 @@ static void yy_reduce(
   pParse->initiateTTrans = true;
   sqlite3Insert(pParse, yymsp[-3].minor.yy387, 0, yymsp[-2].minor.yy40, yymsp[-5].minor.yy52);
 }
-#line 2994 "parse.c"
+#line 3000 "parse.c"
         break;
       case 141: /* idlist_opt ::= LP idlist RP */
-#line 817 "parse.y"
+#line 823 "parse.y"
 {yymsp[-2].minor.yy40 = yymsp[-1].minor.yy40;}
-#line 2999 "parse.c"
+#line 3005 "parse.c"
         break;
       case 142: /* idlist ::= idlist COMMA nm */
-#line 819 "parse.y"
+#line 825 "parse.y"
 {yymsp[-2].minor.yy40 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy40,&yymsp[0].minor.yy0);}
-#line 3004 "parse.c"
+#line 3010 "parse.c"
         break;
       case 143: /* idlist ::= nm */
-#line 821 "parse.y"
+#line 827 "parse.y"
 {yymsp[0].minor.yy40 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
-#line 3009 "parse.c"
+#line 3015 "parse.c"
         break;
       case 144: /* expr ::= LP expr RP */
-#line 870 "parse.y"
+#line 876 "parse.y"
 {spanSet(&yymsp[-2].minor.yy162,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/  yymsp[-2].minor.yy162.pExpr = yymsp[-1].minor.yy162.pExpr;}
-#line 3014 "parse.c"
+#line 3020 "parse.c"
         break;
       case 145: /* term ::= NULL */
       case 149: /* term ::= FLOAT|BLOB */ yytestcase(yyruleno==149);
       case 150: /* term ::= STRING */ yytestcase(yyruleno==150);
-#line 871 "parse.y"
+#line 877 "parse.y"
 {spanExpr(&yymsp[0].minor.yy162,pParse,yymsp[0].major,yymsp[0].minor.yy0);/*A-overwrites-X*/}
-#line 3021 "parse.c"
+#line 3027 "parse.c"
         break;
       case 146: /* expr ::= ID|INDEXED */
       case 147: /* expr ::= JOIN_KW */ yytestcase(yyruleno==147);
-#line 872 "parse.y"
+#line 878 "parse.y"
 {spanExpr(&yymsp[0].minor.yy162,pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
-#line 3027 "parse.c"
+#line 3033 "parse.c"
         break;
       case 148: /* expr ::= nm DOT nm */
-#line 874 "parse.y"
+#line 880 "parse.y"
 {
   Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
   Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1);
   spanSet(&yymsp[-2].minor.yy162,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/
   yymsp[-2].minor.yy162.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
 }
-#line 3037 "parse.c"
+#line 3043 "parse.c"
         break;
       case 151: /* term ::= INTEGER */
-#line 882 "parse.y"
+#line 888 "parse.y"
 {
   yylhsminor.yy162.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1);
   yylhsminor.yy162.zStart = yymsp[0].minor.yy0.z;
   yylhsminor.yy162.zEnd = yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n;
   if( yylhsminor.yy162.pExpr ) yylhsminor.yy162.pExpr->flags |= EP_Leaf;
 }
-#line 3047 "parse.c"
+#line 3053 "parse.c"
   yymsp[0].minor.yy162 = yylhsminor.yy162;
         break;
       case 152: /* expr ::= VARIABLE */
-#line 888 "parse.y"
+#line 894 "parse.y"
 {
   if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){
     u32 n = yymsp[0].minor.yy0.n;
@@ -3069,27 +3075,27 @@ static void yy_reduce(
     }
   }
 }
-#line 3073 "parse.c"
+#line 3079 "parse.c"
         break;
       case 153: /* expr ::= expr COLLATE ID|INDEXED */
-#line 909 "parse.y"
+#line 915 "parse.y"
 {
   yymsp[-2].minor.yy162.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy162.pExpr, &yymsp[0].minor.yy0, 1);
   yymsp[-2].minor.yy162.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
 }
-#line 3081 "parse.c"
+#line 3087 "parse.c"
         break;
       case 154: /* expr ::= CAST LP expr AS typetoken RP */
-#line 914 "parse.y"
+#line 920 "parse.y"
 {
   spanSet(&yymsp[-5].minor.yy162,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/
   yymsp[-5].minor.yy162.pExpr = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
   sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy162.pExpr, yymsp[-3].minor.yy162.pExpr, 0);
 }
-#line 3090 "parse.c"
+#line 3096 "parse.c"
         break;
       case 155: /* expr ::= ID|INDEXED LP distinct exprlist RP */
-#line 920 "parse.y"
+#line 926 "parse.y"
 {
   if( yymsp[-1].minor.yy382 && yymsp[-1].minor.yy382->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
     sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
@@ -3100,29 +3106,29 @@ static void yy_reduce(
     yylhsminor.yy162.pExpr->flags |= EP_Distinct;
   }
 }
-#line 3104 "parse.c"
+#line 3110 "parse.c"
   yymsp[-4].minor.yy162 = yylhsminor.yy162;
         break;
       case 156: /* expr ::= ID|INDEXED LP STAR RP */
-#line 930 "parse.y"
+#line 936 "parse.y"
 {
   yylhsminor.yy162.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
   spanSet(&yylhsminor.yy162,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
 }
-#line 3113 "parse.c"
+#line 3119 "parse.c"
   yymsp[-3].minor.yy162 = yylhsminor.yy162;
         break;
       case 157: /* term ::= CTIME_KW */
-#line 934 "parse.y"
+#line 940 "parse.y"
 {
   yylhsminor.yy162.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0);
   spanSet(&yylhsminor.yy162, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
 }
-#line 3122 "parse.c"
+#line 3128 "parse.c"
   yymsp[0].minor.yy162 = yylhsminor.yy162;
         break;
       case 158: /* expr ::= LP nexprlist COMMA expr RP */
-#line 963 "parse.y"
+#line 969 "parse.y"
 {
   ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy382, yymsp[-1].minor.yy162.pExpr);
   yylhsminor.yy162.pExpr = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
@@ -3133,7 +3139,7 @@ static void yy_reduce(
     sqlite3ExprListDelete(pParse->db, pList);
   }
 }
-#line 3137 "parse.c"
+#line 3143 "parse.c"
   yymsp[-4].minor.yy162 = yylhsminor.yy162;
         break;
       case 159: /* expr ::= expr AND expr */
@@ -3144,22 +3150,22 @@ static void yy_reduce(
       case 164: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==164);
       case 165: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==165);
       case 166: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==166);
-#line 974 "parse.y"
+#line 980 "parse.y"
 {spanBinaryExpr(pParse,yymsp[-1].major,&yymsp[-2].minor.yy162,&yymsp[0].minor.yy162);}
-#line 3150 "parse.c"
+#line 3156 "parse.c"
         break;
       case 167: /* likeop ::= LIKE_KW|MATCH */
-#line 987 "parse.y"
+#line 993 "parse.y"
 {yymsp[0].minor.yy0=yymsp[0].minor.yy0;/*A-overwrites-X*/}
-#line 3155 "parse.c"
+#line 3161 "parse.c"
         break;
       case 168: /* likeop ::= NOT LIKE_KW|MATCH */
-#line 988 "parse.y"
+#line 994 "parse.y"
 {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/}
-#line 3160 "parse.c"
+#line 3166 "parse.c"
         break;
       case 169: /* expr ::= expr likeop expr */
-#line 989 "parse.y"
+#line 995 "parse.y"
 {
   ExprList *pList;
   int bNot = yymsp[-1].minor.yy0.n & 0x80000000;
@@ -3171,10 +3177,10 @@ static void yy_reduce(
   yymsp[-2].minor.yy162.zEnd = yymsp[0].minor.yy162.zEnd;
   if( yymsp[-2].minor.yy162.pExpr ) yymsp[-2].minor.yy162.pExpr->flags |= EP_InfixFunc;
 }
-#line 3175 "parse.c"
+#line 3181 "parse.c"
         break;
       case 170: /* expr ::= expr likeop expr ESCAPE expr */
-#line 1000 "parse.y"
+#line 1006 "parse.y"
 {
   ExprList *pList;
   int bNot = yymsp[-3].minor.yy0.n & 0x80000000;
@@ -3187,58 +3193,58 @@ static void yy_reduce(
   yymsp[-4].minor.yy162.zEnd = yymsp[0].minor.yy162.zEnd;
   if( yymsp[-4].minor.yy162.pExpr ) yymsp[-4].minor.yy162.pExpr->flags |= EP_InfixFunc;
 }
-#line 3191 "parse.c"
+#line 3197 "parse.c"
         break;
       case 171: /* expr ::= expr ISNULL|NOTNULL */
-#line 1027 "parse.y"
+#line 1033 "parse.y"
 {spanUnaryPostfix(pParse,yymsp[0].major,&yymsp[-1].minor.yy162,&yymsp[0].minor.yy0);}
-#line 3196 "parse.c"
+#line 3202 "parse.c"
         break;
       case 172: /* expr ::= expr NOT NULL */
-#line 1028 "parse.y"
+#line 1034 "parse.y"
 {spanUnaryPostfix(pParse,TK_NOTNULL,&yymsp[-2].minor.yy162,&yymsp[0].minor.yy0);}
-#line 3201 "parse.c"
+#line 3207 "parse.c"
         break;
       case 173: /* expr ::= expr IS expr */
-#line 1049 "parse.y"
+#line 1055 "parse.y"
 {
   spanBinaryExpr(pParse,TK_IS,&yymsp[-2].minor.yy162,&yymsp[0].minor.yy162);
   binaryToUnaryIfNull(pParse, yymsp[0].minor.yy162.pExpr, yymsp[-2].minor.yy162.pExpr, TK_ISNULL);
 }
-#line 3209 "parse.c"
+#line 3215 "parse.c"
         break;
       case 174: /* expr ::= expr IS NOT expr */
-#line 1053 "parse.y"
+#line 1059 "parse.y"
 {
   spanBinaryExpr(pParse,TK_ISNOT,&yymsp[-3].minor.yy162,&yymsp[0].minor.yy162);
   binaryToUnaryIfNull(pParse, yymsp[0].minor.yy162.pExpr, yymsp[-3].minor.yy162.pExpr, TK_NOTNULL);
 }
-#line 3217 "parse.c"
+#line 3223 "parse.c"
         break;
       case 175: /* expr ::= NOT expr */
       case 176: /* expr ::= BITNOT expr */ yytestcase(yyruleno==176);
-#line 1077 "parse.y"
+#line 1083 "parse.y"
 {spanUnaryPrefix(&yymsp[-1].minor.yy162,pParse,yymsp[-1].major,&yymsp[0].minor.yy162,&yymsp[-1].minor.yy0);/*A-overwrites-B*/}
-#line 3223 "parse.c"
+#line 3229 "parse.c"
         break;
       case 177: /* expr ::= MINUS expr */
-#line 1081 "parse.y"
+#line 1087 "parse.y"
 {spanUnaryPrefix(&yymsp[-1].minor.yy162,pParse,TK_UMINUS,&yymsp[0].minor.yy162,&yymsp[-1].minor.yy0);/*A-overwrites-B*/}
-#line 3228 "parse.c"
+#line 3234 "parse.c"
         break;
       case 178: /* expr ::= PLUS expr */
-#line 1083 "parse.y"
+#line 1089 "parse.y"
 {spanUnaryPrefix(&yymsp[-1].minor.yy162,pParse,TK_UPLUS,&yymsp[0].minor.yy162,&yymsp[-1].minor.yy0);/*A-overwrites-B*/}
-#line 3233 "parse.c"
+#line 3239 "parse.c"
         break;
       case 179: /* between_op ::= BETWEEN */
       case 182: /* in_op ::= IN */ yytestcase(yyruleno==182);
-#line 1086 "parse.y"
+#line 1092 "parse.y"
 {yymsp[0].minor.yy52 = 0;}
-#line 3239 "parse.c"
+#line 3245 "parse.c"
         break;
       case 181: /* expr ::= expr between_op expr AND expr */
-#line 1088 "parse.y"
+#line 1094 "parse.y"
 {
   ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy162.pExpr);
   pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy162.pExpr);
@@ -3251,10 +3257,10 @@ static void yy_reduce(
   exprNot(pParse, yymsp[-3].minor.yy52, &yymsp[-4].minor.yy162);
   yymsp[-4].minor.yy162.zEnd = yymsp[0].minor.yy162.zEnd;
 }
-#line 3255 "parse.c"
+#line 3261 "parse.c"
         break;
       case 184: /* expr ::= expr in_op LP exprlist RP */
-#line 1104 "parse.y"
+#line 1110 "parse.y"
 {
     if( yymsp[-1].minor.yy382==0 ){
       /* Expressions of the form
@@ -3265,7 +3271,7 @@ static void yy_reduce(
       ** simplify to constants 0 (false) and 1 (true), respectively,
       ** regardless of the value of expr1.
       */
-      sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy162.pExpr);
+	    sql_expr_free(pParse->db, yymsp[-4].minor.yy162.pExpr, false);
       yymsp[-4].minor.yy162.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[yymsp[-3].minor.yy52],1);
     }else if( yymsp[-1].minor.yy382->nExpr==1 ){
       /* Expressions of the form:
@@ -3306,29 +3312,29 @@ static void yy_reduce(
     }
     yymsp[-4].minor.yy162.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
   }
-#line 3310 "parse.c"
+#line 3316 "parse.c"
         break;
       case 185: /* expr ::= LP select RP */
-#line 1155 "parse.y"
+#line 1161 "parse.y"
 {
     spanSet(&yymsp[-2].minor.yy162,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/
     yymsp[-2].minor.yy162.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
     sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy162.pExpr, yymsp[-1].minor.yy279);
   }
-#line 3319 "parse.c"
+#line 3325 "parse.c"
         break;
       case 186: /* expr ::= expr in_op LP select RP */
-#line 1160 "parse.y"
+#line 1166 "parse.y"
 {
     yymsp[-4].minor.yy162.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy162.pExpr, 0);
     sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy162.pExpr, yymsp[-1].minor.yy279);
     exprNot(pParse, yymsp[-3].minor.yy52, &yymsp[-4].minor.yy162);
     yymsp[-4].minor.yy162.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
   }
-#line 3329 "parse.c"
+#line 3335 "parse.c"
         break;
       case 187: /* expr ::= expr in_op nm paren_exprlist */
-#line 1166 "parse.y"
+#line 1172 "parse.y"
 {
     SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0);
     Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
@@ -3338,20 +3344,20 @@ static void yy_reduce(
     exprNot(pParse, yymsp[-2].minor.yy52, &yymsp[-3].minor.yy162);
     yymsp[-3].minor.yy162.zEnd = &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n];
   }
-#line 3342 "parse.c"
+#line 3348 "parse.c"
         break;
       case 188: /* expr ::= EXISTS LP select RP */
-#line 1175 "parse.y"
+#line 1181 "parse.y"
 {
     Expr *p;
     spanSet(&yymsp[-3].minor.yy162,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/
     p = yymsp[-3].minor.yy162.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
     sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy279);
   }
-#line 3352 "parse.c"
+#line 3358 "parse.c"
         break;
       case 189: /* expr ::= CASE case_operand case_exprlist case_else END */
-#line 1184 "parse.y"
+#line 1190 "parse.y"
 {
   spanSet(&yymsp[-4].minor.yy162,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);  /*A-overwrites-C*/
   yymsp[-4].minor.yy162.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy362, 0);
@@ -3360,140 +3366,140 @@ static void yy_reduce(
     sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy162.pExpr);
   }else{
     sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy382);
-    sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy362);
+    sql_expr_free(pParse->db, yymsp[-1].minor.yy362, false);
   }
 }
-#line 3367 "parse.c"
+#line 3373 "parse.c"
         break;
       case 190: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
-#line 1197 "parse.y"
+#line 1203 "parse.y"
 {
   yymsp[-4].minor.yy382 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy382, yymsp[-2].minor.yy162.pExpr);
   yymsp[-4].minor.yy382 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy382, yymsp[0].minor.yy162.pExpr);
 }
-#line 3375 "parse.c"
+#line 3381 "parse.c"
         break;
       case 191: /* case_exprlist ::= WHEN expr THEN expr */
-#line 1201 "parse.y"
+#line 1207 "parse.y"
 {
   yymsp[-3].minor.yy382 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy162.pExpr);
   yymsp[-3].minor.yy382 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy382, yymsp[0].minor.yy162.pExpr);
 }
-#line 3383 "parse.c"
+#line 3389 "parse.c"
         break;
       case 194: /* case_operand ::= expr */
-#line 1211 "parse.y"
+#line 1217 "parse.y"
 {yymsp[0].minor.yy362 = yymsp[0].minor.yy162.pExpr; /*A-overwrites-X*/}
-#line 3388 "parse.c"
+#line 3394 "parse.c"
         break;
       case 197: /* nexprlist ::= nexprlist COMMA expr */
-#line 1222 "parse.y"
+#line 1228 "parse.y"
 {yymsp[-2].minor.yy382 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy382,yymsp[0].minor.yy162.pExpr);}
-#line 3393 "parse.c"
+#line 3399 "parse.c"
         break;
       case 198: /* nexprlist ::= expr */
-#line 1224 "parse.y"
+#line 1230 "parse.y"
 {yymsp[0].minor.yy382 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy162.pExpr); /*A-overwrites-Y*/}
-#line 3398 "parse.c"
+#line 3404 "parse.c"
         break;
       case 200: /* paren_exprlist ::= LP exprlist RP */
       case 205: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==205);
-#line 1232 "parse.y"
+#line 1238 "parse.y"
 {yymsp[-2].minor.yy382 = yymsp[-1].minor.yy382;}
-#line 3404 "parse.c"
+#line 3410 "parse.c"
         break;
       case 201: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm ON nm LP sortlist RP where_opt */
-#line 1239 "parse.y"
+#line 1245 "parse.y"
 {
   sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, 
                      sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0), yymsp[-2].minor.yy382, yymsp[-9].minor.yy52,
                       &yymsp[-10].minor.yy0, yymsp[0].minor.yy362, SQLITE_SO_ASC, yymsp[-7].minor.yy52, SQLITE_IDXTYPE_APPDEF);
 }
-#line 3413 "parse.c"
+#line 3419 "parse.c"
         break;
       case 202: /* uniqueflag ::= UNIQUE */
       case 243: /* raisetype ::= ABORT */ yytestcase(yyruleno==243);
-#line 1246 "parse.y"
+#line 1252 "parse.y"
 {yymsp[0].minor.yy52 = ON_CONFLICT_ACTION_ABORT;}
-#line 3419 "parse.c"
+#line 3425 "parse.c"
         break;
       case 203: /* uniqueflag ::= */
-#line 1247 "parse.y"
+#line 1253 "parse.y"
 {yymsp[1].minor.yy52 = ON_CONFLICT_ACTION_NONE;}
-#line 3424 "parse.c"
+#line 3430 "parse.c"
         break;
       case 206: /* eidlist ::= eidlist COMMA nm collate sortorder */
-#line 1290 "parse.y"
+#line 1296 "parse.y"
 {
   yymsp[-4].minor.yy382 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy382, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy52, yymsp[0].minor.yy52);
 }
-#line 3431 "parse.c"
+#line 3437 "parse.c"
         break;
       case 207: /* eidlist ::= nm collate sortorder */
-#line 1293 "parse.y"
+#line 1299 "parse.y"
 {
   yymsp[-2].minor.yy382 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy52, yymsp[0].minor.yy52); /*A-overwrites-Y*/
 }
-#line 3438 "parse.c"
+#line 3444 "parse.c"
         break;
       case 210: /* cmd ::= DROP INDEX ifexists fullname ON nm */
-#line 1304 "parse.y"
+#line 1310 "parse.y"
 {
     sqlite3DropIndex(pParse, yymsp[-2].minor.yy387, &yymsp[0].minor.yy0, yymsp[-3].minor.yy52);
 }
-#line 3445 "parse.c"
+#line 3451 "parse.c"
         break;
       case 211: /* cmd ::= PRAGMA nm */
-#line 1311 "parse.y"
+#line 1317 "parse.y"
 {
     sqlite3Pragma(pParse,&yymsp[0].minor.yy0,0,0,0,0);
 }
-#line 3452 "parse.c"
+#line 3458 "parse.c"
         break;
       case 212: /* cmd ::= PRAGMA nm EQ nmnum */
-#line 1314 "parse.y"
+#line 1320 "parse.y"
 {
     sqlite3Pragma(pParse,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy0,0,0);
 }
-#line 3459 "parse.c"
+#line 3465 "parse.c"
         break;
       case 213: /* cmd ::= PRAGMA nm LP nmnum RP */
-#line 1317 "parse.y"
+#line 1323 "parse.y"
 {
     sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,0,&yymsp[-1].minor.yy0,0,0);
 }
-#line 3466 "parse.c"
+#line 3472 "parse.c"
         break;
       case 214: /* cmd ::= PRAGMA nm EQ minus_num */
-#line 1320 "parse.y"
+#line 1326 "parse.y"
 {
     sqlite3Pragma(pParse,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy0,0,1);
 }
-#line 3473 "parse.c"
+#line 3479 "parse.c"
         break;
       case 215: /* cmd ::= PRAGMA nm LP minus_num RP */
-#line 1323 "parse.y"
+#line 1329 "parse.y"
 {
     sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,0,&yymsp[-1].minor.yy0,0,1);
 }
-#line 3480 "parse.c"
+#line 3486 "parse.c"
         break;
       case 216: /* cmd ::= PRAGMA nm EQ nm DOT nm */
-#line 1326 "parse.y"
+#line 1332 "parse.y"
 {
     sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,0,&yymsp[0].minor.yy0,&yymsp[-2].minor.yy0,0);
 }
-#line 3487 "parse.c"
+#line 3493 "parse.c"
         break;
       case 217: /* cmd ::= PRAGMA */
-#line 1329 "parse.y"
+#line 1335 "parse.y"
 {
     sqlite3Pragma(pParse, 0,0,0,0,0);
 }
-#line 3494 "parse.c"
+#line 3500 "parse.c"
         break;
       case 220: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
-#line 1349 "parse.y"
+#line 1355 "parse.y"
 {
   Token all;
   all.z = yymsp[-3].minor.yy0.z;
@@ -3501,124 +3507,124 @@ static void yy_reduce(
   pParse->initiateTTrans = false;
   sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy427, &all);
 }
-#line 3505 "parse.c"
+#line 3511 "parse.c"
         break;
       case 221: /* trigger_decl ::= TRIGGER ifnotexists nm trigger_time trigger_event ON fullname foreach_clause when_clause */
-#line 1359 "parse.y"
+#line 1365 "parse.y"
 {
   sqlite3BeginTrigger(pParse, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy52, yymsp[-4].minor.yy10.a, yymsp[-4].minor.yy10.b, yymsp[-2].minor.yy387, yymsp[0].minor.yy362, yymsp[-7].minor.yy52);
   yymsp[-8].minor.yy0 = yymsp[-6].minor.yy0; /*yymsp[-8].minor.yy0-overwrites-T*/
 }
-#line 3513 "parse.c"
+#line 3519 "parse.c"
         break;
       case 222: /* trigger_time ::= BEFORE */
-#line 1365 "parse.y"
+#line 1371 "parse.y"
 { yymsp[0].minor.yy52 = TK_BEFORE; }
-#line 3518 "parse.c"
+#line 3524 "parse.c"
         break;
       case 223: /* trigger_time ::= AFTER */
-#line 1366 "parse.y"
+#line 1372 "parse.y"
 { yymsp[0].minor.yy52 = TK_AFTER;  }
-#line 3523 "parse.c"
+#line 3529 "parse.c"
         break;
       case 224: /* trigger_time ::= INSTEAD OF */
-#line 1367 "parse.y"
+#line 1373 "parse.y"
 { yymsp[-1].minor.yy52 = TK_INSTEAD;}
-#line 3528 "parse.c"
+#line 3534 "parse.c"
         break;
       case 225: /* trigger_time ::= */
-#line 1368 "parse.y"
+#line 1374 "parse.y"
 { yymsp[1].minor.yy52 = TK_BEFORE; }
-#line 3533 "parse.c"
+#line 3539 "parse.c"
         break;
       case 226: /* trigger_event ::= DELETE|INSERT */
       case 227: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==227);
-#line 1372 "parse.y"
+#line 1378 "parse.y"
 {yymsp[0].minor.yy10.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy10.b = 0;}
-#line 3539 "parse.c"
+#line 3545 "parse.c"
         break;
       case 228: /* trigger_event ::= UPDATE OF idlist */
-#line 1374 "parse.y"
+#line 1380 "parse.y"
 {yymsp[-2].minor.yy10.a = TK_UPDATE; yymsp[-2].minor.yy10.b = yymsp[0].minor.yy40;}
-#line 3544 "parse.c"
+#line 3550 "parse.c"
         break;
       case 229: /* when_clause ::= */
-#line 1381 "parse.y"
+#line 1387 "parse.y"
 { yymsp[1].minor.yy362 = 0; }
-#line 3549 "parse.c"
+#line 3555 "parse.c"
         break;
       case 230: /* when_clause ::= WHEN expr */
-#line 1382 "parse.y"
+#line 1388 "parse.y"
 { yymsp[-1].minor.yy362 = yymsp[0].minor.yy162.pExpr; }
-#line 3554 "parse.c"
+#line 3560 "parse.c"
         break;
       case 231: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
-#line 1386 "parse.y"
+#line 1392 "parse.y"
 {
   assert( yymsp[-2].minor.yy427!=0 );
   yymsp[-2].minor.yy427->pLast->pNext = yymsp[-1].minor.yy427;
   yymsp[-2].minor.yy427->pLast = yymsp[-1].minor.yy427;
 }
-#line 3563 "parse.c"
+#line 3569 "parse.c"
         break;
       case 232: /* trigger_cmd_list ::= trigger_cmd SEMI */
-#line 1391 "parse.y"
+#line 1397 "parse.y"
 { 
   assert( yymsp[-1].minor.yy427!=0 );
   yymsp[-1].minor.yy427->pLast = yymsp[-1].minor.yy427;
 }
-#line 3571 "parse.c"
+#line 3577 "parse.c"
         break;
       case 233: /* trnm ::= nm DOT nm */
-#line 1402 "parse.y"
+#line 1408 "parse.y"
 {
   yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;
   sqlite3ErrorMsg(pParse, 
         "qualified table names are not allowed on INSERT, UPDATE, and DELETE "
         "statements within triggers");
 }
-#line 3581 "parse.c"
+#line 3587 "parse.c"
         break;
       case 234: /* tridxby ::= INDEXED BY nm */
-#line 1414 "parse.y"
+#line 1420 "parse.y"
 {
   sqlite3ErrorMsg(pParse,
         "the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
         "within triggers");
 }
-#line 3590 "parse.c"
+#line 3596 "parse.c"
         break;
       case 235: /* tridxby ::= NOT INDEXED */
-#line 1419 "parse.y"
+#line 1425 "parse.y"
 {
   sqlite3ErrorMsg(pParse,
         "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
         "within triggers");
 }
-#line 3599 "parse.c"
+#line 3605 "parse.c"
         break;
       case 236: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */
-#line 1432 "parse.y"
+#line 1438 "parse.y"
 {yymsp[-6].minor.yy427 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy382, yymsp[0].minor.yy362, yymsp[-5].minor.yy52);}
-#line 3604 "parse.c"
+#line 3610 "parse.c"
         break;
       case 237: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */
-#line 1436 "parse.y"
+#line 1442 "parse.y"
 {yymsp[-4].minor.yy427 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy40, yymsp[0].minor.yy279, yymsp[-4].minor.yy52);/*A-overwrites-R*/}
-#line 3609 "parse.c"
+#line 3615 "parse.c"
         break;
       case 238: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */
-#line 1440 "parse.y"
+#line 1446 "parse.y"
 {yymsp[-4].minor.yy427 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy362);}
-#line 3614 "parse.c"
+#line 3620 "parse.c"
         break;
       case 239: /* trigger_cmd ::= select */
-#line 1444 "parse.y"
+#line 1450 "parse.y"
 {yymsp[0].minor.yy427 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy279); /*A-overwrites-X*/}
-#line 3619 "parse.c"
+#line 3625 "parse.c"
         break;
       case 240: /* expr ::= RAISE LP IGNORE RP */
-#line 1447 "parse.y"
+#line 1453 "parse.y"
 {
   spanSet(&yymsp[-3].minor.yy162,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);  /*A-overwrites-X*/
   yymsp[-3].minor.yy162.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0); 
@@ -3626,10 +3632,10 @@ static void yy_reduce(
     yymsp[-3].minor.yy162.pExpr->affinity = ON_CONFLICT_ACTION_IGNORE;
   }
 }
-#line 3630 "parse.c"
+#line 3636 "parse.c"
         break;
       case 241: /* expr ::= RAISE LP raisetype COMMA STRING RP */
-#line 1454 "parse.y"
+#line 1460 "parse.y"
 {
   spanSet(&yymsp[-5].minor.yy162,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);  /*A-overwrites-X*/
   yymsp[-5].minor.yy162.pExpr = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); 
@@ -3637,85 +3643,85 @@ static void yy_reduce(
     yymsp[-5].minor.yy162.pExpr->affinity = (char)yymsp[-3].minor.yy52;
   }
 }
-#line 3641 "parse.c"
+#line 3647 "parse.c"
         break;
       case 242: /* raisetype ::= ROLLBACK */
-#line 1464 "parse.y"
+#line 1470 "parse.y"
 {yymsp[0].minor.yy52 = ON_CONFLICT_ACTION_ROLLBACK;}
-#line 3646 "parse.c"
+#line 3652 "parse.c"
         break;
       case 244: /* raisetype ::= FAIL */
-#line 1466 "parse.y"
+#line 1472 "parse.y"
 {yymsp[0].minor.yy52 = ON_CONFLICT_ACTION_FAIL;}
-#line 3651 "parse.c"
+#line 3657 "parse.c"
         break;
       case 245: /* cmd ::= DROP TRIGGER ifexists fullname */
-#line 1471 "parse.y"
+#line 1477 "parse.y"
 {
   sqlite3DropTrigger(pParse,yymsp[0].minor.yy387,yymsp[-1].minor.yy52);
 }
-#line 3658 "parse.c"
+#line 3664 "parse.c"
         break;
       case 246: /* cmd ::= REINDEX */
-#line 1478 "parse.y"
+#line 1484 "parse.y"
 {sqlite3Reindex(pParse, 0, 0);}
-#line 3663 "parse.c"
+#line 3669 "parse.c"
         break;
       case 247: /* cmd ::= REINDEX nm */
-#line 1479 "parse.y"
+#line 1485 "parse.y"
 {sqlite3Reindex(pParse, &yymsp[0].minor.yy0, 0);}
-#line 3668 "parse.c"
+#line 3674 "parse.c"
         break;
       case 248: /* cmd ::= REINDEX nm ON nm */
-#line 1480 "parse.y"
+#line 1486 "parse.y"
 {sqlite3Reindex(pParse, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);}
-#line 3673 "parse.c"
+#line 3679 "parse.c"
         break;
       case 249: /* cmd ::= ANALYZE */
-#line 1485 "parse.y"
+#line 1491 "parse.y"
 {sqlite3Analyze(pParse, 0);}
-#line 3678 "parse.c"
+#line 3684 "parse.c"
         break;
       case 250: /* cmd ::= ANALYZE nm */
-#line 1486 "parse.y"
+#line 1492 "parse.y"
 {sqlite3Analyze(pParse, &yymsp[0].minor.yy0);}
-#line 3683 "parse.c"
+#line 3689 "parse.c"
         break;
       case 251: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
-#line 1491 "parse.y"
+#line 1497 "parse.y"
 {
   sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy387,&yymsp[0].minor.yy0);
 }
-#line 3690 "parse.c"
+#line 3696 "parse.c"
         break;
       case 252: /* with ::= */
-#line 1514 "parse.y"
+#line 1520 "parse.y"
 {yymsp[1].minor.yy151 = 0;}
-#line 3695 "parse.c"
+#line 3701 "parse.c"
         break;
       case 253: /* with ::= WITH wqlist */
-#line 1516 "parse.y"
+#line 1522 "parse.y"
 { yymsp[-1].minor.yy151 = yymsp[0].minor.yy151; }
-#line 3700 "parse.c"
+#line 3706 "parse.c"
         break;
       case 254: /* with ::= WITH RECURSIVE wqlist */
-#line 1517 "parse.y"
+#line 1523 "parse.y"
 { yymsp[-2].minor.yy151 = yymsp[0].minor.yy151; }
-#line 3705 "parse.c"
+#line 3711 "parse.c"
         break;
       case 255: /* wqlist ::= nm eidlist_opt AS LP select RP */
-#line 1519 "parse.y"
+#line 1525 "parse.y"
 {
   yymsp[-5].minor.yy151 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy382, yymsp[-1].minor.yy279); /*A-overwrites-X*/
 }
-#line 3712 "parse.c"
+#line 3718 "parse.c"
         break;
       case 256: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
-#line 1522 "parse.y"
+#line 1528 "parse.y"
 {
   yymsp[-7].minor.yy151 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy151, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy382, yymsp[-1].minor.yy279);
 }
-#line 3719 "parse.c"
+#line 3725 "parse.c"
         break;
       default:
       /* (257) input ::= ecmd */ yytestcase(yyruleno==257);
@@ -3826,7 +3832,7 @@ static void yy_syntax_error(
   } else {
     sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
   }
-#line 3830 "parse.c"
+#line 3836 "parse.c"
 /************ End %syntax_error code ******************************************/
   sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
 }
diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y
index e2acf24..9ee7dac 100644
--- a/src/box/sql/parse.y
+++ b/src/box/sql/parse.y
@@ -108,7 +108,10 @@ static void disableLookaside(Parse *pParse){
 
 // Input is a single SQL command
 input ::= ecmd.
-ecmd ::= explain cmdx SEMI.       { sqlite3FinishCoding(pParse); }
+ecmd ::= explain cmdx SEMI. {
+	if (!pParse->parse_only)
+		sqlite3FinishCoding(pParse);
+}
 ecmd ::= SEMI. {
   sqlite3ErrorMsg(pParse, "syntax error: empty request");
 }
@@ -378,7 +381,10 @@ cmd ::= DROP VIEW ifexists(E) fullname(X). {
 //
 cmd ::= select(X).  {
   SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
-  sqlite3Select(pParse, X, &dest);
+  if(!pParse->parse_only)
+	  sqlite3Select(pParse, X, &dest);
+  else
+	  sql_expr_extract_select(pParse, X);
   sqlite3SelectDelete(pParse->db, X);
 }
 
@@ -627,7 +633,7 @@ joinop(X) ::= JOIN_KW(A) join_nm(B) join_nm(C) JOIN.
                   {X = sqlite3JoinType(pParse,&A,&B,&C);/*X-overwrites-A*/}
 
 %type on_opt {Expr*}
-%destructor on_opt {sqlite3ExprDelete(pParse->db, $$);}
+%destructor on_opt {sql_expr_free(pParse->db, $$, false);}
 on_opt(N) ::= ON expr(E).   {N = E.pExpr;}
 on_opt(N) ::= .             {N = 0;}
 
@@ -685,7 +691,7 @@ groupby_opt(A) ::= .                      {A = 0;}
 groupby_opt(A) ::= GROUP BY nexprlist(X). {A = X;}
 
 %type having_opt {Expr*}
-%destructor having_opt {sqlite3ExprDelete(pParse->db, $$);}
+%destructor having_opt {sql_expr_free(pParse->db, $$, false);}
 having_opt(A) ::= .                {A = 0;}
 having_opt(A) ::= HAVING expr(X).  {A = X.pExpr;}
 
@@ -735,7 +741,7 @@ cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W). {
 %endif
 
 %type where_opt {Expr*}
-%destructor where_opt {sqlite3ExprDelete(pParse->db, $$);}
+%destructor where_opt {sql_expr_free(pParse->db, $$, false);}
 
 where_opt(A) ::= .                    {A = 0;}
 where_opt(A) ::= WHERE expr(X).       {A = X.pExpr;}
@@ -824,9 +830,9 @@ idlist(A) ::= nm(Y).
 //
 
 %type expr {ExprSpan}
-%destructor expr {sqlite3ExprDelete(pParse->db, $$.pExpr);}
+%destructor expr {sql_expr_free(pParse->db, $$.pExpr, false);}
 %type term {ExprSpan}
-%destructor term {sqlite3ExprDelete(pParse->db, $$.pExpr);}
+%destructor term {sql_expr_free(pParse->db, $$.pExpr, false);}
 
 %include {
   /* This is a utility routine used to set the ExprSpan.zStart and
@@ -1034,7 +1040,7 @@ expr(A) ::= expr(A) NOT NULL(E). {spanUnaryPostfix(pParse,TK_NOTNULL,&A,&E);}
     sqlite3 *db = pParse->db;
     if( pA && pY && pY->op==TK_NULL ){
       pA->op = (u8)op;
-      sqlite3ExprDelete(db, pA->pRight);
+      sql_expr_free(db, pA->pRight, false);
       pA->pRight = 0;
     }
   }
@@ -1111,7 +1117,7 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
       ** simplify to constants 0 (false) and 1 (true), respectively,
       ** regardless of the value of expr1.
       */
-      sqlite3ExprDelete(pParse->db, A.pExpr);
+	    sql_expr_free(pParse->db, A.pExpr, false);
       A.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[N],1);
     }else if( Y->nExpr==1 ){
       /* Expressions of the form:
@@ -1189,7 +1195,7 @@ expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). {
     sqlite3ExprSetHeightAndFlags(pParse, A.pExpr);
   }else{
     sqlite3ExprListDelete(pParse->db, Y);
-    sqlite3ExprDelete(pParse->db, Z);
+    sql_expr_free(pParse->db, Z, false);
   }
 }
 %type case_exprlist {ExprList*}
@@ -1203,11 +1209,11 @@ case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). {
   A = sqlite3ExprListAppend(pParse,A, Z.pExpr);
 }
 %type case_else {Expr*}
-%destructor case_else {sqlite3ExprDelete(pParse->db, $$);}
+%destructor case_else {sql_expr_free(pParse->db, $$, false);}
 case_else(A) ::=  ELSE expr(X).         {A = X.pExpr;}
 case_else(A) ::=  .                     {A = 0;} 
 %type case_operand {Expr*}
-%destructor case_operand {sqlite3ExprDelete(pParse->db, $$);}
+%destructor case_operand {sql_expr_free(pParse->db, $$, false);}
 case_operand(A) ::= expr(X).            {A = X.pExpr; /*A-overwrites-X*/} 
 case_operand(A) ::= .                   {A = 0;} 
 
@@ -1377,7 +1383,7 @@ foreach_clause ::= .
 foreach_clause ::= FOR EACH ROW.
 
 %type when_clause {Expr*}
-%destructor when_clause {sqlite3ExprDelete(pParse->db, $$);}
+%destructor when_clause {sql_expr_free(pParse->db, $$, false);}
 when_clause(A) ::= .             { A = 0; }
 when_clause(A) ::= WHEN expr(X). { A = X.pExpr; }
 
diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c
index 18e25cf..63997f2 100644
--- a/src/box/sql/resolve.c
+++ b/src/box/sql/resolve.c
@@ -115,7 +115,7 @@ resolveAlias(Parse * pParse,	/* Parsing context */
 	}
 	ExprSetProperty(pDup, EP_Alias);
 
-	/* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
+	/* Before calling sql_expr_free(), set the EP_Static flag. This
 	 * prevents ExprDelete() from deleting the Expr structure itself,
 	 * allowing it to be repopulated by the memcpy() on the following line.
 	 * The pExpr->u.zToken might point into memory that will be freed by the
@@ -123,7 +123,7 @@ resolveAlias(Parse * pParse,	/* Parsing context */
 	 * make a copy of the token before doing the sqlite3DbFree().
 	 */
 	ExprSetProperty(pExpr, EP_Static);
-	sqlite3ExprDelete(db, pExpr);
+	sql_expr_free(db, pExpr, false);
 	memcpy(pExpr, pDup, sizeof(*pExpr));
 	if (!ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken != 0) {
 		assert((pExpr->flags & (EP_Reduced | EP_TokenOnly)) == 0);
@@ -462,9 +462,9 @@ lookupName(Parse * pParse,	/* The parsing context */
 
 	/* Clean up and return
 	 */
-	sqlite3ExprDelete(db, pExpr->pLeft);
+	sql_expr_free(db, pExpr->pLeft, false);
 	pExpr->pLeft = 0;
-	sqlite3ExprDelete(db, pExpr->pRight);
+	sql_expr_free(db, pExpr->pRight, false);
 	pExpr->pRight = 0;
 	pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN);
  lookupname_end:
@@ -1030,7 +1030,7 @@ resolveCompoundOrderBy(Parse * pParse,	/* Parsing context.  Leave error messages
 						    resolveOrderByTermToExprList
 						    (pParse, pSelect, pDup);
 					}
-					sqlite3ExprDelete(db, pDup);
+					sql_expr_free(db, pDup, false);
 				}
 			}
 			if (iCol > 0) {
@@ -1052,7 +1052,7 @@ resolveCompoundOrderBy(Parse * pParse,	/* Parsing context.  Leave error messages
 					assert(pParent->pLeft == pE);
 					pParent->pLeft = pNew;
 				}
-				sqlite3ExprDelete(db, pE);
+				sql_expr_free(db, pE, false);
 				pItem->u.x.iOrderByCol = (u16) iCol;
 				pItem->done = 1;
 			} else {
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index c14bd74..cd1bb77 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -94,12 +94,12 @@ clearSelect(sqlite3 * db, Select * p, int bFree)
 		Select *pPrior = p->pPrior;
 		sqlite3ExprListDelete(db, p->pEList);
 		sqlite3SrcListDelete(db, p->pSrc);
-		sqlite3ExprDelete(db, p->pWhere);
+		sql_expr_free(db, p->pWhere, false);
 		sqlite3ExprListDelete(db, p->pGroupBy);
-		sqlite3ExprDelete(db, p->pHaving);
+		sql_expr_free(db, p->pHaving, false);
 		sqlite3ExprListDelete(db, p->pOrderBy);
-		sqlite3ExprDelete(db, p->pLimit);
-		sqlite3ExprDelete(db, p->pOffset);
+		sql_expr_free(db, p->pLimit, false);
+		sql_expr_free(db, p->pOffset, false);
 		if (p->pWith)
 			sqlite3WithDelete(db, p->pWith);
 		if (bFree)
@@ -2669,7 +2669,7 @@ multiSelect(Parse * pParse,	/* Parsing context */
 							     pPrior->
 							     nSelectRow);
 				}
-				sqlite3ExprDelete(db, p->pLimit);
+				sql_expr_free(db, p->pLimit, false);
 				p->pLimit = pLimit;
 				p->pOffset = pOffset;
 				p->iLimit = 0;
@@ -2768,7 +2768,7 @@ multiSelect(Parse * pParse,	/* Parsing context */
 				p->pPrior = pPrior;
 				if (p->nSelectRow > pPrior->nSelectRow)
 					p->nSelectRow = pPrior->nSelectRow;
-				sqlite3ExprDelete(db, p->pLimit);
+				sql_expr_free(db, p->pLimit, false);
 				p->pLimit = pLimit;
 				p->pOffset = pOffset;
 
@@ -3297,9 +3297,9 @@ multiSelectOrderBy(Parse * pParse,	/* Parsing context */
 	} else {
 		regLimitA = regLimitB = 0;
 	}
-	sqlite3ExprDelete(db, p->pLimit);
+	sql_expr_free(db, p->pLimit, false);
 	p->pLimit = 0;
-	sqlite3ExprDelete(db, p->pOffset);
+	sql_expr_free(db, p->pOffset, false);
 	p->pOffset = 0;
 
 	regAddrA = ++pParse->nMem;
@@ -3514,7 +3514,7 @@ substExpr(Parse * pParse,	/* Report errors here */
 					    pExpr->iRightJoinTable;
 					pNew->flags |= EP_FromJoin;
 				}
-				sqlite3ExprDelete(db, pExpr);
+				sql_expr_free(db, pExpr, false);
 				pExpr = pNew;
 			}
 		}
@@ -6334,3 +6334,13 @@ sqlite3Select(Parse * pParse,		/* The parser context */
 #endif
 	return rc;
 }
+
+void
+sql_expr_extract_select(struct Parse *parser, struct Select *select)
+{
+	struct ExprList *expr_list = select->pEList;
+	assert(expr_list->nExpr == 1);
+	parser->parsed_expr = sqlite3ExprDup(parser->db,
+					     expr_list->a->pExpr,
+					     EXPRDUP_REDUCE);
+}
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index e9c0b31..df13380 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -63,10 +63,12 @@
  * asterisks and the comment text.
  */
 
-#include <box/field_def.h>
 #include <stdbool.h>
-#include <trivia/util.h>
+
+#include "box/field_def.h"
+#include "box/sql.h"
 #include "box/txn.h"
+#include "trivia/util.h"
 
 /*
  * These #defines should enable >2GB file support on POSIX if the
@@ -3007,6 +3009,10 @@ struct Parse {
 	With *pWithToFree;	/* Free this WITH object at the end of the parse */
 
 	bool initiateTTrans;	/* Initiate Tarantool transaction */
+	/** If set - do not emit byte code at all, just parse.  */
+	bool parse_only;
+	/** If parse_only is set to true, store parsed expression. */
+	struct Expr *parsed_expr;
 };
 
 /*
@@ -3521,7 +3527,6 @@ void sqlite3PExprAddSelect(Parse *, Expr *, Select *);
 Expr *sqlite3ExprAnd(sqlite3 *, Expr *, Expr *);
 Expr *sqlite3ExprFunction(Parse *, ExprList *, Token *);
 void sqlite3ExprAssignVarNumber(Parse *, Expr *, u32);
-void sqlite3ExprDelete(sqlite3 *, Expr *);
 ExprList *sqlite3ExprListAppend(Parse *, ExprList *, Expr *);
 ExprList *sqlite3ExprListAppendVector(Parse *, ExprList *, IdList *, Expr *);
 void sqlite3ExprListSetSortOrder(ExprList *, int);
diff --git a/src/box/sql/tokenize.c b/src/box/sql/tokenize.c
index f810db4..67d8cce 100644
--- a/src/box/sql/tokenize.c
+++ b/src/box/sql/tokenize.c
@@ -652,3 +652,112 @@ sqlite3RunParser(Parse * pParse, const char *zSql, char **pzErrMsg)
 	assert(nErr == 0 || pParse->rc != SQLITE_OK);
 	return nErr;
 }
+
+int
+sql_expr_compile(sqlite3 *db,
+		 const char *expr,
+		 struct Expr **result,
+		 char **err)
+{
+	struct Parse parser;
+	int nErr = 0;		/* Number of errors encountered */
+	int i;			/* Loop counter */
+	void *engine;		/* The LEMON-generated LALR(1) parser */
+	int token_type;		/* type of the next token */
+	int last_token_type = -1;	/* type of the previous token */
+	int mxSqlLen;		/* Max length of an SQL string */
+
+	assert(expr != 0);
+	mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
+	memset(&parser, 0, sizeof(struct Parse));
+	parser.rc = SQLITE_OK;
+	parser.zTail = expr;
+	parser.db = db;
+	parser.pToplevel = NULL;
+	parser.parse_only = true;
+	i = 0;
+	assert(err != 0);
+	engine = sqlite3ParserAlloc(sqlite3Malloc);
+	if (engine == NULL) {
+		sqlite3OomFault(db);
+		return SQLITE_NOMEM_BKPT;
+	}
+
+	const char *outer = "SELECT ";
+	char *stmt = (char*)region_alloc(&fiber()->gc, strlen(outer) + strlen(expr) + 1);
+	if (stmt == NULL) {
+		sqlite3OomFault(db);
+		return SQLITE_NOMEM_BKPT;
+	}
+	sprintf(stmt, "%s%s", outer, expr);
+	while (true) {
+		assert(i >= 0);
+		if (stmt[i] != 0) {
+			parser.sLastToken.z = &stmt[i];
+			parser.sLastToken.n =
+			    sqlite3GetToken((u8 *) & stmt[i], &token_type,
+					    &parser.sLastToken.isReserved);
+			i += parser.sLastToken.n;
+			if (i > mxSqlLen) {
+				parser.rc = SQLITE_TOOBIG;
+				break;
+			}
+		} else {
+			/* Upon reaching the end of input, call
+			 * the parser two more times with tokens
+			 * TK_SEMI and 0, in that order.
+			 */
+			if (last_token_type == TK_SEMI)
+				token_type = 0;
+			else if (last_token_type == 0)
+				break;
+			else
+				token_type = TK_SEMI;
+		}
+		if (token_type >= TK_SPACE) {
+			assert(token_type == TK_SPACE
+			       || token_type == TK_ILLEGAL);
+			if (token_type == TK_ILLEGAL) {
+				sqlite3ErrorMsg(&parser,
+						"unrecognized token: \"%T\"",
+						&parser.sLastToken);
+				break;
+			}
+		} else {
+			sqlite3Parser(engine, token_type, parser.sLastToken,
+				      &parser);
+			last_token_type = token_type;
+			if (parser.rc != SQLITE_OK || db->mallocFailed)
+				break;
+		}
+	}
+	assert(nErr == 0);
+	assert(stmt[i] == '\0');
+	sqlite3ParserFree(engine, sqlite3_free);
+	if (db->mallocFailed)
+		parser.rc = SQLITE_NOMEM_BKPT;
+	if (parser.rc != SQLITE_OK && parser.rc != SQLITE_DONE
+	    && parser.zErrMsg == 0) {
+		parser.zErrMsg =
+		    sqlite3MPrintf(db, "%s", sqlite3ErrStr(parser.rc));
+	}
+	assert(err != 0);
+	if (parser.zErrMsg) {
+		*err = parser.zErrMsg;
+		sqlite3_log(parser.rc, "%s", *err);
+		parser.zErrMsg = 0;
+		nErr++;
+	}
+
+	assert(parser.pVdbe == NULL);
+	assert(parser.pNewTable == NULL);
+	assert(parser.pWithToFree == NULL);
+	assert(parser.pAinc == NULL);
+	assert(parser.pZombieTab == NULL);
+	assert(parser.pNewTrigger == NULL);
+	assert(parser.pVList == NULL);
+
+	assert(nErr == 0 || parser.rc != SQLITE_OK);
+	*result = parser.parsed_expr;
+	return nErr;
+}
diff --git a/src/box/sql/trigger.c b/src/box/sql/trigger.c
index 5460d1a..0cf3712 100644
--- a/src/box/sql/trigger.c
+++ b/src/box/sql/trigger.c
@@ -52,7 +52,7 @@ sqlite3DeleteTriggerStep(sqlite3 * db, TriggerStep * pTriggerStep)
 		TriggerStep *pTmp = pTriggerStep;
 		pTriggerStep = pTriggerStep->pNext;
 
-		sqlite3ExprDelete(db, pTmp->pWhere);
+		sql_expr_free(db, pTmp->pWhere, false);
 		sqlite3ExprListDelete(db, pTmp->pExprList);
 		sqlite3SelectDelete(db, pTmp->pSelect);
 		sqlite3IdListDelete(db, pTmp->pIdList);
@@ -185,7 +185,7 @@ sqlite3BeginTrigger(Parse * pParse,	/* The parse context of the CREATE TRIGGER s
 	sqlite3DbFree(db, zName);
 	sqlite3SrcListDelete(db, pTableName);
 	sqlite3IdListDelete(db, pColumns);
-	sqlite3ExprDelete(db, pWhen);
+	sql_expr_free(db, pWhen, false);
 	if (!pParse->pNewTrigger) {
 		sqlite3DeleteTrigger(db, pTrigger);
 	} else {
@@ -447,7 +447,7 @@ sqlite3TriggerUpdateStep(sqlite3 * db,	/* The database connection */
 		pTriggerStep->orconf = orconf;
 	}
 	sqlite3ExprListDelete(db, pEList);
-	sqlite3ExprDelete(db, pWhere);
+	sql_expr_free(db, pWhere, false);
 	return pTriggerStep;
 }
 
@@ -470,7 +470,7 @@ sqlite3TriggerDeleteStep(sqlite3 * db,	/* Database connection */
 		    sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
 		pTriggerStep->orconf = ON_CONFLICT_ACTION_DEFAULT;
 	}
-	sqlite3ExprDelete(db, pWhere);
+	sql_expr_free(db, pWhere, false);
 	return pTriggerStep;
 }
 
@@ -485,7 +485,7 @@ sqlite3DeleteTrigger(sqlite3 * db, Trigger * pTrigger)
 	sqlite3DeleteTriggerStep(db, pTrigger->step_list);
 	sqlite3DbFree(db, pTrigger->zName);
 	sqlite3DbFree(db, pTrigger->table);
-	sqlite3ExprDelete(db, pTrigger->pWhen);
+	sql_expr_free(db, pTrigger->pWhen, false);
 	sqlite3IdListDelete(db, pTrigger->pColumns);
 	sqlite3DbFree(db, pTrigger);
 }
@@ -911,7 +911,7 @@ codeRowTrigger(Parse * pParse,	/* Current parse context */
 						   iEndTrigger,
 						   SQLITE_JUMPIFNULL);
 			}
-			sqlite3ExprDelete(db, pWhen);
+			sql_expr_free(db, pWhen, false);
 		}
 
 		/* Code the trigger program into the sub-vdbe. */
diff --git a/src/box/sql/update.c b/src/box/sql/update.c
index bf41325..7727ae5 100644
--- a/src/box/sql/update.c
+++ b/src/box/sql/update.c
@@ -667,7 +667,7 @@ sqlite3Update(Parse * pParse,		/* The parser context */
 	sqlite3DbFree(db, aXRef);	/* Also frees aRegIdx[] and aToOpen[] */
 	sqlite3SrcListDelete(db, pTabList);
 	sqlite3ExprListDelete(db, pChanges);
-	sqlite3ExprDelete(db, pWhere);
+	sql_expr_free(db, pWhere, false);
 	return;
 }
 
diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
index 568ef99..8b06bae 100644
--- a/src/box/sql/wherecode.c
+++ b/src/box/sql/wherecode.c
@@ -1830,7 +1830,7 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo,	/* Complete information about t
 			pLevel->iIdxCur = iCovCur;
 		if (pAndExpr) {
 			pAndExpr->pLeft = 0;
-			sqlite3ExprDelete(db, pAndExpr);
+			sql_expr_free(db, pAndExpr, false);
 		}
 		sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
 		sqlite3VdbeGoto(v, pLevel->addrBrk);
diff --git a/src/box/sql/whereexpr.c b/src/box/sql/whereexpr.c
index 26dcd6a..ccdff46 100644
--- a/src/box/sql/whereexpr.c
+++ b/src/box/sql/whereexpr.c
@@ -97,7 +97,7 @@ whereClauseInsert(WhereClause * pWC, Expr * p, u16 wtFlags)
 					 sizeof(pWC->a[0]) * pWC->nSlot * 2);
 		if (pWC->a == 0) {
 			if (wtFlags & TERM_DYNAMIC) {
-				sqlite3ExprDelete(db, p);
+				sql_expr_free(db, p, false);
 			}
 			pWC->a = pOld;
 			return 0;
@@ -1057,7 +1057,7 @@ exprAnalyze(SrcList * pSrc,	/* the FROM clause */
 				int idxNew;
 				pDup = sqlite3ExprDup(db, pExpr, 0);
 				if (db->mallocFailed) {
-					sqlite3ExprDelete(db, pDup);
+					sql_expr_free(db, pDup, false);
 					return;
 				}
 				idxNew =
@@ -1398,7 +1398,7 @@ sqlite3WhereClauseClear(WhereClause * pWC)
 	sqlite3 *db = pWC->pWInfo->pParse->db;
 	for (i = pWC->nTerm - 1, a = pWC->a; i >= 0; i--, a++) {
 		if (a->wtFlags & TERM_DYNAMIC) {
-			sqlite3ExprDelete(db, a->pExpr);
+			sql_expr_free(db, a->pExpr, false);
 		}
 		if (a->wtFlags & TERM_ORINFO) {
 			whereOrInfoDelete(db, a->u.pOrInfo);
-- 
2.11.0

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [tarantool-patches] Re: [PATCH 3/3] sql: move default col values to Tarantool's core
  2018-03-31  3:55     ` Kirill Yukhin
  2018-03-31  4:24       ` [tarantool-patches] [PATCH] " Kirill Yukhin
@ 2018-04-03  6:29       ` Kirill Yukhin
  1 sibling, 0 replies; 8+ messages in thread
From: Kirill Yukhin @ 2018-04-03  6:29 UTC (permalink / raw)
  To: v.shpilevoy; +Cc: tarantool-patches

Hello,

Vlad removed one more memory issue and refactored sql_expr_compile().
I am completely OK w/ his changes and will push it to 2.x branch.

Final patch in the bottom.

--
Regards, Kirill Yukhin

sql: move default col values to Tarantool's core

Extract expressions parsing into separate routine to
allow Tarantool's backend compile DEFAULT statements w/o
SQL machinery at all. So far, for DEFAULT values no context
is needed: only constant expressions and built-ins are allowed.
In future, table context will be added to allow use column
values for CHECK constraint expressions.

Move DEFAULT string value to space_def. Move compiled expresion
to field_def as well. Reason not to move compiled expression
to tuple_field as follows: we do not want to engage parser
during tuple validation. So, do it in alter.cc.

In order to allow expression duplication in alter.cc: expose
those routines from expr.c and make their names correspond to
coding style.

Since recovery is performed before SQL fronend initialization:
split it into two pieces: 1. create SQL handler, enable
all subsystems 2. Do recovery.  This will allow to run
parser during recovery, since it needs db handle so far.

Part of #3235

25 files changed, 909 insertions(+), 637 deletions(-)
src/CMakeLists.txt      |   2 +-
src/box/alter.cc        |  23 +-
src/box/box.cc          |   3 +-
src/box/field_def.c     |   5 +-
src/box/field_def.h     |   4 +
src/box/space_def.c     | 127 +++++--
src/box/space_def.h     |  18 +-
src/box/sql.c           |  51 ++-
src/box/sql.h           |  90 ++++-
src/box/sql/build.c     |  18 +-
src/box/sql/delete.c    |  12 +-
src/box/sql/expr.c      | 127 +++----
src/box/sql/fkey.c      |  13 +-
src/box/sql/insert.c    |  31 +-
src/box/sql/main.c      |  15 -
src/box/sql/parse.c     | 876 ++++++++++++++++++++++++------------------------
src/box/sql/parse.y     |  32 +-
src/box/sql/resolve.c   |  12 +-
src/box/sql/select.c    |  28 +-
src/box/sql/sqliteInt.h |  11 +-
src/box/sql/tokenize.c  |  26 ++
src/box/sql/trigger.c   |  12 +-
src/box/sql/update.c    |   2 +-
src/box/sql/wherecode.c |   2 +-
src/box/sql/whereexpr.c |   6 +-

modified   src/CMakeLists.txt
@@ -268,7 +268,7 @@ add_executable(
 	${LIBUTIL_FREEBSD_SRC}/flopen.c
 	${LIBUTIL_FREEBSD_SRC}/pidfile.c)
 
-add_dependencies(tarantool build_bundled_libs preprocess_exports)
+add_dependencies(tarantool build_bundled_libs preprocess_exports sql)
 
 # Re-link if exports changed
 set_target_properties(tarantool PROPERTIES LINK_DEPENDS ${exports_file})
modified   src/box/alter.cc
@@ -52,6 +52,7 @@
 #include "memtx_tuple.h"
 #include "version.h"
 #include "sequence.h"
+#include "sql.h"
 
 /**
  * chap-sha1 of empty string, i.e.
@@ -403,6 +404,11 @@ field_def_decode(struct field_def *field, const char **data,
 			  tt_sprintf("collation is reasonable only for "
 				     "string, scalar and any fields"));
 	}
+
+	if (field->default_value != NULL &&
+	    sql_expr_compile(sql_get(), field->default_value,
+			     &field->default_value_expr) != 0)
+		diag_raise();
 }
 
 /**
@@ -429,10 +435,20 @@ space_format_decode(const char *data, uint32_t *out_count,
 	size_t size = count * sizeof(struct field_def);
 	struct field_def *region_defs =
 		(struct field_def *) region_alloc_xc(region, size);
+	/*
+	 * Nullify to prevent a case when decoding will fail in
+	 * the middle and space_def_destroy_fields() below will
+	 * work with garbage pointers.
+	 */
+	memset(region_defs, 0, size);
+	auto fields_guard = make_scoped_guard([=] {
+		space_def_destroy_fields(region_defs, count);
+	});
 	for (uint32_t i = 0; i < count; ++i) {
 		field_def_decode(&region_defs[i], &data, space_name, name_len,
 				 errcode, i, region);
 	}
+	fields_guard.is_active = false;
 	return region_defs;
 }
 
@@ -488,6 +504,9 @@ space_def_new_from_tuple(struct tuple *tuple, uint32_t errcode,
 					 MP_ARRAY);
 	fields = space_format_decode(format, &field_count, name,
 				     name_len, errcode, region);
+	auto fields_guard = make_scoped_guard([=] {
+		space_def_destroy_fields(fields, field_count);
+	});
 	if (exact_field_count != 0 &&
 	    exact_field_count < field_count) {
 		tnt_raise(ClientError, errcode, tt_cstr(name, name_len),
@@ -1455,9 +1474,9 @@ on_replace_dd_space(struct trigger * /* trigger */, void *event)
 		struct space_def *def =
 			space_def_new_from_tuple(new_tuple, ER_CREATE_SPACE,
 						 region);
-		access_check_ddl(def->name, def->uid, SC_SPACE, PRIV_C, true);
 		auto def_guard =
 			make_scoped_guard([=] { space_def_delete(def); });
+		access_check_ddl(def->name, def->uid, SC_SPACE, PRIV_C, true);
 		RLIST_HEAD(empty_list);
 		struct space *space = space_new_xc(def, &empty_list);
 		/**
@@ -1515,9 +1534,9 @@ on_replace_dd_space(struct trigger * /* trigger */, void *event)
 		struct space_def *def =
 			space_def_new_from_tuple(new_tuple, ER_ALTER_SPACE,
 						 region);
-		access_check_ddl(def->name, def->uid, SC_SPACE, PRIV_A, true);
 		auto def_guard =
 			make_scoped_guard([=] { space_def_delete(def); });
+		access_check_ddl(def->name, def->uid, SC_SPACE, PRIV_A, true);
 		/*
 		 * Check basic options. Assume the space to be
 		 * empty, because we can not calculate here
modified   src/box/box.cc
@@ -1760,6 +1760,7 @@ box_cfg_xc(void)
 	replication_init();
 	port_init();
 	iproto_init();
+	sql_init();
 	wal_thread_start();
 
 	title("loading");
@@ -1956,7 +1957,7 @@ box_cfg_xc(void)
 	/* Follow replica */
 	replicaset_follow();
 
-	sql_init();
+	sql_load_schema();
 
 	say_info("ready to accept requests");
 
modified   src/box/field_def.c
@@ -94,6 +94,7 @@ const struct opt_def field_def_reg[] = {
 	OPT_DEF_ENUM("nullable_action", on_conflict_action, struct field_def,
 		     nullable_action, NULL),
 	OPT_DEF("collation", OPT_UINT32, struct field_def, coll_id),
+	OPT_DEF("default", OPT_STRPTR, struct field_def, default_value),
 	OPT_END,
 };
 
@@ -102,7 +103,9 @@ const struct field_def field_def_default = {
 	.name = NULL,
 	.is_nullable = false,
 	.nullable_action = ON_CONFLICT_ACTION_DEFAULT,
-	.coll_id = COLL_NONE
+	.coll_id = COLL_NONE,
+	.default_value = NULL,
+	.default_value_expr = NULL
 };
 
 enum field_type
modified   src/box/field_def.h
@@ -110,6 +110,10 @@ struct field_def {
 	enum on_conflict_action nullable_action;
 	/** Collation ID for string comparison. */
 	uint32_t coll_id;
+	/** 0-terminated SQL expression for DEFAULT value. */
+	char *default_value;
+	/** AST for parsed default value. */
+	struct Expr *default_value_expr;
 };
 
 #if defined(__cplusplus)
modified   src/box/space_def.c
@@ -32,6 +32,7 @@
 #include "space_def.h"
 #include "diag.h"
 #include "error.h"
+#include "sql.h"
 
 const struct space_opts space_opts_default = {
 	/* .temporary = */ false,
@@ -49,34 +50,47 @@ const struct opt_def space_opts_reg[] = {
 /**
  * Size of the space_def.
  * @param name_len Length of the space name.
- * @param field_names_size Size of all names.
+ * @param fields Fields array of space format.
  * @param field_count Space field count.
  * @param[out] names_offset Offset from the beginning of a def to
  *             a field names memory.
  * @param[out] fields_offset Offset from the beginning of a def to
  *             a fields array.
+ * @param[out] def_expr_offset Offset from the beginning of a def
+ *             to a def_value_expr array.
  * @retval Size in bytes.
  */
 static inline size_t
-space_def_sizeof(uint32_t name_len, uint32_t field_names_size,
+space_def_sizeof(uint32_t name_len, const struct field_def *fields,
 		 uint32_t field_count, uint32_t *names_offset,
-		 uint32_t *fields_offset)
+		 uint32_t *fields_offset, uint32_t *def_expr_offset)
 {
+	uint32_t field_strs_size = 0;
+	uint32_t def_exprs_size = 0;
+	for (uint32_t i = 0; i < field_count; ++i) {
+		field_strs_size += strlen(fields[i].name) + 1;
+		if (fields[i].default_value != NULL) {
+			assert(fields[i].default_value_expr != NULL);
+			int len = strlen(fields[i].default_value);
+			field_strs_size += len + 1;
+			struct Expr *e = fields[i].default_value_expr;
+			def_exprs_size += sql_expr_sizeof(e, 0);
+		}
+	}
+
 	*fields_offset = sizeof(struct space_def) + name_len + 1;
 	*names_offset = *fields_offset + field_count * sizeof(struct field_def);
-	return *names_offset + field_names_size;
+	*def_expr_offset = *names_offset + field_strs_size;
+	return *def_expr_offset + def_exprs_size;
 }
 
 struct space_def *
 space_def_dup(const struct space_def *src)
 {
-	uint32_t names_offset, fields_offset;
-	uint32_t field_names_size = 0;
-	for (uint32_t i = 0; i < src->field_count; ++i)
-		field_names_size += strlen(src->fields[i].name) + 1;
-	size_t size = space_def_sizeof(strlen(src->name), field_names_size,
-				       src->field_count, &names_offset,
-				       &fields_offset);
+	uint32_t strs_offset, fields_offset, def_expr_offset;
+	size_t size = space_def_sizeof(strlen(src->name), src->fields,
+				       src->field_count, &strs_offset,
+				       &fields_offset, &def_expr_offset);
 	struct space_def *ret = (struct space_def *) malloc(size);
 	if (ret == NULL) {
 		diag_set(OutOfMemory, size, "malloc", "ret");
@@ -92,12 +106,33 @@ space_def_dup(const struct space_def *src)
 			return NULL;
 		}
 	}
-	char *name_pos = (char *)ret + names_offset;
+	char *strs_pos = (char *)ret + strs_offset;
+	char *expr_pos = (char *)ret + def_expr_offset;
 	if (src->field_count > 0) {
 		ret->fields = (struct field_def *)((char *)ret + fields_offset);
 		for (uint32_t i = 0; i < src->field_count; ++i) {
-			ret->fields[i].name = name_pos;
-			name_pos += strlen(name_pos) + 1;
+			ret->fields[i].name = strs_pos;
+			strs_pos += strlen(strs_pos) + 1;
+			if (src->fields[i].default_value != NULL) {
+				ret->fields[i].default_value = strs_pos;
+				strs_pos += strlen(strs_pos) + 1;
+
+				struct Expr *e =
+					src->fields[i].default_value_expr;
+				assert(e != NULL);
+				char *expr_pos_old = expr_pos;
+				e = sql_expr_dup(sql_get(), e, 0, &expr_pos);
+				assert(e != NULL);
+				/* Note: due to SQL legacy
+				 * duplicactor pointer is not
+				 * promoted for REDUCED exprs.
+				 * Will be fixed w/ Expt
+				 * allocation refactoring.
+				 */
+				assert(expr_pos_old == expr_pos);
+				expr_pos += sql_expr_sizeof(e, 0);
+				ret->fields[i].default_value_expr = e;
+			}
 		}
 	}
 	tuple_dictionary_ref(ret->dict);
@@ -111,12 +146,10 @@ space_def_new(uint32_t id, uint32_t uid, uint32_t exact_field_count,
 	      const struct space_opts *opts, const struct field_def *fields,
 	      uint32_t field_count)
 {
-	uint32_t field_names_size = 0;
-	for (uint32_t i = 0; i < field_count; ++i)
-		field_names_size += strlen(fields[i].name) + 1;
-	uint32_t names_offset, fields_offset;
-	size_t size = space_def_sizeof(name_len, field_names_size, field_count,
-				       &names_offset, &fields_offset);
+	uint32_t strs_offset, fields_offset, def_expr_offset;
+	size_t size = space_def_sizeof(name_len, fields, field_count,
+				       &strs_offset, &fields_offset,
+				       &def_expr_offset);
 	struct space_def *def = (struct space_def *) malloc(size);
 	if (def == NULL) {
 		diag_set(OutOfMemory, size, "malloc", "def");
@@ -150,15 +183,42 @@ space_def_new(uint32_t id, uint32_t uid, uint32_t exact_field_count,
 	if (field_count == 0) {
 		def->fields = NULL;
 	} else {
-		char *name_pos = (char *)def + names_offset;
+		char *strs_pos = (char *)def + strs_offset;
+		char *expr_pos = (char *)def + def_expr_offset;
 		def->fields = (struct field_def *)((char *)def + fields_offset);
 		for (uint32_t i = 0; i < field_count; ++i) {
 			def->fields[i] = fields[i];
-			def->fields[i].name = name_pos;
+			def->fields[i].name = strs_pos;
 			uint32_t len = strlen(fields[i].name);
 			memcpy(def->fields[i].name, fields[i].name, len);
 			def->fields[i].name[len] = 0;
-			name_pos += len + 1;
+			strs_pos += len + 1;
+
+			if (fields[i].default_value != NULL) {
+				def->fields[i].default_value = strs_pos;
+				len = strlen(fields[i].default_value);
+				memcpy(def->fields[i].default_value,
+				       fields[i].default_value, len);
+				def->fields[i].default_value[len] = 0;
+				strs_pos += len + 1;
+
+				struct Expr *e =
+					fields[i].default_value_expr;
+				assert(e != NULL);
+				char *expr_pos_old = expr_pos;
+				e = sql_expr_dup(sql_get(), e, 0, &expr_pos);
+				assert(e != NULL);
+				/* Note: due to SQL legacy
+				 * duplicactor pointer is
+				 * not promoted for
+				 * REDUCED exprs. Will be
+				 * fixed w/ Expt
+				 * allocation refactoring.
+				 */
+				assert(expr_pos_old == expr_pos);
+				expr_pos += sql_expr_sizeof(e, 0);
+				def->fields[i].default_value_expr = e;
+			}
 		}
 	}
 	return def;
@@ -217,3 +277,24 @@ space_def_check_compatibility(const struct space_def *old_def,
 	return 0;
 }
 
+/** Free a default value's syntax trees of @a defs. */
+void
+space_def_destroy_fields(struct field_def *fields, uint32_t field_count)
+{
+	for (uint32_t i = 0; i < field_count; ++i) {
+		if (fields[i].default_value_expr != NULL) {
+			sql_expr_free(sql_get(), fields[i].default_value_expr,
+				      true);
+		}
+	}
+}
+
+void
+space_def_delete(struct space_def *def)
+{
+	space_opts_destroy(&def->opts);
+	tuple_dictionary_unref(def->dict);
+	space_def_destroy_fields(def->fields, def->field_count);
+	TRASH(def);
+	free(def);
+}
modified   src/box/space_def.h
@@ -111,18 +111,20 @@ struct space_def {
 	char name[0];
 };
 
+/*
+ * Free a default value syntax trees of @a defs.
+ * @param fields Fields array to destroy.
+ * @param field_count Length of @a fields.
+ */
+void
+space_def_destroy_fields(struct field_def *fields, uint32_t field_count);
+
 /**
  * Delete the space_def object.
  * @param def Def to delete.
  */
-static inline void
-space_def_delete(struct space_def *def)
-{
-	space_opts_destroy(&def->opts);
-	tuple_dictionary_unref(def->dict);
-	TRASH(def);
-	free(def);
-}
+void
+space_def_delete(struct space_def *def);
 
 /**
  * Duplicate space_def object.
modified   src/box/sql.c
@@ -56,7 +56,7 @@
 #include "xrow.h"
 #include "iproto_constants.h"
 
-static sqlite3 *db;
+static sqlite3 *db = NULL;
 
 static const char nil_key[] = { 0x90 }; /* Empty MsgPack array. */
 
@@ -80,6 +80,27 @@ sql_init()
 }
 
 void
+sql_load_schema()
+{
+	int rc;
+	struct session *user_session = current_session();
+	int commit_internal = !(user_session->sql_flags
+				& SQLITE_InternChanges);
+
+	assert(db->init.busy == 0);
+	db->init.busy = 1;
+	db->pSchema = sqlite3SchemaCreate(db);
+	rc = sqlite3InitDatabase(db);
+	if (rc != SQLITE_OK) {
+		sqlite3SchemaClear(db);
+		panic("failed to initialize SQL subsystem");
+	}
+	db->init.busy = 0;
+	if (rc == SQLITE_OK && commit_internal)
+		sqlite3CommitInternalChanges();
+}
+
+void
 sql_free()
 {
 	sqlite3_close(db); db = NULL;
@@ -1451,11 +1472,17 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
 	for (i = 0; i < n; i++) {
 		const char *t;
 		struct coll *coll = NULL;
+		struct Expr *def = aCol[i].pDflt;
 		if (aCol[i].zColl != NULL &&
 		    strcasecmp(aCol[i].zColl, "binary") != 0) {
 			coll = sqlite3FindCollSeq(aCol[i].zColl);
 		}
-		p = enc->encode_map(p, coll ? 5 : 4);
+		int base_len = 4;
+		if (coll != NULL)
+			base_len += 1;
+		if (def != NULL)
+			base_len += 1;
+		p = enc->encode_map(p, base_len);
 		p = enc->encode_str(p, "name", 4);
 		p = enc->encode_str(p, aCol[i].zName, strlen(aCol[i].zName));
 		p = enc->encode_str(p, "type", 4);
@@ -1477,6 +1504,12 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
 			p = enc->encode_str(p, "collation", strlen("collation"));
 			p = enc->encode_uint(p, coll->id);
 		}
+		if (def != NULL) {
+		        assert((def->flags & EP_IntValue) == 0);
+			assert(def->u.zToken != NULL);
+			p = enc->encode_str(p, "default", strlen("default"));
+			p = enc->encode_str(p, def->u.zToken, strlen(def->u.zToken));
+		}
 	}
 	return (int)(p - base);
 }
@@ -1670,3 +1703,17 @@ tarantoolSqlNextSeqId(uint64_t *max_id)
 
 	return tuple_field_u64(tuple, BOX_SEQUENCE_FIELD_ID, max_id);
 }
+
+struct Expr*
+space_column_default_expr(uint32_t space_id, uint32_t fieldno)
+{
+	struct space *space;
+	space = space_cache_find(space_id);
+	assert(space != NULL);
+	assert(space->def != NULL);
+	if (space->def->opts.is_view)
+		return NULL;
+	assert(space->def->field_count > fieldno);
+
+	return space->def->fields[fieldno].default_value_expr;
+}
modified   src/box/sql.h
@@ -31,6 +31,9 @@
  * SUCH DAMAGE.
  */
 
+#include <stdbool.h>
+#include <stdint.h>
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -39,9 +42,12 @@ void
 sql_init();
 
 void
+sql_load_schema();
+
+void
 sql_free();
 
-/*
+/**
  * struct sqlite3 *
  * sql_get();
  *
@@ -51,10 +57,92 @@ sql_free();
  * don't do anything finicky like sqlite3_close.
  * Behind the scenes, this sqlite was rigged to use Tarantool
  * as a data source.
+ * @retval SQL handle.
  */
 struct sqlite3 *
 sql_get();
 
+struct Expr;
+struct Parse;
+struct Select;
+
+/**
+ * Perform parsing of provided expression. This is done by
+ * surrounding the expression w/ 'SELECT ' prefix and perform
+ * convetional parsing. Then extract result expression value from
+ * stuct Select and return it.
+ * @param db SQL context handle.
+ * @param expr Expression to parse.
+ * @param[out] result Result: AST structure.
+ *
+ * @retval Error code if any.
+ */
+int
+sql_expr_compile(struct sqlite3 *db, const char *expr, struct Expr **result);
+
+/**
+ * Store duplicate of a parsed expression into @a parser.
+ * @param parser Parser context.
+ * @param select Select to extract from.
+ */
+void
+sql_expr_extract_select(struct Parse *parser, struct Select *select);
+
+/**
+ * Given space_id and field number, return default value
+ * for the field.
+ * @param space_id Space ID.
+ * @param fieldno Field index.
+ * @retval Pointer to AST corresponding to default value.
+ * Can be NULL if no DEFAULT specified or it is a view.
+ */
+struct Expr*
+space_column_default_expr(uint32_t space_id, uint32_t fieldno);
+
+/**
+ * Return the number of bytes required to create a duplicate of the
+ * expression passed as the first argument. The second argument is a
+ * mask containing EXPRDUP_XXX flags.
+ *
+ * The value returned includes space to create a copy of the Expr struct
+ * itself and the buffer referred to by Expr.u.zToken, if any.
+ *
+ * If the EXPRDUP_REDUCE flag is set, then the return value includes
+ * space to duplicate all Expr nodes in the tree formed by Expr.pLeft
+ * and Expr.pRight variables (but not for any structures pointed to or
+ * descended from the Expr.x.pList or Expr.x.pSelect variables).
+ * @param expr Root expression of AST.
+ * @param flags The only possible flag is REDUCED, 0 otherwise.
+ * @retval Size in bytes needed to duplicate AST and all private
+ * strings.
+ */
+int
+sql_expr_sizeof(struct Expr *p, int flags);
+
+/**
+ * This function is similar to sqlite3ExprDup(), except that if pzBuffer
+ * is not NULL then *pzBuffer is assumed to point to a buffer large enough
+ * to store the copy of expression p, the copies of p->u.zToken
+ * (if applicable), and the copies of the p->pLeft and p->pRight expressions,
+ * if any. Before returning, *pzBuffer is set to the first byte past the
+ * portion of the buffer copied into by this function.
+ * @param db SQL handle.
+ * @param p Root of expression's AST.
+ * @param dupFlags EXPRDUP_REDUCE or 0.
+ * @param pzBuffer If not NULL, then buffer to store duplicate.
+ */
+struct Expr *
+sql_expr_dup(struct sqlite3 *db, struct Expr *p, int flags, char **buffer);
+
+/**
+ * Free AST pointed by expr.
+ * @param db SQL handle.
+ * @param expr Root pointer of ASR
+ * @param extern_alloc True if skeleton was allocated externally.
+ */
+void
+sql_expr_free(struct sqlite3 *db, struct Expr *expr, bool extern_alloc);
+
 #if defined(__cplusplus)
 } /* extern "C" { */
 #endif
modified   src/box/sql/build.c
@@ -286,7 +286,7 @@ freeIndex(sqlite3 * db, Index * p)
 #ifndef SQLITE_OMIT_ANALYZE
 	sqlite3DeleteIndexSamples(db, p);
 #endif
-	sqlite3ExprDelete(db, p->pPartIdxWhere);
+	sql_expr_free(db, p->pPartIdxWhere, false);
 	sqlite3ExprListDelete(db, p->aColExpr);
 	sqlite3DbFree(db, p->zColAff);
 	sqlite3_free(p->aiRowEst);
@@ -366,7 +366,7 @@ sqlite3DeleteColumnNames(sqlite3 * db, Table * pTable)
 	if ((pCol = pTable->aCol) != 0) {
 		for (i = 0; i < pTable->nCol; i++, pCol++) {
 			sqlite3DbFree(db, pCol->zName);
-			sqlite3ExprDelete(db, pCol->pDflt);
+			sql_expr_free(db, pCol->pDflt, false);
 			sqlite3DbFree(db, pCol->zColl);
 		}
 		sqlite3DbFree(db, pTable->aCol);
@@ -893,7 +893,7 @@ sqlite3AddDefaultValue(Parse * pParse, ExprSpan * pSpan)
 			 * is required by pragma table_info.
 			 */
 			Expr x;
-			sqlite3ExprDelete(db, pCol->pDflt);
+			sql_expr_free(db, pCol->pDflt, false);
 			memset(&x, 0, sizeof(x));
 			x.op = TK_SPAN;
 			x.u.zToken = sqlite3DbStrNDup(db, (char *)pSpan->zStart,
@@ -905,7 +905,7 @@ sqlite3AddDefaultValue(Parse * pParse, ExprSpan * pSpan)
 			sqlite3DbFree(db, x.u.zToken);
 		}
 	}
-	sqlite3ExprDelete(db, pSpan->pExpr);
+	sql_expr_free(db, pSpan->pExpr, false);
 }
 
 
@@ -1019,9 +1019,7 @@ sqlite3AddCheckConstraint(Parse * pParse,	/* Parsing context */
 		}
 	} else
 #endif
-	{
-		sqlite3ExprDelete(pParse->db, pCheckExpr);
-	}
+		sql_expr_free(pParse->db, pCheckExpr, false);
 }
 
 /*
@@ -3256,7 +3254,7 @@ sqlite3CreateIndex(Parse * pParse,	/* All information about this parse */
  exit_create_index:
 	if (pIndex)
 		freeIndex(db, pIndex);
-	sqlite3ExprDelete(db, pPIWhere);
+	sql_expr_free(db, pPIWhere, false);
 	sqlite3ExprListDelete(db, pList);
 	sqlite3SrcListDelete(db, pTblName);
 	sqlite3DbFree(db, zName);
@@ -3728,7 +3726,7 @@ sqlite3SrcListDelete(sqlite3 * db, SrcList * pList)
 			sqlite3ExprListDelete(db, pItem->u1.pFuncArg);
 		sqlite3DeleteTable(db, pItem->pTab);
 		sqlite3SelectDelete(db, pItem->pSelect);
-		sqlite3ExprDelete(db, pItem->pOn);
+		sql_expr_free(db, pItem->pOn, false);
 		sqlite3IdListDelete(db, pItem->pUsing);
 	}
 	sqlite3DbFree(db, pList);
@@ -3784,7 +3782,7 @@ sqlite3SrcListAppendFromTerm(Parse * pParse,	/* Parsing context */
 
  append_from_error:
 	assert(p == 0);
-	sqlite3ExprDelete(db, pOn);
+	sql_expr_free(db, pOn, false);
 	sqlite3IdListDelete(db, pUsing);
 	sqlite3SelectDelete(db, pSubquery);
 	return 0;
modified   src/box/sql/delete.c
@@ -212,10 +212,10 @@ sqlite3LimitWhere(Parse * pParse,	/* The parser context */
 	return pInClause;
 
  limit_where_cleanup:
-	sqlite3ExprDelete(pParse->db, pWhere);
+	sql_expr_free(pParse->db, pWhere);
 	sqlite3ExprListDelete(pParse->db, pOrderBy);
-	sqlite3ExprDelete(pParse->db, pLimit);
-	sqlite3ExprDelete(pParse->db, pOffset);
+	sql_expr_free(pParse->db, pLimit);
+	sql_expr_free(pParse->db, pOffset);
 	return 0;
 }
 #endif				/* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) */
@@ -571,7 +571,7 @@ sqlite3DeleteFrom(Parse * pParse,	/* The parser context */
 
  delete_from_cleanup:
 	sqlite3SrcListDelete(db, pTabList);
-	sqlite3ExprDelete(db, pWhere);
+	sql_expr_free(db, pWhere, false);
 	sqlite3DbFree(db, aToOpen);
 	return;
 }
@@ -636,9 +636,9 @@ sqlite3DeleteByKey(Parse *pParse, char *zTab, const char **columns,
 	return;
 
  error:
-	sqlite3ExprDelete(pParse->db, where);
+	sql_expr_free(pParse->db, where, false);
 	for (int i = 0; i < nPairs; ++i)
-		sqlite3ExprDelete(pParse->db, values[i]);
+		sql_expr_free(pParse->db, values[i], false);
 }
 
 /* Make sure "isView" and other macros defined above are undefined. Otherwise
modified   src/box/sql/expr.c
@@ -492,7 +492,7 @@ sqlite3ExprForVectorField(Parse * pParse,	/* Parsing context */
 		 * pLeft->iTable:   First in an array of register holding result, or 0
 		 *                  if the result is not yet computed.
 		 *
-		 * sqlite3ExprDelete() specifically skips the recursive delete of
+		 * sql_expr_free() specifically skips the recursive delete of
 		 * pLeft on TK_SELECT_COLUMN nodes.  But pRight is followed, so pVector
 		 * can be attached to pRight to cause this node to take ownership of
 		 * pVector.  Typically there will be multiple TK_SELECT_COLUMN nodes
@@ -935,8 +935,8 @@ sqlite3ExprAttachSubtrees(sqlite3 * db,
 {
 	if (pRoot == 0) {
 		assert(db->mallocFailed);
-		sqlite3ExprDelete(db, pLeft);
-		sqlite3ExprDelete(db, pRight);
+		sql_expr_free(db, pLeft, false);
+		sql_expr_free(db, pRight, false);
 	} else {
 		if (pRight) {
 			pRoot->pRight = pRight;
@@ -1052,8 +1052,8 @@ sqlite3ExprAnd(sqlite3 * db, Expr * pLeft, Expr * pRight)
 	} else if (pRight == 0) {
 		return pLeft;
 	} else if (exprAlwaysFalse(pLeft) || exprAlwaysFalse(pRight)) {
-		sqlite3ExprDelete(db, pLeft);
-		sqlite3ExprDelete(db, pRight);
+		sql_expr_free(db, pLeft, false);
+		sql_expr_free(db, pRight, false);
 		return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0],
 					0);
 	} else {
@@ -1172,7 +1172,7 @@ sqlite3ExprAssignVarNumber(Parse * pParse, Expr * pExpr, u32 n)
  * Recursively delete an expression tree.
  */
 static SQLITE_NOINLINE void
-sqlite3ExprDeleteNN(sqlite3 * db, Expr * p)
+sqlite3ExprDeleteNN(sqlite3 * db, Expr * p, bool extern_alloc)
 {
 	assert(p != 0);
 	/* Sanity check: Assert that the IntValue is non-negative if it exists */
@@ -1187,9 +1187,10 @@ sqlite3ExprDeleteNN(sqlite3 * db, Expr * p)
 	if (!ExprHasProperty(p, (EP_TokenOnly | EP_Leaf))) {
 		/* The Expr.x union is never used at the same time as Expr.pRight */
 		assert(p->x.pList == 0 || p->pRight == 0);
-		if (p->pLeft && p->op != TK_SELECT_COLUMN)
-			sqlite3ExprDeleteNN(db, p->pLeft);
-		sqlite3ExprDelete(db, p->pRight);
+		if (p->pLeft && p->op != TK_SELECT_COLUMN && !extern_alloc)
+			sqlite3ExprDeleteNN(db, p->pLeft, extern_alloc);
+		if (!extern_alloc)
+			sql_expr_free(db, p->pRight, extern_alloc);
 		if (ExprHasProperty(p, EP_xIsSelect)) {
 			sqlite3SelectDelete(db, p->x.pSelect);
 		} else {
@@ -1204,10 +1205,10 @@ sqlite3ExprDeleteNN(sqlite3 * db, Expr * p)
 }
 
 void
-sqlite3ExprDelete(sqlite3 * db, Expr * p)
+sql_expr_free(sqlite3 *db, Expr *expr, bool extern_alloc)
 {
-	if (p)
-		sqlite3ExprDeleteNN(db, p);
+	if (expr != NULL)
+		sqlite3ExprDeleteNN(db, expr, extern_alloc);
 }
 
 /*
@@ -1298,61 +1299,39 @@ dupedExprNodeSize(Expr * p, int flags)
 	return ROUND8(nByte);
 }
 
-/*
- * Return the number of bytes required to create a duplicate of the
- * expression passed as the first argument. The second argument is a
- * mask containing EXPRDUP_XXX flags.
- *
- * The value returned includes space to create a copy of the Expr struct
- * itself and the buffer referred to by Expr.u.zToken, if any.
- *
- * If the EXPRDUP_REDUCE flag is set, then the return value includes
- * space to duplicate all Expr nodes in the tree formed by Expr.pLeft
- * and Expr.pRight variables (but not for any structures pointed to or
- * descended from the Expr.x.pList or Expr.x.pSelect variables).
- */
-static int
-dupedExprSize(Expr * p, int flags)
+int
+sql_expr_sizeof(struct Expr *p, int flags)
 {
-	int nByte = 0;
-	if (p) {
-		nByte = dupedExprNodeSize(p, flags);
+	int size = 0;
+	if (p != NULL) {
+		size = dupedExprNodeSize(p, flags);
 		if (flags & EXPRDUP_REDUCE) {
-			nByte +=
-			    dupedExprSize(p->pLeft,
-					  flags) + dupedExprSize(p->pRight,
-								 flags);
+			size +=
+			    sql_expr_sizeof(p->pLeft, flags) +
+			    sql_expr_sizeof(p->pRight, flags);
 		}
 	}
-	return nByte;
+	return size;
 }
 
-/*
- * This function is similar to sqlite3ExprDup(), except that if pzBuffer
- * is not NULL then *pzBuffer is assumed to point to a buffer large enough
- * to store the copy of expression p, the copies of p->u.zToken
- * (if applicable), and the copies of the p->pLeft and p->pRight expressions,
- * if any. Before returning, *pzBuffer is set to the first byte past the
- * portion of the buffer copied into by this function.
- */
-static Expr *
-exprDup(sqlite3 * db, Expr * p, int dupFlags, u8 ** pzBuffer)
+struct Expr *
+sql_expr_dup(struct sqlite3 *db, struct Expr *p, int flags, char **buffer)
 {
 	Expr *pNew;		/* Value to return */
-	u8 *zAlloc;		/* Memory space from which to build Expr object */
-	u32 staticFlag;		/* EP_Static if space not obtained from malloc */
+	u32 staticFlag;         /* EP_Static if space not obtained from malloc */
+	char *zAlloc;		/* Memory space from which to build Expr object */
 
 	assert(db != 0);
 	assert(p);
-	assert(dupFlags == 0 || dupFlags == EXPRDUP_REDUCE);
-	assert(pzBuffer == 0 || dupFlags == EXPRDUP_REDUCE);
+	assert(flags == 0 || flags == EXPRDUP_REDUCE);
 
 	/* Figure out where to write the new Expr structure. */
-	if (pzBuffer) {
-		zAlloc = *pzBuffer;
+	if (buffer) {
+		zAlloc = *buffer;
 		staticFlag = EP_Static;
 	} else {
-		zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, dupFlags));
+		zAlloc = sqlite3DbMallocRawNN(db,
+					      sql_expr_sizeof(p, flags));
 		staticFlag = 0;
 	}
 	pNew = (Expr *) zAlloc;
@@ -1363,15 +1342,14 @@ exprDup(sqlite3 * db, Expr * p, int dupFlags, u8 ** pzBuffer)
 		 * EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed
 		 * by the copy of the p->u.zToken string (if any).
 		 */
-		const unsigned nStructSize = dupedExprStructSize(p, dupFlags);
+		const unsigned nStructSize = dupedExprStructSize(p, flags);
 		const int nNewSize = nStructSize & 0xfff;
 		int nToken;
-		if (!ExprHasProperty(p, EP_IntValue) && p->u.zToken) {
+		if (!ExprHasProperty(p, EP_IntValue) && p->u.zToken)
 			nToken = sqlite3Strlen30(p->u.zToken) + 1;
-		} else {
+		else
 			nToken = 0;
-		}
-		if (dupFlags) {
+		if (flags) {
 			assert(ExprHasProperty(p, EP_Reduced) == 0);
 			memcpy(zAlloc, p, nNewSize);
 		} else {
@@ -1401,29 +1379,28 @@ exprDup(sqlite3 * db, Expr * p, int dupFlags, u8 ** pzBuffer)
 			if (ExprHasProperty(p, EP_xIsSelect)) {
 				pNew->x.pSelect =
 				    sqlite3SelectDup(db, p->x.pSelect,
-						     dupFlags);
+						     flags);
 			} else {
 				pNew->x.pList =
 				    sqlite3ExprListDup(db, p->x.pList,
-						       dupFlags);
+						       flags);
 			}
 		}
 
 		/* Fill in pNew->pLeft and pNew->pRight. */
 		if (ExprHasProperty(pNew, EP_Reduced | EP_TokenOnly)) {
-			zAlloc += dupedExprNodeSize(p, dupFlags);
+			zAlloc += dupedExprNodeSize(p, flags);
 			if (!ExprHasProperty(pNew, EP_TokenOnly | EP_Leaf)) {
 				pNew->pLeft = p->pLeft ?
-				    exprDup(db, p->pLeft, EXPRDUP_REDUCE,
-					    &zAlloc) : 0;
+				    sql_expr_dup(db, p->pLeft, EXPRDUP_REDUCE,
+						 &zAlloc) : 0;
 				pNew->pRight =
-				    p->pRight ? exprDup(db, p->pRight,
-							EXPRDUP_REDUCE,
-							&zAlloc) : 0;
-			}
-			if (pzBuffer) {
-				*pzBuffer = zAlloc;
+				    p->pRight ? sql_expr_dup(db, p->pRight,
+							     EXPRDUP_REDUCE,
+							     &zAlloc) : 0;
 			}
+			if (buffer)
+				*buffer = zAlloc;
 		} else {
 			if (!ExprHasProperty(p, EP_TokenOnly | EP_Leaf)) {
 				if (pNew->op == TK_SELECT_COLUMN) {
@@ -1496,7 +1473,7 @@ Expr *
 sqlite3ExprDup(sqlite3 * db, Expr * p, int flags)
 {
 	assert(flags == 0 || flags == EXPRDUP_REDUCE);
-	return p ? exprDup(db, p, flags, 0) : 0;
+	return p ? sql_expr_dup(db, p, flags, 0) : 0;
 }
 
 ExprList *
@@ -1726,7 +1703,7 @@ sqlite3ExprListAppend(Parse * pParse,	/* Parsing context */
 
  no_mem:
 	/* Avoid leaking memory if malloc has failed. */
-	sqlite3ExprDelete(db, pExpr);
+	sql_expr_free(db, pExpr, false);
 	sqlite3ExprListDelete(db, pList);
 	return 0;
 }
@@ -1802,7 +1779,7 @@ sqlite3ExprListAppendVector(Parse * pParse,	/* Parsing context */
 	}
 
  vector_append_error:
-	sqlite3ExprDelete(db, pExpr);
+	sql_expr_free(db, pExpr, false);
 	sqlite3IdListDelete(db, pColumns);
 	return pList;
 }
@@ -1908,7 +1885,7 @@ exprListDeleteNN(sqlite3 * db, ExprList * pList)
 	struct ExprList_item *pItem;
 	assert(pList->a != 0 || pList->nExpr == 0);
 	for (pItem = pList->a, i = 0; i < pList->nExpr; i++, pItem++) {
-		sqlite3ExprDelete(db, pItem->pExpr);
+		sql_expr_free(db, pItem->pExpr, false);
 		sqlite3DbFree(db, pItem->zName);
 		sqlite3DbFree(db, pItem->zSpan);
 	}
@@ -2991,7 +2968,7 @@ sqlite3CodeSubselect(Parse * pParse,	/* Parsing context */
 						  dest.iSDParm);
 				VdbeComment((v, "Init EXISTS result"));
 			}
-			sqlite3ExprDelete(pParse->db, pSel->pLimit);
+			sql_expr_free(pParse->db, pSel->pLimit, false);
 			pSel->pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER,
 							&sqlite3IntTokens[1],
 							0);
@@ -4597,7 +4574,7 @@ sqlite3ExprCodeCopy(Parse * pParse, Expr * pExpr, int target)
 	pExpr = sqlite3ExprDup(db, pExpr, 0);
 	if (!db->mallocFailed)
 		sqlite3ExprCode(pParse, pExpr, target);
-	sqlite3ExprDelete(db, pExpr);
+	sql_expr_free(db, pExpr, false);
 }
 
 /*
@@ -5157,7 +5134,7 @@ sqlite3ExprIfFalseDup(Parse * pParse, Expr * pExpr, int dest, int jumpIfNull)
 	if (db->mallocFailed == 0) {
 		sqlite3ExprIfFalse(pParse, pCopy, dest, jumpIfNull);
 	}
-	sqlite3ExprDelete(db, pCopy);
+	sql_expr_free(db, pCopy, false);
 }
 
 /*
modified   src/box/sql/fkey.c
@@ -698,10 +698,9 @@ fkScanChildren(Parse * pParse,	/* Parse context */
 	}
 
 	/* Clean up the WHERE clause constructed above. */
-	sqlite3ExprDelete(db, pWhere);
-	if (iFkIfZero) {
+	sql_expr_free(db, pWhere, false);
+	if (iFkIfZero)
 		sqlite3VdbeJumpHere(v, iFkIfZero);
-	}
 }
 
 /*
@@ -737,10 +736,10 @@ fkTriggerDelete(sqlite3 * dbMem, Trigger * p)
 {
 	if (p) {
 		TriggerStep *pStep = p->step_list;
-		sqlite3ExprDelete(dbMem, pStep->pWhere);
+		sql_expr_free(dbMem, pStep->pWhere, false);
 		sqlite3ExprListDelete(dbMem, pStep->pExprList);
 		sqlite3SelectDelete(dbMem, pStep->pSelect);
-		sqlite3ExprDelete(dbMem, p->pWhen);
+		sql_expr_free(dbMem, p->pWhen, false);
 		sqlite3DbFree(dbMem, p);
 	}
 }
@@ -1424,8 +1423,8 @@ fkActionTrigger(Parse * pParse,	/* Parse context */
 		/* Re-enable the lookaside buffer, if it was disabled earlier. */
 		db->lookaside.bDisable--;
 
-		sqlite3ExprDelete(db, pWhere);
-		sqlite3ExprDelete(db, pWhen);
+		sql_expr_free(db, pWhere, false);
+		sql_expr_free(db, pWhen, false);
 		sqlite3ExprListDelete(db, pList);
 		sqlite3SelectDelete(db, pSelect);
 		if (db->mallocFailed == 1) {
modified   src/box/sql/insert.c
@@ -346,6 +346,7 @@ sqlite3Insert(Parse * pParse,	/* Parser context */
 	int regTupleid;		/* registers holding insert tupleid */
 	int regData;		/* register holding first column to insert */
 	int *aRegIdx = 0;	/* One register allocated to each index */
+	uint32_t space_id = 0;
 
 #ifndef SQLITE_OMIT_TRIGGER
 	int isView;		/* True if attempting to insert into a view */
@@ -382,6 +383,8 @@ sqlite3Insert(Parse * pParse,	/* Parser context */
 		goto insert_cleanup;
 	}
 
+	space_id = SQLITE_PAGENO_TO_SPACEID(pTab->tnum);
+
 	/* Figure out if we have any triggers and if the table being
 	 * inserted into is a view
 	 */
@@ -677,13 +680,18 @@ sqlite3Insert(Parse * pParse,	/* Parser context */
 			}
 			if ((!useTempTable && !pList)
 			    || (pColumn && j >= pColumn->nId)) {
-				if (i == pTab->iAutoIncPKey)
+				if (i == pTab->iAutoIncPKey) {
 					sqlite3VdbeAddOp2(v, OP_Integer, -1,
 							  regCols + i + 1);
-				else
+				} else {
+					struct Expr *dflt = NULL;
+					dflt = space_column_default_expr(
+						space_id,
+						i);
 					sqlite3ExprCode(pParse,
-							pTab->aCol[i].pDflt,
+							dflt,
 							regCols + i + 1);
+				}
 			} else if (useTempTable) {
 				sqlite3VdbeAddOp3(v, OP_Column, srcTab, j,
 						  regCols + i + 1);
@@ -754,8 +762,12 @@ sqlite3Insert(Parse * pParse,	/* Parser context */
 							  iRegStore);
 					continue;
 				}
+				struct Expr *dflt = NULL;
+				dflt = space_column_default_expr(
+					space_id,
+					i);
 				sqlite3ExprCodeFactorable(pParse,
-							  pTab->aCol[i].pDflt,
+							  dflt,
 							  iRegStore);
 			} else if (useTempTable) {
 				if ((pTab->tabFlags & TF_Autoincrement)
@@ -1112,10 +1124,13 @@ sqlite3GenerateConstraintChecks(Parse * pParse,		/* The parser context */
 		} else if (onError == ON_CONFLICT_ACTION_DEFAULT) {
 			onError = ON_CONFLICT_ACTION_ABORT;
 		}
-		if (onError == ON_CONFLICT_ACTION_REPLACE
-		    && pTab->aCol[i].pDflt == 0) {
+		struct Expr *dflt = NULL;
+		dflt = space_column_default_expr(
+			SQLITE_PAGENO_TO_SPACEID(pTab->tnum),
+			i);
+		if (onError == ON_CONFLICT_ACTION_REPLACE && dflt == 0)
 			onError = ON_CONFLICT_ACTION_ABORT;
-		}
+
 		assert(onError == ON_CONFLICT_ACTION_ROLLBACK
 		       || onError == ON_CONFLICT_ACTION_ABORT
 		       || onError == ON_CONFLICT_ACTION_FAIL
@@ -1151,7 +1166,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse,		/* The parser context */
 				    sqlite3VdbeAddOp1(v, OP_NotNull,
 						      regNewData + 1 + i);
 				VdbeCoverage(v);
-				sqlite3ExprCode(pParse, pTab->aCol[i].pDflt,
+				sqlite3ExprCode(pParse, dflt,
 						regNewData + 1 + i);
 				sqlite3VdbeJumpHere(v, addr1);
 				break;
modified   src/box/sql/main.c
@@ -2058,21 +2058,6 @@ sql_init_db(sqlite3 **out_db)
 	setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside,
 		       sqlite3GlobalConfig.nLookaside);
 
-	if (rc == SQLITE_OK) {
-		struct session *user_session = current_session();
-		int commit_internal = !(user_session->sql_flags
-					& SQLITE_InternChanges);
-
-		assert(db->init.busy == 0);
-		db->init.busy = 1;
-		db->pSchema = sqlite3SchemaCreate(db);
-		rc = sqlite3InitDatabase(db);
-		if (rc != SQLITE_OK)
-			sqlite3SchemaClear(db);
-		db->init.busy = 0;
-		if (rc == SQLITE_OK && commit_internal)
-			sqlite3CommitInternalChanges();
-	}
 opendb_out:
 	rc = sqlite3_errcode(db);
 	assert(db != 0 || rc == SQLITE_NOMEM);
modified   src/box/sql/parse.c
@@ -81,7 +81,7 @@ static void disableLookaside(Parse *pParse){
   pParse->db->lookaside.bDisable++;
 }
 
-#line 392 "parse.y"
+#line 398 "parse.y"
 
   /*
   ** For a compound SELECT statement, make sure p->pPrior->pNext==p for
@@ -104,7 +104,7 @@ static void disableLookaside(Parse *pParse){
       }
     }
   }
-#line 831 "parse.y"
+#line 837 "parse.y"
 
   /* This is a utility routine used to set the ExprSpan.zStart and
   ** ExprSpan.zEnd values of pOut so that the span covers the complete
@@ -140,7 +140,7 @@ static void disableLookaside(Parse *pParse){
     pOut->zStart = t.z;
     pOut->zEnd = &t.z[t.n];
   }
-#line 939 "parse.y"
+#line 945 "parse.y"
 
   /* This routine constructs a binary expression node out of two ExprSpan
   ** objects and uses the result to populate a new ExprSpan object.
@@ -163,7 +163,7 @@ static void disableLookaside(Parse *pParse){
       pSpan->pExpr = sqlite3PExpr(pParse, TK_NOT, pSpan->pExpr, 0);
     }
   }
-#line 1013 "parse.y"
+#line 1019 "parse.y"
 
   /* Construct an expression node for a unary postfix operator
   */
@@ -176,7 +176,7 @@ static void disableLookaside(Parse *pParse){
     pOperand->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0);
     pOperand->zEnd = &pPostOp->z[pPostOp->n];
   }                           
-#line 1030 "parse.y"
+#line 1036 "parse.y"
 
   /* A routine to convert a binary TK_IS or TK_ISNOT expression into a
   ** unary TK_ISNULL or TK_NOTNULL expression. */
@@ -184,11 +184,11 @@ static void disableLookaside(Parse *pParse){
     sqlite3 *db = pParse->db;
     if( pA && pY && pY->op==TK_NULL ){
       pA->op = (u8)op;
-      sqlite3ExprDelete(db, pA->pRight);
+      sql_expr_free(db, pA->pRight, false);
       pA->pRight = 0;
     }
   }
-#line 1058 "parse.y"
+#line 1064 "parse.y"
 
   /* Construct an expression node for a unary prefix operator
   */
@@ -203,7 +203,7 @@ static void disableLookaside(Parse *pParse){
     pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0);
     pOut->zEnd = pOperand->zEnd;
   }
-#line 1263 "parse.y"
+#line 1269 "parse.y"
 
   /* Add a single new term to an ExprList that is used to store a
   ** list of identifiers.  Report an error if the ID list contains
@@ -1468,7 +1468,7 @@ static void yy_destructor(
     case 183: /* oneselect */
     case 194: /* values */
 {
-#line 386 "parse.y"
+#line 392 "parse.y"
 sqlite3SelectDelete(pParse->db, (yypminor->yy279));
 #line 1474 "parse.c"
 }
@@ -1476,8 +1476,8 @@ sqlite3SelectDelete(pParse->db, (yypminor->yy279));
     case 160: /* term */
     case 161: /* expr */
 {
-#line 829 "parse.y"
-sqlite3ExprDelete(pParse->db, (yypminor->yy162).pExpr);
+#line 835 "parse.y"
+sql_expr_free(pParse->db, (yypminor->yy162).pExpr, false);
 #line 1482 "parse.c"
 }
       break;
@@ -1494,7 +1494,7 @@ sqlite3ExprDelete(pParse->db, (yypminor->yy162).pExpr);
     case 213: /* paren_exprlist */
     case 215: /* case_exprlist */
 {
-#line 1261 "parse.y"
+#line 1267 "parse.y"
 sqlite3ExprListDelete(pParse->db, (yypminor->yy382));
 #line 1500 "parse.c"
 }
@@ -1504,7 +1504,7 @@ sqlite3ExprListDelete(pParse->db, (yypminor->yy382));
     case 199: /* seltablist */
     case 200: /* stl_prefix */
 {
-#line 613 "parse.y"
+#line 619 "parse.y"
 sqlite3SrcListDelete(pParse->db, (yypminor->yy387));
 #line 1510 "parse.c"
 }
@@ -1512,7 +1512,7 @@ sqlite3SrcListDelete(pParse->db, (yypminor->yy387));
     case 184: /* with */
     case 229: /* wqlist */
 {
-#line 1511 "parse.y"
+#line 1517 "parse.y"
 sqlite3WithDelete(pParse->db, (yypminor->yy151));
 #line 1518 "parse.c"
 }
@@ -1524,8 +1524,8 @@ sqlite3WithDelete(pParse->db, (yypminor->yy151));
     case 216: /* case_else */
     case 225: /* when_clause */
 {
-#line 738 "parse.y"
-sqlite3ExprDelete(pParse->db, (yypminor->yy362));
+#line 744 "parse.y"
+sql_expr_free(pParse->db, (yypminor->yy362), false);
 #line 1530 "parse.c"
 }
       break;
@@ -1533,7 +1533,7 @@ sqlite3ExprDelete(pParse->db, (yypminor->yy362));
     case 206: /* idlist */
     case 209: /* idlist_opt */
 {
-#line 650 "parse.y"
+#line 656 "parse.y"
 sqlite3IdListDelete(pParse->db, (yypminor->yy40));
 #line 1539 "parse.c"
 }
@@ -1541,14 +1541,14 @@ sqlite3IdListDelete(pParse->db, (yypminor->yy40));
     case 221: /* trigger_cmd_list */
     case 226: /* trigger_cmd */
 {
-#line 1385 "parse.y"
+#line 1391 "parse.y"
 sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy427));
 #line 1547 "parse.c"
 }
       break;
     case 223: /* trigger_event */
 {
-#line 1371 "parse.y"
+#line 1377 "parse.y"
 sqlite3IdListDelete(pParse->db, (yypminor->yy10).b);
 #line 1554 "parse.c"
 }
@@ -2164,84 +2164,87 @@ static void yy_reduce(
         YYMINORTYPE yylhsminor;
       case 0: /* ecmd ::= explain cmdx SEMI */
 #line 111 "parse.y"
-{ sqlite3FinishCoding(pParse); }
-#line 2169 "parse.c"
+{
+	if (!pParse->parse_only)
+		sqlite3FinishCoding(pParse);
+}
+#line 2172 "parse.c"
         break;
       case 1: /* ecmd ::= SEMI */
-#line 112 "parse.y"
+#line 115 "parse.y"
 {
   sqlite3ErrorMsg(pParse, "syntax error: empty request");
 }
-#line 2176 "parse.c"
+#line 2179 "parse.c"
         break;
       case 2: /* explain ::= EXPLAIN */
-#line 117 "parse.y"
+#line 120 "parse.y"
 { pParse->explain = 1; }
-#line 2181 "parse.c"
+#line 2184 "parse.c"
         break;
       case 3: /* explain ::= EXPLAIN QUERY PLAN */
-#line 118 "parse.y"
+#line 121 "parse.y"
 { pParse->explain = 2; }
-#line 2186 "parse.c"
+#line 2189 "parse.c"
         break;
       case 4: /* cmd ::= BEGIN transtype trans_opt */
-#line 150 "parse.y"
+#line 153 "parse.y"
 {sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy52);}
-#line 2191 "parse.c"
+#line 2194 "parse.c"
         break;
       case 5: /* transtype ::= */
-#line 155 "parse.y"
+#line 158 "parse.y"
 {yymsp[1].minor.yy52 = TK_DEFERRED;}
-#line 2196 "parse.c"
+#line 2199 "parse.c"
         break;
       case 6: /* transtype ::= DEFERRED */
-#line 156 "parse.y"
+#line 159 "parse.y"
 {yymsp[0].minor.yy52 = yymsp[0].major; /*A-overwrites-X*/}
-#line 2201 "parse.c"
+#line 2204 "parse.c"
         break;
       case 7: /* cmd ::= COMMIT trans_opt */
       case 8: /* cmd ::= END trans_opt */ yytestcase(yyruleno==8);
-#line 157 "parse.y"
+#line 160 "parse.y"
 {sqlite3CommitTransaction(pParse);}
-#line 2207 "parse.c"
+#line 2210 "parse.c"
         break;
       case 9: /* cmd ::= ROLLBACK trans_opt */
-#line 159 "parse.y"
+#line 162 "parse.y"
 {sqlite3RollbackTransaction(pParse);}
-#line 2212 "parse.c"
+#line 2215 "parse.c"
         break;
       case 10: /* cmd ::= SAVEPOINT nm */
-#line 163 "parse.y"
+#line 166 "parse.y"
 {
   sqlite3Savepoint(pParse, SAVEPOINT_BEGIN, &yymsp[0].minor.yy0);
 }
-#line 2219 "parse.c"
+#line 2222 "parse.c"
         break;
       case 11: /* cmd ::= RELEASE savepoint_opt nm */
-#line 166 "parse.y"
+#line 169 "parse.y"
 {
   sqlite3Savepoint(pParse, SAVEPOINT_RELEASE, &yymsp[0].minor.yy0);
 }
-#line 2226 "parse.c"
+#line 2229 "parse.c"
         break;
       case 12: /* cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
-#line 169 "parse.y"
+#line 172 "parse.y"
 {
   sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &yymsp[0].minor.yy0);
 }
-#line 2233 "parse.c"
+#line 2236 "parse.c"
         break;
       case 13: /* create_table ::= createkw TABLE ifnotexists nm */
-#line 176 "parse.y"
+#line 179 "parse.y"
 {
    sqlite3StartTable(pParse,&yymsp[0].minor.yy0,yymsp[-1].minor.yy52);
 }
-#line 2240 "parse.c"
+#line 2243 "parse.c"
         break;
       case 14: /* createkw ::= CREATE */
-#line 179 "parse.y"
+#line 182 "parse.y"
 {disableLookaside(pParse);}
-#line 2245 "parse.c"
+#line 2248 "parse.c"
         break;
       case 15: /* ifnotexists ::= */
       case 38: /* autoinc ::= */ yytestcase(yyruleno==38);
@@ -2250,89 +2253,89 @@ static void yy_reduce(
       case 72: /* ifexists ::= */ yytestcase(yyruleno==72);
       case 86: /* distinct ::= */ yytestcase(yyruleno==86);
       case 208: /* collate ::= */ yytestcase(yyruleno==208);
-#line 182 "parse.y"
+#line 185 "parse.y"
 {yymsp[1].minor.yy52 = 0;}
-#line 2256 "parse.c"
+#line 2259 "parse.c"
         break;
       case 16: /* ifnotexists ::= IF NOT EXISTS */
-#line 183 "parse.y"
+#line 186 "parse.y"
 {yymsp[-2].minor.yy52 = 1;}
-#line 2261 "parse.c"
+#line 2264 "parse.c"
         break;
       case 17: /* create_table_args ::= LP columnlist conslist_opt RP */
-#line 185 "parse.y"
+#line 188 "parse.y"
 {
   sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0);
 }
-#line 2268 "parse.c"
+#line 2271 "parse.c"
         break;
       case 18: /* create_table_args ::= AS select */
-#line 188 "parse.y"
+#line 191 "parse.y"
 {
   sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy279);
   sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy279);
 }
-#line 2276 "parse.c"
+#line 2279 "parse.c"
         break;
       case 19: /* columnname ::= nm typetoken */
-#line 194 "parse.y"
+#line 197 "parse.y"
 {sqlite3AddColumn(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
-#line 2281 "parse.c"
+#line 2284 "parse.c"
         break;
       case 20: /* nm ::= ID|INDEXED */
-#line 225 "parse.y"
+#line 228 "parse.y"
 {
   if(yymsp[0].minor.yy0.isReserved) {
     sqlite3ErrorMsg(pParse, "keyword \"%T\" is reserved", &yymsp[0].minor.yy0);
   }
 }
-#line 2290 "parse.c"
+#line 2293 "parse.c"
         break;
       case 21: /* typetoken ::= */
       case 56: /* conslist_opt ::= */ yytestcase(yyruleno==56);
       case 92: /* as ::= */ yytestcase(yyruleno==92);
-#line 236 "parse.y"
+#line 239 "parse.y"
 {yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;}
-#line 2297 "parse.c"
+#line 2300 "parse.c"
         break;
       case 22: /* typetoken ::= typename LP signed RP */
-#line 238 "parse.y"
+#line 241 "parse.y"
 {
   yymsp[-3].minor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy0.z);
 }
-#line 2304 "parse.c"
+#line 2307 "parse.c"
         break;
       case 23: /* typetoken ::= typename LP signed COMMA signed RP */
-#line 241 "parse.y"
+#line 244 "parse.y"
 {
   yymsp[-5].minor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy0.z);
 }
-#line 2311 "parse.c"
+#line 2314 "parse.c"
         break;
       case 24: /* typename ::= typename ID|STRING */
-#line 246 "parse.y"
+#line 249 "parse.y"
 {yymsp[-1].minor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);}
-#line 2316 "parse.c"
+#line 2319 "parse.c"
         break;
       case 25: /* ccons ::= CONSTRAINT nm */
       case 58: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==58);
-#line 255 "parse.y"
+#line 258 "parse.y"
 {pParse->constraintName = yymsp[0].minor.yy0;}
-#line 2322 "parse.c"
+#line 2325 "parse.c"
         break;
       case 26: /* ccons ::= DEFAULT term */
       case 28: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==28);
-#line 256 "parse.y"
+#line 259 "parse.y"
 {sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy162);}
-#line 2328 "parse.c"
+#line 2331 "parse.c"
         break;
       case 27: /* ccons ::= DEFAULT LP expr RP */
-#line 257 "parse.y"
+#line 260 "parse.y"
 {sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy162);}
-#line 2333 "parse.c"
+#line 2336 "parse.c"
         break;
       case 29: /* ccons ::= DEFAULT MINUS term */
-#line 259 "parse.y"
+#line 262 "parse.y"
 {
   ExprSpan v;
   v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy162.pExpr, 0);
@@ -2340,222 +2343,225 @@ static void yy_reduce(
   v.zEnd = yymsp[0].minor.yy162.zEnd;
   sqlite3AddDefaultValue(pParse,&v);
 }
-#line 2344 "parse.c"
+#line 2347 "parse.c"
         break;
       case 30: /* ccons ::= DEFAULT ID|INDEXED */
-#line 266 "parse.y"
+#line 269 "parse.y"
 {
   ExprSpan v;
   spanExpr(&v, pParse, TK_STRING, yymsp[0].minor.yy0);
   sqlite3AddDefaultValue(pParse,&v);
 }
-#line 2353 "parse.c"
+#line 2356 "parse.c"
         break;
       case 31: /* ccons ::= NOT NULL onconf */
-#line 276 "parse.y"
+#line 279 "parse.y"
 {sqlite3AddNotNull(pParse, yymsp[0].minor.yy52);}
-#line 2358 "parse.c"
+#line 2361 "parse.c"
         break;
       case 32: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
-#line 278 "parse.y"
+#line 281 "parse.y"
 {sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy52,yymsp[0].minor.yy52,yymsp[-2].minor.yy52);}
-#line 2363 "parse.c"
+#line 2366 "parse.c"
         break;
       case 33: /* ccons ::= UNIQUE onconf */
-#line 279 "parse.y"
+#line 282 "parse.y"
 {sqlite3CreateIndex(pParse,0,0,0,yymsp[0].minor.yy52,0,0,0,0,
                                    SQLITE_IDXTYPE_UNIQUE);}
-#line 2369 "parse.c"
+#line 2372 "parse.c"
         break;
       case 34: /* ccons ::= CHECK LP expr RP */
-#line 281 "parse.y"
+#line 284 "parse.y"
 {sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy162.pExpr);}
-#line 2374 "parse.c"
+#line 2377 "parse.c"
         break;
       case 35: /* ccons ::= REFERENCES nm eidlist_opt refargs */
-#line 283 "parse.y"
+#line 286 "parse.y"
 {sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy382,yymsp[0].minor.yy52);}
-#line 2379 "parse.c"
+#line 2382 "parse.c"
         break;
       case 36: /* ccons ::= defer_subclause */
-#line 284 "parse.y"
+#line 287 "parse.y"
 {sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy52);}
-#line 2384 "parse.c"
+#line 2387 "parse.c"
         break;
       case 37: /* ccons ::= COLLATE ID|INDEXED */
-#line 285 "parse.y"
+#line 288 "parse.y"
 {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
-#line 2389 "parse.c"
+#line 2392 "parse.c"
         break;
       case 39: /* autoinc ::= AUTOINCR */
-#line 290 "parse.y"
+#line 293 "parse.y"
 {yymsp[0].minor.yy52 = 1;}
-#line 2394 "parse.c"
+#line 2397 "parse.c"
         break;
       case 40: /* refargs ::= */
-#line 298 "parse.y"
+#line 301 "parse.y"
 { yymsp[1].minor.yy52 = ON_CONFLICT_ACTION_NONE*0x0101; /* EV: R-19803-45884 */}
-#line 2399 "parse.c"
+#line 2402 "parse.c"
         break;
       case 41: /* refargs ::= refargs refarg */
-#line 299 "parse.y"
+#line 302 "parse.y"
 { yymsp[-1].minor.yy52 = (yymsp[-1].minor.yy52 & ~yymsp[0].minor.yy107.mask) | yymsp[0].minor.yy107.value; }
-#line 2404 "parse.c"
+#line 2407 "parse.c"
         break;
       case 42: /* refarg ::= MATCH nm */
-#line 301 "parse.y"
+#line 304 "parse.y"
 { yymsp[-1].minor.yy107.value = 0;     yymsp[-1].minor.yy107.mask = 0x000000; }
-#line 2409 "parse.c"
+#line 2412 "parse.c"
         break;
       case 43: /* refarg ::= ON INSERT refact */
-#line 302 "parse.y"
+#line 305 "parse.y"
 { yymsp[-2].minor.yy107.value = 0;     yymsp[-2].minor.yy107.mask = 0x000000; }
-#line 2414 "parse.c"
+#line 2417 "parse.c"
         break;
       case 44: /* refarg ::= ON DELETE refact */
-#line 303 "parse.y"
+#line 306 "parse.y"
 { yymsp[-2].minor.yy107.value = yymsp[0].minor.yy52;     yymsp[-2].minor.yy107.mask = 0x0000ff; }
-#line 2419 "parse.c"
+#line 2422 "parse.c"
         break;
       case 45: /* refarg ::= ON UPDATE refact */
-#line 304 "parse.y"
+#line 307 "parse.y"
 { yymsp[-2].minor.yy107.value = yymsp[0].minor.yy52<<8;  yymsp[-2].minor.yy107.mask = 0x00ff00; }
-#line 2424 "parse.c"
+#line 2427 "parse.c"
         break;
       case 46: /* refact ::= SET NULL */
-#line 306 "parse.y"
+#line 309 "parse.y"
 { yymsp[-1].minor.yy52 = OE_SetNull;  /* EV: R-33326-45252 */}
-#line 2429 "parse.c"
+#line 2432 "parse.c"
         break;
       case 47: /* refact ::= SET DEFAULT */
-#line 307 "parse.y"
+#line 310 "parse.y"
 { yymsp[-1].minor.yy52 = OE_SetDflt;  /* EV: R-33326-45252 */}
-#line 2434 "parse.c"
+#line 2437 "parse.c"
         break;
       case 48: /* refact ::= CASCADE */
-#line 308 "parse.y"
+#line 311 "parse.y"
 { yymsp[0].minor.yy52 = OE_Cascade;  /* EV: R-33326-45252 */}
-#line 2439 "parse.c"
+#line 2442 "parse.c"
         break;
       case 49: /* refact ::= RESTRICT */
-#line 309 "parse.y"
+#line 312 "parse.y"
 { yymsp[0].minor.yy52 = OE_Restrict; /* EV: R-33326-45252 */}
-#line 2444 "parse.c"
+#line 2447 "parse.c"
         break;
       case 50: /* refact ::= NO ACTION */
-#line 310 "parse.y"
+#line 313 "parse.y"
 { yymsp[-1].minor.yy52 = ON_CONFLICT_ACTION_NONE;     /* EV: R-33326-45252 */}
-#line 2449 "parse.c"
+#line 2452 "parse.c"
         break;
       case 51: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
-#line 312 "parse.y"
+#line 315 "parse.y"
 {yymsp[-2].minor.yy52 = 0;}
-#line 2454 "parse.c"
+#line 2457 "parse.c"
         break;
       case 52: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
       case 67: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==67);
       case 138: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==138);
-#line 313 "parse.y"
+#line 316 "parse.y"
 {yymsp[-1].minor.yy52 = yymsp[0].minor.yy52;}
-#line 2461 "parse.c"
+#line 2464 "parse.c"
         break;
       case 54: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
       case 71: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==71);
       case 180: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==180);
       case 183: /* in_op ::= NOT IN */ yytestcase(yyruleno==183);
       case 209: /* collate ::= COLLATE ID|INDEXED */ yytestcase(yyruleno==209);
-#line 316 "parse.y"
+#line 319 "parse.y"
 {yymsp[-1].minor.yy52 = 1;}
-#line 2470 "parse.c"
+#line 2473 "parse.c"
         break;
       case 55: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
-#line 317 "parse.y"
+#line 320 "parse.y"
 {yymsp[-1].minor.yy52 = 0;}
-#line 2475 "parse.c"
+#line 2478 "parse.c"
         break;
       case 57: /* tconscomma ::= COMMA */
-#line 323 "parse.y"
+#line 326 "parse.y"
 {pParse->constraintName.n = 0;}
-#line 2480 "parse.c"
+#line 2483 "parse.c"
         break;
       case 59: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
-#line 327 "parse.y"
+#line 330 "parse.y"
 {sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy382,yymsp[0].minor.yy52,yymsp[-2].minor.yy52,0);}
-#line 2485 "parse.c"
+#line 2488 "parse.c"
         break;
       case 60: /* tcons ::= UNIQUE LP sortlist RP onconf */
-#line 329 "parse.y"
+#line 332 "parse.y"
 {sqlite3CreateIndex(pParse,0,0,yymsp[-2].minor.yy382,yymsp[0].minor.yy52,0,0,0,0,
                                        SQLITE_IDXTYPE_UNIQUE);}
-#line 2491 "parse.c"
+#line 2494 "parse.c"
         break;
       case 61: /* tcons ::= CHECK LP expr RP onconf */
-#line 332 "parse.y"
+#line 335 "parse.y"
 {sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy162.pExpr);}
-#line 2496 "parse.c"
+#line 2499 "parse.c"
         break;
       case 62: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
-#line 334 "parse.y"
+#line 337 "parse.y"
 {
     sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy382, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy382, yymsp[-1].minor.yy52);
     sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy52);
 }
-#line 2504 "parse.c"
+#line 2507 "parse.c"
         break;
       case 64: /* onconf ::= */
       case 66: /* orconf ::= */ yytestcase(yyruleno==66);
-#line 348 "parse.y"
+#line 351 "parse.y"
 {yymsp[1].minor.yy52 = ON_CONFLICT_ACTION_DEFAULT;}
-#line 2510 "parse.c"
+#line 2513 "parse.c"
         break;
       case 65: /* onconf ::= ON CONFLICT resolvetype */
-#line 349 "parse.y"
+#line 352 "parse.y"
 {yymsp[-2].minor.yy52 = yymsp[0].minor.yy52;}
-#line 2515 "parse.c"
+#line 2518 "parse.c"
         break;
       case 68: /* resolvetype ::= IGNORE */
-#line 353 "parse.y"
+#line 356 "parse.y"
 {yymsp[0].minor.yy52 = ON_CONFLICT_ACTION_IGNORE;}
-#line 2520 "parse.c"
+#line 2523 "parse.c"
         break;
       case 69: /* resolvetype ::= REPLACE */
       case 139: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==139);
-#line 354 "parse.y"
+#line 357 "parse.y"
 {yymsp[0].minor.yy52 = ON_CONFLICT_ACTION_REPLACE;}
-#line 2526 "parse.c"
+#line 2529 "parse.c"
         break;
       case 70: /* cmd ::= DROP TABLE ifexists fullname */
-#line 358 "parse.y"
+#line 361 "parse.y"
 {
   sqlite3DropTable(pParse, yymsp[0].minor.yy387, 0, yymsp[-1].minor.yy52);
 }
-#line 2533 "parse.c"
+#line 2536 "parse.c"
         break;
       case 73: /* cmd ::= createkw VIEW ifnotexists nm eidlist_opt AS select */
-#line 369 "parse.y"
+#line 372 "parse.y"
 {
   sqlite3CreateView(pParse, &yymsp[-6].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy382, yymsp[0].minor.yy279, yymsp[-4].minor.yy52);
 }
-#line 2540 "parse.c"
+#line 2543 "parse.c"
         break;
       case 74: /* cmd ::= DROP VIEW ifexists fullname */
-#line 372 "parse.y"
+#line 375 "parse.y"
 {
   sqlite3DropTable(pParse, yymsp[0].minor.yy387, 1, yymsp[-1].minor.yy52);
 }
-#line 2547 "parse.c"
+#line 2550 "parse.c"
         break;
       case 75: /* cmd ::= select */
-#line 379 "parse.y"
+#line 382 "parse.y"
 {
   SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
-  sqlite3Select(pParse, yymsp[0].minor.yy279, &dest);
+  if(!pParse->parse_only)
+	  sqlite3Select(pParse, yymsp[0].minor.yy279, &dest);
+  else
+	  sql_expr_extract_select(pParse, yymsp[0].minor.yy279);
   sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy279);
 }
-#line 2556 "parse.c"
+#line 2562 "parse.c"
         break;
       case 76: /* select ::= with selectnowith */
-#line 416 "parse.y"
+#line 422 "parse.y"
 {
   Select *p = yymsp[0].minor.yy279;
   if( p ){
@@ -2566,10 +2572,10 @@ static void yy_reduce(
   }
   yymsp[-1].minor.yy279 = p; /*A-overwrites-W*/
 }
-#line 2570 "parse.c"
+#line 2576 "parse.c"
         break;
       case 77: /* selectnowith ::= selectnowith multiselect_op oneselect */
-#line 429 "parse.y"
+#line 435 "parse.y"
 {
   Select *pRhs = yymsp[0].minor.yy279;
   Select *pLhs = yymsp[-2].minor.yy279;
@@ -2592,21 +2598,21 @@ static void yy_reduce(
   }
   yymsp[-2].minor.yy279 = pRhs;
 }
-#line 2596 "parse.c"
+#line 2602 "parse.c"
         break;
       case 78: /* multiselect_op ::= UNION */
       case 80: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==80);
-#line 452 "parse.y"
+#line 458 "parse.y"
 {yymsp[0].minor.yy52 = yymsp[0].major; /*A-overwrites-OP*/}
-#line 2602 "parse.c"
+#line 2608 "parse.c"
         break;
       case 79: /* multiselect_op ::= UNION ALL */
-#line 453 "parse.y"
+#line 459 "parse.y"
 {yymsp[-1].minor.yy52 = TK_ALL;}
-#line 2607 "parse.c"
+#line 2613 "parse.c"
         break;
       case 81: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
-#line 457 "parse.y"
+#line 463 "parse.y"
 {
 #ifdef SELECTTRACE_ENABLED
   Token s = yymsp[-8].minor.yy0; /*A-overwrites-S*/
@@ -2637,17 +2643,17 @@ static void yy_reduce(
   }
 #endif /* SELECTRACE_ENABLED */
 }
-#line 2641 "parse.c"
+#line 2647 "parse.c"
         break;
       case 82: /* values ::= VALUES LP nexprlist RP */
-#line 491 "parse.y"
+#line 497 "parse.y"
 {
   yymsp[-3].minor.yy279 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy382,0,0,0,0,0,SF_Values,0,0);
 }
-#line 2648 "parse.c"
+#line 2654 "parse.c"
         break;
       case 83: /* values ::= values COMMA LP exprlist RP */
-#line 494 "parse.y"
+#line 500 "parse.y"
 {
   Select *pRight, *pLeft = yymsp[-4].minor.yy279;
   pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy382,0,0,0,0,0,SF_Values|SF_MultiValue,0,0);
@@ -2660,17 +2666,17 @@ static void yy_reduce(
     yymsp[-4].minor.yy279 = pLeft;
   }
 }
-#line 2664 "parse.c"
+#line 2670 "parse.c"
         break;
       case 84: /* distinct ::= DISTINCT */
-#line 511 "parse.y"
+#line 517 "parse.y"
 {yymsp[0].minor.yy52 = SF_Distinct;}
-#line 2669 "parse.c"
+#line 2675 "parse.c"
         break;
       case 85: /* distinct ::= ALL */
-#line 512 "parse.y"
+#line 518 "parse.y"
 {yymsp[0].minor.yy52 = SF_All;}
-#line 2674 "parse.c"
+#line 2680 "parse.c"
         break;
       case 87: /* sclp ::= */
       case 113: /* orderby_opt ::= */ yytestcase(yyruleno==113);
@@ -2678,94 +2684,94 @@ static void yy_reduce(
       case 196: /* exprlist ::= */ yytestcase(yyruleno==196);
       case 199: /* paren_exprlist ::= */ yytestcase(yyruleno==199);
       case 204: /* eidlist_opt ::= */ yytestcase(yyruleno==204);
-#line 525 "parse.y"
+#line 531 "parse.y"
 {yymsp[1].minor.yy382 = 0;}
-#line 2684 "parse.c"
+#line 2690 "parse.c"
         break;
       case 88: /* selcollist ::= sclp expr as */
-#line 526 "parse.y"
+#line 532 "parse.y"
 {
    yymsp[-2].minor.yy382 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy382, yymsp[-1].minor.yy162.pExpr);
    if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-2].minor.yy382, &yymsp[0].minor.yy0, 1);
    sqlite3ExprListSetSpan(pParse,yymsp[-2].minor.yy382,&yymsp[-1].minor.yy162);
 }
-#line 2693 "parse.c"
+#line 2699 "parse.c"
         break;
       case 89: /* selcollist ::= sclp STAR */
-#line 531 "parse.y"
+#line 537 "parse.y"
 {
   Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0);
   yymsp[-1].minor.yy382 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy382, p);
 }
-#line 2701 "parse.c"
+#line 2707 "parse.c"
         break;
       case 90: /* selcollist ::= sclp nm DOT STAR */
-#line 535 "parse.y"
+#line 541 "parse.y"
 {
   Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0);
   Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
   Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
   yymsp[-3].minor.yy382 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy382, pDot);
 }
-#line 2711 "parse.c"
+#line 2717 "parse.c"
         break;
       case 91: /* as ::= AS nm */
       case 218: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==218);
       case 219: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==219);
-#line 546 "parse.y"
+#line 552 "parse.y"
 {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;}
-#line 2718 "parse.c"
+#line 2724 "parse.c"
         break;
       case 93: /* from ::= */
-#line 560 "parse.y"
+#line 566 "parse.y"
 {yymsp[1].minor.yy387 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy387));}
-#line 2723 "parse.c"
+#line 2729 "parse.c"
         break;
       case 94: /* from ::= FROM seltablist */
-#line 561 "parse.y"
+#line 567 "parse.y"
 {
   yymsp[-1].minor.yy387 = yymsp[0].minor.yy387;
   sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy387);
 }
-#line 2731 "parse.c"
+#line 2737 "parse.c"
         break;
       case 95: /* stl_prefix ::= seltablist joinop */
-#line 569 "parse.y"
+#line 575 "parse.y"
 {
    if( ALWAYS(yymsp[-1].minor.yy387 && yymsp[-1].minor.yy387->nSrc>0) ) yymsp[-1].minor.yy387->a[yymsp[-1].minor.yy387->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy52;
 }
-#line 2738 "parse.c"
+#line 2744 "parse.c"
         break;
       case 96: /* stl_prefix ::= */
-#line 572 "parse.y"
+#line 578 "parse.y"
 {yymsp[1].minor.yy387 = 0;}
-#line 2743 "parse.c"
+#line 2749 "parse.c"
         break;
       case 97: /* seltablist ::= stl_prefix nm as indexed_opt on_opt using_opt */
-#line 574 "parse.y"
+#line 580 "parse.y"
 {
   yymsp[-5].minor.yy387 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy387,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy362,yymsp[0].minor.yy40);
   sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy387, &yymsp[-2].minor.yy0);
 }
-#line 2751 "parse.c"
+#line 2757 "parse.c"
         break;
       case 98: /* seltablist ::= stl_prefix nm LP exprlist RP as on_opt using_opt */
-#line 579 "parse.y"
+#line 585 "parse.y"
 {
   yymsp[-7].minor.yy387 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-7].minor.yy387,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy362,yymsp[0].minor.yy40);
   sqlite3SrcListFuncArgs(pParse, yymsp[-7].minor.yy387, yymsp[-4].minor.yy382);
 }
-#line 2759 "parse.c"
+#line 2765 "parse.c"
         break;
       case 99: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
-#line 585 "parse.y"
+#line 591 "parse.y"
 {
     yymsp[-6].minor.yy387 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy387,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy279,yymsp[-1].minor.yy362,yymsp[0].minor.yy40);
   }
-#line 2766 "parse.c"
+#line 2772 "parse.c"
         break;
       case 100: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
-#line 589 "parse.y"
+#line 595 "parse.y"
 {
     if( yymsp[-6].minor.yy387==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy362==0 && yymsp[0].minor.yy40==0 ){
       yymsp[-6].minor.yy387 = yymsp[-4].minor.yy387;
@@ -2787,135 +2793,135 @@ static void yy_reduce(
       yymsp[-6].minor.yy387 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy387,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy362,yymsp[0].minor.yy40);
     }
   }
-#line 2791 "parse.c"
+#line 2797 "parse.c"
         break;
       case 101: /* fullname ::= nm */
-#line 615 "parse.y"
+#line 621 "parse.y"
 {yymsp[0].minor.yy387 = sqlite3SrcListAppend(pParse->db,0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
-#line 2796 "parse.c"
+#line 2802 "parse.c"
         break;
       case 102: /* joinop ::= COMMA|JOIN */
-#line 621 "parse.y"
+#line 627 "parse.y"
 { yymsp[0].minor.yy52 = JT_INNER; }
-#line 2801 "parse.c"
+#line 2807 "parse.c"
         break;
       case 103: /* joinop ::= JOIN_KW JOIN */
-#line 623 "parse.y"
+#line 629 "parse.y"
 {yymsp[-1].minor.yy52 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0);  /*X-overwrites-A*/}
-#line 2806 "parse.c"
+#line 2812 "parse.c"
         break;
       case 104: /* joinop ::= JOIN_KW join_nm JOIN */
-#line 625 "parse.y"
+#line 631 "parse.y"
 {yymsp[-2].minor.yy52 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
-#line 2811 "parse.c"
+#line 2817 "parse.c"
         break;
       case 105: /* joinop ::= JOIN_KW join_nm join_nm JOIN */
-#line 627 "parse.y"
+#line 633 "parse.y"
 {yymsp[-3].minor.yy52 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
-#line 2816 "parse.c"
+#line 2822 "parse.c"
         break;
       case 106: /* on_opt ::= ON expr */
       case 123: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==123);
       case 130: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==130);
       case 192: /* case_else ::= ELSE expr */ yytestcase(yyruleno==192);
-#line 631 "parse.y"
+#line 637 "parse.y"
 {yymsp[-1].minor.yy362 = yymsp[0].minor.yy162.pExpr;}
-#line 2824 "parse.c"
+#line 2830 "parse.c"
         break;
       case 107: /* on_opt ::= */
       case 122: /* having_opt ::= */ yytestcase(yyruleno==122);
       case 129: /* where_opt ::= */ yytestcase(yyruleno==129);
       case 193: /* case_else ::= */ yytestcase(yyruleno==193);
       case 195: /* case_operand ::= */ yytestcase(yyruleno==195);
-#line 632 "parse.y"
+#line 638 "parse.y"
 {yymsp[1].minor.yy362 = 0;}
-#line 2833 "parse.c"
+#line 2839 "parse.c"
         break;
       case 108: /* indexed_opt ::= */
-#line 645 "parse.y"
+#line 651 "parse.y"
 {yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;}
-#line 2838 "parse.c"
+#line 2844 "parse.c"
         break;
       case 109: /* indexed_opt ::= INDEXED BY nm */
-#line 646 "parse.y"
+#line 652 "parse.y"
 {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;}
-#line 2843 "parse.c"
+#line 2849 "parse.c"
         break;
       case 110: /* indexed_opt ::= NOT INDEXED */
-#line 647 "parse.y"
+#line 653 "parse.y"
 {yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;}
-#line 2848 "parse.c"
+#line 2854 "parse.c"
         break;
       case 111: /* using_opt ::= USING LP idlist RP */
-#line 651 "parse.y"
+#line 657 "parse.y"
 {yymsp[-3].minor.yy40 = yymsp[-1].minor.yy40;}
-#line 2853 "parse.c"
+#line 2859 "parse.c"
         break;
       case 112: /* using_opt ::= */
       case 140: /* idlist_opt ::= */ yytestcase(yyruleno==140);
-#line 652 "parse.y"
+#line 658 "parse.y"
 {yymsp[1].minor.yy40 = 0;}
-#line 2859 "parse.c"
+#line 2865 "parse.c"
         break;
       case 114: /* orderby_opt ::= ORDER BY sortlist */
       case 121: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==121);
-#line 666 "parse.y"
+#line 672 "parse.y"
 {yymsp[-2].minor.yy382 = yymsp[0].minor.yy382;}
-#line 2865 "parse.c"
+#line 2871 "parse.c"
         break;
       case 115: /* sortlist ::= sortlist COMMA expr sortorder */
-#line 667 "parse.y"
+#line 673 "parse.y"
 {
   yymsp[-3].minor.yy382 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy382,yymsp[-1].minor.yy162.pExpr);
   sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy382,yymsp[0].minor.yy52);
 }
-#line 2873 "parse.c"
+#line 2879 "parse.c"
         break;
       case 116: /* sortlist ::= expr sortorder */
-#line 671 "parse.y"
+#line 677 "parse.y"
 {
   yymsp[-1].minor.yy382 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy162.pExpr); /*A-overwrites-Y*/
   sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy382,yymsp[0].minor.yy52);
 }
-#line 2881 "parse.c"
+#line 2887 "parse.c"
         break;
       case 117: /* sortorder ::= ASC */
-#line 678 "parse.y"
+#line 684 "parse.y"
 {yymsp[0].minor.yy52 = SQLITE_SO_ASC;}
-#line 2886 "parse.c"
+#line 2892 "parse.c"
         break;
       case 118: /* sortorder ::= DESC */
-#line 679 "parse.y"
+#line 685 "parse.y"
 {yymsp[0].minor.yy52 = SQLITE_SO_DESC;}
-#line 2891 "parse.c"
+#line 2897 "parse.c"
         break;
       case 119: /* sortorder ::= */
-#line 680 "parse.y"
+#line 686 "parse.y"
 {yymsp[1].minor.yy52 = SQLITE_SO_UNDEFINED;}
-#line 2896 "parse.c"
+#line 2902 "parse.c"
         break;
       case 124: /* limit_opt ::= */
-#line 705 "parse.y"
+#line 711 "parse.y"
 {yymsp[1].minor.yy384.pLimit = 0; yymsp[1].minor.yy384.pOffset = 0;}
-#line 2901 "parse.c"
+#line 2907 "parse.c"
         break;
       case 125: /* limit_opt ::= LIMIT expr */
-#line 706 "parse.y"
+#line 712 "parse.y"
 {yymsp[-1].minor.yy384.pLimit = yymsp[0].minor.yy162.pExpr; yymsp[-1].minor.yy384.pOffset = 0;}
-#line 2906 "parse.c"
+#line 2912 "parse.c"
         break;
       case 126: /* limit_opt ::= LIMIT expr OFFSET expr */
-#line 708 "parse.y"
+#line 714 "parse.y"
 {yymsp[-3].minor.yy384.pLimit = yymsp[-2].minor.yy162.pExpr; yymsp[-3].minor.yy384.pOffset = yymsp[0].minor.yy162.pExpr;}
-#line 2911 "parse.c"
+#line 2917 "parse.c"
         break;
       case 127: /* limit_opt ::= LIMIT expr COMMA expr */
-#line 710 "parse.y"
+#line 716 "parse.y"
 {yymsp[-3].minor.yy384.pOffset = yymsp[-2].minor.yy162.pExpr; yymsp[-3].minor.yy384.pLimit = yymsp[0].minor.yy162.pExpr;}
-#line 2916 "parse.c"
+#line 2922 "parse.c"
         break;
       case 128: /* cmd ::= with DELETE FROM fullname indexed_opt where_opt */
-#line 727 "parse.y"
+#line 733 "parse.y"
 {
   sqlite3WithPush(pParse, yymsp[-5].minor.yy151, 1);
   sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy387, &yymsp[-1].minor.yy0);
@@ -2924,10 +2930,10 @@ static void yy_reduce(
   pParse->initiateTTrans = true;
   sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy387,yymsp[0].minor.yy362);
 }
-#line 2928 "parse.c"
+#line 2934 "parse.c"
         break;
       case 131: /* cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */
-#line 760 "parse.y"
+#line 766 "parse.y"
 {
   sqlite3WithPush(pParse, yymsp[-7].minor.yy151, 1);
   sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy387, &yymsp[-3].minor.yy0);
@@ -2937,41 +2943,41 @@ static void yy_reduce(
   pParse->initiateTTrans = true;
   sqlite3Update(pParse,yymsp[-4].minor.yy387,yymsp[-1].minor.yy382,yymsp[0].minor.yy362,yymsp[-5].minor.yy52);
 }
-#line 2941 "parse.c"
+#line 2947 "parse.c"
         break;
       case 132: /* setlist ::= setlist COMMA nm EQ expr */
-#line 774 "parse.y"
+#line 780 "parse.y"
 {
   yymsp[-4].minor.yy382 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy382, yymsp[0].minor.yy162.pExpr);
   sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy382, &yymsp[-2].minor.yy0, 1);
 }
-#line 2949 "parse.c"
+#line 2955 "parse.c"
         break;
       case 133: /* setlist ::= setlist COMMA LP idlist RP EQ expr */
-#line 778 "parse.y"
+#line 784 "parse.y"
 {
   yymsp[-6].minor.yy382 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy382, yymsp[-3].minor.yy40, yymsp[0].minor.yy162.pExpr);
 }
-#line 2956 "parse.c"
+#line 2962 "parse.c"
         break;
       case 134: /* setlist ::= nm EQ expr */
-#line 781 "parse.y"
+#line 787 "parse.y"
 {
   yylhsminor.yy382 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy162.pExpr);
   sqlite3ExprListSetName(pParse, yylhsminor.yy382, &yymsp[-2].minor.yy0, 1);
 }
-#line 2964 "parse.c"
+#line 2970 "parse.c"
   yymsp[-2].minor.yy382 = yylhsminor.yy382;
         break;
       case 135: /* setlist ::= LP idlist RP EQ expr */
-#line 785 "parse.y"
+#line 791 "parse.y"
 {
   yymsp[-4].minor.yy382 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy40, yymsp[0].minor.yy162.pExpr);
 }
-#line 2972 "parse.c"
+#line 2978 "parse.c"
         break;
       case 136: /* cmd ::= with insert_cmd INTO fullname idlist_opt select */
-#line 791 "parse.y"
+#line 797 "parse.y"
 {
   sqlite3WithPush(pParse, yymsp[-5].minor.yy151, 1);
   sqlSubProgramsRemaining = SQL_MAX_COMPILING_TRIGGERS;
@@ -2979,10 +2985,10 @@ static void yy_reduce(
   pParse->initiateTTrans = true;
   sqlite3Insert(pParse, yymsp[-2].minor.yy387, yymsp[0].minor.yy279, yymsp[-1].minor.yy40, yymsp[-4].minor.yy52);
 }
-#line 2983 "parse.c"
+#line 2989 "parse.c"
         break;
       case 137: /* cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */
-#line 799 "parse.y"
+#line 805 "parse.y"
 {
   sqlite3WithPush(pParse, yymsp[-6].minor.yy151, 1);
   sqlSubProgramsRemaining = SQL_MAX_COMPILING_TRIGGERS;
@@ -2990,64 +2996,64 @@ static void yy_reduce(
   pParse->initiateTTrans = true;
   sqlite3Insert(pParse, yymsp[-3].minor.yy387, 0, yymsp[-2].minor.yy40, yymsp[-5].minor.yy52);
 }
-#line 2994 "parse.c"
+#line 3000 "parse.c"
         break;
       case 141: /* idlist_opt ::= LP idlist RP */
-#line 817 "parse.y"
+#line 823 "parse.y"
 {yymsp[-2].minor.yy40 = yymsp[-1].minor.yy40;}
-#line 2999 "parse.c"
+#line 3005 "parse.c"
         break;
       case 142: /* idlist ::= idlist COMMA nm */
-#line 819 "parse.y"
+#line 825 "parse.y"
 {yymsp[-2].minor.yy40 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy40,&yymsp[0].minor.yy0);}
-#line 3004 "parse.c"
+#line 3010 "parse.c"
         break;
       case 143: /* idlist ::= nm */
-#line 821 "parse.y"
+#line 827 "parse.y"
 {yymsp[0].minor.yy40 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
-#line 3009 "parse.c"
+#line 3015 "parse.c"
         break;
       case 144: /* expr ::= LP expr RP */
-#line 870 "parse.y"
+#line 876 "parse.y"
 {spanSet(&yymsp[-2].minor.yy162,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/  yymsp[-2].minor.yy162.pExpr = yymsp[-1].minor.yy162.pExpr;}
-#line 3014 "parse.c"
+#line 3020 "parse.c"
         break;
       case 145: /* term ::= NULL */
       case 149: /* term ::= FLOAT|BLOB */ yytestcase(yyruleno==149);
       case 150: /* term ::= STRING */ yytestcase(yyruleno==150);
-#line 871 "parse.y"
+#line 877 "parse.y"
 {spanExpr(&yymsp[0].minor.yy162,pParse,yymsp[0].major,yymsp[0].minor.yy0);/*A-overwrites-X*/}
-#line 3021 "parse.c"
+#line 3027 "parse.c"
         break;
       case 146: /* expr ::= ID|INDEXED */
       case 147: /* expr ::= JOIN_KW */ yytestcase(yyruleno==147);
-#line 872 "parse.y"
+#line 878 "parse.y"
 {spanExpr(&yymsp[0].minor.yy162,pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
-#line 3027 "parse.c"
+#line 3033 "parse.c"
         break;
       case 148: /* expr ::= nm DOT nm */
-#line 874 "parse.y"
+#line 880 "parse.y"
 {
   Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
   Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1);
   spanSet(&yymsp[-2].minor.yy162,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/
   yymsp[-2].minor.yy162.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
 }
-#line 3037 "parse.c"
+#line 3043 "parse.c"
         break;
       case 151: /* term ::= INTEGER */
-#line 882 "parse.y"
+#line 888 "parse.y"
 {
   yylhsminor.yy162.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1);
   yylhsminor.yy162.zStart = yymsp[0].minor.yy0.z;
   yylhsminor.yy162.zEnd = yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n;
   if( yylhsminor.yy162.pExpr ) yylhsminor.yy162.pExpr->flags |= EP_Leaf;
 }
-#line 3047 "parse.c"
+#line 3053 "parse.c"
   yymsp[0].minor.yy162 = yylhsminor.yy162;
         break;
       case 152: /* expr ::= VARIABLE */
-#line 888 "parse.y"
+#line 894 "parse.y"
 {
   if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){
     u32 n = yymsp[0].minor.yy0.n;
@@ -3069,27 +3075,27 @@ static void yy_reduce(
     }
   }
 }
-#line 3073 "parse.c"
+#line 3079 "parse.c"
         break;
       case 153: /* expr ::= expr COLLATE ID|INDEXED */
-#line 909 "parse.y"
+#line 915 "parse.y"
 {
   yymsp[-2].minor.yy162.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy162.pExpr, &yymsp[0].minor.yy0, 1);
   yymsp[-2].minor.yy162.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
 }
-#line 3081 "parse.c"
+#line 3087 "parse.c"
         break;
       case 154: /* expr ::= CAST LP expr AS typetoken RP */
-#line 914 "parse.y"
+#line 920 "parse.y"
 {
   spanSet(&yymsp[-5].minor.yy162,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/
   yymsp[-5].minor.yy162.pExpr = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
   sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy162.pExpr, yymsp[-3].minor.yy162.pExpr, 0);
 }
-#line 3090 "parse.c"
+#line 3096 "parse.c"
         break;
       case 155: /* expr ::= ID|INDEXED LP distinct exprlist RP */
-#line 920 "parse.y"
+#line 926 "parse.y"
 {
   if( yymsp[-1].minor.yy382 && yymsp[-1].minor.yy382->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
     sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
@@ -3100,29 +3106,29 @@ static void yy_reduce(
     yylhsminor.yy162.pExpr->flags |= EP_Distinct;
   }
 }
-#line 3104 "parse.c"
+#line 3110 "parse.c"
   yymsp[-4].minor.yy162 = yylhsminor.yy162;
         break;
       case 156: /* expr ::= ID|INDEXED LP STAR RP */
-#line 930 "parse.y"
+#line 936 "parse.y"
 {
   yylhsminor.yy162.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
   spanSet(&yylhsminor.yy162,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
 }
-#line 3113 "parse.c"
+#line 3119 "parse.c"
   yymsp[-3].minor.yy162 = yylhsminor.yy162;
         break;
       case 157: /* term ::= CTIME_KW */
-#line 934 "parse.y"
+#line 940 "parse.y"
 {
   yylhsminor.yy162.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0);
   spanSet(&yylhsminor.yy162, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
 }
-#line 3122 "parse.c"
+#line 3128 "parse.c"
   yymsp[0].minor.yy162 = yylhsminor.yy162;
         break;
       case 158: /* expr ::= LP nexprlist COMMA expr RP */
-#line 963 "parse.y"
+#line 969 "parse.y"
 {
   ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy382, yymsp[-1].minor.yy162.pExpr);
   yylhsminor.yy162.pExpr = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
@@ -3133,7 +3139,7 @@ static void yy_reduce(
     sqlite3ExprListDelete(pParse->db, pList);
   }
 }
-#line 3137 "parse.c"
+#line 3143 "parse.c"
   yymsp[-4].minor.yy162 = yylhsminor.yy162;
         break;
       case 159: /* expr ::= expr AND expr */
@@ -3144,22 +3150,22 @@ static void yy_reduce(
       case 164: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==164);
       case 165: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==165);
       case 166: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==166);
-#line 974 "parse.y"
+#line 980 "parse.y"
 {spanBinaryExpr(pParse,yymsp[-1].major,&yymsp[-2].minor.yy162,&yymsp[0].minor.yy162);}
-#line 3150 "parse.c"
+#line 3156 "parse.c"
         break;
       case 167: /* likeop ::= LIKE_KW|MATCH */
-#line 987 "parse.y"
+#line 993 "parse.y"
 {yymsp[0].minor.yy0=yymsp[0].minor.yy0;/*A-overwrites-X*/}
-#line 3155 "parse.c"
+#line 3161 "parse.c"
         break;
       case 168: /* likeop ::= NOT LIKE_KW|MATCH */
-#line 988 "parse.y"
+#line 994 "parse.y"
 {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/}
-#line 3160 "parse.c"
+#line 3166 "parse.c"
         break;
       case 169: /* expr ::= expr likeop expr */
-#line 989 "parse.y"
+#line 995 "parse.y"
 {
   ExprList *pList;
   int bNot = yymsp[-1].minor.yy0.n & 0x80000000;
@@ -3171,10 +3177,10 @@ static void yy_reduce(
   yymsp[-2].minor.yy162.zEnd = yymsp[0].minor.yy162.zEnd;
   if( yymsp[-2].minor.yy162.pExpr ) yymsp[-2].minor.yy162.pExpr->flags |= EP_InfixFunc;
 }
-#line 3175 "parse.c"
+#line 3181 "parse.c"
         break;
       case 170: /* expr ::= expr likeop expr ESCAPE expr */
-#line 1000 "parse.y"
+#line 1006 "parse.y"
 {
   ExprList *pList;
   int bNot = yymsp[-3].minor.yy0.n & 0x80000000;
@@ -3187,58 +3193,58 @@ static void yy_reduce(
   yymsp[-4].minor.yy162.zEnd = yymsp[0].minor.yy162.zEnd;
   if( yymsp[-4].minor.yy162.pExpr ) yymsp[-4].minor.yy162.pExpr->flags |= EP_InfixFunc;
 }
-#line 3191 "parse.c"
+#line 3197 "parse.c"
         break;
       case 171: /* expr ::= expr ISNULL|NOTNULL */
-#line 1027 "parse.y"
+#line 1033 "parse.y"
 {spanUnaryPostfix(pParse,yymsp[0].major,&yymsp[-1].minor.yy162,&yymsp[0].minor.yy0);}
-#line 3196 "parse.c"
+#line 3202 "parse.c"
         break;
       case 172: /* expr ::= expr NOT NULL */
-#line 1028 "parse.y"
+#line 1034 "parse.y"
 {spanUnaryPostfix(pParse,TK_NOTNULL,&yymsp[-2].minor.yy162,&yymsp[0].minor.yy0);}
-#line 3201 "parse.c"
+#line 3207 "parse.c"
         break;
       case 173: /* expr ::= expr IS expr */
-#line 1049 "parse.y"
+#line 1055 "parse.y"
 {
   spanBinaryExpr(pParse,TK_IS,&yymsp[-2].minor.yy162,&yymsp[0].minor.yy162);
   binaryToUnaryIfNull(pParse, yymsp[0].minor.yy162.pExpr, yymsp[-2].minor.yy162.pExpr, TK_ISNULL);
 }
-#line 3209 "parse.c"
+#line 3215 "parse.c"
         break;
       case 174: /* expr ::= expr IS NOT expr */
-#line 1053 "parse.y"
+#line 1059 "parse.y"
 {
   spanBinaryExpr(pParse,TK_ISNOT,&yymsp[-3].minor.yy162,&yymsp[0].minor.yy162);
   binaryToUnaryIfNull(pParse, yymsp[0].minor.yy162.pExpr, yymsp[-3].minor.yy162.pExpr, TK_NOTNULL);
 }
-#line 3217 "parse.c"
+#line 3223 "parse.c"
         break;
       case 175: /* expr ::= NOT expr */
       case 176: /* expr ::= BITNOT expr */ yytestcase(yyruleno==176);
-#line 1077 "parse.y"
+#line 1083 "parse.y"
 {spanUnaryPrefix(&yymsp[-1].minor.yy162,pParse,yymsp[-1].major,&yymsp[0].minor.yy162,&yymsp[-1].minor.yy0);/*A-overwrites-B*/}
-#line 3223 "parse.c"
+#line 3229 "parse.c"
         break;
       case 177: /* expr ::= MINUS expr */
-#line 1081 "parse.y"
+#line 1087 "parse.y"
 {spanUnaryPrefix(&yymsp[-1].minor.yy162,pParse,TK_UMINUS,&yymsp[0].minor.yy162,&yymsp[-1].minor.yy0);/*A-overwrites-B*/}
-#line 3228 "parse.c"
+#line 3234 "parse.c"
         break;
       case 178: /* expr ::= PLUS expr */
-#line 1083 "parse.y"
+#line 1089 "parse.y"
 {spanUnaryPrefix(&yymsp[-1].minor.yy162,pParse,TK_UPLUS,&yymsp[0].minor.yy162,&yymsp[-1].minor.yy0);/*A-overwrites-B*/}
-#line 3233 "parse.c"
+#line 3239 "parse.c"
         break;
       case 179: /* between_op ::= BETWEEN */
       case 182: /* in_op ::= IN */ yytestcase(yyruleno==182);
-#line 1086 "parse.y"
+#line 1092 "parse.y"
 {yymsp[0].minor.yy52 = 0;}
-#line 3239 "parse.c"
+#line 3245 "parse.c"
         break;
       case 181: /* expr ::= expr between_op expr AND expr */
-#line 1088 "parse.y"
+#line 1094 "parse.y"
 {
   ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy162.pExpr);
   pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy162.pExpr);
@@ -3251,10 +3257,10 @@ static void yy_reduce(
   exprNot(pParse, yymsp[-3].minor.yy52, &yymsp[-4].minor.yy162);
   yymsp[-4].minor.yy162.zEnd = yymsp[0].minor.yy162.zEnd;
 }
-#line 3255 "parse.c"
+#line 3261 "parse.c"
         break;
       case 184: /* expr ::= expr in_op LP exprlist RP */
-#line 1104 "parse.y"
+#line 1110 "parse.y"
 {
     if( yymsp[-1].minor.yy382==0 ){
       /* Expressions of the form
@@ -3265,7 +3271,7 @@ static void yy_reduce(
       ** simplify to constants 0 (false) and 1 (true), respectively,
       ** regardless of the value of expr1.
       */
-      sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy162.pExpr);
+	    sql_expr_free(pParse->db, yymsp[-4].minor.yy162.pExpr, false);
       yymsp[-4].minor.yy162.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[yymsp[-3].minor.yy52],1);
     }else if( yymsp[-1].minor.yy382->nExpr==1 ){
       /* Expressions of the form:
@@ -3306,29 +3312,29 @@ static void yy_reduce(
     }
     yymsp[-4].minor.yy162.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
   }
-#line 3310 "parse.c"
+#line 3316 "parse.c"
         break;
       case 185: /* expr ::= LP select RP */
-#line 1155 "parse.y"
+#line 1161 "parse.y"
 {
     spanSet(&yymsp[-2].minor.yy162,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/
     yymsp[-2].minor.yy162.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
     sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy162.pExpr, yymsp[-1].minor.yy279);
   }
-#line 3319 "parse.c"
+#line 3325 "parse.c"
         break;
       case 186: /* expr ::= expr in_op LP select RP */
-#line 1160 "parse.y"
+#line 1166 "parse.y"
 {
     yymsp[-4].minor.yy162.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy162.pExpr, 0);
     sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy162.pExpr, yymsp[-1].minor.yy279);
     exprNot(pParse, yymsp[-3].minor.yy52, &yymsp[-4].minor.yy162);
     yymsp[-4].minor.yy162.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
   }
-#line 3329 "parse.c"
+#line 3335 "parse.c"
         break;
       case 187: /* expr ::= expr in_op nm paren_exprlist */
-#line 1166 "parse.y"
+#line 1172 "parse.y"
 {
     SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0);
     Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
@@ -3338,20 +3344,20 @@ static void yy_reduce(
     exprNot(pParse, yymsp[-2].minor.yy52, &yymsp[-3].minor.yy162);
     yymsp[-3].minor.yy162.zEnd = &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n];
   }
-#line 3342 "parse.c"
+#line 3348 "parse.c"
         break;
       case 188: /* expr ::= EXISTS LP select RP */
-#line 1175 "parse.y"
+#line 1181 "parse.y"
 {
     Expr *p;
     spanSet(&yymsp[-3].minor.yy162,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/
     p = yymsp[-3].minor.yy162.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
     sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy279);
   }
-#line 3352 "parse.c"
+#line 3358 "parse.c"
         break;
       case 189: /* expr ::= CASE case_operand case_exprlist case_else END */
-#line 1184 "parse.y"
+#line 1190 "parse.y"
 {
   spanSet(&yymsp[-4].minor.yy162,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);  /*A-overwrites-C*/
   yymsp[-4].minor.yy162.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy362, 0);
@@ -3360,140 +3366,140 @@ static void yy_reduce(
     sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy162.pExpr);
   }else{
     sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy382);
-    sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy362);
+    sql_expr_free(pParse->db, yymsp[-1].minor.yy362, false);
   }
 }
-#line 3367 "parse.c"
+#line 3373 "parse.c"
         break;
       case 190: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
-#line 1197 "parse.y"
+#line 1203 "parse.y"
 {
   yymsp[-4].minor.yy382 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy382, yymsp[-2].minor.yy162.pExpr);
   yymsp[-4].minor.yy382 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy382, yymsp[0].minor.yy162.pExpr);
 }
-#line 3375 "parse.c"
+#line 3381 "parse.c"
         break;
       case 191: /* case_exprlist ::= WHEN expr THEN expr */
-#line 1201 "parse.y"
+#line 1207 "parse.y"
 {
   yymsp[-3].minor.yy382 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy162.pExpr);
   yymsp[-3].minor.yy382 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy382, yymsp[0].minor.yy162.pExpr);
 }
-#line 3383 "parse.c"
+#line 3389 "parse.c"
         break;
       case 194: /* case_operand ::= expr */
-#line 1211 "parse.y"
+#line 1217 "parse.y"
 {yymsp[0].minor.yy362 = yymsp[0].minor.yy162.pExpr; /*A-overwrites-X*/}
-#line 3388 "parse.c"
+#line 3394 "parse.c"
         break;
       case 197: /* nexprlist ::= nexprlist COMMA expr */
-#line 1222 "parse.y"
+#line 1228 "parse.y"
 {yymsp[-2].minor.yy382 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy382,yymsp[0].minor.yy162.pExpr);}
-#line 3393 "parse.c"
+#line 3399 "parse.c"
         break;
       case 198: /* nexprlist ::= expr */
-#line 1224 "parse.y"
+#line 1230 "parse.y"
 {yymsp[0].minor.yy382 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy162.pExpr); /*A-overwrites-Y*/}
-#line 3398 "parse.c"
+#line 3404 "parse.c"
         break;
       case 200: /* paren_exprlist ::= LP exprlist RP */
       case 205: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==205);
-#line 1232 "parse.y"
+#line 1238 "parse.y"
 {yymsp[-2].minor.yy382 = yymsp[-1].minor.yy382;}
-#line 3404 "parse.c"
+#line 3410 "parse.c"
         break;
       case 201: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm ON nm LP sortlist RP where_opt */
-#line 1239 "parse.y"
+#line 1245 "parse.y"
 {
   sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, 
                      sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0), yymsp[-2].minor.yy382, yymsp[-9].minor.yy52,
                       &yymsp[-10].minor.yy0, yymsp[0].minor.yy362, SQLITE_SO_ASC, yymsp[-7].minor.yy52, SQLITE_IDXTYPE_APPDEF);
 }
-#line 3413 "parse.c"
+#line 3419 "parse.c"
         break;
       case 202: /* uniqueflag ::= UNIQUE */
       case 243: /* raisetype ::= ABORT */ yytestcase(yyruleno==243);
-#line 1246 "parse.y"
+#line 1252 "parse.y"
 {yymsp[0].minor.yy52 = ON_CONFLICT_ACTION_ABORT;}
-#line 3419 "parse.c"
+#line 3425 "parse.c"
         break;
       case 203: /* uniqueflag ::= */
-#line 1247 "parse.y"
+#line 1253 "parse.y"
 {yymsp[1].minor.yy52 = ON_CONFLICT_ACTION_NONE;}
-#line 3424 "parse.c"
+#line 3430 "parse.c"
         break;
       case 206: /* eidlist ::= eidlist COMMA nm collate sortorder */
-#line 1290 "parse.y"
+#line 1296 "parse.y"
 {
   yymsp[-4].minor.yy382 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy382, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy52, yymsp[0].minor.yy52);
 }
-#line 3431 "parse.c"
+#line 3437 "parse.c"
         break;
       case 207: /* eidlist ::= nm collate sortorder */
-#line 1293 "parse.y"
+#line 1299 "parse.y"
 {
   yymsp[-2].minor.yy382 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy52, yymsp[0].minor.yy52); /*A-overwrites-Y*/
 }
-#line 3438 "parse.c"
+#line 3444 "parse.c"
         break;
       case 210: /* cmd ::= DROP INDEX ifexists fullname ON nm */
-#line 1304 "parse.y"
+#line 1310 "parse.y"
 {
     sqlite3DropIndex(pParse, yymsp[-2].minor.yy387, &yymsp[0].minor.yy0, yymsp[-3].minor.yy52);
 }
-#line 3445 "parse.c"
+#line 3451 "parse.c"
         break;
       case 211: /* cmd ::= PRAGMA nm */
-#line 1311 "parse.y"
+#line 1317 "parse.y"
 {
     sqlite3Pragma(pParse,&yymsp[0].minor.yy0,0,0,0,0);
 }
-#line 3452 "parse.c"
+#line 3458 "parse.c"
         break;
       case 212: /* cmd ::= PRAGMA nm EQ nmnum */
-#line 1314 "parse.y"
+#line 1320 "parse.y"
 {
     sqlite3Pragma(pParse,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy0,0,0);
 }
-#line 3459 "parse.c"
+#line 3465 "parse.c"
         break;
       case 213: /* cmd ::= PRAGMA nm LP nmnum RP */
-#line 1317 "parse.y"
+#line 1323 "parse.y"
 {
     sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,0,&yymsp[-1].minor.yy0,0,0);
 }
-#line 3466 "parse.c"
+#line 3472 "parse.c"
         break;
       case 214: /* cmd ::= PRAGMA nm EQ minus_num */
-#line 1320 "parse.y"
+#line 1326 "parse.y"
 {
     sqlite3Pragma(pParse,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy0,0,1);
 }
-#line 3473 "parse.c"
+#line 3479 "parse.c"
         break;
       case 215: /* cmd ::= PRAGMA nm LP minus_num RP */
-#line 1323 "parse.y"
+#line 1329 "parse.y"
 {
     sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,0,&yymsp[-1].minor.yy0,0,1);
 }
-#line 3480 "parse.c"
+#line 3486 "parse.c"
         break;
       case 216: /* cmd ::= PRAGMA nm EQ nm DOT nm */
-#line 1326 "parse.y"
+#line 1332 "parse.y"
 {
     sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,0,&yymsp[0].minor.yy0,&yymsp[-2].minor.yy0,0);
 }
-#line 3487 "parse.c"
+#line 3493 "parse.c"
         break;
       case 217: /* cmd ::= PRAGMA */
-#line 1329 "parse.y"
+#line 1335 "parse.y"
 {
     sqlite3Pragma(pParse, 0,0,0,0,0);
 }
-#line 3494 "parse.c"
+#line 3500 "parse.c"
         break;
       case 220: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
-#line 1349 "parse.y"
+#line 1355 "parse.y"
 {
   Token all;
   all.z = yymsp[-3].minor.yy0.z;
@@ -3501,124 +3507,124 @@ static void yy_reduce(
   pParse->initiateTTrans = false;
   sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy427, &all);
 }
-#line 3505 "parse.c"
+#line 3511 "parse.c"
         break;
       case 221: /* trigger_decl ::= TRIGGER ifnotexists nm trigger_time trigger_event ON fullname foreach_clause when_clause */
-#line 1359 "parse.y"
+#line 1365 "parse.y"
 {
   sqlite3BeginTrigger(pParse, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy52, yymsp[-4].minor.yy10.a, yymsp[-4].minor.yy10.b, yymsp[-2].minor.yy387, yymsp[0].minor.yy362, yymsp[-7].minor.yy52);
   yymsp[-8].minor.yy0 = yymsp[-6].minor.yy0; /*yymsp[-8].minor.yy0-overwrites-T*/
 }
-#line 3513 "parse.c"
+#line 3519 "parse.c"
         break;
       case 222: /* trigger_time ::= BEFORE */
-#line 1365 "parse.y"
+#line 1371 "parse.y"
 { yymsp[0].minor.yy52 = TK_BEFORE; }
-#line 3518 "parse.c"
+#line 3524 "parse.c"
         break;
       case 223: /* trigger_time ::= AFTER */
-#line 1366 "parse.y"
+#line 1372 "parse.y"
 { yymsp[0].minor.yy52 = TK_AFTER;  }
-#line 3523 "parse.c"
+#line 3529 "parse.c"
         break;
       case 224: /* trigger_time ::= INSTEAD OF */
-#line 1367 "parse.y"
+#line 1373 "parse.y"
 { yymsp[-1].minor.yy52 = TK_INSTEAD;}
-#line 3528 "parse.c"
+#line 3534 "parse.c"
         break;
       case 225: /* trigger_time ::= */
-#line 1368 "parse.y"
+#line 1374 "parse.y"
 { yymsp[1].minor.yy52 = TK_BEFORE; }
-#line 3533 "parse.c"
+#line 3539 "parse.c"
         break;
       case 226: /* trigger_event ::= DELETE|INSERT */
       case 227: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==227);
-#line 1372 "parse.y"
+#line 1378 "parse.y"
 {yymsp[0].minor.yy10.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy10.b = 0;}
-#line 3539 "parse.c"
+#line 3545 "parse.c"
         break;
       case 228: /* trigger_event ::= UPDATE OF idlist */
-#line 1374 "parse.y"
+#line 1380 "parse.y"
 {yymsp[-2].minor.yy10.a = TK_UPDATE; yymsp[-2].minor.yy10.b = yymsp[0].minor.yy40;}
-#line 3544 "parse.c"
+#line 3550 "parse.c"
         break;
       case 229: /* when_clause ::= */
-#line 1381 "parse.y"
+#line 1387 "parse.y"
 { yymsp[1].minor.yy362 = 0; }
-#line 3549 "parse.c"
+#line 3555 "parse.c"
         break;
       case 230: /* when_clause ::= WHEN expr */
-#line 1382 "parse.y"
+#line 1388 "parse.y"
 { yymsp[-1].minor.yy362 = yymsp[0].minor.yy162.pExpr; }
-#line 3554 "parse.c"
+#line 3560 "parse.c"
         break;
       case 231: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
-#line 1386 "parse.y"
+#line 1392 "parse.y"
 {
   assert( yymsp[-2].minor.yy427!=0 );
   yymsp[-2].minor.yy427->pLast->pNext = yymsp[-1].minor.yy427;
   yymsp[-2].minor.yy427->pLast = yymsp[-1].minor.yy427;
 }
-#line 3563 "parse.c"
+#line 3569 "parse.c"
         break;
       case 232: /* trigger_cmd_list ::= trigger_cmd SEMI */
-#line 1391 "parse.y"
+#line 1397 "parse.y"
 { 
   assert( yymsp[-1].minor.yy427!=0 );
   yymsp[-1].minor.yy427->pLast = yymsp[-1].minor.yy427;
 }
-#line 3571 "parse.c"
+#line 3577 "parse.c"
         break;
       case 233: /* trnm ::= nm DOT nm */
-#line 1402 "parse.y"
+#line 1408 "parse.y"
 {
   yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;
   sqlite3ErrorMsg(pParse, 
         "qualified table names are not allowed on INSERT, UPDATE, and DELETE "
         "statements within triggers");
 }
-#line 3581 "parse.c"
+#line 3587 "parse.c"
         break;
       case 234: /* tridxby ::= INDEXED BY nm */
-#line 1414 "parse.y"
+#line 1420 "parse.y"
 {
   sqlite3ErrorMsg(pParse,
         "the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
         "within triggers");
 }
-#line 3590 "parse.c"
+#line 3596 "parse.c"
         break;
       case 235: /* tridxby ::= NOT INDEXED */
-#line 1419 "parse.y"
+#line 1425 "parse.y"
 {
   sqlite3ErrorMsg(pParse,
         "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
         "within triggers");
 }
-#line 3599 "parse.c"
+#line 3605 "parse.c"
         break;
       case 236: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */
-#line 1432 "parse.y"
+#line 1438 "parse.y"
 {yymsp[-6].minor.yy427 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy382, yymsp[0].minor.yy362, yymsp[-5].minor.yy52);}
-#line 3604 "parse.c"
+#line 3610 "parse.c"
         break;
       case 237: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */
-#line 1436 "parse.y"
+#line 1442 "parse.y"
 {yymsp[-4].minor.yy427 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy40, yymsp[0].minor.yy279, yymsp[-4].minor.yy52);/*A-overwrites-R*/}
-#line 3609 "parse.c"
+#line 3615 "parse.c"
         break;
       case 238: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */
-#line 1440 "parse.y"
+#line 1446 "parse.y"
 {yymsp[-4].minor.yy427 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy362);}
-#line 3614 "parse.c"
+#line 3620 "parse.c"
         break;
       case 239: /* trigger_cmd ::= select */
-#line 1444 "parse.y"
+#line 1450 "parse.y"
 {yymsp[0].minor.yy427 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy279); /*A-overwrites-X*/}
-#line 3619 "parse.c"
+#line 3625 "parse.c"
         break;
       case 240: /* expr ::= RAISE LP IGNORE RP */
-#line 1447 "parse.y"
+#line 1453 "parse.y"
 {
   spanSet(&yymsp[-3].minor.yy162,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);  /*A-overwrites-X*/
   yymsp[-3].minor.yy162.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0); 
@@ -3626,10 +3632,10 @@ static void yy_reduce(
     yymsp[-3].minor.yy162.pExpr->affinity = ON_CONFLICT_ACTION_IGNORE;
   }
 }
-#line 3630 "parse.c"
+#line 3636 "parse.c"
         break;
       case 241: /* expr ::= RAISE LP raisetype COMMA STRING RP */
-#line 1454 "parse.y"
+#line 1460 "parse.y"
 {
   spanSet(&yymsp[-5].minor.yy162,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);  /*A-overwrites-X*/
   yymsp[-5].minor.yy162.pExpr = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); 
@@ -3637,85 +3643,85 @@ static void yy_reduce(
     yymsp[-5].minor.yy162.pExpr->affinity = (char)yymsp[-3].minor.yy52;
   }
 }
-#line 3641 "parse.c"
+#line 3647 "parse.c"
         break;
       case 242: /* raisetype ::= ROLLBACK */
-#line 1464 "parse.y"
+#line 1470 "parse.y"
 {yymsp[0].minor.yy52 = ON_CONFLICT_ACTION_ROLLBACK;}
-#line 3646 "parse.c"
+#line 3652 "parse.c"
         break;
       case 244: /* raisetype ::= FAIL */
-#line 1466 "parse.y"
+#line 1472 "parse.y"
 {yymsp[0].minor.yy52 = ON_CONFLICT_ACTION_FAIL;}
-#line 3651 "parse.c"
+#line 3657 "parse.c"
         break;
       case 245: /* cmd ::= DROP TRIGGER ifexists fullname */
-#line 1471 "parse.y"
+#line 1477 "parse.y"
 {
   sqlite3DropTrigger(pParse,yymsp[0].minor.yy387,yymsp[-1].minor.yy52);
 }
-#line 3658 "parse.c"
+#line 3664 "parse.c"
         break;
       case 246: /* cmd ::= REINDEX */
-#line 1478 "parse.y"
+#line 1484 "parse.y"
 {sqlite3Reindex(pParse, 0, 0);}
-#line 3663 "parse.c"
+#line 3669 "parse.c"
         break;
       case 247: /* cmd ::= REINDEX nm */
-#line 1479 "parse.y"
+#line 1485 "parse.y"
 {sqlite3Reindex(pParse, &yymsp[0].minor.yy0, 0);}
-#line 3668 "parse.c"
+#line 3674 "parse.c"
         break;
       case 248: /* cmd ::= REINDEX nm ON nm */
-#line 1480 "parse.y"
+#line 1486 "parse.y"
 {sqlite3Reindex(pParse, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);}
-#line 3673 "parse.c"
+#line 3679 "parse.c"
         break;
       case 249: /* cmd ::= ANALYZE */
-#line 1485 "parse.y"
+#line 1491 "parse.y"
 {sqlite3Analyze(pParse, 0);}
-#line 3678 "parse.c"
+#line 3684 "parse.c"
         break;
       case 250: /* cmd ::= ANALYZE nm */
-#line 1486 "parse.y"
+#line 1492 "parse.y"
 {sqlite3Analyze(pParse, &yymsp[0].minor.yy0);}
-#line 3683 "parse.c"
+#line 3689 "parse.c"
         break;
       case 251: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
-#line 1491 "parse.y"
+#line 1497 "parse.y"
 {
   sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy387,&yymsp[0].minor.yy0);
 }
-#line 3690 "parse.c"
+#line 3696 "parse.c"
         break;
       case 252: /* with ::= */
-#line 1514 "parse.y"
+#line 1520 "parse.y"
 {yymsp[1].minor.yy151 = 0;}
-#line 3695 "parse.c"
+#line 3701 "parse.c"
         break;
       case 253: /* with ::= WITH wqlist */
-#line 1516 "parse.y"
+#line 1522 "parse.y"
 { yymsp[-1].minor.yy151 = yymsp[0].minor.yy151; }
-#line 3700 "parse.c"
+#line 3706 "parse.c"
         break;
       case 254: /* with ::= WITH RECURSIVE wqlist */
-#line 1517 "parse.y"
+#line 1523 "parse.y"
 { yymsp[-2].minor.yy151 = yymsp[0].minor.yy151; }
-#line 3705 "parse.c"
+#line 3711 "parse.c"
         break;
       case 255: /* wqlist ::= nm eidlist_opt AS LP select RP */
-#line 1519 "parse.y"
+#line 1525 "parse.y"
 {
   yymsp[-5].minor.yy151 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy382, yymsp[-1].minor.yy279); /*A-overwrites-X*/
 }
-#line 3712 "parse.c"
+#line 3718 "parse.c"
         break;
       case 256: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
-#line 1522 "parse.y"
+#line 1528 "parse.y"
 {
   yymsp[-7].minor.yy151 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy151, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy382, yymsp[-1].minor.yy279);
 }
-#line 3719 "parse.c"
+#line 3725 "parse.c"
         break;
       default:
       /* (257) input ::= ecmd */ yytestcase(yyruleno==257);
@@ -3826,7 +3832,7 @@ static void yy_syntax_error(
   } else {
     sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
   }
-#line 3830 "parse.c"
+#line 3836 "parse.c"
 /************ End %syntax_error code ******************************************/
   sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
 }
modified   src/box/sql/parse.y
@@ -108,7 +108,10 @@ static void disableLookaside(Parse *pParse){
 
 // Input is a single SQL command
 input ::= ecmd.
-ecmd ::= explain cmdx SEMI.       { sqlite3FinishCoding(pParse); }
+ecmd ::= explain cmdx SEMI. {
+	if (!pParse->parse_only)
+		sqlite3FinishCoding(pParse);
+}
 ecmd ::= SEMI. {
   sqlite3ErrorMsg(pParse, "syntax error: empty request");
 }
@@ -378,7 +381,10 @@ cmd ::= DROP VIEW ifexists(E) fullname(X). {
 //
 cmd ::= select(X).  {
   SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
-  sqlite3Select(pParse, X, &dest);
+  if(!pParse->parse_only)
+	  sqlite3Select(pParse, X, &dest);
+  else
+	  sql_expr_extract_select(pParse, X);
   sqlite3SelectDelete(pParse->db, X);
 }
 
@@ -627,7 +633,7 @@ joinop(X) ::= JOIN_KW(A) join_nm(B) join_nm(C) JOIN.
                   {X = sqlite3JoinType(pParse,&A,&B,&C);/*X-overwrites-A*/}
 
 %type on_opt {Expr*}
-%destructor on_opt {sqlite3ExprDelete(pParse->db, $$);}
+%destructor on_opt {sql_expr_free(pParse->db, $$, false);}
 on_opt(N) ::= ON expr(E).   {N = E.pExpr;}
 on_opt(N) ::= .             {N = 0;}
 
@@ -685,7 +691,7 @@ groupby_opt(A) ::= .                      {A = 0;}
 groupby_opt(A) ::= GROUP BY nexprlist(X). {A = X;}
 
 %type having_opt {Expr*}
-%destructor having_opt {sqlite3ExprDelete(pParse->db, $$);}
+%destructor having_opt {sql_expr_free(pParse->db, $$, false);}
 having_opt(A) ::= .                {A = 0;}
 having_opt(A) ::= HAVING expr(X).  {A = X.pExpr;}
 
@@ -735,7 +741,7 @@ cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W). {
 %endif
 
 %type where_opt {Expr*}
-%destructor where_opt {sqlite3ExprDelete(pParse->db, $$);}
+%destructor where_opt {sql_expr_free(pParse->db, $$, false);}
 
 where_opt(A) ::= .                    {A = 0;}
 where_opt(A) ::= WHERE expr(X).       {A = X.pExpr;}
@@ -824,9 +830,9 @@ idlist(A) ::= nm(Y).
 //
 
 %type expr {ExprSpan}
-%destructor expr {sqlite3ExprDelete(pParse->db, $$.pExpr);}
+%destructor expr {sql_expr_free(pParse->db, $$.pExpr, false);}
 %type term {ExprSpan}
-%destructor term {sqlite3ExprDelete(pParse->db, $$.pExpr);}
+%destructor term {sql_expr_free(pParse->db, $$.pExpr, false);}
 
 %include {
   /* This is a utility routine used to set the ExprSpan.zStart and
@@ -1034,7 +1040,7 @@ expr(A) ::= expr(A) NOT NULL(E). {spanUnaryPostfix(pParse,TK_NOTNULL,&A,&E);}
     sqlite3 *db = pParse->db;
     if( pA && pY && pY->op==TK_NULL ){
       pA->op = (u8)op;
-      sqlite3ExprDelete(db, pA->pRight);
+      sql_expr_free(db, pA->pRight, false);
       pA->pRight = 0;
     }
   }
@@ -1111,7 +1117,7 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
       ** simplify to constants 0 (false) and 1 (true), respectively,
       ** regardless of the value of expr1.
       */
-      sqlite3ExprDelete(pParse->db, A.pExpr);
+	    sql_expr_free(pParse->db, A.pExpr, false);
       A.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[N],1);
     }else if( Y->nExpr==1 ){
       /* Expressions of the form:
@@ -1189,7 +1195,7 @@ expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). {
     sqlite3ExprSetHeightAndFlags(pParse, A.pExpr);
   }else{
     sqlite3ExprListDelete(pParse->db, Y);
-    sqlite3ExprDelete(pParse->db, Z);
+    sql_expr_free(pParse->db, Z, false);
   }
 }
 %type case_exprlist {ExprList*}
@@ -1203,11 +1209,11 @@ case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). {
   A = sqlite3ExprListAppend(pParse,A, Z.pExpr);
 }
 %type case_else {Expr*}
-%destructor case_else {sqlite3ExprDelete(pParse->db, $$);}
+%destructor case_else {sql_expr_free(pParse->db, $$, false);}
 case_else(A) ::=  ELSE expr(X).         {A = X.pExpr;}
 case_else(A) ::=  .                     {A = 0;} 
 %type case_operand {Expr*}
-%destructor case_operand {sqlite3ExprDelete(pParse->db, $$);}
+%destructor case_operand {sql_expr_free(pParse->db, $$, false);}
 case_operand(A) ::= expr(X).            {A = X.pExpr; /*A-overwrites-X*/} 
 case_operand(A) ::= .                   {A = 0;} 
 
@@ -1377,7 +1383,7 @@ foreach_clause ::= .
 foreach_clause ::= FOR EACH ROW.
 
 %type when_clause {Expr*}
-%destructor when_clause {sqlite3ExprDelete(pParse->db, $$);}
+%destructor when_clause {sql_expr_free(pParse->db, $$, false);}
 when_clause(A) ::= .             { A = 0; }
 when_clause(A) ::= WHEN expr(X). { A = X.pExpr; }
 
modified   src/box/sql/resolve.c
@@ -115,7 +115,7 @@ resolveAlias(Parse * pParse,	/* Parsing context */
 	}
 	ExprSetProperty(pDup, EP_Alias);
 
-	/* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
+	/* Before calling sql_expr_free(), set the EP_Static flag. This
 	 * prevents ExprDelete() from deleting the Expr structure itself,
 	 * allowing it to be repopulated by the memcpy() on the following line.
 	 * The pExpr->u.zToken might point into memory that will be freed by the
@@ -123,7 +123,7 @@ resolveAlias(Parse * pParse,	/* Parsing context */
 	 * make a copy of the token before doing the sqlite3DbFree().
 	 */
 	ExprSetProperty(pExpr, EP_Static);
-	sqlite3ExprDelete(db, pExpr);
+	sql_expr_free(db, pExpr, false);
 	memcpy(pExpr, pDup, sizeof(*pExpr));
 	if (!ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken != 0) {
 		assert((pExpr->flags & (EP_Reduced | EP_TokenOnly)) == 0);
@@ -462,9 +462,9 @@ lookupName(Parse * pParse,	/* The parsing context */
 
 	/* Clean up and return
 	 */
-	sqlite3ExprDelete(db, pExpr->pLeft);
+	sql_expr_free(db, pExpr->pLeft, false);
 	pExpr->pLeft = 0;
-	sqlite3ExprDelete(db, pExpr->pRight);
+	sql_expr_free(db, pExpr->pRight, false);
 	pExpr->pRight = 0;
 	pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN);
  lookupname_end:
@@ -1030,7 +1030,7 @@ resolveCompoundOrderBy(Parse * pParse,	/* Parsing context.  Leave error messages
 						    resolveOrderByTermToExprList
 						    (pParse, pSelect, pDup);
 					}
-					sqlite3ExprDelete(db, pDup);
+					sql_expr_free(db, pDup, false);
 				}
 			}
 			if (iCol > 0) {
@@ -1052,7 +1052,7 @@ resolveCompoundOrderBy(Parse * pParse,	/* Parsing context.  Leave error messages
 					assert(pParent->pLeft == pE);
 					pParent->pLeft = pNew;
 				}
-				sqlite3ExprDelete(db, pE);
+				sql_expr_free(db, pE, false);
 				pItem->u.x.iOrderByCol = (u16) iCol;
 				pItem->done = 1;
 			} else {
modified   src/box/sql/select.c
@@ -94,12 +94,12 @@ clearSelect(sqlite3 * db, Select * p, int bFree)
 		Select *pPrior = p->pPrior;
 		sqlite3ExprListDelete(db, p->pEList);
 		sqlite3SrcListDelete(db, p->pSrc);
-		sqlite3ExprDelete(db, p->pWhere);
+		sql_expr_free(db, p->pWhere, false);
 		sqlite3ExprListDelete(db, p->pGroupBy);
-		sqlite3ExprDelete(db, p->pHaving);
+		sql_expr_free(db, p->pHaving, false);
 		sqlite3ExprListDelete(db, p->pOrderBy);
-		sqlite3ExprDelete(db, p->pLimit);
-		sqlite3ExprDelete(db, p->pOffset);
+		sql_expr_free(db, p->pLimit, false);
+		sql_expr_free(db, p->pOffset, false);
 		if (p->pWith)
 			sqlite3WithDelete(db, p->pWith);
 		if (bFree)
@@ -2669,7 +2669,7 @@ multiSelect(Parse * pParse,	/* Parsing context */
 							     pPrior->
 							     nSelectRow);
 				}
-				sqlite3ExprDelete(db, p->pLimit);
+				sql_expr_free(db, p->pLimit, false);
 				p->pLimit = pLimit;
 				p->pOffset = pOffset;
 				p->iLimit = 0;
@@ -2768,7 +2768,7 @@ multiSelect(Parse * pParse,	/* Parsing context */
 				p->pPrior = pPrior;
 				if (p->nSelectRow > pPrior->nSelectRow)
 					p->nSelectRow = pPrior->nSelectRow;
-				sqlite3ExprDelete(db, p->pLimit);
+				sql_expr_free(db, p->pLimit, false);
 				p->pLimit = pLimit;
 				p->pOffset = pOffset;
 
@@ -3297,9 +3297,9 @@ multiSelectOrderBy(Parse * pParse,	/* Parsing context */
 	} else {
 		regLimitA = regLimitB = 0;
 	}
-	sqlite3ExprDelete(db, p->pLimit);
+	sql_expr_free(db, p->pLimit, false);
 	p->pLimit = 0;
-	sqlite3ExprDelete(db, p->pOffset);
+	sql_expr_free(db, p->pOffset, false);
 	p->pOffset = 0;
 
 	regAddrA = ++pParse->nMem;
@@ -3514,7 +3514,7 @@ substExpr(Parse * pParse,	/* Report errors here */
 					    pExpr->iRightJoinTable;
 					pNew->flags |= EP_FromJoin;
 				}
-				sqlite3ExprDelete(db, pExpr);
+				sql_expr_free(db, pExpr, false);
 				pExpr = pNew;
 			}
 		}
@@ -6333,3 +6333,13 @@ sqlite3Select(Parse * pParse,		/* The parser context */
 #endif
 	return rc;
 }
+
+void
+sql_expr_extract_select(struct Parse *parser, struct Select *select)
+{
+	struct ExprList *expr_list = select->pEList;
+	assert(expr_list->nExpr == 1);
+	parser->parsed_expr = sqlite3ExprDup(parser->db,
+					     expr_list->a->pExpr,
+					     EXPRDUP_REDUCE);
+}
modified   src/box/sql/sqliteInt.h
@@ -63,10 +63,12 @@
  * asterisks and the comment text.
  */
 
-#include <box/field_def.h>
 #include <stdbool.h>
-#include <trivia/util.h>
+
+#include "box/field_def.h"
+#include "box/sql.h"
 #include "box/txn.h"
+#include "trivia/util.h"
 
 /*
  * These #defines should enable >2GB file support on POSIX if the
@@ -3007,6 +3009,10 @@ struct Parse {
 	With *pWithToFree;	/* Free this WITH object at the end of the parse */
 
 	bool initiateTTrans;	/* Initiate Tarantool transaction */
+	/** If set - do not emit byte code at all, just parse.  */
+	bool parse_only;
+	/** If parse_only is set to true, store parsed expression. */
+	struct Expr *parsed_expr;
 };
 
 /*
@@ -3526,7 +3532,6 @@ void sqlite3PExprAddSelect(Parse *, Expr *, Select *);
 Expr *sqlite3ExprAnd(sqlite3 *, Expr *, Expr *);
 Expr *sqlite3ExprFunction(Parse *, ExprList *, Token *);
 void sqlite3ExprAssignVarNumber(Parse *, Expr *, u32);
-void sqlite3ExprDelete(sqlite3 *, Expr *);
 ExprList *sqlite3ExprListAppend(Parse *, ExprList *, Expr *);
 ExprList *sqlite3ExprListAppendVector(Parse *, ExprList *, IdList *, Expr *);
 void sqlite3ExprListSetSortOrder(ExprList *, int);
modified   src/box/sql/tokenize.c
@@ -652,3 +652,29 @@ sqlite3RunParser(Parse * pParse, const char *zSql, char **pzErrMsg)
 	assert(nErr == 0 || pParse->rc != SQLITE_OK);
 	return nErr;
 }
+
+int
+sql_expr_compile(sqlite3 *db, const char *expr, struct Expr **result)
+{
+	const char *outer = "SELECT ";
+	int len = strlen(outer) + strlen(expr);
+	char *stmt = (char *) region_alloc(&fiber()->gc, len + 1);
+	if (stmt == NULL) {
+		diag_set(OutOfMemory, len + 1, "region_alloc", "stmt");
+		return -1;
+	}
+	sprintf(stmt, "%s%s", outer, expr);
+
+	struct Parse parser;
+	memset(&parser, 0, sizeof(parser));
+	parser.db = db;
+	parser.parse_only = true;
+	char *unused;
+	if (sqlite3RunParser(&parser, stmt, &unused) != SQLITE_OK) {
+		diag_set(ClientError, ER_SQL_EXECUTE, expr);
+		return -1;
+	}
+	*result = parser.parsed_expr;
+	sqlite3ParserReset(&parser);
+	return 0;
+}
modified   src/box/sql/trigger.c
@@ -52,7 +52,7 @@ sqlite3DeleteTriggerStep(sqlite3 * db, TriggerStep * pTriggerStep)
 		TriggerStep *pTmp = pTriggerStep;
 		pTriggerStep = pTriggerStep->pNext;
 
-		sqlite3ExprDelete(db, pTmp->pWhere);
+		sql_expr_free(db, pTmp->pWhere, false);
 		sqlite3ExprListDelete(db, pTmp->pExprList);
 		sqlite3SelectDelete(db, pTmp->pSelect);
 		sqlite3IdListDelete(db, pTmp->pIdList);
@@ -185,7 +185,7 @@ sqlite3BeginTrigger(Parse * pParse,	/* The parse context of the CREATE TRIGGER s
 	sqlite3DbFree(db, zName);
 	sqlite3SrcListDelete(db, pTableName);
 	sqlite3IdListDelete(db, pColumns);
-	sqlite3ExprDelete(db, pWhen);
+	sql_expr_free(db, pWhen, false);
 	if (!pParse->pNewTrigger) {
 		sqlite3DeleteTrigger(db, pTrigger);
 	} else {
@@ -447,7 +447,7 @@ sqlite3TriggerUpdateStep(sqlite3 * db,	/* The database connection */
 		pTriggerStep->orconf = orconf;
 	}
 	sqlite3ExprListDelete(db, pEList);
-	sqlite3ExprDelete(db, pWhere);
+	sql_expr_free(db, pWhere, false);
 	return pTriggerStep;
 }
 
@@ -470,7 +470,7 @@ sqlite3TriggerDeleteStep(sqlite3 * db,	/* Database connection */
 		    sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
 		pTriggerStep->orconf = ON_CONFLICT_ACTION_DEFAULT;
 	}
-	sqlite3ExprDelete(db, pWhere);
+	sql_expr_free(db, pWhere, false);
 	return pTriggerStep;
 }
 
@@ -485,7 +485,7 @@ sqlite3DeleteTrigger(sqlite3 * db, Trigger * pTrigger)
 	sqlite3DeleteTriggerStep(db, pTrigger->step_list);
 	sqlite3DbFree(db, pTrigger->zName);
 	sqlite3DbFree(db, pTrigger->table);
-	sqlite3ExprDelete(db, pTrigger->pWhen);
+	sql_expr_free(db, pTrigger->pWhen, false);
 	sqlite3IdListDelete(db, pTrigger->pColumns);
 	sqlite3DbFree(db, pTrigger);
 }
@@ -910,7 +910,7 @@ codeRowTrigger(Parse * pParse,	/* Current parse context */
 						   iEndTrigger,
 						   SQLITE_JUMPIFNULL);
 			}
-			sqlite3ExprDelete(db, pWhen);
+			sql_expr_free(db, pWhen, false);
 		}
 
 		/* Code the trigger program into the sub-vdbe. */
modified   src/box/sql/update.c
@@ -667,7 +667,7 @@ sqlite3Update(Parse * pParse,		/* The parser context */
 	sqlite3DbFree(db, aXRef);	/* Also frees aRegIdx[] and aToOpen[] */
 	sqlite3SrcListDelete(db, pTabList);
 	sqlite3ExprListDelete(db, pChanges);
-	sqlite3ExprDelete(db, pWhere);
+	sql_expr_free(db, pWhere, false);
 	return;
 }
 
modified   src/box/sql/wherecode.c
@@ -1830,7 +1830,7 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo,	/* Complete information about t
 			pLevel->iIdxCur = iCovCur;
 		if (pAndExpr) {
 			pAndExpr->pLeft = 0;
-			sqlite3ExprDelete(db, pAndExpr);
+			sql_expr_free(db, pAndExpr, false);
 		}
 		sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
 		sqlite3VdbeGoto(v, pLevel->addrBrk);
modified   src/box/sql/whereexpr.c
@@ -97,7 +97,7 @@ whereClauseInsert(WhereClause * pWC, Expr * p, u16 wtFlags)
 					 sizeof(pWC->a[0]) * pWC->nSlot * 2);
 		if (pWC->a == 0) {
 			if (wtFlags & TERM_DYNAMIC) {
-				sqlite3ExprDelete(db, p);
+				sql_expr_free(db, p, false);
 			}
 			pWC->a = pOld;
 			return 0;
@@ -1057,7 +1057,7 @@ exprAnalyze(SrcList * pSrc,	/* the FROM clause */
 				int idxNew;
 				pDup = sqlite3ExprDup(db, pExpr, 0);
 				if (db->mallocFailed) {
-					sqlite3ExprDelete(db, pDup);
+					sql_expr_free(db, pDup, false);
 					return;
 				}
 				idxNew =
@@ -1398,7 +1398,7 @@ sqlite3WhereClauseClear(WhereClause * pWC)
 	sqlite3 *db = pWC->pWInfo->pParse->db;
 	for (i = pWC->nTerm - 1, a = pWC->a; i >= 0; i--, a++) {
 		if (a->wtFlags & TERM_DYNAMIC) {
-			sqlite3ExprDelete(db, a->pExpr);
+			sql_expr_free(db, a->pExpr, false);
 		}
 		if (a->wtFlags & TERM_ORINFO) {
 			whereOrInfoDelete(db, a->u.pOrInfo);

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2018-04-03  6:29 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-29  6:42 [tarantool-patches] [PATCH 0/3] sql: move column's default value to Tarantool's core Kirill Yukhin
2018-03-29  6:42 ` [tarantool-patches] [PATCH 1/3] Add value field to _schema space Kirill Yukhin
2018-03-29  6:42 ` [tarantool-patches] [PATCH 2/3] sql: remove dead find DB functions Kirill Yukhin
2018-03-29  6:42 ` [tarantool-patches] [PATCH 3/3] sql: move default col values to Tarantool's core Kirill Yukhin
2018-03-29 14:00   ` [tarantool-patches] " v.shpilevoy
2018-03-31  3:55     ` Kirill Yukhin
2018-03-31  4:24       ` [tarantool-patches] [PATCH] " Kirill Yukhin
2018-04-03  6:29       ` [tarantool-patches] Re: [PATCH 3/3] " Kirill Yukhin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox