dbms: development [#CONV-2944].

This commit is contained in:
Alexey Milovidov 2011-08-13 23:03:07 +00:00
parent e29501b7d4
commit b2a826727e
3 changed files with 63 additions and 15 deletions

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <set>
#include <Poco/SharedPtr.h> #include <Poco/SharedPtr.h>
#include <DB/Parsers/IAST.h> #include <DB/Parsers/IAST.h>
@ -58,6 +60,13 @@ private:
void setNotCalculated(ASTPtr ast); void setNotCalculated(ASTPtr ast);
void executeImpl(ASTPtr ast, Block & block); void executeImpl(ASTPtr ast, Block & block);
/** Взять из блока с промежуточными результатами вычислений только столбцы, представляющие собой конечный результат.
* Вернуть новый блок, в котором эти столбцы расположены в правильном порядке.
*/
Block projectResult(ASTPtr ast, Block & block);
void collectFinalColumns(ASTPtr ast, Block & src, Block & dst);
}; };

View File

@ -34,8 +34,7 @@ void Expression::addSemantic(ASTPtr ast)
node->type = boost::apply_visitor(FieldToDataType(), node->value); node->type = boost::apply_visitor(FieldToDataType(), node->value);
} }
ASTs children = ast->children; for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
for (ASTs::iterator it = children.begin(); it != children.end(); ++it)
addSemantic(*it); addSemantic(*it);
} }
@ -44,8 +43,7 @@ void Expression::checkTypes(ASTPtr ast)
{ {
/// Обход в глубину /// Обход в глубину
ASTs children = ast->children; for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
for (ASTs::iterator it = children.begin(); it != children.end(); ++it)
checkTypes(*it); checkTypes(*it);
if (ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast)) if (ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast))
@ -81,8 +79,7 @@ void Expression::glueTreeImpl(ASTPtr ast, Subtrees & subtrees)
{ {
/// Обход в глубину /// Обход в глубину
ASTs children = ast->children; for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
for (ASTs::iterator it = children.begin(); it != children.end(); ++it)
glueTreeImpl(*it, subtrees); glueTreeImpl(*it, subtrees);
if (ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast)) if (ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast))
@ -110,8 +107,7 @@ void Expression::glueTreeImpl(ASTPtr ast, Subtrees & subtrees)
void Expression::setNotCalculated(ASTPtr ast) void Expression::setNotCalculated(ASTPtr ast)
{ {
ast->calculated = false; ast->calculated = false;
ASTs children = ast->children; for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
for (ASTs::iterator it = children.begin(); it != children.end(); ++it)
setNotCalculated(*it); setNotCalculated(*it);
} }
@ -120,6 +116,7 @@ void Expression::execute(Block & block)
{ {
setNotCalculated(ast); setNotCalculated(ast);
executeImpl(ast, block); executeImpl(ast, block);
block = projectResult(ast, block);
} }
@ -127,8 +124,7 @@ void Expression::executeImpl(ASTPtr ast, Block & block)
{ {
/// Обход в глубину /// Обход в глубину
ASTs children = ast->children; for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
for (ASTs::iterator it = children.begin(); it != children.end(); ++it)
executeImpl(*it, block); executeImpl(*it, block);
if (ast->calculated) if (ast->calculated)
@ -189,5 +185,34 @@ void Expression::executeImpl(ASTPtr ast, Block & block)
ast->calculated = true; ast->calculated = true;
} }
Block Expression::projectResult(ASTPtr ast, Block & block)
{
Block res;
collectFinalColumns(ast, block, res);
return res;
}
void Expression::collectFinalColumns(ASTPtr ast, Block & src, Block & dst)
{
if (ASTExpressionList * node = dynamic_cast<ASTExpressionList *>(&*ast))
{
for (ASTs::iterator it = node->children.begin(); it != node->children.end(); ++it)
{
if (ASTIdentifier * ident = dynamic_cast<ASTIdentifier *>(&**it))
dst.insert(src.getByName(ident->name));
else if (ASTFunction * func = dynamic_cast<ASTFunction *>(&**it))
for (ColumnNumbers::const_iterator jt = func->return_column_numbers.begin(); jt != func->return_column_numbers.end(); ++jt)
dst.insert(src.getByPosition(*jt));
else
dst.insert(src.getByName((*it)->getTreeID()));
}
}
else
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
collectFinalColumns(*it, src, dst);
}
} }

View File

@ -1,6 +1,7 @@
#include <iostream> #include <iostream>
#include <iomanip>
#include <mysqlxx/mysqlxx.h> #include <Poco/Stopwatch.h>
#include <DB/IO/WriteBufferFromOStream.h> #include <DB/IO/WriteBufferFromOStream.h>
@ -13,6 +14,7 @@
#include <DB/Parsers/formatAST.h> #include <DB/Parsers/formatAST.h>
#include <DB/DataStreams/TabSeparatedRowOutputStream.h> #include <DB/DataStreams/TabSeparatedRowOutputStream.h>
#include <DB/DataStreams/LimitBlockInputStream.h>
#include <DB/DataStreams/copyData.h> #include <DB/DataStreams/copyData.h>
#include <DB/Interpreters/Expression.h> #include <DB/Interpreters/Expression.h>
@ -105,7 +107,7 @@ int main(int argc, char ** argv)
dump(*ast); dump(*ast);
size_t n = 10; size_t n = argc == 2 ? atoi(argv[1]) : 10;
DB::Block block; DB::Block block;
DB::ColumnWithNameAndType column_x; DB::ColumnWithNameAndType column_x;
@ -121,17 +123,29 @@ int main(int argc, char ** argv)
block.insert(column_x); block.insert(column_x);
expression.execute(block); {
Poco::Stopwatch stopwatch;
stopwatch.start();
expression.execute(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; DB::DataTypes * data_types = new DB::DataTypes;
for (size_t i = 0; i < block.columns(); ++i) for (size_t i = 0; i < block.columns(); ++i)
data_types->push_back(block.getByPosition(i).type); data_types->push_back(block.getByPosition(i).type);
OneBlockInputStream is(block); OneBlockInputStream * is = new OneBlockInputStream(block);
DB::LimitBlockInputStream lis(is, 10, std::max(0, static_cast<int>(n) - 10));
DB::WriteBufferFromOStream out_buf(std::cout); DB::WriteBufferFromOStream out_buf(std::cout);
DB::TabSeparatedRowOutputStream os(out_buf, data_types); DB::TabSeparatedRowOutputStream os(out_buf, data_types);
DB::copyData(is, os); DB::copyData(lis, os);
} }
catch (const DB::Exception & e) catch (const DB::Exception & e)
{ {