#ifndef QUERY_DIALECT_HPP #define QUERY_DIALECT_HPP #include "matador/sql/dialect_token.hpp" #include "matador/sql/sql_functions.hpp" #include "matador/utils/basic_types.hpp" #include "matador/utils/types.hpp" #include "matador/utils/string.hpp" #include #include #include #include namespace matador::utils { class value; } namespace matador::sql { class connection_impl; class dialect final { public: /** * Holding enums concerning escaping identifiers */ enum class escape_identifier_t : uint8_t { ESCAPE_BOTH_SAME, /**< The escape quotes are the same */ ESCAPE_CLOSING_BRACKET /**< The escape quotes differ; escape the closing one */ }; using token_to_string_map = std::unordered_map; using data_type_to_string_map = std::unordered_map; using sql_func_to_string_map = std::unordered_map; using next_placeholder_func = std::function; using to_escaped_string_func = std::function; public: [[nodiscard]] const std::string& token_at(dialect_token token) const; [[nodiscard]] const std::string& data_type_at(utils::basic_type type) const; [[nodiscard]] const std::string& sql_function_at(sql_function_t func) const; /** * Prepare sql dialect identifier for execution * and escape quotes and quote the identifier * string * * @param col The identifier string to be prepared * @return The prepared string */ [[nodiscard]] std::string prepare_identifier_string(const std::string &col) const; [[nodiscard]] std::string table_name(const std::string &table, const std::string &schema_name) const; [[nodiscard]] const std::string& to_string(bool val) const; [[nodiscard]] std::string to_sql_string(const utils::value &val) const ; void bool_strings(const std::string &true_string, const std::string &false_string); /** * Prepare string literal * * @param str String literal to be prepared */ [[nodiscard]] std::string prepare_literal(const std::string &str) const; /** * Wrap identifier quotes around a sql identifier keyword * * @param str Identifier to put quotes around */ void quote_identifier(std::string &str) const; /** * Escape identifier quotes inside identifiers. * * @param str Identifier to be escaped */ void escape_quotes_in_identifier(std::string &str) const; /** * Escape quotes in string literals * * @param str String literal to be escaped */ void escape_quotes_in_literals(std::string &str) const; /** * Returns how the identifier quotes should be * escaped. * * @return How the identifier quotes should be escaped */ [[nodiscard]] escape_identifier_t identifier_escape_type() const; /** * Sets the identifier escape type. Possibilities are * opening and closing escape characters are the same * (ESCAPE_BOTH_SAME) or using a special closing * escape character (ESCAPE_CLOSING_BRACKET) * * @param escape_identifier Identifier escape type */ void identifier_escape_type(escape_identifier_t escape_identifier); /** * Generates a next placeholder string. default is * question mark '?' * * @return Placeholder string */ [[nodiscard]] std::string next_placeholder(const std::vector &bind_vars) const; [[nodiscard]] std::string to_escaped_string(const utils::blob &value, const connection_impl *conn = nullptr) const; /** * Returns the default schema name. * * @return The default schema name. */ [[nodiscard]] std::string default_schema_name() const; [[nodiscard]] const std::string& add_constraint() const; [[nodiscard]] const std::string& alter() const; [[nodiscard]] const std::string& and_() const; [[nodiscard]] const std::string& as() const; [[nodiscard]] const std::string& asc() const; [[nodiscard]] const std::string& begin() const; [[nodiscard]] const std::string& asterisk() const; [[nodiscard]] const std::string& begin_binary_data() const; [[nodiscard]] const std::string& begin_string_data() const; [[nodiscard]] const std::string& between() const; [[nodiscard]] const std::string& column() const; [[nodiscard]] const std::string& columns() const; [[nodiscard]] const std::string& commit() const; [[nodiscard]] const std::string& create() const; [[nodiscard]] const std::string& desc() const; [[nodiscard]] const std::string& distinct() const; [[nodiscard]] const std::string& drop() const; [[nodiscard]] const std::string& drop_constraint() const; [[nodiscard]] const std::string& end_binary_data() const; [[nodiscard]] const std::string& end_quote() const; [[nodiscard]] const std::string& end_string_data() const; [[nodiscard]] const std::string& foreign_key() const; [[nodiscard]] const std::string& from() const; [[nodiscard]] const std::string& group_by() const; [[nodiscard]] const std::string& in() const; [[nodiscard]] const std::string& insert() const; [[nodiscard]] const std::string& into() const; [[nodiscard]] const std::string& join() const; [[nodiscard]] const std::string& like() const; [[nodiscard]] const std::string& limit() const; [[nodiscard]] const std::string& not_() const; [[nodiscard]] const std::string& not_null() const; [[nodiscard]] const std::string& offset() const; [[nodiscard]] const std::string& on() const; [[nodiscard]] const std::string& or_() const; [[nodiscard]] const std::string& order_by() const; [[nodiscard]] const std::string& primary_key() const; [[nodiscard]] const std::string& references() const; [[nodiscard]] const std::string& remove() const; [[nodiscard]] const std::string& rollback() const; [[nodiscard]] const std::string& schema() const; [[nodiscard]] const std::string& select() const; [[nodiscard]] const std::string& set() const; [[nodiscard]] const std::string& start_quote() const; [[nodiscard]] const std::string& string_quote() const; [[nodiscard]] const std::string& table() const; [[nodiscard]] const std::string& update() const; [[nodiscard]] const std::string& values() const; [[nodiscard]] const std::string& where() const; private: dialect() = default; private: friend class dialect_builder; next_placeholder_func placeholder_func_ = [](size_t) { return "?"; }; to_escaped_string_func to_escaped_string_func_ = [](const utils::blob &val) { return utils::to_string(val); }; escape_identifier_t identifier_escape_type_ = escape_identifier_t::ESCAPE_BOTH_SAME; std::string default_schema_name_; token_to_string_map tokens_ { {dialect_token::AddConstraint, "ADD CONSTRAINT"}, {dialect_token::Alter, "ALTER"}, {dialect_token::And, "AND"}, {dialect_token::As, "AS"}, {dialect_token::Asc, "ASC"}, {dialect_token::Asterisk, "*"}, {dialect_token::Begin, "BEGIN TRANSACTION"}, {dialect_token::BeginBinaryData, "X'"}, {dialect_token::BeginStringData, "'"}, {dialect_token::Between, "BETWEEN"}, {dialect_token::Column, "COLUMN"}, {dialect_token::Columns, "COLUMNS"}, {dialect_token::Commit, "COMMIT TRANSACTION"}, {dialect_token::Create, "CREATE"}, {dialect_token::Desc, "DESC"}, {dialect_token::Distinct, "DISTINCT"}, {dialect_token::Drop, "DROP"}, {dialect_token::DropConstraint, "DROP CONSTRAINT"}, {dialect_token::EndBinaryData, "'"}, {dialect_token::EndQuote, "\""}, {dialect_token::EndStringData, "'"}, {dialect_token::ForeignKey, "FOREIGN KEY"}, {dialect_token::From, "FROM"}, {dialect_token::GroupBy, "GROUP BY"}, {dialect_token::In, "IN"}, {dialect_token::Insert, "INSERT"}, {dialect_token::Into, "INTO"}, {dialect_token::Join, "LEFT JOIN"}, {dialect_token::Like, "LIKE"}, {dialect_token::Limit, "LIMIT"}, {dialect_token::None, ""}, {dialect_token::Not, "NOT"}, {dialect_token::NotNull, "NOT NULL"}, {dialect_token::Offset, "OFFSET"}, {dialect_token::On, "ON"}, {dialect_token::Or, "OR"}, {dialect_token::OrderBy, "ORDER BY"}, {dialect_token::PrimaryKey, "PRIMARY KEY"}, {dialect_token::References, "REFERENCES"}, {dialect_token::Remove, "DELETE"}, {dialect_token::Rollback, "ROLLBACK TRANSACTION"}, {dialect_token::Schema, "SCHEMA"}, {dialect_token::Select, "SELECT"}, {dialect_token::Set, "SET"}, {dialect_token::StartQuote, "\""}, {dialect_token::StringQuote, "'"}, {dialect_token::Table, "TABLE"}, {dialect_token::Update, "UPDATE"}, {dialect_token::Values, "VALUES"}, {dialect_token::Where, "WHERE"} }; data_type_to_string_map data_types_ { {utils::basic_type::type_int8, "TINYINT"}, {utils::basic_type::type_int16, "SMALLINT"}, {utils::basic_type::type_int32, "INTEGER"}, {utils::basic_type::type_int64, "BIGINT"}, {utils::basic_type::type_uint8, "TINYINT"}, {utils::basic_type::type_uint16, "INTEGER"}, {utils::basic_type::type_uint32, "BIGINT"}, {utils::basic_type::type_uint64, "BIGINT"}, {utils::basic_type::type_float, "FLOAT"}, {utils::basic_type::type_double, "DOUBLE"}, {utils::basic_type::type_bool, "BOOLEAN"}, {utils::basic_type::type_varchar, "VARCHAR"}, {utils::basic_type::type_text, "TEXT"}, {utils::basic_type::type_date, "DATE"}, {utils::basic_type::type_time, "DATETIME"}, {utils::basic_type::type_blob, "BLOB"}, {utils::basic_type::type_null, "NULL"} }; sql_func_to_string_map sql_func_map_ { {sql_function_t::None, "NONE" }, {sql_function_t::Count, "COUNT" }, {sql_function_t::Avg, "AVG" }, {sql_function_t::Sum, "SUM" }, {sql_function_t::Min, "MIN" }, {sql_function_t::Max, "MAX" }, }; std::array bool_strings_ { "0", "1" }; }; } #endif //QUERY_DIALECT_HPP