From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id 2E3B22632A for ; Tue, 10 Jul 2018 13:08:18 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id rFgo5iKH7DUn for ; Tue, 10 Jul 2018 13:08:18 -0400 (EDT) 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 turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id AC36226325 for ; Tue, 10 Jul 2018 13:08:17 -0400 (EDT) From: Kirill Shcherbatov Subject: [tarantool-patches] [PATCH v2 1/4] sql: get rid off sqlite3NestedParse in clean stats Date: Tue, 10 Jul 2018 20:08:08 +0300 Message-Id: <3017d0e640eebdc6c3f28b5b4a4cbd2ef5646882.1531242355.git.kshcherbatov@tarantool.org> In-Reply-To: References: In-Reply-To: References: Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-help: List-unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-subscribe: List-owner: List-post: List-archive: To: tarantool-patches@freelists.org Cc: korablev@tarantool.org, Kirill Shcherbatov Now we manually generate AST structures to drop outdated stats from _sql_stat1 and _sql_stat4 spaces instead of starting sqlite3NestedParse. This function become totally useless and could be removed. Part of #3496. --- src/box/sql/analyze.c | 102 ++++++++++++++++++++---------------------------- src/box/sql/build.c | 79 ++++++++++++++++++++++++++----------- src/box/sql/sqliteInt.h | 13 ++++++ 3 files changed, 113 insertions(+), 81 deletions(-) diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c index 5f73f02..336d146 100644 --- a/src/box/sql/analyze.c +++ b/src/box/sql/analyze.c @@ -116,71 +116,53 @@ #include "tarantoolInt.h" #include "vdbeInt.h" -/* - * This routine generates code that opens the sql_statN tables. - * The _sql_stat1 table is always relevant. _sql_stat4 is only opened when - * appropriate compile-time options are provided. - * - * If the sql_statN tables do not previously exist, it is created. +/** + * This routine generates code that opens the sql_stat1/4 tables. + * If the sql_statN tables do not previously exist, they are + * created. * - * Argument zWhere may be a pointer to a buffer containing a table name, - * or it may be a NULL pointer. If it is not NULL, then all entries in - * the sql_statN tables associated with the named table are deleted. - * If zWhere==0, then code is generated to delete all stat table entries. + * @param parse Parsing context. + * @param stat_cursor Open the _sql_stat1 table on this cursor. + * @param index_name Delete records of this table if specified. + * @param table_name Delete records of this index if specified. */ static void -openStatTable(Parse * pParse, /* Parsing context */ - int iStatCur, /* Open the _sql_stat1 table on this cursor */ - const char *zWhere, /* Delete entries for this table or index */ - const char *zWhereType /* Either "tbl" or "idx" */ - ) +vdbe_emit_stat_space_open(struct Parse *parse, int stat_cursor, + const char *index_name, const char *table_name) { - const char *aTable[] = { - "_sql_stat1", - "_sql_stat4", - NULL}; - int i; - sqlite3 *db = pParse->db; - Vdbe *v = sqlite3GetVdbe(pParse); - int aRoot[ArraySize(aTable)]; - u8 aCreateTbl[ArraySize(aTable)]; + const char *space_names[] = {"_sql_stat1", "_sql_stat4"}; + const uint32_t space_ids[] = {BOX_SQL_STAT1_ID, BOX_SQL_STAT4_ID}; + struct Vdbe *v = sqlite3GetVdbe(parse); + assert(v != NULL); + assert(sqlite3VdbeDb(v) == parse->db); - if (v == 0) - return; - assert(sqlite3VdbeDb(v) == db); - - /* Create new statistic tables if they do not exist, or clear them - * if they do already exist. + /* + * Create new statistic tables if they do not exist, or + * clear them if they do already exist. */ - for (i = 0; aTable[i]; i++) { - const char *zTab = aTable[i]; - Table *pStat; - /* The table already exists, because it is a system space */ - pStat = sqlite3HashFind(&db->pSchema->tblHash, zTab); - assert(pStat != NULL); - aRoot[i] = pStat->tnum; - aCreateTbl[i] = 0; - if (zWhere) { - sqlite3NestedParse(pParse, - "DELETE FROM \"%s\" WHERE \"%s\"=%Q", - zTab, zWhereType, zWhere); + for (uint i = 0; i < lengthof(space_names); ++i) { + const char *space_name = space_names[i]; + /* + * The table already exists, because it is a + * system space. + */ + assert(sqlite3HashFind(&parse->db->pSchema->tblHash, + space_name) != NULL); + if (table_name != NULL || index_name != NULL) { + vdbe_emit_stat_space_clear(parse, space_name, + index_name, table_name); } else { - /* - * The sql_stat[134] table already exists. - * Delete all rows. - */ - sqlite3VdbeAddOp2(v, OP_Clear, - SQLITE_PAGENO_TO_SPACEID(aRoot[i]), 0); + sqlite3VdbeAddOp2(v, OP_Clear, space_ids[i], 0); } } - /* Open the sql_stat[134] tables for writing. */ - for (i = 0; aTable[i]; i++) { - struct space *space = - space_by_id(SQLITE_PAGENO_TO_SPACEID(aRoot[i])); - vdbe_emit_open_cursor(pParse, iStatCur + i, aRoot[i], space); - sqlite3VdbeChangeP5(v, aCreateTbl[i]); - VdbeComment((v, aTable[i])); + /* Open the sql_stat tables for writing. */ + for (uint i = 0; i < lengthof(space_names); ++i) { + uint32_t id = space_ids[i]; + int tnum = SQLITE_PAGENO_FROM_SPACEID_AND_INDEXID(id, 0); + vdbe_emit_open_cursor(parse, stat_cursor + i, tnum, + space_by_id(id)); + VdbeComment((v, space_names[i])); } } @@ -1117,7 +1099,7 @@ sql_analyze_database(Parse *parser) sql_set_multi_write(parser, false); int stat_cursor = parser->nTab; parser->nTab += 3; - openStatTable(parser, stat_cursor, NULL, NULL); + vdbe_emit_stat_space_open(parser, stat_cursor, NULL, NULL); int reg = parser->nMem + 1; int tab_cursor = parser->nTab; for (struct HashElem *k = sqliteHashFirst(&schema->tblHash); k != NULL; @@ -1145,10 +1127,12 @@ analyzeTable(Parse * pParse, Table * pTab, Index * pOnlyIdx) sql_set_multi_write(pParse, false); iStatCur = pParse->nTab; pParse->nTab += 3; - if (pOnlyIdx) { - openStatTable(pParse, iStatCur, pOnlyIdx->zName, "idx"); + if (pOnlyIdx != NULL) { + vdbe_emit_stat_space_open(pParse, iStatCur, pOnlyIdx->zName, + NULL); } else { - openStatTable(pParse, iStatCur, pTab->def->name, "tbl"); + vdbe_emit_stat_space_open(pParse, iStatCur, NULL, + pTab->def->name); } analyzeOneTable(pParse, pTab, pOnlyIdx, iStatCur, pParse->nMem + 1, pParse->nTab); diff --git a/src/box/sql/build.c b/src/box/sql/build.c index 0072f84..21791a4 100644 --- a/src/box/sql/build.c +++ b/src/box/sql/build.c @@ -2050,6 +2050,60 @@ sql_store_select(struct Parse *parse_context, struct Select *select) } /** + * Create expression record "@col_name = '@col_value'". + * + * @param parse The parsing context. + * @param col_name Name of column. + * @param col_value Name of row. + * @retval not NULL on success. + * @retval NULL on failure. + */ +static struct Expr * +sql_id_eq_str_expr(struct Parse *parse, const char *col_name, + const char *col_value) +{ + struct sqlite3 *db = parse->db; + + struct Expr *col_name_expr = sqlite3Expr(db, TK_ID, col_name); + if (col_name_expr == NULL) + return NULL; + struct Expr *col_value_expr = sqlite3Expr(db, TK_STRING, col_value); + if (col_value_expr == NULL) { + sql_expr_delete(db, col_name_expr, false); + return NULL; + } + return sqlite3PExpr(parse, TK_EQ, col_name_expr, col_value_expr); +} + +void +vdbe_emit_stat_space_clear(struct Parse *parse, const char *stat_table_name, + const char *idx_name, const char *table_name) +{ + assert(idx_name != NULL || table_name != NULL); + struct sqlite3 *db = parse->db; + assert(!db->mallocFailed); + struct SrcList *src_list = sql_alloc_src_list(db); + if (src_list != NULL) + src_list->a[0].zName = sqlite3DbStrDup(db, stat_table_name); + struct Expr *where = NULL; + if (idx_name != NULL) { + struct Expr *expr = sql_id_eq_str_expr(parse, "idx", idx_name); + if (expr != NULL) + where = sqlite3ExprAnd(db, expr, where); + } + if (table_name != NULL) { + struct Expr *expr = sql_id_eq_str_expr(parse, "tbl", table_name); + if (expr != NULL) + where = sqlite3ExprAnd(db, expr, where); + } + /** + * On memory allocation error sql_table delete_from + * releases memory for its own. + */ + sql_table_delete_from(parse, src_list, where); +} + +/** * Remove entries from the _sql_stat1 and _sql_stat4 * system spaces after a DROP INDEX or DROP TABLE command. * @@ -2059,30 +2113,11 @@ sql_store_select(struct Parse *parse_context, struct Select *select) * @param idx_name Index to be dropped. */ static void -sql_clear_stat_spaces(Parse *parse, const char *table_name, +sql_clear_stat_spaces(struct Parse *parse, const char *table_name, const char *idx_name) { - if (idx_name != NULL) { - sqlite3NestedParse(parse, - "DELETE FROM \"_sql_stat1\" " - "WHERE (\"idx\"=%Q AND " - "\"tbl\"=%Q)", - idx_name, table_name); - sqlite3NestedParse(parse, - "DELETE FROM \"_sql_stat4\" " - "WHERE (\"idx\"=%Q AND " - "\"tbl\"=%Q)", - idx_name, table_name); - } else { - sqlite3NestedParse(parse, - "DELETE FROM \"_sql_stat1\" " - "WHERE \"tbl\"=%Q", - table_name); - sqlite3NestedParse(parse, - "DELETE FROM \"_sql_stat4\" " - "WHERE \"tbl\"=%Q", - table_name); - } + vdbe_emit_stat_space_clear(parse, "_sql_stat4", idx_name, table_name); + vdbe_emit_stat_space_clear(parse, "_sql_stat1", idx_name, table_name); } /** diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h index 8b75ae8..d76d173 100644 --- a/src/box/sql/sqliteInt.h +++ b/src/box/sql/sqliteInt.h @@ -4847,4 +4847,17 @@ vdbe_emit_halt_with_presence_test(struct Parse *parser, int space_id, const char *error_src, bool no_error, int cond_opcode); +/** + * Generate VDBE code to delete records from system _sql_stat1 or + * _sql_stat4 table. + * + * @param parse The parsing context. + * @param stat_table_name System stat table name. + * @param idx_name Index name. + * @param table_name Table name. + */ +void +vdbe_emit_stat_space_clear(struct Parse *parse, const char *stat_table_name, + const char *idx_name, const char *table_name); + #endif /* SQLITEINT_H */ -- 2.7.4