dbms: no exception on zero index, added to the test [METR-10798]

This commit is contained in:
Sergey Fedorov 2014-04-17 18:56:58 +04:00
parent e48c3d7b5e
commit a670bd654b
3 changed files with 29 additions and 17 deletions

View File

@ -189,7 +189,8 @@ public:
template <typename T> template <typename T>
struct ArrayElementNumImpl struct ArrayElementNumImpl
{ {
/** Если negative = false - передаётся индекс с начала массива, начиная с нуля. /** Процедура для константного идекса
* Если negative = false - передаётся индекс с начала массива, начиная с нуля.
* Если negative = true - передаётся индекс с конца массива, начиная с нуля. * Если negative = true - передаётся индекс с конца массива, начиная с нуля.
*/ */
template <bool negative> template <bool negative>
@ -215,6 +216,9 @@ struct ArrayElementNumImpl
} }
} }
/** Процедура для неконстантного идекса
* index_type - тип данных идекса
*/
template <typename index_type> template <typename index_type>
static void vector( static void vector(
const PODArray<T> & data, const ColumnArray::Offsets_t & offsets, const PODArray<T> & data, const ColumnArray::Offsets_t & offsets,
@ -232,9 +236,7 @@ struct ArrayElementNumImpl
if (index[i].getType() == Field::Types::UInt64) if (index[i].getType() == Field::Types::UInt64)
{ {
UInt64 cur_id = safeGet<UInt64>(index[i]); UInt64 cur_id = safeGet<UInt64>(index[i]);
if (cur_id == 0) if (cur_id > 0 && cur_id <= array_size)
throw Exception("Array indices is 1-based", ErrorCodes::ZERO_ARRAY_OR_TUPLE_INDEX);
else if (cur_id <= array_size)
result[i] = data[current_offset + cur_id - 1]; result[i] = data[current_offset + cur_id - 1];
else else
result[i] = T(); result[i] = T();
@ -242,9 +244,7 @@ struct ArrayElementNumImpl
else if (index[i].getType() == Field::Types::Int64) else if (index[i].getType() == Field::Types::Int64)
{ {
Int64 cur_id = safeGet<Int64>(index[i]); Int64 cur_id = safeGet<Int64>(index[i]);
if (cur_id == 0) if (cur_id > 0 && cur_id <= array_size)
throw Exception("Array indices is 1-based", ErrorCodes::ZERO_ARRAY_OR_TUPLE_INDEX);
else if (cur_id > 0 && cur_id <= array_size)
result[i] = data[current_offset + cur_id - 1]; result[i] = data[current_offset + cur_id - 1];
else if (cur_id < 0 && -cur_id <= array_size) else if (cur_id < 0 && -cur_id <= array_size)
result[i] = data[offsets[i] + cur_id]; result[i] = data[offsets[i] + cur_id];
@ -261,6 +261,10 @@ struct ArrayElementNumImpl
struct ArrayElementStringImpl struct ArrayElementStringImpl
{ {
/** Процедура для константного идекса
* Если negative = false - передаётся индекс с начала массива, начиная с нуля.
* Если negative = true - передаётся индекс с конца массива, начиная с нуля.
*/
template <bool negative> template <bool negative>
static void vectorConst( static void vectorConst(
const ColumnString::Chars_t & data, const ColumnArray::Offsets_t & offsets, const ColumnString::Offsets_t & string_offsets, const ColumnString::Chars_t & data, const ColumnArray::Offsets_t & offsets, const ColumnString::Offsets_t & string_offsets,
@ -305,6 +309,9 @@ struct ArrayElementStringImpl
} }
} }
/** Процедура для неконстантного идекса
* index_type - тип данных идекса
*/
template <typename index_type> template <typename index_type>
static void vector( static void vector(
const ColumnString::Chars_t & data, const ColumnArray::Offsets_t & offsets, const ColumnString::Offsets_t & string_offsets, const ColumnString::Chars_t & data, const ColumnArray::Offsets_t & offsets, const ColumnString::Offsets_t & string_offsets,
@ -325,10 +332,10 @@ struct ArrayElementStringImpl
if (index[i].getType() == Field::Types::UInt64) if (index[i].getType() == Field::Types::UInt64)
{ {
UInt64 cur_id = safeGet<UInt64>(index[i]); UInt64 cur_id = safeGet<UInt64>(index[i]);
if (cur_id == 0) if (cur_id > 0 && cur_id <= array_size)
adjusted_index = array_size; /// Индекс не вписывается в рамки массива, заменяем заведомо слишком большим
else
adjusted_index = cur_id - 1; adjusted_index = cur_id - 1;
else
adjusted_index = array_size; /// Индекс не вписывается в рамки массива, заменяем заведомо слишком большим
} }
else if (index[i].getType() == Field::Types::Int64) else if (index[i].getType() == Field::Types::Int64)
{ {
@ -577,7 +584,6 @@ private:
return true; return true;
} }
public: public:
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const

View File

@ -3,23 +3,28 @@
13 13
11 11
0 0
0
12 12
0 0
11 11
0 0
0
Df Df
ERT ERT
Ab Ab
Df Df
ABC ABC
[1,2,3] 2 [1,2,3] 2
[1,2,3] 1 [1,2,3] 1
[1,2,3] 0 [1,2,3] 0
[1,2,3] 3 [1,2,3] 3
[1,2,3] 0
[1,2,3] 2 [1,2,3] 2
[1,2,3] 1 [1,2,3] 1
[1,2,3] 0 [1,2,3] 0
@ -28,3 +33,4 @@ ABC
[1,2,3] 3 [1,2,3] 3
[1,2,3] 0 [1,2,3] 0
[1,2,3] 1 [1,2,3] 1
[1,2,3] 0

View File

@ -1,31 +1,31 @@
DROP TABLE IF EXISTS array_element_test; DROP TABLE IF EXISTS array_element_test;
CREATE TABLE array_element_test (arr Array(Int32), id Int32) ENGINE = Memory; CREATE TABLE array_element_test (arr Array(Int32), id Int32) ENGINE = Memory;
insert into array_element_test VALUES ([11,12,13], 2), ([11,12], 3), ([11,12,13], -1), ([11,12], -2), ([11,12], -3); insert into array_element_test VALUES ([11,12,13], 2), ([11,12], 3), ([11,12,13], -1), ([11,12], -2), ([11,12], -3), ([11], 0);
select arr[id] from array_element_test; select arr[id] from array_element_test;
DROP TABLE IF EXISTS array_element_test; DROP TABLE IF EXISTS array_element_test;
CREATE TABLE array_element_test (arr Array(Int32), id UInt32) ENGINE = Memory; CREATE TABLE array_element_test (arr Array(Int32), id UInt32) ENGINE = Memory;
insert into array_element_test VALUES ([11,12,13], 2), ([11,12], 3), ([11,12,13], 1), ([11,12], 4); insert into array_element_test VALUES ([11,12,13], 2), ([11,12], 3), ([11,12,13], 1), ([11,12], 4), ([11], 0);
select arr[id] from array_element_test; select arr[id] from array_element_test;
DROP TABLE IF EXISTS array_element_test; DROP TABLE IF EXISTS array_element_test;
CREATE TABLE array_element_test (arr Array(String), id Int32) ENGINE = Memory; CREATE TABLE array_element_test (arr Array(String), id Int32) ENGINE = Memory;
insert into array_element_test VALUES (['Abc','Df','Q'], 2), (['Abc','DEFQ'], 3), (['ABC','Q','ERT'], -1), (['Ab','ber'], -2), (['AB','asd'], -3); insert into array_element_test VALUES (['Abc','Df','Q'], 2), (['Abc','DEFQ'], 3), (['ABC','Q','ERT'], -1), (['Ab','ber'], -2), (['AB','asd'], -3), (['A'], 0);
select arr[id] from array_element_test; select arr[id] from array_element_test;
DROP TABLE IF EXISTS array_element_test; DROP TABLE IF EXISTS array_element_test;
CREATE TABLE array_element_test (arr Array(String), id UInt32) ENGINE = Memory; CREATE TABLE array_element_test (arr Array(String), id UInt32) ENGINE = Memory;
insert into array_element_test VALUES (['Abc','Df','Q'], 2), (['Abc','DEFQ'], 3), (['ABC','Q','ERT'], 1), (['Ab','ber'], 4); insert into array_element_test VALUES (['Abc','Df','Q'], 2), (['Abc','DEFQ'], 3), (['ABC','Q','ERT'], 1), (['Ab','ber'], 4), (['A'], 0);
select arr[id] from array_element_test; select arr[id] from array_element_test;
DROP TABLE IF EXISTS array_element_test; DROP TABLE IF EXISTS array_element_test;
CREATE TABLE array_element_test (id UInt32) ENGINE = Memory; CREATE TABLE array_element_test (id UInt32) ENGINE = Memory;
insert into array_element_test VALUES (2), (1), (4), (3); insert into array_element_test VALUES (2), (1), (4), (3), (0);
select [1, 2, 3] as arr, arr[id] from array_element_test; select [1, 2, 3] as arr, arr[id] from array_element_test;
DROP TABLE IF EXISTS array_element_test; DROP TABLE IF EXISTS array_element_test;
CREATE TABLE array_element_test (id Int32) ENGINE = Memory; CREATE TABLE array_element_test (id Int32) ENGINE = Memory;
insert into array_element_test VALUES (-2), (1), (-4), (3), (2), (-1), (4), (-3); insert into array_element_test VALUES (-2), (1), (-4), (3), (2), (-1), (4), (-3), (0);
select [1, 2, 3] as arr, arr[id] from array_element_test; select [1, 2, 3] as arr, arr[id] from array_element_test;
DROP TABLE IF EXISTS array_element_test; DROP TABLE IF EXISTS array_element_test;