* [tarantool-patches] [PATCH v1 1/1] sql: do not analyze incorrect statistics
@ 2018-12-15 13:39 imeevma
2018-12-17 17:35 ` [tarantool-patches] " n.pettik
0 siblings, 1 reply; 2+ messages in thread
From: imeevma @ 2018-12-15 13:39 UTC (permalink / raw)
To: v.shpilevoy, tarantool-patches
After this patch, the analysis of statistics in "_sql_stat1" and
"_sql_stat4" with the wrong table name or table index will not be
executed.
Closes #3866
---
https://github.com/tarantool/tarantool/issues/3866
https://github.com/tarantool/tarantool/tree/imeevma/gh-3866-ignore-wrong-data-in-_sql_stat
src/box/sql/analyze.c | 71 +++++++++++++++++++++---------------------
test/sql-tap/analyze1.test.lua | 27 +++++++++++++++-
2 files changed, 62 insertions(+), 36 deletions(-)
diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c
index 3f49280..9865407 100644
--- a/src/box/sql/analyze.c
+++ b/src/box/sql/analyze.c
@@ -1222,27 +1222,26 @@ analysis_loader(void *data, int argc, char **argv, char **unused)
UNUSED_PARAMETER2(unused, argc);
if (argv == 0 || argv[0] == 0 || argv[2] == 0)
return 0;
- struct analysis_index_info *info = (struct analysis_index_info *) data;
- assert(info->stats != NULL);
- struct index_stat *stat = &info->stats[info->index_count++];
struct space *space = space_by_name(argv[0]);
if (space == NULL)
- return -1;
- struct index *index;
+ return 0;
uint32_t iid = box_index_id_by_name(space->def->id, argv[1],
strlen(argv[1]));
/*
* Convention is if index's name matches with space's
* one, then it is primary index.
*/
- if (iid != BOX_ID_NIL) {
- index = space_index(space, iid);
- } else {
+ if (iid == BOX_ID_NIL) {
if (sqlite3_stricmp(argv[0], argv[1]) != 0)
- return -1;
- index = space_index(space, 0);
+ return 0;
+ iid = 0;
}
- assert(index != NULL);
+ struct index *index = space_index(space, iid);
+ if (index == NULL)
+ return 0;
+ struct analysis_index_info *info = (struct analysis_index_info *) data;
+ assert(info->stats != NULL);
+ struct index_stat *stat = &info->stats[info->index_count++];
/*
* Additional field is used to describe total
* count of tuples in index. Although now all
@@ -1395,16 +1394,18 @@ load_stat_from_space(struct sqlite3 *db, const char *sql_select_prepare,
continue;
uint32_t sample_count = sqlite3_column_int(stmt, 2);
struct space *space = space_by_name(space_name);
- assert(space != NULL);
- struct index *index;
+ if (space == NULL)
+ continue;
uint32_t iid = box_index_id_by_name(space->def->id, index_name,
strlen(index_name));
- if (sqlite3_stricmp(space_name, index_name) == 0 &&
- iid == BOX_ID_NIL)
- index = space_index(space, 0);
- else
- index = space_index(space, iid);
- assert(index != NULL);
+ if (iid == BOX_ID_NIL) {
+ if (sqlite3_stricmp(space_name, index_name) != 0)
+ continue;
+ iid = 0;
+ }
+ struct index *index = space_index(space, iid);
+ if (index == NULL)
+ continue;
uint32_t column_count = index->def->key_def->part_count;
struct index_stat *stat = &stats[current_idx_count];
stat->sample_field_count = column_count;
@@ -1463,18 +1464,18 @@ load_stat_from_space(struct sqlite3 *db, const char *sql_select_prepare,
if (index_name == NULL)
continue;
struct space *space = space_by_name(space_name);
- assert(space != NULL);
- struct index *index;
+ if (space == NULL)
+ continue;
uint32_t iid = box_index_id_by_name(space->def->id, index_name,
strlen(index_name));
- if (iid != BOX_ID_NIL) {
- index = space_index(space, iid);
- } else {
+ if (iid == BOX_ID_NIL) {
if (sqlite3_stricmp(space_name, index_name) != 0)
- return -1;
- index = space_index(space, 0);
+ continue;
+ iid = 0;
}
- assert(index != NULL);
+ struct index *index = space_index(space, iid);
+ if (index == NULL)
+ continue;
uint32_t column_count = index->def->key_def->part_count;
if (index != prev_index) {
if (prev_index != NULL) {
@@ -1544,18 +1545,18 @@ load_stat_to_index(struct sqlite3 *db, const char *sql_select_load,
if (index_name == NULL)
continue;
struct space *space = space_by_name(space_name);
- assert(space != NULL);
- struct index *index;
+ if (space == NULL)
+ continue;
uint32_t iid = box_index_id_by_name(space->def->id, index_name,
strlen(index_name));
- if (iid != BOX_ID_NIL) {
- index = space_index(space, iid);
- } else {
+ if (iid == BOX_ID_NIL) {
if (sqlite3_stricmp(space_name, index_name) != 0)
- return -1;
- index = space_index(space, 0);
+ continue;
+ iid = 0;
}
- assert(index != NULL);
+ struct index *index = space_index(space, iid);
+ if (index == NULL)
+ continue;
free(index->def->opts.stat);
index->def->opts.stat = stats[current_idx_count++];
}
diff --git a/test/sql-tap/analyze1.test.lua b/test/sql-tap/analyze1.test.lua
index ea414e9..df5aaf8 100755
--- a/test/sql-tap/analyze1.test.lua
+++ b/test/sql-tap/analyze1.test.lua
@@ -1,6 +1,6 @@
#!/usr/bin/env tarantool
test = require("sqltester")
-test:plan(38)
+test:plan(40)
--!./tcltestrunner.lua
-- 2005 July 22
@@ -346,6 +346,31 @@ test:do_execsql_test(
-- </analyze-4.2>
})
+--
+-- gh-3866 Wrong data in _sql_stat* tables leads to SEGMENTATION
+-- FAULT
+--
+test:do_execsql_test(
+ "analyze-4.3",
+ [[
+ DELETE FROM "_sql_stat1";
+ DELETE FROM "_sql_stat4";
+ INSERT INTO "_sql_stat1" VALUES('abc', 'bca', 'cab');
+ ANALYZE t4;
+ ]], {
+ -- <analyze-4.3>
+ -- </analyze-4.3>
+ })
+
+test:do_execsql_test(
+ "analyze-4.4",
+ [[
+ INSERT INTO "_sql_stat4" VALUES('abc', 'bca', 'cab', 'acb', 'bac', 'cba');
+ ANALYZE t4;
+ ]], {
+ -- <analyze-4.4>
+ -- </analyze-4.4>
+ })
-- Verify that DROP TABLE and DROP INDEX remove entries from the
--
2.7.4
^ permalink raw reply [flat|nested] 2+ messages in thread
* [tarantool-patches] Re: [PATCH v1 1/1] sql: do not analyze incorrect statistics
2018-12-15 13:39 [tarantool-patches] [PATCH v1 1/1] sql: do not analyze incorrect statistics imeevma
@ 2018-12-17 17:35 ` n.pettik
0 siblings, 0 replies; 2+ messages in thread
From: n.pettik @ 2018-12-17 17:35 UTC (permalink / raw)
To: tarantool-patches; +Cc: Imeev Mergen
> After this patch, the analysis of statistics in "_sql_stat1" and
> "_sql_stat4" with the wrong table name or table index will not be
> executed.
Could you please provide more detailed descriptions? Like
what was exact reason of crash, what did you do etc.
From backtrace I see that segfault takes place somewhere
in lua_pushstring().
>
> diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c
> index 3f49280..9865407 100644
> --- a/src/box/sql/analyze.c
> +++ b/src/box/sql/analyze.c
> @@ -1222,27 +1222,26 @@ analysis_loader(void *data, int argc, char **argv, char **unused)
> UNUSED_PARAMETER2(unused, argc);
> if (argv == 0 || argv[0] == 0 || argv[2] == 0)
> return 0;
> - struct analysis_index_info *info = (struct analysis_index_info *) data;
> - assert(info->stats != NULL);
> - struct index_stat *stat = &info->stats[info->index_count++];
> struct space *space = space_by_name(argv[0]);
> if (space == NULL)
> - return -1;
> - struct index *index;
> + return 0;
> uint32_t iid = box_index_id_by_name(space->def->id, argv[1],
> strlen(argv[1]));
> /*
> * Convention is if index's name matches with space's
> * one, then it is primary index.
> */
> - if (iid != BOX_ID_NIL) {
> - index = space_index(space, iid);
> - } else {
> + if (iid == BOX_ID_NIL) {
> if (sqlite3_stricmp(argv[0], argv[1]) != 0)
> - return -1;
> - index = space_index(space, 0);
> + return 0;
> + iid = 0;
> }
> - assert(index != NULL);
> + struct index *index = space_index(space, iid);
> + if (index == NULL)
> + return 0;
> + struct analysis_index_info *info = (struct analysis_index_info *) data;
> + assert(info->stats != NULL);
> + struct index_stat *stat = &info->stats[info->index_count++];
Why do you need all these refactoring things? AFAIU the only thing
you need to do is return 0 instead of -1; otherwise error will be handled
without error message which results in segfault.
Ofc, index_count should be incremented after index verification.
> /*
> * Additional field is used to describe total
> * count of tuples in index. Although now all
> @@ -1395,16 +1394,18 @@ load_stat_from_space(struct sqlite3 *db, const char *sql_select_prepare,
> continue;
> uint32_t sample_count = sqlite3_column_int(stmt, 2);
> struct space *space = space_by_name(space_name);
> - assert(space != NULL);
> - struct index *index;
> + if (space == NULL)
> + continue;
> uint32_t iid = box_index_id_by_name(space->def->id, index_name,
> strlen(index_name));
> - if (sqlite3_stricmp(space_name, index_name) == 0 &&
> - iid == BOX_ID_NIL)
> - index = space_index(space, 0);
> - else
> - index = space_index(space, iid);
> - assert(index != NULL);
> + if (iid == BOX_ID_NIL) {
> + if (sqlite3_stricmp(space_name, index_name) != 0)
> + continue;
> + iid = 0;
> + }
The same question here: do you really need this refactoring?
Let’s make patch as small as you can. I don’t think that such
refactoring makes code cleaner, it only complicates review process.
Tell me if I am wrong.
> + struct index *index = space_index(space, iid);
> + if (index == NULL)
> + continue;
> uint32_t column_count = index->def->key_def->part_count;
> struct index_stat *stat = &stats[current_idx_count];
> stat->sample_field_count = column_count;
> @@ -1463,18 +1464,18 @@ load_stat_from_space(struct sqlite3 *db, const char *sql_select_prepare,
> if (index_name == NULL)
> continue;
> struct space *space = space_by_name(space_name);
> - assert(space != NULL);
> - struct index *index;
> + if (space == NULL)
> + continue;
> uint32_t iid = box_index_id_by_name(space->def->id, index_name,
> strlen(index_name));
> - if (iid != BOX_ID_NIL) {
> - index = space_index(space, iid);
> - } else {
> + if (iid == BOX_ID_NIL) {
> if (sqlite3_stricmp(space_name, index_name) != 0)
> - return -1;
> - index = space_index(space, 0);
> + continue;
> + iid = 0;
> }
> - assert(index != NULL);
> + struct index *index = space_index(space, iid);
> + if (index == NULL)
> + continue;
> uint32_t column_count = index->def->key_def->part_count;
> if (index != prev_index) {
> if (prev_index != NULL) {
> @@ -1544,18 +1545,18 @@ load_stat_to_index(struct sqlite3 *db, const char *sql_select_load,
> if (index_name == NULL)
> continue;
> struct space *space = space_by_name(space_name);
> - assert(space != NULL);
> - struct index *index;
> + if (space == NULL)
> + continue;
> uint32_t iid = box_index_id_by_name(space->def->id, index_name,
> strlen(index_name));
> - if (iid != BOX_ID_NIL) {
> - index = space_index(space, iid);
> - } else {
> + if (iid == BOX_ID_NIL) {
> if (sqlite3_stricmp(space_name, index_name) != 0)
> - return -1;
> - index = space_index(space, 0);
> + continue;
> + iid = 0;
> }
> - assert(index != NULL);
> + struct index *index = space_index(space, iid);
> + if (index == NULL)
> + continue;
> free(index->def->opts.stat);
> index->def->opts.stat = stats[current_idx_count++];
> }
> diff --git a/test/sql-tap/analyze1.test.lua b/test/sql-tap/analyze1.test.lua
> index ea414e9..df5aaf8 100755
> --- a/test/sql-tap/analyze1.test.lua
> +++ b/test/sql-tap/analyze1.test.lua
> @@ -1,6 +1,6 @@
> #!/usr/bin/env tarantool
> test = require("sqltester")
> -test:plan(38)
> +test:plan(40)
>
> --!./tcltestrunner.lua
> -- 2005 July 22
> @@ -346,6 +346,31 @@ test:do_execsql_test(
> -- </analyze-4.2>
> })
>
> +--
> +-- gh-3866 Wrong data in _sql_stat* tables leads to SEGMENTATION
> +-- FAULT
> +—
Nit: I would better say “wrong space name leads to segfault”, since
tests on wrong statistics inserted to stat tables are above your tests.
> +test:do_execsql_test(
> + "analyze-4.3",
> + [[
> + DELETE FROM "_sql_stat1";
> + DELETE FROM "_sql_stat4";
> + INSERT INTO "_sql_stat1" VALUES('abc', 'bca', 'cab');
> + ANALYZE t4;
> + ]], {
> + -- <analyze-4.3>
> + -- </analyze-4.3>
> + })
> +
> +test:do_execsql_test(
> + "analyze-4.4",
> + [[
> + INSERT INTO "_sql_stat4" VALUES('abc', 'bca', 'cab', 'acb', 'bac', 'cba');
> + ANALYZE t4;
> + ]], {
> + -- <analyze-4.4>
> + -- </analyze-4.4>
> + })
Add also test, where name of table is correct, but name of index is wrong.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2018-12-17 17:35 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-15 13:39 [tarantool-patches] [PATCH v1 1/1] sql: do not analyze incorrect statistics imeevma
2018-12-17 17:35 ` [tarantool-patches] " n.pettik
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox