2323#include " ../exceptions.h"
2424
2525#include < stdexcept>
26+ #include < string>
2627
2728namespace clickhouse {
2829namespace {
2930
31+ // Like Python's list's []:
32+ // * 0 - first element
33+ // * 1 - second element
34+ // * -1 - last element
35+ // * -2 - one before last, etc.
36+ const auto & GetASTChildElement (const TypeAst & ast, int position) {
37+ if (static_cast <size_t >(abs (position)) >= ast.elements .size ())
38+ throw ValidationError (" AST child element index out of bounds: " + std::to_string (position));
39+
40+ if (position < 0 )
41+ position = ast.elements .size () + position;
42+
43+ return ast.elements [static_cast <size_t >(position)];
44+ }
45+
3046static ColumnRef CreateTerminalColumn (const TypeAst& ast) {
3147 switch (ast.code ) {
3248 case Type::Void:
@@ -58,24 +74,24 @@ static ColumnRef CreateTerminalColumn(const TypeAst& ast) {
5874 return std::make_shared<ColumnFloat64>();
5975
6076 case Type::Decimal:
61- return std::make_shared<ColumnDecimal>(ast. elements . front ( ).value , ast. elements . back ( ).value );
77+ return std::make_shared<ColumnDecimal>(GetASTChildElement (ast, 0 ).value , GetASTChildElement (ast, - 1 ).value );
6278 case Type::Decimal32:
63- return std::make_shared<ColumnDecimal>(9 , ast. elements . front ( ).value );
79+ return std::make_shared<ColumnDecimal>(9 , GetASTChildElement (ast, 0 ).value );
6480 case Type::Decimal64:
65- return std::make_shared<ColumnDecimal>(18 , ast. elements . front ( ).value );
81+ return std::make_shared<ColumnDecimal>(18 , GetASTChildElement (ast, 0 ).value );
6682 case Type::Decimal128:
67- return std::make_shared<ColumnDecimal>(38 , ast. elements . front ( ).value );
83+ return std::make_shared<ColumnDecimal>(38 , GetASTChildElement (ast, 0 ).value );
6884
6985 case Type::String:
7086 return std::make_shared<ColumnString>();
7187 case Type::FixedString:
72- return std::make_shared<ColumnFixedString>(ast. elements . front ( ).value );
88+ return std::make_shared<ColumnFixedString>(GetASTChildElement (ast, 0 ).value );
7389
7490 case Type::DateTime:
7591 if (ast.elements .empty ()) {
7692 return std::make_shared<ColumnDateTime>();
7793 } else {
78- return std::make_shared<ColumnDateTime>(ast. elements [ 0 ] .value_string );
94+ return std::make_shared<ColumnDateTime>(GetASTChildElement ( ast, 0 ) .value_string );
7995 }
8096 case Type::DateTime64:
8197 if (ast.elements .empty ()) {
@@ -120,13 +136,13 @@ static ColumnRef CreateColumnFromAst(const TypeAst& ast, CreateColumnByTypeSetti
120136 switch (ast.meta ) {
121137 case TypeAst::Array: {
122138 return std::make_shared<ColumnArray>(
123- CreateColumnFromAst (ast. elements . front ( ), settings)
139+ CreateColumnFromAst (GetASTChildElement (ast, 0 ), settings)
124140 );
125141 }
126142
127143 case TypeAst::Nullable: {
128144 return std::make_shared<ColumnNullable>(
129- CreateColumnFromAst (ast. elements . front ( ), settings),
145+ CreateColumnFromAst (GetASTChildElement (ast, 0 ), settings),
130146 std::make_shared<ColumnUInt8>()
131147 );
132148 }
@@ -159,9 +175,10 @@ static ColumnRef CreateColumnFromAst(const TypeAst& ast, CreateColumnByTypeSetti
159175
160176 enum_items.reserve (ast.elements .size () / 2 );
161177 for (size_t i = 0 ; i < ast.elements .size (); i += 2 ) {
162- enum_items.push_back (
163- Type::EnumItem{ ast.elements [i].value_string ,
164- (int16_t )ast.elements [i + 1 ].value });
178+ enum_items.push_back (Type::EnumItem{
179+ ast.elements [i].value_string ,
180+ static_cast <int16_t >(ast.elements [i + 1 ].value )
181+ });
165182 }
166183
167184 if (ast.code == Type::Enum8) {
@@ -176,14 +193,14 @@ static ColumnRef CreateColumnFromAst(const TypeAst& ast, CreateColumnByTypeSetti
176193 break ;
177194 }
178195 case TypeAst::LowCardinality: {
179- const auto nested = ast. elements . front ( );
196+ const auto nested = GetASTChildElement (ast, 0 );
180197 if (settings.low_cardinality_as_wrapped_column ) {
181198 switch (nested.code ) {
182199 // TODO (nemkov): update this to maximize code reuse.
183200 case Type::String:
184201 return std::make_shared<LowCardinalitySerializationAdaptor<ColumnString>>();
185202 case Type::FixedString:
186- return std::make_shared<LowCardinalitySerializationAdaptor<ColumnFixedString>>(nested. elements . front ( ).value );
203+ return std::make_shared<LowCardinalitySerializationAdaptor<ColumnFixedString>>(GetASTChildElement (nested, 0 ).value );
187204 case Type::Nullable:
188205 throw UnimplementedError (" LowCardinality(" + nested.name + " ) is not supported with LowCardinalityAsWrappedColumn on" );
189206 default :
@@ -196,11 +213,11 @@ static ColumnRef CreateColumnFromAst(const TypeAst& ast, CreateColumnByTypeSetti
196213 case Type::String:
197214 return std::make_shared<ColumnLowCardinalityT<ColumnString>>();
198215 case Type::FixedString:
199- return std::make_shared<ColumnLowCardinalityT<ColumnFixedString>>(nested. elements . front ( ).value );
216+ return std::make_shared<ColumnLowCardinalityT<ColumnFixedString>>(GetASTChildElement (nested, 0 ).value );
200217 case Type::Nullable:
201218 return std::make_shared<ColumnLowCardinality>(
202219 std::make_shared<ColumnNullable>(
203- CreateColumnFromAst (nested. elements . front ( ), settings),
220+ CreateColumnFromAst (GetASTChildElement (nested, 0 ), settings),
204221 std::make_shared<ColumnUInt8>()
205222 )
206223 );
@@ -210,7 +227,7 @@ static ColumnRef CreateColumnFromAst(const TypeAst& ast, CreateColumnByTypeSetti
210227 }
211228 }
212229 case TypeAst::SimpleAggregateFunction: {
213- return CreateTerminalColumn (ast. elements . back ( ));
230+ return CreateTerminalColumn (GetASTChildElement (ast, - 1 ));
214231 }
215232
216233 case TypeAst::Map: {
0 commit comments