bool ParserNestedTable::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
    ParserToken open(TokenType::OpeningRoundBracket);
    ParserToken close(TokenType::ClosingRoundBracket);
    ParserIdentifier name_p;
    ParserNameTypePairList columns_p;

    ASTPtr name;
    ASTPtr columns;

    /// For now `name == 'Nested'`, probably alternative nested data structures will appear
    if (!name_p.parse(pos, name, expected))
        return false;

    if (!open.ignore(pos))
        return false;

    if (!columns_p.parse(pos, columns, expected))
        return false;

    if (!close.ignore(pos))
        return false;

    auto func = std::make_shared<ASTFunction>();
    getIdentifierName(name, func->name);
    func->arguments = columns;
    func->children.push_back(columns);
    node = func;

    return true;
}
bool ParserIdentifierWithOptionalParameters::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
    ParserIdentifier non_parametric;
    ParserIdentifierWithParameters parametric;

    if (parametric.parse(pos, node, expected))
        return true;

    ASTPtr ident;
    if (non_parametric.parse(pos, ident, expected))
    {
        auto func = std::make_shared<ASTFunction>();
        getIdentifierName(ident, func->name);
        node = func;
        return true;
    }

    return false;
}
Example #3
0
/*
Function: displayIdentifierAttributes() const

Description: This function will print out all of the attributes associated 
with a symbol table entry. 
*/
void symbolTableEntry::displayIdentifierAttributes(int tabCount) const {
	int idNumTemp = 0;
	std::string idTemp = getIdentifierName();
	printTabs(tabCount);
	std::cout << "Identifier name: " << idTemp << std::endl;
	idTemp = getIdentifierType_String();
	printTabs(tabCount);
	std::cout << "Identifier type: " << idTemp << std::endl;
	printTabs(tabCount);
	std::cout << "Identifier value: ";
	printIdentifierValue(); 
	std::cout << std::endl;
	//!!!!!!!!!!!!!!!!! CHECK THIS LATER !!!!!!!!!!!
	
	if (isFunc) {
		idNumTemp = getNumParams(); 
		std::cout << "Identifier is a function." << std::endl;
		std::cout << "Identifier has " << idNumTemp << " parameters.";
		std::cout << std::endl; 
		std::cout << "Identifier parameters: " << std::endl;
		viewParams(); 
	}

	else if (isPtr) {
		idNumTemp = getNumPtrs();
		std::cout << "Identifier is a pointer." << std::endl;
		std::cout << "Identifier has " << idNumTemp << " parameters.";
		std::cout << std::endl; 
	}

	else if (isArr) {
		idNumTemp = getNumArrDims();
		std::cout << "Identifier is an array." << std::endl;
		std::cout << "Identifier has " << idNumTemp << " dimensions.";
		std::cout << std::endl;
		std::cout << "Identifier dimensions: " << std::endl;
		for (unsigned int i = 0; i < arrayDimensions.size(); i++) {
			std::cout << "Dimension #" << i << " :" << arrayDimensions[i] << std::endl; 
		} 
	}
}
bool ParserInsertQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
    ParserKeyword s_insert_into("INSERT INTO");
    ParserKeyword s_table("TABLE");
    ParserKeyword s_function("FUNCTION");
    ParserToken s_dot(TokenType::Dot);
    ParserKeyword s_values("VALUES");
    ParserKeyword s_format("FORMAT");
    ParserKeyword s_select("SELECT");
    ParserKeyword s_with("WITH");
    ParserToken s_lparen(TokenType::OpeningRoundBracket);
    ParserToken s_rparen(TokenType::ClosingRoundBracket);
    ParserIdentifier name_p;
    ParserList columns_p(std::make_unique<ParserCompoundIdentifier>(), std::make_unique<ParserToken>(TokenType::Comma), false);
    ParserFunction table_function_p;

    ASTPtr database;
    ASTPtr table;
    ASTPtr columns;
    ASTPtr format;
    ASTPtr select;
    ASTPtr table_function;
    /// Insertion data
    const char * data = nullptr;

    if (!s_insert_into.ignore(pos, expected))
        return false;

    s_table.ignore(pos, expected);

    if (s_function.ignore(pos, expected))
    {
        if (!table_function_p.parse(pos, table_function, expected))
            return false;
    }
    else
    {
        if (!name_p.parse(pos, table, expected))
            return false;

        if (s_dot.ignore(pos, expected))
        {
            database = table;
            if (!name_p.parse(pos, table, expected))
                return false;
        }
    }

    /// Is there a list of columns
    if (s_lparen.ignore(pos, expected))
    {
        if (!columns_p.parse(pos, columns, expected))
            return false;

        if (!s_rparen.ignore(pos, expected))
            return false;
    }

    Pos before_select = pos;

    /// VALUES or FORMAT or SELECT
    if (s_values.ignore(pos, expected))
    {
        data = pos->begin;
    }
    else if (s_format.ignore(pos, expected))
    {
        auto name_pos = pos;

        if (!name_p.parse(pos, format, expected))
            return false;

        data = name_pos->end;

        if (data < end && *data == ';')
            throw Exception("You have excessive ';' symbol before data for INSERT.\n"
                                    "Example:\n\n"
                                    "INSERT INTO t (x, y) FORMAT TabSeparated\n"
                                    ";\tHello\n"
                                    "2\tWorld\n"
                                    "\n"
                                    "Note that there is no ';' just after format name, "
                                    "you need to put at least one whitespace symbol before the data.", ErrorCodes::SYNTAX_ERROR);

        while (data < end && (*data == ' ' || *data == '\t' || *data == '\f'))
            ++data;

        /// Data starts after the first newline, if there is one, or after all the whitespace characters, otherwise.

        if (data < end && *data == '\r')
            ++data;

        if (data < end && *data == '\n')
            ++data;
    }
    else if (s_select.ignore(pos, expected) || s_with.ignore(pos,expected))
    {
        pos = before_select;
        ParserSelectWithUnionQuery select_p;
        select_p.parse(pos, select, expected);
    }
    else
    {
        return false;
    }

    auto query = std::make_shared<ASTInsertQuery>();
    node = query;

    if (table_function)
    {
        query->table_function = table_function;
    }
    else
    {
        getIdentifierName(database, query->database);
        getIdentifierName(table, query->table);
    }

    getIdentifierName(format, query->format);

    query->columns = columns;
    query->select = select;
    query->data = data != end ? data : nullptr;
    query->end = end;

    if (columns)
        query->children.push_back(columns);
    if (select)
        query->children.push_back(select);

    return true;
}
bool ParserCreateQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
    ParserKeyword s_create("CREATE");
    ParserKeyword s_temporary("TEMPORARY");
    ParserKeyword s_attach("ATTACH");
    ParserKeyword s_table("TABLE");
    ParserKeyword s_database("DATABASE");
    ParserKeyword s_if_not_exists("IF NOT EXISTS");
    ParserKeyword s_as("AS");
    ParserKeyword s_view("VIEW");
    ParserKeyword s_materialized("MATERIALIZED");
    ParserKeyword s_populate("POPULATE");
    ParserToken s_dot(TokenType::Dot);
    ParserToken s_lparen(TokenType::OpeningRoundBracket);
    ParserToken s_rparen(TokenType::ClosingRoundBracket);
    ParserStorage storage_p;
    ParserIdentifier name_p;
    ParserColumnsOrIndicesDeclarationList columns_or_indices_p;
    ParserSelectWithUnionQuery select_p;

    ASTPtr database;
    ASTPtr table;
    ASTPtr columns_list;
    ASTPtr to_database;
    ASTPtr to_table;
    ASTPtr storage;
    ASTPtr as_database;
    ASTPtr as_table;
    ASTPtr select;
    String cluster_str;
    bool attach = false;
    bool if_not_exists = false;
    bool is_view = false;
    bool is_materialized_view = false;
    bool is_populate = false;
    bool is_temporary = false;

    if (!s_create.ignore(pos, expected))
    {
        if (s_attach.ignore(pos, expected))
            attach = true;
        else
            return false;
    }

    if (s_temporary.ignore(pos, expected))
    {
        is_temporary = true;
    }

    if (s_table.ignore(pos, expected))
    {
        if (s_if_not_exists.ignore(pos, expected))
            if_not_exists = true;

        if (!name_p.parse(pos, table, expected))
            return false;

        if (s_dot.ignore(pos, expected))
        {
            database = table;
            if (!name_p.parse(pos, table, expected))
                return false;
        }

        if (ParserKeyword{"ON"}.ignore(pos, expected))
        {
            if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected))
                return false;
        }

        // Shortcut for ATTACH a previously detached table
        if (attach && (!pos.isValid() || pos.get().type == TokenType::Semicolon))
        {
            auto query = std::make_shared<ASTCreateQuery>();
            node = query;

            query->attach = attach;
            query->if_not_exists = if_not_exists;
            query->cluster = cluster_str;

            getIdentifierName(database, query->database);
            getIdentifierName(table, query->table);

            return true;
        }

        /// List of columns.
        if (s_lparen.ignore(pos, expected))
        {
            if (!columns_or_indices_p.parse(pos, columns_list, expected))
                return false;

            if (!s_rparen.ignore(pos, expected))
                return false;

            if (!storage_p.parse(pos, storage, expected) && !is_temporary)
                return false;
        }
        else
        {
            storage_p.parse(pos, storage, expected);

            if (!s_as.ignore(pos, expected))
                return false;

            if (!select_p.parse(pos, select, expected)) /// AS SELECT ...
            {
                /// AS [db.]table
                if (!name_p.parse(pos, as_table, expected))
                    return false;

                if (s_dot.ignore(pos, expected))
                {
                    as_database = as_table;
                    if (!name_p.parse(pos, as_table, expected))
                        return false;
                }

                /// Optional - ENGINE can be specified.
                if (!storage)
                    storage_p.parse(pos, storage, expected);
            }
        }
    }
    else if (is_temporary)
        return false;
    else if (s_database.ignore(pos, expected))
    {
        if (s_if_not_exists.ignore(pos, expected))
            if_not_exists = true;

        if (!name_p.parse(pos, database, expected))
            return false;

        if (ParserKeyword{"ON"}.ignore(pos, expected))
        {
            if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected))
                return false;
        }

        storage_p.parse(pos, storage, expected);
    }
    else
    {
        /// VIEW or MATERIALIZED VIEW
        if (s_materialized.ignore(pos, expected))
        {
            is_materialized_view = true;
        }
        else
            is_view = true;

        if (!s_view.ignore(pos, expected))
            return false;

        if (s_if_not_exists.ignore(pos, expected))
            if_not_exists = true;

        if (!name_p.parse(pos, table, expected))
            return false;

        if (s_dot.ignore(pos, expected))
        {
            database = table;
            if (!name_p.parse(pos, table, expected))
                return false;
        }

        if (ParserKeyword{"ON"}.ignore(pos, expected))
        {
            if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected))
                return false;
        }

        // TO [db.]table
        if (ParserKeyword{"TO"}.ignore(pos, expected))
        {
            if (!name_p.parse(pos, to_table, expected))
                return false;

            if (s_dot.ignore(pos, expected))
            {
                to_database = to_table;
                if (!name_p.parse(pos, to_table, expected))
                    return false;
            }
        }

        /// Optional - a list of columns can be specified. It must fully comply with SELECT.
        if (s_lparen.ignore(pos, expected))
        {
            if (!columns_or_indices_p.parse(pos, columns_list, expected))
                return false;

            if (!s_rparen.ignore(pos, expected))
                return false;
        }

        if (is_materialized_view && !to_table)
        {
            /// Internal ENGINE for MATERIALIZED VIEW must be specified.
            if (!storage_p.parse(pos, storage, expected))
                return false;

            if (s_populate.ignore(pos, expected))
                is_populate = true;
        }

        /// AS SELECT ...
        if (!s_as.ignore(pos, expected))
            return false;

        if (!select_p.parse(pos, select, expected))
            return false;
    }

    auto query = std::make_shared<ASTCreateQuery>();
    node = query;

    query->attach = attach;
    query->if_not_exists = if_not_exists;
    query->is_view = is_view;
    query->is_materialized_view = is_materialized_view;
    query->is_populate = is_populate;
    query->temporary = is_temporary;

    getIdentifierName(database, query->database);
    getIdentifierName(table, query->table);
    query->cluster = cluster_str;

    getIdentifierName(to_database, query->to_database);
    getIdentifierName(to_table, query->to_table);

    query->set(query->columns_list, columns_list);
    query->set(query->storage, storage);

    getIdentifierName(as_database, query->as_database);
    getIdentifierName(as_table, query->as_table);
    query->set(query->select, select);

    return true;
}
Example #6
0
bool ParserDropQuery::parseDropQuery(Pos & pos, ASTPtr & node, Expected & expected)
{
    ParserKeyword s_temporary("TEMPORARY");
    ParserKeyword s_table("TABLE");
    ParserKeyword s_database("DATABASE");
    ParserToken s_dot(TokenType::Dot);
    ParserKeyword s_if_exists("IF EXISTS");
    ParserIdentifier name_p;

    ASTPtr database;
    ASTPtr table;
    String cluster_str;
    bool if_exists = false;
    bool temporary = false;

    if (s_database.ignore(pos, expected))
    {
        if (s_if_exists.ignore(pos, expected))
            if_exists = true;

        if (!name_p.parse(pos, database, expected))
            return false;

        if (ParserKeyword{"ON"}.ignore(pos, expected))
        {
            if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected))
                return false;
        }
    }
    else
    {
        if (s_temporary.ignore(pos, expected))
            temporary = true;

        if (!s_table.ignore(pos, expected))
            return false;

        if (s_if_exists.ignore(pos, expected))
            if_exists = true;

        if (!name_p.parse(pos, table, expected))
            return false;

        if (s_dot.ignore(pos, expected))
        {
            database = table;
            if (!name_p.parse(pos, table, expected))
                return false;
        }

        if (ParserKeyword{"ON"}.ignore(pos, expected))
        {
            if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected))
                return false;
        }
    }

    auto query = std::make_shared<ASTDropQuery>();
    node = query;

    query->kind = ASTDropQuery::Kind::Drop;
    query->if_exists = if_exists;
    query->temporary = temporary;

    getIdentifierName(database, query->database);
    getIdentifierName(table, query->table);

    query->cluster = cluster_str;

    return true;
}
StoragePtr TableFunctionRemote::executeImpl(const ASTPtr & ast_function, const Context & context) const
{
    ASTs & args_func = typeid_cast<ASTFunction &>(*ast_function).children;

    if (args_func.size() != 1)
        throw Exception(help_message, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);

    ASTs & args = typeid_cast<ASTExpressionList &>(*args_func.at(0)).children;

    const size_t max_args = is_cluster_function ? 3 : 5;
    if (args.size() < 2 || args.size() > max_args)
        throw Exception(help_message, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);

    String cluster_name;
    String cluster_description;
    String remote_database;
    String remote_table;
    ASTPtr remote_table_function_ptr;
    String username;
    String password;

    size_t arg_num = 0;

    auto getStringLiteral = [](const IAST & node, const char * description)
    {
        const ASTLiteral * lit = typeid_cast<const ASTLiteral *>(&node);
        if (!lit)
            throw Exception(description + String(" must be string literal (in single quotes)."), ErrorCodes::BAD_ARGUMENTS);

        if (lit->value.getType() != Field::Types::String)
            throw Exception(description + String(" must be string literal (in single quotes)."), ErrorCodes::BAD_ARGUMENTS);

        return safeGet<const String &>(lit->value);
    };

    if (is_cluster_function)
    {
        ASTPtr ast_name = evaluateConstantExpressionOrIdentifierAsLiteral(args[arg_num], context);
        cluster_name = static_cast<const ASTLiteral &>(*ast_name).value.safeGet<const String &>();
    }
    else
    {
        if (!getIdentifierName(args[arg_num], cluster_name))
            cluster_description = getStringLiteral(*args[arg_num], "Hosts pattern");
    }
    ++arg_num;

    args[arg_num] = evaluateConstantExpressionOrIdentifierAsLiteral(args[arg_num], context);

    const auto function = typeid_cast<const ASTFunction *>(args[arg_num].get());

    if (function && TableFunctionFactory::instance().isTableFunctionName(function->name))
    {
        remote_table_function_ptr = args[arg_num];
        ++arg_num;
    }
    else
    {
        remote_database = static_cast<const ASTLiteral &>(*args[arg_num]).value.safeGet<String>();

        ++arg_num;

        size_t dot = remote_database.find('.');
        if (dot != String::npos)
        {
            /// NOTE Bad - do not support identifiers in backquotes.
            remote_table = remote_database.substr(dot + 1);
            remote_database = remote_database.substr(0, dot);
        }
        else
        {
            if (arg_num >= args.size())
            {
                throw Exception(help_message, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
            }
            else
            {
                args[arg_num] = evaluateConstantExpressionOrIdentifierAsLiteral(args[arg_num], context);
                remote_table = static_cast<const ASTLiteral &>(*args[arg_num]).value.safeGet<String>();
                ++arg_num;
            }
        }
    }

    /// Username and password parameters are prohibited in cluster version of the function
    if (!is_cluster_function)
    {
        if (arg_num < args.size())
        {
            username = getStringLiteral(*args[arg_num], "Username");
            ++arg_num;
        }
        else
            username = "******";

        if (arg_num < args.size())
        {
            password = getStringLiteral(*args[arg_num], "Password");
            ++arg_num;
        }
    }

    if (arg_num < args.size())
        throw Exception(help_message, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);

    /// ExpressionAnalyzer will be created in InterpreterSelectQuery that will meet these `Identifier` when processing the request.
    /// We need to mark them as the name of the database or table, because the default value is column.
    for (auto ast : args)
        setIdentifierSpecial(ast);

    ClusterPtr cluster;
    if (!cluster_name.empty())
    {
        /// Use an existing cluster from the main config
        cluster = context.getCluster(cluster_name);
    }
    else
    {
        /// Create new cluster from the scratch
        size_t max_addresses = context.getSettingsRef().table_function_remote_max_addresses;
        std::vector<String> shards = parseRemoteDescription(cluster_description, 0, cluster_description.size(), ',', max_addresses);

        std::vector<std::vector<String>> names;
        for (size_t i = 0; i < shards.size(); ++i)
            names.push_back(parseRemoteDescription(shards[i], 0, shards[i].size(), '|', max_addresses));

        if (names.empty())
            throw Exception("Shard list is empty after parsing first argument", ErrorCodes::BAD_ARGUMENTS);

        auto maybe_secure_port = context.getTCPPortSecure();
        cluster = std::make_shared<Cluster>(context.getSettings(), names, username, password, (secure ? (maybe_secure_port ? *maybe_secure_port : DBMS_DEFAULT_SECURE_PORT) : context.getTCPPort()), false, secure);
    }

    auto structure_remote_table = getStructureOfRemoteTable(*cluster, remote_database, remote_table, context, remote_table_function_ptr);

    StoragePtr res = remote_table_function_ptr
        ? StorageDistributed::createWithOwnCluster(
            getName(),
            structure_remote_table,
            remote_table_function_ptr,
            cluster,
            context)
        : StorageDistributed::createWithOwnCluster(
            getName(),
            structure_remote_table,
            remote_database,
            remote_table,
            cluster,
            context);

    res->startup();
    return res;
}