[tarantool-patches] Re: [PATCH v3 2/4] sql: Remove zName and nColumn from SQL.
Kirill Shcherbatov
kshcherbatov at tarantool.org
Wed Apr 25 20:10:02 MSK 2018
I've included some extra changes in this commit. Fixed.
---
src/box/sql/build.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index c712b46..d4624eb 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -854,21 +854,17 @@ sqlite3AddDefaultValue(Parse * pParse, ExprSpan * pSpan)
"default value of column [%s] is not constant",
p->def->fields[p->def->field_count - 1].name);
} else {
- assert(p->def != NULL);
struct field_def *field =
&p->def->fields[p->def->field_count - 1];
- struct region *region = &fiber()->gc;
- uint32_t default_length = (int)(pSpan->zEnd - pSpan->zStart);
- field->default_value = region_alloc(region,
- default_length + 1);
+ field->default_value =
+ sqlite3DbStrNDup(db,
+ (char *)pSpan->zStart,
+ (int)(pSpan->zEnd - pSpan->zStart));
if (field->default_value == NULL) {
pParse->rc = SQLITE_NOMEM_BKPT;
pParse->nErr++;
return;
}
- strncpy(field->default_value, (char *)pSpan->zStart,
- default_length);
- field->default_value[default_length] = '\0';
}
}
sql_expr_free(db, pSpan->pExpr, false);
--
2.7.4
On 25.04.2018 19:52, Kirill Shcherbatov wrote:
> 1. Removed zName from SQL Column.
> 2. Removed zColumns from SQL Table.
> 3. Refactored Parser to use def_expression directly.
> 4. Introduced sql_table_def_rebuild intended for collect
> fragmented with sql_field_retrieve space_def into memory
> located in one allocation.
>
> Needed for #3272.
> ---
> src/box/space_def.c | 29 ++++----
> src/box/sql.c | 61 +++++++++++++---
> src/box/sql.h | 23 ++++++
> src/box/sql/alter.c | 32 ++++++---
> src/box/sql/analyze.c | 5 +-
> src/box/sql/build.c | 181 ++++++++++++++++++++++--------------------------
> src/box/sql/delete.c | 6 +-
> src/box/sql/expr.c | 11 +--
> src/box/sql/fkey.c | 20 +++---
> src/box/sql/insert.c | 55 ++++++++-------
> src/box/sql/pragma.c | 24 ++++---
> src/box/sql/resolve.c | 16 +++--
> src/box/sql/select.c | 92 ++++++++++++------------
> src/box/sql/sqliteInt.h | 4 +-
> src/box/sql/update.c | 29 ++++----
> src/box/sql/where.c | 6 +-
> src/box/sql/wherecode.c | 2 +-
> src/box/sql/whereexpr.c | 4 +-
> 18 files changed, 338 insertions(+), 262 deletions(-)
>
> diff --git a/src/box/space_def.c b/src/box/space_def.c
> index 22bd3ca..77c0e02 100644
> --- a/src/box/space_def.c
> +++ b/src/box/space_def.c
> @@ -70,11 +70,12 @@ space_def_sizeof(uint32_t name_len, const struct field_def *fields,
> for (uint32_t i = 0; i < field_count; ++i) {
> field_strs_size += strlen(fields[i].name) + 1;
> if (fields[i].default_value != NULL) {
> - assert(fields[i].default_value_expr != NULL);
> int len = strlen(fields[i].default_value);
> field_strs_size += len + 1;
> - struct Expr *e = fields[i].default_value_expr;
> - def_exprs_size += sql_expr_sizeof(e, 0);
> + if (fields[i].default_value_expr != NULL) {
> + struct Expr *e = fields[i].default_value_expr;
> + def_exprs_size += sql_expr_sizeof(e, 0);
> + }
> }
> }
>
> @@ -116,12 +117,13 @@ space_def_dup(const struct space_def *src)
> if (src->fields[i].default_value != NULL) {
> ret->fields[i].default_value = strs_pos;
> strs_pos += strlen(strs_pos) + 1;
> -
> - struct Expr *e =
> - src->fields[i].default_value_expr;
> - assert(e != NULL);
> + }
> + struct Expr *e =
> + src->fields[i].default_value_expr;
> + if (e != NULL) {
> char *expr_pos_old = expr_pos;
> - e = sql_expr_dup(sql_get(), e, 0, &expr_pos);
> + e = sql_expr_dup(sql_get(), e, 0,
> + &expr_pos);
> assert(e != NULL);
> /* Note: due to SQL legacy
> * duplicactor pointer is not
> @@ -201,12 +203,13 @@ space_def_new(uint32_t id, uint32_t uid, uint32_t exact_field_count,
> fields[i].default_value, len);
> def->fields[i].default_value[len] = 0;
> strs_pos += len + 1;
> -
> - struct Expr *e =
> - fields[i].default_value_expr;
> - assert(e != NULL);
> + }
> + struct Expr *e =
> + fields[i].default_value_expr;
> + if (e != NULL) {
> char *expr_pos_old = expr_pos;
> - e = sql_expr_dup(sql_get(), e, 0, &expr_pos);
> + e = sql_expr_dup(sql_get(), e, 0,
> + &expr_pos);
> assert(e != NULL);
> /* Note: due to SQL legacy
> * duplicactor pointer is
> diff --git a/src/box/sql.c b/src/box/sql.c
> index 166bb71..38aeac6 100644
> --- a/src/box/sql.c
> +++ b/src/box/sql.c
> @@ -1433,7 +1433,7 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
> struct SqliteIndex *pk_idx = sqlite3PrimaryKeyIndex(pTable);
> int pk_forced_int = -1;
> char *base = buf, *p;
> - int i, n = pTable->nCol;
> + int i, n = pTable->def->field_count;
>
> p = enc->encode_array(base, n);
>
> @@ -1449,15 +1449,15 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
> const char *t;
> struct coll *coll = aCol[i].coll;
> struct field_def *field = &pTable->def->fields[i];
> - struct Expr *def = field->default_value_expr;
> + const char *zToken = field->default_value;
> int base_len = 4;
> if (coll != NULL)
> base_len += 1;
> - if (def != NULL)
> + if (zToken != 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, field->name, strlen(field->name));
> p = enc->encode_str(p, "type", 4);
> if (i == pk_forced_int) {
> t = "integer";
> @@ -1477,11 +1477,9 @@ 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));
> + if (zToken != NULL) {
> + p = enc->encode_str(p, "default", strlen("default"));
> + p = enc->encode_str(p, zToken, strlen(zToken));
> }
> }
> return (int)(p - base);
> @@ -1681,3 +1679,48 @@ space_column_default_expr(uint32_t space_id, uint32_t fieldno)
>
> return space->def->fields[fieldno].default_value_expr;
> }
> +
> +Table *
> +sql_ephemeral_table_new(Parse *parser)
> +{
> + sqlite3 *db = parser->db;
> + struct space_def *def = NULL;
> + Table *table = sqlite3DbMallocZero(db, sizeof(Table));
> + if (table != NULL) {
> + def = space_def_new(0, 0, 0, NULL, 0, NULL, 0,
> + &space_opts_default, NULL, 0);
> + }
> + if (def == NULL) {
> + sqlite3DbFree(db, table);
> + parser->rc = SQLITE_NOMEM_BKPT;
> + parser->nErr++;
> + return NULL;
> + }
> + table->def = def;
> + return table;
> +}
> +
> +int
> +sql_table_def_rebuild(struct sqlite3 *db, struct Table *pTable)
> +{
> + struct space_def *old_def = pTable->def;
> + struct space_def *new_def = NULL;
> + new_def = space_def_new(old_def->id, old_def->uid,
> + old_def->field_count, old_def->name,
> + strlen(old_def->name), old_def->engine_name,
> + strlen(old_def->engine_name), &old_def->opts,
> + old_def->fields, old_def->field_count);
> + if (new_def == NULL) {
> + sqlite3OomFault(db);
> + return -1;
> + }
> + struct field_def *fields = old_def->fields;
> + for (uint32_t i = 0; i < old_def->field_count; ++i) {
> + sqlite3DbFree(db, fields[i].default_value);
> + sqlite3DbFree(db, fields[i].name);
> + }
> + space_def_delete(old_def);
> + sqlite3DbFree(db, fields);
> + pTable->def = new_def;
> + return 0;
> +}
> diff --git a/src/box/sql.h b/src/box/sql.h
> index db92d80..9fb3ad1 100644
> --- a/src/box/sql.h
> +++ b/src/box/sql.h
> @@ -65,6 +65,7 @@ sql_get();
> struct Expr;
> struct Parse;
> struct Select;
> +struct Table;
>
> /**
> * Perform parsing of provided expression. This is done by
> @@ -143,6 +144,28 @@ sql_expr_dup(struct sqlite3 *db, struct Expr *p, int flags, char **buffer);
> void
> sql_expr_free(struct sqlite3 *db, struct Expr *expr, bool extern_alloc);
>
> +/**
> + * Create and initialize a new ephemeric SQL Table object.
> + * @param pParse SQL Parser object.
> + * @param zName Table to create name.
> + * @retval NULL on memory allocation error, Parser state changed.
> + * @retval not NULL on success.
> + */
> +struct Table *
> +sql_ephemeral_table_new(struct Parse *parser);
> +
> +/**
> + * Rebuild struct def in Table with memory allocated on a single
> + * malloc. Fields and strings are expected to be allocated with
> + * sqlite3DbMalloc.
> + * @param db The database connection.
> + * @param pTable The Table with fragmented def to rebuild.
> + * @retval 1 on memory allocation error
> + * @retval 0 on success
> + */
> +int
> +sql_table_def_rebuild(struct sqlite3 *db, struct Table *table);
> +
> #if defined(__cplusplus)
> } /* extern "C" { */
> #endif
> diff --git a/src/box/sql/alter.c b/src/box/sql/alter.c
> index 24f0965..bedf602 100644
> --- a/src/box/sql/alter.c
> +++ b/src/box/sql/alter.c
> @@ -144,6 +144,9 @@ sqlite3AlterRenameTable(Parse * pParse, /* Parser context. */
> void
> sqlite3AlterFinishAddColumn(Parse * pParse, Token * pColDef)
> {
> + /* This function is not implemented yet #3075. */
> + assert(false);
> +
> Table *pNew; /* Copy of pParse->pNewTable */
> Table *pTab; /* Table being altered */
> const char *zTab; /* Table name */
> @@ -161,10 +164,10 @@ sqlite3AlterFinishAddColumn(Parse * pParse, Token * pColDef)
> assert(pNew);
>
> zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */
> - pCol = &pNew->aCol[pNew->nCol - 1];
> + pCol = &pNew->aCol[pNew->def->field_count - 1];
> assert(pNew->def != NULL);
> pDflt = space_column_default_expr(SQLITE_PAGENO_TO_SPACEID(pNew->tnum),
> - pNew->nCol - 1);
> + pNew->def->field_count - 1);
> pTab = sqlite3HashFind(&db->pSchema->tblHash, zTab);;
> assert(pTab);
>
> @@ -248,10 +251,13 @@ sqlite3AlterFinishAddColumn(Parse * pParse, Token * pColDef)
> void
> sqlite3AlterBeginAddColumn(Parse * pParse, SrcList * pSrc)
> {
> + /* This function is not implemented yet #3075. */
> + assert(false);
> +
> Table *pNew;
> Table *pTab;
> Vdbe *v;
> - int i;
> + uint32_t i;
> int nAlloc;
> sqlite3 *db = pParse->db;
>
> @@ -281,13 +287,17 @@ sqlite3AlterBeginAddColumn(Parse * pParse, SrcList * pSrc)
> pNew = (Table *) sqlite3DbMallocZero(db, sizeof(Table));
> if (!pNew)
> goto exit_begin_add_column;
> + pNew->def = space_def_dup(pTab->def);
> + if (pNew->def == NULL) {
> + sqlite3DbFree(db, pNew);
> + goto exit_begin_add_column;
> + }
> pParse->pNewTable = pNew;
> pNew->nTabRef = 1;
> - pNew->nCol = pTab->nCol;
> - assert(pNew->nCol > 0);
> - nAlloc = (((pNew->nCol - 1) / 8) * 8) + 8;
> - assert(nAlloc >= pNew->nCol && nAlloc % 8 == 0
> - && nAlloc - pNew->nCol < 8);
> + assert(pNew->def->field_count > 0);
> + nAlloc = (((pNew->def->field_count - 1) / 8) * 8) + 8;
> + assert((uint32_t)nAlloc >= pNew->def->field_count && nAlloc % 8 == 0
> + && nAlloc - pNew->def->field_count < 8);
> pNew->aCol =
> (Column *) sqlite3DbMallocZero(db, sizeof(Column) * nAlloc);
> pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName);
> @@ -295,10 +305,10 @@ sqlite3AlterBeginAddColumn(Parse * pParse, SrcList * pSrc)
> assert(db->mallocFailed);
> goto exit_begin_add_column;
> }
> - memcpy(pNew->aCol, pTab->aCol, sizeof(Column) * pNew->nCol);
> - for (i = 0; i < pNew->nCol; i++) {
> + memcpy(pNew->aCol, pTab->aCol, sizeof(Column) * pNew->def->field_count);
> + for (i = 0; i < pNew->def->field_count; i++) {
> Column *pCol = &pNew->aCol[i];
> - pCol->zName = sqlite3DbStrDup(db, pCol->zName);
> + /* FIXME: pCol->zName = sqlite3DbStrDup(db, pCol->zName); */
> pCol->coll = NULL;
> }
> pNew->pSchema = db->pSchema;
> diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c
> index f0054c5..a0ad511 100644
> --- a/src/box/sql/analyze.c
> +++ b/src/box/sql/analyze.c
> @@ -1023,9 +1023,10 @@ analyzeOneTable(Parse * pParse, /* Parser context */
> regKeyStat = sqlite3GetTempRange(pParse, nPkColumn);
> for (j = 0; j < nPkColumn; j++) {
> k = pPk->aiColumn[j];
> - assert(k >= 0 && k < pTab->nCol);
> + assert(k >= 0 && k < (int)pTab->def->field_count);
> sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKeyStat + j);
> - VdbeComment((v, "%s", pTab->aCol[pPk->aiColumn[j]].zName));
> + VdbeComment((v, "%s",
> + pTab->def->fields[pPk->aiColumn[j]].name));
> }
> sqlite3VdbeAddOp3(v, OP_MakeRecord, regKeyStat,
> nPkColumn, regKey);
> diff --git a/src/box/sql/build.c b/src/box/sql/build.c
> index a2b712a..c712b46 100644
> --- a/src/box/sql/build.c
> +++ b/src/box/sql/build.c
> @@ -291,15 +291,8 @@ sqlite3CommitInternalChanges()
> void
> sqlite3DeleteColumnNames(sqlite3 * db, Table * pTable)
> {
> - int i;
> - Column *pCol;
> assert(pTable != 0);
> - if ((pCol = pTable->aCol) != 0) {
> - for (i = 0; i < pTable->nCol; i++, pCol++) {
> - sqlite3DbFree(db, pCol->zName);
> - }
> - sqlite3DbFree(db, pTable->aCol);
> - }
> + sqlite3DbFree(db, pTable->aCol);
> }
>
> /*
> @@ -393,12 +386,8 @@ deleteTable(sqlite3 * db, Table * pTable)
> sqlite3DbFree(db, pTable->zColAff);
> sqlite3SelectDelete(db, pTable->pSelect);
> sqlite3ExprListDelete(db, pTable->pCheck);
> - if (pTable->def != NULL) {
> - /* Fields has been allocated independently. */
> - struct field_def *fields = pTable->def->fields;
> + if (pTable->def != NULL)
> space_def_delete(pTable->def);
> - sqlite3DbFree(db, fields);
> - }
> sqlite3DbFree(db, pTable);
>
> /* Verify that no lookaside memory was used by schema tables */
> @@ -496,28 +485,16 @@ sqlite3PrimaryKeyIndex(Table * pTab)
> * Create and initialize a new SQL Table object.
> * @param parser SQL Parser object.
> * @param name Table to create name.
> - * @retval NULL on memory allocation error, Parser state is
> - * changed.
> + * @retval NULL on memory allocation error.
> * @retval not NULL on success.
> */
> static Table *
> sql_table_new(Parse *parser, char *name)
> {
> sqlite3 *db = parser->db;
> -
> - Table *table = sqlite3DbMallocZero(db, sizeof(Table));
> - struct space_def *def = space_def_new(0, 0, 0, NULL, 0, NULL, 0,
> - &space_opts_default, NULL, 0);
> - if (table == NULL || def == NULL) {
> - if (def != NULL)
> - space_def_delete(def);
> - sqlite3DbFree(db, table);
> - parser->rc = SQLITE_NOMEM_BKPT;
> - parser->nErr++;
> + struct Table *table = sql_ephemeral_table_new(parser);
> + if (table == NULL)
> return NULL;
> - }
> -
> - table->def = def;
> table->zName = name;
> table->iPKey = -1;
> table->iAutoIncPKey = -1;
> @@ -629,7 +606,6 @@ sql_field_retrieve(Parse *parser, Table *table, uint32_t id)
> sqlite3 *db = parser->db;
> struct field_def *field;
> assert(table->def != NULL);
> - assert(table->def->exact_field_count >= (uint32_t)table->nCol);
> assert(id < SQLITE_MAX_COLUMN);
>
> if (id >= table->def->exact_field_count) {
> @@ -676,12 +652,12 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
> if ((p = pParse->pNewTable) == 0)
> return;
> #if SQLITE_MAX_COLUMN
> - if (p->nCol + 1 > db->aLimit[SQLITE_LIMIT_COLUMN]) {
> + if ((int)p->def->field_count + 1 > db->aLimit[SQLITE_LIMIT_COLUMN]) {
> sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName);
> return;
> }
> #endif
> - if (sql_field_retrieve(pParse, p, (uint32_t) p->nCol) == NULL)
> + if (sql_field_retrieve(pParse, p, (uint32_t) p->def->field_count) == NULL)
> return;
> z = sqlite3DbMallocRaw(db, pName->n + 1);
> if (z == 0)
> @@ -689,28 +665,27 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
> memcpy(z, pName->z, pName->n);
> z[pName->n] = 0;
> sqlite3NormalizeName(z);
> - for (i = 0; i < p->nCol; i++) {
> - if (strcmp(z, p->aCol[i].zName) == 0) {
> + for (i = 0; i < (int)p->def->field_count; i++) {
> + if (strcmp(z, p->def->fields[i].name) == 0) {
> sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
> sqlite3DbFree(db, z);
> return;
> }
> }
> - if ((p->nCol & 0x7) == 0) {
> + if ((p->def->field_count & 0x7) == 0) {
> Column *aNew;
> aNew =
> sqlite3DbRealloc(db, p->aCol,
> - (p->nCol + 8) * sizeof(p->aCol[0]));
> + (p->def->field_count + 8) * sizeof(p->aCol[0]));
> if (aNew == 0) {
> sqlite3DbFree(db, z);
> return;
> }
> p->aCol = aNew;
> }
> - pCol = &p->aCol[p->nCol];
> + pCol = &p->aCol[p->def->field_count];
> memset(pCol, 0, sizeof(p->aCol[0]));
> - pCol->zName = z;
> -
> + p->def->fields[p->def->field_count].name = z;
> if (pType->n == 0) {
> /* If there is no type specified, columns have the default affinity
> * 'BLOB' and type SCALAR.
> @@ -740,7 +715,6 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
> sqlite3_free(zType);
> }
> }
> - p->nCol++;
> p->def->field_count++;
> pParse->constraintName.n = 0;
> }
> @@ -756,9 +730,9 @@ sqlite3AddNotNull(Parse * pParse, int onError)
> {
> Table *p;
> p = pParse->pNewTable;
> - if (p == 0 || NEVER(p->nCol < 1))
> + if (p == 0 || NEVER(p->def->field_count < 1))
> return;
> - p->aCol[p->nCol - 1].notNull = (u8) onError;
> + p->aCol[p->def->field_count - 1].notNull = (u8) onError;
> }
>
> /*
> @@ -871,38 +845,30 @@ void
> sqlite3AddDefaultValue(Parse * pParse, ExprSpan * pSpan)
> {
> Table *p;
> - Column *pCol;
> sqlite3 *db = pParse->db;
> p = pParse->pNewTable;
> if (p != 0) {
> - pCol = &(p->aCol[p->nCol - 1]);
> if (!sqlite3ExprIsConstantOrFunction
> (pSpan->pExpr, db->init.busy)) {
> sqlite3ErrorMsg(pParse,
> "default value of column [%s] is not constant",
> - pCol->zName);
> + p->def->fields[p->def->field_count - 1].name);
> } else {
> - /* A copy of pExpr is used instead of the original, as pExpr contains
> - * tokens that point to volatile memory. The 'span' of the expression
> - * is required by pragma table_info.
> - */
> - Expr x;
> assert(p->def != NULL);
> struct field_def *field =
> - &p->def->fields[p->nCol - 1];
> - sql_expr_free(db, field->default_value_expr, false);
> -
> - memset(&x, 0, sizeof(x));
> - x.op = TK_SPAN;
> - x.u.zToken = sqlite3DbStrNDup(db, (char *)pSpan->zStart,
> - (int)(pSpan->zEnd -
> - pSpan->zStart));
> - x.pLeft = pSpan->pExpr;
> - x.flags = EP_Skip;
> -
> - field->default_value_expr =
> - sqlite3ExprDup(db, &x, EXPRDUP_REDUCE);
> - sqlite3DbFree(db, x.u.zToken);
> + &p->def->fields[p->def->field_count - 1];
> + struct region *region = &fiber()->gc;
> + uint32_t default_length = (int)(pSpan->zEnd - pSpan->zStart);
> + field->default_value = region_alloc(region,
> + default_length + 1);
> + if (field->default_value == NULL) {
> + pParse->rc = SQLITE_NOMEM_BKPT;
> + pParse->nErr++;
> + return;
> + }
> + strncpy(field->default_value, (char *)pSpan->zStart,
> + default_length);
> + field->default_value[default_length] = '\0';
> }
> }
> sql_expr_free(db, pSpan->pExpr, false);
> @@ -947,7 +913,7 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
> }
> pTab->tabFlags |= TF_HasPrimaryKey;
> if (pList == 0) {
> - iCol = pTab->nCol - 1;
> + iCol = pTab->def->field_count - 1;
> pCol = &pTab->aCol[iCol];
> pCol->is_primkey = 1;
> nTerm = 1;
> @@ -962,10 +928,10 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
> goto primary_key_exit;
> }
> const char *zCName = pCExpr->u.zToken;
> - for (iCol = 0; iCol < pTab->nCol; iCol++) {
> + for (iCol = 0; iCol < (int)pTab->def->field_count; iCol++) {
> if (strcmp
> (zCName,
> - pTab->aCol[iCol].zName) == 0) {
> + pTab->def->fields[iCol].name) == 0) {
> pCol = &pTab->aCol[iCol];
> pCol->is_primkey = 1;
> break;
> @@ -1036,7 +1002,7 @@ sqlite3AddCollateType(Parse * pParse, Token * pToken)
>
> if ((p = pParse->pNewTable) == 0)
> return;
> - i = p->nCol - 1;
> + i = p->def->field_count - 1;
> db = pParse->db;
> zColl = sqlite3NameFromToken(db, pToken);
> if (!zColl)
> @@ -1087,7 +1053,7 @@ sql_column_collation(Table *table, uint32_t column)
> * SQL specific structures.
> */
> if (space == NULL || space_index(space, 0) == NULL) {
> - assert(column < (uint32_t)table->nCol);
> + assert(column < (uint32_t)table->def->field_count);
> return table->aCol[column].coll;
> }
>
> @@ -1306,9 +1272,8 @@ createTableStmt(sqlite3 * db, Table * p)
> char *zSep, *zSep2, *zEnd;
> Column *pCol;
> n = 0;
> - for (pCol = p->aCol, i = 0; i < p->nCol; i++, pCol++) {
> - n += identLength(pCol->zName) + 5;
> - }
> + for (i = 0; i < (int)p->def->field_count; i++)
> + n += identLength(p->def->fields[i].name) + 5;
> n += identLength(p->zName);
> if (n < 50) {
> zSep = "";
> @@ -1319,7 +1284,7 @@ createTableStmt(sqlite3 * db, Table * p)
> zSep2 = ",\n ";
> zEnd = "\n)";
> }
> - n += 35 + 6 * p->nCol;
> + n += 35 + 6 * p->def->field_count;
> zStmt = sqlite3DbMallocRaw(0, n);
> if (zStmt == 0) {
> sqlite3OomFault(db);
> @@ -1329,7 +1294,7 @@ createTableStmt(sqlite3 * db, Table * p)
> k = sqlite3Strlen30(zStmt);
> identPut(zStmt, &k, p->zName);
> zStmt[k++] = '(';
> - for (pCol = p->aCol, i = 0; i < p->nCol; i++, pCol++) {
> + for (pCol = p->aCol, i = 0; i < (int)p->def->field_count; i++, pCol++) {
> static const char *const azType[] = {
> /* SQLITE_AFF_BLOB */ "",
> /* SQLITE_AFF_TEXT */ " TEXT",
> @@ -1343,7 +1308,7 @@ createTableStmt(sqlite3 * db, Table * p)
> sqlite3_snprintf(n - k, &zStmt[k], zSep);
> k += sqlite3Strlen30(&zStmt[k]);
> zSep = zSep2;
> - identPut(zStmt, &k, pCol->zName);
> + identPut(zStmt, &k, p->def->fields[i].name);
> assert(pCol->affinity - SQLITE_AFF_BLOB >= 0);
> assert(pCol->affinity - SQLITE_AFF_BLOB < ArraySize(azType));
> testcase(pCol->affinity == SQLITE_AFF_BLOB);
> @@ -1373,7 +1338,8 @@ estimateTableWidth(Table * pTab)
> unsigned wTable = 0;
> const Column *pTabCol;
> int i;
> - for (i = pTab->nCol, pTabCol = pTab->aCol; i > 0; i--, pTabCol++) {
> + for (i = pTab->def->field_count,
> + pTabCol = pTab->aCol; i > 0; i--, pTabCol++) {
> wTable += pTabCol->szEst;
> }
> if (pTab->iPKey < 0)
> @@ -1392,7 +1358,7 @@ estimateIndexWidth(Index * pIdx)
> const Column *aCol = pIdx->pTable->aCol;
> for (i = 0; i < pIdx->nColumn; i++) {
> i16 x = pIdx->aiColumn[i];
> - assert(x < pIdx->pTable->nCol);
> + assert(x < (int)pIdx->pTable->def->field_count);
> wIndex += x < 0 ? 1 : aCol[pIdx->aiColumn[i]].szEst;
> }
> pIdx->szIdxRow = sqlite3LogEst(wIndex * 4);
> @@ -1433,7 +1399,7 @@ convertToWithoutRowidTable(Parse * pParse, Table * pTab)
> /* Mark every PRIMARY KEY column as NOT NULL (except for imposter tables)
> */
> if (!db->init.imposterTable) {
> - for (i = 0; i < pTab->nCol; i++) {
> + for (i = 0; i < (int)pTab->def->field_count; i++) {
> if (pTab->aCol[i].is_primkey) {
> pTab->aCol[i].notNull = ON_CONFLICT_ACTION_ABORT;
> }
> @@ -1446,7 +1412,7 @@ convertToWithoutRowidTable(Parse * pParse, Table * pTab)
> if (pTab->iPKey >= 0) {
> ExprList *pList;
> Token ipkToken;
> - sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zName);
> + sqlite3TokenInit(&ipkToken, pTab->def->fields[pTab->iPKey].name);
> pList = sqlite3ExprListAppend(pParse, 0,
> sqlite3ExprAlloc(db, TK_ID,
> &ipkToken, 0));
> @@ -1663,7 +1629,7 @@ createSpace(Parse * pParse, int iSpaceId, char *zStmt)
> sqlite3DbStrDup(pParse->db, p->zName), P4_DYNAMIC);
> sqlite3VdbeAddOp4(v, OP_String8, 0, iFirstCol + 3 /* engine */ , 0,
> "memtx", P4_STATIC);
> - sqlite3VdbeAddOp2(v, OP_Integer, p->nCol,
> + sqlite3VdbeAddOp2(v, OP_Integer, p->def->field_count,
> iFirstCol + 4 /* field_count */ );
> sqlite3VdbeAddOp4(v, OP_Blob, zOptsSz, iFirstCol + 5, MSGPACK_SUBTYPE,
> zOpts, P4_DYNAMIC);
> @@ -1853,6 +1819,8 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
> p = pParse->pNewTable;
> if (p == 0)
> return;
> + if (sql_table_def_rebuild(db, p) != 0)
> + return;
>
> assert(!db->init.busy || !pSelect);
>
> @@ -2101,7 +2069,7 @@ sqlite3ViewGetColumnNames(Parse * pParse, Table * pTable)
> /* A positive nCol means the columns names for this view are
> * already known.
> */
> - if (pTable->nCol > 0)
> + if (pTable->def->field_count > 0)
> return 0;
>
> /* A negative nCol is a special marker meaning that we are currently
> @@ -2119,12 +2087,12 @@ sqlite3ViewGetColumnNames(Parse * pParse, Table * pTable)
> * CREATE TEMP VIEW ex1 AS SELECT a FROM ex1;
> * SELECT * FROM temp.ex1;
> */
> - if (pTable->nCol < 0) {
> + if ((int)pTable->def->field_count < 0) {
> sqlite3ErrorMsg(pParse, "view %s is circularly defined",
> pTable->zName);
> return 1;
> }
> - assert(pTable->nCol >= 0);
> + assert((int)pTable->def->field_count >= 0);
>
> /* If we get this far, it means we need to compute the table names.
> * Note that the call to sqlite3ResultSetOfSelect() will expand any
> @@ -2138,7 +2106,7 @@ sqlite3ViewGetColumnNames(Parse * pParse, Table * pTable)
> if (pSel) {
> n = pParse->nTab;
> sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
> - pTable->nCol = -1;
> + pTable->def->field_count = -1;
> db->lookaside.bDisable++;
> pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
> pParse->nTab = n;
> @@ -2149,11 +2117,9 @@ sqlite3ViewGetColumnNames(Parse * pParse, Table * pTable)
> * normally holds CHECK constraints on an ordinary table, but for
> * a VIEW it holds the list of column names.
> */
> - sqlite3ColumnsFromExprList(pParse, pTable->pCheck,
> - &pTable->nCol,
> - &pTable->aCol);
> + sqlite3ColumnsFromExprList(pParse, pTable->pCheck, pTable);
> if (db->mallocFailed == 0 && pParse->nErr == 0
> - && pTable->nCol == pSel->pEList->nExpr) {
> + && (int)pTable->def->field_count == pSel->pEList->nExpr) {
> sqlite3SelectAddColumnTypeAndCollation(pParse,
> pTable,
> pSel);
> @@ -2163,12 +2129,15 @@ sqlite3ViewGetColumnNames(Parse * pParse, Table * pTable)
> * the column names from the SELECT statement that defines the view.
> */
> assert(pTable->aCol == 0);
> - pTable->nCol = pSelTab->nCol;
> + assert((int)pTable->def->field_count == -1);
> + struct space_def *def = pSelTab->def;
> + pSelTab->def = pTable->def;
> + pSelTab->def->field_count = 0;
> + pTable->def = def;
> pTable->aCol = pSelTab->aCol;
> - pSelTab->nCol = 0;
> pSelTab->aCol = 0;
> } else {
> - pTable->nCol = 0;
> + pTable->def->field_count = 0;
> nErr++;
> }
> sqlite3DeleteTable(db, pSelTab);
> @@ -2195,8 +2164,18 @@ sqliteViewResetAll(sqlite3 * db)
> Table *pTab = sqliteHashData(i);
> if (pTab->pSelect) {
> sqlite3DeleteColumnNames(db, pTab);
> + struct space_def *old_def = pTab->def;
> + pTab->def = space_def_new(old_def->id, old_def->uid,
> + 0,
> + old_def->name,
> + strlen(old_def->name),
> + old_def->engine_name,
> + strlen(old_def->engine_name),
> + &old_def->opts,
> + NULL, 0);
> + assert(pTab->def);
> + space_def_delete(old_def);
> pTab->aCol = 0;
> - pTab->nCol = 0;
> }
> }
> }
> @@ -2469,13 +2448,13 @@ sqlite3CreateForeignKey(Parse * pParse, /* Parsing context */
> if (p == 0)
> goto fk_end;
> if (pFromCol == 0) {
> - int iCol = p->nCol - 1;
> + int iCol = p->def->field_count - 1;
> if (NEVER(iCol < 0))
> goto fk_end;
> if (pToCol && pToCol->nExpr != 1) {
> sqlite3ErrorMsg(pParse, "foreign key on %s"
> " should reference only one column of table %T",
> - p->aCol[iCol].zName, pTo);
> + p->def->fields[iCol].name, pTo);
> goto fk_end;
> }
> nCol = 1;
> @@ -2508,19 +2487,19 @@ sqlite3CreateForeignKey(Parse * pParse, /* Parsing context */
> z += pTo->n + 1;
> pFKey->nCol = nCol;
> if (pFromCol == 0) {
> - pFKey->aCol[0].iFrom = p->nCol - 1;
> + pFKey->aCol[0].iFrom = p->def->field_count - 1;
> } else {
> for (i = 0; i < nCol; i++) {
> int j;
> - for (j = 0; j < p->nCol; j++) {
> + for (j = 0; j < (int)p->def->field_count; j++) {
> if (strcmp
> - (p->aCol[j].zName,
> + (p->def->fields[j].name,
> pFromCol->a[i].zName) == 0) {
> pFKey->aCol[i].iFrom = j;
> break;
> }
> }
> - if (j >= p->nCol) {
> + if (j >= (int)p->def->field_count) {
> sqlite3ErrorMsg(pParse,
> "unknown column \"%s\" in foreign key definition",
> pFromCol->a[i].zName);
> @@ -2966,7 +2945,9 @@ sqlite3CreateIndex(Parse * pParse, /* All information about this parse */
> */
> if (pList == 0) {
> Token prevCol;
> - sqlite3TokenInit(&prevCol, pTab->aCol[pTab->nCol - 1].zName);
> + sqlite3TokenInit(&prevCol,
> + pTab->def->
> + fields[pTab->def->field_count - 1].name);
> pList = sqlite3ExprListAppend(pParse, 0,
> sqlite3ExprAlloc(db, TK_ID,
> &prevCol, 0));
> @@ -4018,7 +3999,7 @@ sqlite3UniqueConstraint(Parse * pParse, /* Parsing context */
> for (j = 0; j < pIdx->nColumn; j++) {
> char *zCol;
> assert(pIdx->aiColumn[j] >= 0);
> - zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
> + zCol = pTab->def->fields[pIdx->aiColumn[j]].name;
> if (j)
> sqlite3StrAccumAppend(&errMsg, ", ", 2);
> sqlite3XPrintf(&errMsg, "%s.%s", pTab->zName, zCol);
> @@ -4181,7 +4162,7 @@ sqlite3KeyInfoOfIndex(Parse * pParse, sqlite3 * db, Index * pIdx)
> {
> int i;
> int nCol = pIdx->nColumn;
> - int nTableCol = pIdx->pTable->nCol;
> + int nTableCol = pIdx->pTable->def->field_count;
> KeyInfo *pKey;
>
> if (pParse && pParse->nErr)
> diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
> index 3f74b93..65d20fa 100644
> --- a/src/box/sql/delete.c
> +++ b/src/box/sql/delete.c
> @@ -382,7 +382,7 @@ sqlite3DeleteFrom(Parse * pParse, /* The parser context */
> * there is no PK for it, so columns should be loaded manually.
> */
> if (isView) {
> - nPk = pTab->nCol;
> + nPk = pTab->def->field_count;
> iPk = pParse->nMem + 1;
> pParse->nMem += nPk;
> iEphCur = pParse->nTab++;
> @@ -734,13 +734,13 @@ sqlite3GenerateRowDelete(Parse * pParse, /* Parsing context */
> onconf);
> mask |= sqlite3FkOldmask(pParse, pTab);
> iOld = pParse->nMem + 1;
> - pParse->nMem += (1 + pTab->nCol);
> + pParse->nMem += (1 + pTab->def->field_count);
>
> /* Populate the OLD.* pseudo-table register array. These values will be
> * used by any BEFORE and AFTER triggers that exist.
> */
> sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld);
> - for (iCol = 0; iCol < pTab->nCol; iCol++) {
> + for (iCol = 0; iCol < (int)pTab->def->field_count; iCol++) {
> testcase(mask != 0xffffffff && iCol == 31);
> testcase(mask != 0xffffffff && iCol == 32);
> if (mask == 0xffffffff
> diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
> index 0c86761..5f7d741 100644
> --- a/src/box/sql/expr.c
> +++ b/src/box/sql/expr.c
> @@ -48,7 +48,7 @@ static int exprCodeVector(Parse * pParse, Expr * p, int *piToFree);
> char
> sqlite3TableColumnAffinity(Table * pTab, int iCol)
> {
> - assert(iCol < pTab->nCol);
> + assert(iCol < (int)pTab->def->field_count);
> return iCol >= 0 ? pTab->aCol[iCol].affinity : SQLITE_AFF_INTEGER;
> }
>
> @@ -4242,20 +4242,21 @@ sqlite3ExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
> */
> Table *pTab = pExpr->pTab;
> int p1 =
> - pExpr->iTable * (pTab->nCol + 1) + 1 +
> + pExpr->iTable * (pTab->def->field_count + 1) + 1 +
> pExpr->iColumn;
>
> assert(pExpr->iTable == 0 || pExpr->iTable == 1);
> assert(pExpr->iColumn >= 0
> - && pExpr->iColumn < pTab->nCol);
> + && pExpr->iColumn < (int)pTab->def->field_count);
> assert(pTab->iPKey < 0
> || pExpr->iColumn != pTab->iPKey);
> - assert(p1 >= 0 && p1 < (pTab->nCol * 2 + 2));
> + assert(p1 >= 0 && p1 <
> + ((int)pTab->def->field_count * 2 + 2));
>
> sqlite3VdbeAddOp2(v, OP_Param, p1, target);
> VdbeComment((v, "%s.%s -> $%d",
> (pExpr->iTable ? "new" : "old"),
> - pExpr->pTab->aCol[pExpr->iColumn].zName,
> + pExpr->pTab->def->fields[pExpr->iColumn].name,
> target));
>
> #ifndef SQLITE_OMIT_FLOATING_POINT
> diff --git a/src/box/sql/fkey.c b/src/box/sql/fkey.c
> index fb9a310..c15ad8c 100644
> --- a/src/box/sql/fkey.c
> +++ b/src/box/sql/fkey.c
> @@ -243,7 +243,7 @@ sqlite3FkLocateIndex(Parse * pParse, /* Parse context to store any error in */
> if (!zKey)
> return 0;
> if (!strcmp
> - (pParent->aCol[pParent->iPKey].zName, zKey))
> + (pParent->def->fields[pParent->iPKey].name, zKey))
> return 0;
> }
> } else if (paiCol) {
> @@ -305,7 +305,7 @@ sqlite3FkLocateIndex(Parse * pParse, /* Parse context to store any error in */
> if (def_coll != coll)
> break;
>
> - zIdxCol = pParent->aCol[iCol].zName;
> + zIdxCol = pParent->def->fields[iCol].name;
> for (j = 0; j < nCol; j++) {
> if (strcmp
> (pFKey->aCol[j].zCol,
> @@ -650,7 +650,7 @@ fkScanChildren(Parse * pParse, /* Parse context */
> pLeft = exprTableRegister(pParse, pTab, regData, iCol);
> iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
> assert(iCol >= 0);
> - zCol = pFKey->pFrom->aCol[iCol].zName;
> + zCol = pFKey->pFrom->def->fields[iCol].name;
> pRight = sqlite3Expr(db, TK_ID, zCol);
> pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight);
> pWhere = sqlite3ExprAnd(db, pWhere, pEq);
> @@ -863,12 +863,12 @@ fkParentIsModified(Table * pTab, FKey * p, int *aChange)
> for (i = 0; i < p->nCol; i++) {
> char *zKey = p->aCol[i].zCol;
> int iKey;
> - for (iKey = 0; iKey < pTab->nCol; iKey++) {
> + for (iKey = 0; iKey < (int)pTab->def->field_count; iKey++) {
> if (aChange[iKey] >= 0) {
> - Column *pCol = &pTab->aCol[iKey];
> if (zKey) {
> if (0 ==
> - strcmp(pCol->zName, zKey))
> + strcmp(pTab->def->fields[iKey].name,
> + zKey))
> return 1;
> } else if (table_column_is_in_pk(pTab, iKey)) {
> return 1;
> @@ -1282,14 +1282,14 @@ fkActionTrigger(Parse * pParse, /* Parse context */
> assert(iFromCol >= 0);
> assert(pIdx != 0
> || (pTab->iPKey >= 0
> - && pTab->iPKey < pTab->nCol));
> + && pTab->iPKey < (int)pTab->def->field_count));
> assert(pIdx == 0 || pIdx->aiColumn[i] >= 0);
> sqlite3TokenInit(&tToCol,
> - pTab->aCol[pIdx ? pIdx->
> + pTab->def->fields[pIdx ? pIdx->
> aiColumn[i] : pTab->iPKey].
> - zName);
> + name);
> sqlite3TokenInit(&tFromCol,
> - pFKey->pFrom->aCol[iFromCol].zName);
> + pFKey->pFrom->def->fields[iFromCol].name);
>
> /* Create the expression "OLD.zToCol = zFromCol". It is important
> * that the "OLD.zToCol" term is on the LHS of the = operator, so
> diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
> index 1cb9525..06635ee 100644
> --- a/src/box/sql/insert.c
> +++ b/src/box/sql/insert.c
> @@ -146,13 +146,14 @@ sqlite3TableAffinity(Vdbe * v, Table * pTab, int iReg)
> char *zColAff = pTab->zColAff;
> if (zColAff == 0) {
> sqlite3 *db = sqlite3VdbeDb(v);
> - zColAff = (char *)sqlite3DbMallocRaw(0, pTab->nCol + 1);
> + zColAff = (char *)sqlite3DbMallocRaw(0,
> + pTab->def->field_count + 1);
> if (!zColAff) {
> sqlite3OomFault(db);
> return;
> }
>
> - for (i = 0; i < pTab->nCol; i++) {
> + for (i = 0; i < (int)pTab->def->field_count; i++) {
> zColAff[i] = pTab->aCol[i].affinity;
> }
> do {
> @@ -446,7 +447,7 @@ sqlite3Insert(Parse * pParse, /* Parser context */
> * the content of the new row, and the assembled row record.
> */
> regTupleid = regIns = pParse->nMem + 1;
> - pParse->nMem += pTab->nCol + 1;
> + pParse->nMem += pTab->def->field_count + 1;
> regData = regTupleid + 1;
>
> /* If the INSERT statement included an IDLIST term, then make sure
> @@ -465,17 +466,17 @@ sqlite3Insert(Parse * pParse, /* Parser context */
> /* The size of used_columns buffer is checked during compilation time
> * using SQLITE_MAX_COLUMN constant.
> */
> - memset(used_columns, 0, (pTab->nCol + 7) / 8);
> + memset(used_columns, 0, (pTab->def->field_count + 7) / 8);
> bIdListInOrder = 1;
> if (pColumn) {
> for (i = 0; i < pColumn->nId; i++) {
> pColumn->a[i].idx = -1;
> }
> for (i = 0; i < pColumn->nId; i++) {
> - for (j = 0; j < pTab->nCol; j++) {
> + for (j = 0; j < (int)pTab->def->field_count; j++) {
> if (strcmp
> (pColumn->a[i].zName,
> - pTab->aCol[j].zName) == 0) {
> + pTab->def->fields[j].name) == 0) {
> pColumn->a[i].idx = j;
> if (i != j)
> bIdListInOrder = 0;
> @@ -486,7 +487,7 @@ sqlite3Insert(Parse * pParse, /* Parser context */
> break;
> }
> }
> - if (j >= pTab->nCol) {
> + if (j >= (int)pTab->def->field_count) {
> sqlite3ErrorMsg(pParse,
> "table %S has no column named %s",
> pTabList, 0, pColumn->a[i].zName);
> @@ -522,7 +523,7 @@ sqlite3Insert(Parse * pParse, /* Parser context */
> sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
> sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield);
> dest.iSdst = bIdListInOrder ? regData : 0;
> - dest.nSdst = pTab->nCol;
> + dest.nSdst = pTab->def->field_count;
> rc = sqlite3Select(pParse, pSelect, &dest);
> regFromSelect = dest.iSdst;
> if (rc || db->mallocFailed || pParse->nErr)
> @@ -611,10 +612,10 @@ sqlite3Insert(Parse * pParse, /* Parser context */
> ipkColumn = pTab->iPKey;
> }
>
> - if (pColumn == 0 && nColumn && nColumn != (pTab->nCol)) {
> + if (pColumn == 0 && nColumn && nColumn != ((int)pTab->def->field_count)) {
> sqlite3ErrorMsg(pParse,
> "table %S has %d columns but %d values were supplied",
> - pTabList, 0, pTab->nCol, nColumn);
> + pTabList, 0, pTab->def->field_count, nColumn);
> goto insert_cleanup;
> }
> if (pColumn != 0 && nColumn != pColumn->nId) {
> @@ -682,11 +683,12 @@ sqlite3Insert(Parse * pParse, /* Parser context */
> */
> endOfLoop = sqlite3VdbeMakeLabel(v);
> if (tmask & TRIGGER_BEFORE) {
> - int regCols = sqlite3GetTempRange(pParse, pTab->nCol + 1);
> + int regCols = sqlite3GetTempRange(pParse,
> + pTab->def->field_count + 1);
>
> /* Create the new column data
> */
> - for (i = j = 0; i < pTab->nCol; i++) {
> + for (i = j = 0; i < (int)pTab->def->field_count; i++) {
> if (pColumn) {
> for (j = 0; j < pColumn->nId; j++) {
> if (pColumn->a[j].idx == i)
> @@ -732,10 +734,11 @@ sqlite3Insert(Parse * pParse, /* Parser context */
> /* Fire BEFORE or INSTEAD OF triggers */
> sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0,
> TRIGGER_BEFORE, pTab,
> - regCols - pTab->nCol - 1, onError,
> - endOfLoop);
> + regCols - pTab->def->field_count - 1,
> + onError, endOfLoop);
>
> - sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol + 1);
> + sqlite3ReleaseTempRange(pParse, regCols,
> + pTab->def->field_count + 1);
> }
>
> /* Compute the content of the next row to insert into a range of
> @@ -758,7 +761,7 @@ sqlite3Insert(Parse * pParse, /* Parser context */
> /* Compute data for all columns of the new entry, beginning
> * with the first column.
> */
> - for (i = 0; i < pTab->nCol; i++) {
> + for (i = 0; i < (int)pTab->def->field_count; i++) {
> int iRegStore = regData + i;
> if (pColumn == 0) {
> j = i;
> @@ -879,8 +882,8 @@ sqlite3Insert(Parse * pParse, /* Parser context */
> /* Code AFTER triggers */
> sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0,
> TRIGGER_AFTER, pTab,
> - regData - 2 - pTab->nCol, onError,
> - endOfLoop);
> + regData - 2 - pTab->def->field_count,
> + onError, endOfLoop);
> }
>
> /* The bottom of the main insertion loop, if the data source
> @@ -1093,7 +1096,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */
> assert(v != 0);
> /* This table is not a VIEW */
> assert(!space_is_view(pTab));
> - nCol = pTab->nCol;
> + nCol = pTab->def->field_count;
>
> pPk = sqlite3PrimaryKeyIndex(pTab);
> nPkField = index_column_count(pPk);
> @@ -1143,7 +1146,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */
> case ON_CONFLICT_ACTION_FAIL: {
> char *zMsg =
> sqlite3MPrintf(db, "%s.%s", pTab->zName,
> - pTab->aCol[i].zName);
> + pTab->def->fields[i].name);
> sqlite3VdbeAddOp3(v, OP_HaltIfNull,
> SQLITE_CONSTRAINT_NOTNULL,
> onError, regNewData + 1 + i);
> @@ -1282,7 +1285,8 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */
> sqlite3VdbeAddOp2(v, OP_SCopy,
> x, regIdx + i);
> VdbeComment((v, "%s",
> - pTab->aCol[iField].zName));
> + pTab->def->fields[iField].
> + name));
> }
> }
> }
> @@ -1310,7 +1314,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */
> }
> if (IsPrimaryKeyIndex(pIdx) || uniqueByteCodeNeeded) {
> sqlite3VdbeAddOp3(v, OP_MakeRecord, regNewData + 1,
> - pTab->nCol, aRegIdx[ix]);
> + pTab->def->field_count, aRegIdx[ix]);
> VdbeComment((v, "for %s", pIdx->zName));
> }
> } else {
> @@ -1401,7 +1405,8 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */
> sqlite3VdbeAddOp3(v, OP_Column,
> iThisCur, x, regR + i);
> VdbeComment((v, "%s.%s", pTab->zName,
> - pTab->aCol[pPk->aiColumn[i]].zName));
> + pTab->def->fields[
> + pPk->aiColumn[i]].name));
> }
> }
> if (isUpdate && uniqueByteCodeNeeded) {
> @@ -1792,13 +1797,13 @@ xferOptimization(Parse * pParse, /* Parser context */
> if (space_is_view(pSrc)) {
> return 0; /* tab2 may not be a view */
> }
> - if (pDest->nCol != pSrc->nCol) {
> + if (pDest->def->field_count != pSrc->def->field_count) {
> return 0; /* Number of columns must be the same in tab1 and tab2 */
> }
> if (pDest->iPKey != pSrc->iPKey) {
> return 0; /* Both tables must have the same INTEGER PRIMARY KEY */
> }
> - for (i = 0; i < pDest->nCol; i++) {
> + for (i = 0; i < (int)pDest->def->field_count; i++) {
> Column *pDestCol = &pDest->aCol[i];
> Column *pSrcCol = &pSrc->aCol[i];
> if (pDestCol->affinity != pSrcCol->affinity) {
> diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c
> index 4a68cad..e93f377 100644
> --- a/src/box/sql/pragma.c
> +++ b/src/box/sql/pragma.c
> @@ -359,7 +359,8 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */
> Index *pPk = sqlite3PrimaryKeyIndex(pTab);
> pParse->nMem = 6;
> sqlite3ViewGetColumnNames(pParse, pTab);
> - for (i = 0, pCol = pTab->aCol; i < pTab->nCol;
> + for (i = 0, pCol = pTab->aCol;
> + i < (int)pTab->def->field_count;
> i++, pCol++) {
> if (!table_column_is_in_pk(pTab, i)) {
> k = 0;
> @@ -367,7 +368,7 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */
> k = 1;
> } else {
> for (k = 1;
> - k <= pTab->nCol
> + k <= (int)pTab->def->field_count
> && pPk->aiColumn[k - 1] !=
> i; k++) {
> }
> @@ -381,7 +382,9 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */
> char *expr_str = space->
> def->fields[i].default_value;
> sqlite3VdbeMultiLoad(v, 1, "issisi",
> - i, pCol->zName,
> + i,
> + pTab->def->fields[i].
> + name,
> field_type_strs[
> sqlite3ColumnType
> (pCol)],
> @@ -453,8 +456,9 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */
> 0 ? 0 :
> pIdx->
> pTable->
> - aCol[cnum].
> - zName);
> + def->
> + fields[cnum].
> + name);
> if (pPragma->iArg) {
> const char *c_n;
> struct coll *coll;
> @@ -559,7 +563,7 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */
> while (pFK) {
> for (int j = 0; j < pFK->nCol; j++) {
> const char *name =
> - pTab->aCol[pFK->aCol[j].iFrom].zName;
> + pTab->def->fields[pFK->aCol[j].iFrom].name;
> sqlite3VdbeMultiLoad(v, 1, "iissssss", i, j,
> pFK->zTo, name,
> pFK->aCol[j].zCol,
> @@ -614,8 +618,9 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */
> }
> if (pTab == 0 || pTab->pFKey == 0)
> continue;
> - if (pTab->nCol + regRow > pParse->nMem)
> - pParse->nMem = pTab->nCol + regRow;
> + if ((int)pTab->def->field_count + regRow > pParse->nMem)
> + pParse->nMem =
> + pTab->def->field_count + regRow;
> sqlite3OpenTable(pParse, 0, pTab, OP_OpenRead);
> sqlite3VdbeLoadString(v, regResult,
> pTab->zName);
> @@ -677,7 +682,8 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */
> if (pParent && pIdx == 0) {
> int iKey = pFK->aCol[0].iFrom;
> assert(iKey >= 0
> - && iKey < pTab->nCol);
> + && iKey <
> + (int)pTab->def->field_count);
> if (iKey != pTab->iPKey) {
> sqlite3VdbeAddOp3(v,
> OP_Column,
> diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c
> index 823062a..109c410 100644
> --- a/src/box/sql/resolve.c
> +++ b/src/box/sql/resolve.c
> @@ -240,7 +240,7 @@ lookupName(Parse * pParse, /* The parsing context */
> i++, pItem++) {
> pTab = pItem->pTab;
> assert(pTab != 0 && pTab->zName != 0);
> - assert(pTab->nCol > 0);
> + assert(pTab->def->field_count > 0);
> if (pItem->pSelect
> && (pItem->pSelect->
> selFlags & SF_NestedFrom) != 0) {
> @@ -272,9 +272,10 @@ lookupName(Parse * pParse, /* The parsing context */
> if (0 == (cntTab++)) {
> pMatch = pItem;
> }
> - for (j = 0, pCol = pTab->aCol; j < pTab->nCol;
> + for (j = 0, pCol = pTab->aCol;
> + j < (int)pTab->def->field_count;
> j++, pCol++) {
> - if (strcmp(pCol->zName, zCol) ==
> + if (strcmp(pTab->def->fields[j].name, zCol) ==
> 0) {
> /* If there has been exactly one prior match and this match
> * is for the right-hand table of a NATURAL JOIN or is in a
> @@ -332,16 +333,17 @@ lookupName(Parse * pParse, /* The parsing context */
> int iCol;
> cntTab++;
> for (iCol = 0, pCol = pTab->aCol;
> - iCol < pTab->nCol; iCol++, pCol++) {
> - if (strcmp(pCol->zName, zCol) ==
> - 0) {
> + iCol < (int)pTab->def->field_count;
> + iCol++, pCol++) {
> + if (strcmp(pTab->def->fields[iCol].name,
> + zCol) == 0) {
> if (iCol == pTab->iPKey) {
> iCol = -1;
> }
> break;
> }
> }
> - if (iCol < pTab->nCol) {
> + if (iCol < (int)pTab->def->field_count) {
> cnt++;
> if (iCol < 0) {
> pExpr->affinity =
> diff --git a/src/box/sql/select.c b/src/box/sql/select.c
> index 5a50413..1390c5d 100644
> --- a/src/box/sql/select.c
> +++ b/src/box/sql/select.c
> @@ -318,9 +318,9 @@ sqlite3JoinType(Parse * pParse, Token * pA, Token * pB, Token * pC)
> static int
> columnIndex(Table * pTab, const char *zCol)
> {
> - int i;
> - for (i = 0; i < pTab->nCol; i++) {
> - if (strcmp(pTab->aCol[i].zName, zCol) == 0)
> + uint32_t i;
> + for (i = 0; i < pTab->def->field_count; i++) {
> + if (strcmp(pTab->def->fields[i].name, zCol) == 0)
> return i;
> }
> return -1;
> @@ -492,12 +492,12 @@ sqliteProcessJoin(Parse * pParse, Select * p)
> "an ON or USING clause", 0);
> return 1;
> }
> - for (j = 0; j < pRightTab->nCol; j++) {
> + for (j = 0; j < (int)pRightTab->def->field_count; j++) {
> char *zName; /* Name of column in the right table */
> int iLeft; /* Matching left table */
> int iLeftCol; /* Matching column in the left table */
>
> - zName = pRightTab->aCol[j].zName;
> + zName = pRightTab->def->fields[j].name;
> if (tableAndColumnIndex
> (pSrc, i + 1, zName, &iLeft, &iLeftCol)) {
> addWhereTerm(pParse, pSrc, iLeft,
> @@ -1661,7 +1661,8 @@ columnTypeImpl(NameContext * pNC, Expr * pExpr,
> } else if (pTab->pSchema) {
> /* A real table */
> assert(!pS);
> - assert(iCol >= 0 && iCol < pTab->nCol);
> + assert(iCol >= 0 && iCol <
> + (int)pTab->def->field_count);
> #ifdef SQLITE_ENABLE_COLUMN_METADATA
> zOrigCol = pTab->aCol[iCol].zName;
> zType = sqlite3ColumnType(&pTab->aCol[iCol], 0);
> @@ -1754,8 +1755,8 @@ generateColumnNames(Parse * pParse, /* Parser context */
> pTab = pTabList->a[j].pTab;
> if (iCol < 0)
> iCol = pTab->iPKey;
> - assert(iCol >= 0 && iCol < pTab->nCol);
> - zCol = pTab->aCol[iCol].zName;
> + assert(iCol >= 0 && iCol < (int)pTab->def->field_count);
> + zCol = pTab->def->fields[iCol].name;
> if (!shortNames && !fullNames) {
> sqlite3VdbeSetColName(v, i, COLNAME_NAME,
> sqlite3DbStrDup(db,
> @@ -1799,8 +1800,7 @@ generateColumnNames(Parse * pParse, /* Parser context */
> int
> sqlite3ColumnsFromExprList(Parse * pParse, /* Parsing context */
> ExprList * pEList, /* Expr list from which to derive column names */
> - i16 * pnCol, /* Write the number of columns here */
> - Column ** paCol) /* Write the new column list here */
> + Table * pTable) /* Pointer to SQL Table Object*/
> {
> sqlite3 *db = pParse->db; /* Database connection */
> int i, j; /* Loop counters */
> @@ -1822,8 +1822,11 @@ sqlite3ColumnsFromExprList(Parse * pParse, /* Parsing context */
> aCol = 0;
> }
> assert(nCol == (i16) nCol);
> - *pnCol = nCol;
> - *paCol = aCol;
> + assert(pTable->def->fields == NULL);
> + pTable->def->fields =
> + sqlite3DbMallocZero(db, nCol*sizeof(pTable->def->fields[0]));
> + pTable->def->field_count = (uint32_t)nCol;
> + pTable->aCol = aCol;
>
> for (i = 0, pCol = aCol; i < nCol && !db->mallocFailed; i++, pCol++) {
> /* Get an appropriate name for the column
> @@ -1845,7 +1848,7 @@ sqlite3ColumnsFromExprList(Parse * pParse, /* Parsing context */
> pTab = pColExpr->pTab;
> if (iCol < 0)
> iCol = pTab->iPKey;
> - zName = pTab->aCol[iCol].zName;
> + zName = pTab->def->fields[iCol].name;
> } else if (pColExpr->op == TK_ID) {
> assert(!ExprHasProperty(pColExpr, EP_IntValue));
> zName = pColExpr->u.zToken;
> @@ -1874,22 +1877,24 @@ sqlite3ColumnsFromExprList(Parse * pParse, /* Parsing context */
> if (cnt > 3)
> sqlite3_randomness(sizeof(cnt), &cnt);
> }
> - pCol->zName = zName;
> + pTable->def->fields[i].name = zName;
> if (zName && sqlite3HashInsert(&ht, zName, pCol) == pCol) {
> sqlite3OomFault(db);
> }
> }
> sqlite3HashClear(&ht);
> - if (db->mallocFailed) {
> - for (j = 0; j < i; j++) {
> - sqlite3DbFree(db, aCol[j].zName);
> - }
> + int rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_OK;
> + if (sql_table_def_rebuild(db, pTable) != 0)
> + rc = SQLITE_NOMEM_BKPT;
> + if (rc != SQLITE_OK) {
> sqlite3DbFree(db, aCol);
> - *paCol = 0;
> - *pnCol = 0;
> - return SQLITE_NOMEM_BKPT;
> + sqlite3DbFree(db, pTable->def->fields);
> + pTable->def->fields = NULL;
> + pTable->def->field_count = 0;
> + pTable->aCol = 0;
> + rc = SQLITE_NOMEM_BKPT;
> }
> - return SQLITE_OK;
> + return rc;
> }
>
> /*
> @@ -1918,13 +1923,15 @@ sqlite3SelectAddColumnTypeAndCollation(Parse * pParse, /* Parsing contexts */
>
> assert(pSelect != 0);
> assert((pSelect->selFlags & SF_Resolved) != 0);
> - assert(pTab->nCol == pSelect->pEList->nExpr || db->mallocFailed);
> + assert((int)pTab->def->field_count == pSelect->pEList->nExpr
> + || db->mallocFailed);
> if (db->mallocFailed)
> return;
> memset(&sNC, 0, sizeof(sNC));
> sNC.pSrcList = pSelect->pSrc;
> a = pSelect->pEList->a;
> - for (i = 0, pCol = pTab->aCol; i < pTab->nCol; i++, pCol++) {
> + for (i = 0, pCol = pTab->aCol;
> + i < (int)pTab->def->field_count; i++, pCol++) {
> enum field_type type;
> p = a[i].pExpr;
> type = columnType(&sNC, p, 0, 0, 0, &pCol->szEst);
> @@ -1963,10 +1970,9 @@ sqlite3ResultSetOfSelect(Parse * pParse, Select * pSelect)
> while (pSelect->pPrior)
> pSelect = pSelect->pPrior;
> user_session->sql_flags = savedFlags;
> - pTab = sqlite3DbMallocZero(db, sizeof(Table));
> - if (pTab == 0) {
> + pTab = sql_ephemeral_table_new(pParse);
> + if (pTab == NULL)
> return 0;
> - }
> /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
> * is disabled
> */
> @@ -1975,8 +1981,7 @@ sqlite3ResultSetOfSelect(Parse * pParse, Select * pSelect)
> pTab->zName = 0;
> pTab->nRowLogEst = 200;
> assert(200 == sqlite3LogEst(1048576));
> - sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol,
> - &pTab->aCol);
> + sqlite3ColumnsFromExprList(pParse, pSelect->pEList, pTab);
> sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect);
> pTab->iPKey = -1;
> if (db->mallocFailed) {
> @@ -4497,8 +4502,8 @@ withExpand(Walker * pWalker, struct SrcList_item *pFrom)
> return SQLITE_ERROR;
>
> assert(pFrom->pTab == 0);
> - pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
> - if (pTab == 0)
> + pFrom->pTab = pTab = sql_ephemeral_table_new(pParse);
> + if (pTab == NULL)
> return WRC_Abort;
> pTab->nTabRef = 1;
> pTab->zName = sqlite3DbStrDup(db, pCte->zName);
> @@ -4562,8 +4567,7 @@ withExpand(Walker * pWalker, struct SrcList_item *pFrom)
> pEList = pCte->pCols;
> }
>
> - sqlite3ColumnsFromExprList(pParse, pEList, &pTab->nCol,
> - &pTab->aCol);
> + sqlite3ColumnsFromExprList(pParse, pEList, pTab);
> if (bMayRecursive) {
> if (pSel->selFlags & SF_Recursive) {
> pCte->zCteErr =
> @@ -4684,8 +4688,8 @@ selectExpander(Walker * pWalker, Select * p)
> if (sqlite3WalkSelect(pWalker, pSel))
> return WRC_Abort;
> pFrom->pTab = pTab =
> - sqlite3DbMallocZero(db, sizeof(Table));
> - if (pTab == 0)
> + sql_ephemeral_table_new(pParse);
> + if (pTab == NULL)
> return WRC_Abort;
> pTab->nTabRef = 1;
> pTab->zName =
> @@ -4693,8 +4697,7 @@ selectExpander(Walker * pWalker, Select * p)
> while (pSel->pPrior) {
> pSel = pSel->pPrior;
> }
> - sqlite3ColumnsFromExprList(pParse, pSel->pEList,
> - &pTab->nCol, &pTab->aCol);
> + sqlite3ColumnsFromExprList(pParse, pSel->pEList, pTab);
> pTab->iPKey = -1;
> pTab->nRowLogEst = 200;
> assert(200 == sqlite3LogEst(1048576));
> @@ -4727,10 +4730,10 @@ selectExpander(Walker * pWalker, Select * p)
> sqlite3SelectDup(db, pTab->pSelect, 0);
> sqlite3SelectSetName(pFrom->pSelect,
> pTab->zName);
> - nCol = pTab->nCol;
> - pTab->nCol = -1;
> + nCol = pTab->def->field_count;
> + pTab->def->field_count = -1;
> sqlite3WalkSelect(pWalker, pFrom->pSelect);
> - pTab->nCol = nCol;
> + pTab->def->field_count = nCol;
> }
> #endif
> }
> @@ -4835,9 +4838,8 @@ selectExpander(Walker * pWalker, Select * p)
> continue;
> }
> }
> - for (j = 0; j < pTab->nCol; j++) {
> - char *zName =
> - pTab->aCol[j].zName;
> + for (j = 0; j < (int)pTab->def->field_count; j++) {
> + char *zName = pTab->def->fields[j].name;
> char *zColname; /* The computed column name */
> char *zToFree; /* Malloced string that needs to be freed */
> Token sColname; /* Computed column name as a token */
> @@ -5372,10 +5374,10 @@ sqlite3Select(Parse * pParse, /* The parser context */
> /* Catch mismatch in the declared columns of a view and the number of
> * columns in the SELECT on the RHS
> */
> - if (pTab->nCol != pSub->pEList->nExpr) {
> + if ((int)pTab->def->field_count != pSub->pEList->nExpr) {
> sqlite3ErrorMsg(pParse,
> "expected %d columns for '%s' but got %d",
> - pTab->nCol, pTab->zName,
> + pTab->def->field_count, pTab->zName,
> pSub->pEList->nExpr);
> goto select_end;
> }
> diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
> index 8bb45c9..8e1c135 100644
> --- a/src/box/sql/sqliteInt.h
> +++ b/src/box/sql/sqliteInt.h
> @@ -1867,7 +1867,6 @@ struct Savepoint {
> * of this structure.
> */
> struct Column {
> - char *zName; /* Name of this column */
> enum field_type type; /* Column type. */
> /** Collating sequence. */
> struct coll *coll;
> @@ -1950,7 +1949,6 @@ struct Table {
> i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */
> i16 iAutoIncPKey; /* If PK is marked INTEGER PRIMARY KEY AUTOINCREMENT, store
> column number here, -1 otherwise Tarantool specifics */
> - i16 nCol; /* Number of columns in this table */
> LogEst nRowLogEst; /* Estimated rows in table - from _sql_stat1 table */
> LogEst szTabRow; /* Estimated size of each table row in bytes */
> #ifdef SQLITE_ENABLE_COSTMULT
> @@ -3515,7 +3513,7 @@ void sqlite3ResetAllSchemasOfConnection(sqlite3 *);
> void sqlite3CommitInternalChanges();
> void sqlite3DeleteColumnNames(sqlite3 *, Table *);
> bool table_column_is_in_pk(Table *, uint32_t);
> -int sqlite3ColumnsFromExprList(Parse *, ExprList *, i16 *, Column **);
> +int sqlite3ColumnsFromExprList(Parse *, ExprList *, Table *);
> void sqlite3SelectAddColumnTypeAndCollation(Parse *, Table *, Select *);
> Table *sqlite3ResultSetOfSelect(Parse *, Select *);
> Index *sqlite3PrimaryKeyIndex(Table *);
> diff --git a/src/box/sql/update.c b/src/box/sql/update.c
> index f3bd0b7..464feee 100644
> --- a/src/box/sql/update.c
> +++ b/src/box/sql/update.c
> @@ -75,8 +75,8 @@ sqlite3ColumnDefault(Vdbe * v, Table * pTab, int i, int iReg)
> if (!pTab->pSelect) {
> sqlite3_value *pValue = 0;
> Column *pCol = &pTab->aCol[i];
> - VdbeComment((v, "%s.%s", pTab->zName, pCol->zName));
> - assert(i < pTab->nCol);
> + VdbeComment((v, "%s.%s", pTab->zName, pTab->def->fields[i].name));
> + assert(i < (int)pTab->def->field_count);
>
> Expr *expr = NULL;
> struct space *space =
> @@ -212,14 +212,15 @@ sqlite3Update(Parse * pParse, /* The parser context */
> */
> aXRef =
> sqlite3DbMallocRawNN(db,
> - sizeof(int) * (pTab->nCol + nIdx) + nIdx + 2);
> + sizeof(int) *
> + (pTab->def->field_count + nIdx) + nIdx + 2);
> if (aXRef == 0)
> goto update_cleanup;
> - aRegIdx = aXRef + pTab->nCol;
> + aRegIdx = aXRef + pTab->def->field_count;
> aToOpen = (u8 *) (aRegIdx + nIdx);
> memset(aToOpen, 1, nIdx + 1);
> aToOpen[nIdx + 1] = 0;
> - for (i = 0; i < pTab->nCol; i++)
> + for (i = 0; i < (int)pTab->def->field_count; i++)
> aXRef[i] = -1;
>
> /* Initialize the name-context */
> @@ -236,8 +237,8 @@ sqlite3Update(Parse * pParse, /* The parser context */
> if (sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr)) {
> goto update_cleanup;
> }
> - for (j = 0; j < pTab->nCol; j++) {
> - if (strcmp(pTab->aCol[j].zName,
> + for (j = 0; j < (int)pTab->def->field_count; j++) {
> + if (strcmp(pTab->def->fields[j].name,
> pChanges->a[i].zName) == 0) {
> if (pPk && table_column_is_in_pk(pTab, j)) {
> chngPk = 1;
> @@ -253,7 +254,7 @@ sqlite3Update(Parse * pParse, /* The parser context */
> break;
> }
> }
> - if (j >= pTab->nCol) {
> + if (j >= (int)pTab->def->field_count) {
> sqlite3ErrorMsg(pParse, "no such column: %s",
> pChanges->a[i].zName);
> pParse->checkSchema = 1;
> @@ -311,13 +312,13 @@ sqlite3Update(Parse * pParse, /* The parser context */
>
> if (chngPk || pTrigger || hasFK) {
> regOld = pParse->nMem + 1;
> - pParse->nMem += pTab->nCol;
> + pParse->nMem += pTab->def->field_count;
> }
> if (chngPk || pTrigger || hasFK) {
> regNewPk = ++pParse->nMem;
> }
> regNew = pParse->nMem + 1;
> - pParse->nMem += pTab->nCol;
> + pParse->nMem += pTab->def->field_count;
>
> /* If we are trying to update a view, realize that view into
> * an ephemeral table.
> @@ -326,7 +327,7 @@ sqlite3Update(Parse * pParse, /* The parser context */
> if (isView) {
> sqlite3MaterializeView(pParse, pTab, pWhere, iDataCur);
> /* Number of columns from SELECT plus ID.*/
> - nKey = pTab->nCol + 1;
> + nKey = pTab->def->field_count + 1;
> }
> #endif
>
> @@ -478,7 +479,7 @@ sqlite3Update(Parse * pParse, /* The parser context */
> pTrigger, pChanges, 0,
> TRIGGER_BEFORE | TRIGGER_AFTER,
> pTab, onError);
> - for (i = 0; i < pTab->nCol; i++) {
> + for (i = 0; i < (int)pTab->def->field_count; i++) {
> if (oldmask == 0xffffffff
> || (i < 32 && (oldmask & MASKBIT32(i)) != 0)
> || table_column_is_in_pk(pTab, i)) {
> @@ -509,7 +510,7 @@ sqlite3Update(Parse * pParse, /* The parser context */
> newmask =
> sqlite3TriggerColmask(pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE,
> pTab, onError);
> - for (i = 0; i < pTab->nCol; i++) {
> + for (i = 0; i < (int)pTab->def->field_count; i++) {
> if (i == pTab->iPKey) {
> sqlite3VdbeAddOp2(v, OP_Null, 0, regNew + i);
> } else {
> @@ -565,7 +566,7 @@ sqlite3Update(Parse * pParse, /* The parser context */
> * all columns not modified by the update statement into their
> * registers in case this has happened.
> */
> - for (i = 0; i < pTab->nCol; i++) {
> + for (i = 0; i < (int)pTab->def->field_count; i++) {
> if (aXRef[i] < 0 && i != pTab->iPKey) {
> sqlite3ExprCodeGetColumnOfTable(v, pTab,
> iDataCur, i,
> diff --git a/src/box/sql/where.c b/src/box/sql/where.c
> index 7a7103c..fc0f84c 100644
> --- a/src/box/sql/where.c
> +++ b/src/box/sql/where.c
> @@ -716,7 +716,7 @@ constructAutomaticIndex(Parse * pParse, /* The parsing context */
> sqlite3_log(SQLITE_WARNING_AUTOINDEX,
> "automatic index on %s(%s)",
> pTable->zName,
> - pTable->aCol[iCol].zName);
> + pTable->def->fields[iCol].name);
> sentWarning = 1;
> }
> if ((idxCols & cMask) == 0) {
> @@ -4514,9 +4514,9 @@ sqlite3WhereBegin(Parse * pParse, /* The parser context */
> sqlite3OpenTable(pParse, pTabItem->iCursor, pTab, op);
> assert(pTabItem->iCursor == pLevel->iTabCur);
> testcase(pWInfo->eOnePass == ONEPASS_OFF
> - && pTab->nCol == BMS - 1);
> + && pTab->def->field_count == BMS - 1);
> testcase(pWInfo->eOnePass == ONEPASS_OFF
> - && pTab->nCol == BMS);
> + && pTab->def->field_count == BMS);
> #ifdef SQLITE_ENABLE_CURSOR_HINTS
> if (pLoop->pIndex != 0) {
> sqlite3VdbeChangeP5(v,
> diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
> index f1112f2..233fde0 100644
> --- a/src/box/sql/wherecode.c
> +++ b/src/box/sql/wherecode.c
> @@ -50,7 +50,7 @@ explainIndexColumnName(Index * pIdx, int i)
> i = pIdx->aiColumn[i];
> if (i == XN_EXPR)
> return "<expr>";
> - return pIdx->pTable->aCol[i].zName;
> + return pIdx->pTable->def->fields[i].name;
> }
>
> /*
> diff --git a/src/box/sql/whereexpr.c b/src/box/sql/whereexpr.c
> index 86ee273..1b0d961 100644
> --- a/src/box/sql/whereexpr.c
> +++ b/src/box/sql/whereexpr.c
> @@ -1502,10 +1502,10 @@ sqlite3WhereTabFuncArgs(Parse * pParse, /* Parsing context */
> if (pArgs == 0)
> return;
> for (j = k = 0; j < pArgs->nExpr; j++) {
> - while (k < pTab->nCol) {
> + while (k < (int)pTab->def->field_count) {
> k++;
> }
> - if (k >= pTab->nCol) {
> + if (k >= (int)pTab->def->field_count) {
> sqlite3ErrorMsg(pParse,
> "too many arguments on %s() - max %d",
> pTab->zName, j);
>
More information about the Tarantool-patches
mailing list