From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtpng2.m.smailru.net (smtpng2.m.smailru.net [94.100.179.3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 731A94696C4 for ; Tue, 3 Mar 2020 13:12:08 +0300 (MSK) From: Roman Khabibov Date: Tue, 3 Mar 2020 13:12:03 +0300 Message-Id: <20200303101204.16338-3-roman.habibov@tarantool.org> In-Reply-To: <20200303101204.16338-1-roman.habibov@tarantool.org> References: <20200303101204.16338-1-roman.habibov@tarantool.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [Tarantool-patches] [PATCH v2 2/3] sql: don't select from _index during parsing List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: v.shpilevoy@tarantool.org Cc: tarantool-patches@dev.tarantool.org Remove function box_index_by_name() from parser to avoid selects during parsing. Add the ability to choose index during VDBE code compilation which will be used to find the tuple to drop from a system space. Needed for #4120 --- src/box/space.h | 15 +++++++++++ src/box/sql/build.c | 59 +++++++++++++++++++++++++++----------------- src/box/sql/pragma.c | 8 ++---- src/box/sql/vdbe.c | 10 +++++--- 4 files changed, 59 insertions(+), 33 deletions(-) diff --git a/src/box/space.h b/src/box/space.h index 9aea4e5be..28885d037 100644 --- a/src/box/space.h +++ b/src/box/space.h @@ -287,6 +287,21 @@ space_index(struct space *space, uint32_t id) return NULL; } +/** + * Get index by index name. + * @return NULL if the index is not found. + */ +static inline struct index * +space_index_by_name(struct space *space, const char *index_name) +{ + for(uint32_t i = 0; i < space->index_count; i++) { + struct index *index = space->index[i]; + if (strcmp(index_name, index->def->name) == 0) + return index; + } + return NULL; +} + /** * Return true if the unique constraint must be checked for * the index with the given id before inserting a tuple into diff --git a/src/box/sql/build.c b/src/box/sql/build.c index d9bf8de91..e0f690fc2 100644 --- a/src/box/sql/build.c +++ b/src/box/sql/build.c @@ -47,7 +47,6 @@ #include "sqlInt.h" #include "vdbeInt.h" #include "tarantoolInt.h" -#include "box/box.h" #include "box/ck_constraint.h" #include "box/fk_constraint.h" #include "box/sequence.h" @@ -1469,6 +1468,40 @@ vdbe_emit_stat_space_clear(struct Parse *parse, const char *stat_table_name, sql_table_delete_from(parse, src_list, where); } +/** + * Generate VDBE program to remove entry from _index space. + * + * @param parse_context Parsing context. + * @param name Index name. + * @param space_def Def of table which index belongs to. + * @param errcode Type of printing error: "no such index" or + * "no such constraint". + * @param if_exist True if there was in the query. + */ +static void +vdbe_emit_index_drop(struct Parse *parse_context, const char *name, + struct space_def *space_def, int errcode, bool if_exist) +{ + assert(errcode == ER_NO_SUCH_INDEX_NAME || + errcode == ER_NO_SUCH_CONSTRAINT); + struct Vdbe *vdbe = sqlGetVdbe(parse_context); + assert(vdbe != NULL); + assert(parse_context->db != NULL); + int key_reg = sqlGetTempRange(parse_context, 3); + sqlVdbeAddOp2(vdbe, OP_Integer, space_def->id, key_reg); + sqlVdbeAddOp4(vdbe, OP_String8, 0, key_reg + 1, 0, + sqlDbStrDup(parse_context->db, name), P4_DYNAMIC); + const char *error_msg = + tt_sprintf(tnt_errcode_desc(errcode), name, space_def->name); + if (vdbe_emit_halt_with_presence_test(parse_context, BOX_INDEX_ID, 2, + key_reg, 2, errcode, error_msg, + if_exist, OP_Found) != 0) + return; + sqlVdbeAddOp3(vdbe, OP_MakeRecord, key_reg, 2, key_reg + 2); + sqlVdbeAddOp3(vdbe, OP_SDelete, BOX_INDEX_ID, key_reg + 2, 2); + sqlReleaseTempRange(parse_context, key_reg, 3); +} + /** * Generate VDBE program to remove entry from _fk_constraint space. * @@ -2695,29 +2728,9 @@ sql_drop_index(struct Parse *parse_context) parse_context->is_aborted = true; goto exit_drop_index; } - uint32_t index_id = box_index_id_by_name(space->def->id, index_name, - strlen(index_name)); - if (index_id == BOX_ID_NIL) { - if (!if_exists) { - diag_set(ClientError, ER_NO_SUCH_INDEX_NAME, - index_name, table_name); - parse_context->is_aborted = true; - } - goto exit_drop_index; - } - /* - * Generate code to remove entry from _index space - * But firstly, delete statistics since schema - * changes after DDL. - */ - int record_reg = ++parse_context->nMem; - int space_id_reg = ++parse_context->nMem; - int index_id_reg = ++parse_context->nMem; - sqlVdbeAddOp2(v, OP_Integer, space->def->id, space_id_reg); - sqlVdbeAddOp2(v, OP_Integer, index_id, index_id_reg); - sqlVdbeAddOp3(v, OP_MakeRecord, space_id_reg, 2, record_reg); - sqlVdbeAddOp2(v, OP_SDelete, BOX_INDEX_ID, record_reg); + vdbe_emit_index_drop(parse_context, index_name, space->def, + ER_NO_SUCH_INDEX_NAME, if_exists); sqlVdbeChangeP5(v, OPFLAG_NCHANGE); exit_drop_index: sqlSrcListDelete(db, table_list); diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c index a77bf4b16..c15f2e0d1 100644 --- a/src/box/sql/pragma.c +++ b/src/box/sql/pragma.c @@ -33,7 +33,6 @@ * This file contains code used to implement the PRAGMA command. */ #include "box/index.h" -#include "box/box.h" #include "box/tuple.h" #include "box/fk_constraint.h" #include "box/schema.h" @@ -192,12 +191,9 @@ sql_pragma_index_info(struct Parse *parse, struct space *space = space_by_name(tbl_name); if (space == NULL) return; - uint32_t iid = box_index_id_by_name(space->def->id, idx_name, - strlen(idx_name)); - if (iid == BOX_ID_NIL) + struct index *idx = space_index_by_name(space, idx_name); + if (idx == NULL) return; - struct index *idx = space_index(space, iid); - assert(idx != NULL); parse->nMem = 6; struct Vdbe *v = sqlGetVdbe(parse); assert(v != NULL); diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c index 620d74e66..912a10153 100644 --- a/src/box/sql/vdbe.c +++ b/src/box/sql/vdbe.c @@ -4460,11 +4460,12 @@ case OP_SInsert: { break; } -/* Opcode: SDelete P1 P2 * * P5 - * Synopsis: space id = P1, key = r[P2] +/* Opcode: SDelete P1 P2 P3 * P5 + * Synopsis: space id = P1, key = r[P2], searching index id = P3 * * This opcode is used only during DDL routine. - * Delete entry with given key from system space. + * Delete entry with given key from system space. P3 is the index + * number by which to search for the key. * * If P5 is set to OPFLAG_NCHANGE, account overall changes * made to database. @@ -4472,13 +4473,14 @@ case OP_SInsert: { case OP_SDelete: { assert(pOp->p1 > 0); assert(pOp->p2 >= 0); + assert(pOp->p3 >= 0); pIn2 = &aMem[pOp->p2]; struct space *space = space_by_id(pOp->p1); assert(space != NULL); assert(space_is_system(space)); assert(p->errorAction == ON_CONFLICT_ACTION_ABORT); - if (sql_delete_by_key(space, 0, pIn2->z, pIn2->n) != 0) + if (sql_delete_by_key(space, pOp->p3, pIn2->z, pIn2->n) != 0) goto abort_due_to_error; if (pOp->p5 & OPFLAG_NCHANGE) p->nChange++; -- 2.21.0 (Apple Git-122)