dbms: development.

This commit is contained in:
Alexey Milovidov 2010-06-24 19:12:10 +00:00
parent 1677287005
commit 8fc01e90d7
22 changed files with 1491 additions and 202 deletions

View File

@ -0,0 +1,18 @@
#ifndef DBMS_COLUMNS_COLUMNS_H
#define DBMS_COLUMNS_COLUMNS_H
#include <vector>
#include <Poco/SharedPtr.h>
#include <DB/Columns/IColumn.h>
namespace DB
{
using Poco::SharedPtr;
typedef std::vector<SharedPtr<IColumn> > Columns;
}
#endif

View File

@ -1,5 +1,5 @@
#ifndef DBMS_CORE_ICOLUMN_H
#define DBMS_CORE_ICOLUMN_H
#ifndef DBMS_COLUMNS_ICOLUMN_H
#define DBMS_COLUMNS_ICOLUMN_H
#include <Poco/SharedPtr.h>

View File

@ -0,0 +1,15 @@
#ifndef DBMS_CORE_COLUMN_NUMBERS_H
#define DBMS_CORE_COLUMN_NUMBERS_H
#include <vector>
#include <string>
namespace DB
{
typedef std::vector<size_t> ColumnNumbers;
}
#endif

View File

@ -42,6 +42,8 @@ namespace ErrorCodes
CANNOT_READ_COMPRESSED_CHUNK,
ATTEMPT_TO_READ_AFTER_EOF,
CANNOT_READ_ALL_DATA,
TOO_MUCH_ARGUMENTS_FOR_FUNCTION,
TOO_LESS_ARGUMENTS_FOR_FUNCTION,
};
}

View File

@ -0,0 +1,29 @@
#ifndef DBMS_PARSERS_ASTEXPRESSIONLIST_H
#define DBMS_PARSERS_ASTEXPRESSIONLIST_H
#include <DB/Parsers/IAST.h>
namespace DB
{
using Poco::SharedPtr;
/** Список выражений типа "a, b + c, f(d)"
*/
class ASTExpressionList : public IAST
{
public:
StringRange range;
ASTs children;
ASTExpressionList(StringRange range_) : range(range_) {}
/** Получить кусок текста, откуда был получен этот элемент. */
StringRange getRange() { return range; }
};
}
#endif

View File

@ -0,0 +1,29 @@
#ifndef DBMS_PARSERS_ASTFUNCTION_H
#define DBMS_PARSERS_ASTFUNCTION_H
#include <DB/Parsers/IAST.h>
namespace DB
{
/** Применение функции или оператора
*/
class ASTFunction : public IAST
{
public:
StringRange range;
/// имя функции
String name;
/// параметры
ASTPtr arguments;
ASTFunction(StringRange range_) : range(range_) {}
/** Получить кусок текста, откуда был получен этот элемент. */
StringRange getRange() { return range; }
};
}
#endif

View File

@ -0,0 +1,27 @@
#ifndef DBMS_PARSERS_ASTIDENTIFIER_H
#define DBMS_PARSERS_ASTIDENTIFIER_H
#include <DB/Parsers/IAST.h>
namespace DB
{
/** Идентификатор (столбца или алиас, или именованый элемент кортежа)
*/
class ASTIdentifier : public IAST
{
public:
StringRange range;
/// имя
String name;
ASTIdentifier(StringRange range_, const String & name_) : range(range_), name(name_) {}
/** Получить кусок текста, откуда был получен этот элемент. */
StringRange getRange() { return range; }
};
}
#endif

View File

@ -0,0 +1,28 @@
#ifndef DBMS_PARSERS_ASTLITERAL_H
#define DBMS_PARSERS_ASTLITERAL_H
#include <DB/Core/Field.h>
#include <DB/Parsers/IAST.h>
namespace DB
{
/** Литерал (атомарный) - число, строка, NULL
*/
class ASTLiteral : public IAST
{
public:
StringRange range;
/// значение
Field value;
ASTLiteral(StringRange range_, const Field & value_) : range(range_), value(value_) {}
/** Получить кусок текста, откуда был получен этот элемент. */
StringRange getRange() { return range; }
};
}
#endif

View File

@ -0,0 +1,27 @@
#ifndef DBMS_PARSERS_ASTSELECTQUERY_H
#define DBMS_PARSERS_ASTSELECTQUERY_H
#include <DB/Parsers/IAST.h>
namespace DB
{
/** SELECT запрос
*/
class ASTSelectQuery : public IAST
{
public:
StringRange range;
ASTPtr select, from, where, group, having, order, limit;
ASTSelectQuery(StringRange range_) : range(range_) {}
/** Получить кусок текста, откуда был получен этот элемент. */
StringRange getRange() { return range; }
};
}
#endif

View File

@ -0,0 +1,169 @@
#ifndef DBMS_PARSERS_COMMONPARSERS_H
#define DBMS_PARSERS_COMMONPARSERS_H
#include <cstring>
#include <DB/Parsers/IParserBase.h>
namespace DB
{
using Poco::SharedPtr;
/** если прямо сейчас не s, то ошибка
*/
class ParserString : public IParserBase
{
private:
const String & s;
public:
ParserString(const String & s_) : s(s_) {}
protected:
String getName() { return s; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
if (static_cast<ssize_t>(s.size()) < end - pos || std::strncmp(pos, s.data(), s.size()))
return false;
else
{
pos += s.size();
return true;
}
}
};
/** если сейчас словарный символ - то ошибка
* понимается только латиница
*/
class ParserNotWordCharOrEnd : public IParserBase
{
protected:
String getName() { return "non-word character"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
if (pos == end)
return true;
if ((*pos >= 'a' && *pos <= 'z') || (*pos >= 'A' && *pos <= 'Z') || (*pos >= '0' && *pos <= '9') || *pos == '_')
return false;
++pos;
return true;
}
};
/** пробельные символы
*/
class ParserWhiteSpace : public IParserBase
{
protected:
String getName() { return "white space"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
Pos begin = pos;
while (*pos == ' ' || *pos == '\t' || *pos == '\n' || *pos == '\r' || *pos == '\f')
++pos;
return pos != begin;
}
};
class ParserCStyleComment : public IParserBase
{
protected:
String getName() { return "C-style comment"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
if (end - pos >= 4 && pos[0] == '/' && pos[1] == '*')
{
pos += 2;
while (end - pos >= 2 && pos[0] != '*' && pos[1] != '/')
++pos;
if (end - pos < 2)
{
expected = "closing of C-style comment '*/'";
return false;
}
else
{
pos += 2;
return true;
}
}
else
return false;
}
};
class ParserSQLStyleComment : public IParserBase
{
protected:
String getName() { return "SQL-style comment"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
if (end - pos >= 2 && pos[0] == '-' && pos[1] == '-')
{
pos += 2;
while (pos != end && *pos != '\n')
++pos;
if (pos != end)
++pos;
return true;
}
else
return false;
}
};
/** комментарии '--' или c-style
*/
class ParserComment : public IParserBase
{
protected:
String getName() { return "comment"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
ParserCStyleComment p1;
ParserSQLStyleComment p2;
return p1.ignore(pos, end, expected)
|| p2.ignore(pos, end, expected);
}
};
class ParserWhiteSpaceOrComments : public IParserBase
{
protected:
String getName() { return "white space or comments"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
ParserWhiteSpace p1;
ParserComment p2;
bool res = false;
while (p1.ignore(pos, end, expected) || p2.ignore(pos, end, expected))
res = true;
return res;
}
};
}
#endif

View File

@ -0,0 +1,124 @@
#ifndef DBMS_PARSERS_EXPRESSIONELEMENTPARSERS_H
#define DBMS_PARSERS_EXPRESSIONELEMENTPARSERS_H
#include <DB/Parsers/IParserBase.h>
namespace DB
{
class ParserArray : public IParserBase
{
protected:
String getName() { return "array"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
};
/** Если в скобках выражение из одного элемента - возвращает в node этот элемент;
* иначе возвращает функцию tuple от содержимого скобок.
*/
class ParserParenthesisExpression : public IParserBase
{
protected:
String getName() { return "expression in parenthesis"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
};
/** Идентификатор, например, x_yz123
*/
class ParserIdentifier : public IParserBase
{
protected:
String getName() { return "identifier"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
};
/** Функция, например, f(x, y, z)
*/
class ParserFunction : public IParserBase
{
protected:
String getName() { return "function"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
};
/** NULL.
*/
class ParserNull : public IParserBase
{
protected:
String getName() { return "NULL"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
};
/** Число.
*/
class ParserNumber : public IParserBase
{
protected:
String getName() { return "number"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
};
/** Строка в одинарных кавычках.
*/
class ParserStringLiteral : public IParserBase
{
private:
inline char parseEscapeSequence(char c)
{
switch(c)
{
case 'b':
return '\b';
case 'f':
return '\f';
case 'n':
return '\n';
case 'r':
return '\r';
case 't':
return '\t';
case '0':
return '\0';
default:
return c;
}
}
protected:
String getName() { return "string literal"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
};
/** Литерал - одно из: NULL, UInt64, Int64, Float64, String.
*/
class ParserLiteral : public IParserBase
{
protected:
String getName() { return "literal"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
};
/** Элемент выражения - одно из: выражение в круглых скобках, массив, литерал, функция, идентификатор.
*/
class ParserExpressionElement : public IParserBase
{
protected:
String getName() { return "element of expression"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
};
}
#endif

View File

@ -1,119 +0,0 @@
#ifndef DBMS_PARSERS_EXPRESSION_H
#define DBMS_PARSERS_EXPRESSION_H
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/variant/recursive_wrapper.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <iostream>
#include <DB/Core/Types.h>
namespace DB
{
/** Expression - это выражение, которое может стоять в запросе между SELECT и FROM
* Здесь представлен парсер этого выражения (пока без операторов).
* PS. Код довольно сложный :(
*/
/** Типы данных, которые образуются автоматически в результате парсинга.
* Они должны быть в отдельном или глобальном namespace из-за BOOST_FUSION_ADAPT_STRUCT.
*
* spirit может собирать типы данных - результаты парсинга (атрибуты) автоматически,
* или можно использовать свои типы и заполнять их вручную с помощью семантических действий.
* Здесь используется вариант - автоматически.
* (но стоит на будущее иметь ввиду, что его очень сложно заставить скомпилироваться)
*/
namespace ExpressionGrammarTypes
{
/// с тем, какой конкретно тип у числа, будем разбираться потом
typedef Float64 NumberConstant; /// 1, -1, 0.1
typedef String StringConstant; /// 'abc', 'ab\'c', 'abc\\'
typedef Null NullConstant; /// NULL, null, NuLl
typedef boost::variant<
NumberConstant,
StringConstant,
NullConstant> Constant;
typedef String Name; /// x, sum, width
struct Function; /// forward declaration для рекурсии
typedef boost::variant<
boost::recursive_wrapper<Function>,
Constant,
Name> Node; /// элемент выражения
typedef std::vector<Node> Expression; /// выражение - набор элементов через запятую
struct Function /// f(x), sum(a, 10), concat('a', 'bc')
{
Name name; /// sum
Expression args; /// a, 10
};
}
}
/** Необходимо, чтобы struct Function был совместим с boost::fusion::vector (он же boost::tuple),
* который образуется автоматически при парсинге.
* Должно быть в глобальном namespace.
*/
BOOST_FUSION_ADAPT_STRUCT(
DB::ExpressionGrammarTypes::Function,
(DB::ExpressionGrammarTypes::Name, name)
(DB::ExpressionGrammarTypes::Expression, args)
)
namespace DB
{
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
/** Грамматика */
template <typename Iterator>
struct ExpressionGrammar : qi::grammar<Iterator, ExpressionGrammarTypes::Expression(), ascii::space_type>
{
ExpressionGrammar() : ExpressionGrammar::base_type(expression)
{
using qi::lexeme;
using qi::raw;
using qi::alpha;
using qi::alnum;
using qi::double_;
using qi::eps;
using qi::no_case;
using qi::char_;
using qi::_val;
using qi::_1;
expression %= node % ',';
node %= function | constant | name;
name %= raw[lexeme[alpha >> -*(alnum | '_')]];
constant %= number | string | null;
function %= name >> '(' >> expression >> ')';
number %= double_;
null = eps[_val = boost::none] >> no_case["NULL"];
string %= raw[lexeme['\'' >> *((char_ - (char_('\\') | '\'')) | (char_('\'') >> char_)) >> '\'']];
}
qi::rule<Iterator, ExpressionGrammarTypes::Expression(), ascii::space_type> expression;
qi::rule<Iterator, ExpressionGrammarTypes::Node(), ascii::space_type> node;
qi::rule<Iterator, ExpressionGrammarTypes::Constant(), ascii::space_type> constant;
qi::rule<Iterator, ExpressionGrammarTypes::Name(), ascii::space_type> name;
qi::rule<Iterator, ExpressionGrammarTypes::Function(), ascii::space_type> function;
qi::rule<Iterator, ExpressionGrammarTypes::NumberConstant(), ascii::space_type> number;
qi::rule<Iterator, ExpressionGrammarTypes::StringConstant(), ascii::space_type> string;
qi::rule<Iterator, ExpressionGrammarTypes::NullConstant(), ascii::space_type> null;
};
}
#endif

View File

@ -0,0 +1,280 @@
#ifndef DBMS_PARSERS_EXPRESSIONLISTPARSERS_H
#define DBMS_PARSERS_EXPRESSIONLISTPARSERS_H
#include <map>
#include <boost/assign/list_of.hpp>
#include <DB/Parsers/IParserBase.h>
#include <DB/Parsers/CommonParsers.h>
namespace DB
{
/** Оператор и соответствующая ему функция. Например, "+" -> "plus" */
typedef std::map<String, String> Operators_t;
/** Выражение с инфиксным бинарным лево-ассоциативным оператором.
* Например, a + b - c + d.
* NOTE: если оператор словесный (например, OR), то после него не требуется границы слова.
* то есть, можно написать a = b ORx = y.
*/
class ParserLeftAssociativeBinaryOperatorList : public IParserBase
{
private:
const Operators_t & operators;
ParserPtr elem_parser;
public:
/** operators_ - допустимые операторы и соответствующие им функции
*/
ParserLeftAssociativeBinaryOperatorList(const Operators_t & operators_, ParserPtr elem_parser_)
: operators(operators_), elem_parser(elem_parser_)
{
}
protected:
String getName() { return "list, delimited by binary operators"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
};
/** Выражение с префиксным унарным оператором.
* Например, NOT x.
* NOTE: если оператор словесный (например, NOT), то после него не требуется границы слова.
* то есть, можно написать NOTx.
*/
class ParserPrefixUnaryOperatorExpression : public IParserBase
{
private:
const Operators_t & operators;
ParserPtr elem_parser;
public:
/** operators_ - допустимые операторы и соответствующие им функции
*/
ParserPrefixUnaryOperatorExpression(const Operators_t & operators_, ParserPtr elem_parser_)
: operators(operators_), elem_parser(elem_parser_)
{
}
protected:
String getName() { return "expression with prefix unary operator"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
};
class ParserAccessExpression : public IParserBase
{
private:
ParserPtr elem_parser;
ParserLeftAssociativeBinaryOperatorList operator_parser;
public:
ParserAccessExpression();
protected:
String getName() { return "acess expression"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
return operator_parser.parse(pos, end, node, expected);
}
};
class ParserUnaryMinusExpression : public IParserBase
{
private:
ParserPtr elem_parser;
ParserPrefixUnaryOperatorExpression operator_parser;
public:
ParserUnaryMinusExpression()
: elem_parser(new ParserAccessExpression),
operator_parser(boost::assign::map_list_of("-", "negate"), elem_parser)
{
}
protected:
String getName() { return "unary minus expression"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
return operator_parser.parse(pos, end, node, expected);
}
};
class ParserMultiplicativeExpression : public IParserBase
{
private:
ParserPtr elem_parser;
ParserLeftAssociativeBinaryOperatorList operator_parser;
public:
ParserMultiplicativeExpression()
: elem_parser(new ParserUnaryMinusExpression),
operator_parser(boost::assign::map_list_of
("*", "multiply")
("/", "divide")
("%", "modulo"),
elem_parser)
{
}
protected:
String getName() { return "multiplicative expression"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
return operator_parser.parse(pos, end, node, expected);
}
};
class ParserAdditiveExpression : public IParserBase
{
private:
ParserPtr elem_parser;
ParserLeftAssociativeBinaryOperatorList operator_parser;
public:
ParserAdditiveExpression()
: elem_parser(new ParserMultiplicativeExpression),
operator_parser(boost::assign::map_list_of
("+", "plus")
("-", "minus"),
elem_parser)
{
}
protected:
String getName() { return "additive expression"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
return operator_parser.parse(pos, end, node, expected);
}
};
class ParserComparisonExpression : public IParserBase
{
private:
ParserPtr elem_parser;
ParserLeftAssociativeBinaryOperatorList operator_parser;
public:
ParserComparisonExpression()
: elem_parser(new ParserAdditiveExpression),
operator_parser(boost::assign::map_list_of
("==", "equals")
("!=", "notEquals")
("<>", "notEquals")
("<=", "lessOrEquals")
(">=", "greaterOrEquals")
("<", "less")
(">", "greater")
("=", "equals"),
elem_parser)
{
}
protected:
String getName() { return "comparison expression"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
return operator_parser.parse(pos, end, node, expected);
}
};
class ParserLogicalNotExpression : public IParserBase
{
private:
ParserPtr elem_parser;
ParserPrefixUnaryOperatorExpression operator_parser;
public:
ParserLogicalNotExpression()
: elem_parser(new ParserComparisonExpression),
operator_parser(boost::assign::map_list_of("NOT", "not"), elem_parser)
{
}
protected:
String getName() { return "logical-NOT expression"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
return operator_parser.parse(pos, end, node, expected);
}
};
class ParserLogicalAndExpression : public IParserBase
{
private:
ParserPtr elem_parser;
ParserLeftAssociativeBinaryOperatorList operator_parser;
public:
ParserLogicalAndExpression()
: elem_parser(new ParserLogicalNotExpression),
operator_parser(boost::assign::map_list_of("AND", "and"), elem_parser)
{
}
protected:
String getName() { return "logical-AND expression"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
return operator_parser.parse(pos, end, node, expected);
}
};
class ParserLogicalOrExpression : public IParserBase
{
private:
ParserPtr elem_parser;
ParserLeftAssociativeBinaryOperatorList operator_parser;
public:
ParserLogicalOrExpression()
: elem_parser(new ParserLogicalAndExpression),
operator_parser(boost::assign::map_list_of("OR", "or"), elem_parser)
{
}
protected:
String getName() { return "logical-OR expression"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
return operator_parser.parse(pos, end, node, expected);
}
};
/** Список выражений, разделённых запятыми, возможно пустой. */
class ParserExpressionList : public IParserBase
{
protected:
String getName() { return "list of expressions"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
};
class ParserNotEmptyExpressionList : public IParserBase
{
private:
ParserExpressionList nested_parser;
protected:
String getName() { return "not empty list of expressions"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
};
}
#endif

View File

@ -0,0 +1,33 @@
#ifndef DBMS_PARSERS_IAST_H
#define DBMS_PARSERS_IAST_H
#include <list>
#include <Poco/SharedPtr.h>
#include <DB/Core/Types.h>
#include <DB/Parsers/StringRange.h>
namespace DB
{
using Poco::SharedPtr;
/** Элемент синтаксического дерева (в дальнейшем - направленного ациклического графа с элементами семантики)
*/
class IAST
{
public:
/** Получить кусок текста, откуда был получен этот элемент. */
virtual StringRange getRange() = 0;
virtual ~IAST() {}
};
typedef Poco::SharedPtr<IAST> ASTPtr;
typedef std::list<ASTPtr> ASTs;
}
#endif

View File

@ -0,0 +1,71 @@
#ifndef DBMS_PARSERS_IPARSER_H
#define DBMS_PARSERS_IPARSER_H
#include <list>
#include <Poco/SharedPtr.h>
#include <DB/Core/Types.h>
#include <DB/Parsers/IAST.h>
namespace DB
{
using Poco::SharedPtr;
/** Интерфейс для классов-парсеров
*/
class IParser
{
public:
typedef const char * Pos;
/** Получить текст о том, что парсит этот парсер. */
virtual String getName() = 0;
/** Распарсить кусок текста с позиции pos, но не дальше конца строки (end - позиция после конца строки),
* переместить указатель pos на максимальное место, до которого удалось распарсить,
* вернуть в случае успеха true и результат в node, если он нужен, иначе false,
* в expected записать, что ожидалось в максимальной позиции,
* до которой удалось распарсить, если парсинг был неуспешным,
* или что парсит этот парсер, если парсинг был успешным.
* Везде предполагается, что строка, в которую входит диапазон [begin, end) 0-terminated.
*/
virtual bool parse(Pos & pos, Pos end, ASTPtr & node, String & expected) = 0;
bool ignore(Pos & pos, Pos end, String & expected)
{
ASTPtr ignore_node;
return parse(pos, end, ignore_node, expected);
}
bool ignore(Pos & pos, Pos end)
{
String expected;
return ignore(pos, end, expected);
}
/** То же самое, но не двигать позицию и не записывать результат в node.
*/
bool check(Pos & pos, Pos end, String & expected)
{
Pos begin = pos;
ASTPtr node;
if (!parse(pos, end, node, expected))
{
pos = begin;
return false;
}
else
return true;
}
virtual ~IParser() {}
};
typedef SharedPtr<IParser> ParserPtr;
}
#endif

View File

@ -0,0 +1,30 @@
#ifndef DBMS_PARSERS_IPARSERBASE_H
#define DBMS_PARSERS_IPARSERBASE_H
#include <list>
#include <Poco/SharedPtr.h>
#include <DB/Core/Types.h>
#include <DB/Parsers/IParser.h>
namespace DB
{
/** Базовый класс для большинства парсеров
*/
class IParserBase : public IParser
{
public:
bool parse(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
expected = getName();
return parseImpl(pos, end, node, expected);
}
protected:
virtual bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected) = 0;
};
}
#endif

View File

@ -0,0 +1,51 @@
#ifndef DBMS_PARSERS_PARSERSELECTQUERY_H
#define DBMS_PARSERS_PARSERSELECTQUERY_H
#include <DB/Parsers/ASTSelectQuery.h>
#include <DB/Parsers/IParserBase.h>
#include <DB/Parsers/CommonParsers.h>
#include <DB/Parsers/ExpressionListParsers.h>
namespace DB
{
class ParserSelectQuery : public IParserBase
{
protected:
String getName() { return "SELECT query"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
Pos begin = pos;
ASTPtr select_expression_list;
ParserWhiteSpaceOrComments ws;
ParserString s("SELECT");
ParserNotWordCharOrEnd nw;
ParserNotEmptyExpressionList exp_list;
ws.ignore(pos, end);
if (!(s.ignore(pos, end, expected)
&& nw.check(pos, end, expected)))
return false;
ws.ignore(pos, end);
if (!exp_list.parse(pos, end, select_expression_list, expected))
return false;
ASTSelectQuery * select_query = new ASTSelectQuery(StringRange(begin, pos));
node = select_query;
select_query->select = select_expression_list;
return true;
}
};
}
#endif

View File

@ -0,0 +1,14 @@
#ifndef DBMS_PARSERS_STRINGRANGE_H
#define DBMS_PARSERS_STRINGRANGE_H
#include <map>
namespace DB
{
typedef std::pair<const char *, const char *> StringRange;
}
#endif

View File

@ -0,0 +1,308 @@
#include <errno.h>
#include <cstdlib>
#include <DB/Parsers/IAST.h>
#include <DB/Parsers/ASTExpressionList.h>
#include <DB/Parsers/ASTFunction.h>
#include <DB/Parsers/ASTIdentifier.h>
#include <DB/Parsers/ASTLiteral.h>
#include <DB/Parsers/CommonParsers.h>
#include <DB/Parsers/ExpressionListParsers.h>
#include <DB/Parsers/ExpressionElementParsers.h>
namespace DB
{
bool ParserArray::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
Pos begin = pos;
ASTPtr contents_node;
ParserString open("["), close("]");
ParserExpressionList contents;
ParserWhiteSpaceOrComments ws;
if (!open.ignore(pos, end, expected))
return false;
ws.ignore(pos, end);
contents.parse(pos, end, contents_node, expected);
ws.ignore(pos, end);
if (!close.ignore(pos, end, expected))
return false;
ASTFunction * function_node = new ASTFunction(StringRange(begin, pos));
function_node->name = "array";
function_node->arguments = contents_node;
node = function_node;
return true;
}
bool ParserParenthesisExpression::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
Pos begin = pos;
ASTPtr contents_node;
ParserString open("("), close(")");
ParserExpressionList contents;
ParserWhiteSpaceOrComments ws;
if (!open.ignore(pos, end, expected))
return false;
ws.ignore(pos, end);
contents.parse(pos, end, contents_node, expected);
ws.ignore(pos, end);
if (!close.ignore(pos, end, expected))
return false;
ASTExpressionList & expr_list = dynamic_cast<ASTExpressionList &>(*node);
/// пустое выражение в скобках недопустимо
if (expr_list.children.empty())
{
expected = "not empty list of expressions in parenthesis";
return false;
}
if (expr_list.children.size() == 1)
{
node = expr_list.children.front();
}
else
{
ASTFunction * function_node = new ASTFunction(StringRange(begin, pos));
function_node->name = "tuple";
function_node->arguments = contents_node;
node = function_node;
}
return true;
}
bool ParserIdentifier::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
Pos begin = pos;
while (pos != end
&& ((*pos >= 'a' && *pos <= 'z')
|| (*pos >= 'A' && *pos <= 'Z')
|| (*pos == '_')
|| (pos != begin && *pos >= '0' && *pos <= '9')))
++pos;
if (pos != begin)
{
node = new ASTIdentifier(StringRange(begin, pos), String(begin, pos - begin));
return true;
}
else
return false;
}
bool ParserFunction::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
Pos begin = pos;
ASTPtr contents_node;
ParserIdentifier id_parser;
ParserString open("("), close(")");
ParserExpressionList contents;
ParserWhiteSpaceOrComments ws;
ASTIdentifier * p_identifier = new ASTIdentifier(StringRange(begin, pos), "");
ASTIdentifier & identifier = *p_identifier;
ASTPtr identifier_node = p_identifier;
ASTPtr expr_list_node = new ASTExpressionList(StringRange(begin, pos));
if (!id_parser.parse(pos, end, identifier_node, expected))
return false;
ws.ignore(pos, end);
if (!open.ignore(pos, end, expected))
return false;
ws.ignore(pos, end);
contents.parse(pos, end, expr_list_node, expected);
ws.ignore(pos, end);
if (!close.ignore(pos, end, expected))
return false;
ASTFunction * function_node = new ASTFunction(StringRange(begin, pos));
function_node->name = identifier.name;
function_node->arguments = expr_list_node;
node = function_node;
return true;
}
bool ParserNull::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
Pos begin = pos;
ParserString nested_parser("NULL");
if (nested_parser.parse(pos, end, node, expected))
{
node = new ASTLiteral(StringRange(StringRange(begin, pos)), Null());
return true;
}
else
return false;
}
bool ParserNumber::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
Field res;
Pos begin = pos;
if (pos == end)
return false;
Float64 float_value = std::strtod(pos, const_cast<char**>(&pos));
if (pos == begin || errno == ERANGE)
{
expected = "number (this cause range error)";
return false;
}
res = float_value;
/// попробуем использовать более точный тип - UInt64 или Int64
Pos pos_integer = begin;
if (float_value < 0)
{
Int64 int_value = std::strtoll(pos_integer, const_cast<char**>(&pos_integer), 0);
if (pos_integer == pos && errno != ERANGE)
res = int_value;
}
else
{
UInt64 uint_value = std::strtoull(pos_integer, const_cast<char**>(&pos_integer), 0);
if (pos_integer == pos && errno != ERANGE)
res = uint_value;
}
node = new ASTLiteral(StringRange(begin, pos), res);
return true;
}
bool ParserStringLiteral::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
Pos begin = pos;
String s;
if (pos == end || *pos != '\'')
{
expected = "opening single quote";
return false;
}
while (pos != end)
{
size_t bytes = 0;
for (; pos + bytes != end; ++bytes)
if (pos[bytes] == '\\' || pos[bytes] == '\'')
break;
s.append(pos, bytes);
pos += bytes;
if (*pos == '\'')
{
++pos;
node = new ASTLiteral(StringRange(begin, pos), s);
return true;
}
if (*pos == '\\')
{
++pos;
if (pos == end)
{
expected = "escape sequence";
return false;
}
s += parseEscapeSequence(*pos);
++pos;
}
}
expected = "closing single quote";
return false;
}
bool ParserLiteral::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
Pos begin = pos;
ParserNull null_p;
ParserNumber num_p;
ParserStringLiteral str_p;
if (null_p.parse(pos, end, node, expected))
return true;
pos = begin;
if (num_p.parse(pos, end, node, expected))
return true;
pos = begin;
if (str_p.parse(pos, end, node, expected))
return true;
pos = begin;
expected = "literal: one of NULL, number, single quoted string";
return false;
}
bool ParserExpressionElement::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
Pos begin = pos;
ParserParenthesisExpression paren_p;
ParserArray array_p;
ParserLiteral lit_p;
ParserFunction fun_p;
ParserIdentifier id_p;
if (paren_p.parse(pos, end, node, expected))
return true;
pos = begin;
if (array_p.parse(pos, end, node, expected))
return true;
pos = begin;
if (lit_p.parse(pos, end, node, expected))
return true;
pos = begin;
if (fun_p.parse(pos, end, node, expected))
return true;
pos = begin;
if (id_p.parse(pos, end, node, expected))
return true;
pos = begin;
expected = "expression element: one of array, literal, function, identifier, parenthised expression";
return false;
}
}

View File

@ -0,0 +1,202 @@
#include <DB/Parsers/IAST.h>
#include <DB/Parsers/ASTExpressionList.h>
#include <DB/Parsers/ASTFunction.h>
#include <DB/Parsers/CommonParsers.h>
#include <DB/Parsers/ExpressionElementParsers.h>
#include <DB/Parsers/ExpressionListParsers.h>
namespace DB
{
bool ParserLeftAssociativeBinaryOperatorList::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
bool first = true;
ParserWhiteSpaceOrComments ws;
while (1)
{
if (first)
{
ASTPtr elem;
if (!elem_parser->parse(pos, end, elem, expected))
break;
node = elem;
}
else
{
ws.ignore(pos, end);
/// пробуем найти какой-нибудь из допустимых операторов
Pos begin = pos;
Operators_t::const_iterator it;
for (it = operators.begin(); it != operators.end(); ++it)
{
ParserString op(it->first);
if (op.ignore(pos, end, expected))
break;
}
if (it == operators.end())
break;
ws.ignore(pos, end);
/// функция, соответствующая оператору
ASTFunction * p_function = new ASTFunction(StringRange(pos, pos));
ASTFunction & function = *p_function;
ASTPtr function_node = p_function;
/// аргументы функции
ASTExpressionList * p_exp_list = new ASTExpressionList(StringRange(pos, pos));
ASTExpressionList & exp_list = *p_exp_list;
ASTPtr exp_list_node = p_exp_list;
ASTPtr elem;
if (!elem_parser->parse(pos, end, elem, expected))
return false;
/// первым аргументом функции будет предыдущий элемент, вторым - следующий
function.range.first = begin;
function.range.second = pos;
function.name = it->second;
function.arguments = exp_list_node;
exp_list.children.push_back(node);
exp_list.children.push_back(elem);
exp_list.range.second = pos;
/** специальное исключение для оператора доступа к элементу массива x[y], который
* содержит инфиксную часть '[' и суффиксную ']' (задаётся в виде '[')
*/
if (it->first == "[")
{
ParserString rest_p("]");
ws.ignore(pos, end);
if (!rest_p.ignore(pos, end, expected))
return false;
}
node = function_node;
}
first = false;
}
return true;
}
bool ParserPrefixUnaryOperatorExpression::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
ParserWhiteSpaceOrComments ws;
ws.ignore(pos, end);
/// пробуем найти какой-нибудь из допустимых операторов
Pos begin = pos;
Operators_t::const_iterator it;
for (it = operators.begin(); it != operators.end(); ++it)
{
ParserString op(it->first);
if (op.ignore(pos, end, expected))
break;
}
if (it == operators.end())
return false;
ws.ignore(pos, end);
/// функция, соответствующая оператору
ASTFunction * p_function = new ASTFunction(StringRange(pos, pos));
ASTFunction & function = *p_function;
ASTPtr function_node = p_function;
/// аргументы функции
ASTExpressionList * p_exp_list = new ASTExpressionList(StringRange(pos, pos));
ASTExpressionList & exp_list = *p_exp_list;
ASTPtr exp_list_node = p_exp_list;
ASTPtr elem;
if (!elem_parser->parse(pos, end, elem, expected))
return false;
function.range.first = begin;
function.range.second = pos;
function.name = it->second;
function.arguments = exp_list_node;
exp_list.children.push_back(elem);
exp_list.range.second = pos;
node = function_node;
return true;
}
ParserAccessExpression::ParserAccessExpression()
: elem_parser(new ParserExpressionElement),
operator_parser(boost::assign::map_list_of
(".", "tupleElement")
("[", "arrayElement"),
elem_parser)
{
}
bool ParserExpressionList::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
bool first = true;
ParserLogicalOrExpression nested_parser;
ParserWhiteSpaceOrComments ws;
ParserString comma(",");
ASTExpressionList * p_expr_list = new ASTExpressionList(StringRange(pos, pos));
ASTExpressionList & expr_list = *p_expr_list;
node = p_expr_list;
while (1)
{
if (first)
{
ASTPtr elem;
if (!nested_parser.parse(pos, end, elem, expected))
break;
expr_list.children.push_back(elem);
}
else
{
ws.ignore(pos, end);
if (!comma.ignore(pos, end, expected))
break;
ws.ignore(pos, end);
ASTPtr elem;
if (!nested_parser.parse(pos, end, elem, expected))
return false;
expr_list.children.push_back(elem);
}
first = false;
}
return true;
}
bool ParserNotEmptyExpressionList::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
return nested_parser.parse(pos, end, node, expected)
&& !dynamic_cast<ASTExpressionList &>(*node).children.empty();
}
}

View File

@ -1,81 +0,0 @@
#include <iostream>
#include <ostream>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <DB/Parsers/ExpressionGrammar.h>
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
typedef DB::ExpressionGrammarTypes::Expression Expr;
class dumpConst : public boost::static_visitor<>
{
public:
void operator() (const DB::ExpressionGrammarTypes::NumberConstant & x) const
{
std::cout << "Number: " << x << std::endl;
}
void operator() (const DB::ExpressionGrammarTypes::StringConstant & x) const
{
std::cout << "String: " << x << std::endl;
}
void operator() (const DB::ExpressionGrammarTypes::NullConstant & x) const
{
std::cout << "Null" << std::endl;
}
};
class dumpNode : public boost::static_visitor<>
{
public:
void operator() (const DB::ExpressionGrammarTypes::Constant & x) const
{
boost::apply_visitor(dumpConst(), x);
}
void operator() (const DB::ExpressionGrammarTypes::Name & x) const
{
std::cout << "Name: " << x << std::endl;
}
void operator() (const DB::ExpressionGrammarTypes::Function & x) const
{
std::cout << "Function, name: " << x.name << ", args: " << std::endl;
for (Expr::const_iterator it = x.args.begin(); it != x.args.end(); ++it)
boost::apply_visitor(dumpNode(), *it);
std::cout << std::endl;
}
};
void dumpResult(const Expr & value)
{
for (Expr::const_iterator it = value.begin(); it != value.end(); ++it)
boost::apply_visitor(dumpNode(), *it);
}
int main(int argc, char ** argv)
{
typedef std::string::const_iterator iterator_t;
DB::ExpressionGrammar<iterator_t> parser;
DB::ExpressionGrammarTypes::Expression value;
std::string s = "ab1, b, f(c), 0, g(h(i), 1), -1, NULL, null, 'abc'";
iterator_t it = s.begin();
iterator_t end = s.end();
bool res = boost::spirit::qi::phrase_parse(it, end, parser, ascii::space, value);
std::cout << res << '\t' << s.substr(0, it - s.begin()) << std::endl;
dumpResult(value);
return 0;
}

View File

@ -0,0 +1,32 @@
#include <iostream>
#include <strconvert/escape_manip.h>
#include <DB/Parsers/ASTSelectQuery.h>
#include <DB/Parsers/ParserSelectQuery.h>
int main(int argc, char ** argv)
{
DB::ParserSelectQuery parser;
DB::ASTPtr ast;
std::string input = "SELECT 1, 2, 3";
std::string expected;
const char * begin = input.data();
const char * end = begin + input.size();
const char * pos = begin;
if (parser.parse(pos, end, ast, expected))
{
std::cout << "Success." << std::endl;
}
else
{
std::cout << "Failed at position " << (pos - begin) << ": "
<< strconvert::quote_fast << input.substr(pos - begin, 10)
<< ", expected " << expected << "." << std::endl;
}
return 0;
}