mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 16:42:05 +00:00
Added support for MySQL style global variables syntax
This commit is contained in:
parent
4867934204
commit
e6a969e2e6
@ -398,6 +398,7 @@ private:
|
||||
{ TokenType::GreaterOrEquals, Replxx::Color::INTENSE },
|
||||
{ TokenType::Concatenation, Replxx::Color::INTENSE },
|
||||
{ TokenType::At, Replxx::Color::INTENSE },
|
||||
{ TokenType::DoubleAt, Replxx::Color::MAGENTA },
|
||||
|
||||
{ TokenType::EndOfStream, Replxx::Color::DEFAULT },
|
||||
|
||||
|
68
src/Functions/globalVariable.cpp
Normal file
68
src/Functions/globalVariable.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
#include <Functions/IFunctionImpl.h>
|
||||
#include <Functions/FunctionFactory.h>
|
||||
#include <Functions/FunctionHelpers.h>
|
||||
#include <DataTypes/DataTypeString.h>
|
||||
#include <Columns/ColumnString.h>
|
||||
#include <Columns/ColumnConst.h>
|
||||
#include <Core/Field.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int BAD_ARGUMENTS;
|
||||
}
|
||||
|
||||
|
||||
/** globalVariable('name') - takes constant string argument and returns the value of global variable with that name.
|
||||
* It is intended for compatibility with MySQL.
|
||||
*
|
||||
* Currently it's a stub, no variables are implemented. Feel free to add more variables.
|
||||
*/
|
||||
class FunctionGlobalVariable : public IFunction
|
||||
{
|
||||
public:
|
||||
static constexpr auto name = "globalVariable";
|
||||
static FunctionPtr create(const Context &)
|
||||
{
|
||||
return std::make_shared<FunctionGlobalVariable>();
|
||||
}
|
||||
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
size_t getNumberOfArguments() const override
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
||||
{
|
||||
if (!checkColumnConst<ColumnString>(arguments[0].column.get()))
|
||||
throw Exception("Agrument of function " + getName() + " must be constant string", ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
String variable_name = assert_cast<const ColumnConst &>(*arguments[0].column).getValue<String>();
|
||||
|
||||
throw Exception("There is no global variable with name " + variable_name, ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
void executeImpl(Block & block, const ColumnNumbers &, size_t /*result*/, size_t /*input_rows_count*/) override
|
||||
{
|
||||
String variable_name = assert_cast<const ColumnConst &>(*block.getByPosition(0).column).getValue<String>();
|
||||
|
||||
throw Exception("There is no global variable with name " + variable_name, ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void registerFunctionGlobalVariable(FunctionFactory & factory)
|
||||
{
|
||||
factory.registerFunction<FunctionGlobalVariable>();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ void registerFunctionTransform(FunctionFactory &);
|
||||
void registerFunctionGetMacro(FunctionFactory &);
|
||||
void registerFunctionGetScalar(FunctionFactory &);
|
||||
void registerFunctionIsConstant(FunctionFactory &);
|
||||
void registerFunctionGlobalVariable(FunctionFactory &);
|
||||
|
||||
#if USE_ICU
|
||||
void registerFunctionConvertCharset(FunctionFactory &);
|
||||
@ -112,6 +113,7 @@ void registerFunctionsMiscellaneous(FunctionFactory & factory)
|
||||
registerFunctionGetMacro(factory);
|
||||
registerFunctionGetScalar(factory);
|
||||
registerFunctionIsConstant(factory);
|
||||
registerFunctionGlobalVariable(factory);
|
||||
|
||||
#if USE_ICU
|
||||
registerFunctionConvertCharset(factory);
|
||||
|
@ -201,6 +201,7 @@ SRCS(
|
||||
getMacro.cpp
|
||||
getScalar.cpp
|
||||
getSizeOfEnumType.cpp
|
||||
globalVariable.cpp
|
||||
greatCircleDistance.cpp
|
||||
greater.cpp
|
||||
greaterOrEquals.cpp
|
||||
|
@ -1254,6 +1254,37 @@ bool ParserSubstitution::parseImpl(Pos & pos, ASTPtr & node, Expected & expected
|
||||
}
|
||||
|
||||
|
||||
bool ParserMySQLGlobalVariable::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
{
|
||||
if (pos->type != TokenType::DoubleAt)
|
||||
return false;
|
||||
|
||||
++pos;
|
||||
|
||||
if (pos->type != TokenType::BareWord)
|
||||
{
|
||||
expected.add(pos, "variable name");
|
||||
return false;
|
||||
}
|
||||
|
||||
String name(pos->begin, pos->end);
|
||||
++pos;
|
||||
|
||||
auto name_literal = std::make_shared<ASTLiteral>(name);
|
||||
|
||||
auto expr_list_args = std::make_shared<ASTExpressionList>();
|
||||
expr_list_args->children.push_back(std::move(name_literal));
|
||||
|
||||
auto function_node = std::make_shared<ASTFunction>();
|
||||
function_node->name = "globalVariable";
|
||||
function_node->arguments = expr_list_args;
|
||||
function_node->children.push_back(expr_list_args);
|
||||
|
||||
node = function_node;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ParserExpressionElement::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
{
|
||||
return ParserSubquery().parse(pos, node, expected)
|
||||
@ -1276,7 +1307,8 @@ bool ParserExpressionElement::parseImpl(Pos & pos, ASTPtr & node, Expected & exp
|
||||
|| ParserQualifiedAsterisk().parse(pos, node, expected)
|
||||
|| ParserAsterisk().parse(pos, node, expected)
|
||||
|| ParserCompoundIdentifier().parse(pos, node, expected)
|
||||
|| ParserSubstitution().parse(pos, node, expected);
|
||||
|| ParserSubstitution().parse(pos, node, expected)
|
||||
|| ParserMySQLGlobalVariable().parse(pos, node, expected);
|
||||
}
|
||||
|
||||
|
||||
|
@ -301,6 +301,16 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
/** MySQL-style global variable: @@var
|
||||
*/
|
||||
class ParserMySQLGlobalVariable : public IParserBase
|
||||
{
|
||||
protected:
|
||||
const char * getName() const override { return "MySQL-style global variable"; }
|
||||
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||
};
|
||||
|
||||
|
||||
/** The expression element is one of: an expression in parentheses, an array, a literal, a function, an identifier, an asterisk.
|
||||
*/
|
||||
class ParserExpressionElement : public IParserBase
|
||||
|
@ -305,7 +305,12 @@ Token Lexer::nextTokenImpl()
|
||||
return Token(TokenType::ErrorSinglePipeMark, token_begin, pos);
|
||||
}
|
||||
case '@':
|
||||
return Token(TokenType::At, token_begin, ++pos);
|
||||
{
|
||||
++pos;
|
||||
if (pos < end && *pos == '@')
|
||||
return Token(TokenType::DoubleAt, token_begin, ++pos);
|
||||
return Token(TokenType::At, token_begin, pos);
|
||||
}
|
||||
|
||||
default:
|
||||
if (isWordCharASCII(*pos))
|
||||
|
@ -48,7 +48,8 @@ namespace DB
|
||||
M(GreaterOrEquals) \
|
||||
M(Concatenation) /** String concatenation operator: || */ \
|
||||
\
|
||||
M(At) /** @. Used only for specifying user names. */ \
|
||||
M(At) /** @. Used for specifying user names and also for MySQL-style variables. */ \
|
||||
M(DoubleAt) /** @@. Used for MySQL-style global variables. */ \
|
||||
\
|
||||
/** Order is important. EndOfStream goes after all usual tokens, and special error tokens goes after EndOfStream. */ \
|
||||
\
|
||||
|
@ -0,0 +1 @@
|
||||
SELECT @@test; -- { serverError 36 }
|
Loading…
Reference in New Issue
Block a user