From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id A1A4C22B93 for ; Wed, 25 Apr 2018 13:10:06 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 1kAc911k8Wpb for ; Wed, 25 Apr 2018 13:10:06 -0400 (EDT) Received: from smtpng1.m.smailru.net (smtpng1.m.smailru.net [94.100.181.251]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id 13EB922B92 for ; Wed, 25 Apr 2018 13:10:05 -0400 (EDT) Subject: [tarantool-patches] Re: [PATCH v3 2/4] sql: Remove zName and nColumn from SQL. References: From: Kirill Shcherbatov Message-ID: Date: Wed, 25 Apr 2018 20:10:02 +0300 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-help: List-unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-subscribe: List-owner: List-post: List-archive: To: tarantool-patches@freelists.org Cc: "v.shpilevoy@tarantool.org" 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 ""; > - 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); >