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 92BAC469719 for ; Tue, 3 Mar 2020 15:47:40 +0300 (MSK) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 13.0 \(3594.4.19\)) From: Roman Khabibov In-Reply-To: <20200303101204.16338-3-roman.habibov@tarantool.org> Date: Tue, 3 Mar 2020 15:47:38 +0300 Content-Transfer-Encoding: quoted-printable Message-Id: References: <20200303101204.16338-1-roman.habibov@tarantool.org> <20200303101204.16338-3-roman.habibov@tarantool.org> Subject: Re: [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: Vladislav Shpilevoy Cc: tarantool-patches@dev.tarantool.org Don=E2=80=99t see the previous mail of this commit. sql: don't select from _index during parsing 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 | 19 +++++++++++ src/box/sql/build.c | 79 +++++++++++++++++++++----------------------- src/box/sql/pragma.c | 8 ++--- src/box/sql/vdbe.c | 10 +++--- 4 files changed, 64 insertions(+), 52 deletions(-) diff --git a/src/box/space.h b/src/box/space.h index 9aea4e5be..bbdd3ef70 100644 --- a/src/box/space.h +++ b/src/box/space.h @@ -287,6 +287,25 @@ space_index(struct space *space, uint32_t id) return NULL; } =20 +/** + * Get index by index name. + * + * @param space Space index belongs to. + * @param index_name Name of index to be found. + * + * @retval 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 =3D 0; i < space->index_count; i++) { + struct index *index =3D space->index[i]; + if (strcmp(index_name, index->def->name) =3D=3D 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..fef069640 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" @@ -116,24 +115,6 @@ sql_finish_coding(struct Parse *parse_context) parse_context->is_aborted =3D true; } } -/** - * Find index by its name. - * - * @param space Space index belongs to. - * @param name Name of index to be found. - * - * @retval NULL in case index doesn't exist. - */ -static struct index * -sql_space_index_by_name(struct space *space, const char *name) -{ - for (uint32_t i =3D 0; i < space->index_count; ++i) { - struct index *idx =3D space->index[i]; - if (strcmp(name, idx->def->name) =3D=3D 0) - return idx; - } - return NULL; -} =20 bool sql_space_column_is_in_pk(struct space *space, uint32_t column) @@ -1469,6 +1450,40 @@ vdbe_emit_stat_space_clear(struct Parse *parse, = const char *stat_table_name, sql_table_delete_from(parse, src_list, where); } =20 +/** + * 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 =3D=3D ER_NO_SUCH_INDEX_NAME || + errcode =3D=3D ER_NO_SUCH_CONSTRAINT); + struct Vdbe *vdbe =3D sqlGetVdbe(parse_context); + assert(vdbe !=3D NULL); + assert(parse_context->db !=3D NULL); + int key_reg =3D 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 =3D + 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) !=3D = 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. * @@ -2401,7 +2416,7 @@ sql_create_index(struct Parse *parse) { parse->is_aborted =3D true; goto exit_create_index; } - if (sql_space_index_by_name(space, name) !=3D NULL) { + if (space_index_by_name(space, name) !=3D NULL) { if (! create_entity_def->if_not_exist) { diag_set(ClientError, = ER_INDEX_EXISTS_IN_SPACE, name, def->name); @@ -2695,29 +2710,9 @@ sql_drop_index(struct Parse *parse_context) parse_context->is_aborted =3D true; goto exit_drop_index; } - uint32_t index_id =3D box_index_id_by_name(space->def->id, = index_name, - strlen(index_name)); - if (index_id =3D=3D BOX_ID_NIL) { - if (!if_exists) { - diag_set(ClientError, ER_NO_SUCH_INDEX_NAME, - index_name, table_name); - parse_context->is_aborted =3D true; - } - goto exit_drop_index; - } =20 - /* - * Generate code to remove entry from _index space - * But firstly, delete statistics since schema - * changes after DDL. - */ - int record_reg =3D ++parse_context->nMem; - int space_id_reg =3D ++parse_context->nMem; - int index_id_reg =3D ++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 =3D space_by_name(tbl_name); if (space =3D=3D NULL) return; - uint32_t iid =3D box_index_id_by_name(space->def->id, idx_name, - strlen(idx_name)); - if (iid =3D=3D BOX_ID_NIL) + struct index *idx =3D space_index_by_name(space, idx_name); + if (idx =3D=3D NULL) return; - struct index *idx =3D space_index(space, iid); - assert(idx !=3D NULL); parse->nMem =3D 6; struct Vdbe *v =3D sqlGetVdbe(parse); assert(v !=3D 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; } =20 -/* Opcode: SDelete P1 P2 * * P5 - * Synopsis: space id =3D P1, key =3D r[P2] +/* Opcode: SDelete P1 P2 P3 * P5 + * Synopsis: space id =3D P1, key =3D r[P2], searching index id =3D 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 >=3D 0); + assert(pOp->p3 >=3D 0); =20 pIn2 =3D &aMem[pOp->p2]; struct space *space =3D space_by_id(pOp->p1); assert(space !=3D NULL); assert(space_is_system(space)); assert(p->errorAction =3D=3D ON_CONFLICT_ACTION_ABORT); - if (sql_delete_by_key(space, 0, pIn2->z, pIn2->n) !=3D 0) + if (sql_delete_by_key(space, pOp->p3, pIn2->z, pIn2->n) !=3D 0) goto abort_due_to_error; if (pOp->p5 & OPFLAG_NCHANGE) p->nChange++; --=20 2.21.0 (Apple Git-122)