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 A5FFA2684F for ; Wed, 4 Jul 2018 13:18:03 -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 E64wE1s7d4sb for ; Wed, 4 Jul 2018 13:18:03 -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 62B41266C2 for ; Wed, 4 Jul 2018 13:18:03 -0400 (EDT) From: Kirill Shcherbatov Subject: [tarantool-patches] [PATCH v1 1/2] sql: get rid off sqlite3NestedParse in clean stats Date: Wed, 4 Jul 2018 20:17:54 +0300 Message-Id: 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: v.shpilevoy@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 | 39 +++++++++++------------ src/box/sql/build.c | 82 ++++++++++++++++++++++++++++++++++++------------- src/box/sql/sqliteInt.h | 13 ++++++++ 3 files changed, 94 insertions(+), 40 deletions(-) diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c index 5f73f02..e08c151 100644 --- a/src/box/sql/analyze.c +++ b/src/box/sql/analyze.c @@ -116,7 +116,7 @@ #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. @@ -127,21 +127,24 @@ * 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_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); + struct sqlite3 *db = parse->db; + struct Vdbe *v = sqlite3GetVdbe(parse); + assert(v != NULL); int aRoot[ArraySize(aTable)]; u8 aCreateTbl[ArraySize(aTable)]; @@ -160,10 +163,9 @@ openStatTable(Parse * pParse, /* Parsing context */ assert(pStat != NULL); aRoot[i] = pStat->tnum; aCreateTbl[i] = 0; - if (zWhere) { - sqlite3NestedParse(pParse, - "DELETE FROM \"%s\" WHERE \"%s\"=%Q", - zTab, zWhereType, zWhere); + if (table_name != NULL || index_name != NULL) { + vdbe_stat_space_clear(parse, zTab, index_name, + table_name); } else { /* * The sql_stat[134] table already exists. @@ -178,7 +180,7 @@ openStatTable(Parse * pParse, /* Parsing context */ 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); + vdbe_emit_open_cursor(parse, stat_cursor + i, aRoot[i], space); sqlite3VdbeChangeP5(v, aCreateTbl[i]); VdbeComment((v, aTable[i])); } @@ -1117,7 +1119,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_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,11 +1147,10 @@ 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"); - } else { - openStatTable(pParse, iStatCur, pTab->def->name, "tbl"); - } + if (pOnlyIdx != NULL) + vdbe_stat_space_open(pParse, iStatCur, pOnlyIdx->zName, NULL); + else + vdbe_stat_space_open(pParse, iStatCur, NULL, pTab->def->name); analyzeOneTable(pParse, pTab, pOnlyIdx, iStatCur, pParse->nMem + 1, pParse->nTab); loadAnalysis(pParse); diff --git a/src/box/sql/build.c b/src/box/sql/build.c index 0072f84..ac53906 100644 --- a/src/box/sql/build.c +++ b/src/box/sql/build.c @@ -2050,6 +2050,63 @@ sql_store_select(struct Parse *parse_context, struct Select *select) } /** + * Create expression record of with struct ID EQ STRING. + * + * @param parse The parsing context. + * @param col_type_name Name of column. + * @param col_name 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_type_name, + const char *col_name) +{ + struct sqlite3 *db = parse->db; + + struct Expr *col_type_expr = + sqlite3Expr(db, TK_ID, col_type_name); + struct Expr *col_name_expr = + sqlite3Expr(db, TK_STRING, col_name); + struct Expr *col_eq_expr = + sqlite3PExpr(parse, TK_EQ, col_type_expr, col_name_expr); + if (col_type_expr == NULL || col_name_expr == NULL) { + sql_expr_delete(db, col_eq_expr, false); + col_eq_expr = NULL; + } + return col_eq_expr; +} + +void +vdbe_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. * @@ -2062,27 +2119,10 @@ static void sql_clear_stat_spaces(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_stat_space_clear(parse, "_sql_stat4", idx_name, + table_name); + vdbe_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..a0a874c 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_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