/** Возможные варианты: * * 12345 * - целое число * * 0.12345 * .12345 * 0. * - дробь в обычной десятичной записи * * 1.23e-1 * - дробь в инженерной десятичной записи * * 123 / 456 * - дробь с произвольным знаменателем * * На всякий случай, в числителе и знаменателе дроби, поддерживаем предыдущие случаи. * Пример: * 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; }
void rewriteEntityInAst(ASTPtr ast, const String & column_name, const Field & value) { ASTSelectQuery & select = typeid_cast<ASTSelectQuery &>(*ast); ASTExpressionList & node = typeid_cast<ASTExpressionList &>(*select.select_expression_list); ASTs & asts = node.children; auto cur = std::make_shared<ASTLiteral>(StringRange(), value); cur->alias = column_name; ASTPtr column_value = cur; bool is_replaced = false; for (size_t i = 0; i < asts.size(); ++i) { if (const ASTIdentifier * identifier = typeid_cast<const ASTIdentifier *>(&* asts[i])) { if (identifier->kind == ASTIdentifier::Kind::Column && identifier->name == column_name) { asts[i] = column_value; is_replaced = true; } } } if (!is_replaced) asts.insert(asts.begin(), column_value); }
bool ParserSubquery::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected) { Pos begin = pos; ASTPtr select_node; ParserString open("("), close(")"); ParserSelectQuery select; ParserWhiteSpaceOrComments ws; if (!open.ignore(pos, end, max_parsed_pos, expected)) return false; ws.ignore(pos, end); if (!select.parse(pos, end, select_node, max_parsed_pos, expected)) return false; ws.ignore(pos, end); if (!close.ignore(pos, end, max_parsed_pos, expected)) return false; node = std::make_shared<ASTSubquery>(StringRange(begin, pos)); typeid_cast<ASTSubquery &>(*node).children.push_back(select_node); return true; }
static bool EntityClass_parse( EntityClass& entityClass, Tokeniser& tokeniser ){ PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, entityClass.m_name ) ); PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser, "{" ) ); tokeniser.nextLine(); StringOutputStream usage( 256 ); StringOutputStream description( 256 ); CopiedString* currentDescription = 0; StringOutputStream* currentString = 0; for (;; ) { const char* key; PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, key ) ); const char* last = string_findFirstSpaceOrTab( key ); CopiedString first( StringRange( key, last ) ); if ( !string_empty( last ) ) { last = string_findFirstNonSpaceOrTab( last ); } if ( currentString != 0 && string_equal( key, "\\" ) ) { tokeniser.nextLine(); *currentString << " "; PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, *currentString ) ); continue; } if ( currentDescription != 0 ) { *currentDescription = description.c_str(); description.clear(); currentDescription = 0; } currentString = 0; if ( string_equal( key, "}" ) ) { tokeniser.nextLine(); break; } else if ( string_equal( key, "model" ) ) { const char* token; PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, token ) ); entityClass.fixedsize = true; StringOutputStream buffer( 256 ); buffer << PathCleaned( token ); entityClass.m_modelpath = buffer.c_str(); } else if ( string_equal( key, "editor_color" ) ) { const char* value; PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, value ) ); if ( !string_empty( value ) ) { entityClass.colorSpecified = true; bool success = string_parse_vector3( value, entityClass.color ); ASSERT_MESSAGE( success, "editor_color: parse error" ); } } else if ( string_equal( key, "editor_ragdoll" ) ) { //bool ragdoll = atoi(tokeniser.getToken()) != 0; PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); } else if ( string_equal( key, "editor_mins" ) ) { entityClass.sizeSpecified = true; const char* value; PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, value ) ); if ( !string_empty( value ) && !string_equal( value, "?" ) ) { entityClass.fixedsize = true; bool success = string_parse_vector3( value, entityClass.mins ); ASSERT_MESSAGE( success, "editor_mins: parse error" ); } } else if ( string_equal( key, "editor_maxs" ) ) { entityClass.sizeSpecified = true; const char* value; PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, value ) ); if ( !string_empty( value ) && !string_equal( value, "?" ) ) { entityClass.fixedsize = true; bool success = string_parse_vector3( value, entityClass.maxs ); ASSERT_MESSAGE( success, "editor_maxs: parse error" ); } } else if ( string_equal( key, "editor_usage" ) ) { PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, usage ) ); currentString = &usage; } else if ( string_equal_n( key, "editor_usage", 12 ) ) { PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, usage ) ); currentString = &usage; } else if ( string_equal( key, "editor_rotatable" ) || string_equal( key, "editor_showangle" ) || string_equal( key, "editor_showangles" ) // typo? in prey movables.def || string_equal( key, "editor_mover" ) || string_equal( key, "editor_model" ) || string_equal( key, "editor_material" ) || string_equal( key, "editor_combatnode" ) || ( !string_empty( last ) && string_equal( first.c_str(), "editor_gui" ) ) || string_equal_n( key, "editor_copy", 11 ) ) { PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); } else if ( !string_empty( last ) && ( string_equal( first.c_str(), "editor_var" ) || string_equal( first.c_str(), "editor_string" ) ) ) { EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second; attribute.m_type = "string"; currentDescription = &attribute.m_description; currentString = &description; PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); } else if ( !string_empty( last ) && string_equal( first.c_str(), "editor_float" ) ) { EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second; attribute.m_type = "string"; currentDescription = &attribute.m_description; currentString = &description; PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); } else if ( !string_empty( last ) && string_equal( first.c_str(), "editor_snd" ) ) { EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second; attribute.m_type = "sound"; currentDescription = &attribute.m_description; currentString = &description; PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); } else if ( !string_empty( last ) && string_equal( first.c_str(), "editor_bool" ) ) { EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second; attribute.m_type = "boolean"; currentDescription = &attribute.m_description; currentString = &description; PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); } else if ( !string_empty( last ) && string_equal( first.c_str(), "editor_int" ) ) { EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second; attribute.m_type = "integer"; currentDescription = &attribute.m_description; currentString = &description; PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); } else if ( !string_empty( last ) && string_equal( first.c_str(), "editor_model" ) ) { EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second; attribute.m_type = "model"; currentDescription = &attribute.m_description; currentString = &description; PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); } else if ( !string_empty( last ) && string_equal( first.c_str(), "editor_color" ) ) { EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second; attribute.m_type = "color"; currentDescription = &attribute.m_description; currentString = &description; PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); } else if ( !string_empty( last ) && ( string_equal( first.c_str(), "editor_material" ) || string_equal( first.c_str(), "editor_mat" ) ) ) { EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second; attribute.m_type = "shader"; currentDescription = &attribute.m_description; currentString = &description; PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); } else if ( string_equal( key, "inherit" ) ) { entityClass.inheritanceResolved = false; ASSERT_MESSAGE( entityClass.m_parent.empty(), "only one 'inherit' supported per entityDef" ); const char* token; PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, token ) ); entityClass.m_parent.push_back( token ); } // begin quake4-specific keys else if ( string_equal( key, "editor_targetonsel" ) ) { //const char* value = PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); } else if ( string_equal( key, "editor_menu" ) ) { //const char* value = PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); } else if ( string_equal( key, "editor_ignore" ) ) { //const char* value = PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); } // end quake4-specific keys // begin ignore prey (unknown/unused?) entity keys else if ( string_equal( key, "editor_light" ) || string_equal( key, "editor_def def_debrisspawner" ) || string_equal( key, "editor_def def_drop" ) || string_equal( key, "editor_def def_guihand" ) || string_equal( key, "editor_def def_mine" ) ) { //const char* value = PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); } // end ignore prey entity keys else { CopiedString tmp( key ); if ( string_equal_n( key, "editor_", 7 ) ) { globalErrorStream() << "unsupported editor key " << makeQuoted( key ) ; } EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, key ).second; attribute.m_type = "string"; const char* value; PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, value ) ); if ( string_equal( value, "}" ) ) { // hack for quake4 powerups.def bug globalErrorStream() << "entityDef " << makeQuoted( entityClass.m_name.c_str() ) << " key " << makeQuoted( tmp.c_str() ) << " has no value\n"; break; } else { attribute.m_value = value; } } tokeniser.nextLine(); } entityClass.m_comments = usage.c_str(); if ( string_equal( entityClass.m_name.c_str(), "light" ) ) { { EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, "light_radius" ).second; attribute.m_type = "vector3"; attribute.m_value = "300 300 300"; } { EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, "light_center" ).second; attribute.m_type = "vector3"; } { EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, "noshadows" ).second; attribute.m_type = "boolean"; attribute.m_value = "0"; } { EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, "nospecular" ).second; attribute.m_type = "boolean"; attribute.m_value = "0"; } { EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, "nodiffuse" ).second; attribute.m_type = "boolean"; attribute.m_value = "0"; } { EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, "falloff" ).second; attribute.m_type = "real"; } } return true; }
void StorageDistributed::reshardPartitions(ASTPtr query, const String & database_name, const Field & first_partition, const Field & last_partition, const WeightedZooKeeperPaths & weighted_zookeeper_paths, const ASTPtr & sharding_key_expr, bool do_copy, const Field & coordinator, const Settings & settings) { auto & resharding_worker = context.getReshardingWorker(); if (!resharding_worker.isStarted()) throw Exception{"Resharding background thread is not running", ErrorCodes::RESHARDING_NO_WORKER}; if (!coordinator.isNull()) throw Exception{"Use of COORDINATE WITH is forbidden in ALTER TABLE ... RESHARD" " queries for distributed tables", ErrorCodes::RESHARDING_INVALID_PARAMETERS}; std::string coordinator_id = resharding_worker.createCoordinator(cluster); std::atomic<bool> has_notified_error{false}; std::string dumped_coordinator_state; auto handle_exception = [&](const std::string & msg = "") { try { if (!has_notified_error) resharding_worker.setStatus(coordinator_id, ReshardingWorker::STATUS_ERROR, msg); dumped_coordinator_state = resharding_worker.dumpCoordinatorState(coordinator_id); resharding_worker.deleteCoordinator(coordinator_id); } catch (...) { tryLogCurrentException(__PRETTY_FUNCTION__); } }; try { /// Создать запрос ALTER TABLE ... RESHARD [COPY] PARTITION ... COORDINATE WITH ... ASTPtr alter_query_ptr = std::make_shared<ASTAlterQuery>(); auto & alter_query = static_cast<ASTAlterQuery &>(*alter_query_ptr); alter_query.database = remote_database; alter_query.table = remote_table; alter_query.parameters.emplace_back(); ASTAlterQuery::Parameters & parameters = alter_query.parameters.back(); parameters.type = ASTAlterQuery::RESHARD_PARTITION; if (!first_partition.isNull()) parameters.partition = std::make_shared<ASTLiteral>(StringRange(), first_partition); if (!last_partition.isNull()) parameters.last_partition = std::make_shared<ASTLiteral>(StringRange(), last_partition); ASTPtr expr_list = std::make_shared<ASTExpressionList>(); for (const auto & entry : weighted_zookeeper_paths) { ASTPtr weighted_path_ptr = std::make_shared<ASTWeightedZooKeeperPath>(); auto & weighted_path = static_cast<ASTWeightedZooKeeperPath &>(*weighted_path_ptr); weighted_path.path = entry.first; weighted_path.weight = entry.second; expr_list->children.push_back(weighted_path_ptr); } parameters.weighted_zookeeper_paths = expr_list; parameters.sharding_key_expr = sharding_key_expr; parameters.do_copy = do_copy; parameters.coordinator = std::make_shared<ASTLiteral>(StringRange(), Field(coordinator_id)); resharding_worker.registerQuery(coordinator_id, queryToString(alter_query_ptr)); /** Функциональность shard_multiplexing не доделана - выключаем её. * (Потому что установка соединений с разными шардами в рамках одного потока выполняется не параллельно.) * Подробнее смотрите в https://███████████.yandex-team.ru/METR-18300 */ bool enable_shard_multiplexing = false; ClusterProxy::AlterQueryConstructor alter_query_constructor; BlockInputStreams streams = ClusterProxy::Query{alter_query_constructor, cluster, alter_query_ptr, context, settings, enable_shard_multiplexing}.execute(); /// This callback is called if an exception has occurred while attempting to read /// a block from a shard. This is to avoid a potential deadlock if other shards are /// waiting inside a barrier. Actually, even without this solution, we would avoid /// such a deadlock because we would eventually time out while trying to get remote /// blocks. Nevertheless this is not the ideal way of sorting out this issue since /// we would then not get to know the actual cause of the failure. auto exception_callback = [&resharding_worker, coordinator_id, &has_notified_error]() { try { resharding_worker.setStatus(coordinator_id, ReshardingWorker::STATUS_ERROR); has_notified_error = true; } catch (...) { tryLogCurrentException(__PRETTY_FUNCTION__); } }; streams[0] = std::make_shared<UnionBlockInputStream<>>( streams, nullptr, settings.max_distributed_connections, exception_callback); streams.resize(1); auto stream_ptr = dynamic_cast<IProfilingBlockInputStream *>(&*streams[0]); if (stream_ptr == nullptr) throw Exception{"StorageDistributed: Internal error", ErrorCodes::LOGICAL_ERROR}; auto & stream = *stream_ptr; stream.readPrefix(); while (!stream.isCancelled() && stream.read()) ; if (!stream.isCancelled()) stream.readSuffix(); } catch (const Exception & ex) { handle_exception(ex.message()); LOG_ERROR(log, dumped_coordinator_state); throw; } catch (const std::exception & ex) { handle_exception(ex.what()); LOG_ERROR(log, dumped_coordinator_state); throw; } catch (...) { handle_exception(); LOG_ERROR(log, dumped_coordinator_state); throw; } }
bool ParserInsertQuery::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected) { Pos begin = pos; ParserWhiteSpaceOrComments ws; ParserString s_insert("INSERT", true, true); ParserString s_into("INTO", true, true); ParserString s_dot("."); ParserString s_id("ID"); ParserString s_eq("="); ParserStringLiteral id_p; ParserString s_values("VALUES", true, true); ParserString s_format("FORMAT", true, true); ParserString s_select("SELECT", true, true); ParserString s_lparen("("); ParserString 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; ASTPtr id; /// Данные для вставки const char * data = nullptr; ws.ignore(pos, end); /// INSERT INTO if (!s_insert.ignore(pos, end, max_parsed_pos, expected) || !ws.ignore(pos, end) || !s_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); if (s_id.ignore(pos, end, max_parsed_pos, expected)) { if (!s_eq.ignore(pos, end, max_parsed_pos, expected)) return false; ws.ignore(pos, end); if (!id_p.parse(pos, end, id, max_parsed_pos, expected)) return false; } ws.ignore(pos, end); /// Есть ли список столбцов 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 или FORMAT или 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; /// Данные начинаются после первого перевода строки, если такой есть, или после всех пробельных символов, иначе. 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 (id) query->insert_id = safeGet<const String &>(typeid_cast<ASTLiteral &>(*id).value); 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; }
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 ParserShowTablesQuery::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected) { Pos begin = pos; ParserWhiteSpaceOrComments ws; ParserString s_show("SHOW", true, true); ParserString s_tables("TABLES", true, true); ParserString s_databases("DATABASES", true, true); ParserString s_from("FROM", true, true); ParserString s_not("NOT", true, true); ParserString s_like("LIKE", true, true); ParserStringLiteral like_p; ParserIdentifier name_p; ASTPtr like; ASTPtr database; auto query = std::make_shared<ASTShowTablesQuery>(); ws.ignore(pos, end); if (!s_show.ignore(pos, end, max_parsed_pos, expected)) return false; ws.ignore(pos, end); if (s_databases.ignore(pos, end)) { query->databases = true; } else if (s_tables.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if (s_from.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if (!name_p.parse(pos, end, database, max_parsed_pos, expected)) return false; } ws.ignore(pos, end); if (s_not.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); query->not_like = true; } if (s_like.ignore(pos, end, max_parsed_pos, expected)) { ws.ignore(pos, end); if (!like_p.parse(pos, end, like, max_parsed_pos, expected)) return false; } else if (query->not_like) return false; } else return false; ws.ignore(pos, end); query->range = StringRange(begin, pos); if (database) query->from = typeid_cast<ASTIdentifier &>(*database).name; if (like) query->like = safeGet<const String &>(typeid_cast<ASTLiteral &>(*like).value); 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; }
void RunBSP(const char* name) { // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=503 // make sure we don't attempt to region compile a map with the camera outside the region if (region_active && !Region_cameraValid()) { globalErrorStream() << "The camera must be in the region to start a region compile.\n"; return; } SaveMap(); if(Map_Unnamed(g_map)) { globalOutputStream() << "build cancelled\n"; return; } if (g_SnapShots_Enabled && !Map_Unnamed(g_map) && Map_Modified(g_map)) { Map_Snapshot(); } if (region_active) { const char* mapname = Map_Name(g_map); StringOutputStream name(256); name << StringRange(mapname, path_get_filename_base_end(mapname)) << ".reg"; Map_SaveRegion(name.c_str()); } Pointfile_Delete(); bsp_init(); if (g_WatchBSP_Enabled) { ArrayCommandListener listener; build_run(name, listener); // grab the file name for engine running const char* fullname = Map_Name(g_map); StringOutputStream bspname(64); bspname << StringRange(path_get_filename_start(fullname), path_get_filename_base_end(fullname)); BuildMonitor_Run( listener.array(), bspname.c_str() ); } else { char junkpath[PATH_MAX]; strcpy(junkpath, SettingsPath_get()); strcat(junkpath, "junk.txt"); char batpath[PATH_MAX]; #if defined(POSIX) strcpy(batpath, SettingsPath_get()); strcat(batpath, "qe3bsp.sh"); #elif defined(WIN32) strcpy(batpath, SettingsPath_get()); strcat(batpath, "qe3bsp.bat"); #else #error "unsupported platform" #endif bool written = false; { TextFileOutputStream batchFile(batpath); if(!batchFile.failed()) { #if defined (POSIX) batchFile << "#!/bin/sh \n\n"; #endif BatchCommandListener listener(batchFile, junkpath); build_run(name, listener); written = true; } } if(written) { #if defined (POSIX) chmod (batpath, 0744); #endif globalOutputStream() << "Writing the compile script to '" << batpath << "'\n"; globalOutputStream() << "The build output will be saved in '" << junkpath << "'\n"; Q_Exec(batpath, NULL, NULL, true); } } bsp_shutdown(); }
bool ParserNumber::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected) { Field res; Pos begin = pos; if (pos == end) return false; /** Maximum length of number. 319 symbols is enough to write maximum double in decimal form. * Copy is needed to use strto* functions, which require 0-terminated string. */ char buf[320]; size_t bytes_to_copy = end - pos < 319 ? end - pos : 319; memcpy(buf, pos, bytes_to_copy); buf[bytes_to_copy] = 0; char * pos_double = buf; errno = 0; /// Functions strto* don't clear errno. Float64 float_value = std::strtod(buf, &pos_double); if (pos_double == buf || errno == ERANGE) { expected = "number"; return false; } /// excessive "word" symbols after number if (pos_double < buf + bytes_to_copy && ((*pos_double >= 'a' && *pos_double <= 'z') || (*pos_double >= 'A' && *pos_double <= 'Z') || (*pos_double == '_') || (*pos_double >= '0' && *pos_double <= '9'))) { expected = "number"; return false; } res = float_value; /// try to use more exact type: UInt64 or Int64 char * pos_integer = buf; if (float_value < 0) { errno = 0; Int64 int_value = std::strtoll(buf, &pos_integer, 0); if (pos_integer == pos_double && errno != ERANGE) res = int_value; } else { errno = 0; UInt64 uint_value = std::strtoull(buf, &pos_integer, 0); if (pos_integer == pos_double && errno != ERANGE) res = uint_value; } pos += pos_double - buf; node = std::make_shared<ASTLiteral>(StringRange(begin, pos), res); return true; }
bool ParserCastExpression::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected) { const auto begin = pos; ParserIdentifier id_parser; ASTPtr identifier; if (!id_parser.parse(pos, end, identifier, max_parsed_pos, expected)) return false; const auto & id = typeid_cast<const ASTIdentifier &>(*identifier).name; if (id.length() != strlen(name) || 0 != strcasecmp(id.c_str(), name)) { /// Parse as a CASE expression. return ParserCase{}.parse(pos = begin, end, node, max_parsed_pos, expected); } /// Parse as CAST(expression AS type) ParserString open("("), close(")"), comma(","); ParserExpressionInCastExpression expression_and_type(false); ParserWhiteSpaceOrComments ws; ASTPtr expr_list_args; ws.ignore(pos, end); if (!open.ignore(pos, end, max_parsed_pos, expected)) return false; ws.ignore(pos, end); const auto contents_begin = pos; ASTPtr first_argument; if (!expression_and_type.parse(pos, end, first_argument, max_parsed_pos, expected)) return false; ws.ignore(pos, end); /// check for subsequent comma "," if (!comma.ignore(pos, end, max_parsed_pos, expected)) { /// CAST(expression AS type) const auto type = first_argument->tryGetAlias(); if (type.empty()) { /// there is only one argument and it has no alias expected = "type identifier"; return false; } expr_list_args = std::make_shared<ASTExpressionList>(StringRange{contents_begin, end}); first_argument->setAlias({}); expr_list_args->children.push_back(first_argument); expr_list_args->children.emplace_back(std::make_shared<ASTLiteral>(StringRange(), type)); } else { /// CAST(expression, 'type') /// Reparse argument list from scratch max_parsed_pos = pos = contents_begin; ParserExpressionWithOptionalAlias expression{false}; if (!expression.parse(pos, end, first_argument, max_parsed_pos, expected)) return false; ws.ignore(pos, end, max_parsed_pos, expected); if (!comma.ignore(pos, end, max_parsed_pos, expected)) return false; ws.ignore(pos, end, max_parsed_pos, expected); ParserStringLiteral p_type; ASTPtr type_as_literal; if (!p_type.parse(pos, end, type_as_literal, max_parsed_pos, expected)) { expected = "string literal depicting type"; return false; } expr_list_args = std::make_shared<ASTExpressionList>(StringRange{contents_begin, end}); expr_list_args->children.push_back(first_argument); expr_list_args->children.push_back(type_as_literal); } ws.ignore(pos, end); if (!close.ignore(pos, end, max_parsed_pos, expected)) { expected = ")"; return false; } const auto function_node = std::make_shared<ASTFunction>(StringRange(begin, pos)); ASTPtr node_holder{function_node}; function_node->name = name; function_node->arguments = expr_list_args; function_node->children.push_back(function_node->arguments); node = node_holder; return true; }
bool ParserFunction::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected) { Pos begin = pos; ParserIdentifier id_parser; ParserString open("("), close(")"); ParserExpressionList contents(false); ParserWhiteSpaceOrComments ws; ASTPtr identifier; ASTPtr expr_list_args; ASTPtr expr_list_params; if (!id_parser.parse(pos, end, identifier, max_parsed_pos, expected)) return false; ws.ignore(pos, end); if (!open.ignore(pos, end, max_parsed_pos, expected)) return false; ws.ignore(pos, end); Pos contents_begin = pos; if (!contents.parse(pos, end, expr_list_args, max_parsed_pos, expected)) return false; Pos contents_end = pos; ws.ignore(pos, end); if (!close.ignore(pos, end, max_parsed_pos, expected)) return false; /** Проверка на распространённый случай ошибки - часто из-за сложности квотирования аргументов командной строки, * в запрос попадает выражение вида toDate(2014-01-01) вместо toDate('2014-01-01'). * Если не сообщить, что первый вариант - ошибка, то аргумент будет проинтерпретирован как 2014 - 01 - 01 - некоторое число, * и запрос тихо вернёт неожиданный результат. */ if (typeid_cast<const ASTIdentifier &>(*identifier).name == "toDate" && contents_end - contents_begin == strlen("2014-01-01") && contents_begin[0] >= '2' && contents_begin[0] <= '3' && contents_begin[1] >= '0' && contents_begin[1] <= '9' && contents_begin[2] >= '0' && contents_begin[2] <= '9' && contents_begin[3] >= '0' && contents_begin[3] <= '9' && contents_begin[4] == '-' && contents_begin[5] >= '0' && contents_begin[5] <= '9' && contents_begin[6] >= '0' && contents_begin[6] <= '9' && contents_begin[7] == '-' && contents_begin[8] >= '0' && contents_begin[8] <= '9' && contents_begin[9] >= '0' && contents_begin[9] <= '9') { std::string contents(contents_begin, contents_end - contents_begin); throw Exception("Argument of function toDate is unquoted: toDate(" + contents + "), must be: toDate('" + contents + "')" , ErrorCodes::SYNTAX_ERROR); } /// У параметрической агрегатной функции - два списка (параметры и аргументы) в круглых скобках. Пример: quantile(0.9)(x). if (open.ignore(pos, end, max_parsed_pos, expected)) { expr_list_params = expr_list_args; expr_list_args = nullptr; ws.ignore(pos, end); if (!contents.parse(pos, end, expr_list_args, max_parsed_pos, expected)) return false; ws.ignore(pos, end); if (!close.ignore(pos, end, max_parsed_pos, expected)) return false; } auto function_node = std::make_shared<ASTFunction>(StringRange(begin, pos)); ASTPtr node_holder{function_node}; function_node->name = typeid_cast<ASTIdentifier &>(*identifier).name; function_node->arguments = expr_list_args; function_node->children.push_back(function_node->arguments); if (expr_list_params) { function_node->parameters = expr_list_params; function_node->children.push_back(function_node->parameters); } node = node_holder; 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; }
void visit(const char* name, Accelerator& accelerator) { char value[1024]; if (read_var(m_filename, "Commands", name, value )) { if(string_empty(value)) { accelerator.key = 0; accelerator.modifiers = (GdkModifierType)0; return; } int modifiers = 0; const char* last = value + string_length(value); const char* keyEnd = stringrange_find(value, last, '+'); for(const char* modifier = keyEnd; modifier != last;) { const char* next = stringrange_find(modifier + 1, last, '+'); if(next - modifier == 4 && string_equal_nocase_n(modifier, "+alt", 4)) { modifiers |= GDK_MOD1_MASK; } else if(next - modifier == 5 && string_equal_nocase_n(modifier, "+ctrl", 5) != 0) { modifiers |= GDK_CONTROL_MASK; } else if(next - modifier == 6 && string_equal_nocase_n(modifier, "+shift", 6) != 0) { modifiers |= GDK_SHIFT_MASK; } else { globalOutputStream() << "WARNING: failed to parse user command " << makeQuoted(value) << ": unknown modifier " << makeQuoted(StringRange(modifier, next)) << "\n"; } modifier = next; } accelerator.modifiers = (GdkModifierType)modifiers; // strBuff has been cleaned of it's modifiers .. switch between a regular key and a virtual one // based on length if(keyEnd - value == 1) // most often case.. deal with first { accelerator.key = std::toupper(value[0]); ++m_count; } else // special key { CopiedString keyName(StringRange(value, keyEnd)); accelerator.key = global_keys_find(keyName.c_str()); if(accelerator.key != 0) { ++m_count; } else { globalOutputStream() << "WARNING: failed to parse user command " << makeQuoted(value) << ": unknown key " << makeQuoted(keyName.c_str()) << "\n"; } } } }
void Pointfile_Parse(CPointfile& pointfile) { int size; char *data; char *text; int line = 1; const char* mapname = Map_Name(g_map); StringOutputStream name(256); name << StringRange(mapname, path_get_filename_base_end(mapname)) << ".lin"; size = LoadFile (name.c_str(), (void**)&data); if (size == -1) { globalErrorStream() << "Pointfile " << name.c_str() << " not found\n"; return; } // store a pointer text = data; globalOutputStream() << "Reading pointfile " << name.c_str() << "\n"; pointfile.Init(); while (*data) { Vector3 v; if (sscanf(data,"%f %f %f", &v[0], &v[1], &v[2]) != 3) { globalOutputStream() << "Corrupt point file, line " << line << "\n"; break; } while (*data && *data != '\n') { if (*(data-1) == ' ' && *(data) == '-' && *(data+1) == ' ') break; data++; } // deal with zhlt style point files. if (*data == '-') { if (sscanf(data,"- %f %f %f", &v[0], &v[1], &v[2]) != 3) { globalOutputStream() << "Corrupt point file, line " << line << "\n"; break; } while (*data && *data != '\n') data++; } while (*data == '\n') { data++; // skip the \n line++; } pointfile.PushPoint (v); } g_free(text); }
/// AST в список столбцов с типами. Столбцы типа Nested развернуты в список настоящих столбцов. static ColumnsAndDefaults parseColumns( ASTPtr expression_list, const Context & context) { auto & column_list_ast = typeid_cast<ASTExpressionList &>(*expression_list); /// list of table columns in correct order NamesAndTypesList columns{}; ColumnDefaults defaults{}; /// Columns requiring type-deduction or default_expression type-check std::vector<std::pair<NameAndTypePair *, ASTColumnDeclaration *>> defaulted_columns{}; /** all default_expressions as a single expression list, * mixed with conversion-columns for each explicitly specified type */ ASTPtr default_expr_list = std::make_shared<ASTExpressionList>(); default_expr_list->children.reserve(column_list_ast.children.size()); const DataTypeFactory & data_type_factory = DataTypeFactory::instance(); for (auto & ast : column_list_ast.children) { auto & col_decl = typeid_cast<ASTColumnDeclaration &>(*ast); if (col_decl.type) { const auto & type_range = col_decl.type->range; columns.emplace_back(col_decl.name, data_type_factory.get({ type_range.first, type_range.second })); } else /// we're creating dummy DataTypeUInt8 in order to prevent the NullPointerException in ExpressionActions columns.emplace_back(col_decl.name, std::make_shared<DataTypeUInt8>()); /// add column to postprocessing if there is a default_expression specified if (col_decl.default_expression) { defaulted_columns.emplace_back(&columns.back(), &col_decl); /** for columns with explicitly-specified type create two expressions: * 1. default_expression aliased as column name with _tmp suffix * 2. conversion of expression (1) to explicitly-specified type alias as column name */ if (col_decl.type) { const auto & final_column_name = col_decl.name; const auto tmp_column_name = final_column_name + "_tmp"; const auto data_type_ptr = columns.back().type.get(); default_expr_list->children.emplace_back(setAlias( makeASTFunction("CAST", std::make_shared<ASTIdentifier>(StringRange(), tmp_column_name), std::make_shared<ASTLiteral>(StringRange(), Field(data_type_ptr->getName()))), final_column_name)); default_expr_list->children.emplace_back(setAlias(col_decl.default_expression->clone(), tmp_column_name)); } else default_expr_list->children.emplace_back(setAlias(col_decl.default_expression->clone(), col_decl.name)); } } /// set missing types and wrap default_expression's in a conversion-function if necessary if (!defaulted_columns.empty()) { const auto actions = ExpressionAnalyzer{default_expr_list, context, {}, columns} .getActions(true); const auto block = actions->getSampleBlock(); for (auto & column : defaulted_columns) { const auto name_and_type_ptr = column.first; const auto col_decl_ptr = column.second; const auto & column_name = col_decl_ptr->name; const auto has_explicit_type = nullptr != col_decl_ptr->type; auto & explicit_type = name_and_type_ptr->type; /// if column declaration contains explicit type, name_and_type_ptr->type is not null if (has_explicit_type) { const auto & tmp_column = block.getByName(column_name + "_tmp"); const auto & deduced_type = tmp_column.type; /// type mismatch between explicitly specified and deduced type, add conversion for non-array types if (explicit_type->getName() != deduced_type->getName()) { col_decl_ptr->default_expression = makeASTFunction("CAST", col_decl_ptr->default_expression, std::make_shared<ASTLiteral>(StringRange(), explicit_type->getName())); col_decl_ptr->children.clear(); col_decl_ptr->children.push_back(col_decl_ptr->type); col_decl_ptr->children.push_back(col_decl_ptr->default_expression); } } else /// no explicit type, name_and_type_ptr->type is null, set to deduced type explicit_type = block.getByName(column_name).type; defaults.emplace(column_name, ColumnDefault{ columnDefaultTypeFromString(col_decl_ptr->default_specifier), col_decl_ptr->default_expression }); } } return { *DataTypeNested::expandNestedColumns(columns), defaults }; }