#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void dump(DB::IAST & ast, int level = 0) { std::string prefix(level, ' '); if (DB::ASTFunction * node = dynamic_cast(&ast)) { std::cout << prefix << node << " Function, name = " << node->function->getName() << ", return type: " << node->return_type->getName() << std::endl; } else if (DB::ASTIdentifier * node = dynamic_cast(&ast)) { std::cout << prefix << node << " Identifier, name = " << node->name << ", type = " << node->type->getName() << std::endl; } else if (DB::ASTLiteral * node = dynamic_cast(&ast)) { std::cout << prefix << node << " Literal, " << boost::apply_visitor(DB::FieldVisitorToString(), node->value) << ", type = " << node->type->getName() << std::endl; } DB::ASTs children = ast.children; for (DB::ASTs::iterator it = children.begin(); it != children.end(); ++it) dump(**it, level + 1); } class OneBlockInputStream : public DB::IBlockInputStream { private: const DB::Block & block; bool has_been_read; public: OneBlockInputStream(const DB::Block & block_) : block(block_), has_been_read(false) {} DB::Block read() { if (!has_been_read) { has_been_read = true; return block; } else return DB::Block(); } DB::String getName() const { return "OneBlockInputStream"; } }; int main(int argc, char ** argv) { try { DB::ParserSelectQuery parser; DB::ASTPtr ast; std::string input = "SELECT x, s1, s2, " "/*" "2 + x * 2, x * 2, x % 3 == 1, " "s1 == 'abc', s1 == s2, s1 != 'abc', s1 != s2, " "s1 < 'abc', s1 < s2, s1 > 'abc', s1 > s2, " "s1 <= 'abc', s1 <= s2, s1 >= 'abc', s1 >= s2, " "*/" "s1 < s2 AND x % 3 < x % 5"; 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; DB::formatAST(*ast, std::cout); std::cout << std::endl << ast->getTreeID() << std::endl; } else { std::cout << "Failed at position " << (pos - begin) << ": " << mysqlxx::quote << input.substr(pos - begin, 10) << ", expected " << expected << "." << std::endl; } DB::Context context; context.columns["x"] = new DB::DataTypeInt16; context.columns["s1"] = new DB::DataTypeString; context.columns["s2"] = new DB::DataTypeString; (*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; DB::Expression expression(ast, context); dump(*ast); size_t n = argc == 2 ? atoi(argv[1]) : 10; DB::Block block; DB::ColumnWithNameAndType column_x; column_x.name = "x"; column_x.type = new DB::DataTypeInt16; DB::ColumnInt16 * x = new DB::ColumnInt16; column_x.column = x; std::vector & vec_x = x->getData(); vec_x.resize(n); for (size_t i = 0; i < n; ++i) vec_x[i] = i; block.insert(column_x); const char * strings[] = {"abc", "def", "abcd", "defg", "ac"}; DB::ColumnWithNameAndType column_s1; column_s1.name = "s1"; column_s1.type = new DB::DataTypeString; column_s1.column = new DB::ColumnString; for (size_t i = 0; i < n; ++i) column_s1.column->insert(strings[i % 5]); block.insert(column_s1); DB::ColumnWithNameAndType column_s2; column_s2.name = "s2"; column_s2.type = new DB::DataTypeString; column_s2.column = new DB::ColumnString; for (size_t i = 0; i < n; ++i) column_s2.column->insert(strings[i % 3]); block.insert(column_s2); { Poco::Stopwatch stopwatch; stopwatch.start(); expression.execute(block); block = expression.projectResult(block); stopwatch.stop(); std::cout << std::fixed << std::setprecision(2) << "Elapsed " << stopwatch.elapsed() / 1000000.0 << " sec." << ", " << n * 1000000 / stopwatch.elapsed() << " rows/sec." << std::endl; } DB::DataTypes * data_types = new DB::DataTypes; for (size_t i = 0; i < block.columns(); ++i) data_types->push_back(block.getByPosition(i).type); OneBlockInputStream * is = new OneBlockInputStream(block); DB::LimitBlockInputStream lis(is, 20, std::max(0, static_cast(n) - 20)); DB::WriteBufferFromOStream out_buf(std::cout); DB::TabSeparatedRowOutputStream os(out_buf, data_types); DB::copyData(lis, os); } catch (const DB::Exception & e) { std::cerr << e.message() << std::endl; } return 0; }