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: https://github.com/tarantool/tarantool/tree/sudobobo/gh-3235-repl-Table-w-space Issue: https://github.com/tarantool/tarantool/issues/3235 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)