diff --git a/dbms/include/DB/Columns/ColumnConst.h b/dbms/include/DB/Columns/ColumnConst.h index 76c85043111..016ca90f0c1 100644 --- a/dbms/include/DB/Columns/ColumnConst.h +++ b/dbms/include/DB/Columns/ColumnConst.h @@ -30,12 +30,22 @@ public: Field operator[](size_t n) const { return typename NearestFieldType::Type(data); } void cut(size_t start, size_t length) { s = length; } void clear() { s = 0; } + void insert(const Field & x) { - throw Exception("Cannot insert element into constant column", ErrorCodes::CANNOT_INSERT_ELEMENT_INTO_CONSTANT_COLUMN); + throw Exception("Cannot insert element into constant column " + getName(), ErrorCodes::CANNOT_INSERT_ELEMENT_INTO_CONSTANT_COLUMN); } + void insertDefault() { ++s; } - void filter(const Filter & filt) {} + + void filter(const Filter & filt) + { + size_t new_size = 0; + for (Filter::const_iterator it = filt.begin(); it != filt.end(); ++it) + if (*it) + ++new_size; + s = new_size; + } size_t byteSize() { return sizeof(data) + sizeof(s); } diff --git a/dbms/include/DB/DataStreams/ExpressionBlockInputStream.h b/dbms/include/DB/DataStreams/ExpressionBlockInputStream.h index db152000289..c612a48893e 100644 --- a/dbms/include/DB/DataStreams/ExpressionBlockInputStream.h +++ b/dbms/include/DB/DataStreams/ExpressionBlockInputStream.h @@ -16,12 +16,14 @@ using Poco::SharedPtr; * Выражение состоит из идентификаторов столбцов из блока, констант, обычных функций. * Например: hits * 2 + 3, instr("yandex", url) * Выражение не меняет количество строк в потоке, и обрабатывает каждую строку независимо от других. + * part_id - идентификатор части выражения, которую надо вычислять. + * Например, может потребоваться вычислить только часть выражения в секции WHERE. */ class ExpressionBlockInputStream : public IBlockInputStream { public: - ExpressionBlockInputStream(BlockInputStreamPtr input_, SharedPtr expression_) - : input(input_), expression(expression_) {} + ExpressionBlockInputStream(BlockInputStreamPtr input_, SharedPtr expression_, unsigned part_id_ = 0) + : input(input_), expression(expression_), part_id(part_id_) {} Block read() { @@ -29,13 +31,14 @@ public: if (!res) return res; - expression->execute(res); - return expression->projectResult(res); + expression->execute(res, part_id); + return res; } private: BlockInputStreamPtr input; SharedPtr expression; + unsigned part_id; }; } diff --git a/dbms/include/DB/DataStreams/FilterBlockInputStream.h b/dbms/include/DB/DataStreams/FilterBlockInputStream.h index 1dcdd544071..bb152b437bb 100644 --- a/dbms/include/DB/DataStreams/FilterBlockInputStream.h +++ b/dbms/include/DB/DataStreams/FilterBlockInputStream.h @@ -13,18 +13,18 @@ using Poco::SharedPtr; /** Реализует операции WHERE, HAVING. * На вход подаётся поток блоков, в котором в одном из столбцов типа ColumnUInt8 содержатся условия фильтрации. - * Возвращается поток блоков, в котором содержатся только отфильтрованные строки, а также столбец с условиями фильтрации убран. + * Возвращается поток блоков, в котором содержатся только отфильтрованные строки. */ class FilterBlockInputStream : public IBlockInputStream { public: - /// filter_column_ - номер столбца с условиями фильтрации - FilterBlockInputStream(BlockInputStreamPtr input_, size_t filter_column_); + /// filter_column_ - номер столбца с условиями фильтрации. -1 - последний столбец + FilterBlockInputStream(BlockInputStreamPtr input_, ssize_t filter_column_ = -1); Block read(); private: BlockInputStreamPtr input; - size_t filter_column; + ssize_t filter_column; }; } diff --git a/dbms/include/DB/DataStreams/ProjectionBlockInputStream.h b/dbms/include/DB/DataStreams/ProjectionBlockInputStream.h new file mode 100644 index 00000000000..18581aeb094 --- /dev/null +++ b/dbms/include/DB/DataStreams/ProjectionBlockInputStream.h @@ -0,0 +1,39 @@ +#pragma once + +#include + +#include +#include + + +namespace DB +{ + +using Poco::SharedPtr; + + +/** Выбирает из блока только столбцы, являющиеся результатом вычисления выражения. + * Следует применять после ExpressionBlockInputStream. + */ +class ProjectionBlockInputStream : public IBlockInputStream +{ +public: + ProjectionBlockInputStream(BlockInputStreamPtr input_, SharedPtr expression_, unsigned part_id_ = 0) + : input(input_), expression(expression_), part_id(part_id_) {} + + Block read() + { + Block res = input->read(); + if (!res) + return res; + + return expression->projectResult(res, part_id); + } + +private: + BlockInputStreamPtr input; + SharedPtr expression; + unsigned part_id; +}; + +} diff --git a/dbms/include/DB/Interpreters/Context.h b/dbms/include/DB/Interpreters/Context.h index 79c9a2017f8..d9032bd8c44 100644 --- a/dbms/include/DB/Interpreters/Context.h +++ b/dbms/include/DB/Interpreters/Context.h @@ -31,12 +31,12 @@ typedef std::map Databases; */ struct Context { - String path; /// Путь к директории с данными, со слешем на конце. - SharedPtr databases; /// Список БД и таблиц в них. - String current_database; /// Текущая БД. - SharedPtr functions; /// Обычные функции. - DataTypeFactory data_type_factory; /// Типы данных. - NamesAndTypes columns; /// Столбцы текущей обрабатываемой таблицы. + String path; /// Путь к директории с данными, со слешем на конце. + SharedPtr databases; /// Список БД и таблиц в них. + String current_database; /// Текущая БД. + SharedPtr functions; /// Обычные функции. + SharedPtr data_type_factory; /// Типы данных. + NamesAndTypes columns; /// Столбцы текущей обрабатываемой таблицы. SharedPtr mutex; /// Для доступа и модификации разделяемых объектов. diff --git a/dbms/include/DB/Interpreters/Expression.h b/dbms/include/DB/Interpreters/Expression.h index 359a25d60e9..972f0c86053 100644 --- a/dbms/include/DB/Interpreters/Expression.h +++ b/dbms/include/DB/Interpreters/Expression.h @@ -24,6 +24,10 @@ public: glueTree(ast); } + /** Получить список столбцов, которых необходимо прочитать из таблицы, чтобы выполнить выражение. + */ + Names getRequiredColumns(); + /** Выполнить выражение над блоком. Блок должен содержать все столбцы - идентификаторы. * Функция добавляет в блок новые столбцы - результаты вычислений. * part_id - какую часть выражения вычислять. @@ -33,7 +37,7 @@ public: /** Взять из блока с промежуточными результатами вычислений только столбцы, представляющие собой конечный результат. * Вернуть новый блок, в котором эти столбцы расположены в правильном порядке. */ - Block projectResult(Block & block); + Block projectResult(Block & block, unsigned part_id = 0); /** Получить список типов столбцов результата. */ @@ -43,6 +47,9 @@ private: ASTPtr ast; const Context & context; + typedef std::set NamesSet; + NamesSet required_columns; + /** Для узлов - литералов - прописать их типы данных. * Для узлов - функций - прописать ссылки на функции и заменить имена на канонические. @@ -71,7 +78,7 @@ private: void executeImpl(ASTPtr ast, Block & block, unsigned part_id); - void collectFinalColumns(ASTPtr ast, Block & src, Block & dst); + void collectFinalColumns(ASTPtr ast, Block & src, Block & dst, unsigned part_id); void getReturnTypesImpl(ASTPtr ast, DataTypes & res); }; diff --git a/dbms/include/DB/Interpreters/InterpreterSelectQuery.h b/dbms/include/DB/Interpreters/InterpreterSelectQuery.h new file mode 100644 index 00000000000..d6397b81b27 --- /dev/null +++ b/dbms/include/DB/Interpreters/InterpreterSelectQuery.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include + + +namespace DB +{ + + +/** Интерпретирует запрос SELECT. Возвращает поток блоков с результатами выполнения запроса. + */ +class InterpreterSelectQuery +{ +public: + InterpreterSelectQuery(ASTPtr query_ptr_, Context & context_, size_t max_block_size_ = DEFAULT_BLOCK_SIZE); + + BlockInputStreamPtr execute(); + + DataTypes getReturnTypes(); + +private: + StoragePtr getTable(); + + /** Пометить часть дерева запроса некоторым part_id. + * - для того, чтобы потом можно было вычислить только часть выражения из запроса. + */ + void setPartID(ASTPtr ast, unsigned part_id); + + enum PartID + { + PART_OTHER = 0, + PART_SELECT = 1, + PART_WHERE = 2, + PART_HAVING = 3, + }; + + + ASTPtr query_ptr; + Context context; + size_t max_block_size; +}; + + +} diff --git a/dbms/include/DB/Storages/StorageLog.h b/dbms/include/DB/Storages/StorageLog.h index 4d254738167..2d7789e6399 100644 --- a/dbms/include/DB/Storages/StorageLog.h +++ b/dbms/include/DB/Storages/StorageLog.h @@ -28,7 +28,7 @@ public: Block read(); private: size_t block_size; - const Names & column_names; + Names column_names; StorageLog & storage; struct Stream diff --git a/dbms/src/DataStreams/FilterBlockInputStream.cpp b/dbms/src/DataStreams/FilterBlockInputStream.cpp index 4ecb0feab61..731b4a0b03a 100644 --- a/dbms/src/DataStreams/FilterBlockInputStream.cpp +++ b/dbms/src/DataStreams/FilterBlockInputStream.cpp @@ -6,7 +6,7 @@ namespace DB { -FilterBlockInputStream::FilterBlockInputStream(BlockInputStreamPtr input_, size_t filter_column_) +FilterBlockInputStream::FilterBlockInputStream(BlockInputStreamPtr input_, ssize_t filter_column_) : input(input_), filter_column(filter_column_) { } @@ -17,6 +17,9 @@ Block FilterBlockInputStream::read() if (!res) return res; + if (filter_column < 0) + filter_column = static_cast(res.columns()) + filter_column; + size_t columns = res.columns(); ColumnPtr column = res.getByPosition(filter_column).column; @@ -35,10 +38,9 @@ Block FilterBlockInputStream::read() IColumn::Filter & filter = column_vec->getData(); for (size_t i = 0; i < columns; ++i) - if (i != filter_column) + if (i != static_cast(filter_column)) res.getByPosition(i).column->filter(filter); - res.erase(filter_column); return res; } diff --git a/dbms/src/DataStreams/tests/expression_stream.cpp b/dbms/src/DataStreams/tests/expression_stream.cpp index 4119c335fd1..110fe60141d 100644 --- a/dbms/src/DataStreams/tests/expression_stream.cpp +++ b/dbms/src/DataStreams/tests/expression_stream.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -59,10 +60,11 @@ int main(int argc, char ** argv) DB::Names column_names; column_names.push_back("number"); - Poco::SharedPtr in1(table.read(column_names, 0)); - - Poco::SharedPtr in2 = new DB::ExpressionBlockInputStream(in1, expression); - DB::LimitBlockInputStream in3(in2, 10, std::max(static_cast(0), static_cast(n) - 10)); + Poco::SharedPtr in; + in = table.read(column_names, 0); + in = new DB::ExpressionBlockInputStream(in, expression); + in = new DB::ProjectionBlockInputStream(in, expression); + in = new DB::LimitBlockInputStream(in, 10, std::max(static_cast(0), static_cast(n) - 10)); DB::WriteBufferFromOStream out1(std::cout); DB::TabSeparatedRowOutputStream out2(out1, new DB::DataTypes(expression->getReturnTypes())); @@ -71,7 +73,7 @@ int main(int argc, char ** argv) Poco::Stopwatch stopwatch; stopwatch.start(); - DB::copyData(in3, out2); + DB::copyData(*in, out2); stopwatch.stop(); std::cout << std::fixed << std::setprecision(2) diff --git a/dbms/src/DataStreams/tests/filter_stream.cpp b/dbms/src/DataStreams/tests/filter_stream.cpp index 28487223ce4..ad084277898 100644 --- a/dbms/src/DataStreams/tests/filter_stream.cpp +++ b/dbms/src/DataStreams/tests/filter_stream.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -68,6 +69,7 @@ int main(int argc, char ** argv) Poco::SharedPtr in = table.read(column_names, 0); in = new DB::ExpressionBlockInputStream(in, expression); + in = new DB::ProjectionBlockInputStream(in, expression); in = new DB::FilterBlockInputStream(in, 1); in = new DB::LimitBlockInputStream(in, 10, std::max(static_cast(0), static_cast(n) - 10)); diff --git a/dbms/src/DataStreams/tests/filter_stream_hitlog.cpp b/dbms/src/DataStreams/tests/filter_stream_hitlog.cpp index b73aa01dcb1..b81f286816a 100644 --- a/dbms/src/DataStreams/tests/filter_stream_hitlog.cpp +++ b/dbms/src/DataStreams/tests/filter_stream_hitlog.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -169,6 +170,7 @@ int main(int argc, char ** argv) Poco::SharedPtr in = table.read(column_names, 0); Poco::SharedPtr profiling = new DB::ProfilingBlockInputStream(in); in = new DB::ExpressionBlockInputStream(profiling, expression); + in = new DB::ProjectionBlockInputStream(in, expression); in = new DB::FilterBlockInputStream(in, 4); //in = new DB::LimitBlockInputStream(in, 10, std::max(static_cast(0), static_cast(n) - 10)); diff --git a/dbms/src/Interpreters/Expression.cpp b/dbms/src/Interpreters/Expression.cpp index 54109c5c945..4f5ae267fac 100644 --- a/dbms/src/Interpreters/Expression.cpp +++ b/dbms/src/Interpreters/Expression.cpp @@ -30,6 +30,7 @@ void Expression::addSemantic(ASTPtr ast) throw Exception("Unknown identifier " + node->name, ErrorCodes::UNKNOWN_IDENTIFIER); node->type = it->second; + required_columns.insert(node->name); } } else if (ASTLiteral * node = dynamic_cast(&*ast)) @@ -107,6 +108,16 @@ void Expression::glueTreeImpl(ASTPtr ast, Subtrees & subtrees) } +Names Expression::getRequiredColumns() +{ + Names res; + res.reserve(required_columns.size()); + for (NamesSet::const_iterator it = required_columns.begin(); it != required_columns.end(); ++it) + res.push_back(*it); + return res; +} + + void Expression::setNotCalculated(ASTPtr ast, unsigned part_id) { if (ast->part_id == part_id) @@ -189,16 +200,24 @@ void Expression::executeImpl(ASTPtr ast, Block & block, unsigned part_id) } -Block Expression::projectResult(Block & block) +Block Expression::projectResult(Block & block, unsigned part_id) { Block res; - collectFinalColumns(ast, block, res); + collectFinalColumns(ast, block, res, part_id); return res; } -void Expression::collectFinalColumns(ASTPtr ast, Block & src, Block & dst) +void Expression::collectFinalColumns(ASTPtr ast, Block & src, Block & dst, unsigned part_id) { + if (ast->part_id != part_id) + { + if (!dynamic_cast(&*ast)) + for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it) + collectFinalColumns(*it, src, dst, part_id); + return; + } + if (ASTIdentifier * ident = dynamic_cast(&*ast)) { if (ident->kind == ASTIdentifier::Column) @@ -211,7 +230,7 @@ void Expression::collectFinalColumns(ASTPtr ast, Block & src, Block & dst) dst.insert(src.getByPosition(*jt)); else for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it) - collectFinalColumns(*it, src, dst); + collectFinalColumns(*it, src, dst, part_id); } diff --git a/dbms/src/Interpreters/InterpreterCreateQuery.cpp b/dbms/src/Interpreters/InterpreterCreateQuery.cpp index 5b0fbe89a94..237568a8732 100644 --- a/dbms/src/Interpreters/InterpreterCreateQuery.cpp +++ b/dbms/src/Interpreters/InterpreterCreateQuery.cpp @@ -38,7 +38,7 @@ StoragePtr InterpreterCreateQuery::execute(ASTPtr query, Context & context) { ASTNameTypePair & name_and_type_pair = dynamic_cast(**it); StringRange type_range = name_and_type_pair.type->range; - (*columns)[name_and_type_pair.name] = context.data_type_factory.get(String(type_range.first, type_range.second - type_range.first)); + (*columns)[name_and_type_pair.name] = context.data_type_factory->get(String(type_range.first, type_range.second - type_range.first)); } ASTFunction & storage_expr = dynamic_cast(*create.storage); diff --git a/dbms/src/Interpreters/InterpreterSelectQuery.cpp b/dbms/src/Interpreters/InterpreterSelectQuery.cpp new file mode 100644 index 00000000000..8039872c344 --- /dev/null +++ b/dbms/src/Interpreters/InterpreterSelectQuery.cpp @@ -0,0 +1,102 @@ +#include +#include +#include +#include + +#include +#include + +#include +#include + + +namespace DB +{ + + +InterpreterSelectQuery::InterpreterSelectQuery(ASTPtr query_ptr_, Context & context_, size_t max_block_size_) + : query_ptr(query_ptr_), context(context_), max_block_size(max_block_size_) +{ +} + + +StoragePtr InterpreterSelectQuery::getTable() +{ + ASTSelectQuery & query = dynamic_cast(*query_ptr); + + /// Из какой таблицы читать данные. JOIN-ы не поддерживаются. + + String database_name; + String table_name; + + /** Если таблица не указана - используем таблицу system.one. + * Если база данных не указана - используем текущую базу данных. + */ + if (!query.table) + { + database_name = "system"; + table_name = "one"; + } + else if (!query.database) + database_name = context.current_database; + + if (query.database) + database_name = dynamic_cast(*query.database).name; + if (query.table) + table_name = dynamic_cast(*query.table).name; + + if (context.databases->end() == context.databases->find(database_name) + || (*context.databases)[database_name].end() == (*context.databases)[database_name].find(table_name)) + throw Exception("Unknown table " + table_name + " in database " + database_name, ErrorCodes::UNKNOWN_TABLE); + + return (*context.databases)[database_name][table_name]; +} + + +DataTypes InterpreterSelectQuery::getReturnTypes() +{ + context.columns = getTable()->getColumns(); + Expression expression(dynamic_cast(*query_ptr).select_expression_list, context); + return expression.getReturnTypes(); +} + + +BlockInputStreamPtr InterpreterSelectQuery::execute() +{ + ASTSelectQuery & query = dynamic_cast(*query_ptr); + + StoragePtr table = getTable(); + + /// Какие столбцы читать из этой таблицы + + context.columns = table->getColumns(); + Poco::SharedPtr expression = new Expression(query_ptr, context); + BlockInputStreamPtr stream = table->read(expression->getRequiredColumns(), query_ptr, max_block_size); + + /// Если есть условие WHERE - сначала выполним часть выражения, необходимую для его вычисления + if (query.where_expression) + { + setPartID(query.where_expression, PART_WHERE); + stream = new ExpressionBlockInputStream(stream, expression, PART_WHERE); + stream = new FilterBlockInputStream(stream); + } + + /// Выполним оставшуюся часть выражения + stream = new ExpressionBlockInputStream(stream, expression); + + setPartID(query.select_expression_list, PART_SELECT); + stream = new ProjectionBlockInputStream(stream, expression, PART_SELECT); + + return stream; +} + + +void InterpreterSelectQuery::setPartID(ASTPtr ast, unsigned part_id) +{ + ast->part_id = part_id; + + for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it) + setPartID(*it, part_id); +} + +} diff --git a/dbms/src/Interpreters/tests/select_query.cpp b/dbms/src/Interpreters/tests/select_query.cpp new file mode 100644 index 00000000000..8f48bb97e41 --- /dev/null +++ b/dbms/src/Interpreters/tests/select_query.cpp @@ -0,0 +1,168 @@ +#include +#include + +#include + +#include +#include +#include + +#include + +#include + +#include +#include + +#include + +//#include +#include +//#include + +#include +#include + +#include + + +using Poco::SharedPtr; + + +int main(int argc, char ** argv) +{ + try + { + typedef std::pair > NameAndTypePair; + typedef std::list NamesAndTypesList; + + NamesAndTypesList names_and_types_list; + + boost::assign::push_back(names_and_types_list) + ("WatchID", new DB::DataTypeUInt64) + ("JavaEnable", new DB::DataTypeUInt8) + ("Title", new DB::DataTypeString) + ("GoodEvent", new DB::DataTypeUInt32) + ("EventTime", new DB::DataTypeDateTime) + ("CounterID", new DB::DataTypeUInt32) + ("ClientIP", new DB::DataTypeUInt32) + ("RegionID", new DB::DataTypeUInt32) + ("UniqID", new DB::DataTypeUInt64) + ("CounterClass", new DB::DataTypeUInt8) + ("OS", new DB::DataTypeUInt8) + ("UserAgent", new DB::DataTypeUInt8) + ("URL", new DB::DataTypeString) + ("Referer", new DB::DataTypeString) + ("Refresh", new DB::DataTypeUInt8) + ("ResolutionWidth", new DB::DataTypeUInt16) + ("ResolutionHeight", new DB::DataTypeUInt16) + ("ResolutionDepth", new DB::DataTypeUInt8) + ("FlashMajor", new DB::DataTypeUInt8) + ("FlashMinor", new DB::DataTypeUInt8) + ("FlashMinor2", new DB::DataTypeString) + ("NetMajor", new DB::DataTypeUInt8) + ("NetMinor", new DB::DataTypeUInt8) + ("UserAgentMajor", new DB::DataTypeUInt16) + ("UserAgentMinor", new DB::DataTypeFixedString(2)) + ("CookieEnable", new DB::DataTypeUInt8) + ("JavascriptEnable", new DB::DataTypeUInt8) + ("IsMobile", new DB::DataTypeUInt8) + ("MobilePhone", new DB::DataTypeUInt8) + ("MobilePhoneModel", new DB::DataTypeString) + ("Params", new DB::DataTypeString) + ("IPNetworkID", new DB::DataTypeUInt32) + ("TraficSourceID", new DB::DataTypeInt8) + ("SearchEngineID", new DB::DataTypeUInt16) + ("SearchPhrase", new DB::DataTypeString) + ("AdvEngineID", new DB::DataTypeUInt8) + ("IsArtifical", new DB::DataTypeUInt8) + ("WindowClientWidth", new DB::DataTypeUInt16) + ("WindowClientHeight", new DB::DataTypeUInt16) + ("ClientTimeZone", new DB::DataTypeInt16) + ("ClientEventTime", new DB::DataTypeDateTime) + ("SilverlightVersion1", new DB::DataTypeUInt8) + ("SilverlightVersion2", new DB::DataTypeUInt8) + ("SilverlightVersion3", new DB::DataTypeUInt32) + ("SilverlightVersion4", new DB::DataTypeUInt16) + ("PageCharset", new DB::DataTypeString) + ("CodeVersion", new DB::DataTypeUInt32) + ("IsLink", new DB::DataTypeUInt8) + ("IsDownload", new DB::DataTypeUInt8) + ("IsNotBounce", new DB::DataTypeUInt8) + ("FUniqID", new DB::DataTypeUInt64) + ("OriginalURL", new DB::DataTypeString) + ("HID", new DB::DataTypeUInt32) + ("IsOldCounter", new DB::DataTypeUInt8) + ("IsEvent", new DB::DataTypeUInt8) + ("IsParameter", new DB::DataTypeUInt8) + ("DontCountHits", new DB::DataTypeUInt8) + ("WithHash", new DB::DataTypeUInt8) + ; + + SharedPtr names_and_types_map = new DB::NamesAndTypes; + + for (NamesAndTypesList::const_iterator it = names_and_types_list.begin(); it != names_and_types_list.end(); ++it) + { + names_and_types_map->insert(*it); + } + + DB::Context context; + +/* (*context.functions)["plus"] = new DB::FunctionPlus; + (*context.functions)["minus"] = new DB::FunctionMinus; + (*context.functions)["multiply"] = new DB::FunctionMultiply; + (*context.functions)["divide"] = new DB::FunctionDivideFloating; + (*context.functions)["intDiv"] = new DB::FunctionDivideIntegral; + (*context.functions)["modulo"] = new DB::FunctionModulo; +*/ + (*context.functions)["equals"] = new DB::FunctionEquals; +/* (*context.functions)["notEquals"] = new DB::FunctionNotEquals; + (*context.functions)["less"] = new DB::FunctionLess; + (*context.functions)["greater"] = new DB::FunctionGreater; + (*context.functions)["lessOrEquals"] = new DB::FunctionLessOrEquals; + (*context.functions)["greaterOrEquals"] = new DB::FunctionGreaterOrEquals; + + (*context.functions)["and"] = new DB::FunctionAnd; + (*context.functions)["or"] = new DB::FunctionOr; + (*context.functions)["xor"] = new DB::FunctionXor; + (*context.functions)["not"] = new DB::FunctionNot; +*/ + (*context.databases)["default"]["hits"] = new DB::StorageLog("./", "hits", names_and_types_map, ".bin"); + context.current_database = "default"; + + DB::ParserSelectQuery parser; + DB::ASTPtr ast; + std::string input = "SELECT UniqID, URL, CounterID, IsLink FROM hits WHERE URL = 'http://mail.yandex.ru/neo2/#inbox'"; + 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 << "Failed at position " << (pos - begin) << ": " + << mysqlxx::quote << input.substr(pos - begin, 10) + << ", expected " << expected << "." << std::endl; + } + +/* DB::formatAST(*ast, std::cerr); + std::cerr << std::endl; + std::cerr << ast->getTreeID() << std::endl; +*/ + DB::InterpreterSelectQuery interpreter(ast, context); + DB::BlockInputStreamPtr in = interpreter.execute(); + + DB::WriteBufferFromOStream ob(std::cout); + DB::TabSeparatedRowOutputStream out(ob, new DB::DataTypes(interpreter.getReturnTypes())); + + DB::copyData(*in, out); + } + catch (const DB::Exception & e) + { + std::cerr << e.what() << ", " << e.message() << std::endl; + return 1; + } + + return 0; +} diff --git a/dbms/src/Parsers/ParserSelectQuery.cpp b/dbms/src/Parsers/ParserSelectQuery.cpp index 28c1e8c2074..9fcca3519ca 100644 --- a/dbms/src/Parsers/ParserSelectQuery.cpp +++ b/dbms/src/Parsers/ParserSelectQuery.cpp @@ -67,7 +67,8 @@ bool ParserSelectQuery::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & ex ws.ignore(pos, end); } - dynamic_cast(*select_query->database).kind = ASTIdentifier::Database; + if (select_query->database) + dynamic_cast(*select_query->database).kind = ASTIdentifier::Database; dynamic_cast(*select_query->table).kind = ASTIdentifier::Table; }