From f2debd8bf90daf07deb5d4e1d16bd89d3147b978 Mon Sep 17 00:00:00 2001
From: Kirill Yukhin <kyukhin@tarantool.org>
Date: Tue, 31 Jul 2018 13:47:30 +0300
Subject: [PATCH] sql: remove pragma schema_version

This pragma is dead and produces nothing else but segfault.
Along w/ this pragma, remove now dead opcodes which set/read
schema_version and all related routines.
Also, improve opcode generation script.

Part of #3541
---
 extra/mkkeywordhash.c   |   6 +-
 extra/mkopcodeh.sh      |  31 ++++++++--
 src/box/sql/alter.c     |   9 +--
 src/box/sql/build.c     |  33 +----------
 src/box/sql/insert.c    |   1 -
 src/box/sql/parse.y     |   2 -
 src/box/sql/pragma.c    | 126 ++++++----------------------------------
 src/box/sql/pragma.h    |  12 ----
 src/box/sql/prepare.c   |   6 --
 src/box/sql/resolve.c   |   1 -
 src/box/sql/select.c    |   1 -
 src/box/sql/sqliteInt.h |  18 ------
 src/box/sql/trigger.c   |   2 -
 src/box/sql/update.c    |   1 -
 src/box/sql/vdbe.c      |  43 --------------
 src/box/sql/vdbe.h      |  21 +------
 src/box/sql/vdbeaux.c   |  82 --------------------------
 17 files changed, 48 insertions(+), 347 deletions(-)

diff --git a/extra/mkkeywordhash.c b/extra/mkkeywordhash.c
index 705caf1ca7..0aaf8cd754 100644
--- a/extra/mkkeywordhash.c
+++ b/extra/mkkeywordhash.c
@@ -85,11 +85,7 @@ struct Keyword {
 #else
 #  define FKEY       0x00000200
 #endif
-#ifdef SQLITE_OMIT_PRAGMA
-#  define PRAGMA     0
-#else
-#  define PRAGMA     0x00000400
-#endif
+#define PRAGMA       0x00000400
 #ifdef SQLITE_OMIT_REINDEX
 #  define REINDEX    0
 #else
diff --git a/extra/mkopcodeh.sh b/extra/mkopcodeh.sh
index 63ad0d56a4..5f31f2b7d1 100755
--- a/extra/mkopcodeh.sh
+++ b/extra/mkopcodeh.sh
@@ -35,6 +35,7 @@ set -f   # disable pathname expansion
 
 currentOp=""
 nOp=0
+mxTk=-1
 newline="$(printf '\n')"
 IFS="$newline"
 while read line; do
@@ -106,6 +107,9 @@ while read line; do
                         eval "ARRAY_used_$val=1"
                         eval "ARRAY_sameas_$val=$sym"
                         eval "ARRAY_def_$val=$name"
+                        if [ $val -gt $mxTk ] ; then
+                            mxTk=$val
+                        fi
                     fi
                 ;;
                 jump) eval "ARRAY_jump_$name=1" ;;
@@ -219,9 +223,11 @@ while [ "$i" -lt "$nOp" ]; do
     fi
     i=$((i + 1))
 done
-max="$cnt"
+if [ $mxTk -lt $nOp ] ; then
+    mxTk=$nOp
+fi
 i=0
-while [ "$i" -lt "$nOp" ]; do
+while [ "$i" -le "$mxTk" ]; do
     eval "used=\${ARRAY_used_$i:-}"
     if [ -z "$used" ]; then
         eval "ARRAY_def_$i=OP_NotUsed_$i"
@@ -251,9 +257,19 @@ done
 # Generate the bitvectors:
 ARRAY_bv_0=0
 i=0
-while [ "$i" -le "$max" ]; do
+while [ "$i" -le "$mxTk" ]; do
+    eval "is_existing=\${ARRAY_def_$i:-}"
+    if [ ! -n "$is_existing" ] ; then
+        i=$((i + 1))
+        continue
+    fi
     eval "name=\$ARRAY_def_$i"
     x=0
+    eval "is_existing=\${ARRAY_jump_$name:-}"
+    if [ ! -n "$is_existing" ] ; then
+        i=$((i + 1))
+        continue
+    fi
     eval "jump=\$ARRAY_jump_$name"
     eval "in1=\$ARRAY_in1_$name"
     eval "in2=\$ARRAY_in2_$name"
@@ -283,11 +299,16 @@ printf '%s\n' "#define OPFLG_OUT2        0x10  /* out2:  P2 is an output */"
 printf '%s\n' "#define OPFLG_OUT3        0x20  /* out3:  P3 is an output */"
 printf '%s\n' "#define OPFLG_INITIALIZER {\\"
 i=0
-while [ "$i" -le "$max" ]; do
+while [ "$i" -le "$mxTk" ]; do
     if [ "$((i % 8))" -eq 0 ]; then
         printf '/* %3d */' "$i"
     fi
-    eval "bv=\$ARRAY_bv_$i"
+    eval "is_existing=\${ARRAY_bv_$i:-}"
+    if [ ! -n "$is_existing" ] ; then
+        bv=0
+    else
+        eval "bv=\$ARRAY_bv_$i"
+    fi
     printf ' 0x%02x,' "$bv"
     if [ "$((i % 8))" -eq 7 ]; then
         printf '%s\n' "\\"
diff --git a/src/box/sql/alter.c b/src/box/sql/alter.c
index 88fa81f7d0..91b6515ca1 100644
--- a/src/box/sql/alter.c
+++ b/src/box/sql/alter.c
@@ -111,10 +111,7 @@ sqlite3AlterRenameTable(Parse * pParse,	/* Parser context. */
 				pTab->def->name);
 		goto exit_rename_table;
 	}
-	/* Begin a transaction for database.
-	 * Then modify the schema cookie (since the ALTER TABLE modifies the
-	 * schema).
-	 */
+	/* Begin a transaction for database. */
 	v = sqlite3GetVdbe(pParse);
 	if (v == 0) {
 		goto exit_rename_table;
@@ -304,13 +301,11 @@ sqlite3AlterBeginAddColumn(Parse * pParse, SrcList * pSrc)
 	pNew->addColOffset = pTab->addColOffset;
 	pNew->nTabRef = 1;
 
-	/* Begin a transaction and increment the schema cookie.  */
+	/* Begin a transaction. */
 	sql_set_multi_write(pParse, false);
 	v = sqlite3GetVdbe(pParse);
 	if (!v)
 		goto exit_begin_add_column;
-	sqlite3ChangeCookie(pParse);
-
  exit_begin_add_column:
 	sqlite3SrcListDelete(db, pSrc);
 	return;
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 5772ee5076..d812eb9a5c 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -179,10 +179,8 @@ sqlite3LocateTable(Parse * pParse,	/* context in which to report errors */
 	if (p == NULL) {
 		const char *zMsg =
 		    flags & LOCATE_VIEW ? "no such view" : "no such table";
-		if ((flags & LOCATE_NOERR) == 0) {
+		if ((flags & LOCATE_NOERR) == 0)
 			sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
-			pParse->checkSchema = 1;
-		}
 	}
 
 	return p;
@@ -1086,33 +1084,6 @@ vdbe_emit_open_cursor(struct Parse *parse_context, int cursor, int index_id,
 	return sqlite3VdbeAddOp4(parse_context->pVdbe, OP_OpenWrite, cursor,
 				 index_id, 0, (void *) space, P4_SPACEPTR);
 }
-/*
- * Generate code that will increment the schema cookie.
- *
- * The schema cookie is used to determine when the schema for the
- * database changes.  After each schema change, the cookie value
- * changes.  When a process first reads the schema it records the
- * cookie.  Thereafter, whenever it goes to access the database,
- * it checks the cookie to make sure the schema has not changed
- * since it was last read.
- *
- * This plan is not completely bullet-proof.  It is possible for
- * the schema to change multiple times and for the cookie to be
- * set back to prior value.  But schema changes are infrequent
- * and the probability of hitting the same cookie value is only
- * 1 chance in 2^32.  So we're safe enough.
- *
- * IMPLEMENTATION-OF: R-34230-56049 SQLite automatically increments
- * the schema-version whenever the schema changes.
- */
-void
-sqlite3ChangeCookie(Parse * pParse)
-{
-	sqlite3 *db = pParse->db;
-	Vdbe *v = pParse->pVdbe;
-	sqlite3VdbeAddOp3(v, OP_SetCookie, 0, 0,
-			  db->pSchema->schema_cookie + 1);
-}
 
 /*
  * Measure the number of characters needed to output the given
@@ -1495,7 +1466,6 @@ parseTableSchemaRecord(Parse * pParse, int iSpaceId, char *zStmt)
 		makeIndexSchemaRecord(pParse, pIdx, iSpaceId, ++i, NULL);
 	}
 
-	sqlite3ChangeCookie(pParse);
 	sqlite3VdbeAddParseSchema2Op(v, iTop, pParse->nMem - iTop + 1);
 }
 
@@ -2891,7 +2861,6 @@ sql_create_index(struct Parse *parse, struct Token *token,
 		 * Reparse the schema. Code an OP_Expire
 		 * to invalidate all pre-compiled statements.
 		 */
-		sqlite3ChangeCookie(parse);
 		sqlite3VdbeAddParseSchema2Op(vdbe, first_schema_col, 4);
 		sqlite3VdbeAddOp0(vdbe, OP_Expire);
 	}
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 432e003c0b..edd0c31ec6 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -469,7 +469,6 @@ sqlite3Insert(Parse * pParse,	/* Parser context */
 				sqlite3ErrorMsg(pParse,
 						"table %S has no column named %s",
 						pTabList, 0, pColumn->a[i].zName);
-				pParse->checkSchema = 1;
 				goto insert_cleanup;
 			}
 			if (bit_test(used_columns, j)) {
diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y
index 0e50d21fb2..13ddf46165 100644
--- a/src/box/sql/parse.y
+++ b/src/box/sql/parse.y
@@ -1267,7 +1267,6 @@ cmd ::= DROP INDEX ifexists(E) fullname(X) ON nm(Y).   {
 
 ///////////////////////////// The PRAGMA command /////////////////////////////
 //
-%ifndef SQLITE_OMIT_PRAGMA
 cmd ::= PRAGMA nm(X).                        {
     sqlite3Pragma(pParse,&X,0,0,0);
 }
@@ -1296,7 +1295,6 @@ nmnum(A) ::= nm(A).
 nmnum(A) ::= ON(A).
 nmnum(A) ::= DELETE(A).
 nmnum(A) ::= DEFAULT(A).
-%endif SQLITE_OMIT_PRAGMA
 
 %token_class number INTEGER|FLOAT.
 plus_num(A) ::= PLUS number(X).       {A = X;}
diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c
index d427f78446..f3bc62f82e 100644
--- a/src/box/sql/pragma.c
+++ b/src/box/sql/pragma.c
@@ -119,8 +119,6 @@ sqlite3GetBoolean(const char *z, u8 dflt)
  * the rest of the file if PRAGMAs are omitted from the build.
  */
 
-#if !defined(SQLITE_OMIT_PRAGMA)
-
 /*
  * Set result column names for a pragma.
  */
@@ -813,112 +811,25 @@ sqlite3Pragma(Parse * pParse, Token * pId,	/* First part of [schema.]id field */
 			break;
 		}
 
-#ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX
-#define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100
-#endif
-
-#ifndef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
-		/* *   PRAGMA [schema.]schema_version *   PRAGMA
-		 * [schema.]schema_version = <integer> *
-		 *
-		 * PRAGMA [schema.]user_version *   PRAGMA
-		 * [schema.]user_version = <integer> *
-		 *
-		 * PRAGMA [schema.]freelist_count *
-		 *
-		 * PRAGMA [schema.]data_version *
-		 *
-		 * PRAGMA [schema.]application_id *   PRAGMA
-		 * [schema.]application_id = <integer> *
-		 *
-		 * The pragma's schema_version and user_version are used
-		 * to set or get * the value of the schema-version and
-		 * user-version, respectively. Both * the
-		 * schema-version and the user-version are 32-bit
-		 * signed integers * stored in the database header. *
-		 *
-		 * The schema-cookie is usually only manipulated
-		 * internally by SQLite. It * is incremented by SQLite
-		 * whenever the database schema is modified (by *
-		 * creating or dropping a table or index). The schema
-		 * version is used by * SQLite each time a query is
-		 * executed to ensure that the internal cache * of the
-		 * schema used when compiling the SQL query matches the
-		 * schema of * the database against which the compiled
-		 * query is actually executed. * Subverting this
-		 * mechanism by using "PRAGMA schema_version" to modify *
-		 * the schema-version is potentially dangerous and may
-		 * lead to program * crashes or database corruption.
-		 * Use with caution! *
-		 *
-		 * The user-version is not used internally by SQLite. It
-		 * may be used by * applications for any purpose.
-		 */
-	case PragTyp_HEADER_VALUE:{
-			int iCookie = pPragma->iArg;	/* Which cookie to read
-							 * or write
-							 */
-			if (zRight
-			    && (pPragma->mPragFlg & PragFlg_ReadOnly) == 0) {
-				/* Write the specified cookie value */
-				static const VdbeOpList setCookie[] = {
-					{OP_SetCookie, 0, 0, 0},	/* 1 */
-				};
-				VdbeOp *aOp;
-				sqlite3VdbeVerifyNoMallocRequired(v,
-								  ArraySize
-								  (setCookie));
-				aOp =
-				    sqlite3VdbeAddOpList(v,
-							 ArraySize(setCookie),
-							 setCookie, 0);
-				if (ONLY_IF_REALLOC_STRESS(aOp == 0))
-					break;
-				aOp[0].p1 = 0;
-				aOp[0].p2 = iCookie;
-				aOp[0].p3 = sqlite3Atoi(zRight);
-			} else {
-				/* Read the specified cookie value */
-				static const VdbeOpList readCookie[] = {
-					{OP_ReadCookie, 0, 1, 0},	/* 1 */
-					{OP_ResultRow, 1, 1, 0}
-				};
-				VdbeOp *aOp;
-				sqlite3VdbeVerifyNoMallocRequired(v,
-								  ArraySize
-								  (readCookie));
-				aOp =
-				    sqlite3VdbeAddOpList(v,
-							 ArraySize(readCookie),
-							 readCookie, 0);
-				if (ONLY_IF_REALLOC_STRESS(aOp == 0))
-					break;
-				aOp[0].p1 = 0;
-				aOp[1].p1 = 0;
-				aOp[1].p3 = iCookie;
-				sqlite3VdbeReusable(v);
-			}
-			break;
-		}
-		case PragTyp_DEFAULT_ENGINE: {
-			if (sql_default_engine_set(zRight) != 0) {
-				pParse->rc = SQL_TARANTOOL_ERROR;
-				pParse->nErr++;
-				goto pragma_out;
-			}
-			sqlite3VdbeAddOp0(v, OP_Expire);
-			break;
+	case PragTyp_DEFAULT_ENGINE: {
+		if (sql_default_engine_set(zRight) != 0) {
+			pParse->rc = SQL_TARANTOOL_ERROR;
+			pParse->nErr++;
+			goto pragma_out;
 		}
+		sqlite3VdbeAddOp0(v, OP_Expire);
+		break;
+	}
 
-		/* *   PRAGMA busy_timeout *   PRAGMA busy_timeout = N *
-		 *
-		 * Call sqlite3_busy_timeout(db, N).  Return the current
-		 * timeout value * if one is set.  If no busy handler
-		 * or a different busy handler is set * then 0 is
-		 * returned.  Setting the busy_timeout to 0 or negative *
-		 * disables the timeout.
-		 */
-		/* case PragTyp_BUSY_TIMEOUT */
+	/* *   PRAGMA busy_timeout *   PRAGMA busy_timeout = N *
+	 *
+	 * Call sqlite3_busy_timeout(db, N).  Return the current
+	 * timeout value * if one is set.  If no busy handler
+	 * or a different busy handler is set * then 0 is
+	 * returned.  Setting the busy_timeout to 0 or negative *
+	 * disables the timeout.
+	 */
+	/* case PragTyp_BUSY_TIMEOUT */
 	default:{
 			assert(pPragma->ePragTyp == PragTyp_BUSY_TIMEOUT);
 			if (zRight) {
@@ -944,6 +855,3 @@ sqlite3Pragma(Parse * pParse, Token * pId,	/* First part of [schema.]id field */
 	sqlite3DbFree(db, zRight);
 	sqlite3DbFree(db, zTable);
 }
-
-#endif				/* SQLITE_OMIT_PRAGMA */
-#endif
diff --git a/src/box/sql/pragma.h b/src/box/sql/pragma.h
index 795c98c6d2..67717496cf 100644
--- a/src/box/sql/pragma.h
+++ b/src/box/sql/pragma.h
@@ -5,7 +5,6 @@
  */
 
 /* The various pragma types */
-#define PragTyp_HEADER_VALUE                   0
 #define PragTyp_BUSY_TIMEOUT                   1
 #define PragTyp_CASE_SENSITIVE_LIKE            2
 #define PragTyp_COLLATION_LIST                 3
@@ -23,7 +22,6 @@
 #define PragFlg_NeedSchema 0x01	/* Force schema load before running */
 #define PragFlg_NoColumns  0x02	/* OP_ResultRow called with zero columns */
 #define PragFlg_NoColumns1 0x04	/* zero columns if RHS argument is present */
-#define PragFlg_ReadOnly   0x08	/* Read-only HEADER_VALUE */
 #define PragFlg_Result0    0x10	/* Acts as query when no argument */
 #define PragFlg_Result1    0x20	/* Acts as query when has one argument */
 #define PragFlg_SchemaOpt  0x40	/* Schema restricts name search if present */
@@ -224,16 +222,6 @@ static const PragmaName aPragmaName[] = {
 	 /* ColNames:  */ 0, 0,
 	 /* iArg:      */ SQLITE_ReverseOrder},
 #endif
-#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
-	{ /* zName:     */ "schema_version",
-	 /* ePragTyp:  */ PragTyp_HEADER_VALUE,
-	 /* ePragFlg:  */ PragFlg_NoColumns1 | PragFlg_Result0,
-	 /* ColNames:  */ 0, 0,
-	  /* Tarantool: need to take schema version from
-	   * backend.
-	   */
-	 /* iArg:      */ 0},
-#endif
 #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) && defined(SQLITE_ENABLE_SELECTTRACE)
 	{ /* zName:     */ "select_trace",
 	/* ePragTyp:  */ PragTyp_FLAG,
diff --git a/src/box/sql/prepare.c b/src/box/sql/prepare.c
index 14239c489b..ed6d59b5a0 100644
--- a/src/box/sql/prepare.c
+++ b/src/box/sql/prepare.c
@@ -156,12 +156,6 @@ sqlite3InitDatabase(sqlite3 * db)
 		rc = init.rc;
 		goto error_out;
 	}
-
-	/* Tarantool: schema_cookie is not used so far, but
-	 * might be used in future. Set it to dummy value.
-	 */
-	db->pSchema->schema_cookie = 0;
-
 	/* Read the schema information out of the schema tables
 	 */
 	assert(db->init.busy);
diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c
index a4767f2693..280ecd9f76 100644
--- a/src/box/sql/resolve.c
+++ b/src/box/sql/resolve.c
@@ -434,7 +434,6 @@ lookupName(Parse * pParse,	/* The parsing context */
 		} else {
 			sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
 		}
-		pParse->checkSchema = 1;
 		pTopNC->nErr++;
 	}
 
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index d060a4696b..d824b8b974 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -4385,7 +4385,6 @@ sqlite3IndexedByLookup(Parse * pParse, struct SrcList_item *pFrom)
 		if (!pIdx) {
 			sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy,
 					0);
-			pParse->checkSchema = 1;
 			return SQLITE_ERROR;
 		}
 		pFrom->pIBIndex = pIdx;
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index b595984c97..468b6c639c 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -284,21 +284,6 @@ void sqlite3Coverage(int);
 #define NEVER(X)       (X)
 #endif
 
-/*
- * Some malloc failures are only possible if SQLITE_TEST_REALLOC_STRESS is
- * defined.  We need to defend against those failures when testing with
- * SQLITE_TEST_REALLOC_STRESS, but we don't want the unreachable branches
- * during a normal build.  The following macro can be used to disable tests
- * that are always false except when SQLITE_TEST_REALLOC_STRESS is set.
- */
-#if defined(SQLITE_TEST_REALLOC_STRESS)
-#define ONLY_IF_REALLOC_STRESS(X)  (X)
-#elif !defined(NDEBUG)
-#define ONLY_IF_REALLOC_STRESS(X)  ((X)?(assert(0),1):0)
-#else
-#define ONLY_IF_REALLOC_STRESS(X)  (0)
-#endif
-
 /*
  * Is the sqlite3ErrName() function needed in the build?  Currently,
  * it is needed by several "test*.c" files (which are
@@ -1522,7 +1507,6 @@ typedef int VList;
  * An instance of the following structure stores a database schema.
  */
 struct Schema {
-	int schema_cookie;      /* Database schema version number for this file */
 	Hash tblHash;		/* All tables indexed by name */
 	Hash fkeyHash;		/* All foreign keys by referenced table name */
 };
@@ -2840,7 +2824,6 @@ struct Parse {
 	Vdbe *pVdbe;		/* An engine for executing database bytecode */
 	int rc;			/* Return code from execution */
 	u8 colNamesSet;		/* TRUE after OP_ColumnName has been issued to pVdbe */
-	u8 checkSchema;		/* Causes schema cookie check after an error */
 	u8 nTempReg;		/* Number of temporary registers in aTempReg[] */
 	u8 isMultiWrite;	/* True if statement may modify/insert multiple rows */
 	u8 mayAbort;		/* True if statement may throw an ABORT exception */
@@ -4017,7 +4000,6 @@ void sqlite3RegisterDateTimeFunctions(void);
 void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3 *);
 int sqlite3SafetyCheckOk(sqlite3 *);
 int sqlite3SafetyCheckSickOrOk(sqlite3 *);
-void sqlite3ChangeCookie(Parse *);
 
 /**
  * Evaluate a view and store its result in an ephemeral table.
diff --git a/src/box/sql/trigger.c b/src/box/sql/trigger.c
index ec0bc98b80..46f7c31e3f 100644
--- a/src/box/sql/trigger.c
+++ b/src/box/sql/trigger.c
@@ -260,7 +260,6 @@ sql_trigger_finish(struct Parse *parse, struct TriggerStep *step_list,
 		sqlite3VdbeAddOp1(v, OP_Close, cursor);
 
 		sql_set_multi_write(parse, false);
-		sqlite3ChangeCookie(parse);
 	} else {
 		parse->parsed_ast.trigger = trigger;
 		parse->parsed_ast_type = AST_TYPE_TRIGGER;
@@ -450,7 +449,6 @@ vdbe_code_drop_trigger(struct Parse *parser, const char *trigger_name,
 			  record_to_delete);
 	if (account_changes)
 		sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE);
-	sqlite3ChangeCookie(parser);
 }
 
 void
diff --git a/src/box/sql/update.c b/src/box/sql/update.c
index 489a4563a5..a2f6c7387d 100644
--- a/src/box/sql/update.c
+++ b/src/box/sql/update.c
@@ -217,7 +217,6 @@ sqlite3Update(Parse * pParse,		/* The parser context */
 		if (j >= (int)def->field_count) {
 			sqlite3ErrorMsg(pParse, "no such column: %s",
 					pChanges->a[i].zName);
-			pParse->checkSchema = 1;
 			goto update_cleanup;
 		}
 	}
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 2144d95737..ca89908caa 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -3076,49 +3076,6 @@ case OP_TTransaction: {
 	break;
 }
 
-/* Opcode: ReadCookie P1 P2 P3 * *
- *
- * Read cookie number P3 from database P1 and write it into register P2.
- * P3==1 is the schema version.  P3==2 is the database format.
- * P3==3 is the recommended pager cache size, and so forth.  P1==0 is
- * the main database file and P1==1 is the database file used to store
- * temporary tables.
- *
- * There must be a read-lock on the database (either a transaction
- * must be started or there must be an open cursor) before
- * executing this instruction.
- */
-case OP_ReadCookie: {               /* out2 */
-	pOut = out2Prerelease(p, pOp);
-	pOut->u.i = 0;
-	break;
-}
-
-/* Opcode: SetCookie P1 P2 P3 * *
- *
- * Write the integer value P3 into the schema version.
- * P2==3 is the recommended pager cache
- * size, and so forth.  P1==0 is the main database file and P1==1 is the
- * database file used to store temporary tables.
- *
- * A transaction must be started before executing this opcode.
- */
-case OP_SetCookie: {
-	assert(pOp->p1==0);
-	/* See note about index shifting on OP_ReadCookie */
-	/* When the schema cookie changes, record the new cookie internally */
-	user_session->sql_flags |= SQLITE_InternChanges;
-	if (pOp->p1==1) {
-		/* Invalidate all prepared statements whenever the TEMP database
-		 * schema is changed.  Ticket #1644
-		 */
-		sqlite3ExpirePreparedStatements(db);
-		p->expired = 0;
-	}
-	if (rc) goto abort_due_to_error;
-	break;
-}
-
 /* Opcode: OpenRead P1 P2 P3 P4 P5
  * Synopsis: index id = P2, space ptr = P4
  *
diff --git a/src/box/sql/vdbe.h b/src/box/sql/vdbe.h
index cfcc2624a0..2987d7ab0b 100644
--- a/src/box/sql/vdbe.h
+++ b/src/box/sql/vdbe.h
@@ -111,18 +111,6 @@ struct SubProgram {
 	SubProgram *pNext;	/* Next sub-program already visited */
 };
 
-/*
- * A smaller version of VdbeOp used for the VdbeAddOpList() function because
- * it takes up less space.
- */
-struct VdbeOpList {
-	u8 opcode;		/* What operation to perform */
-	signed char p1;		/* First operand */
-	signed char p2;		/* Second parameter (often the jump destination) */
-	signed char p3;		/* Third parameter */
-};
-typedef struct VdbeOpList VdbeOpList;
-
 /*
  * Allowed values of VdbeOp.p4type
  */
@@ -173,9 +161,7 @@ typedef struct VdbeOpList VdbeOpList;
 
 /*
  * The following macro converts a relative address in the p2 field
- * of a VdbeOp structure into a negative number so that
- * sqlite3VdbeAddOpList() knows that the address is relative.  Calling
- * the macro again restores the address.
+ * of a VdbeOp structure into a negative number.
  */
 #define ADDR(X)  (-1-(X))
 
@@ -225,14 +211,10 @@ int sqlite3VdbeAddOp4Dup8(Vdbe *, int, int, int, int, const u8 *, int);
 int sqlite3VdbeAddOp4Int(Vdbe *, int, int, int, int, int);
 void sqlite3VdbeEndCoroutine(Vdbe *, int);
 #if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
-void sqlite3VdbeVerifyNoMallocRequired(Vdbe * p, int N);
 void sqlite3VdbeVerifyNoResultRow(Vdbe * p);
 #else
-#define sqlite3VdbeVerifyNoMallocRequired(A,B)
 #define sqlite3VdbeVerifyNoResultRow(A)
 #endif
-VdbeOp *sqlite3VdbeAddOpList(Vdbe *, int nOp, VdbeOpList const *aOp,
-			     int iLineno);
 void sqlite3VdbeAddParseSchema2Op(Vdbe * p, int, int);
 void sqlite3VdbeChangeOpcode(Vdbe *, u32 addr, u8);
 void sqlite3VdbeChangeP1(Vdbe *, u32 addr, int P1);
@@ -257,7 +239,6 @@ sql_vdbe_set_p4_key_def(struct Parse *parse, struct Index *index);
 VdbeOp *sqlite3VdbeGetOp(Vdbe *, int);
 int sqlite3VdbeMakeLabel(Vdbe *);
 void sqlite3VdbeRunOnlyOnce(Vdbe *);
-void sqlite3VdbeReusable(Vdbe *);
 void sqlite3VdbeDelete(Vdbe *);
 void sqlite3VdbeClearObject(sqlite3 *, Vdbe *);
 void sqlite3VdbeMakeReady(Vdbe *, Parse *);
diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c
index d6ff51cc38..353b21a96c 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -505,15 +505,6 @@ sqlite3VdbeRunOnlyOnce(Vdbe * p)
 	p->runOnlyOnce = 1;
 }
 
-/*
- * Mark the VDBE as one that can only be run multiple times.
- */
-void
-sqlite3VdbeReusable(Vdbe * p)
-{
-	p->runOnlyOnce = 0;
-}
-
 #ifdef SQLITE_DEBUG		/* sqlite3AssertMayAbort() logic */
 
 /*
@@ -722,22 +713,6 @@ sqlite3VdbeCurrentAddr(Vdbe * p)
 	return p->nOp;
 }
 
-/*
- * Verify that at least N opcode slots are available in p without
- * having to malloc for more space (except when compiled using
- * SQLITE_TEST_REALLOC_STRESS).  This interface is used during testing
- * to verify that certain calls to sqlite3VdbeAddOpList() can never
- * fail due to a OOM fault and hence that the return value from
- * sqlite3VdbeAddOpList() will always be non-NULL.
- */
-#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
-void
-sqlite3VdbeVerifyNoMallocRequired(Vdbe * p, int N)
-{
-	assert(p->nOp + N <= p->pParse->nOpAlloc);
-}
-#endif
-
 /*
  * Verify that the VM passed as the only argument does not contain
  * an OP_ResultRow opcode. Fail an assert() if it does. This is used
@@ -779,60 +754,6 @@ sqlite3VdbeTakeOpArray(Vdbe * p, int *pnOp, int *pnMaxArg)
 	return aOp;
 }
 
-/*
- * Add a whole list of operations to the operation stack.  Return a
- * pointer to the first operation inserted.
- *
- * Non-zero P2 arguments to jump instructions are automatically adjusted
- * so that the jump target is relative to the first operation inserted.
- */
-VdbeOp *
-sqlite3VdbeAddOpList(Vdbe * p,	/* Add opcodes to the prepared statement */
-		     int nOp,	/* Number of opcodes to add */
-		     VdbeOpList const *aOp,	/* The opcodes to be added */
-		     int iLineno)	/* Source-file line number of first opcode */
-{
-	int i;
-	struct session MAYBE_UNUSED *user_session;
-	user_session = current_session();
-	VdbeOp *pOut, *pFirst;
-	assert(nOp > 0);
-	assert(p->magic == VDBE_MAGIC_INIT);
-	if (p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p, nOp)) {
-		return 0;
-	}
-	pFirst = pOut = &p->aOp[p->nOp];
-	for (i = 0; i < nOp; i++, aOp++, pOut++) {
-		pOut->opcode = aOp->opcode;
-		pOut->p1 = aOp->p1;
-		pOut->p2 = aOp->p2;
-		assert(aOp->p2 >= 0);
-		if ((sqlite3OpcodeProperty[aOp->opcode] & OPFLG_JUMP) != 0
-		    && aOp->p2 > 0) {
-			pOut->p2 += p->nOp;
-		}
-		pOut->p3 = aOp->p3;
-		pOut->p4type = P4_NOTUSED;
-		pOut->p4.p = 0;
-		pOut->p5 = 0;
-#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
-		pOut->zComment = 0;
-#endif
-#ifdef SQLITE_VDBE_COVERAGE
-		pOut->iSrcLine = iLineno + i;
-#else
-		(void)iLineno;
-#endif
-#ifdef SQLITE_DEBUG
-		if (user_session->sql_flags & SQLITE_VdbeAddopTrace) {
-			sqlite3VdbePrintOp(0, i + p->nOp, &p->aOp[i + p->nOp]);
-		}
-#endif
-	}
-	p->nOp += nOp;
-	return pFirst;
-}
-
 #if defined(SQLITE_ENABLE_STMT_SCANSTATUS)
 /*
  * Add an entry to the array of counters managed by sqlite3_stmt_scanstatus().
@@ -1039,9 +960,6 @@ sqlite3VdbeDeletePriorOpcode(Vdbe * p, u8 op)
 
 /*
  * Change the value of the P4 operand for a specific instruction.
- * This routine is useful when a large program is loaded from a
- * static array using sqlite3VdbeAddOpList but we want to make a
- * few minor changes to the program.
  *
  * If n>=0 then the P4 operand is dynamic, meaning that a copy of
  * the string is made into memory obtained from sqlite3_malloc().
-- 
GitLab