Addition to prev. revision [#CLICKHOUSE-3149].

This commit is contained in:
Alexey Milovidov 2017-07-16 07:08:20 +03:00 committed by alexey-milovidov
parent 5c3ca0c16e
commit 5f98f4b862
4 changed files with 124 additions and 131 deletions

View File

@ -109,6 +109,7 @@ void registerDataTypeNullable(DataTypeFactory & factory);
void registerDataTypeNull(DataTypeFactory & factory);
void registerDataTypeUUID(DataTypeFactory & factory);
void registerDataTypeAggregateFunction(DataTypeFactory & factory);
void registerDataTypeNested(DataTypeFactory & factory);
DataTypeFactory::DataTypeFactory()
@ -125,6 +126,7 @@ DataTypeFactory::DataTypeFactory()
registerDataTypeNull(*this);
registerDataTypeUUID(*this);
registerDataTypeAggregateFunction(*this);
registerDataTypeNested(*this);
}
}

View File

@ -5,6 +5,10 @@
#include <DataTypes/DataTypeArray.h>
#include <DataTypes/DataTypeNested.h>
#include <DataTypes/DataTypeFactory.h>
#include <Parsers/IAST.h>
#include <Parsers/ASTNameTypePair.h>
namespace DB
@ -13,6 +17,8 @@ namespace DB
namespace ErrorCodes
{
extern const int INVALID_NESTED_NAME;
extern const int EMPTY_DATA_PASSED;
extern const int NESTED_TYPE_TOO_DEEP;
}
@ -90,4 +96,30 @@ NamesAndTypesListPtr DataTypeNested::expandNestedColumns(const NamesAndTypesList
return columns;
}
static DataTypePtr create(const ASTPtr & arguments)
{
if (arguments->children.empty())
throw Exception("Nested structure cannot be empty", ErrorCodes::EMPTY_DATA_PASSED);
NamesAndTypesListPtr columns = std::make_shared<NamesAndTypesList>();
for (const auto & child : arguments->children)
{
const ASTNameTypePair & name_and_type_pair = typeid_cast<const ASTNameTypePair &>(*child);
DataTypePtr type = DataTypeFactory::instance().get(name_and_type_pair.type);
if (typeid_cast<const DataTypeNested *>(type.get()))
throw Exception("Nested inside Nested is not allowed", ErrorCodes::NESTED_TYPE_TOO_DEEP);
columns->emplace_back(name_and_type_pair.name, type);
}
return std::make_shared<DataTypeNested>(columns);
}
void registerDataTypeNested(DataTypeFactory & factory)
{
factory.registerDataType("Nested", create);
}
}

View File

@ -2,34 +2,31 @@
\N
\N
\N
1 1 [1] [1] a a ['a'] ['a'] [1] ['a']
1 1 [1] [1] a a ['a'] ['a'] [1] [NULL]
1 1 [1] [1] a a ['a'] ['a'] [NULL] ['a']
1 1 [1] [1] a a \N ['a'] [1] ['a']
1 1 [1] [1] \N a ['a'] ['a'] [1] ['a']
1 1 \N [1] a a ['a'] ['a'] [1] ['a']
\N 1 [1] [1] a a ['a'] ['a'] [1] ['a']
1 1 [1] [1] a a ['a'] ['a'] [1] ['a']
1 1 [1] [1] a a ['a'] ['a'] [1] [NULL]
1 1 [1] [1] a a ['a'] ['a'] [NULL] ['a']
1 1 [1] [1] a a \N ['a'] [1] ['a']
1 1 [1] [1] \N a ['a'] ['a'] [1] ['a']
1 1 \N [1] a a ['a'] ['a'] [1] ['a']
\N 1 [1] [1] a a ['a'] ['a'] [1] ['a']
1 1 [1] [1] a a ['a'] ['a'] [1] ['a']
1 1 [1] [1] a a ['a'] ['a'] [1] [NULL]
1 1 [1] [1] a a ['a'] ['a'] [NULL] ['a']
1 1 [1] [1] a a \N ['a'] [1] ['a']
1 1 [1] [1] \N a ['a'] ['a'] [1] ['a']
1 1 \N [1] a a ['a'] ['a'] [1] ['a']
\N 1 [1] [1] a a ['a'] ['a'] [1] ['a']
1 1 [1] [1] a a ['a'] ['a'] [1] ['a'] 0000-00-00
1 1 [1] [1] a a ['a'] ['a'] [1] [NULL] 0000-00-00
1 1 [1] [1] a a ['a'] ['a'] [NULL] ['a'] 0000-00-00
1 1 [1] [1] a a \N ['a'] [1] ['a'] 0000-00-00
1 1 [1] [1] \N a ['a'] ['a'] [1] ['a'] 0000-00-00
1 1 \N [1] a a ['a'] ['a'] [1] ['a'] 0000-00-00
\N 1 [1] [1] a a ['a'] ['a'] [1] ['a'] 0000-00-00
1 1 a a [1] [1] ['a'] ['a'] 2000-01-01
1 1 a a [1] [1] ['a'] [NULL] 2000-01-01
1 1 a a [1] [NULL] ['a'] ['a'] 2000-01-01
1 1 a \N [1] [1] ['a'] ['a'] 2000-01-01
1 \N a a [1] [1] ['a'] ['a'] 2000-01-01
1 1 a a [1] [1] ['a'] ['a'] 2000-01-01
1 1 a a [1] [1] ['a'] [NULL] 2000-01-01
1 1 a a [1] [NULL] ['a'] ['a'] 2000-01-01
1 1 a \N [1] [1] ['a'] ['a'] 2000-01-01
1 \N a a [1] [1] ['a'] ['a'] 2000-01-01
1 1 a a [1] [1] ['a'] ['a'] 2000-01-01
1 1 a a [1] [1] ['a'] [NULL] 2000-01-01
1 1 a a [1] [NULL] ['a'] ['a'] 2000-01-01
1 1 a \N [1] [1] ['a'] ['a'] 2000-01-01
1 \N a a [1] [1] ['a'] ['a'] 2000-01-01
1 1 a a [1] [1] ['a'] ['a'] 2000-01-01
1 1 a a [1] [1] ['a'] [NULL] 2000-01-01
1 1 a a [1] [NULL] ['a'] ['a'] 2000-01-01
1 1 a \N [1] [1] ['a'] ['a'] 2000-01-01
1 \N a a [1] [1] ['a'] ['a'] 2000-01-01
1 1 a a [1] [1] ['a'] ['a'] 2000-01-01
1 1 a a [1] [1] ['a'] [NULL] 2000-01-01
1 1 a a [1] [NULL] ['a'] ['a'] 2000-01-01
1 1 a \N [1] [1] ['a'] ['a'] 2000-01-01
1 \N a a [1] [1] ['a'] ['a'] 2000-01-01
[2]
2 7
4 3
@ -314,17 +311,4 @@ C 4
\N 3 \N 1
[0] 2
[1] 7
\N 3
[0] 2
[1] 7
[NULL] 3
[0] [0] 2
[1] [1] 6
[1] [NULL] 1
\N [1] 1
\N [NULL] 2
[0] [0]
[1] [1]
[1] [NULL]
\N [1]
\N [NULL]

View File

@ -6,87 +6,97 @@ SELECT 1 + NULL;
SELECT abs(NULL);
SELECT NULL + NULL;
/* MergeTree engine */
DROP TABLE IF EXISTS test.test1;
CREATE TABLE test.test1(
col1 UInt64, col2 Nullable(UInt64),
col3 String, col4 Nullable(String),
col5 Array(UInt64), col6 Array(Nullable(UInt64)),
col7 Array(String), col8 Array(Nullable(String)),
d Date) Engine = MergeTree(d, (col1, d), 8192);
INSERT INTO test.test1 VALUES (1, 1, 'a', 'a', [1], [1], ['a'], ['a'], '2000-01-01');
INSERT INTO test.test1 VALUES (1, NULL, 'a', 'a', [1], [1], ['a'], ['a'], '2000-01-01');
INSERT INTO test.test1 VALUES (1, 1, 'a', NULL, [1], [1], ['a'], ['a'], '2000-01-01');
INSERT INTO test.test1 VALUES (1, 1, 'a', 'a', [1], [NULL], ['a'], ['a'], '2000-01-01');
INSERT INTO test.test1 VALUES (1, 1, 'a', 'a', [1], [1], ['a'], [NULL], '2000-01-01');
SELECT * FROM test.test1 ORDER BY col1,col2,col3,col4,col5,col6,col7,col8 ASC;
/* Memory engine */
DROP TABLE IF EXISTS test.test1;
CREATE TABLE test.test1(
col1 Nullable(UInt64), col2 UInt64,
col3 Nullable(Array(UInt64)), col4 Array(UInt64),
col5 Nullable(String), col6 String,
col7 Nullable(Array(String)), col8 Array(String),
col9 Array(Nullable(UInt64)), col10 Array(Nullable(String))) Engine = Memory;
col1 UInt64, col2 Nullable(UInt64),
col3 String, col4 Nullable(String),
col5 Array(UInt64), col6 Array(Nullable(UInt64)),
col7 Array(String), col8 Array(Nullable(String)),
d Date) Engine = Memory;
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10) VALUES (1, 1, [1], [1], 'a', 'a', ['a'], ['a'], [1], ['a']);
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10) VALUES (NULL, 1, [1], [1], 'a', 'a', ['a'], ['a'], [1], ['a']);
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10) VALUES (1, 1, NULL, [1], 'a', 'a', ['a'], ['a'], [1], ['a']);
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10) VALUES (1, 1, [1], [1], NULL, 'a', ['a'], ['a'], [1], ['a']);
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10) VALUES (1, 1, [1], [1], 'a', 'a', NULL, ['a'], [1], ['a']);
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10) VALUES (1, 1, [1], [1], 'a', 'a', ['a'], ['a'], [NULL], ['a']);
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10) VALUES (1, 1, [1], [1], 'a', 'a', ['a'], ['a'], [1], [NULL]);
SELECT col1, col2, col3, col4, col5, col6, col7, col8, col9, col10 FROM test.test1 ORDER BY col1,col2,col3,col4,col5,col6,col7,col8,col9,col10 ASC;
INSERT INTO test.test1 VALUES (1, 1, 'a', 'a', [1], [1], ['a'], ['a'], '2000-01-01');
INSERT INTO test.test1 VALUES (1, NULL, 'a', 'a', [1], [1], ['a'], ['a'], '2000-01-01');
INSERT INTO test.test1 VALUES (1, 1, 'a', NULL, [1], [1], ['a'], ['a'], '2000-01-01');
INSERT INTO test.test1 VALUES (1, 1, 'a', 'a', [1], [NULL], ['a'], ['a'], '2000-01-01');
INSERT INTO test.test1 VALUES (1, 1, 'a', 'a', [1], [1], ['a'], [NULL], '2000-01-01');
SELECT * FROM test.test1 ORDER BY col1,col2,col3,col4,col5,col6,col7,col8 ASC;
/* TinyLog engine */
DROP TABLE IF EXISTS test.test1;
CREATE TABLE test.test1(
col1 Nullable(UInt64), col2 UInt64,
col3 Nullable(Array(UInt64)), col4 Array(UInt64),
col5 Nullable(String), col6 String,
col7 Nullable(Array(String)), col8 Array(String),
col9 Array(Nullable(UInt64)), col10 Array(Nullable(String))) Engine = TinyLog;
col1 UInt64, col2 Nullable(UInt64),
col3 String, col4 Nullable(String),
col5 Array(UInt64), col6 Array(Nullable(UInt64)),
col7 Array(String), col8 Array(Nullable(String)),
d Date) Engine = TinyLog;
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10) VALUES (1, 1, [1], [1], 'a', 'a', ['a'], ['a'], [1], ['a']);
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10) VALUES (NULL, 1, [1], [1], 'a', 'a', ['a'], ['a'], [1], ['a']);
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10) VALUES (1, 1, NULL, [1], 'a', 'a', ['a'], ['a'], [1], ['a']);
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10) VALUES (1, 1, [1], [1], NULL, 'a', ['a'], ['a'], [1], ['a']);
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10) VALUES (1, 1, [1], [1], 'a', 'a', NULL, ['a'], [1], ['a']);
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10) VALUES (1, 1, [1], [1], 'a', 'a', ['a'], ['a'], [NULL], ['a']);
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10) VALUES (1, 1, [1], [1], 'a', 'a', ['a'], ['a'], [1], [NULL]);
SELECT col1, col2, col3, col4, col5, col6, col7, col8, col9, col10 FROM test.test1 ORDER BY col1,col2,col3,col4,col5,col6,col7,col8,col9,col10 ASC;
INSERT INTO test.test1 VALUES (1, 1, 'a', 'a', [1], [1], ['a'], ['a'], '2000-01-01');
INSERT INTO test.test1 VALUES (1, NULL, 'a', 'a', [1], [1], ['a'], ['a'], '2000-01-01');
INSERT INTO test.test1 VALUES (1, 1, 'a', NULL, [1], [1], ['a'], ['a'], '2000-01-01');
INSERT INTO test.test1 VALUES (1, 1, 'a', 'a', [1], [NULL], ['a'], ['a'], '2000-01-01');
INSERT INTO test.test1 VALUES (1, 1, 'a', 'a', [1], [1], ['a'], [NULL], '2000-01-01');
SELECT * FROM test.test1 ORDER BY col1,col2,col3,col4,col5,col6,col7,col8 ASC;
/* Log engine */
DROP TABLE IF EXISTS test.test1;
CREATE TABLE test.test1(
col1 Nullable(UInt64), col2 UInt64,
col3 Nullable(Array(UInt64)), col4 Array(UInt64),
col5 Nullable(String), col6 String,
col7 Nullable(Array(String)), col8 Array(String),
col9 Array(Nullable(UInt64)), col10 Array(Nullable(String))) Engine = Log;
col1 UInt64, col2 Nullable(UInt64),
col3 String, col4 Nullable(String),
col5 Array(UInt64), col6 Array(Nullable(UInt64)),
col7 Array(String), col8 Array(Nullable(String)),
d Date) Engine = Log;
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10) VALUES (1, 1, [1], [1], 'a', 'a', ['a'], ['a'], [1], ['a']);
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10) VALUES (NULL, 1, [1], [1], 'a', 'a', ['a'], ['a'], [1], ['a']);
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10) VALUES (1, 1, NULL, [1], 'a', 'a', ['a'], ['a'], [1], ['a']);
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10) VALUES (1, 1, [1], [1], NULL, 'a', ['a'], ['a'], [1], ['a']);
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10) VALUES (1, 1, [1], [1], 'a', 'a', NULL, ['a'], [1], ['a']);
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10) VALUES (1, 1, [1], [1], 'a', 'a', ['a'], ['a'], [NULL], ['a']);
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10) VALUES (1, 1, [1], [1], 'a', 'a', ['a'], ['a'], [1], [NULL]);
SELECT col1, col2, col3, col4, col5, col6, col7, col8, col9, col10 FROM test.test1 ORDER BY col1,col2,col3,col4,col5,col6,col7,col8,col9,col10 ASC;
INSERT INTO test.test1 VALUES (1, 1, 'a', 'a', [1], [1], ['a'], ['a'], '2000-01-01');
INSERT INTO test.test1 VALUES (1, NULL, 'a', 'a', [1], [1], ['a'], ['a'], '2000-01-01');
INSERT INTO test.test1 VALUES (1, 1, 'a', NULL, [1], [1], ['a'], ['a'], '2000-01-01');
INSERT INTO test.test1 VALUES (1, 1, 'a', 'a', [1], [NULL], ['a'], ['a'], '2000-01-01');
INSERT INTO test.test1 VALUES (1, 1, 'a', 'a', [1], [1], ['a'], [NULL], '2000-01-01');
SELECT * FROM test.test1 ORDER BY col1,col2,col3,col4,col5,col6,col7,col8 ASC;
/* MergeTree engine */
/* StripeLog engine */
DROP TABLE IF EXISTS test.test1;
CREATE TABLE test.test1(
col1 Nullable(UInt64), col2 UInt64,
col3 Nullable(Array(UInt64)), col4 Array(UInt64),
col5 Nullable(String), col6 String,
col7 Nullable(Array(String)), col8 Array(String),
col9 Array(Nullable(UInt64)), col10 Array(Nullable(String)),
col11 Date) Engine = MergeTree(col11, (col2, col11), 8192);
col1 UInt64, col2 Nullable(UInt64),
col3 String, col4 Nullable(String),
col5 Array(UInt64), col6 Array(Nullable(UInt64)),
col7 Array(String), col8 Array(Nullable(String)),
d Date) Engine = StripeLog;
INSERT INTO test.test1 VALUES (1, 1, 'a', 'a', [1], [1], ['a'], ['a'], '2000-01-01');
INSERT INTO test.test1 VALUES (1, NULL, 'a', 'a', [1], [1], ['a'], ['a'], '2000-01-01');
INSERT INTO test.test1 VALUES (1, 1, 'a', NULL, [1], [1], ['a'], ['a'], '2000-01-01');
INSERT INTO test.test1 VALUES (1, 1, 'a', 'a', [1], [NULL], ['a'], ['a'], '2000-01-01');
INSERT INTO test.test1 VALUES (1, 1, 'a', 'a', [1], [1], ['a'], [NULL], '2000-01-01');
SELECT * FROM test.test1 ORDER BY col1,col2,col3,col4,col5,col6,col7,col8 ASC;
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11) VALUES (1, 1, [1], [1], 'a', 'a', ['a'], ['a'], [1], ['a'], '1970-01-01');
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11) VALUES (NULL, 1, [1], [1], 'a', 'a', ['a'], ['a'], [1], ['a'], '1970-01-01');
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11) VALUES (1, 1, NULL, [1], 'a', 'a', ['a'], ['a'], [1], ['a'], '1970-01-01');
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11) VALUES (1, 1, [1], [1], NULL, 'a', ['a'], ['a'], [1], ['a'], '1970-01-01');
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11) VALUES (1, 1, [1], [1], 'a', 'a', NULL, ['a'], [1], ['a'], '1970-01-01');
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11) VALUES (1, 1, [1], [1], 'a', 'a', ['a'], ['a'], [NULL], ['a'], '1970-01-01');
INSERT INTO test.test1(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11) VALUES (1, 1, [1], [1], 'a', 'a', ['a'], ['a'], [1], [NULL], '1970-01-01');
SELECT col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11 FROM test.test1 ORDER BY col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11 ASC;
/* Insert with expression */
DROP TABLE IF EXISTS test.test1;
CREATE TABLE test.test1(col1 Nullable(Array(UInt64))) Engine=Memory;
CREATE TABLE test.test1(col1 Array(Nullable(UInt64))) Engine=Memory;
INSERT INTO test.test1(col1) VALUES ([1+1]);
SELECT col1 FROM test.test1 ORDER BY col1 ASC;
@ -456,23 +466,6 @@ INSERT INTO test.test1(col1,col2,col3,col4) VALUES(NULL, 3, NULL, 'ACDEFBGH');
SELECT col1, col2, col3, count() FROM test.test1 GROUP BY col1, col2, col3 ORDER BY col1, col2, col3;
DROP TABLE IF EXISTS test.test1;
CREATE TABLE test.test1(col1 Nullable(Array(UInt8)), col2 String) ENGINE=TinyLog;
INSERT INTO test.test1(col1,col2) VALUES([0], 'ABCDEFGH');
INSERT INTO test.test1(col1,col2) VALUES([0], 'BACDEFGH');
INSERT INTO test.test1(col1,col2) VALUES([1], 'BCADEFGH');
INSERT INTO test.test1(col1,col2) VALUES([1], 'BCDAEFGH');
INSERT INTO test.test1(col1,col2) VALUES([1], 'BCDEAFGH');
INSERT INTO test.test1(col1,col2) VALUES([1], 'BCDEFAGH');
INSERT INTO test.test1(col1,col2) VALUES([1], 'BCDEFGAH');
INSERT INTO test.test1(col1,col2) VALUES([1], 'BCDEFGHA');
INSERT INTO test.test1(col1,col2) VALUES([1], 'ACBDEFGH');
INSERT INTO test.test1(col1,col2) VALUES(NULL, 'ACDBEFGH');
INSERT INTO test.test1(col1,col2) VALUES(NULL, 'ACDEBFGH');
INSERT INTO test.test1(col1,col2) VALUES(NULL, 'ACDEFBGH');
SELECT col1, count() FROM test.test1 GROUP BY col1 ORDER BY col1;
DROP TABLE IF EXISTS test.test1;
CREATE TABLE test.test1(col1 Array(Nullable(UInt8)), col2 String) ENGINE=TinyLog;
INSERT INTO test.test1(col1,col2) VALUES([0], 'ABCDEFGH');
@ -489,21 +482,3 @@ INSERT INTO test.test1(col1,col2) VALUES([NULL], 'ACDEBFGH');
INSERT INTO test.test1(col1,col2) VALUES([NULL], 'ACDEFBGH');
SELECT col1, count() FROM test.test1 GROUP BY col1 ORDER BY col1;
DROP TABLE IF EXISTS test.test1;
CREATE TABLE test.test1(col1 Nullable(Array(UInt8)), col2 Array(Nullable(UInt8)), col3 String) ENGINE=TinyLog;
INSERT INTO test.test1(col1,col2,col3) VALUES([0], [0], 'ABCDEFGH');
INSERT INTO test.test1(col1,col2,col3) VALUES([0], [0], 'BACDEFGH');
INSERT INTO test.test1(col1,col2,col3) VALUES([1], [1], 'BCADEFGH');
INSERT INTO test.test1(col1,col2,col3) VALUES([1], [1], 'BCDAEFGH');
INSERT INTO test.test1(col1,col2,col3) VALUES([1], [1], 'BCDEAFGH');
INSERT INTO test.test1(col1,col2,col3) VALUES([1], [1], 'BCDEFAGH');
INSERT INTO test.test1(col1,col2,col3) VALUES([1], [1], 'BCDEFGAH');
INSERT INTO test.test1(col1,col2,col3) VALUES([1], [1], 'BCDEFGHA');
INSERT INTO test.test1(col1,col2,col3) VALUES([1], [NULL], 'ACBDEFGH');
INSERT INTO test.test1(col1,col2,col3) VALUES(NULL, [1], 'ACDBEFGH');
INSERT INTO test.test1(col1,col2,col3) VALUES(NULL, [NULL], 'ACDEBFGH');
INSERT INTO test.test1(col1,col2,col3) VALUES(NULL, [NULL], 'ACDEFBGH');
SELECT col1, col2, count() FROM test.test1 GROUP BY col1, col2 ORDER BY col1, col2;
SELECT DISTINCT col1, col2 FROM test.test1 ORDER BY col1, col2;