[tarantool-patches] Re: [PATCH v1 1/1] sql: do not analyze incorrect statistics

n.pettik korablev at tarantool.org
Mon Dec 17 20:35:04 MSK 2018


> 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.






More information about the Tarantool-patches mailing list