<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body text="#000000" bgcolor="#FFFFFF">
<pre>Completely removes struct Table. Also the
patch simplifies memory management as in
many cases struct space (which replaces
struct Table) is allocated on region
and shouldn't be explicitly freed.
Closes #3235
---
Branch: <a class="moz-txt-link-freetext" href="https://github.com/tarantool/tarantool/tree/sudobobo/gh-3235-repl-Table-w-space" moz-do-not-send="true">https://github.com/tarantool/tarantool/tree/sudobobo/gh-3235-repl-Table-w-space</a>
Issue: <a class="moz-txt-link-freetext" href="https://github.com/tarantool/tarantool/issues/3235" moz-do-not-send="true">https://github.com/tarantool/tarantool/issues/3235</a>
src/box/sql.c | 64 +++-----
src/box/sql.h | 25 +--
src/box/sql/analyze.c | 8 +-
src/box/sql/build.c | 390 +++++++++++++++++++++------------------------
src/box/sql/delete.c | 75 ++++-----
src/box/sql/expr.c | 28 ++--
src/box/sql/fkey.c | 67 ++++----
src/box/sql/insert.c | 97 ++++++-----
src/box/sql/resolve.c | 47 +++---
src/box/sql/select.c | 297 ++++++++++++++++------------------
src/box/sql/sqliteInt.h | 129 +++++++--------
src/box/sql/tarantoolInt.h | 8 +-
src/box/sql/tokenize.c | 10 +-
src/box/sql/treeview.c | 4 +-
src/box/sql/trigger.c | 36 ++---
src/box/sql/update.c | 52 +++---
src/box/sql/where.c | 59 ++++---
src/box/sql/wherecode.c | 8 +-
src/box/sql/whereexpr.c | 13 +-
19 files changed, 635 insertions(+), 782 deletions(-)
diff --git a/src/box/sql.c b/src/box/sql.c
index 387da7b3d..978ad8310 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -972,7 +972,7 @@ cursor_advance(BtCursor *pCur, int *pRes)
*/
char *
-sql_encode_table(struct region *region, struct Table *table, uint32_t *size)
+sql_encode_table(struct region *region, struct space *space, uint32_t *size)
{
size_t used = region_used(region);
struct mpstream stream;
@@ -980,7 +980,7 @@ sql_encode_table(struct region *region, struct Table *table, uint32_t *size)
mpstream_init(&stream, region, region_reserve_cb, region_alloc_cb,
set_encode_error, &is_error);
- const struct space_def *def = table->def;
+ const struct space_def *def = space->def;
assert(def != NULL);
uint32_t field_count = def->field_count;
mpstream_encode_array(&stream, field_count);
@@ -1033,7 +1033,7 @@ sql_encode_table(struct region *region, struct Table *table, uint32_t *size)
}
char *
-sql_encode_table_opts(struct region *region, struct Table *table,
+sql_encode_table_opts(struct region *region, struct space *space,
const char *sql, uint32_t *size)
{
size_t used = region_used(region);
@@ -1043,8 +1043,8 @@ sql_encode_table_opts(struct region *region, struct Table *table,
set_encode_error, &is_error);
int checks_cnt = 0;
struct ExprList_item *a;
- bool is_view = table->def->opts.is_view;
- struct ExprList *checks = table->def->opts.checks;
+ bool is_view = space->def->opts.is_view;
+ struct ExprList *checks = space->def->opts.checks;
if (checks != NULL) {
checks_cnt = checks->nExpr;
a = checks->a;
@@ -1258,49 +1258,26 @@ sql_ephemeral_space_def_new(struct Parse *parser, const char *name)
return def;
}
-Table *
-sql_ephemeral_table_new(Parse *parser, const char *name)
+struct space *
+sql_ephemeral_space_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->space = (struct space *) region_alloc(&parser->region,
- sizeof(struct space));
- if (table->space == NULL) {
+ struct space *space =
+ (struct space *) region_alloc(&parser->region,
+ sizeof(struct space));
+ if (space == NULL) {
diag_set(OutOfMemory, sizeof(struct space), "region", "space");
parser->rc = SQL_TARANTOOL_ERROR;
parser->nErr++;
- sqlite3DbFree(db, table);
return NULL;
}
- memset(table->space, 0, sizeof(struct space));
- table->def = def;
- return table;
-}
-int
-sql_table_def_rebuild(struct sqlite3 *db, struct Table *pTable)
-{
- struct space_def *old_def = pTable->def;
- struct space_def *new_def = NULL;
- new_def = space_def_new(old_def->id, old_def->uid,
- old_def->field_count, old_def->name,
- strlen(old_def->name), old_def->engine_name,
- strlen(old_def->engine_name), &old_def->opts,
- old_def->fields, old_def->field_count);
- if (new_def == NULL) {
- sqlite3OomFault(db);
- return -1;
+ memset(space, 0, sizeof(struct space));
+ space->def = sql_ephemeral_space_def_new(parser, name);
+ if (space->def == NULL) {
+ return NULL;
}
- pTable->def = new_def;
- pTable->def->opts.is_temporary = false;
- return 0;
+
+ return space;
}
int
@@ -1357,11 +1334,10 @@ sql_checks_resolve_space_def_reference(ExprList *expr_list,
sql_parser_create(&parser, sql_get());
parser.parse_only = true;
- Table dummy_table;
- memset(&dummy_table, 0, sizeof(dummy_table));
- dummy_table.def = def;
+ struct space dummy_space;
+ dummy_space.def = def;
- sql_resolve_self_reference(&parser, &dummy_table, NC_IsCheck, NULL,
+ sql_resolve_self_reference(&parser, &dummy_space, NC_IsCheck, NULL,
expr_list);
int rc = 0;
if (parser.rc != SQLITE_OK) {
diff --git a/src/box/sql.h b/src/box/sql.h
index 028a15245..0d9ecd0ce 100644
--- a/src/box/sql.h
+++ b/src/box/sql.h
@@ -225,36 +225,25 @@ void
sql_expr_delete(struct sqlite3 *db, struct Expr *expr, bool extern_alloc);
/**
- * Create and initialize a new ephemeral SQL Table object.
+ * Create and initialize a new ephemeral space object.
* @param parser SQL Parser object.
- * @param name Table to create name.
+ * @param name Space 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);
+struct space *
+sql_ephemeral_space_new(struct Parse *parser, const char *name);
/**
* Create and initialize a new ephemeral space_def object.
* @param parser SQL Parser object.
- * @param name Table to create name.
+ * @param name Space 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.
- * @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);
-
/**
* Duplicate Expr list.
* The flags parameter contains a combination of the EXPRDUP_XXX
@@ -301,13 +290,13 @@ sql_expr_list_append(struct sqlite3 *db, struct ExprList *expr_list,
* the column number. Any errors cause an error message to be set
* in parser.
* @param parser Parsing context.
- * @param table The table being referenced.
+ * @param space The space being referenced.
* @param type NC_IsCheck or NC_IdxExpr.
* @param expr Expression to resolve. May be NULL.
* @param expr_list Expression list to resolve. May be NUL.
*/
void
-sql_resolve_self_reference(struct Parse *parser, struct Table *table, int type,
+sql_resolve_self_reference(struct Parse *parser, struct space *space, int type,
struct Expr *expr, struct ExprList *expr_list);
/**
diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c
index 51c63fa7a..1f800bda7 100644
--- a/src/box/sql/analyze.c
+++ b/src/box/sql/analyze.c
@@ -1588,11 +1588,11 @@ const log_est_t default_tuple_est[] = {DEFAULT_TUPLE_LOG_COUNT,
33, 32, 30, 28, 26, 23};
LogEst
-sql_space_tuple_log_count(struct Table *tab)
+sql_space_tuple_log_count(struct space *space)
{
- struct space *space = space_by_id(tab->def->id);
- if (space == NULL)
- return tab->tuple_log_count;
+ if (space == NULL || space->index_map == NULL)
+ return 0;
+
struct index *pk = space_index(space, 0);
assert(sqlite3LogEst(DEFAULT_TUPLE_COUNT) == DEFAULT_TUPLE_LOG_COUNT);
/* If space represents VIEW, return default number. */
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 49b90b5d0..cae0b3f6e 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -234,64 +234,31 @@ sql_space_column_is_in_pk(struct space *space, uint32_t column)
/**
* Remove the memory data structures associated with the given
- * Table.
+ * space. The only case when some parts of space must be
+ * deleted explicitly is when it comes from building
+ * routine (i.e. it was born during CREATE TABLE
+ * processing). In this case only index defs and check
+ * expressions are allocated using malloc; the rest - on region.
+ * This case is identified by 'is_temporary' flag == TRUE.
*
* @param db Database handler.
- * @param tab Table to be deleted.
+ * @param space Space to be deleted.
*/
-static void
-table_delete(struct sqlite3 *db, struct Table *tab)
-{
- /*
- * There are three possible cases:
- * 1. Table comes from building routine (i.e. it
- * was born during CREATE TABLE processing).
- * In this case only index defs and check expressions
- * are allocated using malloc; the rest - on region.
- * 'is_temporary' flag is set to TRUE.
- * 2. Table comes from query processing (e.g.
- * SELECT, INSERT etc). Hence, table is only
- * wrapper around space and its def from real
- * space cache. As a result we don't need to free
- * anything except for table itself. For such tables
- * flag 'is_temporary' set to FALSE and id != 0.
- * 3. Table is 'ephemeral' and represents metadata for
- * flattened subquery or materialized view. It is quite
- * similar to tables from p.1, but their space_defs
- * are rebuilt (see selectExpander() function) using
- * malloc. Such rebuild is required since subquery
- * flattening may occur in trigger's body, which in
- * turn handled in a separate parsing context.
- * At the end of trigger's parsing, those tables may
- * not be deleted, but added to the zombie list of
- * top-level parsing context. Each parsing context
- * features individual region allocator. Hence, when
- * top-level parsing context starts to release zombie
- * tables, they have already corrupted memory layout.
- * Reproducer for this case can be found in
- * tkt-7bbfb7d442 test. For such tables flag
- * 'is_temporary' set to false and id == 0.
- */
- if (tab->def->opts.is_temporary) {
- for (uint32_t i = 0; i < tab->space->index_count; ++i)
- index_def_delete(tab->space->index[i]->def);
- /* Do not delete table->def allocated on region. */
- sql_expr_list_delete(db, tab->def->opts.checks);
- } else if (tab->def->id == 0) {
- space_def_delete(tab->def);
- }
- sqlite3DbFree(db, tab);
-}
-
void
-sqlite3DeleteTable(sqlite3 * db, Table * pTable)
+sql_space_delete(struct sqlite3 *db, struct space *space)
{
- /* Do not delete the table until the reference count reaches zero. */
- if (!pTable)
- return;
- if (((!db || db->pnBytesFreed == 0) && (--pTable->nTabRef) > 0))
+ if (!space || !db || db->pnBytesFreed == 0)
return;
- table_delete(db, pTable);
+
+ if (space->def->opts.is_temporary) {
+ for (uint32_t i = 0; i < space->index_count; ++i)
+ index_def_delete(space->index[i]->def);
+ /**
+ * Do not delete space and space->def allocated
+ * on region.
+ */
+ sql_expr_list_delete(db, space->def->opts.checks);
+ }
}
/*
@@ -343,15 +310,15 @@ sqlite3CheckIdentifierName(Parse *pParse, char *zName)
}
struct index *
-sql_table_primary_key(const struct Table *tab)
+sql_table_primary_key(const struct space *space)
{
- if (tab->space->index_count == 0 || tab->space->index[0]->def->iid != 0)
+ if (space->index_count == 0 || space->index[0]->def->iid != 0)
return NULL;
- return tab->space->index[0];
+ return space->index[0];
}
/**
- * Create and initialize a new SQL Table object.
+ * Create and initialize a new SQL space object.
* All memory except table object itself is allocated on region.
* @param parser SQL Parser object.
* @param name Table to create name.
@@ -359,18 +326,17 @@ sql_table_primary_key(const struct Table *tab)
* changed.
* @retval not NULL on success.
*/
-static Table *
+static struct space *
sql_table_new(Parse *parser, char *name)
{
- struct Table *table = sql_ephemeral_table_new(parser, name);
- if (table == NULL)
+ struct space *space = sql_ephemeral_space_new(parser, name);
+ if (space == NULL)
return NULL;
- strcpy(table->def->engine_name,
+ strcpy(space->def->engine_name,
sql_storage_engine_strs[current_session()->sql_default_engine]);
- table->nTabRef = 1;
- return table;
+ return space;
}
/*
@@ -396,7 +362,6 @@ sql_table_new(Parse *parser, char *name)
void
sqlite3StartTable(Parse *pParse, Token *pName, int noErr)
{
- Table *pTable;
char *zName = 0; /* The name of the new table */
sqlite3 *db = pParse->db;
struct Vdbe *v = sqlite3GetVdbe(pParse);
@@ -423,12 +388,12 @@ sqlite3StartTable(Parse *pParse, Token *pName, int noErr)
goto cleanup;
}
- pTable = sql_table_new(pParse, zName);
- if (pTable == NULL)
+ struct space *new_space = sql_table_new(pParse, zName);
+ if (new_space == NULL)
goto cleanup;
- assert(pParse->pNewTable == 0);
- pParse->pNewTable = pTable;
+ assert(pParse->new_space == 0);
+ pParse->new_space = new_space;
if (!db->init.busy && (v = sqlite3GetVdbe(pParse)) != 0)
sql_set_multi_write(pParse, true);
@@ -443,45 +408,45 @@ sqlite3StartTable(Parse *pParse, Token *pName, int noErr)
* Useful in cases when initial field_count is unknown.
* Allocated memory should by manually released.
* @param parser SQL Parser object.
- * @param table SQL Table object.
+ * @param space_def Space definition.
* @param id column identifier.
* @retval not NULL on success.
* @retval NULL on out of memory.
*/
static struct field_def *
-sql_field_retrieve(Parse *parser, Table *table, uint32_t id)
+sql_field_retrieve(Parse *parser, struct space_def *space_def, uint32_t id)
{
struct field_def *field;
- assert(table->def != NULL);
+ assert(space_def != NULL);
assert(id < SQLITE_MAX_COLUMN);
- if (id >= table->def->exact_field_count) {
- uint32_t columns_new = table->def->exact_field_count;
+ if (id >= space_def->exact_field_count) {
+ uint32_t columns_new = space_def->exact_field_count;
columns_new = (columns_new > 0) ? 2 * columns_new : 1;
struct region *region = &parser->region;
field = region_alloc(region, columns_new *
- sizeof(table->def->fields[0]));
+ sizeof(space_def->fields[0]));
if (field == NULL) {
diag_set(OutOfMemory, columns_new *
- sizeof(table->def->fields[0]),
- "region_alloc", "sql_field_retrieve");
+ sizeof(space_def->fields[0]),
+ "region_alloc", "sql_field_retrieve");
parser->rc = SQL_TARANTOOL_ERROR;
parser->nErr++;
return NULL;
}
- memcpy(field, table->def->fields,
- sizeof(*field) * table->def->exact_field_count);
+ memcpy(field, space_def->fields,
+ sizeof(*field) * space_def->exact_field_count);
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_new;
+ space_def->fields = field;
+ space_def->exact_field_count = columns_new;
}
- field = &table->def->fields[id];
+ field = &space_def->fields[id];
return field;
}
@@ -513,27 +478,28 @@ void
sqlite3AddColumn(Parse * pParse, Token * pName, struct type_def *type_def)
{
assert(type_def != NULL);
- Table *p;
int i;
char *z;
sqlite3 *db = pParse->db;
- if ((p = pParse->pNewTable) == 0)
+ if ((pParse->new_space) == 0)
return;
+ struct space *space = pParse->new_space;
+
#if SQLITE_MAX_COLUMN
- if ((int)p->def->field_count + 1 > db->aLimit[SQLITE_LIMIT_COLUMN]) {
+ if ((int)space->def->field_count + 1 > db->aLimit[SQLITE_LIMIT_COLUMN]) {
sqlite3ErrorMsg(pParse, "too many columns on %s",
- p->def->name);
+ space->def->name);
return;
}
#endif
- /*
+ /**
* As sql_field_retrieve will allocate memory on region
- * ensure that p->def is also temporal and would be rebuilded or
+ * ensure that p->space->def is also temporal and would be rebuilded or
* dropped.
*/
- assert(p->def->opts.is_temporary);
- if (sql_field_retrieve(pParse, p,
- (uint32_t) p->def->field_count) == NULL)
+ assert(space->def->opts.is_temporary);
+ if (sql_field_retrieve(pParse, space->def,
+ (uint32_t) space->def->field_count) == NULL)
return;
struct region *region = &pParse->region;
z = region_alloc(region, pName->n + 1);
@@ -547,13 +513,14 @@ sqlite3AddColumn(Parse * pParse, Token * pName, struct type_def *type_def)
memcpy(z, pName->z, pName->n);
z[pName->n] = 0;
sqlite3NormalizeName(z);
- for (i = 0; i < (int)p->def->field_count; i++) {
- if (strcmp(z, p->def->fields[i].name) == 0) {
+ for (i = 0; i < (int)space->def->field_count; i++) {
+ if (strcmp(z, space->def->fields[i].name) == 0) {
sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
return;
}
}
- struct field_def *column_def = &p->def->fields[p->def->field_count];
+ struct field_def *column_def =
+ &space->def->fields[space->def->field_count];
memcpy(column_def, &field_def_default, sizeof(field_def_default));
column_def->name = z;
/*
@@ -565,7 +532,7 @@ sqlite3AddColumn(Parse * pParse, Token * pName, struct type_def *type_def)
column_def->is_nullable = true;
column_def->affinity = type_def->type;
column_def->type = sql_affinity_to_field_type(column_def->affinity);
- p->def->field_count++;
+ space->def->field_count++;
pParse->constraintName.n = 0;
}
@@ -573,17 +540,18 @@ void
sql_column_add_nullable_action(struct Parse *parser,
enum on_conflict_action nullable_action)
{
- struct Table *p = parser->pNewTable;
- if (p == NULL || NEVER(p->def->field_count < 1))
+ if (parser->new_space == NULL ||
+ NEVER(parser->new_space->def->field_count < 1))
return;
- struct field_def *field = &p->def->fields[p->def->field_count - 1];
+ struct space *space = parser->new_space;
+ struct field_def *field = &space->def->fields[space->def->field_count - 1];
if (field->nullable_action != ON_CONFLICT_ACTION_DEFAULT &&
nullable_action != field->nullable_action) {
/* Prevent defining nullable_action many times. */
const char *err_msg =
tt_sprintf("NULL declaration for column '%s' of table "
"'%s' has been already set to '%s'",
- field->name, p->def->name,
+ field->name, space->def->name,
on_conflict_action_strs[field->
nullable_action]);
diag_set(ClientError, ER_SQL, err_msg);
@@ -608,20 +576,20 @@ sql_column_add_nullable_action(struct Parse *parser,
void
sqlite3AddDefaultValue(Parse * pParse, ExprSpan * pSpan)
{
- Table *p;
sqlite3 *db = pParse->db;
- p = pParse->pNewTable;
- assert(p->def->opts.is_temporary);
- if (p != 0) {
+ assert(pParse->new_space->def->opts.is_temporary);
+ if (pParse->new_space != 0) {
+ struct space_def *space_def = pParse->new_space->def;
if (!sqlite3ExprIsConstantOrFunction
(pSpan->pExpr, db->init.busy)) {
sqlite3ErrorMsg(pParse,
"default value of column [%s] is not constant",
- p->def->fields[p->def->field_count - 1].name);
+ space_def->
+ fields[space_def->field_count - 1].name);
} else {
- assert(p->def != NULL);
+ assert(space_def != NULL);
struct field_def *field =
- &p->def->fields[p->def->field_count - 1];
+ &space_def->fields[space_def->field_count - 1];
struct region *region = &pParse->region;
uint32_t default_length = (int)(pSpan->zEnd - pSpan->zStart);
field->default_value = region_alloc(region,
@@ -678,19 +646,19 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
enum sort_order sortOrder
)
{
- Table *pTab = pParse->pNewTable;
int iCol = -1, i;
int nTerm;
- if (pTab == 0)
+ if (pParse->new_space == 0)
goto primary_key_exit;
- if (sql_table_primary_key(pTab) != NULL) {
+ struct space *space = pParse->new_space;
+ if (sql_table_primary_key(space) != NULL) {
sqlite3ErrorMsg(pParse,
"table \"%s\" has more than one primary key",
- pTab->def->name);
+ space->def->name);
goto primary_key_exit;
}
if (pList == 0) {
- iCol = pTab->def->field_count - 1;
+ iCol = space->def->field_count - 1;
nTerm = 1;
} else {
nTerm = pList->nExpr;
@@ -704,7 +672,7 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
goto primary_key_exit;
}
const char *name = pCExpr->u.zToken;
- struct space_def *def = pTab->def;
+ struct space_def *def = space->def;
for (uint32_t idx = 0; idx < def->field_count; idx++) {
if (strcmp(name, def->fields[idx].name) == 0) {
iCol = idx;
@@ -714,14 +682,14 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
}
}
if (nTerm == 1 && iCol != -1 &&
- pTab->def->fields[iCol].type == FIELD_TYPE_INTEGER &&
- sortOrder != SORT_ORDER_DESC) {
+ space->def->fields[iCol].type == FIELD_TYPE_INTEGER &&
+ sortOrder != SORT_ORDER_DESC) {
assert(autoInc == 0 || autoInc == 1);
pParse->is_new_table_autoinc = autoInc;
struct sqlite3 *db = pParse->db;
struct ExprList *list;
struct Token token;
- sqlite3TokenInit(&token, pTab->def->fields[iCol].name);
+ sqlite3TokenInit(&token, space->def->fields[iCol].name);
list = sql_expr_list_append(db, NULL,
sqlite3ExprAlloc(db, TK_ID,
&token, 0));
@@ -743,13 +711,13 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
goto primary_key_exit;
}
- struct index *pk = sql_table_primary_key(pTab);
+ struct index *pk = sql_table_primary_key(space);
assert(pk != NULL);
struct key_def *pk_key_def = pk->def->key_def;
for (uint32_t i = 0; i < pk_key_def->part_count; i++) {
uint32_t idx = pk_key_def->parts[i].fieldno;
- field_def_create_for_pk(pParse, &pTab->def->fields[idx],
- pTab->def->name);
+ field_def_create_for_pk(pParse, &space->def->fields[idx],
+ space->def->name);
}
primary_key_exit:
sql_expr_list_delete(pParse->db, pList);
@@ -760,22 +728,22 @@ void
sql_add_check_constraint(struct Parse *parser, struct ExprSpan *span)
{
struct Expr *expr = span->pExpr;
- struct Table *table = parser->pNewTable;
- if (table != NULL) {
+ if (parser->new_space != NULL) {
+ struct space *space = parser->new_space;
expr->u.zToken =
sqlite3DbStrNDup(parser->db, (char *)span->zStart,
(int)(span->zEnd - span->zStart));
if (expr->u.zToken == NULL)
goto release_expr;
- table->def->opts.checks =
+ space->def->opts.checks =
sql_expr_list_append(parser->db,
- table->def->opts.checks, expr);
- if (table->def->opts.checks == NULL) {
+ space->def->opts.checks, expr);
+ if (space->def->opts.checks == NULL) {
sqlite3DbFree(parser->db, expr->u.zToken);
goto release_expr;
}
if (parser->constraintName.n) {
- sqlite3ExprListSetName(parser, table->def->opts.checks,
+ sqlite3ExprListSetName(parser, space->def->opts.checks,
&parser->constraintName, 1);
}
} else {
@@ -791,26 +759,26 @@ release_expr:
void
sqlite3AddCollateType(Parse * pParse, Token * pToken)
{
- Table *p = pParse->pNewTable;
- if (p == NULL)
+ if (pParse->new_space == NULL)
return;
- uint32_t i = p->def->field_count - 1;
+ struct space *space= pParse->new_space;
+ uint32_t i = space->def->field_count - 1;
sqlite3 *db = pParse->db;
char *zColl = sqlite3NameFromToken(db, pToken);
if (!zColl)
return;
- uint32_t *coll_id = &p->def->fields[i].coll_id;
+ uint32_t *coll_id = &space->def->fields[i].coll_id;
if (sql_get_coll_seq(pParse, zColl, coll_id) != NULL) {
/* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
* then an index may have been created on this column before the
* collation type was added. Correct this if it is the case.
*/
- for (uint32_t i = 0; i < p->space->index_count; ++i) {
- struct index *idx = p->space->index[i];
+ for (uint32_t i = 0; i < space->index_count; ++i) {
+ struct index *idx = space->index[i];
assert(idx->def->key_def->part_count == 1);
if (idx->def->key_def->parts[0].fieldno == i) {
coll_id = &idx->def->key_def->parts[0].coll_id;
- (void)sql_column_collation(p->def, i, coll_id);
+ (void)sql_column_collation(space->def, i, coll_id);
}
}
}
@@ -924,7 +892,7 @@ vdbe_emit_create_index(struct Parse *parse, struct space_def *def,
memcpy(raw, index_parts, index_parts_sz);
index_parts = raw;
- if (parse->pNewTable != NULL) {
+ if (parse->new_space != NULL) {
sqlite3VdbeAddOp2(v, OP_SCopy, space_id_reg, entry_reg);
sqlite3VdbeAddOp2(v, OP_Integer, idx_def->iid, entry_reg + 1);
} else {
@@ -964,18 +932,18 @@ error:
static void
createSpace(Parse * pParse, int iSpaceId, char *zStmt)
{
- struct Table *table = pParse->pNewTable;
Vdbe *v = sqlite3GetVdbe(pParse);
int iFirstCol = ++pParse->nMem;
int iRecord = (pParse->nMem += 7);
struct region *region = &pParse->region;
uint32_t table_opts_stmt_sz = 0;
- char *table_opts_stmt = sql_encode_table_opts(region, table, zStmt,
+ struct space *space = pParse->new_space;
+ char *table_opts_stmt = sql_encode_table_opts(region, space, zStmt,
&table_opts_stmt_sz);
if (table_opts_stmt == NULL)
goto error;
uint32_t table_stmt_sz = 0;
- char *table_stmt = sql_encode_table(region, table, &table_stmt_sz);
+ char *table_stmt = sql_encode_table(region, space, &table_stmt_sz);
if (table_stmt == NULL)
goto error;
char *raw = sqlite3DbMallocRaw(pParse->db,
@@ -993,12 +961,12 @@ 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, table->def->name),
+ sqlite3DbStrDup(pParse->db, space->def->name),
P4_DYNAMIC);
sqlite3VdbeAddOp4(v, OP_String8, 0, iFirstCol + 3 /* engine */ , 0,
- sqlite3DbStrDup(pParse->db, table->def->engine_name),
+ sqlite3DbStrDup(pParse->db, space->def->engine_name),
P4_DYNAMIC);
- sqlite3VdbeAddOp2(v, OP_Integer, table->def->field_count,
+ sqlite3VdbeAddOp2(v, OP_Integer, space->def->field_count,
iFirstCol + 4 /* field_count */ );
sqlite3VdbeAddOp4(v, OP_Blob, table_opts_stmt_sz, iFirstCol + 5,
SQL_SUBTYPE_MSGPACK, table_opts_stmt, P4_DYNAMIC);
@@ -1114,14 +1082,14 @@ vdbe_emit_fkey_create(struct Parse *parse_context, const struct fkey_def *fk)
* of <CREATE TABLE ...> statement, we don't have child
* id, but we know register where it will be stored.
*/
- if (parse_context->pNewTable != NULL) {
+ if (parse_context->new_space != NULL) {
sqlite3VdbeAddOp2(vdbe, OP_SCopy, fk->child_id,
constr_tuple_reg + 1);
} else {
sqlite3VdbeAddOp2(vdbe, OP_Integer, fk->child_id,
constr_tuple_reg + 1);
}
- if (parse_context->pNewTable != NULL && fkey_is_self_referenced(fk)) {
+ if (parse_context->new_space != NULL && fkey_is_self_referenced(fk)) {
sqlite3VdbeAddOp2(vdbe, OP_SCopy, fk->parent_id,
constr_tuple_reg + 2);
} else {
@@ -1184,7 +1152,7 @@ vdbe_emit_fkey_create(struct Parse *parse_context, const struct fkey_def *fk)
constr_tuple_reg + 9);
sqlite3VdbeAddOp3(vdbe, OP_SInsert, BOX_FK_CONSTRAINT_ID, 0,
constr_tuple_reg + 9);
- if (parse_context->pNewTable == NULL)
+ if (parse_context->new_space == NULL)
sqlite3VdbeChangeP5(vdbe, OPFLAG_NCHANGE);
save_record(parse_context, BOX_FK_CONSTRAINT_ID, constr_tuple_reg, 2,
vdbe->nOp - 1);
@@ -1229,7 +1197,7 @@ resolve_link(struct Parse *parse_context, const struct space_def *def,
* This routine is called to report the final ")" that terminates
* a CREATE TABLE statement.
*
- * The table structure that other action routines have been building
+ * The space structure that other action routines have been building
* is added to the internal hash tables, assuming no errors have
* occurred.
*
@@ -1238,12 +1206,12 @@ resolve_link(struct Parse *parse_context, const struct space_def *def,
* space and all necessary Tarantool indexes is emitted
* 2. When db->init.busy == 1. This means that byte code for creation
* of new table is executing right now, and it's time to add new entry
- * for the table into SQL memory represenation
+ * for the table into SQL memory representation
*
* If the pSelect argument is not NULL, it means that this routine
- * was called to create a table generated from a
+ * was called to create a space generated from a
* "CREATE TABLE ... AS SELECT ..." statement. The column names of
- * the new table will match the result set of the SELECT.
+ * the new space will match the result set of the SELECT.
*/
void
sqlite3EndTable(Parse * pParse, /* Parse context */
@@ -1251,24 +1219,24 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
Select * pSelect /* Select from a "CREATE ... AS SELECT" */
)
{
- Table *p; /* The new table */
sqlite3 *db = pParse->db; /* The database connection */
if (pEnd == 0 && pSelect == 0) {
return;
}
assert(!db->mallocFailed);
- p = pParse->pNewTable;
- if (p == 0)
+ if (pParse->new_space == 0)
return;
+ struct space *new_space = pParse->new_space;
+
assert(!db->init.busy);
- if (!p->def->opts.is_view) {
- if (sql_table_primary_key(p) == NULL) {
+ if (!new_space->def->opts.is_view) {
+ if (sql_table_primary_key(new_space) == NULL) {
sqlite3ErrorMsg(pParse,
"PRIMARY KEY missing on table %s",
- p->def->name);
+ new_space->def->name);
goto cleanup;
}
}
@@ -1278,8 +1246,8 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
* Set defaults for columns having no separate
* NULL/NOT NULL specifiers.
*/
- struct field_def *field = p->def->fields;
- for (uint32_t i = 0; i < p->def->field_count; ++i, ++field) {
+ struct field_def *field = new_space->def->fields;
+ for (uint32_t i = 0; i < new_space->def->field_count; ++i, ++field) {
if (field->nullable_action == ON_CONFLICT_ACTION_DEFAULT) {
/* Set default nullability NONE. */
field->nullable_action = ON_CONFLICT_ACTION_NONE;
@@ -1295,7 +1263,7 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
/* Text of the CREATE VIEW statement. */
char *stmt = NULL;
- if (p->def->opts.is_view) {
+ if (new_space->def->opts.is_view) {
struct Token *pEnd2 = &pParse->sLastToken;
int n = pEnd2->z - pParse->sNameToken.z;
if (pEnd2->z[0] != ';')
@@ -1306,10 +1274,10 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
int reg_space_id = getNewSpaceId(pParse);
createSpace(pParse, reg_space_id, stmt);
/* Indexes aren't required for VIEW's.. */
- if (!p->def->opts.is_view) {
- for (uint32_t i = 0; i < p->space->index_count; ++i) {
- struct index *idx = p->space->index[i];
- vdbe_emit_create_index(pParse, p->def, idx->def,
+ if (!new_space->def->opts.is_view) {
+ for (uint32_t i = 0; i < new_space->index_count; ++i) {
+ struct index *idx = new_space->index[i];
+ vdbe_emit_create_index(pParse, new_space->def, idx->def,
reg_space_id, idx->def->iid);
}
}
@@ -1325,7 +1293,7 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
sqlite3VdbeAddOp2(v, OP_NextSequenceId, 0, reg_seq_id);
int reg_seq_record =
emitNewSysSequenceRecord(pParse, reg_seq_id,
- p->def->name);
+ new_space->def->name);
sqlite3VdbeAddOp3(v, OP_SInsert, BOX_SEQUENCE_ID, 0,
reg_seq_record);
save_record(pParse, BOX_SEQUENCE_ID, reg_seq_record + 1, 1,
@@ -1346,7 +1314,7 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
if (fk_parse->selfref_cols != NULL) {
struct ExprList *cols = fk_parse->selfref_cols;
for (uint32_t i = 0; i < fk->field_count; ++i) {
- if (resolve_link(pParse, p->def,
+ if (resolve_link(pParse, new_space->def,
cols->a[i].zName,
&fk->links[i].parent_field,
fk->name) != 0)
@@ -1354,7 +1322,7 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
}
fk->parent_id = reg_space_id;
} else if (fk_parse->is_self_referenced) {
- struct index *pk = sql_table_primary_key(p);
+ struct index *pk = sql_table_primary_key(new_space);
if (pk->def->key_def->part_count != fk->field_count) {
diag_set(ClientError, ER_CREATE_FK_CONSTRAINT,
fk->name, "number of columns in "\
@@ -1375,8 +1343,8 @@ sqlite3EndTable(Parse * pParse, /* Parse context */
vdbe_emit_fkey_create(pParse, fk);
}
cleanup:
- sql_expr_list_delete(db, p->def->opts.checks);
- p->def->opts.checks = NULL;
+ sql_expr_list_delete(db, new_space->def->opts.checks);
+ new_space->def->opts.checks = NULL;
}
void
@@ -1385,38 +1353,39 @@ sql_create_view(struct Parse *parse_context, struct Token *begin,
struct Select *select, bool if_exists)
{
struct sqlite3 *db = parse_context->db;
- struct Table *sel_tab = NULL;
if (parse_context->nVar > 0) {
sqlite3ErrorMsg(parse_context,
"parameters are not allowed in views");
goto create_view_fail;
}
sqlite3StartTable(parse_context, name, if_exists);
- struct Table *p = parse_context->pNewTable;
- if (p == NULL || parse_context->nErr != 0)
+ if (parse_context->new_space == NULL || parse_context->nErr != 0)
goto create_view_fail;
- sel_tab = sqlite3ResultSetOfSelect(parse_context, select);
- if (sel_tab == NULL)
+ struct space *space = parse_context->new_space;
+
+ struct space *select_res_space =
+ sqlite3ResultSetOfSelect(parse_context, select);
+ if (select_res_space == NULL)
goto create_view_fail;
if (aliases != NULL) {
- if ((int)sel_tab->def->field_count != aliases->nExpr) {
+ if ((int)select_res_space->def->field_count != aliases->nExpr) {
sqlite3ErrorMsg(parse_context, "expected %d columns "\
"for '%s' but got %d", aliases->nExpr,
- p->def->name,
- sel_tab->def->field_count);
+ space->def->name,
+ select_res_space->def->field_count);
goto create_view_fail;
}
- sqlite3ColumnsFromExprList(parse_context, aliases, p);
- sqlite3SelectAddColumnTypeAndCollation(parse_context, p,
+ sqlite3ColumnsFromExprList(parse_context, aliases, space->def);
+ sqlite3SelectAddColumnTypeAndCollation(parse_context, space,
select);
} else {
- assert(sel_tab->def->opts.is_temporary);
- p->def->fields = sel_tab->def->fields;
- p->def->field_count = sel_tab->def->field_count;
- sel_tab->def->fields = NULL;
- sel_tab->def->field_count = 0;
+ assert(select_res_space->def->opts.is_temporary);
+ space->def->fields = select_res_space->def->fields;
+ space->def->field_count = select_res_space->def->field_count;
+ select_res_space->def->fields = NULL;
+ select_res_space->def->field_count = 0;
}
- p->def->opts.is_view = true;
+ space->def->opts.is_view = true;
/*
* Locate the end of the CREATE VIEW statement.
* Make sEnd point to the end.
@@ -1433,8 +1402,8 @@ sql_create_view(struct Parse *parse_context, struct Token *begin,
n--;
end.z = &z[n - 1];
end.n = 1;
- p->def->opts.sql = strndup(begin->z, n);
- if (p->def->opts.sql == NULL) {
+ space->def->opts.sql = strndup(begin->z, n);
+ if (space->def->opts.sql == NULL) {
diag_set(OutOfMemory, n, "strndup", "opts.sql");
parse_context->rc = SQL_TARANTOOL_ERROR;
parse_context->nErr++;
@@ -1445,7 +1414,6 @@ sql_create_view(struct Parse *parse_context, struct Token *begin,
sqlite3EndTable(parse_context, &end, 0);
create_view_fail:
- sqlite3DbFree(db, sel_tab);
sql_expr_list_delete(db, aliases);
sql_select_delete(db, select);
return;
@@ -1820,13 +1788,15 @@ sql_create_foreign_key(struct Parse *parse_context, struct SrcList *child,
char *parent_name = NULL;
char *constraint_name = NULL;
bool is_self_referenced = false;
- /*
- * Table under construction during CREATE TABLE
+ /**
+ * Space under construction during CREATE TABLE
* processing. NULL for ALTER TABLE statement handling.
*/
- struct Table *new_tab = parse_context->pNewTable;
- /* Whether we are processing ALTER TABLE or CREATE TABLE. */
- bool is_alter = new_tab == NULL;
+ bool is_alter = (parse_context->new_space == NULL);
+ struct space *space;
+ if (!is_alter)
+ space = parse_context->new_space;
+
uint32_t child_cols_count;
if (child_cols == NULL) {
assert(!is_alter);
@@ -1864,7 +1834,7 @@ sql_create_foreign_key(struct Parse *parse_context, struct SrcList *child,
* also child) table will definitely exist.
*/
is_self_referenced = !is_alter &&
- strcmp(parent_name, new_tab->def->name) == 0;
+ strcmp(parent_name, space->def->name) == 0;
struct space *parent_space = space_by_name(parent_name);
if (parent_space == NULL) {
if (is_self_referenced) {
@@ -1889,7 +1859,7 @@ sql_create_foreign_key(struct Parse *parse_context, struct SrcList *child,
constraint_name =
sqlite3MPrintf(db, "FK_CONSTRAINT_%d_%s",
++parse_context->fkey_count,
- new_tab->def->name);
+ space->def->name);
} else {
struct Token *cnstr_nm = &parse_context->constraintName;
constraint_name = sqlite3NameFromToken(db, cnstr_nm);
@@ -1959,10 +1929,10 @@ sql_create_foreign_key(struct Parse *parse_context, struct SrcList *child,
* immediately.
*/
fk->links[0].child_field =
- new_tab->def->field_count - 1;
+ space->def->field_count - 1;
break;
}
- if (resolve_link(parse_context, new_tab->def,
+ if (resolve_link(parse_context, space->def,
child_cols->a[i].zName,
&fk->links[i].child_field,
constraint_name) != 0)
@@ -2148,12 +2118,12 @@ index_fill_def(struct Parse *parse, struct index *index,
"region", "key parts");
goto tnt_error;
}
- struct Table tmp_tab;
- tmp_tab.def = space_def;
- tmp_tab.nTabRef = 2;
+ struct space tmp_space;
+ tmp_space.def = space_def;
+ assert(tmp_space.def != NULL);
for (int i = 0; i < expr_list->nExpr; i++) {
struct Expr *expr = expr_list->a[i].pExpr;
- sql_resolve_self_reference(parse, &tmp_tab, NC_IdxExpr,
+ sql_resolve_self_reference(parse, &tmp_space, NC_IdxExpr,
expr, 0);
if (parse->nErr > 0)
goto cleanup;
@@ -2249,7 +2219,6 @@ sql_create_index(struct Parse *parse, struct Token *token,
* Return early if not found.
*/
struct space *space = NULL;
- struct space_def *def = NULL;
if (tbl_name != NULL) {
assert(token != NULL && token->z != NULL);
const char *name = tbl_name->a[0].zName;
@@ -2262,17 +2231,16 @@ sql_create_index(struct Parse *parse, struct Token *token,
}
goto exit_create_index;
}
- def = space->def;
} else {
- if (parse->pNewTable == NULL)
+ if (parse->new_space == NULL)
goto exit_create_index;
assert(token == NULL);
assert(start == NULL);
- space = parse->pNewTable->space;
- def = parse->pNewTable->def;
+ space = parse->new_space;
+ space->def = parse->new_space->def;
}
- if (def->opts.is_view) {
+ if (space->def->opts.is_view) {
sqlite3ErrorMsg(parse, "views can not be indexed");
goto exit_create_index;
}
@@ -2305,7 +2273,7 @@ sql_create_index(struct Parse *parse, struct Token *token,
if (!if_not_exist) {
sqlite3ErrorMsg(parse,
"index %s.%s already exists",
- def->name, name);
+ space->def->name, name);
}
goto exit_create_index;
}
@@ -2337,7 +2305,7 @@ sql_create_index(struct Parse *parse, struct Token *token,
uint32_t idx_count = space->index_count;
if (constraint_name == NULL ||
strcmp(constraint_name, "") == 0) {
- name = sqlite3MPrintf(db, prefix, def->name,
+ name = sqlite3MPrintf(db, prefix, space->def->name,
idx_count + 1);
} else {
name = sqlite3MPrintf(db, prefix,
@@ -2350,7 +2318,7 @@ sql_create_index(struct Parse *parse, struct Token *token,
goto exit_create_index;
if (tbl_name != NULL && space_is_system(space)) {
- diag_set(ClientError, ER_MODIFY_INDEX, name, def->name,
+ diag_set(ClientError, ER_MODIFY_INDEX, name, space->def->name,
"can't create index on system space");
parse->nErr++;
parse->rc = SQL_TARANTOOL_ERROR;
@@ -2365,8 +2333,8 @@ sql_create_index(struct Parse *parse, struct Token *token,
*/
if (col_list == NULL) {
struct Token prev_col;
- uint32_t last_field = def->field_count - 1;
- sqlite3TokenInit(&prev_col, def->fields[last_field].name);
+ uint32_t last_field = space->def->field_count - 1;
+ sqlite3TokenInit(&prev_col, space->def->fields[last_field].name);
col_list = sql_expr_list_append(parse->db, NULL,
sqlite3ExprAlloc(db, TK_ID,
&prev_col, 0));
@@ -2398,7 +2366,7 @@ sql_create_index(struct Parse *parse, struct Token *token,
iid = space->index_id_max + 1;
else
iid = 0;
- if (index_fill_def(parse, index, def, iid, name, strlen(name),
+ if (index_fill_def(parse, index, space->def, iid, name, strlen(name),
col_list, idx_type) != 0)
goto exit_create_index;
/*
@@ -2422,7 +2390,7 @@ sql_create_index(struct Parse *parse, struct Token *token,
}
index->def->key_def->part_count = new_part_count;
- if (!index_def_is_valid(index->def, def->name))
+ if (!index_def_is_valid(index->def, space->def->name))
goto exit_create_index;
/*
@@ -2454,7 +2422,7 @@ sql_create_index(struct Parse *parse, struct Token *token,
* constraint, but has different onError (behavior on
* constraint violation), then an error is raised.
*/
- if (parse->pNewTable != NULL) {
+ if (parse->new_space != NULL) {
for (uint32_t i = 0; i < space->index_count; ++i) {
struct index *existing_idx = space->index[i];
uint32_t iid = existing_idx->def->iid;
@@ -2523,10 +2491,10 @@ sql_create_index(struct Parse *parse, struct Token *token,
sqlite3VdbeChangeP5(vdbe, OPFLAG_SEEKEQ);
assert(start != NULL);
- int index_id = getNewIid(parse, def->id, cursor);
+ int index_id = getNewIid(parse, space->def->id, cursor);
sqlite3VdbeAddOp1(vdbe, OP_Close, cursor);
- vdbe_emit_create_index(parse, def, index->def,
- def->id, index_id);
+ vdbe_emit_create_index(parse, space->def, index->def,
+ space->def->id, index_id);
sqlite3VdbeChangeP5(vdbe, OPFLAG_NCHANGE);
sqlite3VdbeAddOp0(vdbe, OP_Expire);
}
@@ -2883,7 +2851,7 @@ sqlite3SrcListDelete(sqlite3 * db, SrcList * pList)
sqlite3DbFree(db, pItem->u1.zIndexedBy);
if (pItem->fg.isTabFunc)
sql_expr_list_delete(db, pItem->u1.pFuncArg);
- sqlite3DeleteTable(db, pItem->pTab);
+ sql_space_delete(db, pItem->space);
sql_select_delete(db, pItem->pSelect);
sql_expr_delete(db, pItem->pOn, false);
sqlite3IdListDelete(db, pItem->pUsing);
diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
index f9c42fdec..b687ff8f4 100644
--- a/src/box/sql/delete.c
+++ b/src/box/sql/delete.c
@@ -35,14 +35,14 @@
#include "sqliteInt.h"
#include "tarantoolInt.h"
-struct Table *
-sql_lookup_table(struct Parse *parse, struct SrcList_item *tbl_name)
+struct space *
+sql_lookup_space(struct Parse *parse, struct SrcList_item *space_name)
{
- assert(tbl_name != NULL);
- assert(tbl_name->pTab == NULL);
- struct space *space = space_by_name(tbl_name->zName);
+ assert(space_name != NULL);
+ assert(space_name->space == NULL);
+ struct space *space = space_by_name(space_name->zName);
if (space == NULL) {
- sqlite3ErrorMsg(parse, "no such table: %s", tbl_name->zName);
+ sqlite3ErrorMsg(parse, "no such table: %s", space_name->zName);
return NULL;
}
assert(space != NULL);
@@ -53,16 +53,10 @@ sql_lookup_table(struct Parse *parse, struct SrcList_item *tbl_name)
parse->nErr++;
return NULL;
}
- struct Table *table = sqlite3DbMallocZero(parse->db, sizeof(*table));
- if (table == NULL)
- return NULL;
- table->def = space->def;
- table->space = space;
- table->nTabRef = 1;
- tbl_name->pTab = table;
- if (sqlite3IndexedByLookup(parse, tbl_name) != 0)
- table = NULL;
- return table;
+ space_name->space = space;
+ if (sqlite3IndexedByLookup(parse, space_name) != 0)
+ space = NULL;
+ return space;
}
void
@@ -149,21 +143,20 @@ sql_table_delete_from(struct Parse *parse, struct SrcList *tab_list,
/* True if there are triggers or FKs or subqueries in the
* WHERE clause.
*/
- struct Table *table = sql_lookup_table(parse, tab_list->a);
- if (table == NULL)
+ struct space *space = sql_lookup_space(parse, tab_list->a);
+ if (space == NULL)
goto delete_from_cleanup;
- assert(table->space != NULL);
- trigger_list = sql_triggers_exist(table, TK_DELETE, NULL, NULL);
+ assert(space != NULL);
+ trigger_list = sql_triggers_exist(space->def, TK_DELETE, NULL, NULL);
bool is_complex = trigger_list != NULL ||
- fkey_is_required(table->def->id, NULL);
- struct space *space = table->space;
+ fkey_is_required(space->def->id, NULL);
bool is_view = space->def->opts.is_view;
/* If table is really a view, make sure it has been
* initialized.
*/
if (is_view) {
- if (sql_view_assign_cursors(parse, table->def->opts.sql) != 0)
+ if (sql_view_assign_cursors(parse, space->def->opts.sql) != 0)
goto delete_from_cleanup;
if (trigger_list == NULL) {
@@ -243,7 +236,7 @@ sql_table_delete_from(struct Parse *parse, struct SrcList *tab_list,
int eph_cursor = parse->nTab++;
int addr_eph_open = sqlite3VdbeCurrentAddr(v);
if (is_view) {
- pk_len = table->def->field_count;
+ pk_len = space->def->field_count;
parse->nMem += pk_len;
sqlite3VdbeAddOp2(v, OP_OpenTEphemeral, reg_eph,
pk_len);
@@ -381,7 +374,7 @@ sql_table_delete_from(struct Parse *parse, struct SrcList *tab_list,
if (one_pass != ONEPASS_OFF) {
/* OP_Found will use an unpacked key. */
assert(key_len == pk_len);
- assert(pk_info != NULL || table->def->opts.is_view);
+ assert(pk_info != NULL || space->def->opts.is_view);
sqlite3VdbeAddOp4Int(v, OP_NotFound, tab_cursor,
addr_bypass, reg_key, key_len);
@@ -403,7 +396,7 @@ sql_table_delete_from(struct Parse *parse, struct SrcList *tab_list,
&& one_pass != ONEPASS_OFF)
idx_noseek = one_pass_cur[1];
- sql_generate_row_delete(parse, table, trigger_list, tab_cursor,
+ sql_generate_row_delete(parse, space, trigger_list, tab_cursor,
reg_key, key_len, true,
ON_CONFLICT_ACTION_DEFAULT, one_pass,
idx_noseek);
@@ -422,7 +415,7 @@ sql_table_delete_from(struct Parse *parse, struct SrcList *tab_list,
/* Return the number of rows that were deleted. */
if ((user_session->sql_flags & SQLITE_CountRows) != 0 &&
- parse->pTriggerTab != NULL) {
+ parse->trigger_space != NULL) {
sqlite3VdbeAddOp2(v, OP_ResultRow, reg_count, 1);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted",
@@ -435,7 +428,7 @@ sql_table_delete_from(struct Parse *parse, struct SrcList *tab_list,
}
void
-sql_generate_row_delete(struct Parse *parse, struct Table *table,
+sql_generate_row_delete(struct Parse *parse, struct space *space,
struct sql_trigger *trigger_list, int cursor,
int reg_pk, short npk, bool need_update_count,
enum on_conflict_action onconf, u8 mode,
@@ -464,31 +457,31 @@ sql_generate_row_delete(struct Parse *parse, struct Table *table,
/* If there are any triggers to fire, allocate a range of registers to
* use for the old.* references in the triggers.
*/
- if (table != NULL &&
- (fkey_is_required(table->def->id, NULL) || trigger_list != NULL)) {
+ if (space != NULL &&
+ (fkey_is_required(space->def->id, NULL) ||
+ trigger_list != NULL)) {
/* Mask of OLD.* columns in use */
/* TODO: Could use temporary registers here. */
uint32_t mask =
sql_trigger_colmask(parse, trigger_list, 0, 0,
TRIGGER_BEFORE | TRIGGER_AFTER,
- table, onconf);
- struct space *space = space_by_id(table->def->id);
+ space, onconf);
assert(space != NULL);
mask |= space->fkey_mask;
first_old_reg = parse->nMem + 1;
- parse->nMem += (1 + (int)table->def->field_count);
+ parse->nMem += (1 + (int)space->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, reg_pk, first_old_reg);
- for (int i = 0; i < (int)table->def->field_count; i++) {
+ for (int i = 0; i < (int)space->def->field_count; i++) {
testcase(mask != 0xffffffff && iCol == 31);
testcase(mask != 0xffffffff && iCol == 32);
if (mask == 0xffffffff
|| (i <= 31 && (mask & MASKBIT32(i)) != 0)) {
- sqlite3ExprCodeGetColumnOfTable(v, table->def,
+ sqlite3ExprCodeGetColumnOfTable(v, space->def,
cursor, i,
first_old_reg +
i + 1);
@@ -498,7 +491,7 @@ sql_generate_row_delete(struct Parse *parse, struct Table *table,
/* Invoke BEFORE DELETE trigger programs. */
int addr_start = sqlite3VdbeCurrentAddr(v);
vdbe_code_row_trigger(parse, trigger_list, TK_DELETE, NULL,
- TRIGGER_BEFORE, table, first_old_reg,
+ TRIGGER_BEFORE, space, first_old_reg,
onconf, label);
/* If any BEFORE triggers were coded, then seek
@@ -518,7 +511,7 @@ sql_generate_row_delete(struct Parse *parse, struct Table *table,
* constraints attached to other tables) are not
* violated by deleting this row.
*/
- fkey_emit_check(parse, table, first_old_reg, 0, NULL);
+ fkey_emit_check(parse, space, first_old_reg, 0, NULL);
}
/* Delete the index and table entries. Skip this step if
@@ -526,7 +519,7 @@ sql_generate_row_delete(struct Parse *parse, struct Table *table,
* of the DELETE statement is to fire the INSTEAD OF
* triggers).
*/
- if (table == NULL || !table->def->opts.is_view) {
+ if (space == NULL || !space->def->opts.is_view) {
uint8_t p5 = 0;
sqlite3VdbeAddOp2(v, OP_Delete, cursor,
(need_update_count ? OPFLAG_NCHANGE : 0));
@@ -541,18 +534,18 @@ sql_generate_row_delete(struct Parse *parse, struct Table *table,
sqlite3VdbeChangeP5(v, p5);
}
- if (table != NULL) {
+ if (space != NULL) {
/* Do any ON CASCADE, SET NULL or SET DEFAULT
* operations required to handle rows (possibly
* in other tables) that refer via a foreign
* key to the row just deleted.
*/
- fkey_emit_actions(parse, table, first_old_reg, NULL);
+ fkey_emit_actions(parse, space, first_old_reg, NULL);
/* Invoke AFTER DELETE trigger programs. */
vdbe_code_row_trigger(parse, trigger_list, TK_DELETE, 0,
- TRIGGER_AFTER, table, first_old_reg,
+ TRIGGER_AFTER, space, first_old_reg,
onconf, label);
}
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index d83be5101..e2fbcedf8 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -208,8 +208,11 @@ sql_expr_coll(Parse *parse, Expr *p, bool *is_explicit_coll, uint32_t *coll_id)
if ((op == TK_AGG_COLUMN || op == TK_COLUMN ||
op == TK_REGISTER || op == TK_TRIGGER) &&
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
+ /*
+ * op==TK_REGISTER && p->space_def!=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) {
@@ -1573,7 +1576,6 @@ sqlite3SrcListDup(sqlite3 * db, SrcList * p, int flags)
for (i = 0; i < p->nSrc; i++) {
struct SrcList_item *pNewItem = &pNew->a[i];
struct SrcList_item *pOldItem = &p->a[i];
- Table *pTab;
pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
pNewItem->fg = pOldItem->fg;
@@ -1589,10 +1591,7 @@ sqlite3SrcListDup(sqlite3 * db, SrcList * p, int flags)
pNewItem->u1.pFuncArg =
sql_expr_list_dup(db, pOldItem->u1.pFuncArg, flags);
}
- pTab = pNewItem->pTab = pOldItem->pTab;
- if (pTab) {
- pTab->nTabRef++;
- }
+ pNewItem->space = pOldItem->space;
pNewItem->pSelect =
sqlite3SelectDup(db, pOldItem->pSelect, flags);
pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn, flags);
@@ -2202,7 +2201,6 @@ isCandidateForInOpt(Expr * pX)
Select *p;
SrcList *pSrc;
ExprList *pEList;
- Table MAYBE_UNUSED *pTab;
int i;
if (!ExprHasProperty(pX, EP_xIsSelect))
return 0; /* Not a subquery */
@@ -2230,10 +2228,9 @@ isCandidateForInOpt(Expr * pX)
return 0; /* Single term in FROM clause */
if (pSrc->a[0].pSelect)
return 0; /* FROM is not a subquery or view */
- pTab = pSrc->a[0].pTab;
- assert(pTab != 0);
+ assert(pSrc->a[0].space != 0);
/* FROM clause is not a view */
- assert(!pTab->def->opts.is_view);
+ assert(!pSrc->a[0].space->def->opts.is_view);
pEList = p->pEList;
assert(pEList != 0);
/* All SELECT results must be columns. */
@@ -2412,19 +2409,18 @@ sqlite3FindInIndex(Parse * pParse, /* Parsing context */
*/
if (pParse->nErr == 0 && (p = isCandidateForInOpt(pX)) != 0) {
sqlite3 *db = pParse->db; /* Database connection */
- Table *pTab; /* Table <table>. */
ExprList *pEList = p->pEList;
int nExpr = pEList->nExpr;
assert(p->pEList != 0); /* Because of isCandidateForInOpt(p) */
assert(p->pEList->a[0].pExpr != 0); /* Because of isCandidateForInOpt(p) */
assert(p->pSrc != 0); /* Because of isCandidateForInOpt(p) */
- pTab = p->pSrc->a[0].pTab;
assert(v); /* sqlite3GetVdbe() has always been previously called */
int affinity_ok = 1;
int i;
+ struct space *space = p->pSrc->a[0].space;
/* Check that the affinity that will be used to perform each
* comparison is the same as the affinity of each column in table
* on the RHS of the IN operator. If it not, it is not possible to
@@ -2435,7 +2431,7 @@ sqlite3FindInIndex(Parse * pParse, /* Parsing context */
int iCol = pEList->a[i].pExpr->iColumn;
/* RHS table */
enum affinity_type idxaff =
- sqlite3TableColumnAffinity(pTab->def, iCol);
+ sqlite3TableColumnAffinity(space->def, iCol);
enum affinity_type lhs_aff = sqlite3ExprAffinity(pLhs);
/*
* Index search is possible only if types
@@ -2450,7 +2446,7 @@ sqlite3FindInIndex(Parse * pParse, /* Parsing context */
* Here we need real space since further
* it is used in cursor opening routine.
*/
- struct space *space = space_by_id(pTab->def->id);
+
/* Search for an existing index that will work for this IN operator */
for (uint32_t k = 0; k < space->index_count &&
eType == 0; ++k) {
@@ -4339,7 +4335,7 @@ sqlite3ExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
break;
}
case TK_RAISE:
- if (pParse->pTriggerTab == NULL) {
+ if (pParse->trigger_space == NULL) {
sqlite3ErrorMsg(pParse, "RAISE() may only be used "
"within a trigger-program");
return 0;
diff --git a/src/box/sql/fkey.c b/src/box/sql/fkey.c
index 3033cfcbb..93f98b9db 100644
--- a/src/box/sql/fkey.c
+++ b/src/box/sql/fkey.c
@@ -302,20 +302,23 @@ fkey_lookup_parent(struct Parse *parse_context, struct space *parent,
sqlite3VdbeAddOp1(v, OP_Close, cursor);
}
-/*
- * Return an Expr object that refers to a memory register corresponding
- * to column iCol of table pTab.
+/**
+ * Return an Expr object that refers to a memory register
+ * corresponding to column iCol of given space.
*
- * regBase is the first of an array of register that contains the data
- * for pTab. regBase+1 holds the first column.
+ * regBase is the first of an array of register that contains
+ * the data for given space. regBase+1 holds the first column.
* regBase+2 holds the second column, and so forth.
+ *
+ * @param pParse Parsing and code generating context.
+ * @param space The space whose content is at r[regBase]...
+ * @param regBase Contents of table pTab.
+ * @param iCol Which column of pTab is desired.
+ * @return an Expr object that refers to a memory register
+ * corresponding to column iCol of given space.
*/
static Expr *
-exprTableRegister(Parse * pParse, /* Parsing and code generating context */
- Table * pTab, /* The table whose content is at r[regBase]... */
- int regBase, /* Contents of table pTab */
- i16 iCol /* Which column of pTab is desired */
- )
+exprTableRegister(Parse * pParse, struct space * space, int regBase, i16 iCol)
{
Expr *pExpr;
sqlite3 *db = pParse->db;
@@ -324,7 +327,7 @@ exprTableRegister(Parse * pParse, /* Parsing and code generating context */
if (pExpr) {
if (iCol >= 0) {
pExpr->iTable = regBase + iCol + 1;
- char affinity = pTab->def->fields[iCol].affinity;
+ char affinity = space->def->fields[iCol].affinity;
pExpr->affinity = affinity;
} else {
pExpr->iTable = regBase;
@@ -400,7 +403,7 @@ exprTableColumn(sqlite3 * db, struct space_def *def, int cursor, i16 column)
* @param incr_count Amount to increment deferred counter by.
*/
static void
-fkey_scan_children(struct Parse *parser, struct SrcList *src, struct Table *tab,
+fkey_scan_children(struct Parse *parser, struct SrcList *src, struct space *space,
struct fkey_def *fkey, int reg_data, int incr_count)
{
assert(incr_count == -1 || incr_count == 1);
@@ -432,7 +435,7 @@ fkey_scan_children(struct Parse *parser, struct SrcList *src, struct Table *tab,
for (uint32_t i = 0; i < fkey->field_count; i++) {
uint32_t fieldno = fkey->links[i].parent_field;
struct Expr *pexpr =
- exprTableRegister(parser, tab, reg_data, fieldno);
+ exprTableRegister(parser, space, reg_data, fieldno);
fieldno = fkey->links[i].child_field;
const char *field_name = child_space->def->fields[fieldno].name;
struct Expr *chexpr = sqlite3Expr(db, TK_ID, field_name);
@@ -449,13 +452,13 @@ fkey_scan_children(struct Parse *parser, struct SrcList *src, struct Table *tab,
* NOT( $current_a==a AND $current_b==b AND ... )
* The primary key is (a,b,...)
*/
- if (tab->def->id == fkey->child_id && incr_count > 0) {
+ if (space->def->id == fkey->child_id && incr_count > 0) {
struct Expr *expr = NULL, *pexpr, *chexpr, *eq;
for (uint32_t i = 0; i < fkey->field_count; i++) {
uint32_t fieldno = fkey->links[i].parent_field;
- pexpr = exprTableRegister(parser, tab, reg_data,
+ pexpr = exprTableRegister(parser, space, reg_data,
fieldno);
- chexpr = exprTableColumn(db, tab->def,
+ chexpr = exprTableColumn(db, space->def,
src->a[0].iCursor, fieldno);
eq = sqlite3PExpr(parser, TK_EQ, pexpr, chexpr);
expr = sqlite3ExprAnd(db, expr, eq);
@@ -527,7 +530,7 @@ fkey_action_is_set_null(struct Parse *parse_context, const struct fkey *fkey)
}
void
-fkey_emit_check(struct Parse *parser, struct Table *tab, int reg_old,
+fkey_emit_check(struct Parse *parser, struct space *space, int reg_old,
int reg_new, const int *changed_cols)
{
bool is_update = changed_cols != NULL;
@@ -543,7 +546,6 @@ fkey_emit_check(struct Parse *parser, struct Table *tab, int reg_old,
* Loop through all the foreign key constraints for which
* tab is the child table.
*/
- struct space *space = space_by_id(tab->def->id);
assert(space != NULL);
struct fkey *fk;
rlist_foreach_entry(fk, &space->child_fkey, child_link) {
@@ -618,27 +620,17 @@ fkey_emit_check(struct Parse *parser, struct Table *tab, int reg_old,
struct SrcList_item *item = src->a;
struct space *child = space_by_id(fk->def->child_id);
assert(child != NULL);
- /*
- * Create surrogate struct Table wrapper around
- * space_def to support legacy interface.
- */
- struct Table fake_tab;
- memset(&fake_tab, 0, sizeof(fake_tab));
- fake_tab.def = child->def;
- fake_tab.space = child;
- /* Prevent from deallocationg fake_tab. */
- fake_tab.nTabRef = 2;
- item->pTab = &fake_tab;
+ item->space = child;
item->zName = sqlite3DbStrDup(db, child->def->name);
item->iCursor = parser->nTab++;
if (reg_new != 0) {
- fkey_scan_children(parser, src, tab, fk->def, reg_new,
+ fkey_scan_children(parser, src, space, fk->def, reg_new,
-1);
}
if (reg_old != 0) {
enum fkey_action action = fk_def->on_update;
- fkey_scan_children(parser, src, tab, fk->def, reg_old,
+ fkey_scan_children(parser, src, space, fk->def, reg_old,
1);
/*
* If this is a deferred FK constraint, or
@@ -739,7 +731,7 @@ fkey_is_required(uint32_t space_id, const int *changes)
* foreign key object by fkey_delete().
*
* @param pParse Parse context.
- * @param pTab Table being updated or deleted from.
+ * @param space Space being updated or deleted from.
* @param fkey Foreign key to get action for.
* @param is_update True if action is on update.
*
@@ -747,7 +739,7 @@ fkey_is_required(uint32_t space_id, const int *changes)
* @retval NULL on failure.
*/
static struct sql_trigger *
-fkey_action_trigger(struct Parse *pParse, struct Table *pTab, struct fkey *fkey,
+fkey_action_trigger(struct Parse *pParse, struct space *space, struct fkey *fkey,
bool is_update)
{
struct sqlite3 *db = pParse->db;
@@ -776,7 +768,7 @@ fkey_action_trigger(struct Parse *pParse, struct Table *pTab, struct fkey *fkey,
struct field_def *child_fields = child_space->def->fields;
uint32_t pcol = fk_def->links[i].parent_field;
- sqlite3TokenInit(&t_to_col, pTab->def->fields[pcol].name);
+ sqlite3TokenInit(&t_to_col, space->def->fields[pcol].name);
uint32_t chcol = fk_def->links[i].child_field;
sqlite3TokenInit(&t_from_col, child_fields[chcol].name);
@@ -934,7 +926,7 @@ fkey_action_trigger(struct Parse *pParse, struct Table *pTab, struct fkey *fkey,
}
void
-fkey_emit_actions(struct Parse *parser, struct Table *tab, int reg_old,
+fkey_emit_actions(struct Parse *parser, struct space *space, int reg_old,
const int *changes)
{
/*
@@ -943,7 +935,6 @@ fkey_emit_actions(struct Parse *parser, struct Table *tab, int reg_old,
* this operation (either update or delete),
* invoke the associated trigger sub-program.
*/
- struct space *space = space_by_id(tab->def->id);
assert(space != NULL);
struct fkey *fk;
rlist_foreach_entry(fk, &space->parent_fkey, parent_link) {
@@ -951,10 +942,10 @@ fkey_emit_actions(struct Parse *parser, struct Table *tab, int reg_old,
!fkey_is_modified(fk->def, FIELD_LINK_PARENT, changes))
continue;
struct sql_trigger *pAct =
- fkey_action_trigger(parser, tab, fk, changes != NULL);
+ fkey_action_trigger(parser, space, fk, changes != NULL);
if (pAct == NULL)
continue;
- vdbe_code_row_trigger_direct(parser, pAct, tab, reg_old,
+ vdbe_code_row_trigger_direct(parser, pAct, space, reg_old,
ON_CONFLICT_ACTION_ABORT, 0);
}
}
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index f147f6a50..c45bcc21b 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -117,14 +117,14 @@ sql_space_autoinc_fieldno(struct space *space)
* SELECT.
*
* @param parser Parse context.
- * @param table Table AST object.
- * @retval true if the table table in database or any of its
+ * @param space_def Space definition.
+ * @retval true if the space (given by space_id) in database or any of its
* indices have been opened at any point in the VDBE
* program.
* @retval false else.
*/
static bool
-vdbe_has_table_read(struct Parse *parser, const struct Table *table)
+vdbe_has_table_read(struct Parse *parser, const struct space_def *space_def)
{
struct Vdbe *v = sqlite3GetVdbe(parser);
int last_instr = sqlite3VdbeCurrentAddr(v);
@@ -141,7 +141,7 @@ vdbe_has_table_read(struct Parse *parser, const struct Table *table)
space = op->p4.space;
else
continue;
- if (space->def->id == table->def->id)
+ if (space->def->id == space_def->id)
return true;
}
}
@@ -260,7 +260,6 @@ sqlite3Insert(Parse * pParse, /* Parser context */
enum on_conflict_action on_error)
{
sqlite3 *db; /* The main database structure */
- Table *pTab; /* The table to insert into. aka TABLE */
char *zTab; /* Name of the table into which we are inserting */
int i, j; /* Loop counters */
Vdbe *v; /* Generate code into this virtual machine */
@@ -311,32 +310,32 @@ sqlite3Insert(Parse * pParse, /* Parser context */
zTab = pTabList->a[0].zName;
if (NEVER(zTab == 0))
goto insert_cleanup;
- pTab = sql_lookup_table(pParse, pTabList->a);
- if (pTab == NULL)
- goto insert_cleanup;
+ struct space *space = sql_lookup_space(pParse, pTabList->a);
- space_id = pTab->def->id;
+ if (space == NULL)
+ goto insert_cleanup;
/* Figure out if we have any triggers and if the table being
* inserted into is a view
*/
- trigger = sql_triggers_exist(pTab, TK_INSERT, NULL, &tmask);
- bool is_view = pTab->def->opts.is_view;
+ trigger = sql_triggers_exist(space->def, TK_INSERT, NULL, &tmask);
+ struct space_def *space_def = space->def;
+ space_id = space->def->id;
+
+ bool is_view = space_def->opts.is_view;
assert((trigger != NULL && tmask != 0) ||
(trigger == NULL && tmask == 0));
/* If pTab is really a view, make sure it has been initialized.
* ViewGetColumnNames() is a no-op if pTab is not a view.
*/
- if (is_view &&
- sql_view_assign_cursors(pParse, pTab->def->opts.sql) != 0)
+ if (is_view && sql_view_assign_cursors(pParse, space_def->opts.sql) != 0)
goto insert_cleanup;
- struct space_def *def = pTab->def;
/* Cannot insert into a read-only table. */
if (is_view && tmask == 0) {
sqlite3ErrorMsg(pParse, "cannot modify %s because it is a view",
- def->name);
+ space_def->name);
goto insert_cleanup;
}
@@ -358,7 +357,7 @@ sqlite3Insert(Parse * pParse, /* Parser context */
* This is the 2nd template.
*/
if (pColumn == 0 &&
- xferOptimization(pParse, pTab->space, pSelect, on_error)) {
+ xferOptimization(pParse, space, pSelect, on_error)) {
assert(trigger == NULL);
assert(pList == 0);
goto insert_end;
@@ -372,7 +371,7 @@ sqlite3Insert(Parse * pParse, /* Parser context */
* row record.
*/
regTupleid = regIns = ++pParse->nMem;
- pParse->nMem += def->field_count + 1;
+ pParse->nMem += space_def->field_count + 1;
regData = regTupleid + 1;
/* If the INSERT statement included an IDLIST term, then make sure
@@ -384,23 +383,23 @@ 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, (def->field_count + 7) / 8);
+ memset(used_columns, 0, (space_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 < (int) def->field_count; j++) {
+ for (j = 0; j < (int) space_def->field_count; j++) {
if (strcmp(pColumn->a[i].zName,
- def->fields[j].name) == 0) {
+ space_def->fields[j].name) == 0) {
pColumn->a[i].idx = j;
if (i != j)
bIdListInOrder = 0;
break;
}
}
- if (j >= (int) def->field_count) {
+ if (j >= (int) space_def->field_count) {
sqlite3ErrorMsg(pParse,
"table %S has no column named %s",
pTabList, 0, pColumn->a[i].zName);
@@ -436,7 +435,7 @@ sqlite3Insert(Parse * pParse, /* Parser context */
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield, -1);
dest.iSdst = bIdListInOrder ? regData : 0;
- dest.nSdst = def->field_count;
+ dest.nSdst = space_def->field_count;
rc = sqlite3Select(pParse, pSelect, &dest);
regFromSelect = dest.iSdst;
if (rc || db->mallocFailed || pParse->nErr)
@@ -459,7 +458,7 @@ sqlite3Insert(Parse * pParse, /* Parser context */
* the SELECT statement. Also use a temp table in
* the case of row triggers.
*/
- if (trigger != NULL || vdbe_has_table_read(pParse, pTab))
+ if (trigger != NULL || vdbe_has_table_read(pParse, space_def))
useTempTable = 1;
if (useTempTable) {
@@ -519,10 +518,10 @@ sqlite3Insert(Parse * pParse, /* Parser context */
}
}
- if (pColumn == 0 && nColumn && nColumn != (int)def->field_count) {
+ if (pColumn == 0 && nColumn && nColumn != (int)space_def->field_count) {
sqlite3ErrorMsg(pParse,
"table %S has %d columns but %d values were supplied",
- pTabList, 0, def->field_count, nColumn);
+ pTabList, 0, space_def->field_count, nColumn);
goto insert_cleanup;
}
if (pColumn != 0 && nColumn != pColumn->nId) {
@@ -565,18 +564,18 @@ sqlite3Insert(Parse * pParse, /* Parser context */
sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
VdbeCoverage(v);
}
- struct space *space = space_by_id(pTab->def->id);
assert(space != NULL);
uint32_t autoinc_fieldno = sql_space_autoinc_fieldno(space);
/* Run the BEFORE and INSTEAD OF triggers, if there are any
*/
endOfLoop = sqlite3VdbeMakeLabel(v);
if (tmask & TRIGGER_BEFORE) {
- int regCols = sqlite3GetTempRange(pParse, def->field_count + 1);
+ int regCols =
+ sqlite3GetTempRange(pParse, space_def->field_count + 1);
/* Create the new column data
*/
- for (i = j = 0; i < (int)def->field_count; i++) {
+ for (i = j = 0; i < (int)space_def->field_count; i++) {
if (pColumn) {
for (j = 0; j < pColumn->nId; j++) {
if (pColumn->a[j].idx == i)
@@ -616,15 +615,15 @@ sqlite3Insert(Parse * pParse, /* Parser context */
* table column affinities.
*/
if (!is_view)
- sql_emit_table_affinity(v, pTab->def, regCols + 1);
+ sql_emit_table_affinity(v, space_def, regCols + 1);
/* Fire BEFORE or INSTEAD OF triggers */
vdbe_code_row_trigger(pParse, trigger, TK_INSERT, 0,
- TRIGGER_BEFORE, pTab,
- regCols - def->field_count - 1, on_error,
+ TRIGGER_BEFORE, space,
+ regCols - space_def->field_count - 1, on_error,
endOfLoop);
- sqlite3ReleaseTempRange(pParse, regCols, def->field_count + 1);
+ sqlite3ReleaseTempRange(pParse, regCols, space_def->field_count + 1);
}
/* Compute the content of the next row to insert into a range of
@@ -636,7 +635,7 @@ sqlite3Insert(Parse * pParse, /* Parser context */
/* Compute data for all columns of the new entry, beginning
* with the first column.
*/
- for (i = 0; i < (int) def->field_count; i++) {
+ for (i = 0; i < (int) space_def->field_count; i++) {
int iRegStore = regData + i;
if (pColumn == 0) {
j = i;
@@ -651,7 +650,7 @@ sqlite3Insert(Parse * pParse, /* Parser context */
if (i == (int) autoinc_fieldno) {
sqlite3VdbeAddOp2(v,
OP_NextAutoincValue,
- pTab->def->id,
+ space->def->id,
iRegStore);
continue;
}
@@ -758,11 +757,11 @@ sqlite3Insert(Parse * pParse, /* Parser context */
* Generate code to check constraints and process
* final insertion.
*/
- vdbe_emit_constraint_checks(pParse, pTab, regIns + 1,
+ vdbe_emit_constraint_checks(pParse, space, regIns + 1,
on_error, endOfLoop, 0);
- fkey_emit_check(pParse, pTab, 0, regIns, 0);
+ fkey_emit_check(pParse, space, 0, regIns, 0);
vdbe_emit_insertion_completion(v, space, regIns + 1,
- pTab->def->field_count,
+ space->def->field_count,
on_error);
}
@@ -775,8 +774,8 @@ sqlite3Insert(Parse * pParse, /* Parser context */
if (trigger != NULL) {
/* Code AFTER triggers */
vdbe_code_row_trigger(pParse, trigger, TK_INSERT, 0,
- TRIGGER_AFTER, pTab,
- regData - 2 - def->field_count, on_error,
+ TRIGGER_AFTER, space,
+ regData - 2 - space_def->field_count, on_error,
endOfLoop);
}
@@ -798,7 +797,7 @@ sqlite3Insert(Parse * pParse, /* Parser context */
/* Return the number of rows inserted. */
if ((user_session->sql_flags & SQLITE_CountRows) != 0 &&
- pParse->pTriggerTab == NULL) {
+ pParse->trigger_space == NULL) {
sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted",
@@ -861,7 +860,7 @@ checkConstraintUnchanged(Expr * pExpr, int *aiChng)
}
void
-vdbe_emit_constraint_checks(struct Parse *parse_context, struct Table *tab,
+vdbe_emit_constraint_checks(struct Parse *parse_context, struct space *space,
int new_tuple_reg,
enum on_conflict_action on_conflict,
int ignore_label, int *upd_cols)
@@ -870,7 +869,6 @@ vdbe_emit_constraint_checks(struct Parse *parse_context, struct Table *tab,
struct Vdbe *v = sqlite3GetVdbe(parse_context);
assert(v != NULL);
bool is_update = upd_cols != NULL;
- struct space *space = space_by_id(tab->def->id);
assert(space != NULL);
struct space_def *def = space->def;
/* Insertion into VIEW is prohibited. */
@@ -964,7 +962,7 @@ vdbe_emit_constraint_checks(struct Parse *parse_context, struct Table *tab,
sqlite3VdbeResolveLabel(v, all_ok);
}
}
- sql_emit_table_affinity(v, tab->def, new_tuple_reg);
+ sql_emit_table_affinity(v, space->def, new_tuple_reg);
/*
* Other actions except for REPLACE and UPDATE OR IGNORE
* can be handled by setting appropriate flag in OP_Halt.
@@ -974,8 +972,8 @@ vdbe_emit_constraint_checks(struct Parse *parse_context, struct Table *tab,
return;
/* Calculate MAX range of register we may occupy. */
uint32_t reg_count = 0;
- for (uint32_t i = 0; i < tab->space->index_count; ++i) {
- struct index *idx = tab->space->index[i];
+ for (uint32_t i = 0; i < space->index_count; ++i) {
+ struct index *idx = space->index[i];
if (idx->def->key_def->part_count > reg_count)
reg_count = idx->def->key_def->part_count;
}
@@ -991,8 +989,8 @@ vdbe_emit_constraint_checks(struct Parse *parse_context, struct Table *tab,
* Otherwise, we should skip removal of old entry and
* insertion of new one.
*/
- for (uint32_t i = 0; i < tab->space->index_count; ++i) {
- struct index *idx = tab->space->index[i];
+ for (uint32_t i = 0; i < space->index_count; ++i) {
+ struct index *idx = space->index[i];
/* Conflicts may occur only in UNIQUE indexes. */
if (!idx->def->opts.is_unique)
continue;
@@ -1041,8 +1039,9 @@ process_index: ;
part_count);
sql_set_multi_write(parse_context, true);
struct sql_trigger *trigger =
- sql_triggers_exist(tab, TK_DELETE, NULL, NULL);
- sql_generate_row_delete(parse_context, tab, trigger,
+ sql_triggers_exist(space->def, TK_DELETE, NULL,
+ NULL);
+ sql_generate_row_delete(parse_context, space, trigger,
cursor, idx_key_reg, part_count,
true,
ON_CONFLICT_ACTION_REPLACE,
diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c
index 6462467bc..226ed80d0 100644
--- a/src/box/sql/resolve.c
+++ b/src/box/sql/resolve.c
@@ -185,8 +185,8 @@ sqlite3MatchSpanName(const char *zSpan,
*
* pExpr->iTable Set to the cursor number for the table obtained
* from pSrcList.
- * pExpr->pTab Points to the Table structure of X.Y (even if
- * X and/or Y are implied.)
+ * pExpr->space_def Points to the space_def structure of X.Y
+ * (even if X and/or Y are implied.)
* pExpr->iColumn Set to the column number within the table.
* pExpr->op Set to TK_COLUMN.
* pExpr->pLeft Any expression this points to is deleted
@@ -218,7 +218,7 @@ lookupName(Parse * pParse, /* The parsing context */
struct SrcList_item *pMatch = 0; /* The matching pSrcList item */
NameContext *pTopNC = pNC; /* First namecontext in the list */
int isTrigger = 0; /* True if resolved to a trigger column */
- Table *pTab = 0; /* Table hold the row */
+ struct space_def *space_def;
assert(pNC); /* the name context cannot be NULL. */
assert(zCol); /* The Z in X.Y.Z cannot be NULL */
@@ -237,9 +237,10 @@ lookupName(Parse * pParse, /* The parsing context */
if (pSrcList) {
for (i = 0, pItem = pSrcList->a; i < pSrcList->nSrc;
i++, pItem++) {
- pTab = pItem->pTab;
- assert(pTab != 0 && pTab->def->name != NULL);
- assert(pTab->def->field_count > 0);
+ assert(pItem->space != NULL &&
+ pItem->space->def->name != NULL);
+ struct space_def *space_def = pItem->space->def;
+ assert(space_def->field_count > 0);
if (pItem->pSelect
&& (pItem->pSelect->
selFlags & SF_NestedFrom) != 0) {
@@ -262,7 +263,7 @@ lookupName(Parse * pParse, /* The parsing context */
if (zTab) {
const char *zTabName =
pItem->zAlias ? pItem->
- zAlias : pTab->def->name;
+ zAlias : space_def->name;
assert(zTabName != 0);
if (strcmp(zTabName, zTab) != 0) {
continue;
@@ -271,9 +272,9 @@ lookupName(Parse * pParse, /* The parsing context */
if (0 == (cntTab++)) {
pMatch = pItem;
}
- for (j = 0; j < (int)pTab->def->field_count;
+ for (j = 0; j < (int)space_def->field_count;
j++) {
- if (strcmp(pTab->def->fields[j].name,
+ if (strcmp(space_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
@@ -298,7 +299,7 @@ lookupName(Parse * pParse, /* The parsing context */
}
if (pMatch) {
pExpr->iTable = pMatch->iCursor;
- pExpr->space_def = pMatch->pTab->def;
+ pExpr->space_def = pMatch->space->def;
/* RIGHT JOIN not (yet) supported */
assert((pMatch->fg.jointype & JT_RIGHT) == 0);
if ((pMatch->fg.jointype & JT_LEFT) != 0) {
@@ -311,32 +312,32 @@ lookupName(Parse * pParse, /* The parsing context */
* it is a new.* or old.* trigger argument reference
*/
if (zTab != 0 && cntTab == 0
- && pParse->pTriggerTab != 0) {
+ && pParse->trigger_space != 0) {
int op = pParse->eTriggerOp;
assert(op == TK_DELETE || op == TK_UPDATE
|| op == TK_INSERT);
if (op != TK_DELETE && sqlite3StrICmp("new", zTab) == 0) {
pExpr->iTable = 1;
- pTab = pParse->pTriggerTab;
+ space_def = pParse->trigger_space->def;
} else if (op != TK_INSERT
&& sqlite3StrICmp("old", zTab) == 0) {
pExpr->iTable = 0;
- pTab = pParse->pTriggerTab;
+ space_def = pParse->trigger_space->def;
} else {
- pTab = 0;
+ space_def = 0;
}
- if (pTab) {
+ if (space_def) {
int iCol;
cntTab++;
for (iCol = 0; iCol <
- (int)pTab->def->field_count; iCol++) {
- if (strcmp(pTab->def->fields[iCol].name,
+ (int)space_def->field_count; iCol++) {
+ if (strcmp(space_def->fields[iCol].name,
zCol) == 0) {
break;
}
}
- if (iCol < (int)pTab->def->field_count) {
+ if (iCol < (int)space_def->field_count) {
cnt++;
if (iCol < 0) {
pExpr->affinity =
@@ -357,7 +358,7 @@ lookupName(Parse * pParse, /* The parsing context */
: (((u32) 1) << iCol));
}
pExpr->iColumn = (i16) iCol;
- pExpr->space_def = pTab->def;
+ pExpr->space_def = space_def;
isTrigger = 1;
}
}
@@ -489,7 +490,7 @@ 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->space_def = pItem->pTab->def;
+ p->space_def = pItem->space->def;
p->iTable = pItem->iCursor;
p->iColumn = (ynVar) iCol;
testcase(iCol == BMS);
@@ -1613,7 +1614,7 @@ sqlite3ResolveSelectNames(Parse * pParse, /* The parser context */
}
void
-sql_resolve_self_reference(struct Parse *parser, struct Table *table, int type,
+sql_resolve_self_reference(struct Parse *parser, struct space *space, int type,
struct Expr *expr, struct ExprList *expr_list)
{
/* Fake SrcList for parser->pNewTable */
@@ -1625,8 +1626,8 @@ sql_resolve_self_reference(struct Parse *parser, struct Table *table, int type,
memset(&sNC, 0, sizeof(sNC));
memset(&sSrc, 0, sizeof(sSrc));
sSrc.nSrc = 1;
- sSrc.a[0].zName = table->def->name;
- sSrc.a[0].pTab = table;
+ sSrc.a[0].zName = space->def->name;
+ sSrc.a[0].space = space;
sSrc.a[0].iCursor = -1;
sNC.pParse = parser;
sNC.pSrcList = &sSrc;
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index 02ee225f1..55739d96a 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -419,11 +419,11 @@ sqlite3JoinType(Parse * pParse, Token * pA, Token * pB, Token * pC)
* is not contained in the table.
*/
static int
-columnIndex(Table * pTab, const char *zCol)
+columnIndex(struct space *space, const char *zCol)
{
int i;
- for (i = 0; i < (int)pTab->def->field_count; i++) {
- if (strcmp(pTab->def->fields[i].name, zCol) == 0)
+ for (i = 0; i < (int)space->def->field_count; i++) {
+ if (strcmp(space->def->fields[i].name, zCol) == 0)
return i;
}
return -1;
@@ -450,7 +450,7 @@ tableAndColumnIndex(SrcList * pSrc, /* Array of tables to search */
assert((piTab == 0) == (piCol == 0)); /* Both or neither are NULL */
for (i = 0; i < N; i++) {
- iCol = columnIndex(pSrc->a[i].pTab, zCol);
+ iCol = columnIndex(pSrc->a[i].space, zCol);
if (iCol >= 0) {
if (piTab) {
*piTab = i;
@@ -490,8 +490,8 @@ addWhereTerm(Parse * pParse, /* Parsing context */
assert(iLeft < iRight);
assert(pSrc->nSrc > iRight);
- assert(pSrc->a[iLeft].pTab);
- assert(pSrc->a[iRight].pTab);
+ assert(pSrc->a[iLeft].space);
+ assert(pSrc->a[iRight].space);
pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iColLeft);
pE2 = sqlite3CreateColumnExpr(db, pSrc, iRight, iColRight);
@@ -577,11 +577,11 @@ sqliteProcessJoin(Parse * pParse, Select * p)
pLeft = &pSrc->a[0];
pRight = &pLeft[1];
for (i = 0; i < pSrc->nSrc - 1; i++, pRight++, pLeft++) {
- Table *pLeftTab = pLeft->pTab;
- Table *pRightTab = pRight->pTab;
+ struct space *left_space = pLeft->space;
+ struct space *right_space = pRight->space;
int isOuter;
- if (NEVER(pLeftTab == 0 || pRightTab == 0))
+ if (NEVER(left_space == 0 || right_space == 0))
continue;
isOuter = (pRight->fg.jointype & JT_OUTER) != 0;
@@ -595,12 +595,12 @@ sqliteProcessJoin(Parse * pParse, Select * p)
"an ON or USING clause", 0);
return 1;
}
- for (j = 0; j < (int)pRightTab->def->field_count; j++) {
+ for (j = 0; j < (int)right_space->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->def->fields[j].name;
+ zName = right_space->def->fields[j].name;
if (tableAndColumnIndex
(pSrc, i + 1, zName, &iLeft, &iLeftCol)) {
addWhereTerm(pParse, pSrc, iLeft,
@@ -645,7 +645,7 @@ sqliteProcessJoin(Parse * pParse, Select * p)
int iRightCol; /* Column number of matching column on the right */
zName = pList->a[j].zName;
- iRightCol = columnIndex(pRightTab, zName);
+ iRightCol = columnIndex(right_space, zName);
if (iRightCol < 0
|| !tableAndColumnIndex(pSrc, i + 1, zName,
&iLeft, &iLeftCol)
@@ -1757,7 +1757,6 @@ generateColumnNames(Parse * pParse, /* Parser context */
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName,
SQLITE_TRANSIENT);
} else if (p->op == TK_COLUMN || p->op == TK_AGG_COLUMN) {
- Table *pTab;
char *zCol;
int iCol = p->iColumn;
for (j = 0; ALWAYS(j < pTabList->nSrc); j++) {
@@ -1765,9 +1764,9 @@ generateColumnNames(Parse * pParse, /* Parser context */
break;
}
assert(j < pTabList->nSrc);
- pTab = pTabList->a[j].pTab;
- assert(iCol >= 0 && iCol < (int)pTab->def->field_count);
- zCol = pTab->def->fields[iCol].name;
+ struct space_def *space_def = pTabList->a[j].space->def;
+ assert(iCol >= 0 && iCol < (int)space_def->field_count);
+ zCol = space_def->fields[iCol].name;
if (!shortNames && !fullNames) {
sqlite3VdbeSetColName(v, i, COLNAME_NAME,
sqlite3DbStrDup(db,
@@ -1775,9 +1774,8 @@ generateColumnNames(Parse * pParse, /* Parser context */
SQLITE_DYNAMIC);
} else if (fullNames) {
char *zName = 0;
- zName =
- sqlite3MPrintf(db, "%s.%s", pTab->def->name,
- zCol);
+ zName = sqlite3MPrintf(db, "%s.%s",
+ space_def->name, zCol);
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName,
SQLITE_DYNAMIC);
} else {
@@ -1819,7 +1817,8 @@ generateColumnNames(Parse * pParse, /* Parser context */
* store NULL in *paCol and 0 in *pnCol and return SQLITE_NOMEM.
*/
int
-sqlite3ColumnsFromExprList(Parse * parse, ExprList * expr_list, Table *table)
+sqlite3ColumnsFromExprList(Parse * parse, ExprList * expr_list,
+ struct space_def *space_def)
{
/* Database connection */
sqlite3 *db = parse->db;
@@ -1837,22 +1836,22 @@ sqlite3ColumnsFromExprList(Parse * parse, ExprList * expr_list, Table *table)
* sqlite3ViewGetColumnNames could use it to resolve
* names for existing table.
*/
- assert(table->def->fields == NULL);
+ assert(space_def->fields == NULL);
struct region *region = &parse->region;
- table->def->fields =
+ space_def->fields =
region_alloc(region,
- column_count * sizeof(table->def->fields[0]));
- if (table->def->fields == NULL) {
+ column_count * sizeof(space_def->fields[0]));
+ if (space_def->fields == NULL) {
sqlite3OomFault(db);
goto cleanup;
}
for (uint32_t i = 0; i < column_count; i++) {
- memcpy(&table->def->fields[i], &field_def_default,
+ memcpy(&space_def->fields[i], &field_def_default,
sizeof(field_def_default));
- table->def->fields[i].nullable_action = ON_CONFLICT_ACTION_NONE;
- table->def->fields[i].is_nullable = true;
+ space_def->fields[i].nullable_action = ON_CONFLICT_ACTION_NONE;
+ space_def->fields[i].is_nullable = true;
}
- table->def->field_count = column_count;
+ space_def->field_count = column_count;
for (uint32_t i = 0; i < column_count; i++) {
/* Get an appropriate name for the column
@@ -1903,18 +1902,17 @@ sqlite3ColumnsFromExprList(Parse * parse, ExprList * expr_list, Table *table)
sqlite3MPrintf(db, "%.*z_%u", nName, zName, ++cnt);
}
size_t name_len = strlen(zName);
- void *field = &table->def->fields[i];
+ void *field = &space_def->fields[i];
if (zName != NULL &&
sqlite3HashInsert(&ht, zName, field) == field)
sqlite3OomFault(db);
- table->def->fields[i].name =
- region_alloc(region, name_len + 1);
- if (table->def->fields[i].name == NULL) {
+ space_def->fields[i].name = region_alloc(region, name_len + 1);
+ if (space_def->fields[i].name == NULL) {
sqlite3OomFault(db);
goto cleanup;
} else {
- memcpy(table->def->fields[i].name, zName, name_len);
- table->def->fields[i].name[name_len] = '\0';
+ memcpy(space_def->fields[i].name, zName, name_len);
+ space_def->fields[i].name[name_len] = '\0';
}
}
cleanup:
@@ -1925,8 +1923,8 @@ cleanup:
* pTable->def could be not temporal in
* sqlite3ViewGetColumnNames so we need clean-up.
*/
- table->def->fields = NULL;
- table->def->field_count = 0;
+ space_def->fields = NULL;
+ space_def->field_count = 0;
rc = SQLITE_NOMEM_BKPT;
}
return rc;
@@ -1934,20 +1932,28 @@ cleanup:
}
/*
+
+ */
+
+/**
* Add type and collation information to a column list based on
* a SELECT statement.
*
- * The column list presumably came from selectColumnNamesFromExprList().
- * The column list has only names, not types or collations. This
- * routine goes through and adds the types and collations.
+ * The column list presumably came from
+ * selectColumnNamesFromExprList(). The column list has only
+ * names, not types or collations. This routine goes through
+ * and adds the types and collations.
*
* This routine requires that all identifiers in the SELECT
* statement be resolved.
+ *
+ * @param pParse Parsing contexts.
+ * @param space Add column type information to this table.
+ * @param pSelect SELECT used to determine types and collations.
*/
void
-sqlite3SelectAddColumnTypeAndCollation(Parse * pParse, /* Parsing contexts */
- Table * pTab, /* Add column type information to this table */
- Select * pSelect) /* SELECT used to determine types and collations */
+sqlite3SelectAddColumnTypeAndCollation(Parse * pParse, struct space * space,
+ Select * pSelect)
{
sqlite3 *db = pParse->db;
NameContext sNC;
@@ -1956,35 +1962,35 @@ sqlite3SelectAddColumnTypeAndCollation(Parse * pParse, /* Parsing contexts */
assert(pSelect != 0);
assert((pSelect->selFlags & SF_Resolved) != 0);
- assert((int)pTab->def->field_count == pSelect->pEList->nExpr ||
+ assert((int)space->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 (uint32_t i = 0; i < pTab->def->field_count; i++) {
+ for (uint32_t i = 0; i < space->def->field_count; i++) {
p = a[i].pExpr;
char affinity = sqlite3ExprAffinity(p);
if (affinity == 0)
affinity = AFFINITY_BLOB;
- pTab->def->fields[i].affinity = affinity;
- pTab->def->fields[i].type = sql_affinity_to_field_type(affinity);
+ space->def->fields[i].affinity = affinity;
+ space->def->fields[i].type = sql_affinity_to_field_type(affinity);
bool is_found;
uint32_t coll_id;
- if (pTab->def->fields[i].coll_id == COLL_NONE &&
+ if (space->def->fields[i].coll_id == COLL_NONE &&
sql_expr_coll(pParse, p, &is_found, &coll_id) &&
coll_id != COLL_NONE)
- pTab->def->fields[i].coll_id = coll_id;
+ space->def->fields[i].coll_id = coll_id;
}
}
/*
- * Given a SELECT statement, generate a Table structure that describes
+ * Given a SELECT statement, generate a space structure that describes
* the result set of that SELECT.
*/
-Table *
+struct space *
sqlite3ResultSetOfSelect(Parse * pParse, Select * pSelect)
{
sqlite3 *db = pParse->db;
@@ -2000,23 +2006,20 @@ sqlite3ResultSetOfSelect(Parse * pParse, Select * pSelect)
while (pSelect->pPrior)
pSelect = pSelect->pPrior;
user_session->sql_flags = savedFlags;
- Table *table = sql_ephemeral_table_new(pParse, NULL);
- if (table == NULL)
+ struct space *space = sql_ephemeral_space_new(pParse, NULL);
+
+ if (space == NULL)
return 0;
- /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
+ /* The sqlite3ResultSetOfSelect() is only used in contexts where lookaside
* is disabled
*/
assert(db->lookaside.bDisable);
- table->nTabRef = 1;
- table->tuple_log_count = DEFAULT_TUPLE_LOG_COUNT;
- assert(sqlite3LogEst(DEFAULT_TUPLE_COUNT) == DEFAULT_TUPLE_LOG_COUNT);
- sqlite3ColumnsFromExprList(pParse, pSelect->pEList, table);
- sqlite3SelectAddColumnTypeAndCollation(pParse, table, pSelect);
+ sqlite3ColumnsFromExprList(pParse, pSelect->pEList, space->def);
+ sqlite3SelectAddColumnTypeAndCollation(pParse, space, pSelect);
if (db->mallocFailed) {
- sqlite3DeleteTable(db, table);
return 0;
}
- return table;
+ return space;
}
/*
@@ -4043,24 +4046,9 @@ flattenSubquery(Parse * pParse, /* Parsing context */
pSubitem->zAlias = 0;
pSubitem->pSelect = 0;
- /* Defer deleting the Table object associated with the
- * subquery until code generation is
- * complete, since there may still exist Expr.pTab entries that
- * refer to the subquery even after flattening. Ticket #3346.
- *
- * pSubitem->pTab is always non-NULL by test restrictions and tests above.
+ /* Deletion of the pSubitem->space will be done when a corresponding
+ * region will be freed.
*/
- if (ALWAYS(pSubitem->pTab != 0)) {
- Table *pTabToDel = pSubitem->pTab;
- if (pTabToDel->nTabRef == 1) {
- Parse *pToplevel = sqlite3ParseToplevel(pParse);
- pTabToDel->pNextZombie = pToplevel->pZombieTab;
- pToplevel->pZombieTab = pTabToDel;
- } else {
- pTabToDel->nTabRef--;
- }
- pSubitem->pTab = 0;
- }
/* The following loop runs once for each term in a compound-subquery
* flattening (as described above). If we are doing a different kind
@@ -4365,8 +4353,7 @@ is_simple_count(struct Select *select, struct AggInfo *agg_info)
select->pSrc->nSrc != 1 || select->pSrc->a[0].pSelect != NULL) {
return NULL;
}
- uint32_t space_id = select->pSrc->a[0].pTab->def->id;
- struct space *space = space_by_id(space_id);
+ struct space *space = select->pSrc->a[0].space;
assert(space != NULL && !space->def->opts.is_view);
struct Expr *expr = select->pEList->a[0].pExpr;
assert(expr != NULL);
@@ -4391,14 +4378,14 @@ is_simple_count(struct Select *select, struct AggInfo *agg_info)
int
sqlite3IndexedByLookup(Parse * pParse, struct SrcList_item *pFrom)
{
- if (pFrom->pTab && pFrom->fg.isIndexedBy) {
- Table *pTab = pFrom->pTab;
+ if (pFrom->space && pFrom->fg.isIndexedBy) {
+ struct space *space = pFrom->space;
char *zIndexedBy = pFrom->u1.zIndexedBy;
struct index *idx = NULL;
- for (uint32_t i = 0; i < pTab->space->index_count; ++i) {
- if (strcmp(pTab->space->index[i]->def->name,
+ for (uint32_t i = 0; i < space->index_count; ++i) {
+ if (strcmp(space->index[i]->def->name,
zIndexedBy) == 0) {
- idx = pTab->space->index[i];
+ idx = space->index[i];
break;
}
}
@@ -4572,9 +4559,9 @@ sqlite3WithPush(Parse * pParse, With * pWith, u8 bFree)
* if currently processing a CTE expression, if it is a recursive
* reference to the current CTE.
*
- * If pFrom falls into either of the two categories above, pFrom->pTab
+ * If pFrom falls into either of the two categories above, pFrom->space
* and other fields are populated accordingly. The caller should check
- * (pFrom->pTab!=0) to determine whether or not a successful match
+ * (pFrom->space!=0) to determine whether or not a successful match
* was found.
*
* Whether or not a match is found, SQLITE_OK is returned if no error
@@ -4589,11 +4576,10 @@ withExpand(Walker * pWalker, struct SrcList_item *pFrom)
struct Cte *pCte; /* Matched CTE (or NULL if no match) */
With *pWith; /* WITH clause that pCte belongs to */
- assert(pFrom->pTab == 0);
+ assert(pFrom->space == 0);
pCte = searchWith(pParse->pWith, pFrom, &pWith);
if (pCte) {
- Table *pTab;
ExprList *pEList;
Select *pSel;
Select *pLeft; /* Left-most SELECT statement */
@@ -4612,15 +4598,10 @@ withExpand(Walker * pWalker, struct SrcList_item *pFrom)
if (cannotBeFunction(pParse, pFrom))
return SQLITE_ERROR;
- assert(pFrom->pTab == 0);
- pFrom->pTab = pTab =
- sql_ephemeral_table_new(pParse, pCte->zName);
- if (pTab == NULL)
+ assert(pFrom->space == 0);
+ pFrom->space = sql_ephemeral_space_new(pParse, pCte->zName);
+ if (pFrom->space == NULL)
return WRC_Abort;
- pTab->nTabRef = 1;
- pTab->tuple_log_count = DEFAULT_TUPLE_LOG_COUNT;
- assert(sqlite3LogEst(DEFAULT_TUPLE_COUNT) ==
- DEFAULT_TUPLE_LOG_COUNT);
pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
if (db->mallocFailed)
return SQLITE_NOMEM_BKPT;
@@ -4629,6 +4610,7 @@ withExpand(Walker * pWalker, struct SrcList_item *pFrom)
/* Check if this is a recursive CTE. */
pSel = pFrom->pSelect;
bMayRecursive = (pSel->op == TK_ALL || pSel->op == TK_UNION);
+ int ref_counter = 0;
if (bMayRecursive) {
int i;
SrcList *pSrc = pFrom->pSelect->pSrc;
@@ -4638,24 +4620,21 @@ withExpand(Walker * pWalker, struct SrcList_item *pFrom)
&& 0 == sqlite3StrICmp(pItem->zName,
pCte->zName)
) {
- pItem->pTab = pTab;
+ pItem->space = pFrom->space;
pItem->fg.isRecursive = 1;
- pTab->nTabRef++;
+ ref_counter++;
pSel->selFlags |= SF_Recursive;
}
}
}
-
- /* Only one recursive reference is permitted. */
- if (pTab->nTabRef > 2) {
+ if (ref_counter > 1) {
sqlite3ErrorMsg(pParse,
"multiple references to recursive table: %s",
pCte->zName);
return SQLITE_ERROR;
}
- assert(pTab->nTabRef == 1
- || ((pSel->selFlags & SF_Recursive)
- && pTab->nTabRef == 2));
+ assert(ref_counter == 0 ||
+ ((pSel->selFlags & SF_Recursive) && ref_counter == 1));
pCte->zCteErr = "circular reference: %s";
pSavedWith = pParse->pWith;
@@ -4677,7 +4656,7 @@ withExpand(Walker * pWalker, struct SrcList_item *pFrom)
pEList = pCte->pCols;
}
- sqlite3ColumnsFromExprList(pParse, pEList, pTab);
+ sqlite3ColumnsFromExprList(pParse, pEList, pFrom->space->def);
if (bMayRecursive) {
if (pSel->selFlags & SF_Recursive) {
@@ -4777,25 +4756,24 @@ selectExpander(Walker * pWalker, Select * p)
/* Look up every table named in the FROM clause of the select. If
* an entry of the FROM clause is a subquery instead of a table or view,
- * then create a transient table structure to describe the subquery.
+ * then create a transient space structure to describe the subquery.
*/
for (i = 0, pFrom = pTabList->a; i < pTabList->nSrc; i++, pFrom++) {
- Table *pTab;
- assert(pFrom->fg.isRecursive == 0 || pFrom->pTab != 0);
+ assert(pFrom->fg.isRecursive == 0 || pFrom->space != 0);
if (pFrom->fg.isRecursive)
continue;
- assert(pFrom->pTab == 0);
+ assert(pFrom->space == 0);
#ifndef SQLITE_OMIT_CTE
if (withExpand(pWalker, pFrom))
return WRC_Abort;
- if (pFrom->pTab) {
+ if (pFrom->space) {
} else
#endif
if (pFrom->zName == 0) {
Select *pSel = pFrom->pSelect;
/* A sub-query in the FROM clause of a SELECT */
assert(pSel != 0);
- assert(pFrom->pTab == 0);
+ assert(pFrom->space == 0);
if (sqlite3WalkSelect(pWalker, pSel))
return WRC_Abort;
/*
@@ -4803,39 +4781,36 @@ selectExpander(Walker * pWalker, Select * p)
* unique identifier.
*/
const char *name = "sqlite_sq_DEADBEAFDEADBEAF";
- pFrom->pTab = pTab =
- sql_ephemeral_table_new(pParse, name);
- if (pTab == NULL)
+ struct space *space;
+ pFrom->space = space =
+ sql_ephemeral_space_new(sqlite3ParseToplevel(pParse),
+ name);
+
+ if (space == 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;
+ name = tt_sprintf("sqlite_sq_%llX", (void *)space);
+ sprintf(space->def->name, "%s", name);
while (pSel->pPrior) {
pSel = pSel->pPrior;
}
- sqlite3ColumnsFromExprList(pParse, pSel->pEList, pTab);
- if (sql_table_def_rebuild(db, pTab) != 0)
- return WRC_Abort;
- pTab->tuple_log_count = DEFAULT_TUPLE_LOG_COUNT;
- assert(sqlite3LogEst(DEFAULT_TUPLE_COUNT) ==
- DEFAULT_TUPLE_LOG_COUNT);
+ sqlite3ColumnsFromExprList(pParse, pSel->pEList,
+ space->def);
} else {
/*
* An ordinary table or view name in the
* FROM clause.
*/
- pTab = sql_lookup_table(pParse, pFrom);
- if (pTab == NULL)
+ struct space *space = sql_lookup_space(pParse, pFrom);
+ if (space == NULL)
return WRC_Abort;
if (cannotBeFunction(pParse, pFrom))
return WRC_Abort;
- if (pTab->def->opts.is_view) {
+ if (space->def->opts.is_view) {
struct Select *select =
- sql_view_compile(db,
- pTab->def->opts.sql);
+ sql_view_compile(db, space->def->opts.sql);
if (select == NULL)
return WRC_Abort;
sqlite3SrcListAssignCursors(pParse,
@@ -4843,11 +4818,11 @@ selectExpander(Walker * pWalker, Select * p)
assert(pFrom->pSelect == 0);
pFrom->pSelect = select;
sqlite3SelectSetName(pFrom->pSelect,
- pTab->def->name);
- int columns = pTab->def->field_count;
- pTab->def->field_count = -1;
+ space->def->name);
+ int columns = space->def->field_count;
+ space->def->field_count = -1;
sqlite3WalkSelect(pWalker, pFrom->pSelect);
- pTab->def->field_count = columns;
+ space->def->field_count = columns;
}
}
/* Locate the index named by the INDEXED BY clause, if any. */
@@ -4929,12 +4904,11 @@ selectExpander(Walker * pWalker, Select * p)
}
for (i = 0, pFrom = pTabList->a;
i < pTabList->nSrc; i++, pFrom++) {
- Table *pTab = pFrom->pTab;
+ struct space *space = pFrom->space;
Select *pSub = pFrom->pSelect;
char *zTabName = pFrom->zAlias;
- if (zTabName == 0) {
- zTabName = pTab->def->name;
- }
+ if (zTabName == 0)
+ zTabName = space->def->name;
if (db->mallocFailed)
break;
if (pSub == 0
@@ -4943,14 +4917,13 @@ selectExpander(Walker * pWalker, Select * p)
0) {
pSub = 0;
if (zTName
- && strcmp(zTName,
- zTabName)
+ && strcmp(zTName, zTabName)
!= 0) {
continue;
}
}
- for (j = 0; j < (int)pTab->def->field_count; j++) {
- char *zName = pTab->def->fields[j].name;
+ for (j = 0; j < (int)space->def->field_count; j++) {
+ char *zName = space->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 */
@@ -5138,16 +5111,16 @@ selectAddSubqueryTypeInfo(Walker * pWalker, Select * p)
pParse = pWalker->pParse;
pTabList = p->pSrc;
for (i = 0, pFrom = pTabList->a; i < pTabList->nSrc; i++, pFrom++) {
- Table *pTab = pFrom->pTab;
- assert(pTab != 0);
- if (pTab->def->id == 0) {
+ struct space *space = pFrom->space;
+ assert(space != 0);
+ if (space->def->id == 0) {
/* A sub-query in the FROM clause of a SELECT */
Select *pSel = pFrom->pSelect;
if (pSel) {
while (pSel->pPrior)
pSel = pSel->pPrior;
sqlite3SelectAddColumnTypeAndCollation(pParse,
- pTab,
+ space,
pSel);
}
}
@@ -5509,17 +5482,17 @@ sqlite3Select(Parse * pParse, /* The parser context */
struct SrcList_item *pItem = &pTabList->a[i];
Select *pSub = pItem->pSelect;
int isAggSub;
- Table *pTab = pItem->pTab;
+ struct space *space = pItem->space;
if (pSub == 0)
continue;
/* Catch mismatch in the declared columns of a view and the number of
* columns in the SELECT on the RHS
*/
- if ((int)pTab->def->field_count != pSub->pEList->nExpr) {
+ if ((int)space->def->field_count != pSub->pEList->nExpr) {
sqlite3ErrorMsg(pParse,
"expected %d columns for '%s' but got %d",
- pTab->def->field_count, pTab->def->name,
+ space->def->field_count, space->def->name,
pSub->pEList->nExpr);
goto select_end;
}
@@ -5645,23 +5618,26 @@ sqlite3Select(Parse * pParse, /* The parser context */
pItem->regReturn = ++pParse->nMem;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn,
0, addrTop);
- VdbeComment((v, "%s", pItem->pTab->def->name));
+ VdbeComment((v, "%s", pItem->space->def->name));
pItem->addrFillSub = addrTop;
sqlite3SelectDestInit(&dest, SRT_Coroutine,
pItem->regReturn, -1);
pItem->iSelectId = pParse->iNextSelectId;
sqlite3Select(pParse, pSub, &dest);
- pItem->pTab->tuple_log_count = pSub->nSelectRow;
pItem->fg.viaCoroutine = 1;
pItem->regResult = dest.iSdst;
sqlite3VdbeEndCoroutine(v, pItem->regReturn);
sqlite3VdbeJumpHere(v, addrTop - 1);
sqlite3ClearTempRegCache(pParse);
} else {
- /* Generate a subroutine that will fill an ephemeral table with
- * the content of this subquery. pItem->addrFillSub will point
- * to the address of the generated subroutine. pItem->regReturn
- * is a register allocated to hold the subroutine return address
+ /* Generate a subroutine that will fill
+ * an ephemeral space with the content
+ * of this subquery. pItem->addrFillSub
+ * will point to the address of the
+ * generated subroutine.
+ * pItem->regReturn is a register
+ * allocated to hold the subroutine
+ * return address
*/
int topAddr;
int onceAddr = 0;
@@ -5673,28 +5649,29 @@ sqlite3Select(Parse * pParse, /* The parser context */
pItem->regReturn);
pItem->addrFillSub = topAddr + 1;
if (pItem->fg.isCorrelated == 0) {
- /* If the subquery is not correlated and if we are not inside of
- * a trigger, then we only need to compute the value of the subquery
- * once.
+ /* If the subquery is not
+ * correlated and if we are not
+ * inside of a trigger, then
+ * we only need to compute the
+ * value of the subquery once.
*/
onceAddr = sqlite3VdbeAddOp0(v, OP_Once);
VdbeCoverage(v);
VdbeComment((v, "materialize \"%s\"",
- pItem->pTab->def->name));
+ pItem->space->def->name));
} else {
VdbeNoopComment((v, "materialize \"%s\"",
- pItem->pTab->def->name));
+ pItem->space->def->name));
}
sqlite3SelectDestInit(&dest, SRT_EphemTab,
pItem->iCursor, ++pParse->nMem);
pItem->iSelectId = pParse->iNextSelectId;
sqlite3Select(pParse, pSub, &dest);
- pItem->pTab->tuple_log_count = pSub->nSelectRow;
if (onceAddr)
sqlite3VdbeJumpHere(v, onceAddr);
retAddr =
sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
- VdbeComment((v, "end %s", pItem->pTab->def->name));
+ VdbeComment((v, "end %s", pItem->space->def->name));
sqlite3VdbeChangeP1(v, topAddr, retAddr);
sqlite3ClearTempRegCache(pParse);
}
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index ee24e0337..6ace02253 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -1418,7 +1418,6 @@ typedef struct SQLiteThread SQLiteThread;
typedef struct SelectDest SelectDest;
typedef struct SrcList SrcList;
typedef struct StrAccum StrAccum;
-typedef struct Table Table;
typedef struct Token Token;
typedef struct TreeView TreeView;
typedef struct TriggerPrg TriggerPrg;
@@ -1811,35 +1810,15 @@ struct Savepoint {
#define SQLITE_NULLEQ 0x80 /* NULL=NULL */
#define SQLITE_NOTNULL 0x90 /* Assert that operands are never NULL */
-/*
- * The schema for each SQL table and view is represented in memory
- * by an instance of the following structure.
- */
-struct Table {
- u32 nTabRef; /* Number of pointers to this Table */
- /**
- * Estimated number of entries in table.
- * Used only when table represents temporary objects,
- * such as nested SELECTs or VIEWs. Otherwise, this stat
- * can be fetched from space struct.
- */
- LogEst tuple_log_count;
- Table *pNextZombie; /* Next on the Parse.pZombieTab list */
- /** Space definition with Tarantool metadata. */
- struct space_def *def;
- /** Surrogate space containing array of indexes. */
- struct space *space;
-};
-
/**
* Return logarithm of tuple count in space.
*
- * @param tab Table containing id of space to be examined.
+ * @param space Space to be examined.
* @retval Logarithm of tuple count in space, or default values,
* if there is no corresponding space for given table.
*/
LogEst
-sql_space_tuple_log_count(struct Table *tab);
+sql_space_tuple_log_count(struct space *space);
/*
* Each foreign key constraint is an instance of the following structure.
@@ -2070,7 +2049,7 @@ typedef int ynVar;
* then iTable is the address of a subroutine that computes the subquery.
*
* If the Expr is of type OP_Column, and the table it is selecting from
- * is a disk table or the "old.*" pseudo-table, then pTab points to the
+ * is a disk table or the "old.*" pseudo-table, then space_def points to the
* corresponding table definition.
*
* ALLOCATION NOTES:
@@ -2334,7 +2313,7 @@ struct SrcList {
struct SrcList_item {
char *zName; /* Name of the table */
char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
- Table *pTab; /* An SQL table corresponding to zName */
+ struct space *space; /* A space corresponding to zName */
Select *pSelect; /* A SELECT statement used in place of a table name */
int addrFillSub; /* Address of subroutine to manifest a subquery */
int regReturn; /* Register holding return address of addrFillSub */
@@ -2352,7 +2331,7 @@ struct SrcList {
int iCursor; /* The VDBE cursor number used to access this table */
Expr *pOn; /* The ON clause of a join */
IdList *pUsing; /* The USING clause of a join */
- Bitmask colUsed; /* Bit N (1<<N) set if column N of pTab is used */
+ Bitmask colUsed; /* Bit N (1<<N) set if column N of space is used */
union {
char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */
ExprList *pFuncArg; /* Arguments to table-valued-function */
@@ -2733,7 +2712,7 @@ struct Parse {
int nSelect; /* Number of SELECT statements seen */
int nSelectIndent; /* How far to indent SELECTTRACE() output */
Parse *pToplevel; /* Parse structure for main program (or NULL) */
- Table *pTriggerTab; /* Table triggers are being coded for */
+ struct space *trigger_space; /* Space triggers are being coded for */
u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
u32 oldmask; /* Mask of old.* columns referenced */
u32 newmask; /* Mask of new.* columns referenced */
@@ -2776,8 +2755,7 @@ struct Parse {
VList *pVList; /* Mapping between variable names and numbers */
Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
const char *zTail; /* All SQL text past the last semicolon parsed */
- Table *pNewTable; /* A table being constructed by CREATE TABLE */
- Table *pZombieTab; /* List of Table objects to delete after code gen */
+ struct space *new_space; /* A space being constructed by CREATE TABLE */
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
With *pWith; /* Current WITH clause, or NULL */
With *pWithToFree; /* Free this WITH object at the end of the parse */
@@ -3320,7 +3298,6 @@ u32 sqlite3ExprListFlags(const ExprList *);
int sqlite3Init(sqlite3 *);
void sqlite3Pragma(Parse *, Token *, Token *, Token *, int);
-void sqlite3DeleteColumnNames(sqlite3 *, Table *);
/**
* Return true if given column is part of primary key.
@@ -3343,20 +3320,21 @@ sql_space_column_is_in_pk(struct space *space, uint32_t);
*
* @param parse Parsing context.
* @param expr_list Expr list from which to derive column names.
- * @param table Destination table.
+ * @param space_def Destination space definition.
* @retval SQLITE_OK on success.
* @retval error codef on error.
*/
-int sqlite3ColumnsFromExprList(Parse *parse, ExprList *expr_list, Table *table);
+int sqlite3ColumnsFromExprList(Parse *parse, ExprList *expr_list,
+ struct space_def *space_def);
-void sqlite3SelectAddColumnTypeAndCollation(Parse *, Table *, Select *);
-Table *sqlite3ResultSetOfSelect(Parse *, Select *);
+void sqlite3SelectAddColumnTypeAndCollation(Parse *, struct space *, Select *);
+struct space *sqlite3ResultSetOfSelect(Parse *, Select *);
/**
* Return the PRIMARY KEY index of a table.
*/
struct index *
-sql_table_primary_key(const struct Table *tab);
+sql_table_primary_key(const struct space *space);
void sqlite3StartTable(Parse *, Token *, int);
void sqlite3AddColumn(Parse *, Token *, struct type_def *);
@@ -3474,7 +3452,7 @@ sql_store_select(struct Parse *parse_context, struct Select *select);
void
sql_drop_table(struct Parse *, struct SrcList *, bool, bool);
-void sqlite3DeleteTable(sqlite3 *, Table *);
+void sql_space_delete(sqlite3 *, struct space *);
void sqlite3Insert(Parse *, SrcList *, Select *, IdList *,
enum on_conflict_action);
void *sqlite3ArrayAllocate(sqlite3 *, void *, int, int *, int *);
@@ -3542,22 +3520,22 @@ Select *sqlite3SelectNew(Parse *, ExprList *, SrcList *, Expr *, ExprList *,
* subqueries (as in the FROM clause of a SELECT statement) in
* this case it contains the name of a single table, as one might
* find in an INSERT, DELETE, or UPDATE statement. Look up that
- * space in the cache and create Table wrapper around it.
+ * space in the cache.
* Set an error message and return NULL if the table name is not
* found or if space doesn't have format.
*
* The following fields are initialized appropriate in src_list:
*
- * src_list->a[0].pTab Pointer to the Table object.
+ * src_list->a[0].space Pointer to the space object.
* src_list->a[0].pIndex Pointer to the INDEXED BY index,
* if there is one.
*
* @param parse Parsing context.
- * @param tbl_name Table element.
- * @retval Table object if found, NULL otherwise.
+ * @param space_name Space element.
+ * @retval Space object if found, NULL otherwise.
*/
-struct Table *
-sql_lookup_table(struct Parse *parse, struct SrcList_item *tbl_name);
+struct space *
+sql_lookup_space(struct Parse *parse, struct SrcList_item *space_name);
/**
* Generate code for a DELETE FROM statement.
@@ -3603,10 +3581,11 @@ int sqlite3WhereOkOnePass(WhereInfo *, int *);
/**
* Generate code that will extract the iColumn-th column from
- * table pTab and store the column value in a register.
+ * table defined by space_def 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
+ * This is not guaranteed 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.
@@ -3622,8 +3601,8 @@ sqlite3ExprCodeGetColumn(Parse *, struct space_def *, int, int, int, u8);
/**
* Generate code that will extract the iColumn-th column from
- * table pTab and store the column value in a register, copy the
- * result.
+ * table defined by space_def 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.
@@ -3749,7 +3728,7 @@ int sqlite3ExprNeedsNoAffinityChange(const Expr *, char);
* of cursor should be preserved instead.
*
* @param parse Parsing context.
- * @param table Table containing the row to be deleted.
+ * @param space Space containing the row to be deleted.
* @param trigger_list List of triggers to (potentially) fire.
* @param cursor Cursor from which column data is extracted/
* @param reg_pk First memory cell containing the PRIMARY KEY.
@@ -3763,7 +3742,7 @@ int sqlite3ExprNeedsNoAffinityChange(const Expr *, char);
* to the index entry to be deleted.
*/
void
-sql_generate_row_delete(struct Parse *parse, struct Table *table,
+sql_generate_row_delete(struct Parse *parse, struct space *space,
struct sql_trigger *trigger_list, int cursor,
int reg_pk, short npk, bool need_update_count,
enum on_conflict_action onconf, u8 mode,
@@ -3854,7 +3833,7 @@ sql_generate_index_key(struct Parse *parse, struct index *index, int cursor,
* CHECK REPLACE Illegal. Results in an exception.
*
* @param parse_context Current parsing context.
- * @param tab The table being inserted or updated.
+ * @param space The space being inserted or updated.
* @param new_tuple_reg First register in a range holding values
* to insert.
* @param on_conflict On conflict error action of INSERT or
@@ -3865,7 +3844,7 @@ sql_generate_index_key(struct Parse *parse, struct index *index, int cursor,
*/
void
vdbe_emit_constraint_checks(struct Parse *parse_context,
- struct Table *tab, int new_tuple_reg,
+ struct space *space, int new_tuple_reg,
enum on_conflict_action on_conflict,
int ignore_label, int *upd_cols);
@@ -3985,19 +3964,21 @@ vdbe_code_drop_trigger(struct Parse *parser, const char *trigger_name,
bool account_changes);
/**
- * Return a list of all triggers on table pTab if there exists at
- * least one trigger that must be fired when an operation of type
- * 'op' is performed on the table, and, if that operation is an
- * UPDATE, if at least one of the columns in changes_list is being
- * modified.
- *
- * @param table The table the contains the triggers.
+ * Return a list of all triggers on space (represented with
+ * space_def) if there exists at least one trigger that must be
+ * fired when an operation of type 'op' is performed on the
+ * table, and, if that operation is an UPDATE, if at least one
+ * of the columns in changes_list is being modified.
+ *
+ * @param space_def The definition of the space that contains
+ * the triggers.
* @param op operation one of TK_DELETE, TK_INSERT, TK_UPDATE.
* @param changes_list Columns that change in an UPDATE statement.
* @param[out] pMask Mask of TRIGGER_BEFORE|TRIGGER_AFTER
*/
struct sql_trigger *
-sql_triggers_exist(struct Table *table, int op, struct ExprList *changes_list,
+sql_triggers_exist(struct space_def *space_def, int op,
+ struct ExprList *changes_list,
int *mask_ptr);
/**
@@ -4020,13 +4001,13 @@ sql_triggers_exist(struct Table *table, int op, struct ExprList *changes_list,
* Register Contains
* ------------------------------------------------------
* reg+0 OLD.PK
- * reg+1 OLD.* value of left-most column of pTab
+ * reg+1 OLD.* value of left-most column of space
* ... ...
- * reg+N OLD.* value of right-most column of pTab
+ * reg+N OLD.* value of right-most column of space
* reg+N+1 NEW.PK
- * reg+N+2 OLD.* value of left-most column of pTab
+ * reg+N+2 OLD.* value of left-most column of space
* ... ...
- * reg+N+N+1 NEW.* value of right-most column of pTab
+ * reg+N+N+1 NEW.* value of right-most column of space
*
* For ON DELETE triggers, the registers containing the NEW.*
* values will never be accessed by the trigger program, so they
@@ -4048,7 +4029,7 @@ sql_triggers_exist(struct Table *table, int op, struct ExprList *changes_list,
* @param op operation, one of TK_UPDATE, TK_INSERT, TK_DELETE.
* @param changes_list Changes list for any UPDATE OF triggers.
* @param tr_tm One of TRIGGER_BEFORE, TRIGGER_AFTER.
- * @param table The table to code triggers from.
+ * @param space The space to code triggers from.
* @param reg The first in an array of registers.
* @param orconf ON CONFLICT policy.
* @param ignore_jump Instruction to jump to for RAISE(IGNORE).
@@ -4056,7 +4037,7 @@ sql_triggers_exist(struct Table *table, int op, struct ExprList *changes_list,
void
vdbe_code_row_trigger(struct Parse *parser, struct sql_trigger *trigger,
int op, struct ExprList *changes_list, int tr_tm,
- struct Table *table, int reg, int orconf, int ignore_jump);
+ struct space *space, int reg, int orconf, int ignore_jump);
/**
* Generate code for the trigger program associated with trigger
@@ -4066,14 +4047,14 @@ vdbe_code_row_trigger(struct Parse *parser, struct sql_trigger *trigger,
*
* @param parser Parse context.
* @param trigger Trigger to code.
- * @param table The table to code triggers from.
+ * @param space The space to code triggers from.
* @param reg Reg array containing OLD.* and NEW.* values.
* @param orconf ON CONFLICT policy.
* @param ignore_jump Instruction to jump to for RAISE(IGNORE).
*/
void
vdbe_code_row_trigger_direct(struct Parse *parser, struct sql_trigger *trigger,
- struct Table *table, int reg, int orconf,
+ struct space *space, int reg, int orconf,
int ignore_jump);
void sqlite3DeleteTriggerStep(sqlite3 *, TriggerStep *);
@@ -4119,7 +4100,7 @@ TriggerStep *sqlite3TriggerDeleteStep(sqlite3 *, Token *, Expr *);
* @param changes_list Changes list for any UPDATE OF triggers.
* @param new 1 for new.* ref mask, 0 for old.* ref mask.
* @param tr_tm Mask of TRIGGER_BEFORE|TRIGGER_AFTER.
- * @param table The table to code triggers from.
+ * @param space The space to code triggers from.
* @param orconf Default ON CONFLICT policy for trigger steps.
*
* @retval mask value.
@@ -4127,7 +4108,7 @@ TriggerStep *sqlite3TriggerDeleteStep(sqlite3 *, Token *, Expr *);
u32
sql_trigger_colmask(Parse *parser, struct sql_trigger *trigger,
ExprList *changes_list, int new, int tr_tm,
- Table *table, int orconf);
+ struct space *space, int orconf);
#define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p))
#define sqlite3IsToplevel(p) ((p)->pToplevel==0)
@@ -4440,8 +4421,8 @@ int sqlite3ResolveOrderGroupBy(Parse *, Select *, ExprList *, const char *);
/**
* Generate code for default value.
* The most recently coded instruction was an OP_Column to retrieve the
- * i-th column of table pTab. This routine sets the P4 parameter of the
- * OP_Column to the default value, if any.
+ * i-th column of table defined by space_def. This routine sets
+ * the P4 parameter of the OP_Column to the default value, if any.
*
* The default value of a column is specified by a DEFAULT clause in the
* column definition. This was either supplied by the user when the table
@@ -4738,25 +4719,25 @@ void sqlite3WithPush(Parse *, With *, u8);
* inserted using the INSERT convention.
*
* @param parser SQL parser.
- * @param tab Table from which the row is deleted.
+ * @param space Space from which the row is deleted.
* @param reg_old Register with deleted row.
* @param reg_new Register with inserted row.
* @param changed_cols Array of updated columns. Can be NULL.
*/
void
-fkey_emit_check(struct Parse *parser, struct Table *tab, int reg_old,
+fkey_emit_check(struct Parse *parser, struct space *space, int reg_old,
int reg_new, const int *changed_cols);
/**
* Emit VDBE code to do CASCADE, SET NULL or SET DEFAULT actions
* when deleting or updating a row.
* @param parser SQL parser.
- * @param tab Table being updated or deleted from.
+ * @param space Space being updated or deleted from.
* @param reg_old Register of the old record.
* param changes Array of numbers of changed columns.
*/
void
-fkey_emit_actions(struct Parse *parser, struct Table *tab, int reg_old,
+fkey_emit_actions(struct Parse *parser, struct space *space, int reg_old,
const int *changes);
/**
diff --git a/src/box/sql/tarantoolInt.h b/src/box/sql/tarantoolInt.h
index 0aa31bdd6..4db541115 100644
--- a/src/box/sql/tarantoolInt.h
+++ b/src/box/sql/tarantoolInt.h
@@ -131,19 +131,19 @@ tarantoolSqlite3IncrementMaxid(uint64_t *space_max_id);
/**
* Encode format as entry to be inserted to _space on @region.
* @param region Region to use.
- * @param table Table to encode.
+ * @param table Space to encode.
* @param[out] size Size of result allocation.
*
* @retval NULL Error.
* @retval not NULL Pointer to msgpack on success.
*/
char *
-sql_encode_table(struct region *region, struct Table *table, uint32_t *size);
+sql_encode_table(struct region *region, struct space *space, uint32_t *size);
/**
* Encode "opts" dictionary for _space entry on @region.
* @param region Region to use.
- * @param table Table containing opts to encode.
+ * @param space Space containing opts to encode.
* @param sql Source request to encode.
* @param[out] size Size of result allocation.
*
@@ -151,7 +151,7 @@ sql_encode_table(struct region *region, struct Table *table, uint32_t *size);
* @retval not NULL Pointer to msgpack on success.
*/
char *
-sql_encode_table_opts(struct region *region, struct Table *table,
+sql_encode_table_opts(struct region *region, struct space *space,
const char *sql, uint32_t *size);
/**
diff --git a/src/box/sql/tokenize.c b/src/box/sql/tokenize.c
index 4eebfe527..5be4c57f6 100644
--- a/src/box/sql/tokenize.c
+++ b/src/box/sql/tokenize.c
@@ -449,7 +449,7 @@ sqlite3RunParser(Parse * pParse, const char *zSql, char **pzErrMsg)
sqlite3OomFault(db);
return SQLITE_NOMEM_BKPT;
}
- assert(pParse->pNewTable == 0);
+ assert(pParse->new_space == 0);
assert(pParse->parsed_ast.trigger == NULL);
assert(pParse->nVar == 0);
assert(pParse->pVList == 0);
@@ -529,16 +529,10 @@ sqlite3RunParser(Parse * pParse, const char *zSql, char **pzErrMsg)
sqlite3VdbeDelete(pParse->pVdbe);
pParse->pVdbe = 0;
}
- sqlite3DeleteTable(db, pParse->pNewTable);
-
+ sql_space_delete(db, pParse->new_space);
if (pParse->pWithToFree)
sqlite3WithDelete(db, pParse->pWithToFree);
sqlite3DbFree(db, pParse->pVList);
- while (pParse->pZombieTab) {
- Table *p = pParse->pZombieTab;
- pParse->pZombieTab = p->pNextZombie;
- sqlite3DeleteTable(db, p);
- }
assert(nErr == 0 || pParse->rc != SQLITE_OK);
return nErr;
}
diff --git a/src/box/sql/treeview.c b/src/box/sql/treeview.c
index f6a1755f4..a97ffdded 100644
--- a/src/box/sql/treeview.c
+++ b/src/box/sql/treeview.c
@@ -222,9 +222,9 @@ sqlite3TreeViewSelect(TreeView * pView, const Select * p, u8 moreToFollow)
if (pItem->zName) {
sqlite3XPrintf(&x, " %s", pItem->zName);
}
- if (pItem->pTab) {
+ if (pItem->space) {
sqlite3XPrintf(&x, " tabname=%Q",
- pItem->pTab->def->name);
+ pItem->space->def->name);
}
if (pItem->zAlias) {
sqlite3XPrintf(&x, " (AS %s)",
diff --git a/src/box/sql/trigger.c b/src/box/sql/trigger.c
index 7d5dc9e23..7f1d18342 100644
--- a/src/box/sql/trigger.c
+++ b/src/box/sql/trigger.c
@@ -558,14 +558,15 @@ checkColumnOverlap(IdList * pIdList, ExprList * pEList)
}
struct sql_trigger *
-sql_triggers_exist(struct Table *table, int op, struct ExprList *changes_list,
+sql_triggers_exist(struct space_def *space_def, int op,
+ struct ExprList *changes_list,
int *mask_ptr)
{
int mask = 0;
struct sql_trigger *trigger_list = NULL;
struct session *user_session = current_session();
if ((user_session->sql_flags & SQLITE_EnableTrigger) != 0)
- trigger_list = space_trigger_list(table->def->id);
+ trigger_list = space_trigger_list(space_def->id);
for (struct sql_trigger *p = trigger_list; p != NULL; p = p->next) {
if (p->op == op && checkColumnOverlap(p->pColumns,
changes_list) != 0)
@@ -614,7 +615,7 @@ codeTriggerProgram(Parse * pParse, /* The parser context */
Vdbe *v = pParse->pVdbe;
sqlite3 *db = pParse->db;
- assert(pParse->pTriggerTab && pParse->pToplevel);
+ assert(pParse->trigger_space && pParse->pToplevel);
assert(pStepList);
assert(v != 0);
@@ -748,7 +749,7 @@ transferParseError(Parse * pTo, Parse * pFrom)
*
* @param parser Current parse context.
* @param trigger sql_trigger to code.
- * @param table trigger is attached to.
+ * @param space Trigger is attached to.
* @param orconf ON CONFLICT policy to code trigger program with.
*
* @retval not NULL on success.
@@ -756,7 +757,7 @@ transferParseError(Parse * pTo, Parse * pFrom)
*/
static TriggerPrg *
sql_row_trigger_program(struct Parse *parser, struct sql_trigger *trigger,
- struct Table *table, int orconf)
+ struct space *space, int orconf)
{
Parse *pTop = sqlite3ParseToplevel(parser);
/* Database handle. */
@@ -768,7 +769,7 @@ sql_row_trigger_program(struct Parse *parser, struct sql_trigger *trigger,
Parse *pSubParse; /* Parse context for sub-vdbe */
int iEndTrigger = 0; /* Label to jump to if WHEN is false */
- assert(trigger->zName == NULL || table->def->id == trigger->space_id);
+ assert(trigger->zName == NULL || space->def->id == trigger->space_id);
assert(pTop->pVdbe);
/* Allocate the TriggerPrg and SubProgram objects. To ensure that they
@@ -799,7 +800,7 @@ sql_row_trigger_program(struct Parse *parser, struct sql_trigger *trigger,
sql_parser_create(pSubParse, db);
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pSubParse;
- pSubParse->pTriggerTab = table;
+ pSubParse->trigger_space = space;
pSubParse->pToplevel = pTop;
pSubParse->eTriggerOp = trigger->op;
pSubParse->nQueryLoop = parser->nQueryLoop;
@@ -814,7 +815,7 @@ sql_row_trigger_program(struct Parse *parser, struct sql_trigger *trigger,
(trigger->op == TK_UPDATE ? "UPDATE" : ""),
(trigger->op == TK_INSERT ? "INSERT" : ""),
(trigger->op == TK_DELETE ? "DELETE" : ""),
- table->def->name));
+ space->def->name));
#ifndef SQLITE_OMIT_TRACE
sqlite3VdbeChangeP4(v, -1,
sqlite3MPrintf(db, "-- TRIGGER %s",
@@ -864,7 +865,6 @@ sql_row_trigger_program(struct Parse *parser, struct sql_trigger *trigger,
sqlite3VdbeDelete(v);
}
- assert(!pSubParse->pZombieTab);
assert(!pSubParse->pTriggerPrg && !pSubParse->nMaxArg);
sql_parser_destroy(pSubParse);
sqlite3StackFree(db, pSubParse);
@@ -888,12 +888,12 @@ sql_row_trigger_program(struct Parse *parser, struct sql_trigger *trigger,
*/
static TriggerPrg *
sql_row_trigger(struct Parse *parser, struct sql_trigger *trigger,
- struct Table *table, int orconf)
+ struct space *space, int orconf)
{
Parse *pRoot = sqlite3ParseToplevel(parser);
TriggerPrg *pPrg;
- assert(trigger->zName == NULL || table->def->id == trigger->space_id);
+ assert(trigger->zName == NULL || space->def->id == trigger->space_id);
/*
* It may be that this trigger has already been coded (or
@@ -911,20 +911,20 @@ sql_row_trigger(struct Parse *parser, struct sql_trigger *trigger,
* a new one.
*/
if (pPrg == NULL)
- pPrg = sql_row_trigger_program(parser, trigger, table, orconf);
+ pPrg = sql_row_trigger_program(parser, trigger, space, orconf);
return pPrg;
}
void
vdbe_code_row_trigger_direct(struct Parse *parser, struct sql_trigger *trigger,
- struct Table *table, int reg, int orconf,
+ struct space *space, int reg, int orconf,
int ignore_jump)
{
/* Main VM. */
struct Vdbe *v = sqlite3GetVdbe(parser);
- TriggerPrg *pPrg = sql_row_trigger(parser, trigger, table, orconf);
+ TriggerPrg *pPrg = sql_row_trigger(parser, trigger, space, orconf);
assert(pPrg != NULL || parser->nErr != 0 ||
parser->db->mallocFailed != 0);
@@ -962,7 +962,7 @@ vdbe_code_row_trigger_direct(struct Parse *parser, struct sql_trigger *trigger,
void
vdbe_code_row_trigger(struct Parse *parser, struct sql_trigger *trigger,
int op, struct ExprList *changes_list, int tr_tm,
- struct Table *table, int reg, int orconf, int ignore_jump)
+ struct space *space, int reg, int orconf, int ignore_jump)
{
assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
assert(tr_tm == TRIGGER_BEFORE || tr_tm == TRIGGER_AFTER);
@@ -972,7 +972,7 @@ vdbe_code_row_trigger(struct Parse *parser, struct sql_trigger *trigger,
/* Determine whether we should code trigger. */
if (p->op == op && p->tr_tm == tr_tm &&
checkColumnOverlap(p->pColumns, changes_list)) {
- vdbe_code_row_trigger_direct(parser, p, table, reg,
+ vdbe_code_row_trigger_direct(parser, p, space, reg,
orconf, ignore_jump);
}
}
@@ -981,7 +981,7 @@ vdbe_code_row_trigger(struct Parse *parser, struct sql_trigger *trigger,
u32
sql_trigger_colmask(Parse *parser, struct sql_trigger *trigger,
ExprList *changes_list, int new, int tr_tm,
- Table *table, int orconf)
+ struct space *space, int orconf)
{
const int op = changes_list != NULL ? TK_UPDATE : TK_DELETE;
u32 mask = 0;
@@ -991,7 +991,7 @@ sql_trigger_colmask(Parse *parser, struct sql_trigger *trigger,
if (p->op == op && (tr_tm & p->tr_tm)
&& checkColumnOverlap(p->pColumns, changes_list)) {
TriggerPrg *prg =
- sql_row_trigger(parser, p, table, orconf);
+ sql_row_trigger(parser, p, space, orconf);
if (prg != NULL)
mask |= prg->aColmask[new];
}
diff --git a/src/box/sql/update.c b/src/box/sql/update.c
index dbef22fd8..3b7122360 100644
--- a/src/box/sql/update.c
+++ b/src/box/sql/update.c
@@ -81,7 +81,6 @@ sqlite3Update(Parse * pParse, /* The parser context */
enum on_conflict_action on_error)
{
int i, j; /* Loop counters */
- Table *pTab; /* The table to be updated */
int addrTop = 0; /* VDBE instruction address of the start of the loop */
WhereInfo *pWInfo; /* Information about the WHERE clause */
Vdbe *v; /* The virtual database engine */
@@ -124,32 +123,32 @@ sqlite3Update(Parse * pParse, /* The parser context */
/* Locate the table which we want to update.
*/
- pTab = sql_lookup_table(pParse, pTabList->a);
- if (pTab == NULL)
+ struct space *space = sql_lookup_space(pParse, pTabList->a);
+ if (space == NULL)
goto update_cleanup;
/* Figure out if we have any triggers and if the table being
* updated is a view.
*/
- trigger = sql_triggers_exist(pTab, TK_UPDATE, pChanges, &tmask);
- is_view = pTab->def->opts.is_view;
+ trigger = sql_triggers_exist(space->def, TK_UPDATE, pChanges, &tmask);
+ is_view = space->def->opts.is_view;
assert(trigger != NULL || tmask == 0);
if (is_view &&
- sql_view_assign_cursors(pParse,pTab->def->opts.sql) != 0) {
+ sql_view_assign_cursors(pParse, space->def->opts.sql) != 0) {
goto update_cleanup;
}
if (is_view && tmask == 0) {
sqlite3ErrorMsg(pParse, "cannot modify %s because it is a view",
- pTab->def->name);
+ space->def->name);
goto update_cleanup;
}
- struct space_def *def = pTab->def;
+ struct space_def *def = space->def;
/* Allocate cursor on primary index. */
int pk_cursor = pParse->nTab++;
pTabList->a[0].iCursor = pk_cursor;
- struct index *pPk = space_index(pTab->space, 0);
+ struct index *pPk = space_index(space, 0);
i = sizeof(int) * def->field_count;
aXRef = (int *) region_alloc(&pParse->region, i);
if (aXRef == NULL) {
@@ -176,7 +175,7 @@ sqlite3Update(Parse * pParse, /* The parser context */
if (strcmp(def->fields[j].name,
pChanges->a[i].zName) == 0) {
if (pPk &&
- sql_space_column_is_in_pk(pTab->space, j))
+ sql_space_column_is_in_pk(space, j))
is_pk_modified = true;
if (aXRef[j] != -1) {
sqlite3ErrorMsg(pParse,
@@ -202,7 +201,7 @@ sqlite3Update(Parse * pParse, /* The parser context */
*/
pTabList->a[0].colUsed = 0;
- hasFK = fkey_is_required(pTab->def->id, aXRef);
+ hasFK = fkey_is_required(space->def->id, aXRef);
/* Begin generating code. */
v = sqlite3GetVdbe(pParse);
@@ -226,13 +225,11 @@ sqlite3Update(Parse * pParse, /* The parser context */
* an ephemeral table.
*/
uint32_t pk_part_count;
- struct space *space;
if (is_view) {
sql_materialize_view(pParse, def->name, pWhere, pk_cursor);
/* Number of columns from SELECT plus ID.*/
pk_part_count = nKey = def->field_count + 1;
} else {
- space = pTab->space;
assert(space != NULL);
vdbe_emit_open_cursor(pParse, pk_cursor, 0, space);
pk_part_count = pPk->def->key_def->part_count;
@@ -298,7 +295,7 @@ sqlite3Update(Parse * pParse, /* The parser context */
/* Initialize the count of updated rows
*/
if ((user_session->sql_flags & SQLITE_CountRows)
- && !pParse->pTriggerTab) {
+ && !pParse->trigger_space) {
regRowCount = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
}
@@ -333,16 +330,15 @@ sqlite3Update(Parse * pParse, /* The parser context */
* information is needed
*/
if (is_pk_modified || hasFK != 0 || trigger != NULL) {
- struct space *space = space_by_id(pTab->def->id);
assert(space != NULL);
u32 oldmask = hasFK ? space->fkey_mask : 0;
oldmask |= sql_trigger_colmask(pParse, trigger, pChanges, 0,
TRIGGER_BEFORE | TRIGGER_AFTER,
- pTab, on_error);
+ space, on_error);
for (i = 0; i < (int)def->field_count; i++) {
if (oldmask == 0xffffffff
|| (i < 32 && (oldmask & MASKBIT32(i)) != 0) ||
- sql_space_column_is_in_pk(pTab->space, i)) {
+ sql_space_column_is_in_pk(space, i)) {
testcase(oldmask != 0xffffffff && i == 31);
sqlite3ExprCodeGetColumnOfTable(v, def,
pk_cursor, i,
@@ -368,7 +364,7 @@ sqlite3Update(Parse * pParse, /* The parser context */
* be used eliminates some redundant opcodes.
*/
newmask = sql_trigger_colmask(pParse, trigger, pChanges, 1,
- TRIGGER_BEFORE, pTab, on_error);
+ TRIGGER_BEFORE, space, on_error);
for (i = 0; i < (int)def->field_count; i++) {
j = aXRef[i];
if (j >= 0) {
@@ -394,9 +390,9 @@ sqlite3Update(Parse * pParse, /* The parser context */
* verified. One could argue that this is wrong.
*/
if (tmask & TRIGGER_BEFORE) {
- sql_emit_table_affinity(v, pTab->def, regNew);
+ sql_emit_table_affinity(v, space->def, regNew);
vdbe_code_row_trigger(pParse, trigger, TK_UPDATE, pChanges,
- TRIGGER_BEFORE, pTab, regOldPk,
+ TRIGGER_BEFORE, space, regOldPk,
on_error, labelContinue);
/* The row-trigger may have deleted the row being updated. In this
@@ -431,11 +427,11 @@ sqlite3Update(Parse * pParse, /* The parser context */
if (!is_view) {
assert(regOldPk > 0);
- vdbe_emit_constraint_checks(pParse, pTab, regNewPk + 1,
+ vdbe_emit_constraint_checks(pParse, space, regNewPk + 1,
on_error, labelContinue, aXRef);
/* Do FK constraint checks. */
if (hasFK) {
- fkey_emit_check(pParse, pTab, regOldPk, 0, aXRef);
+ fkey_emit_check(pParse, space, regOldPk, 0, aXRef);
}
if (on_error == ON_CONFLICT_ACTION_REPLACE) {
/*
@@ -451,11 +447,11 @@ sqlite3Update(Parse * pParse, /* The parser context */
sqlite3VdbeJumpHere(v, not_found_lbl);
}
if (hasFK) {
- fkey_emit_check(pParse, pTab, 0, regNewPk, aXRef);
+ fkey_emit_check(pParse, space, 0, regNewPk, aXRef);
}
if (on_error == ON_CONFLICT_ACTION_REPLACE) {
vdbe_emit_insertion_completion(v, space, regNew,
- pTab->def->field_count,
+ space->def->field_count,
on_error);
} else {
@@ -501,18 +497,18 @@ sqlite3Update(Parse * pParse, /* The parser context */
* via a foreign key to the row just updated.
*/
if (hasFK)
- fkey_emit_actions(pParse, pTab, regOldPk, aXRef);
+ fkey_emit_actions(pParse, space, regOldPk, aXRef);
}
/* Increment the row counter
*/
if ((user_session->sql_flags & SQLITE_CountRows)
- && !pParse->pTriggerTab) {
+ && !pParse->trigger_space) {
sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);
}
vdbe_code_row_trigger(pParse, trigger, TK_UPDATE, pChanges,
- TRIGGER_AFTER, pTab, regOldPk, on_error,
+ TRIGGER_AFTER, space, regOldPk, on_error,
labelContinue);
/* Repeat the above with the next record to be updated, until
@@ -529,7 +525,7 @@ sqlite3Update(Parse * pParse, /* The parser context */
/* Return the number of rows that were changed. */
if (user_session->sql_flags & SQLITE_CountRows &&
- pParse->pTriggerTab == NULL) {
+ pParse->trigger_space == NULL) {
sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated",
diff --git a/src/box/sql/where.c b/src/box/sql/where.c
index 571b5af78..c26661a20 100644
--- a/src/box/sql/where.c
+++ b/src/box/sql/where.c
@@ -580,7 +580,6 @@ isDistinctRedundant(Parse * pParse, /* Parsing context */
WhereClause * pWC, /* The WHERE clause */
ExprList * pDistinct) /* The result set that needs to be DISTINCT */
{
- Table *pTab;
int iBase;
/* If there is more than one table or sub-select in the FROM clause of
@@ -590,7 +589,7 @@ isDistinctRedundant(Parse * pParse, /* Parsing context */
if (pTabList->nSrc != 1)
return 0;
iBase = pTabList->a[0].iCursor;
- pTab = pTabList->a[0].pTab;
+ struct space *space = pTabList->a[0].space;
/* If any of the expressions is an IPK column on table iBase, then return
* true. Note: The (p->iTable==iBase) part of this test may be false if the
@@ -601,7 +600,7 @@ isDistinctRedundant(Parse * pParse, /* Parsing context */
if (p->op == TK_COLUMN && p->iTable == iBase && p->iColumn < 0)
return 1;
}
- if (pTab->space == NULL)
+ if (space == NULL)
return 0;
/* Loop through all indices on the table, checking each to see if it makes
* the DISTINCT qualifier redundant. It does so if:
@@ -616,8 +615,8 @@ isDistinctRedundant(Parse * pParse, /* Parsing context */
* 3. All of those index columns for which the WHERE clause does not
* contain a "col=X" term are subject to a NOT NULL constraint.
*/
- for (uint32_t j = 0; j < pTab->space->index_count; ++j) {
- struct index_def *def = pTab->space->index[j]->def;
+ for (uint32_t j = 0; j < space->index_count; ++j) {
+ struct index_def *def = space->index[j]->def;
if (!def->opts.is_unique)
continue;
uint32_t col_count = def->key_def->part_count;
@@ -629,7 +628,7 @@ isDistinctRedundant(Parse * pParse, /* Parsing context */
i) < 0)
break;
uint32_t x = def->key_def->parts[i].fieldno;
- if (pTab->def->fields[x].is_nullable)
+ if (space->def->fields[x].is_nullable)
break;
}
}
@@ -1685,13 +1684,13 @@ whereLoopPrint(WhereLoop * p, WhereClause * pWC)
WhereInfo *pWInfo = pWC->pWInfo;
int nb = 1 + (pWInfo->pTabList->nSrc + 3) / 4;
struct SrcList_item *pItem = pWInfo->pTabList->a + p->iTab;
- Table *pTab = pItem->pTab;
+ struct space_def *space_def = pItem->space->def;
Bitmask mAll = (((Bitmask) 1) << (nb * 4)) - 1;
#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->def->name);
+ pItem->zAlias ? pItem->zAlias : space_def->name);
#endif
const char *zName;
if (p->index_def != NULL && (zName = p->index_def->name) != NULL) {
@@ -2778,20 +2777,19 @@ whereLoopAddBtree(WhereLoopBuilder * pBuilder, /* WHERE clause information */
int b; /* A boolean value */
LogEst rSize; /* number of rows in the table */
WhereClause *pWC; /* The parsed WHERE clause */
- Table *pTab; /* Table being queried */
pNew = pBuilder->pNew;
pWInfo = pBuilder->pWInfo;
pTabList = pWInfo->pTabList;
pSrc = pTabList->a + pNew->iTab;
- pTab = pSrc->pTab;
pWC = pBuilder->pWC;
+ struct space *space = pSrc->space;
if (pSrc->pIBIndex) {
/* An INDEXED BY clause specifies a particular index to use */
probe = pSrc->pIBIndex;
- } else if (pTab->space->index_count != 0) {
- probe = pTab->space->index[0]->def;
+ } else if (space->index_count != 0) {
+ probe = space->index[0]->def;
} else {
/* There is no INDEXED BY clause. Create a fake Index object in local
* variable fake_index to represent the primary key index. Make this
@@ -2802,7 +2800,7 @@ whereLoopAddBtree(WhereLoopBuilder * pBuilder, /* WHERE clause information */
struct key_part_def part;
part.fieldno = 0;
- part.type = pTab->def->fields[0].type;
+ part.type = space->def->fields[0].type;
part.nullable_action = ON_CONFLICT_ACTION_ABORT;
part.is_nullable = false;
part.sort_order = SORT_ORDER_ASC;
@@ -2818,7 +2816,7 @@ tnt_error:
struct index_opts opts;
index_opts_create(&opts);
- fake_index = index_def_new(pTab->def->id, 0,"fake_autoindex",
+ fake_index = index_def_new(space->def->id, 0,"fake_autoindex",
sizeof("fake_autoindex") - 1,
TREE, &opts, key_def, NULL);
key_def_delete(key_def);
@@ -2834,7 +2832,7 @@ tnt_error:
goto tnt_error;
}
stat->tuple_log_est = (log_est_t *) ((char *) (stat + 1));
- stat->tuple_log_est[0] = sql_space_tuple_log_count(pTab);
+ stat->tuple_log_est[0] = sql_space_tuple_log_count(pSrc->space);
stat->tuple_log_est[1] = 0;
fake_index->opts.stat = stat;
@@ -2901,10 +2899,10 @@ tnt_error:
* index is considered.
*/
uint32_t idx_count = fake_index == NULL || pSrc->pIBIndex != NULL ?
- pTab->space->index_count : 1;
+ space->index_count : 1;
for (uint32_t i = 0; i < idx_count; iSortIdx++, i++) {
if (i > 0)
- probe = pTab->space->index[i]->def;
+ probe = space->index[i]->def;
rSize = index_field_tuple_est(probe, 0);
pNew->nEq = 0;
pNew->nBtm = 0;
@@ -4083,7 +4081,7 @@ where_loop_builder_shortcut(struct WhereLoopBuilder *builder)
return 0;
assert(where_info->pTabList->nSrc >= 1);
struct SrcList_item *item = where_info->pTabList->a;
- struct space_def *space_def = item->pTab->def;
+ struct space_def *space_def = item->space->def;
assert(space_def != NULL);
if (item->fg.isIndexedBy)
return 0;
@@ -4559,10 +4557,10 @@ sqlite3WhereBegin(Parse * pParse, /* The parser context */
*/
for (ii = 0, pLevel = pWInfo->a; ii < nTabList; ii++, pLevel++) {
struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
- Table *pTab = pTabItem->pTab;
+ struct space_def *space_def = pTabItem->space->def;
pLoop = pLevel->pWLoop;
- struct space *space = space_cache_find(pTabItem->pTab->def->id);
- if (pTab->def->id == 0 || pTab->def->opts.is_view) {
+ struct space *space = space_cache_find(space_def->id);
+ if (space_def->id == 0 || space_def->opts.is_view) {
/* Do nothing */
} else if ((pLoop->wsFlags & WHERE_IDX_ONLY) == 0 &&
(wctrlFlags & WHERE_OR_SUBCLAUSE) == 0) {
@@ -4573,10 +4571,6 @@ sqlite3WhereBegin(Parse * pParse, /* The parser context */
space);
VdbeComment((v, "%s", space->def->name));
assert(pTabItem->iCursor == pLevel->iTabCur);
- testcase(pWInfo->eOnePass == ONEPASS_OFF
- && pTab->nCol == BMS - 1);
- testcase(pWInfo->eOnePass == ONEPASS_OFF
- && pTab->nCol == BMS);
sqlite3VdbeChangeP5(v, bFordelete);
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed,
@@ -4612,15 +4606,16 @@ sqlite3WhereBegin(Parse * pParse, /* The parser context */
op = 0;
} else if (pWInfo->eOnePass != ONEPASS_OFF) {
iIndexCur = iAuxArg;
- if (pTabItem->pTab->space->index_count != 0) {
+ if (pTabItem->space->index_count != 0) {
uint32_t iid = 0;
- struct index *pJ = pTabItem->pTab->space->index[iid];
+ struct index *pJ =
+ pTabItem->space->index[iid];
assert(wctrlFlags &
WHERE_ONEPASS_DESIRED);
while (pJ->def->iid != idx_def->iid) {
iIndexCur++;
iid++;
- pJ = pTabItem->pTab->space->index[iid];
+ pJ = pTabItem->space->index[iid];
}
} else {
for(uint32_t i = 0;
@@ -4825,7 +4820,7 @@ sqlite3WhereEnd(WhereInfo * pWInfo)
sqlite3VdbeJumpHere(v, addr);
}
VdbeModuleComment((v, "End WHERE-loop%d: %s", i,
- pWInfo->pTabList->a[pLevel->iFrom].pTab->
+ pWInfo->pTabList->a[pLevel->iFrom].space->
def->name));
}
@@ -4839,8 +4834,7 @@ sqlite3WhereEnd(WhereInfo * pWInfo)
int k, last;
VdbeOp *pOp;
struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
- Table *pTab MAYBE_UNUSED = pTabItem->pTab;
- assert(pTab != 0);
+ assert(pTabItem->space != 0);
pLoop = pLevel->pWLoop;
/* For a co-routine, change all OP_Column references to the table of
@@ -4880,7 +4874,8 @@ sqlite3WhereEnd(WhereInfo * pWInfo)
if (pOp->opcode == OP_Column) {
int x = pOp->p2;
assert(def == NULL ||
- def->space_id == pTab->def->id);
+ def->space_id ==
+ pTabItem->space->def->id);
if (x >= 0) {
pOp->p2 = x;
pOp->p1 = pLevel->iIdxCur;
diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
index b124a1d53..631e40b02 100644
--- a/src/box/sql/wherecode.c
+++ b/src/box/sql/wherecode.c
@@ -934,7 +934,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->def->name));
+ VdbeComment((v, "next row of \"%s\"", pTabItem->space->def->name));
pLevel->op = OP_Goto;
} else if (pLoop->wsFlags & WHERE_INDEXED) {
/* Case 4: A scan using an index.
@@ -1353,9 +1353,9 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo, /* Complete information about t
int ii; /* Loop counter */
u16 wctrlFlags; /* Flags for sub-WHERE clause */
Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
- Table *pTab = pTabItem->pTab;
+ struct space *space = pTabItem->space;
struct key_def *pk_key_def =
- space_index(pTab->space, 0)->def->key_def;
+ space_index(space, 0)->def->key_def;
uint32_t pk_part_count = pk_key_def->part_count;
pTerm = pLoop->aLTerm[0];
@@ -1520,7 +1520,7 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo, /* Complete information about t
fieldno;
sqlite3ExprCodeGetColumnToReg
(pParse,
- pTab->def,
+ space->def,
fieldno,
iCur,
r + iPk);
diff --git a/src/box/sql/whereexpr.c b/src/box/sql/whereexpr.c
index 342064ec8..b1efff558 100644
--- a/src/box/sql/whereexpr.c
+++ b/src/box/sql/whereexpr.c
@@ -1477,26 +1477,23 @@ sqlite3WhereTabFuncArgs(Parse * pParse, /* Parsing context */
WhereClause * pWC /* Xfer function arguments to here */
)
{
- Table *pTab;
int j, k;
ExprList *pArgs;
Expr *pColRef;
Expr *pTerm;
if (pItem->fg.isTabFunc == 0)
return;
- pTab = pItem->pTab;
- assert(pTab != 0);
+ struct space_def *space_def = pItem->space->def;
pArgs = pItem->u1.pFuncArg;
if (pArgs == 0)
return;
for (j = k = 0; j < pArgs->nExpr; j++) {
- while (k < (int)pTab->def->field_count) {
+ while (k < (int)space_def->field_count)
k++;
- }
- if (k >= (int)pTab->def->field_count) {
+ if (k >= (int)space_def->field_count) {
sqlite3ErrorMsg(pParse,
"too many arguments on %s() - max %d",
- pTab->def->name, j);
+ space_def->name, j);
return;
}
pColRef = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0);
@@ -1504,7 +1501,7 @@ sqlite3WhereTabFuncArgs(Parse * pParse, /* Parsing context */
return;
pColRef->iTable = pItem->iCursor;
pColRef->iColumn = k++;
- pColRef->space_def = pTab->def;
+ pColRef->space_def = space_def;
pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef,
sqlite3ExprDup(pParse->db,
pArgs->a[j].pExpr, 0));
--
2.14.3 (Apple Git-98)
</pre>
</body>
</html>