/** Возможные варианты:
  *
  * 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;
}
Beispiel #4
0
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;
}
Beispiel #7
0
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;
}
Beispiel #9
0
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;
}
Beispiel #10
0
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;
}
Beispiel #14
0
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;
}
Beispiel #15
0
  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";
        }
      }
    }
  }
Beispiel #16
0
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 };
}