bool ParserNestedTable::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { ParserToken open(TokenType::OpeningRoundBracket); ParserToken close(TokenType::ClosingRoundBracket); ParserIdentifier name_p; ParserNameTypePairList columns_p; ASTPtr name; ASTPtr columns; /// For now `name == 'Nested'`, probably alternative nested data structures will appear if (!name_p.parse(pos, name, expected)) return false; if (!open.ignore(pos)) return false; if (!columns_p.parse(pos, columns, expected)) return false; if (!close.ignore(pos)) return false; auto func = std::make_shared<ASTFunction>(); getIdentifierName(name, func->name); func->arguments = columns; func->children.push_back(columns); node = func; return true; }
bool ParserIdentifierWithOptionalParameters::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { ParserIdentifier non_parametric; ParserIdentifierWithParameters parametric; if (parametric.parse(pos, node, expected)) return true; ASTPtr ident; if (non_parametric.parse(pos, ident, expected)) { auto func = std::make_shared<ASTFunction>(); getIdentifierName(ident, func->name); node = func; return true; } return false; }
/* Function: displayIdentifierAttributes() const Description: This function will print out all of the attributes associated with a symbol table entry. */ void symbolTableEntry::displayIdentifierAttributes(int tabCount) const { int idNumTemp = 0; std::string idTemp = getIdentifierName(); printTabs(tabCount); std::cout << "Identifier name: " << idTemp << std::endl; idTemp = getIdentifierType_String(); printTabs(tabCount); std::cout << "Identifier type: " << idTemp << std::endl; printTabs(tabCount); std::cout << "Identifier value: "; printIdentifierValue(); std::cout << std::endl; //!!!!!!!!!!!!!!!!! CHECK THIS LATER !!!!!!!!!!! if (isFunc) { idNumTemp = getNumParams(); std::cout << "Identifier is a function." << std::endl; std::cout << "Identifier has " << idNumTemp << " parameters."; std::cout << std::endl; std::cout << "Identifier parameters: " << std::endl; viewParams(); } else if (isPtr) { idNumTemp = getNumPtrs(); std::cout << "Identifier is a pointer." << std::endl; std::cout << "Identifier has " << idNumTemp << " parameters."; std::cout << std::endl; } else if (isArr) { idNumTemp = getNumArrDims(); std::cout << "Identifier is an array." << std::endl; std::cout << "Identifier has " << idNumTemp << " dimensions."; std::cout << std::endl; std::cout << "Identifier dimensions: " << std::endl; for (unsigned int i = 0; i < arrayDimensions.size(); i++) { std::cout << "Dimension #" << i << " :" << arrayDimensions[i] << std::endl; } } }
bool ParserInsertQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { ParserKeyword s_insert_into("INSERT INTO"); ParserKeyword s_table("TABLE"); ParserKeyword s_function("FUNCTION"); ParserToken s_dot(TokenType::Dot); ParserKeyword s_values("VALUES"); ParserKeyword s_format("FORMAT"); ParserKeyword s_select("SELECT"); ParserKeyword s_with("WITH"); ParserToken s_lparen(TokenType::OpeningRoundBracket); ParserToken s_rparen(TokenType::ClosingRoundBracket); ParserIdentifier name_p; ParserList columns_p(std::make_unique<ParserCompoundIdentifier>(), std::make_unique<ParserToken>(TokenType::Comma), false); ParserFunction table_function_p; ASTPtr database; ASTPtr table; ASTPtr columns; ASTPtr format; ASTPtr select; ASTPtr table_function; /// Insertion data const char * data = nullptr; if (!s_insert_into.ignore(pos, expected)) return false; s_table.ignore(pos, expected); if (s_function.ignore(pos, expected)) { if (!table_function_p.parse(pos, table_function, expected)) return false; } else { if (!name_p.parse(pos, table, expected)) return false; if (s_dot.ignore(pos, expected)) { database = table; if (!name_p.parse(pos, table, expected)) return false; } } /// Is there a list of columns if (s_lparen.ignore(pos, expected)) { if (!columns_p.parse(pos, columns, expected)) return false; if (!s_rparen.ignore(pos, expected)) return false; } Pos before_select = pos; /// VALUES or FORMAT or SELECT if (s_values.ignore(pos, expected)) { data = pos->begin; } else if (s_format.ignore(pos, expected)) { auto name_pos = pos; if (!name_p.parse(pos, format, expected)) return false; data = name_pos->end; if (data < end && *data == ';') throw Exception("You have excessive ';' symbol before data for INSERT.\n" "Example:\n\n" "INSERT INTO t (x, y) FORMAT TabSeparated\n" ";\tHello\n" "2\tWorld\n" "\n" "Note that there is no ';' just after format name, " "you need to put at least one whitespace symbol before the data.", ErrorCodes::SYNTAX_ERROR); while (data < end && (*data == ' ' || *data == '\t' || *data == '\f')) ++data; /// Data starts after the first newline, if there is one, or after all the whitespace characters, otherwise. if (data < end && *data == '\r') ++data; if (data < end && *data == '\n') ++data; } else if (s_select.ignore(pos, expected) || s_with.ignore(pos,expected)) { pos = before_select; ParserSelectWithUnionQuery select_p; select_p.parse(pos, select, expected); } else { return false; } auto query = std::make_shared<ASTInsertQuery>(); node = query; if (table_function) { query->table_function = table_function; } else { getIdentifierName(database, query->database); getIdentifierName(table, query->table); } getIdentifierName(format, query->format); query->columns = columns; query->select = select; query->data = data != end ? data : nullptr; query->end = end; if (columns) query->children.push_back(columns); if (select) query->children.push_back(select); return true; }
bool ParserCreateQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { ParserKeyword s_create("CREATE"); ParserKeyword s_temporary("TEMPORARY"); ParserKeyword s_attach("ATTACH"); ParserKeyword s_table("TABLE"); ParserKeyword s_database("DATABASE"); ParserKeyword s_if_not_exists("IF NOT EXISTS"); ParserKeyword s_as("AS"); ParserKeyword s_view("VIEW"); ParserKeyword s_materialized("MATERIALIZED"); ParserKeyword s_populate("POPULATE"); ParserToken s_dot(TokenType::Dot); ParserToken s_lparen(TokenType::OpeningRoundBracket); ParserToken s_rparen(TokenType::ClosingRoundBracket); ParserStorage storage_p; ParserIdentifier name_p; ParserColumnsOrIndicesDeclarationList columns_or_indices_p; ParserSelectWithUnionQuery select_p; ASTPtr database; ASTPtr table; ASTPtr columns_list; ASTPtr to_database; ASTPtr to_table; ASTPtr storage; ASTPtr as_database; ASTPtr as_table; ASTPtr select; String cluster_str; bool attach = false; bool if_not_exists = false; bool is_view = false; bool is_materialized_view = false; bool is_populate = false; bool is_temporary = false; if (!s_create.ignore(pos, expected)) { if (s_attach.ignore(pos, expected)) attach = true; else return false; } if (s_temporary.ignore(pos, expected)) { is_temporary = true; } if (s_table.ignore(pos, expected)) { if (s_if_not_exists.ignore(pos, expected)) if_not_exists = true; if (!name_p.parse(pos, table, expected)) return false; if (s_dot.ignore(pos, expected)) { database = table; if (!name_p.parse(pos, table, expected)) return false; } if (ParserKeyword{"ON"}.ignore(pos, expected)) { if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected)) return false; } // Shortcut for ATTACH a previously detached table if (attach && (!pos.isValid() || pos.get().type == TokenType::Semicolon)) { auto query = std::make_shared<ASTCreateQuery>(); node = query; query->attach = attach; query->if_not_exists = if_not_exists; query->cluster = cluster_str; getIdentifierName(database, query->database); getIdentifierName(table, query->table); return true; } /// List of columns. if (s_lparen.ignore(pos, expected)) { if (!columns_or_indices_p.parse(pos, columns_list, expected)) return false; if (!s_rparen.ignore(pos, expected)) return false; if (!storage_p.parse(pos, storage, expected) && !is_temporary) return false; } else { storage_p.parse(pos, storage, expected); if (!s_as.ignore(pos, expected)) return false; if (!select_p.parse(pos, select, expected)) /// AS SELECT ... { /// AS [db.]table if (!name_p.parse(pos, as_table, expected)) return false; if (s_dot.ignore(pos, expected)) { as_database = as_table; if (!name_p.parse(pos, as_table, expected)) return false; } /// Optional - ENGINE can be specified. if (!storage) storage_p.parse(pos, storage, expected); } } } else if (is_temporary) return false; else if (s_database.ignore(pos, expected)) { if (s_if_not_exists.ignore(pos, expected)) if_not_exists = true; if (!name_p.parse(pos, database, expected)) return false; if (ParserKeyword{"ON"}.ignore(pos, expected)) { if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected)) return false; } storage_p.parse(pos, storage, expected); } else { /// VIEW or MATERIALIZED VIEW if (s_materialized.ignore(pos, expected)) { is_materialized_view = true; } else is_view = true; if (!s_view.ignore(pos, expected)) return false; if (s_if_not_exists.ignore(pos, expected)) if_not_exists = true; if (!name_p.parse(pos, table, expected)) return false; if (s_dot.ignore(pos, expected)) { database = table; if (!name_p.parse(pos, table, expected)) return false; } if (ParserKeyword{"ON"}.ignore(pos, expected)) { if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected)) return false; } // TO [db.]table if (ParserKeyword{"TO"}.ignore(pos, expected)) { if (!name_p.parse(pos, to_table, expected)) return false; if (s_dot.ignore(pos, expected)) { to_database = to_table; if (!name_p.parse(pos, to_table, expected)) return false; } } /// Optional - a list of columns can be specified. It must fully comply with SELECT. if (s_lparen.ignore(pos, expected)) { if (!columns_or_indices_p.parse(pos, columns_list, expected)) return false; if (!s_rparen.ignore(pos, expected)) return false; } if (is_materialized_view && !to_table) { /// Internal ENGINE for MATERIALIZED VIEW must be specified. if (!storage_p.parse(pos, storage, expected)) return false; if (s_populate.ignore(pos, expected)) is_populate = true; } /// AS SELECT ... if (!s_as.ignore(pos, expected)) return false; if (!select_p.parse(pos, select, expected)) return false; } auto query = std::make_shared<ASTCreateQuery>(); node = query; query->attach = attach; query->if_not_exists = if_not_exists; query->is_view = is_view; query->is_materialized_view = is_materialized_view; query->is_populate = is_populate; query->temporary = is_temporary; getIdentifierName(database, query->database); getIdentifierName(table, query->table); query->cluster = cluster_str; getIdentifierName(to_database, query->to_database); getIdentifierName(to_table, query->to_table); query->set(query->columns_list, columns_list); query->set(query->storage, storage); getIdentifierName(as_database, query->as_database); getIdentifierName(as_table, query->as_table); query->set(query->select, select); return true; }
bool ParserDropQuery::parseDropQuery(Pos & pos, ASTPtr & node, Expected & expected) { ParserKeyword s_temporary("TEMPORARY"); ParserKeyword s_table("TABLE"); ParserKeyword s_database("DATABASE"); ParserToken s_dot(TokenType::Dot); ParserKeyword s_if_exists("IF EXISTS"); ParserIdentifier name_p; ASTPtr database; ASTPtr table; String cluster_str; bool if_exists = false; bool temporary = false; if (s_database.ignore(pos, expected)) { if (s_if_exists.ignore(pos, expected)) if_exists = true; if (!name_p.parse(pos, database, expected)) return false; if (ParserKeyword{"ON"}.ignore(pos, expected)) { if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected)) return false; } } else { if (s_temporary.ignore(pos, expected)) temporary = true; if (!s_table.ignore(pos, expected)) return false; if (s_if_exists.ignore(pos, expected)) if_exists = true; if (!name_p.parse(pos, table, expected)) return false; if (s_dot.ignore(pos, expected)) { database = table; if (!name_p.parse(pos, table, expected)) return false; } if (ParserKeyword{"ON"}.ignore(pos, expected)) { if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected)) return false; } } auto query = std::make_shared<ASTDropQuery>(); node = query; query->kind = ASTDropQuery::Kind::Drop; query->if_exists = if_exists; query->temporary = temporary; getIdentifierName(database, query->database); getIdentifierName(table, query->table); query->cluster = cluster_str; return true; }
StoragePtr TableFunctionRemote::executeImpl(const ASTPtr & ast_function, const Context & context) const { ASTs & args_func = typeid_cast<ASTFunction &>(*ast_function).children; if (args_func.size() != 1) throw Exception(help_message, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); ASTs & args = typeid_cast<ASTExpressionList &>(*args_func.at(0)).children; const size_t max_args = is_cluster_function ? 3 : 5; if (args.size() < 2 || args.size() > max_args) throw Exception(help_message, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); String cluster_name; String cluster_description; String remote_database; String remote_table; ASTPtr remote_table_function_ptr; String username; String password; size_t arg_num = 0; auto getStringLiteral = [](const IAST & node, const char * description) { const ASTLiteral * lit = typeid_cast<const ASTLiteral *>(&node); if (!lit) throw Exception(description + String(" must be string literal (in single quotes)."), ErrorCodes::BAD_ARGUMENTS); if (lit->value.getType() != Field::Types::String) throw Exception(description + String(" must be string literal (in single quotes)."), ErrorCodes::BAD_ARGUMENTS); return safeGet<const String &>(lit->value); }; if (is_cluster_function) { ASTPtr ast_name = evaluateConstantExpressionOrIdentifierAsLiteral(args[arg_num], context); cluster_name = static_cast<const ASTLiteral &>(*ast_name).value.safeGet<const String &>(); } else { if (!getIdentifierName(args[arg_num], cluster_name)) cluster_description = getStringLiteral(*args[arg_num], "Hosts pattern"); } ++arg_num; args[arg_num] = evaluateConstantExpressionOrIdentifierAsLiteral(args[arg_num], context); const auto function = typeid_cast<const ASTFunction *>(args[arg_num].get()); if (function && TableFunctionFactory::instance().isTableFunctionName(function->name)) { remote_table_function_ptr = args[arg_num]; ++arg_num; } else { remote_database = static_cast<const ASTLiteral &>(*args[arg_num]).value.safeGet<String>(); ++arg_num; size_t dot = remote_database.find('.'); if (dot != String::npos) { /// NOTE Bad - do not support identifiers in backquotes. remote_table = remote_database.substr(dot + 1); remote_database = remote_database.substr(0, dot); } else { if (arg_num >= args.size()) { throw Exception(help_message, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); } else { args[arg_num] = evaluateConstantExpressionOrIdentifierAsLiteral(args[arg_num], context); remote_table = static_cast<const ASTLiteral &>(*args[arg_num]).value.safeGet<String>(); ++arg_num; } } } /// Username and password parameters are prohibited in cluster version of the function if (!is_cluster_function) { if (arg_num < args.size()) { username = getStringLiteral(*args[arg_num], "Username"); ++arg_num; } else username = "******"; if (arg_num < args.size()) { password = getStringLiteral(*args[arg_num], "Password"); ++arg_num; } } if (arg_num < args.size()) throw Exception(help_message, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); /// ExpressionAnalyzer will be created in InterpreterSelectQuery that will meet these `Identifier` when processing the request. /// We need to mark them as the name of the database or table, because the default value is column. for (auto ast : args) setIdentifierSpecial(ast); ClusterPtr cluster; if (!cluster_name.empty()) { /// Use an existing cluster from the main config cluster = context.getCluster(cluster_name); } else { /// Create new cluster from the scratch size_t max_addresses = context.getSettingsRef().table_function_remote_max_addresses; std::vector<String> shards = parseRemoteDescription(cluster_description, 0, cluster_description.size(), ',', max_addresses); std::vector<std::vector<String>> names; for (size_t i = 0; i < shards.size(); ++i) names.push_back(parseRemoteDescription(shards[i], 0, shards[i].size(), '|', max_addresses)); if (names.empty()) throw Exception("Shard list is empty after parsing first argument", ErrorCodes::BAD_ARGUMENTS); auto maybe_secure_port = context.getTCPPortSecure(); cluster = std::make_shared<Cluster>(context.getSettings(), names, username, password, (secure ? (maybe_secure_port ? *maybe_secure_port : DBMS_DEFAULT_SECURE_PORT) : context.getTCPPort()), false, secure); } auto structure_remote_table = getStructureOfRemoteTable(*cluster, remote_database, remote_table, context, remote_table_function_ptr); StoragePtr res = remote_table_function_ptr ? StorageDistributed::createWithOwnCluster( getName(), structure_remote_table, remote_table_function_ptr, cluster, context) : StorageDistributed::createWithOwnCluster( getName(), structure_remote_table, remote_database, remote_table, cluster, context); res->startup(); return res; }