* [tarantool-patches] [PATCH v3 0/4] sql: Removed Column fields to server with region allocations
@ 2018-04-25 16:52 Kirill Shcherbatov
2018-04-25 16:52 ` [tarantool-patches] [PATCH v3 1/4] sql: Fix code style in sqlite3Pragma Kirill Shcherbatov
` (5 more replies)
0 siblings, 6 replies; 26+ messages in thread
From: Kirill Shcherbatov @ 2018-04-25 16:52 UTC (permalink / raw)
To: tarantool-patches; +Cc: v.shpilevoy, Kirill Shcherbatov
Branch: http://github.com/tarantool/tarantool/tree/gh-3272-no-sql-names
Issue: https://github.com/tarantool/tarantool/issues/3272
Kirill Shcherbatov (4):
sql: Fix code style in sqlite3Pragma.
sql: Remove zName and nColumn from SQL.
sql: Removed type from SQL.
sql: Region-based allocations.
src/box/space_def.c | 29 ++++---
src/box/sql.c | 90 ++++++++++++++++---
src/box/sql.h | 32 +++++++
src/box/sql/alter.c | 32 ++++---
src/box/sql/analyze.c | 5 +-
src/box/sql/build.c | 226 +++++++++++++++++++++++-------------------------
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 | 84 +++++++++---------
src/box/sql/prepare.c | 26 +++---
src/box/sql/resolve.c | 16 ++--
src/box/sql/select.c | 120 ++++++++++++++-----------
src/box/sql/sqliteInt.h | 8 +-
src/box/sql/tokenize.c | 3 +
src/box/sql/trigger.c | 2 +
src/box/sql/update.c | 29 ++++---
src/box/sql/util.c | 9 --
src/box/sql/where.c | 6 +-
src/box/sql/wherecode.c | 2 +-
src/box/sql/whereexpr.c | 4 +-
22 files changed, 477 insertions(+), 338 deletions(-)
--
2.7.4
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] [PATCH v3 1/4] sql: Fix code style in sqlite3Pragma.
2018-04-25 16:52 [tarantool-patches] [PATCH v3 0/4] sql: Removed Column fields to server with region allocations Kirill Shcherbatov
@ 2018-04-25 16:52 ` Kirill Shcherbatov
2018-04-26 11:47 ` [tarantool-patches] " Vladislav Shpilevoy
2018-04-25 16:52 ` [tarantool-patches] [PATCH v3 2/4] sql: Remove zName and nColumn from SQL Kirill Shcherbatov
` (4 subsequent siblings)
5 siblings, 1 reply; 26+ messages in thread
From: Kirill Shcherbatov @ 2018-04-25 16:52 UTC (permalink / raw)
To: tarantool-patches; +Cc: v.shpilevoy, Kirill Shcherbatov
---
src/box/sql/pragma.c | 56 +++++++++++++++++++++++++---------------------------
1 file changed, 27 insertions(+), 29 deletions(-)
diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c
index e41f69b..4a68cad 100644
--- a/src/box/sql/pragma.c
+++ b/src/box/sql/pragma.c
@@ -544,37 +544,35 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */
#ifndef SQLITE_OMIT_FOREIGN_KEY
case PragTyp_FOREIGN_KEY_LIST:{
- if (zRight) {
- FKey *pFK;
- Table *pTab;
- pTab = sqlite3HashFind(&db->pSchema->tblHash,
- zRight);
- if (pTab != NULL) {
- pFK = pTab->pFKey;
- if (pFK) {
- int i = 0;
- pParse->nMem = 8;
- while (pFK) {
- int j;
- for (j = 0;
- j < pFK->nCol;
- j++) {
- sqlite3VdbeMultiLoad(v, 1, "iissssss", i, j, pFK->zTo, pTab->aCol[pFK->aCol[j].iFrom].zName, pFK->aCol[j].zCol, actionName(pFK->aAction[1]), /* ON UPDATE */
- actionName(pFK->aAction[0]), /* ON DELETE */
- "NONE");
- sqlite3VdbeAddOp2
- (v,
- OP_ResultRow,
- 1, 8);
- }
- ++i;
- pFK = pFK->pNextFrom;
- }
- }
- }
- }
+ if (!zRight)
+ break;
+ FKey *pFK;
+ Table *pTab;
+ pTab = sqlite3HashFind(&db->pSchema->tblHash, zRight);
+ if (pTab == NULL)
break;
+ pFK = pTab->pFKey;
+ if (!pFK)
+ break;
+ int i = 0;
+ pParse->nMem = 8;
+ while (pFK) {
+ for (int j = 0; j < pFK->nCol; j++) {
+ const char *name =
+ pTab->aCol[pFK->aCol[j].iFrom].zName;
+ sqlite3VdbeMultiLoad(v, 1, "iissssss", i, j,
+ pFK->zTo, name,
+ pFK->aCol[j].zCol,
+ actionName(pFK->aAction[1]),
+ actionName(pFK->aAction[0]),
+ "NONE");
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 8);
+ }
+ ++i;
+ pFK = pFK->pNextFrom;
}
+ break;
+ }
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
#ifndef SQLITE_OMIT_FOREIGN_KEY
--
2.7.4
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] [PATCH v3 2/4] sql: Remove zName and nColumn from SQL.
2018-04-25 16:52 [tarantool-patches] [PATCH v3 0/4] sql: Removed Column fields to server with region allocations Kirill Shcherbatov
2018-04-25 16:52 ` [tarantool-patches] [PATCH v3 1/4] sql: Fix code style in sqlite3Pragma Kirill Shcherbatov
@ 2018-04-25 16:52 ` Kirill Shcherbatov
2018-04-25 17:10 ` [tarantool-patches] " Kirill Shcherbatov
2018-04-26 11:47 ` Vladislav Shpilevoy
2018-04-25 16:52 ` [tarantool-patches] [PATCH v3 3/4] sql: Removed type " Kirill Shcherbatov
` (3 subsequent siblings)
5 siblings, 2 replies; 26+ messages in thread
From: Kirill Shcherbatov @ 2018-04-25 16:52 UTC (permalink / raw)
To: tarantool-patches; +Cc: v.shpilevoy, Kirill Shcherbatov
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);
--
2.7.4
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] [PATCH v3 3/4] sql: Removed type from SQL.
2018-04-25 16:52 [tarantool-patches] [PATCH v3 0/4] sql: Removed Column fields to server with region allocations Kirill Shcherbatov
2018-04-25 16:52 ` [tarantool-patches] [PATCH v3 1/4] sql: Fix code style in sqlite3Pragma Kirill Shcherbatov
2018-04-25 16:52 ` [tarantool-patches] [PATCH v3 2/4] sql: Remove zName and nColumn from SQL Kirill Shcherbatov
@ 2018-04-25 16:52 ` Kirill Shcherbatov
2018-04-25 16:52 ` [tarantool-patches] [PATCH v3 4/4] sql: Region-based allocations Kirill Shcherbatov
` (2 subsequent siblings)
5 siblings, 0 replies; 26+ messages in thread
From: Kirill Shcherbatov @ 2018-04-25 16:52 UTC (permalink / raw)
To: tarantool-patches; +Cc: v.shpilevoy, Kirill Shcherbatov
Needed for #3272.
---
src/box/sql.c | 13 +++++++++----
src/box/sql/build.c | 12 +++++++-----
src/box/sql/pragma.c | 12 ++++++------
src/box/sql/select.c | 8 ++++----
src/box/sql/sqliteInt.h | 2 --
src/box/sql/util.c | 9 ---------
6 files changed, 26 insertions(+), 30 deletions(-)
diff --git a/src/box/sql.c b/src/box/sql.c
index 38aeac6..6d4255e 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -1430,10 +1430,12 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
{
struct Column *aCol = pTable->aCol;
const struct Enc *enc = get_enc(buf);
+ const struct space_def *def = pTable->def;
+ assert(def != NULL);
struct SqliteIndex *pk_idx = sqlite3PrimaryKeyIndex(pTable);
int pk_forced_int = -1;
char *base = buf, *p;
- int i, n = pTable->def->field_count;
+ int i, n = def->field_count;
p = enc->encode_array(base, n);
@@ -1441,14 +1443,14 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
* treat it as strict type, not affinity. */
if (pk_idx && pk_idx->nColumn == 1) {
int pk = pk_idx->aiColumn[0];
- if (pTable->aCol[pk].type == FIELD_TYPE_INTEGER)
+ if (def->fields[pk].type == FIELD_TYPE_INTEGER)
pk_forced_int = pk;
}
for (i = 0; i < n; i++) {
const char *t;
struct coll *coll = aCol[i].coll;
- struct field_def *field = &pTable->def->fields[i];
+ struct field_def *field = &def->fields[i];
const char *zToken = field->default_value;
int base_len = 4;
if (coll != NULL)
@@ -1521,6 +1523,9 @@ int tarantoolSqlite3MakeTableOpts(Table *pTable, const char *zSql, void *buf)
int tarantoolSqlite3MakeIdxParts(SqliteIndex *pIndex, void *buf)
{
struct Column *aCol = pIndex->pTable->aCol;
+ struct space_def *def = pIndex->pTable->def;
+ assert(def != NULL);
+
const struct Enc *enc = get_enc(buf);
struct SqliteIndex *primary_index;
char *base = buf, *p;
@@ -1532,7 +1537,7 @@ int tarantoolSqlite3MakeIdxParts(SqliteIndex *pIndex, void *buf)
* treat it as strict type, not affinity. */
if (primary_index->nColumn == 1) {
int pk = primary_index->aiColumn[0];
- if (aCol[pk].type == FIELD_TYPE_INTEGER)
+ if (def->fields[pk].type == FIELD_TYPE_INTEGER)
pk_forced_int = pk;
}
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index c712b46..584e6b1 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -685,7 +685,8 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
}
pCol = &p->aCol[p->def->field_count];
memset(pCol, 0, sizeof(p->aCol[0]));
- p->def->fields[p->def->field_count].name = z;
+ struct field_def *column_def = &p->def->fields[p->def->field_count];
+ column_def->name = z;
if (pType->n == 0) {
/* If there is no type specified, columns have the default affinity
* 'BLOB' and type SCALAR.
@@ -693,8 +694,8 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
* specified type, the code below should emit an error.
*/
pCol->affinity = SQLITE_AFF_BLOB;
- pCol->type = FIELD_TYPE_SCALAR;
pCol->szEst = 1;
+ column_def->type = FIELD_TYPE_SCALAR;
} else {
/* TODO: convert string of type into runtime
* FIELD_TYPE value for other types.
@@ -703,16 +704,16 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
pType->n == 7) ||
(sqlite3StrNICmp(pType->z, "INT", 3) == 0 &&
pType->n == 3)) {
- pCol->type = FIELD_TYPE_INTEGER;
pCol->affinity = SQLITE_AFF_INTEGER;
+ column_def->type = FIELD_TYPE_INTEGER;
} else {
zType = sqlite3_malloc(pType->n + 1);
memcpy(zType, pType->z, pType->n);
zType[pType->n] = 0;
sqlite3Dequote(zType);
pCol->affinity = sqlite3AffinityType(zType, 0);
- pCol->type = FIELD_TYPE_SCALAR;
sqlite3_free(zType);
+ column_def->type = FIELD_TYPE_SCALAR;
}
}
p->def->field_count++;
@@ -939,9 +940,10 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
}
}
}
+ assert(pCol == &pTab->aCol[iCol]);
if (nTerm == 1
&& pCol
- && (sqlite3ColumnType(pCol) == FIELD_TYPE_INTEGER)
+ && (pTab->def->fields[iCol].type == FIELD_TYPE_INTEGER)
&& sortOrder != SQLITE_SO_DESC) {
assert(autoInc == 0 || autoInc == 1);
pTab->iPKey = iCol;
diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c
index e93f377..0cf103c 100644
--- a/src/box/sql/pragma.c
+++ b/src/box/sql/pragma.c
@@ -381,13 +381,13 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */
space_cache_find(space_id);
char *expr_str = space->
def->fields[i].default_value;
+ const char *name =
+ pTab->def->fields[i].name;
+ enum field_type type =
+ pTab->def->fields[i].type;
sqlite3VdbeMultiLoad(v, 1, "issisi",
- i,
- pTab->def->fields[i].
- name,
- field_type_strs[
- sqlite3ColumnType
- (pCol)],
+ i, name,
+ field_type_strs[type],
nullable == 0,
expr_str, k);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1,
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index 1390c5d..9eeff8e 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -1664,12 +1664,12 @@ columnTypeImpl(NameContext * pNC, Expr * pExpr,
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);
+ zOrigCol = pTab->def->fields[iCol].name;
+ zType = pTab->def->fields[iCol].type;
estWidth = pTab->aCol[iCol].szEst;
zOrigTab = pTab->zName;
#else
- column_type = sqlite3ColumnType(&pTab->aCol[iCol]);
+ column_type = pTab->def->fields[iCol].type;
estWidth = pTab->aCol[iCol].szEst;
#endif
}
@@ -1937,7 +1937,7 @@ sqlite3SelectAddColumnTypeAndCollation(Parse * pParse, /* Parsing contexts */
type = columnType(&sNC, p, 0, 0, 0, &pCol->szEst);
szAll += pCol->szEst;
pCol->affinity = sqlite3ExprAffinity(p);
- pCol->type = type;
+ pTab->def->fields[i].type = type;
if (pCol->affinity == 0)
pCol->affinity = SQLITE_AFF_BLOB;
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 8e1c135..94d5c80 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -1867,7 +1867,6 @@ struct Savepoint {
* of this structure.
*/
struct Column {
- enum field_type type; /* Column type. */
/** Collating sequence. */
struct coll *coll;
/**
@@ -3388,7 +3387,6 @@ int sqlite3IoerrnomemError(int);
*/
int sqlite3StrICmp(const char *, const char *);
unsigned sqlite3Strlen30(const char *);
-enum field_type sqlite3ColumnType(Column *);
#define sqlite3StrNICmp sqlite3_strnicmp
void sqlite3MallocInit(void);
diff --git a/src/box/sql/util.c b/src/box/sql/util.c
index 8c4e7b9..401b215 100644
--- a/src/box/sql/util.c
+++ b/src/box/sql/util.c
@@ -130,15 +130,6 @@ sqlite3Strlen30(const char *z)
}
/*
- * Return the declared type of a column.
- */
-inline enum field_type
-sqlite3ColumnType(Column * pCol)
-{
- return pCol->type;
-}
-
-/*
* Helper function for sqlite3Error() - called rarely. Broken out into
* a separate routine to avoid unnecessary register saves on entry to
* sqlite3Error().
--
2.7.4
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] [PATCH v3 4/4] sql: Region-based allocations.
2018-04-25 16:52 [tarantool-patches] [PATCH v3 0/4] sql: Removed Column fields to server with region allocations Kirill Shcherbatov
` (2 preceding siblings ...)
2018-04-25 16:52 ` [tarantool-patches] [PATCH v3 3/4] sql: Removed type " Kirill Shcherbatov
@ 2018-04-25 16:52 ` Kirill Shcherbatov
2018-04-26 11:47 ` [tarantool-patches] " Vladislav Shpilevoy
2018-04-26 11:47 ` [tarantool-patches] Re: [PATCH v3 0/4] sql: Removed Column fields to server with region allocations Vladislav Shpilevoy
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 0/7] sql: refactor SQL Parser structures Kirill Shcherbatov
5 siblings, 1 reply; 26+ messages in thread
From: Kirill Shcherbatov @ 2018-04-25 16:52 UTC (permalink / raw)
To: tarantool-patches; +Cc: v.shpilevoy, Kirill Shcherbatov
Function sql_field_retrieve could leak names
in error cases. Let allocate all memory with
region allocator.
Needed for #3272.
---
src/box/sql.c | 44 +++++++++++++++++++++++++++++++-------------
src/box/sql.h | 9 +++++++++
src/box/sql/build.c | 37 ++++++++++++++++++++++++-------------
src/box/sql/prepare.c | 26 ++++++++++++++++----------
src/box/sql/select.c | 24 +++++++++++++++++++++---
src/box/sql/sqliteInt.h | 2 ++
src/box/sql/tokenize.c | 3 +++
src/box/sql/trigger.c | 2 ++
8 files changed, 108 insertions(+), 39 deletions(-)
diff --git a/src/box/sql.c b/src/box/sql.c
index 6d4255e..2893d70 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -1685,22 +1685,43 @@ space_column_default_expr(uint32_t space_id, uint32_t fieldno)
return space->def->fields[fieldno].default_value_expr;
}
+struct space_def *
+sql_ephemeral_space_def_new(Parse *parser)
+{
+ struct space_def *def = NULL;
+ struct region *region = &fiber()->gc;
+ size_t size = sizeof(struct space_def) + 1;
+ def = (struct space_def *)region_alloc(region, size);
+ if (def != NULL) {
+ memset(def, 0, size);
+ def->dict =
+ (struct tuple_dictionary *)
+ region_alloc(region,
+ sizeof(struct tuple_dictionary));
+ }
+ if (def == NULL || def->dict == NULL) {
+ parser->rc = SQLITE_NOMEM_BKPT;
+ parser->nErr++;
+ return NULL;
+ }
+ def->dict->refs = 1;
+ def->opts.temporary = true;
+ return def;
+}
+
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 (table != NULL)
+ def = sql_ephemeral_space_def_new(parser);
if (def == NULL) {
sqlite3DbFree(db, table);
- parser->rc = SQLITE_NOMEM_BKPT;
- parser->nErr++;
return NULL;
}
+
table->def = def;
return table;
}
@@ -1708,6 +1729,9 @@ sql_ephemeral_table_new(Parse *parser)
int
sql_table_def_rebuild(struct sqlite3 *db, struct Table *pTable)
{
+ assert(pTable->def->opts.temporary == true);
+
+ /* All allocations are on region. */
struct space_def *old_def = pTable->def;
struct space_def *new_def = NULL;
new_def = space_def_new(old_def->id, old_def->uid,
@@ -1719,13 +1743,7 @@ sql_table_def_rebuild(struct sqlite3 *db, struct Table *pTable)
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;
+ pTable->def->opts.temporary = false;
return 0;
}
diff --git a/src/box/sql.h b/src/box/sql.h
index 9fb3ad1..410653b 100644
--- a/src/box/sql.h
+++ b/src/box/sql.h
@@ -155,6 +155,15 @@ struct Table *
sql_ephemeral_table_new(struct Parse *parser);
/**
+ * Create and initialize a new ephemeric space_def object.
+ * @param pParse SQL Parser object.
+ * @retval NULL on memory allocation error, Parser state changed.
+ * @retval not NULL on success.
+ */
+struct space_def *
+sql_ephemeral_space_def_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.
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 584e6b1..4db4356 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -386,7 +386,9 @@ deleteTable(sqlite3 * db, Table * pTable)
sqlite3DbFree(db, pTable->zColAff);
sqlite3SelectDelete(db, pTable->pSelect);
sqlite3ExprListDelete(db, pTable->pCheck);
- if (pTable->def != NULL)
+ /* Do not delete pTable->def allocated not on region. */
+ assert(pTable->def != NULL);
+ if (pTable->def->opts.temporary == false)
space_def_delete(pTable->def);
sqlite3DbFree(db, pTable);
@@ -483,6 +485,7 @@ sqlite3PrimaryKeyIndex(Table * pTab)
/**
* Create and initialize a new SQL Table object.
+ * All memory is allocated on region.
* @param parser SQL Parser object.
* @param name Table to create name.
* @retval NULL on memory allocation error.
@@ -603,29 +606,33 @@ sqlite3StartTable(Parse *pParse, Token *pName, int noErr)
static struct field_def *
sql_field_retrieve(Parse *parser, Table *table, uint32_t id)
{
- sqlite3 *db = parser->db;
struct field_def *field;
assert(table->def != NULL);
assert(id < SQLITE_MAX_COLUMN);
if (id >= table->def->exact_field_count) {
- uint32_t columns = table->def->exact_field_count;
- columns = (columns > 0) ? 2 * columns : 1;
- field = sqlite3DbRealloc(db, table->def->fields,
- columns * sizeof(table->def->fields[0]));
+ uint32_t columns_new = table->def->exact_field_count;
+ columns_new = (columns_new > 0) ? 2 * columns_new : 1;
+ struct region *region = &fiber()->gc;
+ field = region_alloc(region,
+ columns_new * sizeof(table->def->fields[0]));
if (field == NULL) {
parser->rc = SQLITE_NOMEM_BKPT;
parser->nErr++;
return NULL;
}
- for (uint32_t i = columns / 2; i < columns; i++) {
+ for (uint32_t i = 0; i < table->def->exact_field_count; i++) {
+ memcpy(&field[i], &table->def->fields[i],
+ sizeof(struct field_def));
+ }
+ for (uint32_t i = columns_new / 2; i < columns_new; i++) {
memcpy(&field[i], &field_def_default,
sizeof(struct field_def));
}
table->def->fields = field;
- table->def->exact_field_count = columns;
+ table->def->exact_field_count = columns_new;
}
field = &table->def->fields[id];
@@ -651,6 +658,7 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
sqlite3 *db = pParse->db;
if ((p = pParse->pNewTable) == 0)
return;
+ assert(p->def->opts.temporary == true);
#if SQLITE_MAX_COLUMN
if ((int)p->def->field_count + 1 > db->aLimit[SQLITE_LIMIT_COLUMN]) {
sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName);
@@ -659,7 +667,8 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
#endif
if (sql_field_retrieve(pParse, p, (uint32_t) p->def->field_count) == NULL)
return;
- z = sqlite3DbMallocRaw(db, pName->n + 1);
+ struct region *region = &fiber()->gc;
+ z = region_alloc(region, pName->n + 1);
if (z == 0)
return;
memcpy(z, pName->z, pName->n);
@@ -668,7 +677,6 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
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;
}
}
@@ -677,10 +685,8 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
aNew =
sqlite3DbRealloc(db, p->aCol,
(p->def->field_count + 8) * sizeof(p->aCol[0]));
- if (aNew == 0) {
- sqlite3DbFree(db, z);
+ if (aNew == 0)
return;
- }
p->aCol = aNew;
}
pCol = &p->aCol[p->def->field_count];
@@ -848,6 +854,7 @@ sqlite3AddDefaultValue(Parse * pParse, ExprSpan * pSpan)
Table *p;
sqlite3 *db = pParse->db;
p = pParse->pNewTable;
+ assert(p->def->opts.temporary == true);
if (p != 0) {
if (!sqlite3ExprIsConstantOrFunction
(pSpan->pExpr, db->init.busy)) {
@@ -1956,6 +1963,7 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
if (db->init.busy) {
Table *pOld;
Schema *pSchema = p->pSchema;
+ assert(p->def->opts.temporary == false);
pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p);
if (pOld) {
assert(p == pOld); /* Malloc must have failed inside HashInsert() */
@@ -2127,6 +2135,7 @@ sqlite3ViewGetColumnNames(Parse * pParse, Table * pTable)
pSel);
}
} else if (pSelTab) {
+ assert(pTable->def->opts.temporary == false);
/* CREATE VIEW name AS... without an argument list. Construct
* the column names from the SELECT statement that defines the view.
*/
@@ -2167,6 +2176,8 @@ sqliteViewResetAll(sqlite3 * db)
if (pTab->pSelect) {
sqlite3DeleteColumnNames(db, pTab);
struct space_def *old_def = pTab->def;
+ assert(old_def->opts.temporary == false);
+ /* Ignore fields allocated on region */
pTab->def = space_def_new(old_def->id, old_def->uid,
0,
old_def->name,
diff --git a/src/box/sql/prepare.c b/src/box/sql/prepare.c
index 2ab8751..7dc14f6 100644
--- a/src/box/sql/prepare.c
+++ b/src/box/sql/prepare.c
@@ -211,17 +211,19 @@ sqlite3InitDatabase(sqlite3 * db)
void
sqlite3ParserReset(Parse * pParse)
{
- if (pParse) {
- sqlite3 *db = pParse->db;
- sqlite3DbFree(db, pParse->aLabel);
- sqlite3ExprListDelete(db, pParse->pConstExpr);
- if (db) {
- assert(db->lookaside.bDisable >=
- pParse->disableLookaside);
- db->lookaside.bDisable -= pParse->disableLookaside;
- }
- pParse->disableLookaside = 0;
+ if (pParse == NULL)
+ return;
+ sqlite3 *db = pParse->db;
+ sqlite3DbFree(db, pParse->aLabel);
+ sqlite3ExprListDelete(db, pParse->pConstExpr);
+ if (db) {
+ assert(db->lookaside.bDisable >=
+ pParse->disableLookaside);
+ db->lookaside.bDisable -= pParse->disableLookaside;
}
+ pParse->disableLookaside = 0;
+ struct region *region = &fiber()->gc;
+ region_truncate(region, pParse->region_initial_size);
}
/*
@@ -265,6 +267,10 @@ sqlite3Prepare(sqlite3 * db, /* Database handle. */
* works even if READ_UNCOMMITTED is set.
*/
sParse.db = db;
+ /* Store region initial size to revert future allocations */
+ struct region *region = &fiber()->gc;
+ sParse.region_initial_size = region_used(region);
+
if (nBytes >= 0 && (nBytes == 0 || zSql[nBytes - 1] != 0)) {
char *zSqlCopy;
int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index 9eeff8e..03bfcf9 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -1822,9 +1822,20 @@ sqlite3ColumnsFromExprList(Parse * pParse, /* Parsing context */
aCol = 0;
}
assert(nCol == (i16) nCol);
+
+ struct region *region = &fiber()->gc;
assert(pTable->def->fields == NULL);
+ if (pTable->def->opts.temporary == false) {
+ /* CREATE VIEW name AS... without an argument list. Construct
+ * the column names from the SELECT statement that defines the view.
+ */
+ pTable->def->field_count = 0;
+ space_def_delete(pTable->def);
+ pTable->def = sql_ephemeral_space_def_new(pParse);
+ }
pTable->def->fields =
- sqlite3DbMallocZero(db, nCol*sizeof(pTable->def->fields[0]));
+ region_alloc(region, nCol*sizeof(pTable->def->fields[0]));
+ memset(pTable->def->fields, 0, nCol*sizeof(pTable->def->fields[0]));
pTable->def->field_count = (uint32_t)nCol;
pTable->aCol = aCol;
@@ -1877,9 +1888,16 @@ sqlite3ColumnsFromExprList(Parse * pParse, /* Parsing context */
if (cnt > 3)
sqlite3_randomness(sizeof(cnt), &cnt);
}
- pTable->def->fields[i].name = zName;
- if (zName && sqlite3HashInsert(&ht, zName, pCol) == pCol) {
+ uint32_t zNameLen = (uint32_t)strlen(zName);
+ if (zName && sqlite3HashInsert(&ht, zName, pCol) == pCol)
+ sqlite3OomFault(db);
+ pTable->def->fields[i].name =
+ region_alloc(region, zNameLen + 1);
+ if (pTable->def->fields[i].name == NULL) {
sqlite3OomFault(db);
+ } else {
+ memcpy(pTable->def->fields[i].name, zName, zNameLen);
+ pTable->def->fields[i].name[zNameLen] = '\0';
}
}
sqlite3HashClear(&ht);
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 94d5c80..520b74c 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -2933,6 +2933,8 @@ struct Parse {
u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
u8 disableTriggers; /* True to disable triggers */
+ /** Region size at the Parser launch */
+ size_t region_initial_size;
/**************************************************************************
* Fields above must be initialized to zero. The fields that follow,
diff --git a/src/box/sql/tokenize.c b/src/box/sql/tokenize.c
index c77aa9b..9055bd0 100644
--- a/src/box/sql/tokenize.c
+++ b/src/box/sql/tokenize.c
@@ -664,6 +664,9 @@ sql_expr_compile(sqlite3 *db, const char *expr, struct Expr **result)
memset(&parser, 0, sizeof(parser));
parser.db = db;
parser.parse_only = true;
+ struct region *region = &fiber()->gc;
+ parser.region_initial_size = region_used(region);
+
char *unused;
if (sqlite3RunParser(&parser, stmt, &unused) != SQLITE_OK) {
diag_set(ClientError, ER_SQL_EXECUTE, expr);
diff --git a/src/box/sql/trigger.c b/src/box/sql/trigger.c
index 28c56db..9b03be1 100644
--- a/src/box/sql/trigger.c
+++ b/src/box/sql/trigger.c
@@ -873,6 +873,8 @@ codeRowTrigger(Parse * pParse, /* Current parse context */
pSubParse->pToplevel = pTop;
pSubParse->eTriggerOp = pTrigger->op;
pSubParse->nQueryLoop = pParse->nQueryLoop;
+ struct region *region = &fiber()->gc;
+ pSubParse->region_initial_size = region_used(region);
v = sqlite3GetVdbe(pSubParse);
if (v) {
--
2.7.4
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] Re: [PATCH v3 2/4] sql: Remove zName and nColumn from SQL.
2018-04-25 16:52 ` [tarantool-patches] [PATCH v3 2/4] sql: Remove zName and nColumn from SQL Kirill Shcherbatov
@ 2018-04-25 17:10 ` Kirill Shcherbatov
2018-04-26 12:12 ` Vladislav Shpilevoy
2018-04-26 11:47 ` Vladislav Shpilevoy
1 sibling, 1 reply; 26+ messages in thread
From: Kirill Shcherbatov @ 2018-04-25 17:10 UTC (permalink / raw)
To: tarantool-patches; +Cc: v.shpilevoy
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);
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] Re: [PATCH v3 0/4] sql: Removed Column fields to server with region allocations
2018-04-25 16:52 [tarantool-patches] [PATCH v3 0/4] sql: Removed Column fields to server with region allocations Kirill Shcherbatov
` (3 preceding siblings ...)
2018-04-25 16:52 ` [tarantool-patches] [PATCH v3 4/4] sql: Region-based allocations Kirill Shcherbatov
@ 2018-04-26 11:47 ` Vladislav Shpilevoy
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 0/7] sql: refactor SQL Parser structures Kirill Shcherbatov
5 siblings, 0 replies; 26+ messages in thread
From: Vladislav Shpilevoy @ 2018-04-26 11:47 UTC (permalink / raw)
To: Kirill Shcherbatov, tarantool-patches
Hello. Thanks for contributing! See below my 1 comment.
On 25/04/2018 19:52, Kirill Shcherbatov wrote:
> Branch: http://github.com/tarantool/tarantool/tree/gh-3272-no-sql-names
> Issue: https://github.com/tarantool/tarantool/issues/3272
Please, provide a description of the patchset.
>
> Kirill Shcherbatov (4):
> sql: Fix code style in sqlite3Pragma.
> sql: Remove zName and nColumn from SQL.
> sql: Removed type from SQL.
> sql: Region-based allocations.
>
> src/box/space_def.c | 29 ++++---
> src/box/sql.c | 90 ++++++++++++++++---
> src/box/sql.h | 32 +++++++
> src/box/sql/alter.c | 32 ++++---
> src/box/sql/analyze.c | 5 +-
> src/box/sql/build.c | 226 +++++++++++++++++++++++-------------------------
> 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 | 84 +++++++++---------
> src/box/sql/prepare.c | 26 +++---
> src/box/sql/resolve.c | 16 ++--
> src/box/sql/select.c | 120 ++++++++++++++-----------
> src/box/sql/sqliteInt.h | 8 +-
> src/box/sql/tokenize.c | 3 +
> src/box/sql/trigger.c | 2 +
> src/box/sql/update.c | 29 ++++---
> src/box/sql/util.c | 9 --
> src/box/sql/where.c | 6 +-
> src/box/sql/wherecode.c | 2 +-
> src/box/sql/whereexpr.c | 4 +-
> 22 files changed, 477 insertions(+), 338 deletions(-)
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] Re: [PATCH v3 1/4] sql: Fix code style in sqlite3Pragma.
2018-04-25 16:52 ` [tarantool-patches] [PATCH v3 1/4] sql: Fix code style in sqlite3Pragma Kirill Shcherbatov
@ 2018-04-26 11:47 ` Vladislav Shpilevoy
0 siblings, 0 replies; 26+ messages in thread
From: Vladislav Shpilevoy @ 2018-04-26 11:47 UTC (permalink / raw)
To: Kirill Shcherbatov, tarantool-patches
Hello. Please, do not start a commit message from a capital letter, and do
not put dot at the end. Read this:
https://tarantool.io/en/doc/1.9/dev_guide/developer_guidelines.html#how-to-write-a-commit-message
Fix this in other commits too.
See below 1 comment.
On 25/04/2018 19:52, Kirill Shcherbatov wrote:
> ---
> src/box/sql/pragma.c | 56 +++++++++++++++++++++++++---------------------------
> 1 file changed, 27 insertions(+), 29 deletions(-)
>
> diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c
> index e41f69b..4a68cad 100644
> --- a/src/box/sql/pragma.c
> +++ b/src/box/sql/pragma.c
> @@ -544,37 +544,35 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */
>
> #ifndef SQLITE_OMIT_FOREIGN_KEY
> case PragTyp_FOREIGN_KEY_LIST:{
> - if (zRight) {
> - FKey *pFK;
> - Table *pTab;
> - pTab = sqlite3HashFind(&db->pSchema->tblHash,
> - zRight);
> - if (pTab != NULL) {
> - pFK = pTab->pFKey;
> - if (pFK) {
> - int i = 0;
> - pParse->nMem = 8;
> - while (pFK) {
> - int j;
> - for (j = 0;
> - j < pFK->nCol;
> - j++) {
> - sqlite3VdbeMultiLoad(v, 1, "iissssss", i, j, pFK->zTo, pTab->aCol[pFK->aCol[j].iFrom].zName, pFK->aCol[j].zCol, actionName(pFK->aAction[1]), /* ON UPDATE */
> - actionName(pFK->aAction[0]), /* ON DELETE */
> - "NONE");
> - sqlite3VdbeAddOp2
> - (v,
> - OP_ResultRow,
> - 1, 8);
> - }
> - ++i;
> - pFK = pFK->pNextFrom;
> - }
> - }
> - }
> - }
> + if (!zRight)
1. Please, use explicit == NULL. Same in other places.
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] Re: [PATCH v3 2/4] sql: Remove zName and nColumn from SQL.
2018-04-25 16:52 ` [tarantool-patches] [PATCH v3 2/4] sql: Remove zName and nColumn from SQL Kirill Shcherbatov
2018-04-25 17:10 ` [tarantool-patches] " Kirill Shcherbatov
@ 2018-04-26 11:47 ` Vladislav Shpilevoy
1 sibling, 0 replies; 26+ messages in thread
From: Vladislav Shpilevoy @ 2018-04-26 11:47 UTC (permalink / raw)
To: Kirill Shcherbatov, tarantool-patches
Hello. See my comment about the smaller version of this commit.
I can not see the new version on the branch, so I am reviewing
this one.
See my 8 comments below about the first part of the patch. Next part
I will review, when you push actual version.
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
1. Collect fragmented what, field_def? If so, the it would be good
to write it explicitly.
> 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
>
> @@ -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);
2. Garbage diff. You just wrap &expr_pos on the new line, but it fits in one
line with sql_expr_dup.
> @@ -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);
3. Same as 2. Please, before sending a patch make a self-review. It really
helps, I do it too, even for review letters, that I am sending now. During
self-review you can catch and remove such things with no waiting until I
found it myself.
> 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
> @@ -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;
> + }
4. Table can be NULL, and def not NULL - it leads to crash. And why you do not
call sqlite3OomFault(db); here?
> 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.
5. As I said in the previous reviews, 'ephemeric' word does not mean
'эфемерный'. Use ephemeral.
> + * @param pParse SQL Parser object.
> + * @param zName Table to create name.
6. I do not see zName parameter here.
> + * @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
7. Please, return -1 on errors.
> 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);
8. We have 'unreachable()' macro for this.
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] Re: [PATCH v3 4/4] sql: Region-based allocations.
2018-04-25 16:52 ` [tarantool-patches] [PATCH v3 4/4] sql: Region-based allocations Kirill Shcherbatov
@ 2018-04-26 11:47 ` Vladislav Shpilevoy
0 siblings, 0 replies; 26+ messages in thread
From: Vladislav Shpilevoy @ 2018-04-26 11:47 UTC (permalink / raw)
To: Kirill Shcherbatov, tarantool-patches
Hello. Thanks for contributing! See below 16 comments.
On 25/04/2018 19:52, Kirill Shcherbatov wrote:
> Function sql_field_retrieve could leak names
> in error cases. Let allocate all memory with
> region allocator.
>
> Needed for #3272.
1. It is not only 3272. It is a part of the separate region
allocations issue. I do not remember the number, please, find and
write here 'Part of #nnnn#' on new line.
> diff --git a/src/box/sql.c b/src/box/sql.c
> index 6d4255e..2893d70 100644
> --- a/src/box/sql.c
> +++ b/src/box/sql.c
> @@ -1685,22 +1685,43 @@ space_column_default_expr(uint32_t space_id, uint32_t fieldno)
> return space->def->fields[fieldno].default_value_expr;
> }
>
> +struct space_def *
> +sql_ephemeral_space_def_new(Parse *parser)
> +{
> + struct space_def *def = NULL;
> + struct region *region = &fiber()->gc;
> + size_t size = sizeof(struct space_def) + 1;
> + def = (struct space_def *)region_alloc(region, size);
> + if (def != NULL) {
> + memset(def, 0, size);
> + def->dict =
> + (struct tuple_dictionary *)
> + region_alloc(region,
> + sizeof(struct tuple_dictionary));
2. Why do you need a dictionary? It must not be used in SQL anywhere. And
please, do not mess checks on allocations error - try to check it right after
allocation. It is hard to review code, where after alloc its result is checked
multiple times on ==/!= NULL. If you have multiple allocations, and after fail of
each one you must destroy some results of the previous ones, or set some error
codes, you can use this way:
if (alloc1_failed)
goto error1;
...
if (alloc2_failed)
goto error2;
...
error3:
do_clean3...
error2:
do_clean2...
error1:
do_clean1...
return -1;
See the good example in vy_lsm_new() function.
> + }
> + if (def == NULL || def->dict == NULL) {
> + parser->rc = SQLITE_NOMEM_BKPT;
> + parser->nErr++;
> + return NULL;
> + }
> + def->dict->refs = 1;
> + def->opts.temporary = true;
> + return def;
> +}
> +
> 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 (table != NULL)
> + def = sql_ephemeral_space_def_new(parser);
> if (def == NULL) {
> sqlite3DbFree(db, table);
> - parser->rc = SQLITE_NOMEM_BKPT;
> - parser->nErr++;
3. Why did you remove it? Region allocation error is the same, as
malloc allocation error. See details in 6.
> return NULL;
> }
> +
4. Garbage diff.
> diff --git a/src/box/sql/build.c b/src/box/sql/build.c
> index 584e6b1..4db4356 100644
> --- a/src/box/sql/build.c
> +++ b/src/box/sql/build.c
> @@ -386,7 +386,9 @@ deleteTable(sqlite3 * db, Table * pTable)
> sqlite3DbFree(db, pTable->zColAff);
> sqlite3SelectDelete(db, pTable->pSelect);
> sqlite3ExprListDelete(db, pTable->pCheck);
> - if (pTable->def != NULL)
> + /* Do not delete pTable->def allocated not on region. */
> + assert(pTable->def != NULL);
> + if (pTable->def->opts.temporary == false)
5. Boolean variables checking on true/false can be omitted.
> @@ -603,29 +606,33 @@ sqlite3StartTable(Parse *pParse, Token *pName, int noErr)
> static struct field_def *
> sql_field_retrieve(Parse *parser, Table *table, uint32_t id)
> {
> - sqlite3 *db = parser->db;
> struct field_def *field;
> assert(table->def != NULL);
> assert(id < SQLITE_MAX_COLUMN);
>
> if (id >= table->def->exact_field_count) {
> - uint32_t columns = table->def->exact_field_count;
> - columns = (columns > 0) ? 2 * columns : 1;
> - field = sqlite3DbRealloc(db, table->def->fields,
> - columns * sizeof(table->def->fields[0]));
> + uint32_t columns_new = table->def->exact_field_count;
> + columns_new = (columns_new > 0) ? 2 * columns_new : 1;
> + struct region *region = &fiber()->gc;
> + field = region_alloc(region,
> + columns_new * sizeof(table->def->fields[0]))
6. On region error please do diag_set error. Region error is Tarantool error, not
sqlite. And on such error you must return not SQLITE_NOMEM_BKPT, but
SQL_TARANTOOL_ERROR. It leads to returning to a user an error, that is set in diag.
> if (field == NULL) {
> parser->rc = SQLITE_NOMEM_BKPT;
> parser->nErr++;
> return NULL;
> }
>
> - for (uint32_t i = columns / 2; i < columns; i++) {
> + for (uint32_t i = 0; i < table->def->exact_field_count; i++) {
> + memcpy(&field[i], &table->def->fields[i],
> + sizeof(struct field_def));
> + }
7. It would be good to note here, that field names are not on the same
region allocation, and it is ok to memcpy pointers on them.
> + for (uint32_t i = columns_new / 2; i < columns_new; i++) {
> memcpy(&field[i], &field_def_default,
> sizeof(struct field_def));
> }
>
> table->def->fields = field;
> - table->def->exact_field_count = columns;
> + table->def->exact_field_count = columns_new;
8. This diff, and other columns->columns_new diff are garbage. Why did you
rename it? The previous name was ok.
> @@ -677,10 +685,8 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
> aNew =
> sqlite3DbRealloc(db, p->aCol,
> (p->def->field_count + 8) * sizeof(p->aCol[0]));
> - if (aNew == 0) {
> - sqlite3DbFree(db, z);
> + if (aNew == 0)
> return;
9. Please, use == NULL for pointers. I see, that it is left from the original
code, but if you modify it, then use Tarantool code style in the new code please.
> diff --git a/src/box/sql/prepare.c b/src/box/sql/prepare.c
> index 2ab8751..7dc14f6 100644
> --- a/src/box/sql/prepare.c
> +++ b/src/box/sql/prepare.c
> @@ -211,17 +211,19 @@ sqlite3InitDatabase(sqlite3 * db)
> void
> sqlite3ParserReset(Parse * pParse)
> {
> - if (pParse) {
> - sqlite3 *db = pParse->db;
> - sqlite3DbFree(db, pParse->aLabel);
> - sqlite3ExprListDelete(db, pParse->pConstExpr);
> - if (db) {
> - assert(db->lookaside.bDisable >=
> - pParse->disableLookaside);
> - db->lookaside.bDisable -= pParse->disableLookaside;
> - }
> - pParse->disableLookaside = 0;
> + if (pParse == NULL)
> + return;
> + sqlite3 *db = pParse->db;
> + sqlite3DbFree(db, pParse->aLabel);
> + sqlite3ExprListDelete(db, pParse->pConstExpr);
> + if (db) {
10. Same as 9.
> diff --git a/src/box/sql/select.c b/src/box/sql/select.c
> index 9eeff8e..03bfcf9 100644
> --- a/src/box/sql/select.c
> +++ b/src/box/sql/select.c
> @@ -1822,9 +1822,20 @@ sqlite3ColumnsFromExprList(Parse * pParse, /* Parsing context */
> aCol = 0;
> }
> assert(nCol == (i16) nCol);
> +
> + struct region *region = &fiber()->gc;
> assert(pTable->def->fields == NULL);
> + if (pTable->def->opts.temporary == false) {
11. At first, same as 5. At second, why? I can not see this in the original code.
> @@ -1877,9 +1888,16 @@ sqlite3ColumnsFromExprList(Parse * pParse, /* Parsing context */
> if (cnt > 3)
> sqlite3_randomness(sizeof(cnt), &cnt);
> }
> - pTable->def->fields[i].name = zName;
> - if (zName && sqlite3HashInsert(&ht, zName, pCol) == pCol) {
> + uint32_t zNameLen = (uint32_t)strlen(zName);
12. For new code please use Tarantool code style - no Camel case.
zNameLen -> name_len.
> + if (zName && sqlite3HashInsert(&ht, zName, pCol) == pCol)
13. Same as 9.
> diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
> index 94d5c80..520b74c 100644
> --- a/src/box/sql/sqliteInt.h
> +++ b/src/box/sql/sqliteInt.h
> @@ -2933,6 +2933,8 @@ struct Parse {
> u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
> u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
> u8 disableTriggers; /* True to disable triggers */
> + /** Region size at the Parser launch */
14. Please, put a dot at the end of the comment.
> diff --git a/src/box/sql/tokenize.c b/src/box/sql/tokenize.c
> index c77aa9b..9055bd0 100644
> --- a/src/box/sql/tokenize.c
> +++ b/src/box/sql/tokenize.c
> @@ -664,6 +664,9 @@ sql_expr_compile(sqlite3 *db, const char *expr, struct Expr **result)
> memset(&parser, 0, sizeof(parser));
> parser.db = db;
> parser.parse_only = true;
> + struct region *region = &fiber()->gc;
> + parser.region_initial_size = region_used(region);
15. It is a second place, where a parser is created. How about creating a function
sql_parser_create(struct Parser *parser), that will do this?
16. I do not see, that you removed def rebuilding from sqlite3ColumnsFromExprList -
it is not needed anymore.
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] Re: [PATCH v3 2/4] sql: Remove zName and nColumn from SQL.
2018-04-25 17:10 ` [tarantool-patches] " Kirill Shcherbatov
@ 2018-04-26 12:12 ` Vladislav Shpilevoy
0 siblings, 0 replies; 26+ messages in thread
From: Vladislav Shpilevoy @ 2018-04-26 12:12 UTC (permalink / raw)
To: Kirill Shcherbatov, tarantool-patches
Hello. Look like you did not push the new commit. On the branch
it still is huge, not src/box/sql/build.c | 12 ++++--------.
On 25/04/2018 20:10, Kirill Shcherbatov wrote:
> I've included some extra changes in this commit. Fixed.
>
> ---
> src/box/sql/build.c | 12 ++++--------
> 1 file changed, 4 insertions(+), 8 deletions(-)
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] [PATCH v4 0/7] sql: refactor SQL Parser structures
2018-04-25 16:52 [tarantool-patches] [PATCH v3 0/4] sql: Removed Column fields to server with region allocations Kirill Shcherbatov
` (4 preceding siblings ...)
2018-04-26 11:47 ` [tarantool-patches] Re: [PATCH v3 0/4] sql: Removed Column fields to server with region allocations Vladislav Shpilevoy
@ 2018-04-28 18:26 ` Kirill Shcherbatov
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 1/7] sql: fix code style in sqlite3Pragma Kirill Shcherbatov
` (7 more replies)
5 siblings, 8 replies; 26+ messages in thread
From: Kirill Shcherbatov @ 2018-04-28 18:26 UTC (permalink / raw)
To: tarantool-patches; +Cc: v.shpilevoy, Kirill Shcherbatov
Branch: http://github.com/tarantool/tarantool/tree/gh-3272-no-sql-names
Issue: https://github.com/tarantool/tarantool/issues/3272
Kirill Shcherbatov (7):
sql: fix code style in sqlite3Pragma
sql: remove zName and nColumn from SQL
sql: start using type from space_def
sql: start using collations and is_nullable from space_def
sql: move names to server
sql: start using is_view field from space_def
sql: space_def* instead of Table* in Expr
src/box/field_def.c | 1 +
src/box/field_def.h | 5 +
src/box/space_def.c | 29 ++--
src/box/sql.c | 156 +++++++++++++++++----
src/box/sql.h | 32 +++++
src/box/sql/alter.c | 54 ++++---
src/box/sql/analyze.c | 16 ++-
src/box/sql/build.c | 364 ++++++++++++++++++++++++++----------------------
src/box/sql/delete.c | 25 ++--
src/box/sql/expr.c | 65 +++++----
src/box/sql/fkey.c | 51 ++++---
src/box/sql/hash.c | 5 +-
src/box/sql/insert.c | 88 ++++++------
src/box/sql/pragma.c | 96 +++++++------
src/box/sql/prepare.c | 26 ++--
src/box/sql/resolve.c | 33 +++--
src/box/sql/select.c | 185 +++++++++++++-----------
src/box/sql/sqliteInt.h | 37 ++---
src/box/sql/tokenize.c | 3 +
src/box/sql/treeview.c | 2 +-
src/box/sql/trigger.c | 6 +-
src/box/sql/update.c | 52 +++----
src/box/sql/util.c | 9 --
src/box/sql/vdbe.c | 2 +-
src/box/sql/vdbeaux.c | 19 ++-
src/box/sql/where.c | 24 ++--
src/box/sql/wherecode.c | 23 +--
src/box/sql/whereexpr.c | 8 +-
28 files changed, 831 insertions(+), 585 deletions(-)
--
2.7.4
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] [PATCH v4 1/7] sql: fix code style in sqlite3Pragma
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 0/7] sql: refactor SQL Parser structures Kirill Shcherbatov
@ 2018-04-28 18:26 ` Kirill Shcherbatov
2018-05-03 10:10 ` [tarantool-patches] " Vladislav Shpilevoy
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 2/7] sql: remove zName and nColumn from SQL Kirill Shcherbatov
` (6 subsequent siblings)
7 siblings, 1 reply; 26+ messages in thread
From: Kirill Shcherbatov @ 2018-04-28 18:26 UTC (permalink / raw)
To: tarantool-patches; +Cc: v.shpilevoy, Kirill Shcherbatov
---
src/box/sql/pragma.c | 56 +++++++++++++++++++++++++---------------------------
1 file changed, 27 insertions(+), 29 deletions(-)
diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c
index e41f69b..4a68cad 100644
--- a/src/box/sql/pragma.c
+++ b/src/box/sql/pragma.c
@@ -544,37 +544,35 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */
#ifndef SQLITE_OMIT_FOREIGN_KEY
case PragTyp_FOREIGN_KEY_LIST:{
- if (zRight) {
- FKey *pFK;
- Table *pTab;
- pTab = sqlite3HashFind(&db->pSchema->tblHash,
- zRight);
- if (pTab != NULL) {
- pFK = pTab->pFKey;
- if (pFK) {
- int i = 0;
- pParse->nMem = 8;
- while (pFK) {
- int j;
- for (j = 0;
- j < pFK->nCol;
- j++) {
- sqlite3VdbeMultiLoad(v, 1, "iissssss", i, j, pFK->zTo, pTab->aCol[pFK->aCol[j].iFrom].zName, pFK->aCol[j].zCol, actionName(pFK->aAction[1]), /* ON UPDATE */
- actionName(pFK->aAction[0]), /* ON DELETE */
- "NONE");
- sqlite3VdbeAddOp2
- (v,
- OP_ResultRow,
- 1, 8);
- }
- ++i;
- pFK = pFK->pNextFrom;
- }
- }
- }
- }
+ if (!zRight)
+ break;
+ FKey *pFK;
+ Table *pTab;
+ pTab = sqlite3HashFind(&db->pSchema->tblHash, zRight);
+ if (pTab == NULL)
break;
+ pFK = pTab->pFKey;
+ if (!pFK)
+ break;
+ int i = 0;
+ pParse->nMem = 8;
+ while (pFK) {
+ for (int j = 0; j < pFK->nCol; j++) {
+ const char *name =
+ pTab->aCol[pFK->aCol[j].iFrom].zName;
+ sqlite3VdbeMultiLoad(v, 1, "iissssss", i, j,
+ pFK->zTo, name,
+ pFK->aCol[j].zCol,
+ actionName(pFK->aAction[1]),
+ actionName(pFK->aAction[0]),
+ "NONE");
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 8);
+ }
+ ++i;
+ pFK = pFK->pNextFrom;
}
+ break;
+ }
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
#ifndef SQLITE_OMIT_FOREIGN_KEY
--
2.7.4
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] [PATCH v4 2/7] sql: remove zName and nColumn from SQL
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 0/7] sql: refactor SQL Parser structures Kirill Shcherbatov
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 1/7] sql: fix code style in sqlite3Pragma Kirill Shcherbatov
@ 2018-04-28 18:26 ` Kirill Shcherbatov
2018-05-03 10:10 ` [tarantool-patches] " Vladislav Shpilevoy
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 3/7] sql: start using type from space_def Kirill Shcherbatov
` (5 subsequent siblings)
7 siblings, 1 reply; 26+ messages in thread
From: Kirill Shcherbatov @ 2018-04-28 18:26 UTC (permalink / raw)
To: tarantool-patches; +Cc: v.shpilevoy, Kirill Shcherbatov
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.
Part of #3272.
---
src/box/space_def.c | 29 ++++---
src/box/sql.c | 79 +++++++++++++++--
src/box/sql.h | 32 +++++++
src/box/sql/alter.c | 32 ++++---
src/box/sql/analyze.c | 5 +-
src/box/sql/build.c | 221 +++++++++++++++++++++++-------------------------
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/prepare.c | 26 +++---
src/box/sql/resolve.c | 16 ++--
src/box/sql/select.c | 112 ++++++++++++++----------
src/box/sql/sqliteInt.h | 6 +-
src/box/sql/tokenize.c | 3 +
src/box/sql/trigger.c | 2 +
src/box/sql/update.c | 29 ++++---
src/box/sql/where.c | 6 +-
src/box/sql/wherecode.c | 2 +-
src/box/sql/whereexpr.c | 4 +-
21 files changed, 433 insertions(+), 287 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..5ab116b 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,66 @@ space_column_default_expr(uint32_t space_id, uint32_t fieldno)
return space->def->fields[fieldno].default_value_expr;
}
+
+struct space_def *
+sql_ephemeral_space_def_new(Parse *parser)
+{
+ struct space_def *def = NULL;
+ struct region *region = &fiber()->gc;
+ size_t size = sizeof(struct space_def) + 1;
+ def = (struct space_def *)region_alloc(region, size);
+ if (def != NULL) {
+ memset(def, 0, size);
+ def->dict =
+ (struct tuple_dictionary *)
+ region_alloc(region,
+ sizeof(struct tuple_dictionary));
+ }
+ if (def == NULL || def->dict == NULL) {
+ parser->rc = SQLITE_NOMEM_BKPT;
+ parser->nErr++;
+ return NULL;
+ }
+ def->dict->refs = 1;
+ def->opts.temporary = true;
+ return def;
+}
+
+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 = sql_ephemeral_space_def_new(parser);
+ if (def == NULL) {
+ sqlite3DbFree(db, table);
+ return NULL;
+ }
+
+ table->def = def;
+ return table;
+}
+
+int
+sql_table_def_rebuild(struct sqlite3 *db, struct Table *pTable)
+{
+ assert(pTable->def->opts.temporary == true);
+
+ /* All allocations are on region. */
+ 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;
+ }
+ pTable->def = new_def;
+ pTable->def->opts.temporary = false;
+ return 0;
+}
diff --git a/src/box/sql.h b/src/box/sql.h
index db92d80..410653b 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,37 @@ 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);
+
+/**
+ * Create and initialize a new ephemeric space_def object.
+ * @param pParse SQL Parser object.
+ * @retval NULL on memory allocation error, Parser state changed.
+ * @retval not NULL on success.
+ */
+struct space_def *
+sql_ephemeral_space_def_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..d3a33d5 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,10 @@ 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;
+ /* Do not delete pTable->def allocated not on region. */
+ assert(pTable->def != NULL);
+ if (pTable->def->opts.temporary == false)
space_def_delete(pTable->def);
- sqlite3DbFree(db, fields);
- }
sqlite3DbFree(db, pTable);
/* Verify that no lookaside memory was used by schema tables */
@@ -494,30 +485,19 @@ sqlite3PrimaryKeyIndex(Table * pTab)
/**
* Create and initialize a new SQL Table object.
+ * All memory is allocated on region.
* @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;
@@ -568,10 +548,11 @@ sqlite3StartTable(Parse *pParse, Token *pName, int noErr)
}
zName = sqlite3NameFromToken(db, pName);
-
pParse->sNameToken = *pName;
if (zName == 0)
return;
+ if (sqlite3CheckIdentifierName(pParse, zName) != SQLITE_OK)
+ goto begin_table_error;
assert(db->pSchema != NULL);
pTable = sqlite3HashFind(&db->pSchema->tblHash, zName);
@@ -626,30 +607,33 @@ sqlite3StartTable(Parse *pParse, Token *pName, int noErr)
static struct field_def *
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) {
- uint32_t columns = table->def->exact_field_count;
- columns = (columns > 0) ? 2 * columns : 1;
- field = sqlite3DbRealloc(db, table->def->fields,
- columns * sizeof(table->def->fields[0]));
+ uint32_t columns_new = table->def->exact_field_count;
+ columns_new = (columns_new > 0) ? 2 * columns_new : 1;
+ struct region *region = &fiber()->gc;
+ field = region_alloc(region,
+ columns_new * sizeof(table->def->fields[0]));
if (field == NULL) {
parser->rc = SQLITE_NOMEM_BKPT;
parser->nErr++;
return NULL;
}
- for (uint32_t i = columns / 2; i < columns; i++) {
+ for (uint32_t i = 0; i < table->def->exact_field_count; i++) {
+ memcpy(&field[i], &table->def->fields[i],
+ sizeof(struct field_def));
+ }
+ for (uint32_t i = columns_new / 2; i < columns_new; i++) {
memcpy(&field[i], &field_def_default,
sizeof(struct field_def));
}
table->def->fields = field;
- table->def->exact_field_count = columns;
+ table->def->exact_field_count = columns_new;
}
field = &table->def->fields[id];
@@ -675,42 +659,40 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
sqlite3 *db = pParse->db;
if ((p = pParse->pNewTable) == 0)
return;
+ assert(p->def->opts.temporary == true);
#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);
+ struct region *region = &fiber()->gc;
+ z = region_alloc(region, pName->n + 1);
if (z == 0)
return;
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]));
- if (aNew == 0) {
- sqlite3DbFree(db, z);
+ (p->def->field_count + 8) * sizeof(p->aCol[0]));
+ if (aNew == 0)
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 +722,6 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
sqlite3_free(zType);
}
}
- p->nCol++;
p->def->field_count++;
pParse->constraintName.n = 0;
}
@@ -756,9 +737,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 +852,31 @@ void
sqlite3AddDefaultValue(Parse * pParse, ExprSpan * pSpan)
{
Table *p;
- Column *pCol;
sqlite3 *db = pParse->db;
p = pParse->pNewTable;
+ assert(p->def->opts.temporary == true);
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 +921,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 +936,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 +1010,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 +1061,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 +1280,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 +1292,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 +1302,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 +1316,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 +1346,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 +1366,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 +1407,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 +1420,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 +1637,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,7 +1827,6 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
p = pParse->pNewTable;
if (p == 0)
return;
-
assert(!db->init.busy || !pSelect);
/* If db->init.busy == 1, then we're called from
@@ -1874,6 +1847,9 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
}
}
+ if (sql_table_def_rebuild(db, p) != 0)
+ return;
+
#ifndef SQLITE_OMIT_CHECK
/* Resolve names in all CHECK constraint expressions.
*/
@@ -1986,6 +1962,7 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
if (db->init.busy) {
Table *pOld;
Schema *pSchema = p->pSchema;
+ assert(p->def->opts.temporary == false);
pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p);
if (pOld) {
assert(p == pOld); /* Malloc must have failed inside HashInsert() */
@@ -2101,7 +2078,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 +2096,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 +2115,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,26 +2126,28 @@ 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);
}
} else if (pSelTab) {
+ assert(pTable->def->opts.temporary == false);
/* CREATE VIEW name AS... without an argument list. Construct
* 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 +2174,20 @@ sqliteViewResetAll(sqlite3 * db)
Table *pTab = sqliteHashData(i);
if (pTab->pSelect) {
sqlite3DeleteColumnNames(db, pTab);
+ struct space_def *old_def = pTab->def;
+ assert(old_def->opts.temporary == false);
+ /* Ignore fields allocated on region */
+ 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 +2460,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 +2499,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 +2957,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 +4011,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 +4174,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/prepare.c b/src/box/sql/prepare.c
index 2ab8751..7dc14f6 100644
--- a/src/box/sql/prepare.c
+++ b/src/box/sql/prepare.c
@@ -211,17 +211,19 @@ sqlite3InitDatabase(sqlite3 * db)
void
sqlite3ParserReset(Parse * pParse)
{
- if (pParse) {
- sqlite3 *db = pParse->db;
- sqlite3DbFree(db, pParse->aLabel);
- sqlite3ExprListDelete(db, pParse->pConstExpr);
- if (db) {
- assert(db->lookaside.bDisable >=
- pParse->disableLookaside);
- db->lookaside.bDisable -= pParse->disableLookaside;
- }
- pParse->disableLookaside = 0;
+ if (pParse == NULL)
+ return;
+ sqlite3 *db = pParse->db;
+ sqlite3DbFree(db, pParse->aLabel);
+ sqlite3ExprListDelete(db, pParse->pConstExpr);
+ if (db) {
+ assert(db->lookaside.bDisable >=
+ pParse->disableLookaside);
+ db->lookaside.bDisable -= pParse->disableLookaside;
}
+ pParse->disableLookaside = 0;
+ struct region *region = &fiber()->gc;
+ region_truncate(region, pParse->region_initial_size);
}
/*
@@ -265,6 +267,10 @@ sqlite3Prepare(sqlite3 * db, /* Database handle. */
* works even if READ_UNCOMMITTED is set.
*/
sParse.db = db;
+ /* Store region initial size to revert future allocations */
+ struct region *region = &fiber()->gc;
+ sParse.region_initial_size = region_used(region);
+
if (nBytes >= 0 && (nBytes == 0 || zSql[nBytes - 1] != 0)) {
char *zSqlCopy;
int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
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..d71603e 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,22 @@ sqlite3ColumnsFromExprList(Parse * pParse, /* Parsing context */
aCol = 0;
}
assert(nCol == (i16) nCol);
- *pnCol = nCol;
- *paCol = aCol;
+
+ struct region *region = &fiber()->gc;
+ assert(pTable->def->fields == NULL);
+ if (pTable->def->opts.temporary == false) {
+ /* CREATE VIEW name AS... without an argument list. Construct
+ * the column names from the SELECT statement that defines the view.
+ */
+ pTable->def->field_count = 0;
+ space_def_delete(pTable->def);
+ pTable->def = sql_ephemeral_space_def_new(pParse);
+ }
+ pTable->def->fields =
+ region_alloc(region, nCol*sizeof(pTable->def->fields[0]));
+ memset(pTable->def->fields, 0, 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 +1859,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 +1888,31 @@ sqlite3ColumnsFromExprList(Parse * pParse, /* Parsing context */
if (cnt > 3)
sqlite3_randomness(sizeof(cnt), &cnt);
}
- pCol->zName = zName;
- if (zName && sqlite3HashInsert(&ht, zName, pCol) == pCol) {
+ uint32_t zNameLen = (uint32_t)strlen(zName);
+ if (zName && sqlite3HashInsert(&ht, zName, pCol) == pCol)
+ sqlite3OomFault(db);
+ pTable->def->fields[i].name =
+ region_alloc(region, zNameLen + 1);
+ if (pTable->def->fields[i].name == NULL) {
sqlite3OomFault(db);
+ } else {
+ memcpy(pTable->def->fields[i].name, zName, zNameLen);
+ pTable->def->fields[i].name[zNameLen] = '\0';
}
}
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 +1941,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 +1988,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 +1999,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 +4520,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 +4585,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 +4706,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 +4715,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 +4748,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 +4856,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 +5392,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..98212e3 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
@@ -2936,6 +2934,8 @@ struct Parse {
u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
u8 disableTriggers; /* True to disable triggers */
+ /** Region size at the Parser launch */
+ size_t region_initial_size;
/**************************************************************************
* Fields above must be initialized to zero. The fields that follow,
@@ -3515,7 +3515,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/tokenize.c b/src/box/sql/tokenize.c
index c77aa9b..9055bd0 100644
--- a/src/box/sql/tokenize.c
+++ b/src/box/sql/tokenize.c
@@ -664,6 +664,9 @@ sql_expr_compile(sqlite3 *db, const char *expr, struct Expr **result)
memset(&parser, 0, sizeof(parser));
parser.db = db;
parser.parse_only = true;
+ struct region *region = &fiber()->gc;
+ parser.region_initial_size = region_used(region);
+
char *unused;
if (sqlite3RunParser(&parser, stmt, &unused) != SQLITE_OK) {
diag_set(ClientError, ER_SQL_EXECUTE, expr);
diff --git a/src/box/sql/trigger.c b/src/box/sql/trigger.c
index 28c56db..9b03be1 100644
--- a/src/box/sql/trigger.c
+++ b/src/box/sql/trigger.c
@@ -873,6 +873,8 @@ codeRowTrigger(Parse * pParse, /* Current parse context */
pSubParse->pToplevel = pTop;
pSubParse->eTriggerOp = pTrigger->op;
pSubParse->nQueryLoop = pParse->nQueryLoop;
+ struct region *region = &fiber()->gc;
+ pSubParse->region_initial_size = region_used(region);
v = sqlite3GetVdbe(pSubParse);
if (v) {
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);
--
2.7.4
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] [PATCH v4 3/7] sql: start using type from space_def
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 0/7] sql: refactor SQL Parser structures Kirill Shcherbatov
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 1/7] sql: fix code style in sqlite3Pragma Kirill Shcherbatov
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 2/7] sql: remove zName and nColumn from SQL Kirill Shcherbatov
@ 2018-04-28 18:26 ` Kirill Shcherbatov
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 4/7] sql: start using collations and is_nullable " Kirill Shcherbatov
` (4 subsequent siblings)
7 siblings, 0 replies; 26+ messages in thread
From: Kirill Shcherbatov @ 2018-04-28 18:26 UTC (permalink / raw)
To: tarantool-patches; +Cc: v.shpilevoy, Kirill Shcherbatov
Part of #3272.
---
src/box/sql.c | 13 +++++++++----
src/box/sql/build.c | 12 +++++++-----
src/box/sql/pragma.c | 12 ++++++------
src/box/sql/select.c | 8 ++++----
src/box/sql/sqliteInt.h | 2 --
src/box/sql/util.c | 9 ---------
6 files changed, 26 insertions(+), 30 deletions(-)
diff --git a/src/box/sql.c b/src/box/sql.c
index 5ab116b..2893d70 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -1430,10 +1430,12 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
{
struct Column *aCol = pTable->aCol;
const struct Enc *enc = get_enc(buf);
+ const struct space_def *def = pTable->def;
+ assert(def != NULL);
struct SqliteIndex *pk_idx = sqlite3PrimaryKeyIndex(pTable);
int pk_forced_int = -1;
char *base = buf, *p;
- int i, n = pTable->def->field_count;
+ int i, n = def->field_count;
p = enc->encode_array(base, n);
@@ -1441,14 +1443,14 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
* treat it as strict type, not affinity. */
if (pk_idx && pk_idx->nColumn == 1) {
int pk = pk_idx->aiColumn[0];
- if (pTable->aCol[pk].type == FIELD_TYPE_INTEGER)
+ if (def->fields[pk].type == FIELD_TYPE_INTEGER)
pk_forced_int = pk;
}
for (i = 0; i < n; i++) {
const char *t;
struct coll *coll = aCol[i].coll;
- struct field_def *field = &pTable->def->fields[i];
+ struct field_def *field = &def->fields[i];
const char *zToken = field->default_value;
int base_len = 4;
if (coll != NULL)
@@ -1521,6 +1523,9 @@ int tarantoolSqlite3MakeTableOpts(Table *pTable, const char *zSql, void *buf)
int tarantoolSqlite3MakeIdxParts(SqliteIndex *pIndex, void *buf)
{
struct Column *aCol = pIndex->pTable->aCol;
+ struct space_def *def = pIndex->pTable->def;
+ assert(def != NULL);
+
const struct Enc *enc = get_enc(buf);
struct SqliteIndex *primary_index;
char *base = buf, *p;
@@ -1532,7 +1537,7 @@ int tarantoolSqlite3MakeIdxParts(SqliteIndex *pIndex, void *buf)
* treat it as strict type, not affinity. */
if (primary_index->nColumn == 1) {
int pk = primary_index->aiColumn[0];
- if (aCol[pk].type == FIELD_TYPE_INTEGER)
+ if (def->fields[pk].type == FIELD_TYPE_INTEGER)
pk_forced_int = pk;
}
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index d3a33d5..99059b3 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -692,7 +692,8 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
}
pCol = &p->aCol[p->def->field_count];
memset(pCol, 0, sizeof(p->aCol[0]));
- p->def->fields[p->def->field_count].name = z;
+ struct field_def *column_def = &p->def->fields[p->def->field_count];
+ column_def->name = z;
if (pType->n == 0) {
/* If there is no type specified, columns have the default affinity
* 'BLOB' and type SCALAR.
@@ -700,8 +701,8 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
* specified type, the code below should emit an error.
*/
pCol->affinity = SQLITE_AFF_BLOB;
- pCol->type = FIELD_TYPE_SCALAR;
pCol->szEst = 1;
+ column_def->type = FIELD_TYPE_SCALAR;
} else {
/* TODO: convert string of type into runtime
* FIELD_TYPE value for other types.
@@ -710,16 +711,16 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
pType->n == 7) ||
(sqlite3StrNICmp(pType->z, "INT", 3) == 0 &&
pType->n == 3)) {
- pCol->type = FIELD_TYPE_INTEGER;
pCol->affinity = SQLITE_AFF_INTEGER;
+ column_def->type = FIELD_TYPE_INTEGER;
} else {
zType = sqlite3_malloc(pType->n + 1);
memcpy(zType, pType->z, pType->n);
zType[pType->n] = 0;
sqlite3Dequote(zType);
pCol->affinity = sqlite3AffinityType(zType, 0);
- pCol->type = FIELD_TYPE_SCALAR;
sqlite3_free(zType);
+ column_def->type = FIELD_TYPE_SCALAR;
}
}
p->def->field_count++;
@@ -947,9 +948,10 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
}
}
}
+ assert(pCol == &pTab->aCol[iCol]);
if (nTerm == 1
&& pCol
- && (sqlite3ColumnType(pCol) == FIELD_TYPE_INTEGER)
+ && (pTab->def->fields[iCol].type == FIELD_TYPE_INTEGER)
&& sortOrder != SQLITE_SO_DESC) {
assert(autoInc == 0 || autoInc == 1);
pTab->iPKey = iCol;
diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c
index e93f377..0cf103c 100644
--- a/src/box/sql/pragma.c
+++ b/src/box/sql/pragma.c
@@ -381,13 +381,13 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */
space_cache_find(space_id);
char *expr_str = space->
def->fields[i].default_value;
+ const char *name =
+ pTab->def->fields[i].name;
+ enum field_type type =
+ pTab->def->fields[i].type;
sqlite3VdbeMultiLoad(v, 1, "issisi",
- i,
- pTab->def->fields[i].
- name,
- field_type_strs[
- sqlite3ColumnType
- (pCol)],
+ i, name,
+ field_type_strs[type],
nullable == 0,
expr_str, k);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1,
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index d71603e..03bfcf9 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -1664,12 +1664,12 @@ columnTypeImpl(NameContext * pNC, Expr * pExpr,
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);
+ zOrigCol = pTab->def->fields[iCol].name;
+ zType = pTab->def->fields[iCol].type;
estWidth = pTab->aCol[iCol].szEst;
zOrigTab = pTab->zName;
#else
- column_type = sqlite3ColumnType(&pTab->aCol[iCol]);
+ column_type = pTab->def->fields[iCol].type;
estWidth = pTab->aCol[iCol].szEst;
#endif
}
@@ -1955,7 +1955,7 @@ sqlite3SelectAddColumnTypeAndCollation(Parse * pParse, /* Parsing contexts */
type = columnType(&sNC, p, 0, 0, 0, &pCol->szEst);
szAll += pCol->szEst;
pCol->affinity = sqlite3ExprAffinity(p);
- pCol->type = type;
+ pTab->def->fields[i].type = type;
if (pCol->affinity == 0)
pCol->affinity = SQLITE_AFF_BLOB;
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 98212e3..520b74c 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -1867,7 +1867,6 @@ struct Savepoint {
* of this structure.
*/
struct Column {
- enum field_type type; /* Column type. */
/** Collating sequence. */
struct coll *coll;
/**
@@ -3390,7 +3389,6 @@ int sqlite3IoerrnomemError(int);
*/
int sqlite3StrICmp(const char *, const char *);
unsigned sqlite3Strlen30(const char *);
-enum field_type sqlite3ColumnType(Column *);
#define sqlite3StrNICmp sqlite3_strnicmp
void sqlite3MallocInit(void);
diff --git a/src/box/sql/util.c b/src/box/sql/util.c
index 8c4e7b9..401b215 100644
--- a/src/box/sql/util.c
+++ b/src/box/sql/util.c
@@ -130,15 +130,6 @@ sqlite3Strlen30(const char *z)
}
/*
- * Return the declared type of a column.
- */
-inline enum field_type
-sqlite3ColumnType(Column * pCol)
-{
- return pCol->type;
-}
-
-/*
* Helper function for sqlite3Error() - called rarely. Broken out into
* a separate routine to avoid unnecessary register saves on entry to
* sqlite3Error().
--
2.7.4
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] [PATCH v4 4/7] sql: start using collations and is_nullable from space_def
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 0/7] sql: refactor SQL Parser structures Kirill Shcherbatov
` (2 preceding siblings ...)
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 3/7] sql: start using type from space_def Kirill Shcherbatov
@ 2018-04-28 18:26 ` Kirill Shcherbatov
2018-05-03 10:21 ` [tarantool-patches] " Vladislav Shpilevoy
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 5/7] sql: move names to server Kirill Shcherbatov
` (3 subsequent siblings)
7 siblings, 1 reply; 26+ messages in thread
From: Kirill Shcherbatov @ 2018-04-28 18:26 UTC (permalink / raw)
To: tarantool-patches; +Cc: v.shpilevoy, Kirill Shcherbatov
Part of #3272.
---
src/box/sql.c | 36 +++++++++++++++++++++++++-----------
src/box/sql/alter.c | 11 ++++++++---
src/box/sql/build.c | 20 +++++++++++++-------
src/box/sql/fkey.c | 7 ++-----
src/box/sql/select.c | 6 ++++--
src/box/sql/sqliteInt.h | 7 -------
src/box/sql/vdbeaux.c | 5 ++++-
7 files changed, 56 insertions(+), 36 deletions(-)
diff --git a/src/box/sql.c b/src/box/sql.c
index 2893d70..ef11eb9 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -1449,7 +1449,9 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
for (i = 0; i < n; i++) {
const char *t;
- struct coll *coll = aCol[i].coll;
+ struct coll *coll =
+ coll_by_id(pTable->def->fields[i].coll_id);
+
struct field_def *field = &def->fields[i];
const char *zToken = field->default_value;
int base_len = 4;
@@ -1461,19 +1463,25 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
p = enc->encode_str(p, "name", 4);
p = enc->encode_str(p, field->name, strlen(field->name));
p = enc->encode_str(p, "type", 4);
+
+ assert(def->fields[i].is_nullable ==
+ (def->fields[i].nullable_action ==
+ ON_CONFLICT_ACTION_NONE));
+
if (i == pk_forced_int) {
t = "integer";
} else {
t = aCol[i].affinity == SQLITE_AFF_BLOB ? "scalar" :
- convertSqliteAffinity(aCol[i].affinity, aCol[i].notNull == 0);
+ convertSqliteAffinity(aCol[i].affinity,
+ def->fields[i].is_nullable);
}
p = enc->encode_str(p, t, strlen(t));
p = enc->encode_str(p, "is_nullable", 11);
- p = enc->encode_bool(p, aCol[i].notNull ==
- ON_CONFLICT_ACTION_NONE);
+ p = enc->encode_bool(p, def->fields[i].is_nullable);
p = enc->encode_str(p, "nullable_action", 15);
- assert(aCol[i].notNull < on_conflict_action_MAX);
- const char *action = on_conflict_action_strs[aCol[i].notNull];
+ assert(def->fields[i].nullable_action < on_conflict_action_MAX);
+ const char *action =
+ on_conflict_action_strs[def->fields[i].nullable_action];
p = enc->encode_str(p, action, strlen(action));
if (coll != NULL) {
p = enc->encode_str(p, "collation", strlen("collation"));
@@ -1552,11 +1560,16 @@ int tarantoolSqlite3MakeIdxParts(SqliteIndex *pIndex, void *buf)
p = enc->encode_array(base, n);
for (i = 0; i < n; i++) {
int col = pIndex->aiColumn[i];
+ assert(def->fields[col].is_nullable ==
+ (def->fields[col].nullable_action ==
+ ON_CONFLICT_ACTION_NONE));
const char *t;
- if (pk_forced_int == col)
+ if (pk_forced_int == col) {
t = "integer";
- else
- t = convertSqliteAffinity(aCol[col].affinity, aCol[col].notNull == 0);
+ } else {
+ t = convertSqliteAffinity(aCol[col].affinity,
+ def->fields[col].is_nullable);
+ }
/* do not decode default collation */
p = enc->encode_map(p, pIndex->coll_array[i] == NULL ? 4 : 5);
p = enc->encode_str(p, "type", sizeof("type")-1);
@@ -1568,9 +1581,10 @@ int tarantoolSqlite3MakeIdxParts(SqliteIndex *pIndex, void *buf)
p = enc->encode_uint(p, pIndex->coll_array[i]->id);
}
p = enc->encode_str(p, "is_nullable", 11);
- p = enc->encode_bool(p, aCol[col].notNull == ON_CONFLICT_ACTION_NONE);
+ p = enc->encode_bool(p, def->fields[col].is_nullable);
p = enc->encode_str(p, "nullable_action", 15);
- const char *action_str = on_conflict_action_strs[aCol[col].notNull];
+ const char *action_str =
+ on_conflict_action_strs[def->fields[col].nullable_action];
p = enc->encode_str(p, action_str, strlen(action_str));
}
return (int)(p - base);
diff --git a/src/box/sql/alter.c b/src/box/sql/alter.c
index bedf602..f830a15 100644
--- a/src/box/sql/alter.c
+++ b/src/box/sql/alter.c
@@ -198,7 +198,12 @@ sqlite3AlterFinishAddColumn(Parse * pParse, Token * pColDef)
"Cannot add a REFERENCES column with non-NULL default value");
return;
}
- if (pCol->notNull && !pDflt) {
+ assert(pNew->def->fields[pNew->def->field_count - 1].is_nullable ==
+ (pNew->def->fields[pNew->def->field_count - 1].nullable_action ==
+ ON_CONFLICT_ACTION_NONE));
+
+ if (pNew->def->fields[pNew->def->field_count - 1].nullable_action
+ && !pDflt) {
sqlite3ErrorMsg(pParse,
"Cannot add a NOT NULL column with default value NULL");
return;
@@ -307,9 +312,9 @@ sqlite3AlterBeginAddColumn(Parse * pParse, SrcList * pSrc)
}
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];
+ /* FIXME: Column *pCol = &pNew->aCol[i]; */
/* FIXME: pCol->zName = sqlite3DbStrDup(db, pCol->zName); */
- pCol->coll = NULL;
+ /* FIXME: pCol->coll = NULL; */
}
pNew->pSchema = db->pSchema;
pNew->addColOffset = pTab->addColOffset;
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 99059b3..e9c0686 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -694,6 +694,8 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
memset(pCol, 0, sizeof(p->aCol[0]));
struct field_def *column_def = &p->def->fields[p->def->field_count];
column_def->name = z;
+ column_def->is_nullable = true;
+ column_def->nullable_action = ON_CONFLICT_ACTION_NONE;
if (pType->n == 0) {
/* If there is no type specified, columns have the default affinity
* 'BLOB' and type SCALAR.
@@ -740,7 +742,9 @@ sqlite3AddNotNull(Parse * pParse, int onError)
p = pParse->pNewTable;
if (p == 0 || NEVER(p->def->field_count < 1))
return;
- p->aCol[p->def->field_count - 1].notNull = (u8) onError;
+ p->def->fields[p->def->field_count - 1].nullable_action = (u8)onError;
+ p->def->fields[p->def->field_count - 1].is_nullable =
+ (onError == ON_CONFLICT_ACTION_NONE);
}
/*
@@ -1018,10 +1022,10 @@ sqlite3AddCollateType(Parse * pParse, Token * pToken)
if (!zColl)
return;
- struct coll *coll = sqlite3LocateCollSeq(pParse, db, zColl);
+ struct coll *coll = coll_by_name(zColl, strlen(zColl));
if (coll != NULL) {
Index *pIdx;
- p->aCol[i].coll = coll;
+ p->def->fields[i].coll_id = coll->id;
/* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
* then an index may have been created on this column before the
@@ -1032,8 +1036,6 @@ sqlite3AddCollateType(Parse * pParse, Token * pToken)
if (pIdx->aiColumn[0] == i)
pIdx->coll_array[0] = sql_column_collation(p, i);
}
- } else {
- sqlite3DbFree(db, zColl);
}
}
@@ -1064,7 +1066,9 @@ sql_column_collation(Table *table, uint32_t column)
*/
if (space == NULL || space_index(space, 0) == NULL) {
assert(column < (uint32_t)table->def->field_count);
- return table->aCol[column].coll;
+ struct coll *coll =
+ coll_by_id(table->def->fields[column].coll_id);
+ return coll;
}
return space->format->fields[column].coll;
@@ -1411,7 +1415,9 @@ convertToWithoutRowidTable(Parse * pParse, Table * pTab)
if (!db->init.imposterTable) {
for (i = 0; i < (int)pTab->def->field_count; i++) {
if (pTab->aCol[i].is_primkey) {
- pTab->aCol[i].notNull = ON_CONFLICT_ACTION_ABORT;
+ pTab->def->fields[i].nullable_action
+ = ON_CONFLICT_ACTION_ABORT;
+ pTab->def->fields[i].is_nullable = false;
}
}
}
diff --git a/src/box/sql/fkey.c b/src/box/sql/fkey.c
index c15ad8c..8c015c9 100644
--- a/src/box/sql/fkey.c
+++ b/src/box/sql/fkey.c
@@ -34,6 +34,7 @@
* support to compiled SQL statements.
*/
#include <box/coll.h>
+#include "box/coll_cache.h"
#include "sqliteInt.h"
#include "box/session.h"
#include "tarantoolInt.h"
@@ -535,11 +536,7 @@ exprTableRegister(Parse * pParse, /* Parsing and code generating context */
pCol = &pTab->aCol[iCol];
pExpr->iTable = regBase + iCol + 1;
pExpr->affinity = pCol->affinity;
- const char *coll_name;
- if (pCol->coll == NULL && pCol->coll != NULL)
- coll_name = pCol->coll->name;
- else
- coll_name = "binary";
+ const char *coll_name = "binary";
pExpr = sqlite3ExprAddCollateString(pParse, pExpr,
coll_name);
} else {
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index 03bfcf9..fa1de9b 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -1836,6 +1836,8 @@ sqlite3ColumnsFromExprList(Parse * pParse, /* Parsing context */
pTable->def->fields =
region_alloc(region, nCol*sizeof(pTable->def->fields[0]));
memset(pTable->def->fields, 0, nCol*sizeof(pTable->def->fields[0]));
+ for (int i = 0; i < nCol; i++)
+ pTable->def->fields[i].is_nullable = true;
pTable->def->field_count = (uint32_t)nCol;
pTable->aCol = aCol;
@@ -1961,8 +1963,8 @@ sqlite3SelectAddColumnTypeAndCollation(Parse * pParse, /* Parsing contexts */
pCol->affinity = SQLITE_AFF_BLOB;
bool unused;
struct coll *coll = sql_expr_coll(pParse, p, &unused);
- if (coll != NULL && pCol->coll == NULL)
- pCol->coll = coll;
+ if (coll != NULL && pTab->def->fields[i].coll_id == COLL_NONE)
+ pTab->def->fields[i].coll_id = coll->id;
}
pTab->szTabRow = sqlite3LogEst(szAll * 4);
}
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 520b74c..a045286 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -1867,13 +1867,6 @@ struct Savepoint {
* of this structure.
*/
struct Column {
- /** Collating sequence. */
- struct coll *coll;
- /**
- * An ON_CONFLICT_ACTION code for handling a NOT NULL
- * constraint.
- */
- enum on_conflict_action notNull;
char affinity; /* One of the SQLITE_AFF_... values */
u8 szEst; /* Estimated size of value in this column. sizeof(INT)==1 */
u8 is_primkey; /* Boolean propertie for being PK */
diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c
index b3998ea..f76c689 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -4743,6 +4743,9 @@ table_column_is_nullable(struct Table *tab, uint32_t column)
ON_CONFLICT_ACTION_NONE;
} else {
/* tab is ephemeral (in SQLite sense). */
- return tab->aCol[column].notNull == 0;
+ assert(tab->def->fields[column].is_nullable ==
+ (tab->def->fields[column].nullable_action ==
+ ON_CONFLICT_ACTION_NONE));
+ return tab->def->fields[column].is_nullable;
}
}
--
2.7.4
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] [PATCH v4 5/7] sql: move names to server
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 0/7] sql: refactor SQL Parser structures Kirill Shcherbatov
` (3 preceding siblings ...)
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 4/7] sql: start using collations and is_nullable " Kirill Shcherbatov
@ 2018-04-28 18:26 ` Kirill Shcherbatov
2018-05-03 11:08 ` [tarantool-patches] " Vladislav Shpilevoy
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 6/7] sql: start using is_view field from space_def Kirill Shcherbatov
` (2 subsequent siblings)
7 siblings, 1 reply; 26+ messages in thread
From: Kirill Shcherbatov @ 2018-04-28 18:26 UTC (permalink / raw)
To: tarantool-patches; +Cc: v.shpilevoy, Kirill Shcherbatov
Part of #3272.
---
src/box/sql.c | 38 ++++++++++++++++++++++-------
src/box/sql.h | 6 ++---
src/box/sql/alter.c | 11 +++++----
src/box/sql/analyze.c | 11 +++++----
src/box/sql/build.c | 61 ++++++++++++++++++++++++++++++-----------------
src/box/sql/delete.c | 6 ++---
src/box/sql/fkey.c | 11 +++++----
src/box/sql/hash.c | 5 ++--
src/box/sql/insert.c | 9 +++----
src/box/sql/pragma.c | 4 ++--
src/box/sql/resolve.c | 7 +++---
src/box/sql/select.c | 63 ++++++++++++++++++++++++-------------------------
src/box/sql/sqliteInt.h | 1 -
src/box/sql/treeview.c | 2 +-
src/box/sql/trigger.c | 4 ++--
src/box/sql/update.c | 3 ++-
src/box/sql/vdbe.c | 2 +-
src/box/sql/where.c | 5 ++--
src/box/sql/wherecode.c | 3 ++-
src/box/sql/whereexpr.c | 2 +-
20 files changed, 150 insertions(+), 104 deletions(-)
diff --git a/src/box/sql.c b/src/box/sql.c
index ef11eb9..47f7cb1 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -1699,12 +1699,13 @@ space_column_default_expr(uint32_t space_id, uint32_t fieldno)
return space->def->fields[fieldno].default_value_expr;
}
-struct space_def *
-sql_ephemeral_space_def_new(Parse *parser)
+static struct space_def *
+sql_ephemeral_space_def_new(Parse *parser, const char *name)
{
struct space_def *def = NULL;
struct region *region = &fiber()->gc;
- size_t size = sizeof(struct space_def) + 1;
+ size_t name_len = name != NULL ? strlen(name) : 0;
+ size_t size = sizeof(struct space_def) + name_len + 1;
def = (struct space_def *)region_alloc(region, size);
if (def != NULL) {
memset(def, 0, size);
@@ -1718,19 +1719,40 @@ sql_ephemeral_space_def_new(Parse *parser)
parser->nErr++;
return NULL;
}
+ memcpy(def->name, name, name_len);
+ def->name[name_len] = '\0';
def->dict->refs = 1;
def->opts.temporary = true;
return def;
}
+struct space_def *
+sql_ephemeral_space_def_clone(Parse *parser, struct space_def *old_def)
+{
+ struct space_def *new_def = NULL;
+ new_def = sql_ephemeral_space_def_new(parser, old_def->name);
+ if (new_def == NULL) {
+ parser->rc = SQLITE_NOMEM_BKPT;
+ parser->nErr++;
+ return NULL;
+ }
+ new_def->opts = old_def->opts;
+ new_def->opts.temporary = true;
+ new_def->id = old_def->id;
+ new_def->uid = old_def->uid;
+ memcpy(new_def->engine_name, old_def->engine_name,
+ strlen(old_def->engine_name));
+ return new_def;
+}
+
Table *
-sql_ephemeral_table_new(Parse *parser)
+sql_ephemeral_table_new(Parse *parser, const char *name)
{
sqlite3 *db = parser->db;
struct space_def *def = NULL;
Table *table = sqlite3DbMallocZero(db, sizeof(Table));
if (table != NULL)
- def = sql_ephemeral_space_def_new(parser);
+ def = sql_ephemeral_space_def_new(parser, name);
if (def == NULL) {
sqlite3DbFree(db, table);
return NULL;
@@ -1744,13 +1766,13 @@ int
sql_table_def_rebuild(struct sqlite3 *db, struct Table *pTable)
{
assert(pTable->def->opts.temporary == true);
-
/* All allocations are on region. */
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,
+ old_def->field_count,
+ pTable->def->name, strlen(pTable->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) {
diff --git a/src/box/sql.h b/src/box/sql.h
index 410653b..d7cfd70 100644
--- a/src/box/sql.h
+++ b/src/box/sql.h
@@ -152,16 +152,16 @@ sql_expr_free(struct sqlite3 *db, struct Expr *expr, bool extern_alloc);
* @retval not NULL on success.
*/
struct Table *
-sql_ephemeral_table_new(struct Parse *parser);
+sql_ephemeral_table_new(struct Parse *parser, const char *name);
/**
- * Create and initialize a new ephemeric space_def object.
+ * Create and initialize a new ephemeric space_def object copy.
* @param pParse SQL Parser object.
* @retval NULL on memory allocation error, Parser state changed.
* @retval not NULL on success.
*/
struct space_def *
-sql_ephemeral_space_def_new(struct Parse *parser);
+sql_ephemeral_space_def_clone(struct Parse *parser, struct space_def *old_def);
/**
* Rebuild struct def in Table with memory allocated on a single
diff --git a/src/box/sql/alter.c b/src/box/sql/alter.c
index f830a15..33a4f4d 100644
--- a/src/box/sql/alter.c
+++ b/src/box/sql/alter.c
@@ -109,7 +109,7 @@ sqlite3AlterRenameTable(Parse * pParse, /* Parser context. */
#ifndef SQLITE_OMIT_VIEW
if (space_is_view(pTab)) {
sqlite3ErrorMsg(pParse, "view %s may not be altered",
- pTab->zName);
+ pTab->def->name);
goto exit_rename_table;
}
#endif
@@ -163,7 +163,7 @@ sqlite3AlterFinishAddColumn(Parse * pParse, Token * pColDef)
pNew = pParse->pNewTable;
assert(pNew);
- zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */
+ zTab = &pNew->def->name[16]; /* Skip the "sqlite_altertab_" prefix on the name */
pCol = &pNew->aCol[pNew->def->field_count - 1];
assert(pNew->def != NULL);
pDflt = space_column_default_expr(SQLITE_PAGENO_TO_SPACEID(pNew->tnum),
@@ -235,7 +235,7 @@ sqlite3AlterFinishAddColumn(Parse * pParse, Token * pColDef)
(void)pColDef;
/* Reload the schema of the modified table. */
- reloadTableSchema(pParse, pTab, pTab->zName);
+ reloadTableSchema(pParse, pTab, pTab->def->name);
}
/*
@@ -305,8 +305,9 @@ sqlite3AlterBeginAddColumn(Parse * pParse, SrcList * pSrc)
&& nAlloc - pNew->def->field_count < 8);
pNew->aCol =
(Column *) sqlite3DbMallocZero(db, sizeof(Column) * nAlloc);
- pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName);
- if (!pNew->aCol || !pNew->zName) {
+ /* FIXME: pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName); */
+ /* FIXME: if (!pNew->aCol || !pNew->zName) { */
+ if (!pNew->aCol) {
assert(db->mallocFailed);
goto exit_begin_add_column;
}
diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c
index a0ad511..dc5b4e9 100644
--- a/src/box/sql/analyze.c
+++ b/src/box/sql/analyze.c
@@ -828,7 +828,7 @@ analyzeOneTable(Parse * pParse, /* Parser context */
return;
}
assert(pTab->tnum != 0);
- if (sqlite3_strlike("\\_%", pTab->zName, '\\') == 0) {
+ if (sqlite3_strlike("\\_%", pTab->def->name, '\\') == 0) {
/* Do not gather statistics on system tables */
return;
}
@@ -842,7 +842,7 @@ analyzeOneTable(Parse * pParse, /* Parser context */
iIdxCur = iTab++;
pParse->nTab = MAX(pParse->nTab, iTab);
sqlite3OpenTable(pParse, iTabCur, pTab, OP_OpenRead);
- sqlite3VdbeLoadString(v, regTabname, pTab->zName);
+ sqlite3VdbeLoadString(v, regTabname, pTab->def->name);
for (pIdx = pTab->pIndex; pIdx; pIdx = pIdx->pNext) {
int addrRewind; /* Address of "OP_Rewind iIdxCur" */
@@ -857,7 +857,7 @@ analyzeOneTable(Parse * pParse, /* Parser context */
* instead more familiar table name.
*/
if (IsPrimaryKeyIndex(pIdx)) {
- zIdxName = pTab->zName;
+ zIdxName = pTab->def->name;
} else {
zIdxName = pIdx->zName;
}
@@ -865,7 +865,8 @@ analyzeOneTable(Parse * pParse, /* Parser context */
/* Populate the register containing the index name. */
sqlite3VdbeLoadString(v, regIdxname, zIdxName);
- VdbeComment((v, "Analysis for %s.%s", pTab->zName, zIdxName));
+ VdbeComment((v, "Analysis for %s.%s",
+ pTab->def->name, zIdxName));
/*
* Pseudo-code for loop that calls stat_push():
@@ -1146,7 +1147,7 @@ analyzeTable(Parse * pParse, Table * pTab, Index * pOnlyIdx)
if (pOnlyIdx) {
openStatTable(pParse, iStatCur, pOnlyIdx->zName, "idx");
} else {
- openStatTable(pParse, iStatCur, pTab->zName, "tbl");
+ openStatTable(pParse, iStatCur, pTab->def->name, "tbl");
}
analyzeOneTable(pParse, pTab, pOnlyIdx, iStatCur, pParse->nMem + 1,
pParse->nTab);
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index e9c0686..4e0ae87 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -382,7 +382,6 @@ deleteTable(sqlite3 * db, Table * pTable)
*/
sqlite3HashClear(&pTable->idxHash);
sqlite3DeleteColumnNames(db, pTable);
- sqlite3DbFree(db, pTable->zName);
sqlite3DbFree(db, pTable->zColAff);
sqlite3SelectDelete(db, pTable->pSelect);
sqlite3ExprListDelete(db, pTable->pCheck);
@@ -495,10 +494,9 @@ static Table *
sql_table_new(Parse *parser, char *name)
{
sqlite3 *db = parser->db;
- struct Table *table = sql_ephemeral_table_new(parser);
+ struct Table *table = sql_ephemeral_table_new(parser, name);
if (table == NULL)
return NULL;
- table->zName = name;
table->iPKey = -1;
table->iAutoIncPKey = -1;
table->pSchema = db->pSchema;
@@ -662,7 +660,8 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
assert(p->def->opts.temporary == true);
#if SQLITE_MAX_COLUMN
if ((int)p->def->field_count + 1 > db->aLimit[SQLITE_LIMIT_COLUMN]) {
- sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName);
+ sqlite3ErrorMsg(pParse, "too many columns on %s",
+ p->def->name);
return;
}
#endif
@@ -921,7 +920,7 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
if (pTab->tabFlags & TF_HasPrimaryKey) {
sqlite3ErrorMsg(pParse,
"table \"%s\" has more than one primary key",
- pTab->zName);
+ pTab->def->name);
goto primary_key_exit;
}
pTab->tabFlags |= TF_HasPrimaryKey;
@@ -1288,7 +1287,7 @@ createTableStmt(sqlite3 * db, Table * p)
n = 0;
for (i = 0; i < (int)p->def->field_count; i++)
n += identLength(p->def->fields[i].name) + 5;
- n += identLength(p->zName);
+ n += identLength(p->def->name);
if (n < 50) {
zSep = "";
zSep2 = ",";
@@ -1306,7 +1305,7 @@ createTableStmt(sqlite3 * db, Table * p)
}
sqlite3_snprintf(n, zStmt, "CREATE TABLE ");
k = sqlite3Strlen30(zStmt);
- identPut(zStmt, &k, p->zName);
+ identPut(zStmt, &k, (char *)p->def->name);
zStmt[k++] = '(';
for (pCol = p->aCol, i = 0; i < (int)p->def->field_count; i++, pCol++) {
static const char *const azType[] = {
@@ -1642,7 +1641,7 @@ createSpace(Parse * pParse, int iSpaceId, char *zStmt)
sqlite3VdbeAddOp2(v, OP_Integer, effective_user()->uid,
iFirstCol + 1 /* owner */ );
sqlite3VdbeAddOp4(v, OP_String8, 0, iFirstCol + 2 /* name */ , 0,
- sqlite3DbStrDup(pParse->db, p->zName), P4_DYNAMIC);
+ sqlite3DbStrDup(pParse->db, p->def->name), P4_DYNAMIC);
sqlite3VdbeAddOp4(v, OP_String8, 0, iFirstCol + 3 /* engine */ , 0,
"memtx", P4_STATIC);
sqlite3VdbeAddOp2(v, OP_Integer, p->def->field_count,
@@ -1710,7 +1709,8 @@ parseTableSchemaRecord(Parse * pParse, int iSpaceId, char *zStmt)
sqlite3VdbeAddOp4(v,
OP_String8, 0, iTop, 0,
- sqlite3DbStrDup(pParse->db, p->zName), P4_DYNAMIC);
+ sqlite3DbStrDup(pParse->db, p->def->name),
+ P4_DYNAMIC);
sqlite3VdbeAddOp2(v, OP_SCopy, iSpaceId, iTop + 1);
sqlite3VdbeAddOp2(v, OP_Integer, 0, iTop + 2);
sqlite3VdbeAddOp4(v, OP_String8, 0, iTop + 3, 0, zStmt, P4_DYNAMIC);
@@ -1848,7 +1848,7 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
if ((p->tabFlags & TF_HasPrimaryKey) == 0) {
sqlite3ErrorMsg(pParse,
"PRIMARY KEY missing on table %s",
- p->zName);
+ p->def->name);
return;
} else {
convertToWithoutRowidTable(pParse, p);
@@ -1950,7 +1950,7 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
reg_seq_record = emitNewSysSequenceRecord(pParse,
reg_seq_id,
- p->zName);
+ p->def->name);
sqlite3VdbeAddOp2(v, OP_SInsert, BOX_SEQUENCE_ID,
reg_seq_record);
/* Do an insertion into _space_sequence. */
@@ -1970,8 +1970,8 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
if (db->init.busy) {
Table *pOld;
Schema *pSchema = p->pSchema;
- assert(p->def->opts.temporary == false);
- pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p);
+ pOld = sqlite3HashInsert(&pSchema->tblHash,
+ p->def->name, p);
if (pOld) {
assert(p == pOld); /* Malloc must have failed inside HashInsert() */
sqlite3OomFault(db);
@@ -2106,7 +2106,7 @@ sqlite3ViewGetColumnNames(Parse * pParse, Table * pTable)
*/
if ((int)pTable->def->field_count < 0) {
sqlite3ErrorMsg(pParse, "view %s is circularly defined",
- pTable->zName);
+ pTable->def->name);
return 1;
}
assert((int)pTable->def->field_count >= 0);
@@ -2135,6 +2135,11 @@ sqlite3ViewGetColumnNames(Parse * pParse, Table * pTable)
* a VIEW it holds the list of column names.
*/
sqlite3ColumnsFromExprList(pParse, pTable->pCheck, pTable);
+ struct space_def *old_def = pTable->def;
+ old_def->opts.temporary = true; /* delete it manually */
+ if (sql_table_def_rebuild(db, pTable) != 0)
+ nErr++;
+ space_def_delete(old_def);
if (db->mallocFailed == 0 && pParse->nErr == 0
&& (int)pTable->def->field_count == pSel->pEList->nExpr) {
sqlite3SelectAddColumnTypeAndCollation(pParse,
@@ -2142,18 +2147,30 @@ sqlite3ViewGetColumnNames(Parse * pParse, Table * pTable)
pSel);
}
} else if (pSelTab) {
- assert(pTable->def->opts.temporary == false);
/* CREATE VIEW name AS... without an argument list. Construct
* the column names from the SELECT statement that defines the view.
*/
assert(pTable->aCol == 0);
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;
+ assert(pSelTab->def->opts.temporary);
+
+ struct space_def *old_def = pTable->def;
+ struct space_def *new_def =
+ sql_ephemeral_space_def_clone(pParse, old_def);
+ if (new_def == NULL) {
+ nErr++;
+ } else {
+ new_def->fields = pSelTab->def->fields;
+ new_def->field_count = pSelTab->def->field_count;
+ pTable->def = new_def;
+ if (sql_table_def_rebuild(db, pTable) != 0)
+ nErr++;
+ }
pTable->aCol = pSelTab->aCol;
pSelTab->aCol = 0;
+ pSelTab->def = old_def;
+ pSelTab->def->fields = NULL;
+ pSelTab->def->field_count = 0;
} else {
pTable->def->field_count = 0;
nErr++;
@@ -2939,7 +2956,7 @@ sqlite3CreateIndex(Parse * pParse, /* All information about this parse */
if (!ifNotExist) {
sqlite3ErrorMsg(pParse,
"index %s.%s already exists",
- pTab->zName, zName);
+ pTab->def->name, zName);
} else {
assert(!db->init.busy);
}
@@ -2952,7 +2969,7 @@ sqlite3CreateIndex(Parse * pParse, /* All information about this parse */
pLoop = pLoop->pNext, n++) {
}
zName =
- sqlite3MPrintf(db, "sqlite_autoindex_%s_%d", pTab->zName,
+ sqlite3MPrintf(db, "sqlite_autoindex_%s_%d", pTab->def->name,
n);
if (zName == 0) {
goto exit_create_index;
@@ -4022,7 +4039,7 @@ sqlite3UniqueConstraint(Parse * pParse, /* Parsing context */
zCol = pTab->def->fields[pIdx->aiColumn[j]].name;
if (j)
sqlite3StrAccumAppend(&errMsg, ", ", 2);
- sqlite3XPrintf(&errMsg, "%s.%s", pTab->zName, zCol);
+ sqlite3XPrintf(&errMsg, "%s.%s", pTab->def->name, zCol);
}
}
zErr = sqlite3StrAccumFinish(&errMsg);
diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
index 65d20fa..c6ecba6 100644
--- a/src/box/sql/delete.c
+++ b/src/box/sql/delete.c
@@ -82,13 +82,13 @@ sqlite3IsReadOnly(Parse * pParse, Table * pTab, int viewOk)
*/
if ((pTab->tabFlags & TF_Readonly) != 0 && pParse->nested == 0) {
sqlite3ErrorMsg(pParse, "table %s may not be modified",
- pTab->zName);
+ pTab->def->name);
return 1;
}
#ifndef SQLITE_OMIT_VIEW
if (!viewOk && space_is_view(pTab)) {
sqlite3ErrorMsg(pParse, "cannot modify %s because it is a view",
- pTab->zName);
+ pTab->def->name);
return 1;
}
#endif
@@ -115,7 +115,7 @@ sqlite3MaterializeView(Parse * pParse, /* Parsing context */
pFrom = sqlite3SrcListAppend(db, 0, 0);
if (pFrom) {
assert(pFrom->nSrc == 1);
- pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
+ pFrom->a[0].zName = sqlite3DbStrDup(db, pView->def->name);
assert(pFrom->a[0].pOn == 0);
assert(pFrom->a[0].pUsing == 0);
}
diff --git a/src/box/sql/fkey.c b/src/box/sql/fkey.c
index 8c015c9..16f72d8 100644
--- a/src/box/sql/fkey.c
+++ b/src/box/sql/fkey.c
@@ -332,7 +332,7 @@ sqlite3FkLocateIndex(Parse * pParse, /* Parse context to store any error in */
if (!pParse->disableTriggers) {
sqlite3ErrorMsg(pParse,
"foreign key mismatch - \"%w\" referencing \"%w\"",
- pFKey->pFrom->zName, pFKey->zTo);
+ pFKey->pFrom->def->name, pFKey->zTo);
}
sqlite3DbFree(pParse->db, aiCol);
return 1;
@@ -721,7 +721,8 @@ fkScanChildren(Parse * pParse, /* Parse context */
FKey *
sqlite3FkReferences(Table * pTab)
{
- return (FKey *) sqlite3HashFind(&pTab->pSchema->fkeyHash, pTab->zName);
+ return (FKey *) sqlite3HashFind(&pTab->pSchema->fkeyHash,
+ pTab->def->name);
}
/*
@@ -951,7 +952,7 @@ sqlite3FkCheck(Parse * pParse, /* Parse context */
int bIgnore = 0;
if (aChange
- && sqlite3_stricmp(pTab->zName, pFKey->zTo) != 0
+ && sqlite3_stricmp(pTab->def->name, pFKey->zTo) != 0
&& fkChildIsModified(pFKey, aChange) == 0) {
continue;
}
@@ -1076,7 +1077,7 @@ sqlite3FkCheck(Parse * pParse, /* Parse context */
if (pSrc) {
struct SrcList_item *pItem = pSrc->a;
pItem->pTab = pFKey->pFrom;
- pItem->zName = pFKey->pFrom->zName;
+ pItem->zName = pFKey->pFrom->def->name;
pItem->pTab->nTabRef++;
pItem->iCursor = pParse->nTab++;
@@ -1375,7 +1376,7 @@ fkActionTrigger(Parse * pParse, /* Parse context */
}
sqlite3DbFree(db, aiCol);
- zFrom = pFKey->pFrom->zName;
+ zFrom = pFKey->pFrom->def->name;
nFrom = sqlite3Strlen30(zFrom);
if (action == OE_Restrict) {
diff --git a/src/box/sql/hash.c b/src/box/sql/hash.c
index cedcb7d..79f0840 100644
--- a/src/box/sql/hash.c
+++ b/src/box/sql/hash.c
@@ -69,6 +69,7 @@ sqlite3HashClear(Hash * pH)
while (elem) {
HashElem *next_elem = elem->next;
sqlite3_free(elem);
+ free((void *)elem->pKey);
elem = next_elem;
}
pH->count = 0;
@@ -292,7 +293,7 @@ sqlite3HashInsert(Hash * pH, const char *pKey, void *data)
removeElementGivenHash(pH, elem, h);
} else {
elem->data = data;
- elem->pKey = pKey;
+ elem->pKey = strdup(pKey);
}
return old_data;
}
@@ -301,7 +302,7 @@ sqlite3HashInsert(Hash * pH, const char *pKey, void *data)
new_elem = (HashElem *) sqlite3Malloc(sizeof(HashElem));
if (new_elem == 0)
return data;
- new_elem->pKey = pKey;
+ new_elem->pKey = strdup(pKey);
new_elem->data = data;
pH->count++;
if (pH->count >= 10 && pH->count > 2 * pH->htsize) {
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 06635ee..bde0cc1 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -56,7 +56,7 @@ sqlite3OpenTable(Parse * pParse, /* Generate code into this VDBE */
assert(pPk->tnum == pTab->tnum);
emit_open_cursor(pParse, iCur, pPk->tnum);
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
- VdbeComment((v, "%s", pTab->zName));
+ VdbeComment((v, "%s", pTab->def->name));
}
/*
@@ -1145,7 +1145,8 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */
case ON_CONFLICT_ACTION_ROLLBACK:
case ON_CONFLICT_ACTION_FAIL: {
char *zMsg =
- sqlite3MPrintf(db, "%s.%s", pTab->zName,
+ sqlite3MPrintf(db, "%s.%s",
+ pTab->def->name,
pTab->def->fields[i].name);
sqlite3VdbeAddOp3(v, OP_HaltIfNull,
SQLITE_CONSTRAINT_NOTNULL,
@@ -1200,7 +1201,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */
} else {
char *zName = pCheck->a[i].zName;
if (zName == 0)
- zName = pTab->zName;
+ zName = pTab->def->name;
if (onError == ON_CONFLICT_ACTION_REPLACE)
onError = ON_CONFLICT_ACTION_ABORT;
sqlite3HaltConstraint(pParse,
@@ -1404,7 +1405,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */
x = pPk->aiColumn[i];
sqlite3VdbeAddOp3(v, OP_Column,
iThisCur, x, regR + i);
- VdbeComment((v, "%s.%s", pTab->zName,
+ VdbeComment((v, "%s.%s", pTab->def->name,
pTab->def->fields[
pPk->aiColumn[i]].name));
}
diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c
index 0cf103c..463bb7e 100644
--- a/src/box/sql/pragma.c
+++ b/src/box/sql/pragma.c
@@ -405,7 +405,7 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */
i = sqliteHashNext(i)) {
Table *pTab = sqliteHashData(i);
sqlite3VdbeMultiLoad(v, 1, "ssii",
- pTab->zName,
+ pTab->def->name,
0,
pTab->szTabRow,
pTab->nRowLogEst);
@@ -623,7 +623,7 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */
pTab->def->field_count + regRow;
sqlite3OpenTable(pParse, 0, pTab, OP_OpenRead);
sqlite3VdbeLoadString(v, regResult,
- pTab->zName);
+ pTab->def->name);
for (i = 1, pFK = pTab->pFKey; pFK;
i++, pFK = pFK->pNextFrom) {
pParent =
diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c
index 109c410..5d85ef7 100644
--- a/src/box/sql/resolve.c
+++ b/src/box/sql/resolve.c
@@ -239,7 +239,8 @@ lookupName(Parse * pParse, /* The parsing context */
for (i = 0, pItem = pSrcList->a; i < pSrcList->nSrc;
i++, pItem++) {
pTab = pItem->pTab;
- assert(pTab != 0 && pTab->zName != 0);
+ assert(pTab != 0 &&
+ pTab->def->name != NULL);
assert(pTab->def->field_count > 0);
if (pItem->pSelect
&& (pItem->pSelect->
@@ -263,7 +264,7 @@ lookupName(Parse * pParse, /* The parsing context */
if (zTab) {
const char *zTabName =
pItem->zAlias ? pItem->
- zAlias : pTab->zName;
+ zAlias : pTab->def->name;
assert(zTabName != 0);
if (strcmp(zTabName, zTab) != 0) {
continue;
@@ -1604,7 +1605,7 @@ sqlite3ResolveSelfReference(Parse * pParse, /* Parsing context */
memset(&sNC, 0, sizeof(sNC));
memset(&sSrc, 0, sizeof(sSrc));
sSrc.nSrc = 1;
- sSrc.a[0].zName = pTab->zName;
+ sSrc.a[0].zName = pTab->def->name;
sSrc.a[0].pTab = pTab;
sSrc.a[0].iCursor = -1;
sNC.pParse = pParse;
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index fa1de9b..199caf0 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -1765,7 +1765,8 @@ generateColumnNames(Parse * pParse, /* Parser context */
} else if (fullNames) {
char *zName = 0;
zName =
- sqlite3MPrintf(db, "%s.%s", pTab->zName,
+ sqlite3MPrintf(db, "%s.%s",
+ pTab->def->name,
zCol);
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName,
SQLITE_DYNAMIC);
@@ -1825,14 +1826,6 @@ sqlite3ColumnsFromExprList(Parse * pParse, /* Parsing context */
struct region *region = &fiber()->gc;
assert(pTable->def->fields == NULL);
- if (pTable->def->opts.temporary == false) {
- /* CREATE VIEW name AS... without an argument list. Construct
- * the column names from the SELECT statement that defines the view.
- */
- pTable->def->field_count = 0;
- space_def_delete(pTable->def);
- pTable->def = sql_ephemeral_space_def_new(pParse);
- }
pTable->def->fields =
region_alloc(region, nCol*sizeof(pTable->def->fields[0]));
memset(pTable->def->fields, 0, nCol*sizeof(pTable->def->fields[0]));
@@ -1904,11 +1897,8 @@ sqlite3ColumnsFromExprList(Parse * pParse, /* Parsing context */
}
sqlite3HashClear(&ht);
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);
- sqlite3DbFree(db, pTable->def->fields);
pTable->def->fields = NULL;
pTable->def->field_count = 0;
pTable->aCol = 0;
@@ -1972,6 +1962,7 @@ sqlite3SelectAddColumnTypeAndCollation(Parse * pParse, /* Parsing contexts */
/*
* Given a SELECT statement, generate a Table structure that describes
* the result set of that SELECT.
+ * Return table with def is allocated on region.
*/
Table *
sqlite3ResultSetOfSelect(Parse * pParse, Select * pSelect)
@@ -1990,7 +1981,7 @@ sqlite3ResultSetOfSelect(Parse * pParse, Select * pSelect)
while (pSelect->pPrior)
pSelect = pSelect->pPrior;
user_session->sql_flags = savedFlags;
- pTab = sql_ephemeral_table_new(pParse);
+ pTab = sql_ephemeral_table_new(pParse, NULL);
if (pTab == NULL)
return 0;
/* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
@@ -1998,7 +1989,6 @@ sqlite3ResultSetOfSelect(Parse * pParse, Select * pSelect)
*/
assert(db->lookaside.bDisable);
pTab->nTabRef = 1;
- pTab->zName = 0;
pTab->nRowLogEst = 200;
assert(200 == sqlite3LogEst(1048576));
sqlite3ColumnsFromExprList(pParse, pSelect->pEList, pTab);
@@ -4522,11 +4512,11 @@ withExpand(Walker * pWalker, struct SrcList_item *pFrom)
return SQLITE_ERROR;
assert(pFrom->pTab == 0);
- pFrom->pTab = pTab = sql_ephemeral_table_new(pParse);
+ pFrom->pTab = pTab =
+ sql_ephemeral_table_new(pParse, pCte->zName);
if (pTab == NULL)
return WRC_Abort;
pTab->nTabRef = 1;
- pTab->zName = sqlite3DbStrDup(db, pCte->zName);
pTab->iPKey = -1;
pTab->nRowLogEst = 200;
assert(200 == sqlite3LogEst(1048576));
@@ -4691,12 +4681,14 @@ selectExpander(Walker * pWalker, Select * p)
for (i = 0, pFrom = pTabList->a; i < pTabList->nSrc; i++, pFrom++) {
Table *pTab;
assert(pFrom->fg.isRecursive == 0 || pFrom->pTab != 0);
- if (pFrom->fg.isRecursive)
+ if (pFrom->fg.isRecursive) {
continue;
+ }
assert(pFrom->pTab == 0);
#ifndef SQLITE_OMIT_CTE
- if (withExpand(pWalker, pFrom))
+ if (withExpand(pWalker, pFrom)) {
return WRC_Abort;
+ }
if (pFrom->pTab) {
} else
#endif
@@ -4707,17 +4699,24 @@ selectExpander(Walker * pWalker, Select * p)
assert(pFrom->pTab == 0);
if (sqlite3WalkSelect(pWalker, pSel))
return WRC_Abort;
+ char *name = "sqlite_sq_DEADBEAFDEADBEAF";
pFrom->pTab = pTab =
- sql_ephemeral_table_new(pParse);
+ sql_ephemeral_table_new(pParse, name);
if (pTab == NULL)
return WRC_Abort;
+ /* rewrite old name with correct pointer */
+ name = sqlite3MPrintf(db, "sqlite_sq_%p", (void *)pTab);
+ sprintf(pTab->def->name, "%s", name);
+ sqlite3DbFree(db, name);
+
pTab->nTabRef = 1;
- pTab->zName =
- sqlite3MPrintf(db, "sqlite_sq_%p", (void *)pTab);
while (pSel->pPrior) {
pSel = pSel->pPrior;
}
sqlite3ColumnsFromExprList(pParse, pSel->pEList, pTab);
+ if (sql_table_def_rebuild(db, pTab) != 0)
+ return WRC_Abort;
+
pTab->iPKey = -1;
pTab->nRowLogEst = 200;
assert(200 == sqlite3LogEst(1048576));
@@ -4727,12 +4726,13 @@ selectExpander(Walker * pWalker, Select * p)
assert(pFrom->pTab == 0);
pFrom->pTab = pTab =
sqlite3LocateTable(pParse, 0, pFrom->zName);
- if (pTab == NULL)
+ if (pTab == NULL) {
return WRC_Abort;
+ }
if (pTab->nTabRef >= 0xffff) {
sqlite3ErrorMsg(pParse,
"too many references to \"%s\": max 65535",
- pTab->zName);
+ pTab->def->name);
pFrom->pTab = 0;
return WRC_Abort;
}
@@ -4749,7 +4749,7 @@ selectExpander(Walker * pWalker, Select * p)
pFrom->pSelect =
sqlite3SelectDup(db, pTab->pSelect, 0);
sqlite3SelectSetName(pFrom->pSelect,
- pTab->zName);
+ pTab->def->name);
nCol = pTab->def->field_count;
pTab->def->field_count = -1;
sqlite3WalkSelect(pWalker, pFrom->pSelect);
@@ -4842,7 +4842,7 @@ selectExpander(Walker * pWalker, Select * p)
Select *pSub = pFrom->pSelect;
char *zTabName = pFrom->zAlias;
if (zTabName == 0) {
- zTabName = pTab->zName;
+ zTabName = pTab->def->name;
}
if (db->mallocFailed)
break;
@@ -5288,7 +5288,7 @@ explainSimpleCount(Parse * pParse, /* Parse context */
if (pParse->explain == 2) {
int bCover = (pIdx != 0 && !IsPrimaryKeyIndex(pIdx));
char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s%s%s",
- pTab->zName,
+ pTab->def->name,
bCover ? " USING COVERING INDEX " :
"",
bCover ? pIdx->zName : "");
@@ -5390,14 +5390,13 @@ sqlite3Select(Parse * pParse, /* The parser context */
Table *pTab = pItem->pTab;
if (pSub == 0)
continue;
-
/* Catch mismatch in the declared columns of a view and the number of
* columns in the SELECT on the RHS
*/
if ((int)pTab->def->field_count != pSub->pEList->nExpr) {
sqlite3ErrorMsg(pParse,
"expected %d columns for '%s' but got %d",
- pTab->def->field_count, pTab->zName,
+ pTab->def->field_count, pTab->def->name,
pSub->pEList->nExpr);
goto select_end;
}
@@ -5515,7 +5514,7 @@ sqlite3Select(Parse * pParse, /* The parser context */
pItem->regReturn = ++pParse->nMem;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn,
0, addrTop);
- VdbeComment((v, "%s", pItem->pTab->zName));
+ VdbeComment((v, "%s", pItem->pTab->def->name));
pItem->addrFillSub = addrTop;
sqlite3SelectDestInit(&dest, SRT_Coroutine,
pItem->regReturn);
@@ -5550,10 +5549,10 @@ sqlite3Select(Parse * pParse, /* The parser context */
onceAddr = sqlite3VdbeAddOp0(v, OP_Once);
VdbeCoverage(v);
VdbeComment((v, "materialize \"%s\"",
- pItem->pTab->zName));
+ pItem->pTab->def->name));
} else {
VdbeNoopComment((v, "materialize \"%s\"",
- pItem->pTab->zName));
+ pItem->pTab->def->name));
}
sqlite3SelectDestInit(&dest, SRT_EphemTab,
pItem->iCursor);
@@ -5564,7 +5563,7 @@ sqlite3Select(Parse * pParse, /* The parser context */
sqlite3VdbeJumpHere(v, onceAddr);
retAddr =
sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
- VdbeComment((v, "end %s", pItem->pTab->zName));
+ VdbeComment((v, "end %s", pItem->pTab->def->name));
sqlite3VdbeChangeP1(v, topAddr, retAddr);
sqlite3ClearTempRegCache(pParse);
}
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index a045286..6eddbec 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -1927,7 +1927,6 @@ struct Column {
* by an instance of the following structure.
*/
struct Table {
- char *zName; /* Name of the table or view */
Column *aCol; /* Information about each column */
Index *pIndex; /* List of SQL indexes on this table. */
Select *pSelect; /* NULL for tables. Points to definition if a view. */
diff --git a/src/box/sql/treeview.c b/src/box/sql/treeview.c
index 1ff949c..f9077c1 100644
--- a/src/box/sql/treeview.c
+++ b/src/box/sql/treeview.c
@@ -224,7 +224,7 @@ sqlite3TreeViewSelect(TreeView * pView, const Select * p, u8 moreToFollow)
}
if (pItem->pTab) {
sqlite3XPrintf(&x, " tabname=%Q",
- pItem->pTab->zName);
+ pItem->pTab->def->name);
}
if (pItem->zAlias) {
sqlite3XPrintf(&x, " (AS %s)",
diff --git a/src/box/sql/trigger.c b/src/box/sql/trigger.c
index 9b03be1..ae992eb 100644
--- a/src/box/sql/trigger.c
+++ b/src/box/sql/trigger.c
@@ -134,7 +134,7 @@ sqlite3BeginTrigger(Parse * pParse, /* The parse context of the CREATE TRIGGER s
}
/* Do not create a trigger on a system table */
- if (sqlite3StrNICmp(pTab->zName, "sqlite_", 7) == 0) {
+ if (sqlite3StrNICmp(pTab->def->name, "sqlite_", 7) == 0) {
sqlite3ErrorMsg(pParse,
"cannot create trigger on system table");
goto trigger_cleanup;
@@ -885,7 +885,7 @@ codeRowTrigger(Parse * pParse, /* Current parse context */
(pTrigger->op == TK_UPDATE ? "UPDATE" : ""),
(pTrigger->op == TK_INSERT ? "INSERT" : ""),
(pTrigger->op == TK_DELETE ? "DELETE" : ""),
- pTab->zName));
+ pTab->def->name));
#ifndef SQLITE_OMIT_TRACE
sqlite3VdbeChangeP4(v, -1,
sqlite3MPrintf(db, "-- TRIGGER %s",
diff --git a/src/box/sql/update.c b/src/box/sql/update.c
index 464feee..ad00537 100644
--- a/src/box/sql/update.c
+++ b/src/box/sql/update.c
@@ -75,7 +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, pTab->def->fields[i].name));
+ VdbeComment((v, "%s.%s", pTab->def->name,
+ pTab->def->fields[i].name));
assert(i < (int)pTab->def->field_count);
Expr *expr = NULL;
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 013460f..dc779b4 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -4799,7 +4799,7 @@ case OP_RenameTable: {
sqlite3HashInsert(&db->pSchema->fkeyHash, zNewTableName, pFKey);
}
- sqlite3UnlinkAndDeleteTable(db, pTab->zName);
+ sqlite3UnlinkAndDeleteTable(db, pTab->def->name);
initData.db = db;
initData.pzErrMsg = &p->zErrMsg;
diff --git a/src/box/sql/where.c b/src/box/sql/where.c
index fc0f84c..88f4c28 100644
--- a/src/box/sql/where.c
+++ b/src/box/sql/where.c
@@ -1639,7 +1639,8 @@ whereLoopPrint(WhereLoop * p, WhereClause * pWC)
sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId,
p->iTab, nb, p->maskSelf, nb, p->prereq & mAll);
sqlite3DebugPrintf(" %12s",
- pItem->zAlias ? pItem->zAlias : pTab->zName);
+ pItem->zAlias ? pItem->zAlias :
+ pTab->def->name);
#endif
const char *zName;
if (p->pIndex && (zName = p->pIndex->zName) != 0) {
@@ -4749,7 +4750,7 @@ sqlite3WhereEnd(WhereInfo * pWInfo)
}
VdbeModuleComment((v, "End WHERE-loop%d: %s", i,
pWInfo->pTabList->a[pLevel->iFrom].pTab->
- zName));
+ def->name));
}
/* The "break" point is here, just past the end of the outer loop.
diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
index 233fde0..3da7cdb 100644
--- a/src/box/sql/wherecode.c
+++ b/src/box/sql/wherecode.c
@@ -1158,7 +1158,8 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo, /* Complete information about t
pTabItem->addrFillSub);
pLevel->p2 = sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk);
VdbeCoverage(v);
- VdbeComment((v, "next row of \"%s\"", pTabItem->pTab->zName));
+ VdbeComment((v, "next row of \"%s\"",
+ pTabItem->pTab->def->name));
pLevel->op = OP_Goto;
} else if (pLoop->wsFlags & WHERE_INDEXED) {
/* Case 4: A scan using an index.
diff --git a/src/box/sql/whereexpr.c b/src/box/sql/whereexpr.c
index 1b0d961..e602111 100644
--- a/src/box/sql/whereexpr.c
+++ b/src/box/sql/whereexpr.c
@@ -1508,7 +1508,7 @@ sqlite3WhereTabFuncArgs(Parse * pParse, /* Parsing context */
if (k >= (int)pTab->def->field_count) {
sqlite3ErrorMsg(pParse,
"too many arguments on %s() - max %d",
- pTab->zName, j);
+ pTab->def->name, j);
return;
}
pColRef = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0);
--
2.7.4
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] [PATCH v4 6/7] sql: start using is_view field from space_def
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 0/7] sql: refactor SQL Parser structures Kirill Shcherbatov
` (4 preceding siblings ...)
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 5/7] sql: move names to server Kirill Shcherbatov
@ 2018-04-28 18:26 ` Kirill Shcherbatov
2018-05-03 11:16 ` [tarantool-patches] " Vladislav Shpilevoy
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 7/7] sql: space_def* instead of Table* in Expr Kirill Shcherbatov
2018-05-03 10:10 ` [tarantool-patches] Re: [PATCH v4 0/7] sql: refactor SQL Parser structures Vladislav Shpilevoy
7 siblings, 1 reply; 26+ messages in thread
From: Kirill Shcherbatov @ 2018-04-28 18:26 UTC (permalink / raw)
To: tarantool-patches; +Cc: v.shpilevoy, Kirill Shcherbatov
Part of #3272.
---
src/box/sql.c | 2 ++
src/box/sql/build.c | 24 +++++++++++++++++-------
src/box/sql/delete.c | 9 ++++++---
src/box/sql/expr.c | 3 ++-
src/box/sql/select.c | 2 ++
src/box/sql/update.c | 3 ++-
6 files changed, 31 insertions(+), 12 deletions(-)
diff --git a/src/box/sql.c b/src/box/sql.c
index 47f7cb1..9f5a124 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -1511,6 +1511,8 @@ int tarantoolSqlite3MakeTableOpts(Table *pTable, const char *zSql, void *buf)
bool is_view = false;
if (pTable != NULL)
is_view = pTable->pSelect != NULL;
+ assert(!pTable || pTable->def->opts.is_view == is_view);
+
p = enc->encode_map(base, is_view ? 2 : 1);
p = enc->encode_str(p, "sql", 3);
p = enc->encode_str(p, zSql, strlen(zSql));
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 4e0ae87..a98a6bd 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -1844,7 +1844,8 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
if (db->init.busy)
p->tnum = db->init.newTnum;
- if (!p->pSelect) {
+ assert(p->def->opts.is_view == (p->pSelect != NULL));
+ if (!p->def->opts.is_view) {
if ((p->tabFlags & TF_HasPrimaryKey) == 0) {
sqlite3ErrorMsg(pParse,
"PRIMARY KEY missing on table %s",
@@ -1892,7 +1893,8 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
/*
* Initialize zType for the new view or table.
*/
- if (p->pSelect == 0) {
+ assert(p->def->opts.is_view == (p->pSelect != NULL));
+ if (!p->def->opts.is_view) {
/* A regular table */
zType = "TABLE";
#ifndef SQLITE_OMIT_VIEW
@@ -1921,7 +1923,9 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
if (pSelect) {
zStmt = createTableStmt(db, p);
} else {
- Token *pEnd2 = p->pSelect ? &pParse->sLastToken : pEnd;
+ assert(p->def->opts.is_view == (p->pSelect != NULL));
+ Token *pEnd2 = p->def->opts.is_view ?
+ &pParse->sLastToken : pEnd;
n = (int)(pEnd2->z - pParse->sNameToken.z);
if (pEnd2->z[0] != ';')
n += pEnd2->n;
@@ -1933,7 +1937,8 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
iSpaceId = getNewSpaceId(pParse);
createSpace(pParse, iSpaceId, zStmt);
/* Indexes aren't required for VIEW's. */
- if (p->pSelect == NULL) {
+ assert(p->def->opts.is_view == (p->pSelect != NULL));
+ if (!p->def->opts.is_view) {
createImplicitIndices(pParse, iSpaceId);
}
@@ -1981,7 +1986,8 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
current_session()->sql_flags |= SQLITE_InternChanges;
#ifndef SQLITE_OMIT_ALTERTABLE
- if (!p->pSelect) {
+ assert(p->def->opts.is_view == (p->pSelect != NULL));
+ if (!p->def->opts.is_view) {
const char *zName = (const char *)pParse->sNameToken.z;
int nName;
assert(!pSelect && pCons && pEnd);
@@ -2033,6 +2039,7 @@ sqlite3CreateView(Parse * pParse, /* The parsing context */
* they will persist after the current sqlite3_exec() call returns.
*/
p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
+ p->def->opts.is_view = true;
p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE);
if (db->mallocFailed)
goto create_view_fail;
@@ -2119,6 +2126,7 @@ sqlite3ViewGetColumnNames(Parse * pParse, Table * pTable)
* statement that defines the view.
*/
assert(pTable->pSelect);
+ assert(pTable->def->opts.is_view == (pTable->pSelect != NULL));
pSel = sqlite3SelectDup(db, pTable->pSelect, 0);
if (pSel) {
n = pParse->nTab;
@@ -2197,7 +2205,8 @@ sqliteViewResetAll(sqlite3 * db)
for (i = sqliteHashFirst(&db->pSchema->tblHash); i;
i = sqliteHashNext(i)) {
Table *pTab = sqliteHashData(i);
- if (pTab->pSelect) {
+ assert(pTab->def->opts.is_view == (pTab->pSelect != NULL));
+ if (pTab->def->opts.is_view) {
sqlite3DeleteColumnNames(db, pTab);
struct space_def *old_def = pTab->def;
assert(old_def->opts.temporary == false);
@@ -2920,7 +2929,8 @@ sqlite3CreateIndex(Parse * pParse, /* All information about this parse */
assert(pTab != 0);
assert(pParse->nErr == 0);
#ifndef SQLITE_OMIT_VIEW
- if (pTab->pSelect) {
+ assert(pTab->def->opts.is_view == (pTab->pSelect != NULL));
+ if (pTab->def->opts.is_view) {
sqlite3ErrorMsg(pParse, "views may not be indexed");
goto exit_create_index;
}
diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
index c6ecba6..37baca2 100644
--- a/src/box/sql/delete.c
+++ b/src/box/sql/delete.c
@@ -283,7 +283,8 @@ sqlite3DeleteFrom(Parse * pParse, /* The parser context */
*/
#ifndef SQLITE_OMIT_TRIGGER
pTrigger = sqlite3TriggersExist(pTab, TK_DELETE, 0, 0);
- isView = pTab->pSelect != 0;
+ assert(pTab->def->opts.is_view == (pTab->pSelect != NULL));
+ isView = pTab->def->opts.is_view;
bComplex = pTrigger || sqlite3FkRequired(pTab, 0);
#else
#define pTrigger 0
@@ -512,7 +513,8 @@ sqlite3DeleteFrom(Parse * pParse, /* The parser context */
if (eOnePass != ONEPASS_OFF) {
assert(nKey == nPk); /* OP_Found will use an unpacked key */
if (aToOpen[iDataCur - iTabCur]) {
- assert(pPk != 0 || pTab->pSelect != 0);
+ assert(pTab->def->opts.is_view == (pTab->pSelect != NULL));
+ assert(pPk != 0 || pTab->def->opts.is_view);
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur,
addrBypass, iKey, nKey);
@@ -786,7 +788,8 @@ sqlite3GenerateRowDelete(Parse * pParse, /* Parsing context */
* the update-hook is not invoked for rows removed by REPLACE, but the
* pre-update-hook is.
*/
- if (pTab->pSelect == 0) {
+ assert(pTab->def->opts.is_view == (pTab->pSelect != NULL));
+ if (!pTab->def->opts.is_view) {
u8 p5 = 0;
/* kyukhin: Tarantool handles indices uypdate automatically. */
/* sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); */
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 5f7d741..119940c 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -2233,7 +2233,8 @@ isCandidateForInOpt(Expr * pX)
return 0; /* FROM is not a subquery or view */
pTab = pSrc->a[0].pTab;
assert(pTab != 0);
- assert(pTab->pSelect == 0); /* FROM clause is not a view */
+ assert(pTab->def->opts.is_view == (pTab->pSelect != NULL));
+ assert(!pTab->def->opts.is_view); /* FROM clause is not a view */
pEList = p->pEList;
assert(pEList != 0);
/* All SELECT results must be columns. */
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index 199caf0..34d296d 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -4746,6 +4746,8 @@ selectExpander(Walker * pWalker, Select * p)
if (sqlite3ViewGetColumnNames(pParse, pTab))
return WRC_Abort;
assert(pFrom->pSelect == 0);
+ assert(pTab->def->opts.is_view ==
+ (pTab->pSelect != NULL));
pFrom->pSelect =
sqlite3SelectDup(db, pTab->pSelect, 0);
sqlite3SelectSetName(pFrom->pSelect,
diff --git a/src/box/sql/update.c b/src/box/sql/update.c
index ad00537..2f36423 100644
--- a/src/box/sql/update.c
+++ b/src/box/sql/update.c
@@ -72,7 +72,8 @@ void
sqlite3ColumnDefault(Vdbe * v, Table * pTab, int i, int iReg)
{
assert(pTab != 0);
- if (!pTab->pSelect) {
+ assert(pTab->def->opts.is_view == (pTab->pSelect != NULL));
+ if (!pTab->def->opts.is_view) {
sqlite3_value *pValue = 0;
Column *pCol = &pTab->aCol[i];
VdbeComment((v, "%s.%s", pTab->def->name,
--
2.7.4
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] [PATCH v4 7/7] sql: space_def* instead of Table* in Expr
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 0/7] sql: refactor SQL Parser structures Kirill Shcherbatov
` (5 preceding siblings ...)
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 6/7] sql: start using is_view field from space_def Kirill Shcherbatov
@ 2018-04-28 18:26 ` Kirill Shcherbatov
2018-05-03 11:32 ` [tarantool-patches] " Vladislav Shpilevoy
2018-05-03 10:10 ` [tarantool-patches] Re: [PATCH v4 0/7] sql: refactor SQL Parser structures Vladislav Shpilevoy
7 siblings, 1 reply; 26+ messages in thread
From: Kirill Shcherbatov @ 2018-04-28 18:26 UTC (permalink / raw)
To: tarantool-patches; +Cc: v.shpilevoy, Kirill Shcherbatov
Part of #3272.
---
src/box/field_def.c | 1 +
src/box/field_def.h | 5 ++++
src/box/sql.c | 10 ++++----
src/box/sql/build.c | 48 ++++++++++++++++++++------------------
src/box/sql/delete.c | 4 ++--
src/box/sql/expr.c | 61 ++++++++++++++++++++++++++-----------------------
src/box/sql/fkey.c | 13 +++++------
src/box/sql/insert.c | 24 ++++++++++---------
src/box/sql/pragma.c | 8 ++++---
src/box/sql/resolve.c | 10 ++++----
src/box/sql/select.c | 26 +++++++++++++--------
src/box/sql/sqliteInt.h | 21 +++++++++--------
src/box/sql/update.c | 29 +++++++++++------------
src/box/sql/vdbeaux.c | 20 ++++++----------
src/box/sql/where.c | 13 +++++++----
src/box/sql/wherecode.c | 18 +++++++++------
src/box/sql/whereexpr.c | 2 +-
17 files changed, 167 insertions(+), 146 deletions(-)
diff --git a/src/box/field_def.c b/src/box/field_def.c
index 010b3b7..63aab46 100644
--- a/src/box/field_def.c
+++ b/src/box/field_def.c
@@ -100,6 +100,7 @@ const struct opt_def field_def_reg[] = {
const struct field_def field_def_default = {
.type = FIELD_TYPE_ANY,
+ .affinity = 0,
.name = NULL,
.is_nullable = false,
.nullable_action = ON_CONFLICT_ACTION_DEFAULT,
diff --git a/src/box/field_def.h b/src/box/field_def.h
index dfc1950..4577f6b 100644
--- a/src/box/field_def.h
+++ b/src/box/field_def.h
@@ -102,6 +102,11 @@ struct field_def {
* then UNKNOWN is stored for it.
*/
enum field_type type;
+ /**
+ * Affinity type for comparations in SQL.
+ * FIXME: Remove affinity after types redesign in SQL.
+ */
+ char affinity;
/** 0-terminated field name. */
char *name;
/** True, if a field can store NULL. */
diff --git a/src/box/sql.c b/src/box/sql.c
index 9f5a124..11ec0b1 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -1428,7 +1428,6 @@ static const char *convertSqliteAffinity(int affinity, bool allow_nulls)
*/
int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
{
- struct Column *aCol = pTable->aCol;
const struct Enc *enc = get_enc(buf);
const struct space_def *def = pTable->def;
assert(def != NULL);
@@ -1471,8 +1470,9 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
if (i == pk_forced_int) {
t = "integer";
} else {
- t = aCol[i].affinity == SQLITE_AFF_BLOB ? "scalar" :
- convertSqliteAffinity(aCol[i].affinity,
+ char affinity = def->fields[i].affinity;
+ t = affinity == SQLITE_AFF_BLOB ? "scalar" :
+ convertSqliteAffinity(affinity,
def->fields[i].is_nullable);
}
p = enc->encode_str(p, t, strlen(t));
@@ -1532,7 +1532,6 @@ int tarantoolSqlite3MakeTableOpts(Table *pTable, const char *zSql, void *buf)
*/
int tarantoolSqlite3MakeIdxParts(SqliteIndex *pIndex, void *buf)
{
- struct Column *aCol = pIndex->pTable->aCol;
struct space_def *def = pIndex->pTable->def;
assert(def != NULL);
@@ -1569,7 +1568,8 @@ int tarantoolSqlite3MakeIdxParts(SqliteIndex *pIndex, void *buf)
if (pk_forced_int == col) {
t = "integer";
} else {
- t = convertSqliteAffinity(aCol[col].affinity,
+ char affinity = def->fields[col].affinity;
+ t = convertSqliteAffinity(affinity,
def->fields[col].is_nullable);
}
/* do not decode default collation */
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index a98a6bd..742f8a5 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -701,7 +701,7 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
* TODO: since SQL standard prohibits column creation without
* specified type, the code below should emit an error.
*/
- pCol->affinity = SQLITE_AFF_BLOB;
+ column_def->affinity = SQLITE_AFF_BLOB;
pCol->szEst = 1;
column_def->type = FIELD_TYPE_SCALAR;
} else {
@@ -712,14 +712,14 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
pType->n == 7) ||
(sqlite3StrNICmp(pType->z, "INT", 3) == 0 &&
pType->n == 3)) {
- pCol->affinity = SQLITE_AFF_INTEGER;
+ column_def->affinity = SQLITE_AFF_INTEGER;
column_def->type = FIELD_TYPE_INTEGER;
} else {
zType = sqlite3_malloc(pType->n + 1);
memcpy(zType, pType->z, pType->n);
zType[pType->n] = 0;
sqlite3Dequote(zType);
- pCol->affinity = sqlite3AffinityType(zType, 0);
+ column_def->affinity = sqlite3AffinityType(zType, 0);
sqlite3_free(zType);
column_def->type = FIELD_TYPE_SCALAR;
}
@@ -1032,8 +1032,10 @@ sqlite3AddCollateType(Parse * pParse, Token * pToken)
*/
for (pIdx = p->pIndex; pIdx; pIdx = pIdx->pNext) {
assert(pIdx->nColumn == 1);
- if (pIdx->aiColumn[0] == i)
- pIdx->coll_array[0] = sql_column_collation(p, i);
+ if (pIdx->aiColumn[0] == i) {
+ pIdx->coll_array[0] =
+ sql_column_collation(p->def, i);
+ }
}
}
}
@@ -1046,10 +1048,10 @@ sqlite3AddCollateType(Parse * pParse, Token * pToken)
* @retval Pointer to collation.
*/
struct coll *
-sql_column_collation(Table *table, uint32_t column)
+sql_column_collation(struct space_def *def, uint32_t column)
{
- assert(table != NULL);
- uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(table->tnum);
+ assert(def != NULL);
+ uint32_t space_id = def->id;
struct space *space = space_by_id(space_id);
/*
* It is not always possible to fetch collation directly
@@ -1064,9 +1066,9 @@ sql_column_collation(Table *table, uint32_t column)
* SQL specific structures.
*/
if (space == NULL || space_index(space, 0) == NULL) {
- assert(column < (uint32_t)table->def->field_count);
+ assert(column < (uint32_t)def->field_count);
struct coll *coll =
- coll_by_id(table->def->fields[column].coll_id);
+ coll_by_id(def->fields[column].coll_id);
return coll;
}
@@ -1322,18 +1324,19 @@ createTableStmt(sqlite3 * db, Table * p)
k += sqlite3Strlen30(&zStmt[k]);
zSep = zSep2;
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);
- testcase(pCol->affinity == SQLITE_AFF_TEXT);
- testcase(pCol->affinity == SQLITE_AFF_NUMERIC);
- testcase(pCol->affinity == SQLITE_AFF_INTEGER);
- testcase(pCol->affinity == SQLITE_AFF_REAL);
-
- zType = azType[pCol->affinity - SQLITE_AFF_BLOB];
+ char affinity = p->def->fields[i].affinity;
+ assert(affinity - SQLITE_AFF_BLOB >= 0);
+ assert(affinity - SQLITE_AFF_BLOB < ArraySize(azType));
+ testcase(affinity == SQLITE_AFF_BLOB);
+ testcase(affinity == SQLITE_AFF_TEXT);
+ testcase(affinity == SQLITE_AFF_NUMERIC);
+ testcase(affinity == SQLITE_AFF_INTEGER);
+ testcase(affinity == SQLITE_AFF_REAL);
+
+ zType = azType[affinity - SQLITE_AFF_BLOB];
len = sqlite3Strlen30(zType);
- assert(pCol->affinity == SQLITE_AFF_BLOB
- || pCol->affinity == sqlite3AffinityType(zType, 0));
+ assert(affinity == SQLITE_AFF_BLOB
+ || affinity == sqlite3AffinityType(zType, 0));
memcpy(&zStmt[k], zType, len);
k += len;
assert(k <= n);
@@ -1843,6 +1846,7 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
*/
if (db->init.busy)
p->tnum = db->init.newTnum;
+ p->def->id = SQLITE_PAGENO_TO_SPACEID(p->tnum);
assert(p->def->opts.is_view == (p->pSelect != NULL));
if (!p->def->opts.is_view) {
@@ -3094,7 +3098,7 @@ sqlite3CreateIndex(Parse * pParse, /* All information about this parse */
goto exit_create_index;
}
} else if (j >= 0) {
- coll = sql_column_collation(pTab, j);
+ coll = sql_column_collation(pTab->def, j);
} else {
coll = NULL;
}
diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
index 37baca2..5056005 100644
--- a/src/box/sql/delete.c
+++ b/src/box/sql/delete.c
@@ -431,7 +431,7 @@ sqlite3DeleteFrom(Parse * pParse, /* The parser context */
if (!isView) {
for (i = 0; i < nPk; i++) {
assert(pPk->aiColumn[i] >= 0);
- sqlite3ExprCodeGetColumnOfTable(v, pTab,
+ sqlite3ExprCodeGetColumnOfTable(v, pTab->def,
iTabCur,
pPk->
aiColumn[i],
@@ -747,7 +747,7 @@ sqlite3GenerateRowDelete(Parse * pParse, /* Parsing context */
testcase(mask != 0xffffffff && iCol == 32);
if (mask == 0xffffffff
|| (iCol <= 31 && (mask & MASKBIT32(iCol)) != 0)) {
- sqlite3ExprCodeGetColumnOfTable(v, pTab,
+ sqlite3ExprCodeGetColumnOfTable(v, pTab->def,
iDataCur, iCol,
iOld + iCol +
1);
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 119940c..4e20098 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -46,10 +46,11 @@ static int exprCodeVector(Parse * pParse, Expr * p, int *piToFree);
* Return the affinity character for a single column of a table.
*/
char
-sqlite3TableColumnAffinity(Table * pTab, int iCol)
+sqlite3TableColumnAffinity(struct space_def *def, int iCol)
{
- assert(iCol < (int)pTab->def->field_count);
- return iCol >= 0 ? pTab->aCol[iCol].affinity : SQLITE_AFF_INTEGER;
+ assert(iCol < (int)def->field_count);
+ return iCol >= 0 ? def->fields[iCol].affinity :
+ SQLITE_AFF_INTEGER;
}
/*
@@ -90,7 +91,8 @@ sqlite3ExprAffinity(Expr * pExpr)
}
#endif
if (op == TK_AGG_COLUMN || op == TK_COLUMN) {
- return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn);
+ return sqlite3TableColumnAffinity(pExpr->space_def,
+ pExpr->iColumn);
}
if (op == TK_SELECT_COLUMN) {
assert(pExpr->pLeft->flags & EP_xIsSelect);
@@ -179,13 +181,13 @@ sql_expr_coll(Parse *parse, Expr *p, bool *is_found)
}
if ((op == TK_AGG_COLUMN || op == TK_COLUMN ||
op == TK_REGISTER || op == TK_TRIGGER) &&
- p->pTab != 0) {
+ p->space_def != 0) {
/* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
* a TK_COLUMN but was previously evaluated and cached in a register
*/
int j = p->iColumn;
if (j >= 0) {
- coll = sql_column_collation(p->pTab, j);
+ coll = sql_column_collation(p->space_def, j);
*is_found = true;
}
break;
@@ -2132,10 +2134,10 @@ sqlite3ExprCanBeNull(const Expr * p)
case TK_BLOB:
return 0;
case TK_COLUMN:
- assert(p->pTab != 0);
+ assert(p->space_def!= 0);
return ExprHasProperty(p, EP_CanBeNull) ||
(p->iColumn >= 0
- && table_column_is_nullable(p->pTab, p->iColumn));
+ && table_column_is_nullable(p->space_def, p->iColumn));
default:
return 1;
}
@@ -2435,7 +2437,9 @@ sqlite3FindInIndex(Parse * pParse, /* Parsing context */
for (i = 0; i < nExpr && affinity_ok; i++) {
Expr *pLhs = sqlite3VectorFieldSubexpr(pX->pLeft, i);
int iCol = pEList->a[i].pExpr->iColumn;
- char idxaff = sqlite3TableColumnAffinity(pTab, iCol); /* RHS table */
+ /* RHS table */
+ char idxaff =
+ sqlite3TableColumnAffinity(pTab->def, iCol);
char cmpaff = sqlite3CompareAffinity(pLhs, idxaff);
testcase(cmpaff == SQLITE_AFF_BLOB);
testcase(cmpaff == SQLITE_AFF_TEXT);
@@ -3175,8 +3179,9 @@ sqlite3ExprCodeIN(Parse * pParse, /* Parsing and code generating context */
struct Index *pk = sqlite3PrimaryKeyIndex(tab);
assert(pk);
+ char affinity = tab->def->fields[pk->aiColumn[0]].affinity;
if (pk->nColumn == 1
- && tab->aCol[pk->aiColumn[0]].affinity == 'D'
+ && affinity == 'D'
&& pk->aiColumn[0] < nVector) {
int reg_pk = rLhs + pk->aiColumn[0];
sqlite3VdbeAddOp2(v, OP_MustBeInt, reg_pk, destIfFalse);
@@ -3519,7 +3524,7 @@ sqlite3ExprCodeLoadIndexColumn(Parse * pParse, /* The parsing context */
sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[iIdxCol].pExpr,
regOut);
} else {
- sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable,
+ sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable->def,
iTabCur, iTabCol, regOut);
}
}
@@ -3529,7 +3534,7 @@ sqlite3ExprCodeLoadIndexColumn(Parse * pParse, /* The parsing context */
*/
void
sqlite3ExprCodeGetColumnOfTable(Vdbe * v, /* The VDBE under construction */
- Table * pTab, /* The table containing the value */
+ struct space_def *space_def,
int iTabCur, /* The PK cursor */
int iCol, /* Index of the column to extract */
int regOut /* Extract the value into this register */
@@ -3537,7 +3542,7 @@ sqlite3ExprCodeGetColumnOfTable(Vdbe * v, /* The VDBE under construction */
{
sqlite3VdbeAddOp3(v, OP_Column, iTabCur, iCol, regOut);
if (iCol >= 0) {
- sqlite3ColumnDefault(v, pTab, iCol, regOut);
+ sqlite3ColumnDefault(v, space_def, iCol, regOut);
}
}
@@ -3552,7 +3557,7 @@ sqlite3ExprCodeGetColumnOfTable(Vdbe * v, /* The VDBE under construction */
*/
int
sqlite3ExprCodeGetColumn(Parse * pParse, /* Parsing and code generating context */
- Table * pTab, /* Description of the table we are reading from */
+ struct space_def * space_def,
int iColumn, /* Index of the table column */
int iTable, /* The cursor pointing to the table */
int iReg, /* Store results here */
@@ -3572,7 +3577,7 @@ sqlite3ExprCodeGetColumn(Parse * pParse, /* Parsing and code generating context
}
}
assert(v != 0);
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg);
+ sqlite3ExprCodeGetColumnOfTable(v, space_def, iTable, iColumn, iReg);
if (p5) {
sqlite3VdbeChangeP5(v, p5);
} else {
@@ -3583,14 +3588,14 @@ sqlite3ExprCodeGetColumn(Parse * pParse, /* Parsing and code generating context
void
sqlite3ExprCodeGetColumnToReg(Parse * pParse, /* Parsing and code generating context */
- Table * pTab, /* Description of the table we are reading from */
+ struct space_def * space_def,
int iColumn, /* Index of the table column */
int iTable, /* The cursor pointing to the table */
int iReg /* Store results here */
)
{
int r1 =
- sqlite3ExprCodeGetColumn(pParse, pTab, iColumn, iTable, iReg, 0);
+ sqlite3ExprCodeGetColumn(pParse, space_def, iColumn, iTable, iReg, 0);
if (r1 != iReg)
sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, r1, iReg);
}
@@ -3777,7 +3782,7 @@ sqlite3ExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
iTab = pParse->iSelfTab;
}
}
- return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
+ return sqlite3ExprCodeGetColumn(pParse, pExpr->space_def,
pExpr->iColumn, iTab,
target, pExpr->op2);
}
@@ -4241,23 +4246,21 @@ sqlite3ExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
* p1==1 -> old.a p1==4 -> new.a
* p1==2 -> old.b p1==5 -> new.b
*/
- Table *pTab = pExpr->pTab;
+ struct space_def *def = pExpr->space_def;
int p1 =
- pExpr->iTable * (pTab->def->field_count + 1) + 1 +
+ pExpr->iTable * (def->field_count + 1) + 1 +
pExpr->iColumn;
assert(pExpr->iTable == 0 || pExpr->iTable == 1);
assert(pExpr->iColumn >= 0
- && pExpr->iColumn < (int)pTab->def->field_count);
- assert(pTab->iPKey < 0
- || pExpr->iColumn != pTab->iPKey);
+ && pExpr->iColumn < (int)def->field_count);
assert(p1 >= 0 && p1 <
- ((int)pTab->def->field_count * 2 + 2));
+ ((int)def->field_count * 2 + 2));
sqlite3VdbeAddOp2(v, OP_Param, p1, target);
VdbeComment((v, "%s.%s -> $%d",
(pExpr->iTable ? "new" : "old"),
- pExpr->pTab->def->fields[pExpr->iColumn].name,
+ def->fields[pExpr->iColumn].name,
target));
#ifndef SQLITE_OMIT_FLOATING_POINT
@@ -4267,9 +4270,9 @@ sqlite3ExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
* EVIDENCE-OF: R-60985-57662 SQLite will convert the value back to
* floating point when extracting it from the record.
*/
+ char affinity = def->fields[pExpr->iColumn].affinity;
if (pExpr->iColumn >= 0
- && pTab->aCol[pExpr->iColumn].affinity ==
- SQLITE_AFF_REAL) {
+ && affinity == SQLITE_AFF_REAL) {
sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
}
#endif
@@ -5440,8 +5443,8 @@ analyzeAggregate(Walker * pWalker, Expr * pExpr)
pAggInfo)) >= 0) {
pCol =
&pAggInfo->aCol[k];
- pCol->pTab =
- pExpr->pTab;
+ pCol->space_def =
+ pExpr->space_def;
pCol->iTable =
pExpr->iTable;
pCol->iColumn =
diff --git a/src/box/sql/fkey.c b/src/box/sql/fkey.c
index 16f72d8..52f86d4 100644
--- a/src/box/sql/fkey.c
+++ b/src/box/sql/fkey.c
@@ -299,7 +299,7 @@ sqlite3FkLocateIndex(Parse * pParse, /* Parse context to store any error in */
* unusable. Bail out early in this case.
*/
struct coll *def_coll;
- def_coll = sql_column_collation(pParent,
+ def_coll = sql_column_collation(pParent->def,
iCol);
struct coll *coll;
coll = sql_index_collation(pIdx, i);
@@ -527,15 +527,14 @@ exprTableRegister(Parse * pParse, /* Parsing and code generating context */
)
{
Expr *pExpr;
- Column *pCol;
sqlite3 *db = pParse->db;
pExpr = sqlite3Expr(db, TK_REGISTER, 0);
if (pExpr) {
if (iCol >= 0 && iCol != pTab->iPKey) {
- pCol = &pTab->aCol[iCol];
pExpr->iTable = regBase + iCol + 1;
- pExpr->affinity = pCol->affinity;
+ char affinity = pTab->def->fields[iCol].affinity;
+ pExpr->affinity = affinity;
const char *coll_name = "binary";
pExpr = sqlite3ExprAddCollateString(pParse, pExpr,
coll_name);
@@ -553,14 +552,14 @@ exprTableRegister(Parse * pParse, /* Parsing and code generating context */
*/
static Expr *
exprTableColumn(sqlite3 * db, /* The database connection */
- Table * pTab, /* The table whose column is desired */
+ struct space_def *def,
int iCursor, /* The open cursor on the table */
i16 iCol /* The column that is wanted */
)
{
Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0);
if (pExpr) {
- pExpr->pTab = pTab;
+ pExpr->space_def = def;
pExpr->iTable = iCursor;
pExpr->iColumn = iCol;
}
@@ -673,7 +672,7 @@ fkScanChildren(Parse * pParse, /* Parse context */
i16 iCol = pIdx->aiColumn[i];
assert(iCol >= 0);
pLeft = exprTableRegister(pParse, pTab, regData, iCol);
- pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor,
+ pRight = exprTableColumn(db, pTab->def, pSrc->a[0].iCursor,
iCol);
pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight);
pAll = sqlite3ExprAnd(db, pAll, pEq);
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index bde0cc1..7c21359 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -90,7 +90,6 @@ sqlite3IndexAffinityStr(sqlite3 * db, Index * pIdx)
*/
int n;
int nColumn = index_column_count(pIdx);
- Table *pTab = pIdx->pTable;
pIdx->zColAff =
(char *)sqlite3DbMallocRaw(0, nColumn + 1);
if (!pIdx->zColAff) {
@@ -100,7 +99,9 @@ sqlite3IndexAffinityStr(sqlite3 * db, Index * pIdx)
for (n = 0; n < nColumn; n++) {
i16 x = pIdx->aiColumn[n];
if (x >= 0) {
- pIdx->zColAff[n] = pTab->aCol[x].affinity;
+ char affinity = pIdx->pTable->
+ def->fields[x].affinity;
+ pIdx->zColAff[n] = affinity;
} else {
char aff;
assert(x == XN_EXPR);
@@ -154,7 +155,8 @@ sqlite3TableAffinity(Vdbe * v, Table * pTab, int iReg)
}
for (i = 0; i < (int)pTab->def->field_count; i++) {
- zColAff[i] = pTab->aCol[i].affinity;
+ char affinity = pTab->def->fields[i].affinity;
+ zColAff[i] = affinity;
}
do {
zColAff[i--] = 0;
@@ -1115,7 +1117,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */
/* Don't bother checking for NOT NULL on columns that do not change */
continue;
}
- if (table_column_is_nullable(pTab, i)
+ if (table_column_is_nullable(pTab->def, i)
|| (pTab->tabFlags & TF_Autoincrement
&& pTab->iAutoIncPKey == i))
continue; /* This column is allowed to be NULL */
@@ -1805,17 +1807,17 @@ xferOptimization(Parse * pParse, /* Parser context */
return 0; /* Both tables must have the same INTEGER PRIMARY KEY */
}
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) {
+ char pdest_affinity = pDest->def->fields[i].affinity;
+ char psrc_affinity = pSrc->def->fields[i].affinity;
+ if (pdest_affinity != psrc_affinity) {
return 0; /* Affinity must be the same on all columns */
}
- if (sql_column_collation(pDest, i) !=
- sql_column_collation(pSrc, i)) {
+ if (sql_column_collation(pDest->def, i) !=
+ sql_column_collation(pSrc->def, i)) {
return 0; /* Collating sequence must be the same on all columns */
}
- if (!table_column_is_nullable(pDest, i)
- && table_column_is_nullable(pSrc, i)) {
+ if (!table_column_is_nullable(pDest->def, i)
+ && table_column_is_nullable(pSrc->def, i)) {
return 0; /* tab2 must be NOT NULL if tab1 is */
}
/* Default values for second and subsequent columns need to match. */
diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c
index 463bb7e..c49817f 100644
--- a/src/box/sql/pragma.c
+++ b/src/box/sql/pragma.c
@@ -373,7 +373,9 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */
i; k++) {
}
}
- bool nullable = table_column_is_nullable(pTab, i);
+ bool nullable =
+ table_column_is_nullable(pTab->def,
+ i);
uint32_t space_id =
SQLITE_PAGENO_TO_SPACEID(
pTab->tnum);
@@ -691,7 +693,7 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */
iKey,
regRow);
sqlite3ColumnDefault(v,
- pTab,
+ pTab->def,
iKey,
regRow);
sqlite3VdbeAddOp2(v,
@@ -708,7 +710,7 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */
} else {
for (j = 0; j < pFK->nCol; j++) {
sqlite3ExprCodeGetColumnOfTable
- (v, pTab, 0,
+ (v, pTab->def, 0,
aiCols ? aiCols[j]
: pFK->aCol[j].
iFrom, regRow + j);
diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c
index 5d85ef7..f24399c 100644
--- a/src/box/sql/resolve.c
+++ b/src/box/sql/resolve.c
@@ -227,7 +227,7 @@ lookupName(Parse * pParse, /* The parsing context */
/* Initialize the node to no-match */
pExpr->iTable = -1;
- pExpr->pTab = 0;
+ pExpr->space_def = NULL;
ExprSetVVAProperty(pExpr, EP_NoReduce);
/* Start at the inner-most context and move outward until a match is found */
@@ -301,7 +301,7 @@ lookupName(Parse * pParse, /* The parsing context */
}
if (pMatch) {
pExpr->iTable = pMatch->iCursor;
- pExpr->pTab = pMatch->pTab;
+ pExpr->space_def = pMatch->pTab->def;
/* RIGHT JOIN not (yet) supported */
assert((pMatch->fg.jointype & JT_RIGHT) == 0);
if ((pMatch->fg.jointype & JT_LEFT) != 0) {
@@ -365,7 +365,7 @@ lookupName(Parse * pParse, /* The parsing context */
: (((u32) 1) << iCol));
}
pExpr->iColumn = (i16) iCol;
- pExpr->pTab = pTab;
+ pExpr->space_def = pTab->def;
isTrigger = 1;
}
}
@@ -499,9 +499,9 @@ sqlite3CreateColumnExpr(sqlite3 * db, SrcList * pSrc, int iSrc, int iCol)
Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0);
if (p) {
struct SrcList_item *pItem = &pSrc->a[iSrc];
- p->pTab = pItem->pTab;
+ p->space_def = pItem->pTab->def;
p->iTable = pItem->iCursor;
- if (p->pTab->iPKey == iCol) {
+ if (pItem->pTab->iPKey == iCol) {
p->iColumn = -1;
} else {
p->iColumn = (ynVar) iCol;
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index 34d296d..ff9f18b 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -1636,7 +1636,7 @@ columnTypeImpl(NameContext * pNC, Expr * pExpr,
break;
}
- assert(pTab && pExpr->pTab == pTab);
+ assert(pTab && pExpr->space_def == pTab->def);
if (pS) {
/* The "table" is actually a sub-select or a view in the FROM clause
* of the SELECT statement. Return the declaration type and origin
@@ -1842,19 +1842,23 @@ sqlite3ColumnsFromExprList(Parse * pParse, /* Parsing context */
/* If the column contains an "AS <name>" phrase, use <name> as the name */
} else {
Expr *pColExpr = p; /* The expression that is the result column name */
- Table *pTab; /* Table associated with this expression */
+ struct space_def *space_def;
while (pColExpr->op == TK_DOT) {
pColExpr = pColExpr->pRight;
assert(pColExpr != 0);
}
if (pColExpr->op == TK_COLUMN
- && ALWAYS(pColExpr->pTab != 0)) {
+ && ALWAYS(pColExpr->space_def != NULL)) {
/* For columns use the column name name */
int iCol = pColExpr->iColumn;
- pTab = pColExpr->pTab;
+ space_def = pColExpr->space_def;
+ Table *pTable =
+ sqlite3LocateTable(pParse, 0,
+ space_def->name);
+ assert(pTable != NULL);
if (iCol < 0)
- iCol = pTab->iPKey;
- zName = pTab->def->fields[iCol].name;
+ iCol = pTable->iPKey;
+ zName = space_def->fields[iCol].name;
} else if (pColExpr->op == TK_ID) {
assert(!ExprHasProperty(pColExpr, EP_IntValue));
zName = pColExpr->u.zToken;
@@ -1946,11 +1950,13 @@ sqlite3SelectAddColumnTypeAndCollation(Parse * pParse, /* Parsing contexts */
p = a[i].pExpr;
type = columnType(&sNC, p, 0, 0, 0, &pCol->szEst);
szAll += pCol->szEst;
- pCol->affinity = sqlite3ExprAffinity(p);
pTab->def->fields[i].type = type;
- if (pCol->affinity == 0)
- pCol->affinity = SQLITE_AFF_BLOB;
+ char affinity = sqlite3ExprAffinity(p);
+ if (affinity == 0)
+ affinity = SQLITE_AFF_BLOB;
+ pTab->def->fields[i].affinity = affinity;
+
bool unused;
struct coll *coll = sql_expr_coll(pParse, p, &unused);
if (coll != NULL && pTab->def->fields[i].coll_id == COLL_NONE)
@@ -5931,7 +5937,7 @@ sqlite3Select(Parse * pParse, /* The parser context */
if (pCol->iSorterColumn >= j) {
int r1 = j + regBase;
sqlite3ExprCodeGetColumnToReg
- (pParse, pCol->pTab,
+ (pParse, pCol->space_def,
pCol->iColumn,
pCol->iTable, r1);
j++;
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 6eddbec..4c2c6fb 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 affinity; /* One of the SQLITE_AFF_... values */
u8 szEst; /* Estimated size of value in this column. sizeof(INT)==1 */
u8 is_primkey; /* Boolean propertie for being PK */
};
@@ -2226,7 +2225,8 @@ struct AggInfo {
int mnReg, mxReg; /* Range of registers allocated for aCol and aFunc */
ExprList *pGroupBy; /* The group by clause */
struct AggInfo_col { /* For each column used in source tables */
- Table *pTab; /* Source table */
+ /* Pointer to space definition. */
+ struct space_def *space_def;
int iTable; /* Cursor number of the source table */
int iColumn; /* Column number within the source table */
int iSorterColumn; /* Column number in the sorting index */
@@ -2361,7 +2361,8 @@ struct Expr {
* TK_AGG_FUNCTION: nesting depth
*/
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
- Table *pTab; /* Table for TK_COLUMN expressions. */
+ /* Pointer for table relative definition. */
+ struct space_def *space_def;
};
/*
@@ -3520,7 +3521,7 @@ void sqlite3AddCollateType(Parse *, Token *);
const char *
column_collation_name(Table *, uint32_t);
struct coll *
-sql_column_collation(Table *, uint32_t);
+sql_column_collation(struct space_def *, uint32_t);
const char *
index_collation_name(Index *, uint32_t);
struct coll *
@@ -3607,9 +3608,9 @@ int sqlite3WhereOkOnePass(WhereInfo *, int *);
#define ONEPASS_SINGLE 1 /* ONEPASS valid for a single row update */
#define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */
void sqlite3ExprCodeLoadIndexColumn(Parse *, Index *, int, int, int);
-int sqlite3ExprCodeGetColumn(Parse *, Table *, int, int, int, u8);
-void sqlite3ExprCodeGetColumnToReg(Parse *, Table *, int, int, int);
-void sqlite3ExprCodeGetColumnOfTable(Vdbe *, Table *, int, int, int);
+int sqlite3ExprCodeGetColumn(Parse *, struct space_def *, int, int, int, u8);
+void sqlite3ExprCodeGetColumnToReg(Parse *, struct space_def *, int, int, int);
+void sqlite3ExprCodeGetColumnOfTable(Vdbe *, struct space_def *, int, int, int);
void sqlite3ExprCodeMove(Parse *, int, int, int);
void sqlite3ExprCacheStore(Parse *, int, int, int);
void sqlite3ExprCachePush(Parse *);
@@ -3802,7 +3803,7 @@ const char *sqlite3IndexAffinityStr(sqlite3 *, Index *);
void sqlite3TableAffinity(Vdbe *, Table *, int);
char sqlite3CompareAffinity(Expr * pExpr, char aff2);
int sqlite3IndexAffinityOk(Expr * pExpr, char idx_affinity);
-char sqlite3TableColumnAffinity(Table *, int);
+char sqlite3TableColumnAffinity(struct space_def *, int);
char sqlite3ExprAffinity(Expr * pExpr);
int sqlite3Atoi64(const char *, i64 *, int);
int sqlite3DecOrHexToI64(const char *, i64 *);
@@ -3890,7 +3891,7 @@ int sqlite3ResolveExprListNames(NameContext *, ExprList *);
void sqlite3ResolveSelectNames(Parse *, Select *, NameContext *);
void sqlite3ResolveSelfReference(Parse *, Table *, int, Expr *, ExprList *);
int sqlite3ResolveOrderGroupBy(Parse *, Select *, ExprList *, const char *);
-void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
+void sqlite3ColumnDefault(Vdbe *, struct space_def *, int, int);
void sqlite3AlterFinishAddColumn(Parse *, Token *);
void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
char* rename_table(sqlite3 *, const char *, const char *, bool *);
@@ -4141,6 +4142,6 @@ enum on_conflict_action
table_column_nullable_action(struct Table *tab, uint32_t column);
bool
-table_column_is_nullable(struct Table *tab, uint32_t column);
+table_column_is_nullable(struct space_def *def, uint32_t column);
#endif /* SQLITEINT_H */
diff --git a/src/box/sql/update.c b/src/box/sql/update.c
index 2f36423..38f824f 100644
--- a/src/box/sql/update.c
+++ b/src/box/sql/update.c
@@ -69,30 +69,27 @@
* space.
*/
void
-sqlite3ColumnDefault(Vdbe * v, Table * pTab, int i, int iReg)
+sqlite3ColumnDefault(Vdbe * v, struct space_def * def, int i, int iReg)
{
- assert(pTab != 0);
- assert(pTab->def->opts.is_view == (pTab->pSelect != NULL));
- if (!pTab->def->opts.is_view) {
+ assert(def != NULL);
+ if (!def->opts.is_view) {
sqlite3_value *pValue = 0;
- Column *pCol = &pTab->aCol[i];
- VdbeComment((v, "%s.%s", pTab->def->name,
- pTab->def->fields[i].name));
- assert(i < (int)pTab->def->field_count);
+ char affinity = def->fields[i].affinity;
+ VdbeComment((v, "%s.%s", def->name, def->fields[i].name));
+ assert(i < (int)def->field_count);
Expr *expr = NULL;
struct space *space =
- space_cache_find(SQLITE_PAGENO_TO_SPACEID(pTab->tnum));
+ space_cache_find(def->id);
if (space != NULL && space->def->fields != NULL)
expr = space->def->fields[i].default_value_expr;
sqlite3ValueFromExpr(sqlite3VdbeDb(v),
- expr,
- pCol->affinity, &pValue);
+ expr, affinity, &pValue);
if (pValue) {
sqlite3VdbeAppendP4(v, pValue, P4_MEM);
}
#ifndef SQLITE_OMIT_FLOATING_POINT
- if (pTab->aCol[i].affinity == SQLITE_AFF_REAL) {
+ if (affinity == SQLITE_AFF_REAL) {
sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
}
#endif
@@ -381,7 +378,7 @@ sqlite3Update(Parse * pParse, /* The parser context */
} else {
for (i = 0; i < nPk; i++) {
assert(pPk->aiColumn[i] >= 0);
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,
+ sqlite3ExprCodeGetColumnOfTable(v, pTab->def, iDataCur,
pPk->aiColumn[i],
iPk + i);
}
@@ -486,7 +483,7 @@ sqlite3Update(Parse * pParse, /* The parser context */
|| (i < 32 && (oldmask & MASKBIT32(i)) != 0)
|| table_column_is_in_pk(pTab, i)) {
testcase(oldmask != 0xffffffff && i == 31);
- sqlite3ExprCodeGetColumnOfTable(v, pTab,
+ sqlite3ExprCodeGetColumnOfTable(v, pTab->def,
iDataCur, i,
regOld + i);
} else {
@@ -529,7 +526,7 @@ sqlite3Update(Parse * pParse, /* The parser context */
*/
testcase(i == 31);
testcase(i == 32);
- sqlite3ExprCodeGetColumnToReg(pParse, pTab, i,
+ sqlite3ExprCodeGetColumnToReg(pParse, pTab->def, i,
iDataCur,
regNew + i);
} else {
@@ -570,7 +567,7 @@ sqlite3Update(Parse * pParse, /* The parser context */
*/
for (i = 0; i < (int)pTab->def->field_count; i++) {
if (aXRef[i] < 0 && i != pTab->iPKey) {
- sqlite3ExprCodeGetColumnOfTable(v, pTab,
+ sqlite3ExprCodeGetColumnOfTable(v, pTab->def,
iDataCur, i,
regNew + i);
}
diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c
index f76c689..f9927ed 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -4724,28 +4724,22 @@ table_column_nullable_action(struct Table *tab, uint32_t column)
* @return return nullability flag value
*/
bool
-table_column_is_nullable(struct Table *tab, uint32_t column)
+table_column_is_nullable(struct space_def *def, uint32_t column)
{
/* Temporary hack: until Tarantoool's ephemeral spaces are on-boarded,
* views are not handled properly in Tarantool as well. */
- if (!(tab->tabFlags | TF_Ephemeral || space_is_view(tab))) {
- uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(tab->tnum);
- struct space *space = space_cache_find(space_id);
-
- assert(space);
-
+ struct space *space = space_cache_find(def->id);
+ if (space != NULL && !space->def->opts.is_view) {
struct tuple_format *format = space->format;
-
assert(format);
assert(format->field_count > column);
-
return format->fields[column].nullable_action ==
- ON_CONFLICT_ACTION_NONE;
+ ON_CONFLICT_ACTION_NONE;
} else {
/* tab is ephemeral (in SQLite sense). */
- assert(tab->def->fields[column].is_nullable ==
- (tab->def->fields[column].nullable_action ==
+ assert(def->fields[column].is_nullable ==
+ (def->fields[column].nullable_action ==
ON_CONFLICT_ACTION_NONE));
- return tab->def->fields[column].is_nullable;
+ return def->fields[column].is_nullable;
}
}
diff --git a/src/box/sql/where.c b/src/box/sql/where.c
index 88f4c28..d33fd9c 100644
--- a/src/box/sql/where.c
+++ b/src/box/sql/where.c
@@ -378,7 +378,9 @@ whereScanInit(WhereScan * pScan, /* The WhereScan object being initialized */
if (iColumn == XN_EXPR) {
pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
} else if (iColumn >= 0) {
- pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
+ char affinity =
+ pIdx->pTable->def->fields[iColumn].affinity;
+ pScan->idxaff = affinity;
pScan->coll = sql_index_collation(pIdx, j);
pScan->is_column_seen = true;
}
@@ -491,7 +493,7 @@ indexColumnNotNull(Index * pIdx, int iCol)
assert(iCol >= 0 && iCol < (int)index_column_count(pIdx));
j = pIdx->aiColumn[iCol];
if (j >= 0) {
- return !table_column_is_nullable(pIdx->pTable, j);
+ return !table_column_is_nullable(pIdx->pTable->def, j);
} else if (j == (-1)) {
return 1;
} else {
@@ -2237,7 +2239,8 @@ whereRangeVectorLen(Parse * pParse, /* Parsing context */
aff = sqlite3CompareAffinity(pRhs, sqlite3ExprAffinity(pLhs));
idxaff =
- sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn);
+ sqlite3TableColumnAffinity(pIdx->pTable->def,
+ pLhs->iColumn);
if (aff != idxaff)
break;
@@ -3331,8 +3334,8 @@ wherePathSatisfiesOrderBy(WhereInfo * pWInfo, /* The WHERE clause */
if (isOrderDistinct
&& iColumn >= 0
&& j >= pLoop->nEq
- && table_column_is_nullable(pIndex->pTable,
- iColumn)) {
+ && table_column_is_nullable(
+ pIndex->pTable->def, iColumn)) {
isOrderDistinct = 0;
}
diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
index 3da7cdb..3459020 100644
--- a/src/box/sql/wherecode.c
+++ b/src/box/sql/wherecode.c
@@ -909,7 +909,7 @@ codeCursorHintFixExpr(Walker * pWalker, Expr * pExpr)
if (pExpr->iTable != pHint->iTabCur) {
Vdbe *v = pWalker->pParse->pVdbe;
int reg = ++pWalker->pParse->nMem; /* Register for column value */
- sqlite3ExprCodeGetColumnOfTable(v, pExpr->pTab,
+ sqlite3ExprCodeGetColumnOfTable(v, pExpr->pTab->def,
pExpr->iTable,
pExpr->iColumn, reg);
pExpr->op = TK_REGISTER;
@@ -1261,8 +1261,9 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo, /* Complete information about t
* FYI: entries in an index are ordered as follows:
* NULL, ... NULL, min_value, ...
*/
- if ((j >= 0 && table_column_is_nullable(pIdx->pTable, j))
- || j == XN_EXPR) {
+ if ((j >= 0 &&
+ table_column_is_nullable(pIdx->pTable->def, j)) ||
+ j == XN_EXPR) {
assert(pLoop->nSkip == 0);
bSeekPastNull = 1;
nExtraReg = 1;
@@ -1308,7 +1309,9 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo, /* Complete information about t
if (pRangeStart == 0) {
j = pIdx->aiColumn[nEq];
if ((j >= 0
- && table_column_is_nullable(pIdx->pTable, j)) || j == XN_EXPR) {
+ && table_column_is_nullable(
+ pIdx->pTable->def, j)) ||
+ j == XN_EXPR) {
bSeekPastNull = 1;
}
}
@@ -1387,8 +1390,9 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo, /* Complete information about t
struct Index *pk = sqlite3PrimaryKeyIndex(pIdx->pTable);
assert(pk);
int nPkCol = index_column_count(pk);
- if (nPkCol == 1
- && pIdx->pTable->aCol[pk->aiColumn[0]].affinity == 'D') {
+ char affinity =
+ pIdx->pTable->def->fields[pk->aiColumn[0]].affinity;
+ if (nPkCol == 1 && affinity == 'D') {
/* Right now INTEGER PRIMARY KEY is the only option to
* get Tarantool's INTEGER column type. Need special handling
* here: try to loosely convert FLOAT to INT. If RHS type
@@ -1725,7 +1729,7 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo, /* Complete information about t
for (iPk = 0; iPk < nPk; iPk++) {
int iCol = pPk->aiColumn[iPk];
sqlite3ExprCodeGetColumnToReg
- (pParse, pTab,
+ (pParse, pTab->def,
iCol, iCur,
r + iPk);
}
diff --git a/src/box/sql/whereexpr.c b/src/box/sql/whereexpr.c
index e602111..d1f2cc5 100644
--- a/src/box/sql/whereexpr.c
+++ b/src/box/sql/whereexpr.c
@@ -1516,7 +1516,7 @@ sqlite3WhereTabFuncArgs(Parse * pParse, /* Parsing context */
return;
pColRef->iTable = pItem->iCursor;
pColRef->iColumn = k++;
- pColRef->pTab = pTab;
+ pColRef->space_def = pTab->def;
pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef,
sqlite3ExprDup(pParse->db,
pArgs->a[j].pExpr, 0));
--
2.7.4
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] Re: [PATCH v4 2/7] sql: remove zName and nColumn from SQL
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 2/7] sql: remove zName and nColumn from SQL Kirill Shcherbatov
@ 2018-05-03 10:10 ` Vladislav Shpilevoy
0 siblings, 0 replies; 26+ messages in thread
From: Vladislav Shpilevoy @ 2018-05-03 10:10 UTC (permalink / raw)
To: Kirill Shcherbatov, tarantool-patches
Hello. Same as in the previous letter.
On 28/04/2018 21:26, 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.
>
> Part of #3272.
> ---
> src/box/space_def.c | 29 ++++---
> src/box/sql.c | 79 +++++++++++++++--
> src/box/sql.h | 32 +++++++
> src/box/sql/alter.c | 32 ++++---
> src/box/sql/analyze.c | 5 +-
> src/box/sql/build.c | 221 +++++++++++++++++++++++-------------------------
> 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/prepare.c | 26 +++---
> src/box/sql/resolve.c | 16 ++--
> src/box/sql/select.c | 112 ++++++++++++++----------
> src/box/sql/sqliteInt.h | 6 +-
> src/box/sql/tokenize.c | 3 +
> src/box/sql/trigger.c | 2 +
> src/box/sql/update.c | 29 ++++---
> src/box/sql/where.c | 6 +-
> src/box/sql/wherecode.c | 2 +-
> src/box/sql/whereexpr.c | 4 +-
> 21 files changed, 433 insertions(+), 287 deletions(-)
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] Re: [PATCH v4 0/7] sql: refactor SQL Parser structures
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 0/7] sql: refactor SQL Parser structures Kirill Shcherbatov
` (6 preceding siblings ...)
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 7/7] sql: space_def* instead of Table* in Expr Kirill Shcherbatov
@ 2018-05-03 10:10 ` Vladislav Shpilevoy
7 siblings, 0 replies; 26+ messages in thread
From: Vladislav Shpilevoy @ 2018-05-03 10:10 UTC (permalink / raw)
To: tarantool-patches
Hello.
On 28/04/2018 21:26, Kirill Shcherbatov wrote:
> Branch: http://github.com/tarantool/tarantool/tree/gh-3272-no-sql-names
> Issue: https://github.com/tarantool/tarantool/issues/3272
1. Please, describe the patchset here.
>
> Kirill Shcherbatov (7):
> sql: fix code style in sqlite3Pragma
> sql: remove zName and nColumn from SQL
> sql: start using type from space_def
> sql: start using collations and is_nullable from space_def
> sql: move names to server
> sql: start using is_view field from space_def
> sql: space_def* instead of Table* in Expr
>
> src/box/field_def.c | 1 +
> src/box/field_def.h | 5 +
> src/box/space_def.c | 29 ++--
> src/box/sql.c | 156 +++++++++++++++++----
> src/box/sql.h | 32 +++++
> src/box/sql/alter.c | 54 ++++---
> src/box/sql/analyze.c | 16 ++-
> src/box/sql/build.c | 364 ++++++++++++++++++++++++++----------------------
> src/box/sql/delete.c | 25 ++--
> src/box/sql/expr.c | 65 +++++----
> src/box/sql/fkey.c | 51 ++++---
> src/box/sql/hash.c | 5 +-
> src/box/sql/insert.c | 88 ++++++------
> src/box/sql/pragma.c | 96 +++++++------
> src/box/sql/prepare.c | 26 ++--
> src/box/sql/resolve.c | 33 +++--
> src/box/sql/select.c | 185 +++++++++++++-----------
> src/box/sql/sqliteInt.h | 37 ++---
> src/box/sql/tokenize.c | 3 +
> src/box/sql/treeview.c | 2 +-
> src/box/sql/trigger.c | 6 +-
> src/box/sql/update.c | 52 +++----
> src/box/sql/util.c | 9 --
> src/box/sql/vdbe.c | 2 +-
> src/box/sql/vdbeaux.c | 19 ++-
> src/box/sql/where.c | 24 ++--
> src/box/sql/wherecode.c | 23 +--
> src/box/sql/whereexpr.c | 8 +-
> 28 files changed, 831 insertions(+), 585 deletions(-)
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] Re: [PATCH v4 1/7] sql: fix code style in sqlite3Pragma
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 1/7] sql: fix code style in sqlite3Pragma Kirill Shcherbatov
@ 2018-05-03 10:10 ` Vladislav Shpilevoy
0 siblings, 0 replies; 26+ messages in thread
From: Vladislav Shpilevoy @ 2018-05-03 10:10 UTC (permalink / raw)
To: Kirill Shcherbatov, tarantool-patches
Hello. Please, fix comments from the previous review.
On 28/04/2018 21:26, Kirill Shcherbatov wrote:
> ---
> src/box/sql/pragma.c | 56 +++++++++++++++++++++++++---------------------------
> 1 file changed, 27 insertions(+), 29 deletions(-)
>
> diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c
> index e41f69b..4a68cad 100644
> --- a/src/box/sql/pragma.c
> +++ b/src/box/sql/pragma.c
> @@ -544,37 +544,35 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */
>
> #ifndef SQLITE_OMIT_FOREIGN_KEY
> case PragTyp_FOREIGN_KEY_LIST:{
> - if (zRight) {
> - FKey *pFK;
> - Table *pTab;
> - pTab = sqlite3HashFind(&db->pSchema->tblHash,
> - zRight);
> - if (pTab != NULL) {
> - pFK = pTab->pFKey;
> - if (pFK) {
> - int i = 0;
> - pParse->nMem = 8;
> - while (pFK) {
> - int j;
> - for (j = 0;
> - j < pFK->nCol;
> - j++) {
> - sqlite3VdbeMultiLoad(v, 1, "iissssss", i, j, pFK->zTo, pTab->aCol[pFK->aCol[j].iFrom].zName, pFK->aCol[j].zCol, actionName(pFK->aAction[1]), /* ON UPDATE */
> - actionName(pFK->aAction[0]), /* ON DELETE */
> - "NONE");
> - sqlite3VdbeAddOp2
> - (v,
> - OP_ResultRow,
> - 1, 8);
> - }
> - ++i;
> - pFK = pFK->pNextFrom;
> - }
> - }
> - }
> - }
> + if (!zRight)
> + break;
> + FKey *pFK;
> + Table *pTab;
> + pTab = sqlite3HashFind(&db->pSchema->tblHash, zRight);
> + if (pTab == NULL)
> break;
> + pFK = pTab->pFKey;
> + if (!pFK)
> + break;
> + int i = 0;
> + pParse->nMem = 8;
> + while (pFK) {
> + for (int j = 0; j < pFK->nCol; j++) {
> + const char *name =
> + pTab->aCol[pFK->aCol[j].iFrom].zName;
> + sqlite3VdbeMultiLoad(v, 1, "iissssss", i, j,
> + pFK->zTo, name,
> + pFK->aCol[j].zCol,
> + actionName(pFK->aAction[1]),
> + actionName(pFK->aAction[0]),
> + "NONE");
> + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 8);
> + }
> + ++i;
> + pFK = pFK->pNextFrom;
> }
> + break;
> + }
> #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
>
> #ifndef SQLITE_OMIT_FOREIGN_KEY
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] Re: [PATCH v4 4/7] sql: start using collations and is_nullable from space_def
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 4/7] sql: start using collations and is_nullable " Kirill Shcherbatov
@ 2018-05-03 10:21 ` Vladislav Shpilevoy
0 siblings, 0 replies; 26+ messages in thread
From: Vladislav Shpilevoy @ 2018-05-03 10:21 UTC (permalink / raw)
To: Kirill Shcherbatov, tarantool-patches
Hello. See 5 comments below.
On 28/04/2018 21:26, Kirill Shcherbatov wrote:
> Part of #3272.
> ---
> src/box/sql.c | 36 +++++++++++++++++++++++++-----------
> src/box/sql/alter.c | 11 ++++++++---
> src/box/sql/build.c | 20 +++++++++++++-------
> src/box/sql/fkey.c | 7 ++-----
> src/box/sql/select.c | 6 ++++--
> src/box/sql/sqliteInt.h | 7 -------
> src/box/sql/vdbeaux.c | 5 ++++-
> 7 files changed, 56 insertions(+), 36 deletions(-)
>
> diff --git a/src/box/sql.c b/src/box/sql.c
> index 2893d70..ef11eb9 100644
> --- a/src/box/sql.c
> +++ b/src/box/sql.c
> @@ -1449,7 +1449,9 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
>
> for (i = 0; i < n; i++) {
> const char *t;
> - struct coll *coll = aCol[i].coll;
> + struct coll *coll =
> + coll_by_id(pTable->def->fields[i].coll_id);
> +
> struct field_def *field = &def->fields[i];
> const char *zToken = field->default_value;
> int base_len = 4;
> @@ -1461,19 +1463,25 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
> p = enc->encode_str(p, "name", 4);
> p = enc->encode_str(p, field->name, strlen(field->name));
> p = enc->encode_str(p, "type", 4);
> +
> + assert(def->fields[i].is_nullable ==
> + (def->fields[i].nullable_action ==
> + ON_CONFLICT_ACTION_NONE));
1. AFAIR I asked you to wrap this check into a function.
> diff --git a/src/box/sql/alter.c b/src/box/sql/alter.c
> index bedf602..f830a15 100644
> --- a/src/box/sql/alter.c
> +++ b/src/box/sql/alter.c
> @@ -307,9 +312,9 @@ sqlite3AlterBeginAddColumn(Parse * pParse, SrcList * pSrc)
> }
> 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];
> + /* FIXME: Column *pCol = &pNew->aCol[i]; */
2. Why FIXME ?
> diff --git a/src/box/sql/fkey.c b/src/box/sql/fkey.c
> index c15ad8c..8c015c9 100644
> --- a/src/box/sql/fkey.c
> +++ b/src/box/sql/fkey.c
> @@ -34,6 +34,7 @@
> * support to compiled SQL statements.
> */
> #include <box/coll.h>
> +#include "box/coll_cache.h"
3. Why? It is not used here.
> @@ -535,11 +536,7 @@ exprTableRegister(Parse * pParse, /* Parsing and code generating context */
> pCol = &pTab->aCol[iCol];
> pExpr->iTable = regBase + iCol + 1;
> pExpr->affinity = pCol->affinity;
> - const char *coll_name;
> - if (pCol->coll == NULL && pCol->coll != NULL)
> - coll_name = pCol->coll->name;
> - else
> - coll_name = "binary";
> + const char *coll_name = "binary";
> pExpr = sqlite3ExprAddCollateString(pParse, pExpr,
> coll_name);
4. Why you did not just inline "binary" string ?
> diff --git a/src/box/sql/select.c b/src/box/sql/select.c
> index 03bfcf9..fa1de9b 100644
> --- a/src/box/sql/select.c
> +++ b/src/box/sql/select.c
> @@ -1836,6 +1836,8 @@ sqlite3ColumnsFromExprList(Parse * pParse, /* Parsing context */
> pTable->def->fields =
> region_alloc(region, nCol*sizeof(pTable->def->fields[0]));
> memset(pTable->def->fields, 0, nCol*sizeof(pTable->def->fields[0]));
> + for (int i = 0; i < nCol; i++)
> + pTable->def->fields[i].is_nullable = true;
5. Why?
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] Re: [PATCH v4 5/7] sql: move names to server
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 5/7] sql: move names to server Kirill Shcherbatov
@ 2018-05-03 11:08 ` Vladislav Shpilevoy
0 siblings, 0 replies; 26+ messages in thread
From: Vladislav Shpilevoy @ 2018-05-03 11:08 UTC (permalink / raw)
To: Kirill Shcherbatov, tarantool-patches
"sql: move names to server" - which names? whose names?
I see, that your code starts to use space name from space_def instead of name from
struct Table - it is not obvious from the commit header. And it is not "move" -
these names are in the server already. You just start to use them.
See below 27 comments.
On 28/04/2018 21:26, Kirill Shcherbatov wrote:
> Part of #3272.
> ---
> src/box/sql.c | 38 ++++++++++++++++++++++-------
> src/box/sql.h | 6 ++---
> src/box/sql/alter.c | 11 +++++----
> src/box/sql/analyze.c | 11 +++++----
> src/box/sql/build.c | 61 ++++++++++++++++++++++++++++++-----------------
> src/box/sql/delete.c | 6 ++---
> src/box/sql/fkey.c | 11 +++++----
> src/box/sql/hash.c | 5 ++--
> src/box/sql/insert.c | 9 +++----
> src/box/sql/pragma.c | 4 ++--
> src/box/sql/resolve.c | 7 +++---
> src/box/sql/select.c | 63 ++++++++++++++++++++++++-------------------------
> src/box/sql/sqliteInt.h | 1 -
> src/box/sql/treeview.c | 2 +-
> src/box/sql/trigger.c | 4 ++--
> src/box/sql/update.c | 3 ++-
> src/box/sql/vdbe.c | 2 +-
> src/box/sql/where.c | 5 ++--
> src/box/sql/wherecode.c | 3 ++-
> src/box/sql/whereexpr.c | 2 +-
> 20 files changed, 150 insertions(+), 104 deletions(-)
>
> diff --git a/src/box/sql.c b/src/box/sql.c
> index ef11eb9..47f7cb1 100644
> --- a/src/box/sql.c
> +++ b/src/box/sql.c
> @@ -1699,12 +1699,13 @@ space_column_default_expr(uint32_t space_id, uint32_t fieldno)
> return space->def->fields[fieldno].default_value_expr;
> }
>
> -struct space_def *
> -sql_ephemeral_space_def_new(Parse *parser)
> +static struct space_def *
> +sql_ephemeral_space_def_new(Parse *parser, const char *name)
> {
> struct space_def *def = NULL;
> struct region *region = &fiber()->gc;
> - size_t size = sizeof(struct space_def) + 1;
> + size_t name_len = name != NULL ? strlen(name) : 0;
> + size_t size = sizeof(struct space_def) + name_len + 1;
> def = (struct space_def *)region_alloc(region, size);
> if (def != NULL) {
> memset(def, 0, size);
> @@ -1718,19 +1719,40 @@ sql_ephemeral_space_def_new(Parse *parser)
> parser->nErr++;
> return NULL;
> }
> + memcpy(def->name, name, name_len);
> + def->name[name_len] = '\0';
> def->dict->refs = 1;
> def->opts.temporary = true;
> return def;
> }
>
> +struct space_def *
> +sql_ephemeral_space_def_clone(Parse *parser, struct space_def *old_def)
> +{
> + struct space_def *new_def = NULL;
> + new_def = sql_ephemeral_space_def_new(parser, old_def->name);
> + if (new_def == NULL) {
> + parser->rc = SQLITE_NOMEM_BKPT;
> + parser->nErr++;
> + return NULL;
> + }
> + new_def->opts = old_def->opts;
> + new_def->opts.temporary = true;
> + new_def->id = old_def->id;
> + new_def->uid = old_def->uid;
> + memcpy(new_def->engine_name, old_def->engine_name,
> + strlen(old_def->engine_name));
1. I see, that this code can be much simpler and shorter, if you will do just
one memcpy(new_def, old_def, size). And now it becomes at least third place,
where size of a space_def is needed. Lets declare space_def_sizeof function from
space_def.c in space_def.h, make it non-static, and use here and in
sql_ephemeral_space_def_new.
> diff --git a/src/box/sql.h b/src/box/sql.h
> index 410653b..d7cfd70 100644
> --- a/src/box/sql.h
> +++ b/src/box/sql.h
> @@ -152,16 +152,16 @@ sql_expr_free(struct sqlite3 *db, struct Expr *expr, bool extern_alloc);
> * @retval not NULL on success.
> */
> struct Table *
> -sql_ephemeral_table_new(struct Parse *parser);
> +sql_ephemeral_table_new(struct Parse *parser, const char *name);
2. Fix the comment as well.
>
> /**
> - * Create and initialize a new ephemeric space_def object.
> + * Create and initialize a new ephemeric space_def object copy.
> * @param pParse SQL Parser object.
> * @retval NULL on memory allocation error, Parser state changed.
> * @retval not NULL on success.
> */
> struct space_def *
> -sql_ephemeral_space_def_new(struct Parse *parser);
> +sql_ephemeral_space_def_clone(struct Parse *parser, struct space_def *old_def);
3. Same. And write a new comment for sql_ephemeral_space_def_new.
> diff --git a/src/box/sql/alter.c b/src/box/sql/alter.c
> index f830a15..33a4f4d 100644
> --- a/src/box/sql/alter.c
> +++ b/src/box/sql/alter.c
> @@ -865,7 +865,8 @@ analyzeOneTable(Parse * pParse, /* Parser context */
>
> /* Populate the register containing the index name. */
> sqlite3VdbeLoadString(v, regIdxname, zIdxName);
> - VdbeComment((v, "Analysis for %s.%s", pTab->zName, zIdxName));
> + VdbeComment((v, "Analysis for %s.%s",
> + pTab->def->name, zIdxName));
4. Wrong alignment.
> diff --git a/src/box/sql/build.c b/src/box/sql/build.c
> index e9c0686..4e0ae87 100644
> --- a/src/box/sql/build.c
> +++ b/src/box/sql/build.c
> @@ -662,7 +660,8 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
> assert(p->def->opts.temporary == true);
> #if SQLITE_MAX_COLUMN
> if ((int)p->def->field_count + 1 > db->aLimit[SQLITE_LIMIT_COLUMN]) {
> - sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName);
> + sqlite3ErrorMsg(pParse, "too many columns on %s",
> + p->def->name);
5. Leading white space.
> @@ -1306,7 +1305,7 @@ createTableStmt(sqlite3 * db, Table * p)
> }
> sqlite3_snprintf(n, zStmt, "CREATE TABLE ");
> k = sqlite3Strlen30(zStmt);
> - identPut(zStmt, &k, p->zName);
> + identPut(zStmt, &k, (char *)p->def->name);
6. Please, make identPut second argument be const char * to avoid this
conversion.
> @@ -1710,7 +1709,8 @@ parseTableSchemaRecord(Parse * pParse, int iSpaceId, char *zStmt)
>
> sqlite3VdbeAddOp4(v,
> OP_String8, 0, iTop, 0,
> - sqlite3DbStrDup(pParse->db, p->zName), P4_DYNAMIC);
> + sqlite3DbStrDup(pParse->db, p->def->name),
> + P4_DYNAMIC);
7. Wrong alignment.
> @@ -1950,7 +1950,7 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
>
> reg_seq_record = emitNewSysSequenceRecord(pParse,
> reg_seq_id,
> - p->zName);
> + p->def->name);
8. Same.
> @@ -2135,6 +2135,11 @@ sqlite3ViewGetColumnNames(Parse * pParse, Table * pTable)
> * a VIEW it holds the list of column names.
> */
> sqlite3ColumnsFromExprList(pParse, pTable->pCheck, pTable);
> + struct space_def *old_def = pTable->def;
> + old_def->opts.temporary = true; /* delete it manually */
9. Comment is out of 66 symbols. Start a comment from a capital letter. Put a
dot at the end of sentence.
> @@ -2142,18 +2147,30 @@ sqlite3ViewGetColumnNames(Parse * pParse, Table * pTable)
> pSel);
> }
> } else if (pSelTab) {
> - assert(pTable->def->opts.temporary == false);
> /* CREATE VIEW name AS... without an argument list. Construct
> * the column names from the SELECT statement that defines the view.
> */
> assert(pTable->aCol == 0);
> 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;
> + assert(pSelTab->def->opts.temporary);
> +
> + struct space_def *old_def = pTable->def;
> + struct space_def *new_def =
> + sql_ephemeral_space_def_clone(pParse, old_def);
> + if (new_def == NULL) {
> + nErr++;
> + } else {
> + new_def->fields = pSelTab->def->fields;
> + new_def->field_count = pSelTab->def->field_count;
10. Out of 80 symbols.
> + pTable->def = new_def;
> + if (sql_table_def_rebuild(db, pTable) != 0)
11. Why you can not instead of clone() + rebuild() just do one space_def_new() ?
Or even space_def_dup, if old_def is not ephemeral.
> diff --git a/src/box/sql/hash.c b/src/box/sql/hash.c
> index cedcb7d..79f0840 100644
> --- a/src/box/sql/hash.c
> +++ b/src/box/sql/hash.c
> @@ -69,6 +69,7 @@ sqlite3HashClear(Hash * pH)
> while (elem) {
> HashElem *next_elem = elem->next;
> sqlite3_free(elem);
> + free((void *)elem->pKey);
12. Unnecessary cast.
> diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
> index 06635ee..bde0cc1 100644
> --- a/src/box/sql/insert.c
> +++ b/src/box/sql/insert.c
> @@ -1145,7 +1145,8 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */
> case ON_CONFLICT_ACTION_ROLLBACK:
> case ON_CONFLICT_ACTION_FAIL: {
> char *zMsg =
> - sqlite3MPrintf(db, "%s.%s", pTab->zName,
> + sqlite3MPrintf(db, "%s.%s",
13. Leading white space.
> @@ -1404,7 +1405,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */
> x = pPk->aiColumn[i];
> sqlite3VdbeAddOp3(v, OP_Column,
> iThisCur, x, regR + i);
> - VdbeComment((v, "%s.%s", pTab->zName,
> + VdbeComment((v, "%s.%s", pTab->def->name,
> pTab->def->fields[
> pPk->aiColumn[i]].name));
14. Wrong alignment.
> diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c
> index 109c410..5d85ef7 100644
> --- a/src/box/sql/resolve.c
> +++ b/src/box/sql/resolve.c
> @@ -239,7 +239,8 @@ lookupName(Parse * pParse, /* The parsing context */
> for (i = 0, pItem = pSrcList->a; i < pSrcList->nSrc;
> i++, pItem++) {
> pTab = pItem->pTab;
> - assert(pTab != 0 && pTab->zName != 0);
> + assert(pTab != 0 &&
> + pTab->def->name != NULL);
15. Leading white space.
> diff --git a/src/box/sql/select.c b/src/box/sql/select.c
> index fa1de9b..199caf0 100644
> --- a/src/box/sql/select.c
> +++ b/src/box/sql/select.c
> @@ -1765,7 +1765,8 @@ generateColumnNames(Parse * pParse, /* Parser context */
> } else if (fullNames) {
> char *zName = 0;
> zName =
> - sqlite3MPrintf(db, "%s.%s", pTab->zName,
> + sqlite3MPrintf(db, "%s.%s",
16. Same.
> @@ -1972,6 +1962,7 @@ sqlite3SelectAddColumnTypeAndCollation(Parse * pParse, /* Parsing contexts */
> /*
> * Given a SELECT statement, generate a Table structure that describes
> * the result set of that SELECT.
> + * Return table with def is allocated on region.
17. Return'ed'. No 'is'. And please, use doxygen style: @param, @retval etc.
> @@ -4691,12 +4681,14 @@ selectExpander(Walker * pWalker, Select * p)
> for (i = 0, pFrom = pTabList->a; i < pTabList->nSrc; i++, pFrom++) {
> Table *pTab;
> assert(pFrom->fg.isRecursive == 0 || pFrom->pTab != 0);
> - if (pFrom->fg.isRecursive)
> + if (pFrom->fg.isRecursive) {
> continue;
> + }
18. Unnecessary diff.
> assert(pFrom->pTab == 0);
> #ifndef SQLITE_OMIT_CTE
> - if (withExpand(pWalker, pFrom))
> + if (withExpand(pWalker, pFrom)) {
> return WRC_Abort;
> + }
19. Same.
> @@ -4707,17 +4699,24 @@ selectExpander(Walker * pWalker, Select * p)
> assert(pFrom->pTab == 0);
> if (sqlite3WalkSelect(pWalker, pSel))
> return WRC_Abort;
> + char *name = "sqlite_sq_DEADBEAFDEADBEAF";
20. Write a comment why it is needed.
> pFrom->pTab = pTab =
> - sql_ephemeral_table_new(pParse);
> + sql_ephemeral_table_new(pParse, name);
> if (pTab == NULL)
> return WRC_Abort;
> + /* rewrite old name with correct pointer */
> + name = sqlite3MPrintf(db, "sqlite_sq_%p", (void *)pTab);
> + sprintf(pTab->def->name, "%s", name);
> + sqlite3DbFree(db, name);
21. Use tt_sprintf instead of sqlite3MPrintf + sqlite3DbFree. And you did not check
if mprintf returned NULL.
> +
> pTab->nTabRef = 1;
> - pTab->zName =
> - sqlite3MPrintf(db, "sqlite_sq_%p", (void *)pTab);
> while (pSel->pPrior) {
> pSel = pSel->pPrior;
> }
> sqlite3ColumnsFromExprList(pParse, pSel->pEList, pTab);
> + if (sql_table_def_rebuild(db, pTab) != 0)
> + return WRC_Abort;
22. Why do you need rebuild? AFAIK ephemeral struct Table dies together with
the parser.
> @@ -4727,12 +4726,13 @@ selectExpander(Walker * pWalker, Select * p)
> assert(pFrom->pTab == 0);
> pFrom->pTab = pTab =
> sqlite3LocateTable(pParse, 0, pFrom->zName);
> - if (pTab == NULL)
> + if (pTab == NULL) {
> return WRC_Abort;
> + }
23. Same as 18.
> @@ -5390,14 +5390,13 @@ sqlite3Select(Parse * pParse, /* The parser context */
> Table *pTab = pItem->pTab;
> if (pSub == 0)
> continue;
> -
24. Same.
> diff --git a/src/box/sql/update.c b/src/box/sql/update.c
> index 464feee..ad00537 100644
> --- a/src/box/sql/update.c
> +++ b/src/box/sql/update.c
> @@ -75,7 +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, pTab->def->fields[i].name));
> + VdbeComment((v, "%s.%s", pTab->def->name,
> + pTab->def->fields[i].name));
25. Same as 14.
> diff --git a/src/box/sql/where.c b/src/box/sql/where.c
> index fc0f84c..88f4c28 100644
> --- a/src/box/sql/where.c
> +++ b/src/box/sql/where.c
> @@ -1639,7 +1639,8 @@ whereLoopPrint(WhereLoop * p, WhereClause * pWC)
> sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId,
> p->iTab, nb, p->maskSelf, nb, p->prereq & mAll);
> sqlite3DebugPrintf(" %12s",
> - pItem->zAlias ? pItem->zAlias : pTab->zName);
> + pItem->zAlias ? pItem->zAlias :
26. Same as 15.
> diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
> index 233fde0..3da7cdb 100644
> --- a/src/box/sql/wherecode.c
> +++ b/src/box/sql/wherecode.c
> @@ -1158,7 +1158,8 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo, /* Complete information about t
> pTabItem->addrFillSub);
> pLevel->p2 = sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk);
> VdbeCoverage(v);
> - VdbeComment((v, "next row of \"%s\"", pTabItem->pTab->zName));
> + VdbeComment((v, "next row of \"%s\"",
27. Same.
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] Re: [PATCH v4 6/7] sql: start using is_view field from space_def
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 6/7] sql: start using is_view field from space_def Kirill Shcherbatov
@ 2018-05-03 11:16 ` Vladislav Shpilevoy
0 siblings, 0 replies; 26+ messages in thread
From: Vladislav Shpilevoy @ 2018-05-03 11:16 UTC (permalink / raw)
To: Kirill Shcherbatov, tarantool-patches
"start using is_view field from space_def" instead of what? It is
not obvious that the previous flag was Table->pSelect != NULL.
See 3 comments below.
On 28/04/2018 21:26, Kirill Shcherbatov wrote:
> Part of #3272.
> ---
> src/box/sql.c | 2 ++
> src/box/sql/build.c | 24 +++++++++++++++++-------
> src/box/sql/delete.c | 9 ++++++---
> src/box/sql/expr.c | 3 ++-
> src/box/sql/select.c | 2 ++
> src/box/sql/update.c | 3 ++-
> 6 files changed, 31 insertions(+), 12 deletions(-)
>
> diff --git a/src/box/sql.c b/src/box/sql.c
> index 47f7cb1..9f5a124 100644
> --- a/src/box/sql.c
> +++ b/src/box/sql.c
> @@ -1511,6 +1511,8 @@ int tarantoolSqlite3MakeTableOpts(Table *pTable, const char *zSql, void *buf)
> bool is_view = false;
> if (pTable != NULL)
> is_view = pTable->pSelect != NULL;
> + assert(!pTable || pTable->def->opts.is_view == is_view);
1. You said, that you start using is_view, but here you continue to
use pSelect. Why? 🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔 Lets move pSelect into
assert, and use is_view from table space_def. And how pTable can be NULL here?
2. Remove (void)pTable;. The pTable argument is not unused now.
> @@ -1933,7 +1937,8 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
> iSpaceId = getNewSpaceId(pParse);
> createSpace(pParse, iSpaceId, zStmt);
> /* Indexes aren't required for VIEW's. */
> - if (p->pSelect == NULL) {
> + assert(p->def->opts.is_view == (p->pSelect != NULL));
> + if (!p->def->opts.is_view) {
> createImplicitIndices(pParse, iSpaceId);
> }
3. Unnecessary {}.
^ permalink raw reply [flat|nested] 26+ messages in thread
* [tarantool-patches] Re: [PATCH v4 7/7] sql: space_def* instead of Table* in Expr
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 7/7] sql: space_def* instead of Table* in Expr Kirill Shcherbatov
@ 2018-05-03 11:32 ` Vladislav Shpilevoy
0 siblings, 0 replies; 26+ messages in thread
From: Vladislav Shpilevoy @ 2018-05-03 11:32 UTC (permalink / raw)
To: tarantool-patches, Kirill Shcherbatov
Hello. Write here why it is needed, and what this patch
allows to do in the next step.
See 10 comments below.
On 28/04/2018 21:26, Kirill Shcherbatov wrote:
> Part of #3272.
> ---
> src/box/field_def.c | 1 +
> src/box/field_def.h | 5 ++++
> src/box/sql.c | 10 ++++----
> src/box/sql/build.c | 48 ++++++++++++++++++++------------------
> src/box/sql/delete.c | 4 ++--
> src/box/sql/expr.c | 61 ++++++++++++++++++++++++++-----------------------
> src/box/sql/fkey.c | 13 +++++------
> src/box/sql/insert.c | 24 ++++++++++---------
> src/box/sql/pragma.c | 8 ++++---
> src/box/sql/resolve.c | 10 ++++----
> src/box/sql/select.c | 26 +++++++++++++--------
> src/box/sql/sqliteInt.h | 21 +++++++++--------
> src/box/sql/update.c | 29 +++++++++++------------
> src/box/sql/vdbeaux.c | 20 ++++++----------
> src/box/sql/where.c | 13 +++++++----
> src/box/sql/wherecode.c | 18 +++++++++------
> src/box/sql/whereexpr.c | 2 +-
> 17 files changed, 167 insertions(+), 146 deletions(-)
>
> diff --git a/src/box/field_def.c b/src/box/field_def.c
> index 010b3b7..63aab46 100644
> --- a/src/box/field_def.c
> +++ b/src/box/field_def.c
> @@ -100,6 +100,7 @@ const struct opt_def field_def_reg[] = {
>
> const struct field_def field_def_default = {
> .type = FIELD_TYPE_ANY,
> + .affinity = 0,
1. Use enum for affinities.
> diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
> index 119940c..4e20098 100644
> --- a/src/box/sql/expr.c
> +++ b/src/box/sql/expr.c
> @@ -179,13 +181,13 @@ sql_expr_coll(Parse *parse, Expr *p, bool *is_found)
> }
> if ((op == TK_AGG_COLUMN || op == TK_COLUMN ||
> op == TK_REGISTER || op == TK_TRIGGER) &&
> - p->pTab != 0) {
> + p->space_def != 0) {
> /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
> * a TK_COLUMN but was previously evaluated and cached in a register
> */
> int j = p->iColumn;
> if (j >= 0) {
> - coll = sql_column_collation(p->pTab, j);
> + coll = sql_column_collation(p->space_def, j);
> *is_found = true;
> }
> break;
> @@ -2132,10 +2134,10 @@ sqlite3ExprCanBeNull(const Expr * p)
> case TK_BLOB:
> return 0;
> case TK_COLUMN:
> - assert(p->pTab != 0);
> + assert(p->space_def!= 0);
2. Use explicit != NULL, and put white space around binary operators.
> @@ -3529,7 +3534,7 @@ sqlite3ExprCodeLoadIndexColumn(Parse * pParse, /* The parsing context */
> */
> void
> sqlite3ExprCodeGetColumnOfTable(Vdbe * v, /* The VDBE under construction */
> - Table * pTab, /* The table containing the value */
> + struct space_def *space_def,
3. Please, convert the function into Tarantool code style, and
write a comment. Same about all functions, whose signature is changed.
> diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
> index bde0cc1..7c21359 100644
> --- a/src/box/sql/insert.c
> +++ b/src/box/sql/insert.c
> @@ -1805,17 +1807,17 @@ xferOptimization(Parse * pParse, /* Parser context */
> return 0; /* Both tables must have the same INTEGER PRIMARY KEY */
> }
> 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) {
> + char pdest_affinity = pDest->def->fields[i].affinity;
> + char psrc_affinity = pSrc->def->fields[i].affinity;
> + if (pdest_affinity != psrc_affinity) {
> return 0; /* Affinity must be the same on all columns */
> }
4. Unnecessary {}.
> - if (sql_column_collation(pDest, i) !=
> - sql_column_collation(pSrc, i)) {
> + if (sql_column_collation(pDest->def, i) !=
> + sql_column_collation(pSrc->def, i)) {
> return 0; /* Collating sequence must be the same on all columns */
> }
5. Same.
> - if (!table_column_is_nullable(pDest, i)
> - && table_column_is_nullable(pSrc, i)) {
> + if (!table_column_is_nullable(pDest->def, i)
> + && table_column_is_nullable(pSrc->def, i)) {
> return 0; /* tab2 must be NOT NULL if tab1 is */
> }
6. Same.
> diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c
> index 463bb7e..c49817f 100644
> --- a/src/box/sql/pragma.c
> +++ b/src/box/sql/pragma.c
> @@ -373,7 +373,9 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */
> i; k++) {
> }
> }
> - bool nullable = table_column_is_nullable(pTab, i);
> + bool nullable =
> + table_column_is_nullable(pTab->def,
> + i);
7. Now this function can not be names table_column.... It does not take
table as an argument. Please, rename it to space_def.
> diff --git a/src/box/sql/select.c b/src/box/sql/select.c
> index 34d296d..ff9f18b 100644
> --- a/src/box/sql/select.c
> +++ b/src/box/sql/select.c
> @@ -1636,7 +1636,7 @@ columnTypeImpl(NameContext * pNC, Expr * pExpr,
> break;
> }
>
> - assert(pTab && pExpr->pTab == pTab);
> + assert(pTab && pExpr->space_def == pTab->def);
8. Please, use explicit != NULL.
> diff --git a/src/box/sql/update.c b/src/box/sql/update.c
> index 2f36423..38f824f 100644
> --- a/src/box/sql/update.c
> +++ b/src/box/sql/update.c
> @@ -69,30 +69,27 @@
> * space.
> */
> void
> -sqlite3ColumnDefault(Vdbe * v, Table * pTab, int i, int iReg)
> +sqlite3ColumnDefault(Vdbe * v, struct space_def * def, int i, int iReg)
> {
> - assert(pTab != 0);
> - assert(pTab->def->opts.is_view == (pTab->pSelect != NULL));
> - if (!pTab->def->opts.is_view) {
> + assert(def != NULL);
> + if (!def->opts.is_view) {
> sqlite3_value *pValue = 0;
> - Column *pCol = &pTab->aCol[i];
> - VdbeComment((v, "%s.%s", pTab->def->name,
> - pTab->def->fields[i].name));
> - assert(i < (int)pTab->def->field_count);
> + char affinity = def->fields[i].affinity;
> + VdbeComment((v, "%s.%s", def->name, def->fields[i].name));
> + assert(i < (int)def->field_count);
>
> Expr *expr = NULL;
> struct space *space =
> - space_cache_find(SQLITE_PAGENO_TO_SPACEID(pTab->tnum));
> + space_cache_find(def->id);
9. Why do you still need space_cache_find, if you already have
space_def and default_value_expr in it?
> diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c
> index f76c689..f9927ed 100644
> --- a/src/box/sql/vdbeaux.c
> +++ b/src/box/sql/vdbeaux.c
> @@ -4724,28 +4724,22 @@ table_column_nullable_action(struct Table *tab, uint32_t column)
> * @return return nullability flag value
> */
> bool
> -table_column_is_nullable(struct Table *tab, uint32_t column)
> +table_column_is_nullable(struct space_def *def, uint32_t column)
> {
> /* Temporary hack: until Tarantoool's ephemeral spaces are on-boarded,
> * views are not handled properly in Tarantool as well. */
> - if (!(tab->tabFlags | TF_Ephemeral || space_is_view(tab))) {
> - uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(tab->tnum);
> - struct space *space = space_cache_find(space_id);
> -
> - assert(space);
> -
> + struct space *space = space_cache_find(def->id);
10. You do not need space_cache_find. Space_def is enough here, it has
nullable action too.
^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2018-05-03 11:38 UTC | newest]
Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-25 16:52 [tarantool-patches] [PATCH v3 0/4] sql: Removed Column fields to server with region allocations Kirill Shcherbatov
2018-04-25 16:52 ` [tarantool-patches] [PATCH v3 1/4] sql: Fix code style in sqlite3Pragma Kirill Shcherbatov
2018-04-26 11:47 ` [tarantool-patches] " Vladislav Shpilevoy
2018-04-25 16:52 ` [tarantool-patches] [PATCH v3 2/4] sql: Remove zName and nColumn from SQL Kirill Shcherbatov
2018-04-25 17:10 ` [tarantool-patches] " Kirill Shcherbatov
2018-04-26 12:12 ` Vladislav Shpilevoy
2018-04-26 11:47 ` Vladislav Shpilevoy
2018-04-25 16:52 ` [tarantool-patches] [PATCH v3 3/4] sql: Removed type " Kirill Shcherbatov
2018-04-25 16:52 ` [tarantool-patches] [PATCH v3 4/4] sql: Region-based allocations Kirill Shcherbatov
2018-04-26 11:47 ` [tarantool-patches] " Vladislav Shpilevoy
2018-04-26 11:47 ` [tarantool-patches] Re: [PATCH v3 0/4] sql: Removed Column fields to server with region allocations Vladislav Shpilevoy
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 0/7] sql: refactor SQL Parser structures Kirill Shcherbatov
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 1/7] sql: fix code style in sqlite3Pragma Kirill Shcherbatov
2018-05-03 10:10 ` [tarantool-patches] " Vladislav Shpilevoy
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 2/7] sql: remove zName and nColumn from SQL Kirill Shcherbatov
2018-05-03 10:10 ` [tarantool-patches] " Vladislav Shpilevoy
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 3/7] sql: start using type from space_def Kirill Shcherbatov
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 4/7] sql: start using collations and is_nullable " Kirill Shcherbatov
2018-05-03 10:21 ` [tarantool-patches] " Vladislav Shpilevoy
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 5/7] sql: move names to server Kirill Shcherbatov
2018-05-03 11:08 ` [tarantool-patches] " Vladislav Shpilevoy
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 6/7] sql: start using is_view field from space_def Kirill Shcherbatov
2018-05-03 11:16 ` [tarantool-patches] " Vladislav Shpilevoy
2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 7/7] sql: space_def* instead of Table* in Expr Kirill Shcherbatov
2018-05-03 11:32 ` [tarantool-patches] " Vladislav Shpilevoy
2018-05-03 10:10 ` [tarantool-patches] Re: [PATCH v4 0/7] sql: refactor SQL Parser structures Vladislav Shpilevoy
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox