* [tarantool-patches] [PATCH v5 2/3] sql: remove SQL fields from Table and Column
2018-05-11 8:49 [tarantool-patches] [PATCH v5 0/3] sql: refactor SQL Parser structures Kirill Shcherbatov
2018-05-11 8:49 ` [tarantool-patches] [PATCH v5 1/3] sql: fix code style in sqlite3Pragma Kirill Shcherbatov
@ 2018-05-11 8:49 ` Kirill Shcherbatov
2018-05-11 20:59 ` [tarantool-patches] " Vladislav Shpilevoy
2018-05-11 8:49 ` [tarantool-patches] [PATCH v5 3/3] sql: space_def* instead of Table* in Expr Kirill Shcherbatov
2018-05-11 8:58 ` [tarantool-patches] Re: [PATCH v5 0/3] sql: refactor SQL Parser structures Vladislav Shpilevoy
3 siblings, 1 reply; 13+ messages in thread
From: Kirill Shcherbatov @ 2018-05-11 8:49 UTC (permalink / raw)
To: tarantool-patches; +Cc: v.shpilevoy, Kirill Shcherbatov
1. Removed zName, is_nullable, collation, type
from SQL Column.
2. Removed zColumns, zName from SQL Table.
3. Refactored Parser to use def_expression directly.
4. Introduced is_view flag.
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, #3218.
---
src/box/field_def.h | 6 +
src/box/space_def.c | 29 +++--
src/box/sql.c | 128 +++++++++++++++----
src/box/sql.h | 33 +++++
src/box/sql/alter.c | 55 +++++---
src/box/sql/analyze.c | 16 ++-
src/box/sql/build.c | 334 ++++++++++++++++++++++++++----------------------
src/box/sql/delete.c | 21 +--
src/box/sql/expr.c | 14 +-
src/box/sql/fkey.c | 38 +++---
src/box/sql/hash.c | 5 +-
src/box/sql/hash.h | 2 +-
src/box/sql/insert.c | 67 +++++-----
src/box/sql/pragma.c | 34 +++--
src/box/sql/prepare.c | 45 +++----
src/box/sql/resolve.c | 22 ++--
src/box/sql/select.c | 159 +++++++++++++----------
src/box/sql/sqliteInt.h | 37 ++++--
src/box/sql/tokenize.c | 5 +-
src/box/sql/treeview.c | 2 +-
src/box/sql/trigger.c | 7 +-
src/box/sql/update.c | 33 ++---
src/box/sql/util.c | 9 --
src/box/sql/vdbe.c | 2 +-
src/box/sql/vdbeaux.c | 9 +-
src/box/sql/where.c | 12 +-
src/box/sql/wherecode.c | 4 +-
src/box/sql/whereexpr.c | 6 +-
28 files changed, 675 insertions(+), 459 deletions(-)
diff --git a/src/box/field_def.h b/src/box/field_def.h
index dfc1950..a42beab 100644
--- a/src/box/field_def.h
+++ b/src/box/field_def.h
@@ -116,6 +116,12 @@ struct field_def {
struct Expr *default_value_expr;
};
+static inline bool
+nullable_action_to_is_nullable(enum on_conflict_action nullable_action)
+{
+ return nullable_action == ON_CONFLICT_ACTION_NONE;
+}
+
#if defined(__cplusplus)
} /* extern "C" */
#endif /* defined(__cplusplus) */
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..7d48cdc 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->nCol;
+ int i, n = def->field_count;
p = enc->encode_array(base, n);
@@ -1441,47 +1443,53 @@ 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 Expr *def = field->default_value_expr;
+ 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;
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);
+
+ assert(def->fields[i].is_nullable ==
+ nullable_action_to_is_nullable(
+ def->fields[i].nullable_action));
+
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"));
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);
@@ -1496,13 +1504,12 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
*/
int tarantoolSqlite3MakeTableOpts(Table *pTable, const char *zSql, void *buf)
{
- (void)pTable;
const struct Enc *enc = get_enc(buf);
char *base = buf, *p;
bool is_view = false;
if (pTable != NULL)
- is_view = pTable->pSelect != NULL;
+ is_view = pTable->def->opts.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));
@@ -1523,6 +1530,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;
@@ -1534,7 +1544,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;
}
@@ -1549,11 +1559,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 ==
+ nullable_action_to_is_nullable(
+ def->fields[col].nullable_action));
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);
@@ -1565,9 +1580,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);
@@ -1681,3 +1697,65 @@ 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, const char *name)
+{
+ struct space_def *def = NULL;
+ struct region *region = &fiber()->gc;
+ 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) {
+ diag_set(OutOfMemory, sizeof(struct tuple_dictionary),
+ "region_alloc", "sql_ephemeral_space_def_new");
+ parser->rc = SQL_TARANTOOL_ERROR;
+ parser->nErr++;
+ return NULL;
+ } else {
+ memset(def, 0, size);
+ }
+ memcpy(def->name, name, name_len);
+ def->name[name_len] = '\0';
+ def->opts.temporary = true;
+ return def;
+}
+
+Table *
+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, name);
+ 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);
+
+ /* 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..ac8d07a 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,38 @@ 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 parser SQL Parser object.
+ * @param name 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, const char *name);
+
+/**
+ * Create and initialize a new ephemeric space_def object.
+ * @param parser SQL Parser object.
+ * @param name Table to create name.
+ * @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, const char *name);
+
+/**
+ * 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 table 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..85404ac 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
@@ -144,6 +144,9 @@ sqlite3AlterRenameTable(Parse * pParse, /* Parser context. */
void
sqlite3AlterFinishAddColumn(Parse * pParse, Token * pColDef)
{
+ /* This function is not implemented yet #3075. */
+ unreachable();
+
Table *pNew; /* Copy of pParse->pNewTable */
Table *pTab; /* Table being altered */
const char *zTab; /* Table name */
@@ -160,11 +163,12 @@ sqlite3AlterFinishAddColumn(Parse * pParse, Token * pColDef)
pNew = pParse->pNewTable;
assert(pNew);
- zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */
- pCol = &pNew->aCol[pNew->nCol - 1];
+ /* Skip the "sqlite_altertab_" prefix on the name. */
+ zTab = &pNew->def->name[16];
+ 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);
@@ -195,7 +199,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 ==
+ nullable_action_to_is_nullable(
+ pNew->def->fields[pNew->def->field_count - 1].nullable_action));
+
+ 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;
@@ -227,7 +236,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);
}
/*
@@ -248,10 +257,13 @@ sqlite3AlterFinishAddColumn(Parse * pParse, Token * pColDef)
void
sqlite3AlterBeginAddColumn(Parse * pParse, SrcList * pSrc)
{
+ /* This function is not implemented yet #3075. */
+ unreachable();
+
Table *pNew;
Table *pTab;
Vdbe *v;
- int i;
+ uint32_t i;
int nAlloc;
sqlite3 *db = pParse->db;
@@ -281,25 +293,30 @@ 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);
- 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;
}
- memcpy(pNew->aCol, pTab->aCol, sizeof(Column) * pNew->nCol);
- for (i = 0; i < pNew->nCol; i++) {
- Column *pCol = &pNew->aCol[i];
- pCol->zName = sqlite3DbStrDup(db, pCol->zName);
- pCol->coll = NULL;
+ memcpy(pNew->aCol, pTab->aCol, sizeof(Column) * pNew->def->field_count);
+ for (i = 0; i < pNew->def->field_count; i++) {
+ /* FIXME: Column *pCol = &pNew->aCol[i]; */
+ /* FIXME: pCol->zName = sqlite3DbStrDup(db, pCol->zName); */
+ /* FIXME: pCol->coll = NULL; */
}
pNew->pSchema = db->pSchema;
pNew->addColOffset = pTab->addColOffset;
diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c
index f0054c5..2722c08 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():
@@ -1023,9 +1024,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);
@@ -1145,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 a2b712a..a02fe89 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);
}
/*
@@ -389,16 +382,13 @@ 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);
- 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)
space_def_delete(pTable->def);
- sqlite3DbFree(db, fields);
- }
sqlite3DbFree(db, pTable);
/* Verify that no lookaside memory was used by schema tables */
@@ -494,31 +484,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, name);
+ if (table == NULL)
return NULL;
- }
-
- table->def = def;
- table->zName = name;
table->iPKey = -1;
table->iAutoIncPKey = -1;
table->pSchema = db->pSchema;
@@ -568,10 +546,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 +605,35 @@ 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;
+ diag_set(OutOfMemory, columns_new * sizeof(table->def->fields[0]),
+ "region_alloc", "sql_field_retrieve");
+ parser->rc = SQL_TARANTOOL_ERROR;
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,44 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
sqlite3 *db = pParse->db;
if ((p = pParse->pNewTable) == 0)
return;
+ assert(p->def->opts.temporary);
#if SQLITE_MAX_COLUMN
- if (p->nCol + 1 > db->aLimit[SQLITE_LIMIT_COLUMN]) {
- sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName);
+ if ((int)p->def->field_count + 1 > db->aLimit[SQLITE_LIMIT_COLUMN]) {
+ sqlite3ErrorMsg(pParse, "too many columns on %s",
+ p->def->name);
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 == NULL)
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;
-
+ 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.
@@ -718,8 +704,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.
@@ -728,19 +714,18 @@ 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->nCol++;
p->def->field_count++;
pParse->constraintName.n = 0;
}
@@ -756,9 +741,11 @@ 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->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);
}
/*
@@ -871,38 +858,31 @@ void
sqlite3AddDefaultValue(Parse * pParse, ExprSpan * pSpan)
{
Table *p;
- Column *pCol;
sqlite3 *db = pParse->db;
p = pParse->pNewTable;
+ assert(p->def->opts.temporary);
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);
@@ -942,12 +922,12 @@ 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;
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 +942,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;
@@ -973,9 +953,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;
@@ -1036,16 +1017,16 @@ 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)
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
@@ -1056,9 +1037,8 @@ sqlite3AddCollateType(Parse * pParse, Token * pToken)
if (pIdx->aiColumn[0] == i)
pIdx->coll_array[0] = sql_column_collation(p, i);
}
- } else {
- sqlite3DbFree(db, zColl);
}
+ sqlite3DbFree(db, zColl);
}
/**
@@ -1087,8 +1067,10 @@ 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);
- return table->aCol[column].coll;
+ assert(column < (uint32_t)table->def->field_count);
+ struct coll *coll =
+ coll_by_id(table->def->fields[column].coll_id);
+ return coll;
}
return space->format->fields[column].coll;
@@ -1306,10 +1288,9 @@ 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;
- }
- n += identLength(p->zName);
+ for (i = 0; i < (int)p->def->field_count; i++)
+ n += identLength(p->def->fields[i].name) + 5;
+ n += identLength(p->def->name);
if (n < 50) {
zSep = "";
zSep2 = ",";
@@ -1319,7 +1300,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);
@@ -1327,9 +1308,9 @@ createTableStmt(sqlite3 * db, Table * p)
}
sqlite3_snprintf(n, zStmt, "CREATE TABLE ");
k = sqlite3Strlen30(zStmt);
- identPut(zStmt, &k, p->zName);
+ identPut(zStmt, &k, p->def->name);
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 +1324,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 +1354,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 +1374,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,9 +1415,11 @@ 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;
+ pTab->def->fields[i].nullable_action
+ = ON_CONFLICT_ACTION_ABORT;
+ pTab->def->fields[i].is_nullable = false;
}
}
}
@@ -1446,7 +1430,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));
@@ -1660,10 +1644,10 @@ 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->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);
@@ -1726,9 +1710,9 @@ parseTableSchemaRecord(Parse * pParse, int iSpaceId, char *zStmt)
int i, iTop = pParse->nMem + 1;
pParse->nMem += 4;
- sqlite3VdbeAddOp4(v,
- OP_String8, 0, iTop, 0,
- sqlite3DbStrDup(pParse->db, p->zName), P4_DYNAMIC);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, iTop, 0,
+ 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);
@@ -1853,7 +1837,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
@@ -1863,17 +1846,21 @@ 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",
- p->zName);
+ p->def->name);
return;
} else {
convertToWithoutRowidTable(pParse, p);
}
}
+ if (sql_table_def_rebuild(db, p) != 0)
+ return;
+
#ifndef SQLITE_OMIT_CHECK
/* Resolve names in all CHECK constraint expressions.
*/
@@ -1908,7 +1895,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
@@ -1937,7 +1925,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;
@@ -1949,9 +1939,9 @@ 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);
- }
/* Check to see if we need to create an _sequence table for
* keeping track of autoincrement keys.
@@ -1966,7 +1956,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. */
@@ -1986,7 +1976,7 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
if (db->init.busy) {
Table *pOld;
Schema *pSchema = p->pSchema;
- 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);
@@ -1996,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);
@@ -2048,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;
@@ -2101,7 +2093,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 +2111,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);
+ pTable->def->name);
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
@@ -2134,11 +2126,12 @@ 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;
sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
- pTable->nCol = -1;
+ pTable->def->field_count = -1;
db->lookaside.bDisable++;
pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
pParse->nTab = n;
@@ -2149,11 +2142,16 @@ 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);
+ struct space_def *old_def = pTable->def;
+ /* Delete it manually. */
+ old_def->opts.temporary = true;
+ if (sql_table_def_rebuild(db, pTable) != 0)
+ nErr++;
+ space_def_delete(old_def);
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 +2161,31 @@ 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);
+ assert(pSelTab->def->opts.temporary);
+
+ struct space_def *old_def = pTable->def;
+ struct space_def *new_def = NULL;
+ new_def = sql_ephemeral_space_def_new(pParse, old_def->name);
+ if (new_def == NULL) {
+ nErr++;
+ } else {
+ memcpy(new_def, old_def, sizeof(struct space_def));
+ new_def->dict = NULL;
+ new_def->opts.temporary = true;
+ 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->nCol = 0;
- pSelTab->aCol = 0;
+ pSelTab->aCol = NULL;
+ pSelTab->def = old_def;
+ pSelTab->def->fields = NULL;
+ pSelTab->def->field_count = 0;
} else {
- pTable->nCol = 0;
+ pTable->def->field_count = 0;
nErr++;
}
sqlite3DeleteTable(db, pSelTab);
@@ -2193,10 +2210,22 @@ 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);
+ /* 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 +2498,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 +2537,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);
@@ -2904,7 +2933,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;
}
@@ -2940,7 +2970,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);
}
@@ -2953,7 +2983,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;
@@ -2966,7 +2996,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,10 +4050,10 @@ 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);
+ sqlite3XPrintf(&errMsg, "%s.%s", pTab->def->name, zCol);
}
}
zErr = sqlite3StrAccumFinish(&errMsg);
@@ -4181,7 +4213,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..37baca2 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);
}
@@ -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
@@ -382,7 +383,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++;
@@ -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);
@@ -734,13 +736,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
@@ -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 0c86761..119940c 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;
}
@@ -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. */
@@ -4242,20 +4243,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..916b346 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,
@@ -331,7 +331,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;
@@ -535,13 +535,8 @@ 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";
pExpr = sqlite3ExprAddCollateString(pParse, pExpr,
- coll_name);
+ "binary");
} else {
pExpr->iTable = regBase;
pExpr->affinity = SQLITE_AFF_INTEGER;
@@ -650,7 +645,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);
@@ -724,7 +719,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);
}
/*
@@ -863,12 +859,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;
@@ -954,7 +950,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;
}
@@ -1079,7 +1075,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++;
@@ -1282,14 +1278,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
@@ -1378,7 +1374,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..b109cca 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(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/hash.h b/src/box/sql/hash.h
index f049c6d..f57824e 100644
--- a/src/box/sql/hash.h
+++ b/src/box/sql/hash.h
@@ -80,7 +80,7 @@ struct Hash {
struct HashElem {
HashElem *next, *prev; /* Next and previous elements in the table */
void *data; /* Data associated with this element */
- const char *pKey; /* Key associated with this element */
+ char *pKey; /* Key associated with this element */
};
/*
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 939b5e3..c272ae1 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));
}
/*
@@ -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);
@@ -1142,8 +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,
- pTab->aCol[i].zName);
+ sqlite3MPrintf(db, "%s.%s", pTab->def->name,
+ pTab->def->fields[i].name);
sqlite3VdbeAddOp3(v, OP_HaltIfNull,
SQLITE_CONSTRAINT_NOTNULL,
onError, regNewData + 1 + i);
@@ -1197,7 +1200,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,
@@ -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 */
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regNewData + 1,
- pTab->nCol, aRegIdx[ix]);
+ pTab->def->field_count, aRegIdx[ix]);
VdbeComment((v, "for %s", pIdx->zName));
}
@@ -1390,10 +1394,11 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */
for (i = 0; i < nPkCol; i++) {
assert(pPk->aiColumn[i] >= 0);
x = pPk->aiColumn[i];
- sqlite3VdbeAddOp3(v, OP_Column,
- iThisCur, x, regR + i);
- VdbeComment((v, "%s.%s", pTab->zName,
- pTab->aCol[pPk->aiColumn[i]].zName));
+ sqlite3VdbeAddOp3(v, OP_Column, iThisCur,
+ x, regR + i);
+ VdbeComment((v, "%s.%s", pTab->def->name,
+ pTab->def->fields[
+ pPk->aiColumn[i]].name));
}
}
if (isUpdate && uniqueByteCodeNeeded) {
@@ -1784,13 +1789,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 b9038b7..250c402 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++) {
}
@@ -380,11 +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, pCol->zName,
- field_type_strs[
- sqlite3ColumnType
- (pCol)],
+ i, name,
+ field_type_strs[type],
nullable == 0,
expr_str, k);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1,
@@ -402,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);
@@ -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 != NULL) {
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,11 +618,12 @@ 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);
+ pTab->def->name);
for (i = 1, pFK = pTab->pFKey; pFK;
i++, pFK = pFK->pNextFrom) {
pParent =
@@ -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..926c3dd 100644
--- a/src/box/sql/prepare.c
+++ b/src/box/sql/prepare.c
@@ -204,26 +204,6 @@ sqlite3InitDatabase(sqlite3 * db)
return rc;
}
-
-/*
- * Free all memory allocations in the pParse object
- */
-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;
- }
-}
-
/*
* Compile the UTF-8 encoded SQL statement zSql into a statement handle.
*/
@@ -241,9 +221,7 @@ sqlite3Prepare(sqlite3 * db, /* Database handle. */
int rc = SQLITE_OK; /* Result code */
int i; /* Loop counter */
Parse sParse; /* Parsing context */
-
- memset(&sParse, 0, PARSE_HDR_SZ);
- memset(PARSE_TAIL(&sParse), 0, PARSE_TAIL_SZ);
+ sql_parser_create(&sParse);
sParse.pReprepare = pReprepare;
assert(ppStmt && *ppStmt == 0);
/* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */
@@ -265,6 +243,7 @@ sqlite3Prepare(sqlite3 * db, /* Database handle. */
* works even if READ_UNCOMMITTED is set.
*/
sParse.db = db;
+
if (nBytes >= 0 && (nBytes == 0 || zSql[nBytes - 1] != 0)) {
char *zSqlCopy;
int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
@@ -350,7 +329,7 @@ sqlite3Prepare(sqlite3 * db, /* Database handle. */
end_prepare:
- sqlite3ParserReset(&sParse);
+ sql_parser_free(&sParse);
rc = sqlite3ApiExit(db, rc);
assert((rc & db->errMask) == rc);
return rc;
@@ -456,3 +435,21 @@ sqlite3_prepare_v2(sqlite3 * db, /* Database handle. */
assert(rc == SQLITE_OK || ppStmt == 0 || *ppStmt == 0); /* VERIFY: F13021 */
return rc;
}
+
+void
+sql_parser_free(Parse *parser)
+{
+ if (parser == NULL)
+ return;
+ sqlite3 *db = parser->db;
+ sqlite3DbFree(db, parser->aLabel);
+ sqlite3ExprListDelete(db, parser->pConstExpr);
+ if (db != NULL) {
+ assert(db->lookaside.bDisable >=
+ parser->disableLookaside);
+ db->lookaside.bDisable -= parser->disableLookaside;
+ }
+ parser->disableLookaside = 0;
+ struct region *region = &fiber()->gc;
+ region_truncate(region, parser->region_initial_size);
+}
diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c
index 823062a..f95ef27 100644
--- a/src/box/sql/resolve.c
+++ b/src/box/sql/resolve.c
@@ -239,8 +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->nCol > 0);
+ assert(pTab != 0 && pTab->def->name != NULL);
+ assert(pTab->def->field_count > 0);
if (pItem->pSelect
&& (pItem->pSelect->
selFlags & SF_NestedFrom) != 0) {
@@ -263,7 +263,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;
@@ -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 =
@@ -1602,7 +1604,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 5a50413..32a8e08 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,14 +1661,15 @@ 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);
+ 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
}
@@ -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,
@@ -1764,8 +1765,7 @@ generateColumnNames(Parse * pParse, /* Parser context */
} else if (fullNames) {
char *zName = 0;
zName =
- sqlite3MPrintf(db, "%s.%s", pTab->zName,
- zCol);
+ sqlite3MPrintf(db, "%s.%s", pTab->def->name, zCol);
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName,
SQLITE_DYNAMIC);
} else {
@@ -1799,8 +1799,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 */
@@ -1819,11 +1818,25 @@ sqlite3ColumnsFromExprList(Parse * pParse, /* Parsing context */
testcase(aCol == 0);
} else {
nCol = 0;
- aCol = 0;
+ aCol = NULL;
}
assert(nCol == (i16) nCol);
- *pnCol = nCol;
- *paCol = aCol;
+
+ /*
+ * This should be a table without resolved columns.
+ * sqlite3ViewGetColumnNames could use it to resolve
+ * names for existent table.
+ */
+ assert(pTable->def->fields == NULL);
+ struct region *region = &fiber()->gc;
+ pTable->def->fields =
+ region_alloc(region, nCol * sizeof(pTable->def->fields[0]));
+ memset(pTable->def->fields, 0, nCol * sizeof(pTable->def->fields[0]));
+ /* NULL nullable_action should math is_nullable flag. */
+ for (int i = 0; i < nCol; i++)
+ pTable->def->fields[i].is_nullable = true;
+ 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 +1858,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 +1887,28 @@ 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 name_len = (uint32_t)strlen(zName);
+ if (zName != NULL && sqlite3HashInsert(&ht, zName, pCol) == pCol)
sqlite3OomFault(db);
+ pTable->def->fields[i].name =
+ region_alloc(region, name_len + 1);
+ if (pTable->def->fields[i].name == NULL) {
+ sqlite3OomFault(db);
+ } else {
+ memcpy(pTable->def->fields[i].name, zName, name_len);
+ pTable->def->fields[i].name[name_len] = '\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 (rc != SQLITE_OK) {
sqlite3DbFree(db, aCol);
- *paCol = 0;
- *pnCol = 0;
- return SQLITE_NOMEM_BKPT;
+ pTable->def->fields = NULL;
+ pTable->def->field_count = 0;
+ pTable->aCol = NULL;
+ rc = SQLITE_NOMEM_BKPT;
}
- return SQLITE_OK;
+ return rc;
}
/*
@@ -1918,26 +1937,28 @@ 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);
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;
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);
}
@@ -1945,6 +1966,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 allocated on region.
*/
Table *
sqlite3ResultSetOfSelect(Parse * pParse, Select * pSelect)
@@ -1963,20 +1985,17 @@ 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, NULL);
+ if (pTab == NULL)
return 0;
- }
/* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
* is disabled
*/
assert(db->lookaside.bDisable);
pTab->nTabRef = 1;
- 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,11 +4516,11 @@ 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, 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));
@@ -4562,8 +4581,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 =
@@ -4683,18 +4701,24 @@ selectExpander(Walker * pWalker, Select * p)
assert(pFrom->pTab == 0);
if (sqlite3WalkSelect(pWalker, pSel))
return WRC_Abort;
+ /* Will overwritten with pointer as unique identifier. */
+ const char *name = "sqlite_sq_DEADBEAFDEADBEAF";
pFrom->pTab = pTab =
- sqlite3DbMallocZero(db, sizeof(Table));
- if (pTab == 0)
+ sql_ephemeral_table_new(pParse, name);
+ if (pTab == NULL)
return WRC_Abort;
+ /* rewrite old name with correct pointer */
+ name = tt_sprintf("sqlite_sq_%llX", (void *)pTab);
+ sprintf(pTab->def->name, "%s", name);
+
pTab->nTabRef = 1;
- pTab->zName =
- sqlite3MPrintf(db, "sqlite_sq_%p", (void *)pTab);
while (pSel->pPrior) {
pSel = pSel->pPrior;
}
- sqlite3ColumnsFromExprList(pParse, pSel->pEList,
- &pTab->nCol, &pTab->aCol);
+ 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));
@@ -4709,7 +4733,7 @@ selectExpander(Walker * pWalker, Select * p)
if (pTab->nTabRef >= 0xffff) {
sqlite3ErrorMsg(pParse,
"too many references to \"%s\": max 65535",
- pTab->zName);
+ pTab->def->name);
pFrom->pTab = 0;
return WRC_Abort;
}
@@ -4723,14 +4747,16 @@ 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,
- pTab->zName);
- nCol = pTab->nCol;
- pTab->nCol = -1;
+ pTab->def->name);
+ nCol = pTab->def->field_count;
+ pTab->def->field_count = -1;
sqlite3WalkSelect(pWalker, pFrom->pSelect);
- pTab->nCol = nCol;
+ pTab->def->field_count = nCol;
}
#endif
}
@@ -4819,7 +4845,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;
@@ -4835,9 +4861,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 */
@@ -5266,7 +5291,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 : "");
@@ -5372,10 +5397,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->def->name,
pSub->pEList->nExpr);
goto select_end;
}
@@ -5493,7 +5518,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);
@@ -5528,10 +5553,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);
@@ -5542,7 +5567,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 8bb45c9..4fba008 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -1867,15 +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;
- /**
- * 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 */
@@ -1936,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. */
@@ -1950,7 +1940,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 +2925,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,
@@ -3390,7 +3381,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);
@@ -3515,7 +3505,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 *);
@@ -3975,7 +3965,6 @@ void sqlite3InvalidFunction(sqlite3_context *, int, sqlite3_value **);
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *);
int sqlite3VdbeParameterIndex(Vdbe *, const char *, int);
int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
-void sqlite3ParserReset(Parse *);
int sqlite3Reprepare(Vdbe *);
void sqlite3ExprListCheckLength(Parse *, ExprList *, const char *);
struct coll *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
@@ -4153,4 +4142,24 @@ table_column_nullable_action(struct Table *tab, uint32_t column);
bool
table_column_is_nullable(struct Table *tab, uint32_t column);
+/**
+ * Initialize a new parser object.
+ * @param parser object to initialize.
+ */
+static inline void
+sql_parser_create(struct Parse *parser)
+{
+ memset(parser, 0, PARSE_HDR_SZ);
+ memset(PARSE_TAIL(parser), 0, PARSE_TAIL_SZ);
+ struct region *region = &fiber()->gc;
+ parser->region_initial_size = region_used(region);
+}
+
+/**
+ * Release the parser object resources.
+ * @param parser object to release.
+ */
+void
+sql_parser_free(struct Parse *parser);
+
#endif /* SQLITEINT_H */
diff --git a/src/box/sql/tokenize.c b/src/box/sql/tokenize.c
index c77aa9b..e37ad49 100644
--- a/src/box/sql/tokenize.c
+++ b/src/box/sql/tokenize.c
@@ -661,15 +661,16 @@ sql_expr_compile(sqlite3 *db, const char *expr, struct Expr **result)
sprintf(stmt, "%s%s", outer, expr);
struct Parse parser;
- memset(&parser, 0, sizeof(parser));
+ sql_parser_create(&parser);
parser.db = db;
parser.parse_only = true;
+
char *unused;
if (sqlite3RunParser(&parser, stmt, &unused) != SQLITE_OK) {
diag_set(ClientError, ER_SQL_EXECUTE, expr);
return -1;
}
*result = parser.parsed_expr;
- sqlite3ParserReset(&parser);
+ sql_parser_free(&parser);
return 0;
}
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 28c56db..9259343 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;
@@ -868,6 +868,7 @@ codeRowTrigger(Parse * pParse, /* Current parse context */
return 0;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pSubParse;
+ sql_parser_create(pSubParse);
pSubParse->db = db;
pSubParse->pTriggerTab = pTab;
pSubParse->pToplevel = pTop;
@@ -883,7 +884,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",
@@ -934,7 +935,7 @@ codeRowTrigger(Parse * pParse, /* Current parse context */
assert(!pSubParse->pZombieTab);
assert(!pSubParse->pTriggerPrg && !pSubParse->nMaxArg);
- sqlite3ParserReset(pSubParse);
+ sql_parser_free(pSubParse);
sqlite3StackFree(db, pSubParse);
return pPrg;
diff --git a/src/box/sql/update.c b/src/box/sql/update.c
index f3bd0b7..5f5807c 100644
--- a/src/box/sql/update.c
+++ b/src/box/sql/update.c
@@ -72,11 +72,13 @@ 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->zName, pCol->zName));
- assert(i < pTab->nCol);
+ VdbeComment((v, "%s.%s", pTab->def->name,
+ pTab->def->fields[i].name));
+ assert(i < (int)pTab->def->field_count);
Expr *expr = NULL;
struct space *space =
@@ -212,14 +214,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 +239,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 +256,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 +314,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 +329,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 +481,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 +512,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 +568,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/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().
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/vdbeaux.c b/src/box/sql/vdbeaux.c
index b3998ea..0ccca77 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -4739,10 +4739,13 @@ table_column_is_nullable(struct Table *tab, uint32_t column)
assert(format);
assert(format->field_count > column);
- return format->fields[column].nullable_action ==
- ON_CONFLICT_ACTION_NONE;
+ return nullable_action_to_is_nullable(
+ format->fields[column].nullable_action);
} else {
/* tab is ephemeral (in SQLite sense). */
- return tab->aCol[column].notNull == 0;
+ assert(tab->def->fields[column].is_nullable ==
+ nullable_action_to_is_nullable(
+ tab->def->fields[column].nullable_action));
+ return tab->def->fields[column].is_nullable;
}
}
diff --git a/src/box/sql/where.c b/src/box/sql/where.c
index 7a7103c..9ab6295 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) {
@@ -1638,8 +1638,8 @@ whereLoopPrint(WhereLoop * p, WhereClause * pWC)
#ifdef SQLITE_DEBUG
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);
+ sqlite3DebugPrintf(" %12s", pItem->zAlias ? pItem->zAlias :
+ pTab->def->name);
#endif
const char *zName;
if (p->pIndex && (zName = p->pIndex->zName) != 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,
@@ -4749,7 +4749,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 f1112f2..9d4055a 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;
}
/*
@@ -1158,7 +1158,7 @@ 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 86ee273..e602111 100644
--- a/src/box/sql/whereexpr.c
+++ b/src/box/sql/whereexpr.c
@@ -1502,13 +1502,13 @@ 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);
+ pTab->def->name, j);
return;
}
pColRef = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0);
--
2.7.4
^ permalink raw reply [flat|nested] 13+ messages in thread
* [tarantool-patches] [PATCH v5 3/3] sql: space_def* instead of Table* in Expr
2018-05-11 8:49 [tarantool-patches] [PATCH v5 0/3] sql: refactor SQL Parser structures Kirill Shcherbatov
2018-05-11 8:49 ` [tarantool-patches] [PATCH v5 1/3] sql: fix code style in sqlite3Pragma Kirill Shcherbatov
2018-05-11 8:49 ` [tarantool-patches] [PATCH v5 2/3] sql: remove SQL fields from Table and Column Kirill Shcherbatov
@ 2018-05-11 8:49 ` Kirill Shcherbatov
2018-05-11 20:59 ` [tarantool-patches] " Vladislav Shpilevoy
2018-05-11 8:58 ` [tarantool-patches] Re: [PATCH v5 0/3] sql: refactor SQL Parser structures Vladislav Shpilevoy
3 siblings, 1 reply; 13+ messages in thread
From: Kirill Shcherbatov @ 2018-05-11 8:49 UTC (permalink / raw)
To: tarantool-patches; +Cc: v.shpilevoy, Kirill Shcherbatov
This patch allows to remove Checks from SQL to
server as sqlite3ResolveSelfReference requires
Expr structure pointer.
Part of #3272.
---
src/box/field_def.c | 1 +
src/box/field_def.h | 14 ++++++
src/box/sql.c | 10 ++---
src/box/sql/build.c | 48 +++++++++++---------
src/box/sql/delete.c | 4 +-
src/box/sql/expr.c | 115 +++++++++++++++++++++++++++---------------------
src/box/sql/fkey.c | 13 +++---
src/box/sql/insert.c | 39 +++++++++-------
src/box/sql/pragma.c | 8 ++--
src/box/sql/resolve.c | 10 ++---
src/box/sql/select.c | 26 ++++++-----
src/box/sql/sqliteInt.h | 41 +++++------------
src/box/sql/update.c | 35 +++++++--------
src/box/sql/vdbeaux.c | 28 +++---------
src/box/sql/where.c | 13 +++---
src/box/sql/wherecode.c | 19 +++++---
src/box/sql/whereexpr.c | 2 +-
17 files changed, 219 insertions(+), 207 deletions(-)
diff --git a/src/box/field_def.c b/src/box/field_def.c
index 010b3b7..cdae5bc 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 = SQLITE_AFF_UNDEFINED,
.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 a42beab..b210756 100644
--- a/src/box/field_def.h
+++ b/src/box/field_def.h
@@ -70,6 +70,15 @@ enum on_conflict_action {
on_conflict_action_MAX
};
+enum affinity_type {
+ SQLITE_AFF_UNDEFINED = 0,
+ SQLITE_AFF_BLOB = 'A',
+ SQLITE_AFF_TEXT = 'B',
+ SQLITE_AFF_NUMERIC = 'C',
+ SQLITE_AFF_INTEGER = 'D',
+ SQLITE_AFF_REAL = 'E',
+};
+
/** \endcond public */
extern const char *field_type_strs[];
@@ -102,6 +111,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.
+ */
+ enum affinity_type 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 7d48cdc..5e8c96d 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));
@@ -1529,7 +1529,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);
@@ -1566,7 +1565,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 a02fe89..f082d01 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -703,7 +703,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 {
@@ -714,14 +714,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;
}
@@ -1034,8 +1034,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);
+ }
}
}
sqlite3DbFree(db, zColl);
@@ -1049,10 +1051,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
@@ -1067,9 +1069,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;
}
@@ -1325,18 +1327,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);
@@ -1845,6 +1848,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) {
@@ -3098,7 +3102,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..8b34c57 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 != NULL) {
/* 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,11 @@ sqlite3ExprCanBeNull(const Expr * p)
case TK_BLOB:
return 0;
case TK_COLUMN:
- assert(p->pTab != 0);
+ assert(p->space_def != NULL);
return ExprHasProperty(p, EP_CanBeNull) ||
(p->iColumn >= 0
- && table_column_is_nullable(p->pTab, p->iColumn));
+ && space_def_column_is_nullable(p->space_def,
+ p->iColumn));
default:
return 1;
}
@@ -2435,7 +2438,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 +3180,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,45 +3525,48 @@ 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);
}
}
-/*
+/**
* Generate code to extract the value of the iCol-th column of a table.
+ * @param v The VDBE under construction.
+ * @param space_def Space definition.
+ * @param iTabCur The PK cursor.
+ * @param iCol Index of the column to extract.
+ * @param regOut Extract the value into this register.
*/
void
-sqlite3ExprCodeGetColumnOfTable(Vdbe * v, /* The VDBE under construction */
- Table * pTab, /* The table containing the value */
- int iTabCur, /* The PK cursor */
- int iCol, /* Index of the column to extract */
- int regOut /* Extract the value into this register */
- )
+sqlite3ExprCodeGetColumnOfTable(Vdbe * v, struct space_def *space_def,
+ int iTabCur, int iCol, int regOut)
{
sqlite3VdbeAddOp3(v, OP_Column, iTabCur, iCol, regOut);
if (iCol >= 0) {
- sqlite3ColumnDefault(v, pTab, iCol, regOut);
+ sqlite3ColumnDefault(v, space_def, iCol, regOut);
}
}
-/*
+/**
* Generate code that will extract the iColumn-th column from
* table pTab and store the column value in a register.
*
- * An effort is made to store the column value in register iReg. This
- * is not garanteeed for GetColumn() - the result can be stored in
- * any register. But the result is guaranteed to land in register iReg
- * for GetColumnToReg().
+ * An effort is made to store the column value in register iReg.
+ * This is not garanteeed for GetColumn() - the result can be
+ * stored in any register. But the result is guaranteed to land
+ * in register iReg for GetColumnToReg().
+ * @param pParse Parsing and code generating context.
+ * @param space_def Space definition.
+ * @param iColumn Index of the table column.
+ * @param iTable The cursor pointing to the table.
+ * @param iReg Store results here.
+ * @param p5 P5 value for OP_Column + FLAGS.
+ * @return iReg value.
*/
int
-sqlite3ExprCodeGetColumn(Parse * pParse, /* Parsing and code generating context */
- Table * pTab, /* Description of the table we are reading from */
- int iColumn, /* Index of the table column */
- int iTable, /* The cursor pointing to the table */
- int iReg, /* Store results here */
- u8 p5 /* P5 value for OP_Column + FLAGS */
- )
+sqlite3ExprCodeGetColumn(Parse * pParse, struct space_def * space_def,
+ int iColumn, int iTable, int iReg, u8 p5)
{
Vdbe *v = pParse->pVdbe;
int i;
@@ -3572,7 +3581,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 {
@@ -3581,16 +3590,22 @@ sqlite3ExprCodeGetColumn(Parse * pParse, /* Parsing and code generating context
return iReg;
}
+/**
+ * Generate code that will extract the iColumn-th column from
+ * table pTab and store the column value in a register, copy the
+ * result.
+ * @param pParse Parsing and code generating context.
+ * @param space_def Space definition.
+ * @param iColumn Index of the table column.
+ * @param iTable The cursor pointing to the table.
+ * @param iReg Store results here.
+ */
void
-sqlite3ExprCodeGetColumnToReg(Parse * pParse, /* Parsing and code generating context */
- Table * pTab, /* Description of the table we are reading from */
- int iColumn, /* Index of the table column */
- int iTable, /* The cursor pointing to the table */
- int iReg /* Store results here */
- )
+sqlite3ExprCodeGetColumnToReg(Parse * pParse, struct space_def * space_def,
+ int iColumn, int iTable, int iReg)
{
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 +3792,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 +4256,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 +4280,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 +5453,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 916b346..f14a60d 100644
--- a/src/box/sql/fkey.c
+++ b/src/box/sql/fkey.c
@@ -298,7 +298,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);
@@ -526,15 +526,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;
pExpr = sqlite3ExprAddCollateString(pParse, pExpr,
"binary");
} else {
@@ -551,14 +550,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;
}
@@ -671,7 +670,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 c272ae1..8ecfe10 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 (space_def_column_is_nullable(pTab->def, i)
|| (pTab->tabFlags & TF_Autoincrement
&& pTab->iAutoIncPKey == i))
continue; /* This column is allowed to be NULL */
@@ -1796,19 +1798,22 @@ 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) {
- return 0; /* Affinity must be the same on all columns */
- }
- if (sql_column_collation(pDest, i) !=
- sql_column_collation(pSrc, 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)) {
- return 0; /* tab2 must be NOT NULL if tab1 is */
- }
+ char pdest_affinity = pDest->def->fields[i].affinity;
+ char psrc_affinity = pSrc->def->fields[i].affinity;
+ /* Affinity must be the same on all columns. */
+ if (pdest_affinity != psrc_affinity)
+ return 0;
+ /*
+ * Collating sequence must be the same on all
+ * columns.
+ */
+ if (sql_column_collation(pDest->def, i) !=
+ sql_column_collation(pSrc->def, i))
+ return 0;
+ /* The tab2 must be NOT NULL if tab1 is */
+ if (!space_def_column_is_nullable(pDest->def, i)
+ && space_def_column_is_nullable(pSrc->def, i))
+ return 0;
/* Default values for second and subsequent columns need to match. */
if (i > 0) {
uint32_t src_space_id =
diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c
index 250c402..0207ee8 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 =
+ space_def_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 f95ef27..35adb10 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 */
@@ -300,7 +300,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) {
@@ -364,7 +364,7 @@ lookupName(Parse * pParse, /* The parsing context */
: (((u32) 1) << iCol));
}
pExpr->iColumn = (i16) iCol;
- pExpr->pTab = pTab;
+ pExpr->space_def = pTab->def;
isTrigger = 1;
}
}
@@ -498,9 +498,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 32a8e08..5bd958a 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 != NULL && 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
@@ -1846,19 +1846,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;
@@ -1950,11 +1954,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)
@@ -5933,7 +5939,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 4fba008..ad7cc54 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 */
};
@@ -1879,26 +1878,6 @@ struct Column {
#define SQLITE_SO_DESC 1 /* Sort in ascending order */
#define SQLITE_SO_UNDEFINED -1 /* No sort order specified */
-/*
- * Column affinity types.
- *
- * These used to have mnemonic name like 'i' for SQLITE_AFF_INTEGER and
- * 't' for SQLITE_AFF_TEXT. But we can save a little space and improve
- * the speed a little by numbering the values consecutively.
- *
- * But rather than start with 0 or 1, we begin with 'A'. That way,
- * when multiple affinity types are concatenated into a string and
- * used as the P4 operand, they will be more readable.
- *
- * Note also that the numeric types are grouped together so that testing
- * for a numeric type is a single comparison. And the BLOB type is first.
- */
-#define SQLITE_AFF_BLOB 'A'
-#define SQLITE_AFF_TEXT 'B'
-#define SQLITE_AFF_NUMERIC 'C'
-#define SQLITE_AFF_INTEGER 'D'
-#define SQLITE_AFF_REAL 'E'
-
#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC)
/*
@@ -2226,7 +2205,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 +2341,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 +3501,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 +3588,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 +3783,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 +3871,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 *);
@@ -4140,7 +4121,7 @@ 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);
+space_def_column_is_nullable(struct space_def *def, uint32_t column);
/**
* Initialize a new parser object.
diff --git a/src/box/sql/update.c b/src/box/sql/update.c
index 5f5807c..9ae77e0 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));
- if (space != NULL && space->def->fields != NULL)
- expr = space->def->fields[i].default_value_expr;
+ assert(def->fields != NULL && i < (int)def->field_count);
+ if (def->fields != NULL)
+ expr = 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 0ccca77..3054fc3 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -4724,28 +4724,10 @@ 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)
+space_def_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 tuple_format *format = space->format;
-
- assert(format);
- assert(format->field_count > column);
-
- return nullable_action_to_is_nullable(
- format->fields[column].nullable_action);
- } else {
- /* tab is ephemeral (in SQLite sense). */
- assert(tab->def->fields[column].is_nullable ==
- nullable_action_to_is_nullable(
- tab->def->fields[column].nullable_action));
- return tab->def->fields[column].is_nullable;
- }
+ assert(def->fields[column].is_nullable ==
+ nullable_action_to_is_nullable(
+ def->fields[column].nullable_action));
+ return def->fields[column].is_nullable;
}
diff --git a/src/box/sql/where.c b/src/box/sql/where.c
index 9ab6295..c878a97 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 !space_def_column_is_nullable(pIdx->pTable->def, j);
} else if (j == (-1)) {
return 1;
} else {
@@ -2236,7 +2238,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;
@@ -3330,8 +3333,8 @@ wherePathSatisfiesOrderBy(WhereInfo * pWInfo, /* The WHERE clause */
if (isOrderDistinct
&& iColumn >= 0
&& j >= pLoop->nEq
- && table_column_is_nullable(pIndex->pTable,
- iColumn)) {
+ && space_def_column_is_nullable(
+ pIndex->pTable->def, iColumn)) {
isOrderDistinct = 0;
}
diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
index 9d4055a..1263e05 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;
@@ -1260,8 +1260,10 @@ 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 &&
+ space_def_column_is_nullable(pIdx->pTable->def,
+ j)) ||
+ j == XN_EXPR) {
assert(pLoop->nSkip == 0);
bSeekPastNull = 1;
nExtraReg = 1;
@@ -1307,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) {
+ && space_def_column_is_nullable(
+ pIdx->pTable->def, j)) ||
+ j == XN_EXPR) {
bSeekPastNull = 1;
}
}
@@ -1386,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
@@ -1724,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] 13+ messages in thread