mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 08:32:02 +00:00
dbms: development [#CONV-2944].
This commit is contained in:
parent
9b153918e7
commit
420e68e7c7
@ -30,12 +30,22 @@ public:
|
||||
Field operator[](size_t n) const { return typename NearestFieldType<T>::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); }
|
||||
|
||||
|
@ -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> expression_)
|
||||
: input(input_), expression(expression_) {}
|
||||
ExpressionBlockInputStream(BlockInputStreamPtr input_, SharedPtr<Expression> 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> expression;
|
||||
unsigned part_id;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
39
dbms/include/DB/DataStreams/ProjectionBlockInputStream.h
Normal file
39
dbms/include/DB/DataStreams/ProjectionBlockInputStream.h
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <Poco/SharedPtr.h>
|
||||
|
||||
#include <DB/Interpreters/Expression.h>
|
||||
#include <DB/DataStreams/IBlockInputStream.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using Poco::SharedPtr;
|
||||
|
||||
|
||||
/** Выбирает из блока только столбцы, являющиеся результатом вычисления выражения.
|
||||
* Следует применять после ExpressionBlockInputStream.
|
||||
*/
|
||||
class ProjectionBlockInputStream : public IBlockInputStream
|
||||
{
|
||||
public:
|
||||
ProjectionBlockInputStream(BlockInputStreamPtr input_, SharedPtr<Expression> 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> expression;
|
||||
unsigned part_id;
|
||||
};
|
||||
|
||||
}
|
@ -31,12 +31,12 @@ typedef std::map<String, Tables> Databases;
|
||||
*/
|
||||
struct Context
|
||||
{
|
||||
String path; /// Путь к директории с данными, со слешем на конце.
|
||||
SharedPtr<Databases> databases; /// Список БД и таблиц в них.
|
||||
String current_database; /// Текущая БД.
|
||||
SharedPtr<Functions> functions; /// Обычные функции.
|
||||
DataTypeFactory data_type_factory; /// Типы данных.
|
||||
NamesAndTypes columns; /// Столбцы текущей обрабатываемой таблицы.
|
||||
String path; /// Путь к директории с данными, со слешем на конце.
|
||||
SharedPtr<Databases> databases; /// Список БД и таблиц в них.
|
||||
String current_database; /// Текущая БД.
|
||||
SharedPtr<Functions> functions; /// Обычные функции.
|
||||
SharedPtr<DataTypeFactory> data_type_factory; /// Типы данных.
|
||||
NamesAndTypes columns; /// Столбцы текущей обрабатываемой таблицы.
|
||||
|
||||
SharedPtr<Poco::FastMutex> mutex; /// Для доступа и модификации разделяемых объектов.
|
||||
|
||||
|
@ -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<String> 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);
|
||||
};
|
||||
|
45
dbms/include/DB/Interpreters/InterpreterSelectQuery.h
Normal file
45
dbms/include/DB/Interpreters/InterpreterSelectQuery.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <DB/Interpreters/Context.h>
|
||||
#include <DB/DataStreams/IBlockInputStream.h>
|
||||
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
}
|
@ -28,7 +28,7 @@ public:
|
||||
Block read();
|
||||
private:
|
||||
size_t block_size;
|
||||
const Names & column_names;
|
||||
Names column_names;
|
||||
StorageLog & storage;
|
||||
|
||||
struct Stream
|
||||
|
@ -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<ssize_t>(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<size_t>(filter_column))
|
||||
res.getByPosition(i).column->filter(filter);
|
||||
|
||||
res.erase(filter_column);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include <DB/DataStreams/LimitBlockInputStream.h>
|
||||
#include <DB/DataStreams/ExpressionBlockInputStream.h>
|
||||
#include <DB/DataStreams/ProjectionBlockInputStream.h>
|
||||
#include <DB/DataStreams/TabSeparatedRowOutputStream.h>
|
||||
#include <DB/DataStreams/copyData.h>
|
||||
|
||||
@ -59,10 +60,11 @@ int main(int argc, char ** argv)
|
||||
DB::Names column_names;
|
||||
column_names.push_back("number");
|
||||
|
||||
Poco::SharedPtr<DB::IBlockInputStream> in1(table.read(column_names, 0));
|
||||
|
||||
Poco::SharedPtr<DB::ExpressionBlockInputStream> in2 = new DB::ExpressionBlockInputStream(in1, expression);
|
||||
DB::LimitBlockInputStream in3(in2, 10, std::max(static_cast<Int64>(0), static_cast<Int64>(n) - 10));
|
||||
Poco::SharedPtr<DB::IBlockInputStream> 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<Int64>(0), static_cast<Int64>(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)
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include <DB/DataStreams/LimitBlockInputStream.h>
|
||||
#include <DB/DataStreams/ExpressionBlockInputStream.h>
|
||||
#include <DB/DataStreams/ProjectionBlockInputStream.h>
|
||||
#include <DB/DataStreams/FilterBlockInputStream.h>
|
||||
#include <DB/DataStreams/TabSeparatedRowOutputStream.h>
|
||||
#include <DB/DataStreams/copyData.h>
|
||||
@ -68,6 +69,7 @@ int main(int argc, char ** argv)
|
||||
|
||||
Poco::SharedPtr<DB::IBlockInputStream> 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<Int64>(0), static_cast<Int64>(n) - 10));
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include <DB/DataStreams/LimitBlockInputStream.h>
|
||||
#include <DB/DataStreams/ExpressionBlockInputStream.h>
|
||||
#include <DB/DataStreams/ProjectionBlockInputStream.h>
|
||||
#include <DB/DataStreams/FilterBlockInputStream.h>
|
||||
#include <DB/DataStreams/ProfilingBlockInputStream.h>
|
||||
#include <DB/DataStreams/TabSeparatedRowOutputStream.h>
|
||||
@ -169,6 +170,7 @@ int main(int argc, char ** argv)
|
||||
Poco::SharedPtr<DB::IBlockInputStream> in = table.read(column_names, 0);
|
||||
Poco::SharedPtr<DB::ProfilingBlockInputStream> 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<Int64>(0), static_cast<Int64>(n) - 10));
|
||||
|
||||
|
@ -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<ASTLiteral *>(&*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<ASTFunction *>(&*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<ASTIdentifier *>(&*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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -38,7 +38,7 @@ StoragePtr InterpreterCreateQuery::execute(ASTPtr query, Context & context)
|
||||
{
|
||||
ASTNameTypePair & name_and_type_pair = dynamic_cast<ASTNameTypePair &>(**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<ASTFunction &>(*create.storage);
|
||||
|
102
dbms/src/Interpreters/InterpreterSelectQuery.cpp
Normal file
102
dbms/src/Interpreters/InterpreterSelectQuery.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
#include <DB/DataStreams/ExpressionBlockInputStream.h>
|
||||
#include <DB/DataStreams/ProjectionBlockInputStream.h>
|
||||
#include <DB/DataStreams/FilterBlockInputStream.h>
|
||||
#include <DB/DataStreams/LimitBlockInputStream.h>
|
||||
|
||||
#include <DB/Parsers/ASTSelectQuery.h>
|
||||
#include <DB/Parsers/ASTIdentifier.h>
|
||||
|
||||
#include <DB/Interpreters/Expression.h>
|
||||
#include <DB/Interpreters/InterpreterSelectQuery.h>
|
||||
|
||||
|
||||
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<ASTSelectQuery &>(*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<ASTIdentifier &>(*query.database).name;
|
||||
if (query.table)
|
||||
table_name = dynamic_cast<ASTIdentifier &>(*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<ASTSelectQuery &>(*query_ptr).select_expression_list, context);
|
||||
return expression.getReturnTypes();
|
||||
}
|
||||
|
||||
|
||||
BlockInputStreamPtr InterpreterSelectQuery::execute()
|
||||
{
|
||||
ASTSelectQuery & query = dynamic_cast<ASTSelectQuery &>(*query_ptr);
|
||||
|
||||
StoragePtr table = getTable();
|
||||
|
||||
/// Какие столбцы читать из этой таблицы
|
||||
|
||||
context.columns = table->getColumns();
|
||||
Poco::SharedPtr<Expression> 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);
|
||||
}
|
||||
|
||||
}
|
168
dbms/src/Interpreters/tests/select_query.cpp
Normal file
168
dbms/src/Interpreters/tests/select_query.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
#include <boost/assign/list_inserter.hpp>
|
||||
|
||||
#include <Poco/SharedPtr.h>
|
||||
#include <Poco/Stopwatch.h>
|
||||
#include <Poco/NumberParser.h>
|
||||
|
||||
#include <DB/IO/WriteBufferFromOStream.h>
|
||||
|
||||
#include <DB/Storages/StorageLog.h>
|
||||
|
||||
#include <DB/DataStreams/TabSeparatedRowOutputStream.h>
|
||||
#include <DB/DataStreams/copyData.h>
|
||||
|
||||
#include <DB/DataTypes/DataTypesNumberFixed.h>
|
||||
|
||||
//#include <DB/Functions/FunctionsArithmetic.h>
|
||||
#include <DB/Functions/FunctionsComparison.h>
|
||||
//#include <DB/Functions/FunctionsLogical.h>
|
||||
|
||||
#include <DB/Parsers/ParserSelectQuery.h>
|
||||
#include <DB/Parsers/formatAST.h>
|
||||
|
||||
#include <DB/Interpreters/InterpreterSelectQuery.h>
|
||||
|
||||
|
||||
using Poco::SharedPtr;
|
||||
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
try
|
||||
{
|
||||
typedef std::pair<std::string, SharedPtr<DB::IDataType> > NameAndTypePair;
|
||||
typedef std::list<NameAndTypePair> 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<DB::NamesAndTypes> 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;
|
||||
}
|
@ -67,7 +67,8 @@ bool ParserSelectQuery::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & ex
|
||||
ws.ignore(pos, end);
|
||||
}
|
||||
|
||||
dynamic_cast<ASTIdentifier &>(*select_query->database).kind = ASTIdentifier::Database;
|
||||
if (select_query->database)
|
||||
dynamic_cast<ASTIdentifier &>(*select_query->database).kind = ASTIdentifier::Database;
|
||||
dynamic_cast<ASTIdentifier &>(*select_query->table).kind = ASTIdentifier::Table;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user