[tarantool-patches] Re: [PATCH 09/10] sql: disable ON CONFLICT actions for indexes
n.pettik
korablev at tarantool.org
Tue Aug 21 19:31:37 MSK 2018
>> diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
>> index cb120384a..271886ec6 100644
>> --- a/src/box/sql/insert.c
>> +++ b/src/box/sql/insert.c
>> +vdbe_emit_constraint_checks(struct Parse *parse_context, struct Table *tab,
>> + int new_tuple_reg,
>> + enum on_conflict_action on_conflict,
>> + int ignore_label, int *upd_cols)
>> {
>> - Vdbe *v; /* VDBE under constrution */
>> - Index *pIdx; /* Pointer to one of the indices */
>> - Index *pPk = 0; /* The PRIMARY KEY index */
>> - sqlite3 *db; /* Database connection */
>> - int addr1; /* Address of jump instruction */
>> - int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
>> - u8 isUpdate; /* True if this is an UPDATE operation */
>> - u8 bAffinityDone = 0; /* True if the OP_Affinity operation has been run */
>> struct session *user_session = current_session();
>> -
>> - isUpdate = regOldData != 0;
>> - db = pParse->db;
>> - v = sqlite3GetVdbe(pParse);
>> - assert(v != 0);
>> - struct space_def *def = pTab->def;
>> - /* This table is not a VIEW */
>> + struct sqlite3 *db = parse_context->db;
>> + struct Vdbe *v = sqlite3GetVdbe(parse_context);
>> + assert(v != NULL);
>> + struct space_def *def = tab->def;
>> + /* Insertion into VIEW is prohibited. */
>> assert(!def->opts.is_view);
>> -
>> - pPk = sqlite3PrimaryKeyIndex(pTab);
>> -
>> - /* Record that this module has started */
>> - VdbeModuleComment((v, "BEGIN: GenCnstCks(%d,%d,%d,%d,%d)",
>> - iDataCur, iIdxCur, regNewData, regOldData, pkChng));
>> -
>> - enum on_conflict_action override_error = on_conflict->override_error;
>> - enum on_conflict_action on_error;
>> - /* Test all NOT NULL constraints.
>> - */
>> + bool is_update = upd_cols != NULL;
>> + /* Test all NOT NULL constraints. */
>> for (uint32_t i = 0; i < def->field_count; i++) {
>> - if (aiChng && aiChng[i] < 0) {
>> - /* Don't bother checking for NOT NULL on columns that do not change */
>> + /*
>> + * Don't bother checking for NOT NULL on columns
>> + * that do not change.
>> + */
>> + if (is_update && upd_cols[i] < 0)
>> continue;
>> - }
>> - if (def->fields[i].is_nullable || pTab->iAutoIncPKey == (int) i)
>> - continue; /* This column is allowed to be NULL */
>> -
>> - on_error = table_column_nullable_action(pTab, i);
>> - if (override_error != ON_CONFLICT_ACTION_DEFAULT)
>> - on_error = override_error;
>> - /* ABORT is a default error action */
>> - if (on_error == ON_CONFLICT_ACTION_DEFAULT)
>> - on_error = ON_CONFLICT_ACTION_ABORT;
>> -
>> - struct Expr *dflt = NULL;
>> - dflt = space_column_default_expr(pTab->def->id, i);
>> - if (on_error == ON_CONFLICT_ACTION_REPLACE && dflt == 0)
>> - on_error = ON_CONFLICT_ACTION_ABORT;
>> -
>> - assert(on_error != ON_CONFLICT_ACTION_NONE);
>> - switch (on_error) {
>> + /* This column is allowed to be NULL. */
>> + if (def->fields[i].is_nullable || tab->iAutoIncPKey == (int) i)
>> + continue;
>> + enum on_conflict_action on_conflict_nullable =
>> + on_conflict != ON_CONFLICT_ACTION_DEFAULT ?
>> + on_conflict : table_column_nullable_action(tab, i);
>
> 1. Can you remove table_column_nullable_action? It is the single place of its
> usage. You can do space_by_id once at the begin of the function and use
> the space explicitly both here and below for space_checks_expr_list (that
> also would be removed in such a case).
Ok, surely. Space is not even required here, we can fetch nullable action
from table->def:
+++ b/src/box/sql/insert.c
@@ -859,7 +859,7 @@ vdbe_emit_constraint_checks(struct Parse *parse_context, struct Table *tab,
continue;
enum on_conflict_action on_conflict_nullable =
on_conflict != ON_CONFLICT_ACTION_DEFAULT ?
- on_conflict : table_column_nullable_action(tab, i);
+ on_conflict : tab->def->fields[i].nullable_action;
@@ -4796,9 +4858,6 @@ extern int sqlSubProgramsRemaining;
extern int sqlite3InitDatabase(sqlite3 * db);
-enum on_conflict_action
-table_column_nullable_action(struct Table *tab, uint32_t column);
-
+++ b/src/box/sql/vdbeaux.c
@@ -3869,30 +3869,3 @@ sqlite3VdbeRecordUnpackMsgpack(struct key_def *key_def, /* Information about the
pMem++;
}
}
-
-/**
- * Return action on nullable constraint violation of given column in given table.
- * FIXME: This is implemented in expensive way. For each invocation table lookup
- * is performed. In future, first param will be replaced with pointer to struct
- * space.
- *
- * @param tab pointer to the table
- * @param column column number for which action to be returned
- * @retval return action found for given column
- */
-enum on_conflict_action
-table_column_nullable_action(struct Table *tab, uint32_t column)
-{
- struct space *space = space_cache_find(tab->def->id);
-
- assert(space != NULL);
-
- struct tuple_format *format = space->format;
-
- assert(format != NULL);
- assert(format->field_count > column);
-
- struct tuple_field field = format->fields[column];
-
- return field.nullable_action;
-}
>> --- a/src/box/sql/update.c
>> +++ b/src/box/sql/update.c
>> @@ -152,34 +144,17 @@ sqlite3Update(Parse * pParse, /* The parser context */
>> }
>> struct space_def *def = pTab->def;
>> -
>> - /* Allocate a cursors for the main database table and for all indices.
>> - * The index cursors might not be used, but if they are used they
>> - * need to occur right after the database cursor. So go ahead and
>> - * allocate enough space, just in case.
>> - */
>> - pTabList->a[0].iCursor = iBaseCur = iDataCur = pParse->nTab++;
>> - iIdxCur = iDataCur + 1;
>> - pPk = is_view ? 0 : sqlite3PrimaryKeyIndex(pTab);
>> - for (nIdx = 0, pIdx = pTab->pIndex; pIdx; pIdx = pIdx->pNext, nIdx++) {
>> - if (sql_index_is_primary(pIdx) && pPk != 0) {
>> - iDataCur = pParse->nTab;
>> - pTabList->a[0].iCursor = iDataCur;
>> - }
>> - pParse->nTab++;
>> - }
>> -
>> - /* Allocate space for aXRef[], aRegIdx[], and aToOpen[].
>> - * Initialize aXRef[] and aToOpen[] to their default values.
>> - */
>> - aXRef = sqlite3DbMallocRawNN(db, sizeof(int) *
>> - (def->field_count + nIdx) + nIdx + 2);
>> - if (aXRef == 0)
>> + int nIdx = 0;
>> + for (struct Index *idx = pTab->pIndex; idx != NULL;
>> + idx = idx->pNext, nIdx++);
>
> 2. In the same function below we do space_by_id from the
> result of which we can get space->index_count. It is not?
Well, it is useless code, actually. I forgot to remove it:
+++ b/src/box/sql/update.c
@@ -144,9 +144,6 @@ sqlite3Update(Parse * pParse, /* The parser context */
}
struct space_def *def = pTab->def;
- int nIdx = 0;
- for (struct Index *idx = pTab->pIndex; idx != NULL;
- idx = idx->pNext, nIdx++);
More information about the Tarantool-patches
mailing list