static bool parseDecimal(IParser::Pos & pos, IParser::Pos end, ASTSampleRatio::Rational & res, IParser::Pos & max_parsed_pos) { ParserWhitespaceOrComments ws; ws.ignore(pos, end); UInt64 num_before = 0; UInt64 num_after = 0; Int64 exponent = 0; IParser::Pos pos_after_first_num = tryReadIntText(num_before, pos, end); bool has_num_before_point = pos_after_first_num > pos; pos = pos_after_first_num; bool has_point = pos < end && *pos == '.'; if (has_point) ++pos; if (!has_num_before_point && !has_point) return false; size_t number_of_digits_after_point = 0; if (has_point) { IParser::Pos pos_after_second_num = tryReadIntText(num_after, pos, end); number_of_digits_after_point = pos_after_second_num - pos; pos = pos_after_second_num; } bool has_exponent = pos < end && (*pos == 'e' || *pos == 'E'); if (has_exponent) { ++pos; IParser::Pos pos_after_exponent = tryReadIntText(exponent, pos, end); if (pos_after_exponent == pos) return false; pos = pos_after_exponent; } res.numerator = num_before * exp10(number_of_digits_after_point) + num_after; res.denominator = exp10(number_of_digits_after_point); if (exponent > 0) res.numerator *= exp10(exponent); if (exponent < 0) res.denominator *= exp10(-exponent); /// NOTE You do not need to remove the common power of ten from the numerator and denominator. return true; }
/** Possible options: * * 12345 * - an integer * * 0.12345 * .12345 * 0. * - fraction in ordinary decimal notation * * 1.23e-1 * - fraction in scientific decimal notation * * 123 / 456 * - fraction with an ordinary denominator * * Just in case, in the numerator and denominator of the fraction, we support the previous cases. * Example: * 123.0 / 456e0 */ bool ParserSampleRatio::parseImpl(IParser::Pos & pos, IParser::Pos end, ASTPtr & node, IParser::Pos & max_parsed_pos, Expected & expected) { auto begin = pos; ParserWhitespaceOrComments ws; ASTSampleRatio::Rational numerator; ASTSampleRatio::Rational denominator; ASTSampleRatio::Rational res; ws.ignore(pos, end); if (!parseDecimal(pos, end, numerator, max_parsed_pos)) return false; ws.ignore(pos, end); bool has_slash = pos < end && *pos == '/'; if (has_slash) { ++pos; ws.ignore(pos, end); if (!parseDecimal(pos, end, denominator, max_parsed_pos)) return false; res.numerator = numerator.numerator * denominator.denominator; res.denominator = numerator.denominator * denominator.numerator; } else { res = numerator; } ws.ignore(pos, end); node = std::make_shared<ASTSampleRatio>(StringRange(begin, pos), res); return true; }
bool ParserTablePropertiesQuery::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected) { Pos begin = pos; ParserWhitespaceOrComments ws; ParserKeyword s_exists("EXISTS"); ParserKeyword s_describe("DESCRIBE"); ParserKeyword s_desc("DESC"); ParserKeyword s_show("SHOW"); ParserKeyword s_create("CREATE"); ParserKeyword s_table("TABLE"); ParserString s_dot("."); ParserIdentifier name_p; ASTPtr database; ASTPtr table; std::shared_ptr<ASTQueryWithTableAndOutput> query; ws.ignore(pos, end); if (s_exists.ignore(pos, end, max_parsed_pos, expected)) { query = std::make_shared<ASTExistsQuery>(); } else if (s_describe.ignore(pos, end, max_parsed_pos, expected) || s_desc.ignore(pos, end, max_parsed_pos, expected)) { query = std::make_shared<ASTDescribeQuery>(); } else if (s_show.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if (!s_create.ignore(pos, end, max_parsed_pos, expected)) return false; query = std::make_shared<ASTShowCreateQuery>(); } else { return false; } ws.ignore(pos, end); s_table.ignore(pos, end, max_parsed_pos, expected); ws.ignore(pos, end); if (!name_p.parse(pos, end, table, max_parsed_pos, expected)) return false; ws.ignore(pos, end); if (s_dot.ignore(pos, end, max_parsed_pos, expected)) { database = table; if (!name_p.parse(pos, end, table, max_parsed_pos, expected)) return false; ws.ignore(pos, end); } ws.ignore(pos, end); query->range = StringRange(begin, pos); if (database) query->database = typeid_cast<ASTIdentifier &>(*database).name; if (table) query->table = typeid_cast<ASTIdentifier &>(*table).name; node = query; return true; }
bool ParserAlterQuery::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected) { Pos begin = pos; ParserKeyword s_alter_table("ALTER TABLE"); ParserKeyword s_add_column("ADD COLUMN"); ParserKeyword s_drop_column("DROP COLUMN"); ParserKeyword s_modify_column("MODIFY COLUMN"); ParserKeyword s_modify_primary_key("MODIFY PRIMARY KEY"); ParserKeyword s_attach_partition("ATTACH PARTITION"); ParserKeyword s_detach_partition("DETACH PARTITION"); ParserKeyword s_drop_partition("DROP PARTITION"); ParserKeyword s_attach_part("ATTACH PART"); ParserKeyword s_fetch_partition("FETCH PARTITION"); ParserKeyword s_freeze_partition("FREEZE PARTITION"); ParserKeyword s_reshard("RESHARD"); ParserKeyword s_partition("PARTITION"); ParserKeyword s_after("AFTER"); ParserKeyword s_from("FROM"); ParserKeyword s_from_partition("FROM PARTITION"); ParserKeyword s_copy("COPY"); ParserKeyword s_to("TO"); ParserKeyword s_using("USING"); ParserKeyword s_coordinate("COORDINATE"); ParserKeyword s_with("WITH"); ParserKeyword s_name("NAME"); ParserString s_dot("."); ParserString s_comma(","); ParserString s_doubledot(".."); ParserWhitespaceOrComments ws; ParserIdentifier table_parser; ParserCompoundIdentifier parser_name; ParserCompoundColumnDeclaration parser_col_decl; ParserLiteral parser_literal; ParserUnsignedInteger parser_uint; ParserStringLiteral parser_string_literal; ASTPtr table; ASTPtr database; String cluster_str; ASTPtr col_type; ASTPtr col_after; ASTPtr col_drop; auto query = std::make_shared<ASTAlterQuery>(); ws.ignore(pos, end); if (!s_alter_table.ignore(pos, end, max_parsed_pos, expected)) return false; ws.ignore(pos, end); if (!table_parser.parse(pos, end, database, max_parsed_pos, expected)) return false; /// Parse [db].name if (s_dot.ignore(pos, end)) { if (!table_parser.parse(pos, end, table, max_parsed_pos, expected)) return false; query->table = typeid_cast<ASTIdentifier &>(*table).name; query->database = typeid_cast<ASTIdentifier &>(*database).name; } else { table = database; query->table = typeid_cast<ASTIdentifier &>(*table).name; } ws.ignore(pos, end); if (ParserKeyword{"ON"}.ignore(pos, end, max_parsed_pos, expected)) { if (!ASTQueryWithOnCluster::parse(pos, end, cluster_str, max_parsed_pos, expected)) return false; } bool parsing_finished = false; do { ASTAlterQuery::Parameters params; ws.ignore(pos, end); if (s_add_column.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if (!parser_col_decl.parse(pos, end, params.col_decl, max_parsed_pos, expected)) return false; ws.ignore(pos, end); if (s_after.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if(!parser_name.parse(pos, end, params.column, max_parsed_pos, expected)) return false; } params.type = ASTAlterQuery::ADD_COLUMN; } else if (s_drop_partition.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if (!parser_literal.parse(pos, end, params.partition, max_parsed_pos, expected)) return false; params.type = ASTAlterQuery::DROP_PARTITION; } else if (s_drop_column.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if (!parser_name.parse(pos, end, params.column, max_parsed_pos, expected)) return false; params.type = ASTAlterQuery::DROP_COLUMN; params.detach = false; if (s_from_partition.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if (!parser_literal.parse(pos, end, params.partition, max_parsed_pos, expected)) return false; } } else if (s_detach_partition.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if (!parser_literal.parse(pos, end, params.partition, max_parsed_pos, expected)) return false; params.type = ASTAlterQuery::DROP_PARTITION; params.detach = true; } else if (s_attach_partition.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if (!parser_literal.parse(pos, end, params.partition, max_parsed_pos, expected)) return false; params.type = ASTAlterQuery::ATTACH_PARTITION; } else if (s_attach_part.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if (!parser_literal.parse(pos, end, params.partition, max_parsed_pos, expected)) return false; params.part = true; params.type = ASTAlterQuery::ATTACH_PARTITION; } else if (s_fetch_partition.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if (!parser_literal.parse(pos, end, params.partition, max_parsed_pos, expected)) return false; ws.ignore(pos, end); if (!s_from.ignore(pos, end, max_parsed_pos, expected)) return false; ws.ignore(pos, end); ASTPtr ast_from; if (!parser_string_literal.parse(pos, end, ast_from, max_parsed_pos, expected)) return false; params.from = typeid_cast<const ASTLiteral &>(*ast_from).value.get<const String &>(); params.type = ASTAlterQuery::FETCH_PARTITION; } else if (s_freeze_partition.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if (!parser_literal.parse(pos, end, params.partition, max_parsed_pos, expected)) return false; ws.ignore(pos, end); /// WITH NAME 'name' - place local backup to directory with specified name if (s_with.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if (!s_name.ignore(pos, end, max_parsed_pos, expected)) return false; ws.ignore(pos, end); ASTPtr ast_with_name; if (!parser_string_literal.parse(pos, end, ast_with_name, max_parsed_pos, expected)) return false; params.with_name = typeid_cast<const ASTLiteral &>(*ast_with_name).value.get<const String &>(); ws.ignore(pos, end); } params.type = ASTAlterQuery::FREEZE_PARTITION; } else if (s_modify_column.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if (!parser_col_decl.parse(pos, end, params.col_decl, max_parsed_pos, expected)) return false; ws.ignore(pos, end); params.type = ASTAlterQuery::MODIFY_COLUMN; } else if (s_modify_primary_key.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if (!ParserString("(").ignore(pos, end, max_parsed_pos, expected)) return false; ws.ignore(pos, end); if (!ParserNotEmptyExpressionList(false).parse(pos, end, params.primary_key, max_parsed_pos, expected)) return false; ws.ignore(pos, end); if (!ParserString(")").ignore(pos, end, max_parsed_pos, expected)) return false; ws.ignore(pos, end); params.type = ASTAlterQuery::MODIFY_PRIMARY_KEY; } else if (s_reshard.ignore(pos, end, max_parsed_pos, expected)) { ParserList weighted_zookeeper_paths_p(std::make_unique<ParserWeightedZooKeeperPath>(), std::make_unique<ParserString>(","), false); ParserExpressionWithOptionalAlias parser_sharding_key_expr(false); ParserStringLiteral parser_coordinator; ws.ignore(pos, end); if (s_copy.ignore(pos, end, max_parsed_pos, expected)) params.do_copy = true; ws.ignore(pos, end); if (s_partition.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if (!parser_uint.parse(pos, end, params.partition, max_parsed_pos, expected)) return false; ws.ignore(pos, end); if (s_doubledot.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if (!parser_uint.parse(pos, end, params.last_partition, max_parsed_pos, expected)) return false; } } ws.ignore(pos, end); if (!s_to.ignore(pos, end, max_parsed_pos, expected)) return false; ws.ignore(pos, end); if (!weighted_zookeeper_paths_p.parse(pos, end, params.weighted_zookeeper_paths, max_parsed_pos, expected)) return false; ws.ignore(pos, end); if (!s_using.ignore(pos, end, max_parsed_pos, expected)) return false; ws.ignore(pos, end); if (!parser_sharding_key_expr.parse(pos, end, params.sharding_key_expr, max_parsed_pos, expected)) return false; ws.ignore(pos, end); if (s_coordinate.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if (!s_with.ignore(pos, end, max_parsed_pos, expected)) return false; ws.ignore(pos, end); if (!parser_coordinator.parse(pos, end, params.coordinator, max_parsed_pos, expected)) return false; ws.ignore(pos, end); } params.type = ASTAlterQuery::RESHARD_PARTITION; } else return false; ws.ignore(pos, end); if (!s_comma.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); parsing_finished = true; } query->addParameters(params); } while (!parsing_finished); query->range = StringRange(begin, end); query->cluster = cluster_str; node = query; return true; }
bool ParserInsertQuery::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected) { Pos begin = pos; ParserWhitespaceOrComments ws; ParserKeyword s_insert_into("INSERT INTO"); ParserKeyword s_dot("."); ParserKeyword s_values("VALUES"); ParserKeyword s_format("FORMAT"); ParserKeyword s_select("SELECT"); ParserKeyword s_lparen("("); ParserKeyword s_rparen(")"); ParserIdentifier name_p; ParserList columns_p(std::make_unique<ParserCompoundIdentifier>(), std::make_unique<ParserString>(","), false); ASTPtr database; ASTPtr table; ASTPtr columns; ASTPtr format; ASTPtr select; /// Insertion data const char * data = nullptr; ws.ignore(pos, end); if (!s_insert_into.ignore(pos, end, max_parsed_pos, expected)) return false; ws.ignore(pos, end); if (!name_p.parse(pos, end, table, max_parsed_pos, expected)) return false; ws.ignore(pos, end); if (s_dot.ignore(pos, end, max_parsed_pos, expected)) { database = table; if (!name_p.parse(pos, end, table, max_parsed_pos, expected)) return false; ws.ignore(pos, end); } ws.ignore(pos, end); /// Is there a list of columns if (s_lparen.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if (!columns_p.parse(pos, end, columns, max_parsed_pos, expected)) return false; ws.ignore(pos, end); if (!s_rparen.ignore(pos, end, max_parsed_pos, expected)) return false; } ws.ignore(pos, end); Pos before_select = pos; /// VALUES or FORMAT or SELECT if (s_values.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); data = pos; pos = end; } else if (s_format.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if (!name_p.parse(pos, end, format, max_parsed_pos, expected)) return false; /// Data starts after the first newline, if there is one, or after all the whitespace characters, otherwise. ParserWhitespaceOrComments ws_without_nl(false); ws_without_nl.ignore(pos, end); if (pos != end && *pos == ';') throw Exception("You have excessive ';' symbol before data for INSERT.\n" "Example:\n\n" "INSERT INTO t (x, y) FORMAT TabSeparated\n" "1\tHello\n" "2\tWorld\n" "\n" "Note that there is no ';' in first line.", ErrorCodes::SYNTAX_ERROR); if (pos != end && *pos == '\n') ++pos; data = pos; pos = end; } else if (s_select.ignore(pos, end, max_parsed_pos, expected)) { pos = before_select; ParserSelectQuery select_p; select_p.parse(pos, end, select, max_parsed_pos, expected); } else { expected = "VALUES or FORMAT or SELECT"; return false; } auto query = std::make_shared<ASTInsertQuery>(StringRange(begin, data ? data : pos)); node = query; if (database) query->database = typeid_cast<ASTIdentifier &>(*database).name; query->table = typeid_cast<ASTIdentifier &>(*table).name; if (format) query->format = typeid_cast<ASTIdentifier &>(*format).name; query->columns = columns; query->select = select; query->data = data != end ? data : NULL; query->end = end; if (columns) query->children.push_back(columns); if (select) query->children.push_back(select); return true; }