From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org> To: Kirill Shcherbatov <kshcherbatov@tarantool.org>, tarantool-patches@freelists.org Subject: [tarantool-patches] Re: [PATCH v3 4/4] sql: Region-based allocations. Date: Thu, 26 Apr 2018 14:47:23 +0300 [thread overview] Message-ID: <4a62ec38-3764-28a1-3de1-4e93e1f51508@tarantool.org> (raw) In-Reply-To: <cca1e3b0cbba5a069c80a9d45e1ff44fc02f2626.1524675029.git.kshcherbatov@tarantool.org> Hello. Thanks for contributing! See below 16 comments. On 25/04/2018 19:52, Kirill Shcherbatov wrote: > Function sql_field_retrieve could leak names > in error cases. Let allocate all memory with > region allocator. > > Needed for #3272. 1. It is not only 3272. It is a part of the separate region allocations issue. I do not remember the number, please, find and write here 'Part of #nnnn#' on new line. > diff --git a/src/box/sql.c b/src/box/sql.c > index 6d4255e..2893d70 100644 > --- a/src/box/sql.c > +++ b/src/box/sql.c > @@ -1685,22 +1685,43 @@ space_column_default_expr(uint32_t space_id, uint32_t fieldno) > return space->def->fields[fieldno].default_value_expr; > } > > +struct space_def * > +sql_ephemeral_space_def_new(Parse *parser) > +{ > + struct space_def *def = NULL; > + struct region *region = &fiber()->gc; > + size_t size = sizeof(struct space_def) + 1; > + def = (struct space_def *)region_alloc(region, size); > + if (def != NULL) { > + memset(def, 0, size); > + def->dict = > + (struct tuple_dictionary *) > + region_alloc(region, > + sizeof(struct tuple_dictionary)); 2. Why do you need a dictionary? It must not be used in SQL anywhere. And please, do not mess checks on allocations error - try to check it right after allocation. It is hard to review code, where after alloc its result is checked multiple times on ==/!= NULL. If you have multiple allocations, and after fail of each one you must destroy some results of the previous ones, or set some error codes, you can use this way: if (alloc1_failed) goto error1; ... if (alloc2_failed) goto error2; ... error3: do_clean3... error2: do_clean2... error1: do_clean1... return -1; See the good example in vy_lsm_new() function. > + } > + if (def == NULL || def->dict == NULL) { > + parser->rc = SQLITE_NOMEM_BKPT; > + parser->nErr++; > + return NULL; > + } > + def->dict->refs = 1; > + def->opts.temporary = true; > + return def; > +} > + > Table * > sql_ephemeral_table_new(Parse *parser) > { > sqlite3 *db = parser->db; > struct space_def *def = NULL; > Table *table = sqlite3DbMallocZero(db, sizeof(Table)); > - if (table != NULL) { > - def = space_def_new(0, 0, 0, NULL, 0, NULL, 0, > - &space_opts_default, NULL, 0); > - } > + if (table != NULL) > + def = sql_ephemeral_space_def_new(parser); > if (def == NULL) { > sqlite3DbFree(db, table); > - parser->rc = SQLITE_NOMEM_BKPT; > - parser->nErr++; 3. Why did you remove it? Region allocation error is the same, as malloc allocation error. See details in 6. > return NULL; > } > + 4. Garbage diff. > diff --git a/src/box/sql/build.c b/src/box/sql/build.c > index 584e6b1..4db4356 100644 > --- a/src/box/sql/build.c > +++ b/src/box/sql/build.c > @@ -386,7 +386,9 @@ deleteTable(sqlite3 * db, Table * pTable) > sqlite3DbFree(db, pTable->zColAff); > sqlite3SelectDelete(db, pTable->pSelect); > sqlite3ExprListDelete(db, pTable->pCheck); > - if (pTable->def != NULL) > + /* Do not delete pTable->def allocated not on region. */ > + assert(pTable->def != NULL); > + if (pTable->def->opts.temporary == false) 5. Boolean variables checking on true/false can be omitted. > @@ -603,29 +606,33 @@ sqlite3StartTable(Parse *pParse, Token *pName, int noErr) > static struct field_def * > sql_field_retrieve(Parse *parser, Table *table, uint32_t id) > { > - sqlite3 *db = parser->db; > struct field_def *field; > assert(table->def != NULL); > assert(id < SQLITE_MAX_COLUMN); > > if (id >= table->def->exact_field_count) { > - uint32_t columns = table->def->exact_field_count; > - columns = (columns > 0) ? 2 * columns : 1; > - field = sqlite3DbRealloc(db, table->def->fields, > - columns * sizeof(table->def->fields[0])); > + uint32_t columns_new = table->def->exact_field_count; > + columns_new = (columns_new > 0) ? 2 * columns_new : 1; > + struct region *region = &fiber()->gc; > + field = region_alloc(region, > + columns_new * sizeof(table->def->fields[0])) 6. On region error please do diag_set error. Region error is Tarantool error, not sqlite. And on such error you must return not SQLITE_NOMEM_BKPT, but SQL_TARANTOOL_ERROR. It leads to returning to a user an error, that is set in diag. > if (field == NULL) { > parser->rc = SQLITE_NOMEM_BKPT; > parser->nErr++; > return NULL; > } > > - for (uint32_t i = columns / 2; i < columns; i++) { > + for (uint32_t i = 0; i < table->def->exact_field_count; i++) { > + memcpy(&field[i], &table->def->fields[i], > + sizeof(struct field_def)); > + } 7. It would be good to note here, that field names are not on the same region allocation, and it is ok to memcpy pointers on them. > + for (uint32_t i = columns_new / 2; i < columns_new; i++) { > memcpy(&field[i], &field_def_default, > sizeof(struct field_def)); > } > > table->def->fields = field; > - table->def->exact_field_count = columns; > + table->def->exact_field_count = columns_new; 8. This diff, and other columns->columns_new diff are garbage. Why did you rename it? The previous name was ok. > @@ -677,10 +685,8 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType) > aNew = > sqlite3DbRealloc(db, p->aCol, > (p->def->field_count + 8) * sizeof(p->aCol[0])); > - if (aNew == 0) { > - sqlite3DbFree(db, z); > + if (aNew == 0) > return; 9. Please, use == NULL for pointers. I see, that it is left from the original code, but if you modify it, then use Tarantool code style in the new code please. > diff --git a/src/box/sql/prepare.c b/src/box/sql/prepare.c > index 2ab8751..7dc14f6 100644 > --- a/src/box/sql/prepare.c > +++ b/src/box/sql/prepare.c > @@ -211,17 +211,19 @@ sqlite3InitDatabase(sqlite3 * db) > void > sqlite3ParserReset(Parse * pParse) > { > - if (pParse) { > - sqlite3 *db = pParse->db; > - sqlite3DbFree(db, pParse->aLabel); > - sqlite3ExprListDelete(db, pParse->pConstExpr); > - if (db) { > - assert(db->lookaside.bDisable >= > - pParse->disableLookaside); > - db->lookaside.bDisable -= pParse->disableLookaside; > - } > - pParse->disableLookaside = 0; > + if (pParse == NULL) > + return; > + sqlite3 *db = pParse->db; > + sqlite3DbFree(db, pParse->aLabel); > + sqlite3ExprListDelete(db, pParse->pConstExpr); > + if (db) { 10. Same as 9. > diff --git a/src/box/sql/select.c b/src/box/sql/select.c > index 9eeff8e..03bfcf9 100644 > --- a/src/box/sql/select.c > +++ b/src/box/sql/select.c > @@ -1822,9 +1822,20 @@ sqlite3ColumnsFromExprList(Parse * pParse, /* Parsing context */ > aCol = 0; > } > assert(nCol == (i16) nCol); > + > + struct region *region = &fiber()->gc; > assert(pTable->def->fields == NULL); > + if (pTable->def->opts.temporary == false) { 11. At first, same as 5. At second, why? I can not see this in the original code. > @@ -1877,9 +1888,16 @@ sqlite3ColumnsFromExprList(Parse * pParse, /* Parsing context */ > if (cnt > 3) > sqlite3_randomness(sizeof(cnt), &cnt); > } > - pTable->def->fields[i].name = zName; > - if (zName && sqlite3HashInsert(&ht, zName, pCol) == pCol) { > + uint32_t zNameLen = (uint32_t)strlen(zName); 12. For new code please use Tarantool code style - no Camel case. zNameLen -> name_len. > + if (zName && sqlite3HashInsert(&ht, zName, pCol) == pCol) 13. Same as 9. > diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h > index 94d5c80..520b74c 100644 > --- a/src/box/sql/sqliteInt.h > +++ b/src/box/sql/sqliteInt.h > @@ -2933,6 +2933,8 @@ struct Parse { > u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ > u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ > u8 disableTriggers; /* True to disable triggers */ > + /** Region size at the Parser launch */ 14. Please, put a dot at the end of the comment. > diff --git a/src/box/sql/tokenize.c b/src/box/sql/tokenize.c > index c77aa9b..9055bd0 100644 > --- a/src/box/sql/tokenize.c > +++ b/src/box/sql/tokenize.c > @@ -664,6 +664,9 @@ sql_expr_compile(sqlite3 *db, const char *expr, struct Expr **result) > memset(&parser, 0, sizeof(parser)); > parser.db = db; > parser.parse_only = true; > + struct region *region = &fiber()->gc; > + parser.region_initial_size = region_used(region); 15. It is a second place, where a parser is created. How about creating a function sql_parser_create(struct Parser *parser), that will do this? 16. I do not see, that you removed def rebuilding from sqlite3ColumnsFromExprList - it is not needed anymore.
next prev parent reply other threads:[~2018-04-26 11:47 UTC|newest] Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-04-25 16:52 [tarantool-patches] [PATCH v3 0/4] sql: Removed Column fields to server with region allocations Kirill Shcherbatov 2018-04-25 16:52 ` [tarantool-patches] [PATCH v3 1/4] sql: Fix code style in sqlite3Pragma Kirill Shcherbatov 2018-04-26 11:47 ` [tarantool-patches] " Vladislav Shpilevoy 2018-04-25 16:52 ` [tarantool-patches] [PATCH v3 2/4] sql: Remove zName and nColumn from SQL Kirill Shcherbatov 2018-04-25 17:10 ` [tarantool-patches] " Kirill Shcherbatov 2018-04-26 12:12 ` Vladislav Shpilevoy 2018-04-26 11:47 ` Vladislav Shpilevoy 2018-04-25 16:52 ` [tarantool-patches] [PATCH v3 3/4] sql: Removed type " Kirill Shcherbatov 2018-04-25 16:52 ` [tarantool-patches] [PATCH v3 4/4] sql: Region-based allocations Kirill Shcherbatov 2018-04-26 11:47 ` Vladislav Shpilevoy [this message] 2018-04-26 11:47 ` [tarantool-patches] Re: [PATCH v3 0/4] sql: Removed Column fields to server with region allocations Vladislav Shpilevoy 2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 0/7] sql: refactor SQL Parser structures Kirill Shcherbatov 2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 1/7] sql: fix code style in sqlite3Pragma Kirill Shcherbatov 2018-05-03 10:10 ` [tarantool-patches] " Vladislav Shpilevoy 2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 2/7] sql: remove zName and nColumn from SQL Kirill Shcherbatov 2018-05-03 10:10 ` [tarantool-patches] " Vladislav Shpilevoy 2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 3/7] sql: start using type from space_def Kirill Shcherbatov 2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 4/7] sql: start using collations and is_nullable " Kirill Shcherbatov 2018-05-03 10:21 ` [tarantool-patches] " Vladislav Shpilevoy 2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 5/7] sql: move names to server Kirill Shcherbatov 2018-05-03 11:08 ` [tarantool-patches] " Vladislav Shpilevoy 2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 6/7] sql: start using is_view field from space_def Kirill Shcherbatov 2018-05-03 11:16 ` [tarantool-patches] " Vladislav Shpilevoy 2018-04-28 18:26 ` [tarantool-patches] [PATCH v4 7/7] sql: space_def* instead of Table* in Expr Kirill Shcherbatov 2018-05-03 11:32 ` [tarantool-patches] " Vladislav Shpilevoy 2018-05-03 10:10 ` [tarantool-patches] Re: [PATCH v4 0/7] sql: refactor SQL Parser structures Vladislav Shpilevoy
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=4a62ec38-3764-28a1-3de1-4e93e1f51508@tarantool.org \ --to=v.shpilevoy@tarantool.org \ --cc=kshcherbatov@tarantool.org \ --cc=tarantool-patches@freelists.org \ --subject='[tarantool-patches] Re: [PATCH v3 4/4] sql: Region-based allocations.' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox