[tarantool-patches] [PATCH] sql: move default col values to Tarantool's core

Kirill Yukhin kyukhin at tarantool.org
Sat Mar 31 07:24:02 MSK 2018


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





More information about the Tarantool-patches mailing list