mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 15:12:02 +00:00
dbms: development [#CONV-2944].
This commit is contained in:
parent
bf1e7e85f0
commit
492cb89aa9
@ -61,6 +61,9 @@ namespace ErrorCodes
|
||||
EMPTY_LIST_OF_COLUMNS_QUERIED,
|
||||
COLUMN_QUERIED_MORE_THAN_ONCE,
|
||||
TYPE_MISMATCH,
|
||||
STORAGE_DOESNT_ALLOW_PARAMETERS,
|
||||
UNKNOWN_STORAGE,
|
||||
TABLE_ALREADY_EXISTS,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,7 @@
|
||||
|
||||
#include <Poco/RegularExpression.h>
|
||||
|
||||
#include <DB/DataTypes/DataTypesNumberFixed.h>
|
||||
#include <DB/DataTypes/DataTypesNumberVariable.h>
|
||||
#include <DB/DataTypes/DataTypeDate.h>
|
||||
#include <DB/DataTypes/DataTypeDateTime.h>
|
||||
#include <DB/DataTypes/DataTypeString.h>
|
||||
#include <DB/DataTypes/DataTypeFixedString.h>
|
||||
#include <DB/DataTypes/IDataType.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
|
@ -19,9 +19,12 @@ using Poco::SharedPtr;
|
||||
class IDataType
|
||||
{
|
||||
public:
|
||||
/// Основное имя типа (например, BIGINT UNSIGNED).
|
||||
/// Основное имя типа (например, UInt64).
|
||||
virtual std::string getName() const = 0;
|
||||
|
||||
/// Является ли тип числовым.
|
||||
virtual bool isNumeric() const { return false; }
|
||||
|
||||
/// Клонировать
|
||||
virtual SharedPtr<IDataType> clone() const = 0;
|
||||
|
||||
|
@ -19,6 +19,8 @@ class IDataTypeNumber : public IDataType
|
||||
{
|
||||
public:
|
||||
typedef FType FieldType;
|
||||
|
||||
bool isNumeric() const { return true; }
|
||||
|
||||
void serializeText(const Field & field, WriteBuffer & ostr) const
|
||||
{
|
||||
|
@ -1,26 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <Poco/SharedPtr.h>
|
||||
#include <set>
|
||||
|
||||
#include <DB/Core/NamesAndTypes.h>
|
||||
#include <DB/Storages/IStorage.h>
|
||||
#include <DB/Functions/IFunction.h>
|
||||
#include <DB/DataTypes/DataTypeFactory.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using Poco::SharedPtr;
|
||||
|
||||
/// имя функции -> функция
|
||||
typedef std::map<String, FunctionPtr> Functions;
|
||||
|
||||
/// имя таблицы -> таблица
|
||||
typedef std::map<String, StoragePtr> Tables;
|
||||
|
||||
/// имя БД -> таблицы
|
||||
typedef std::map<String, Tables> Databases;
|
||||
|
||||
|
||||
/** Набор известных объектов, которые могут быть использованы в запросе.
|
||||
*/
|
||||
struct Context
|
||||
{
|
||||
Functions functions;
|
||||
NamesAndTypes columns;
|
||||
String path; /// Путь к директории с данными, со слешем на конце.
|
||||
Databases databases; /// Список БД и таблиц в них.
|
||||
String current_database; /// Текущая БД.
|
||||
Functions functions; /// Обычные функции.
|
||||
DataTypeFactory data_type_factory; /// Типы данных.
|
||||
NamesAndTypes columns; /// Столбцы текущей обрабатываемой таблицы.
|
||||
};
|
||||
|
||||
|
||||
|
21
dbms/include/DB/Interpreters/InterpreterCreateQuery.h
Normal file
21
dbms/include/DB/Interpreters/InterpreterCreateQuery.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <DB/Storages/IStorage.h>
|
||||
#include <DB/Interpreters/Context.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
|
||||
/** Позволяет создать новую таблицу или создать объект уже существующей таблицы.
|
||||
*/
|
||||
class InterpreterCreateQuery
|
||||
{
|
||||
public:
|
||||
/// Добавляет созданную таблицу в контекст, а также возвращает её.
|
||||
StoragePtr execute(ASTPtr query, Context & context);
|
||||
};
|
||||
|
||||
|
||||
}
|
@ -30,7 +30,7 @@ private:
|
||||
class StorageSystemNumbers : public IStorage
|
||||
{
|
||||
public:
|
||||
StorageSystemNumbers();
|
||||
StorageSystemNumbers(const std::string & name_);
|
||||
|
||||
std::string getName() const { return "SystemNumbers"; }
|
||||
std::string getTableName() const { return "Numbers"; }
|
||||
@ -43,6 +43,7 @@ public:
|
||||
size_t max_block_size = DEFAULT_BLOCK_SIZE);
|
||||
|
||||
private:
|
||||
const std::string name;
|
||||
NamesAndTypes columns;
|
||||
};
|
||||
|
||||
|
@ -54,7 +54,7 @@ int main(int argc, char ** argv)
|
||||
|
||||
Poco::SharedPtr<DB::Expression> expression = new DB::Expression(ast, context);
|
||||
|
||||
DB::StorageSystemNumbers table;
|
||||
DB::StorageSystemNumbers table("Numbers");
|
||||
|
||||
DB::Names column_names;
|
||||
column_names.push_back("number");
|
||||
|
@ -2,6 +2,12 @@
|
||||
|
||||
#include <mysqlxx/String.h>
|
||||
|
||||
#include <DB/DataTypes/DataTypesNumberFixed.h>
|
||||
#include <DB/DataTypes/DataTypesNumberVariable.h>
|
||||
#include <DB/DataTypes/DataTypeDate.h>
|
||||
#include <DB/DataTypes/DataTypeDateTime.h>
|
||||
#include <DB/DataTypes/DataTypeString.h>
|
||||
#include <DB/DataTypes/DataTypeFixedString.h>
|
||||
#include <DB/DataTypes/DataTypeFactory.h>
|
||||
|
||||
|
||||
@ -13,19 +19,21 @@ DataTypeFactory::DataTypeFactory()
|
||||
: fixed_string_regexp("^FixedString\\s*\\(\\s*(\\d+)\\s*\\)$")
|
||||
{
|
||||
boost::assign::insert(non_parametric_data_types)
|
||||
("UInt8", new DataTypeUInt8)
|
||||
("UInt16", new DataTypeUInt16)
|
||||
("UInt32", new DataTypeUInt32)
|
||||
("UInt64", new DataTypeUInt64)
|
||||
("Int8", new DataTypeInt8)
|
||||
("Int16", new DataTypeInt16)
|
||||
("Int32", new DataTypeInt32)
|
||||
("Int64", new DataTypeInt64)
|
||||
("Float32", new DataTypeFloat32)
|
||||
("Float64", new DataTypeFloat64)
|
||||
("VarUInt", new DataTypeVarUInt)
|
||||
("VarInt", new DataTypeVarInt)
|
||||
("String", new DataTypeString)
|
||||
("UInt8", new DataTypeUInt8)
|
||||
("UInt16", new DataTypeUInt16)
|
||||
("UInt32", new DataTypeUInt32)
|
||||
("UInt64", new DataTypeUInt64)
|
||||
("Int8", new DataTypeInt8)
|
||||
("Int16", new DataTypeInt16)
|
||||
("Int32", new DataTypeInt32)
|
||||
("Int64", new DataTypeInt64)
|
||||
("Float32", new DataTypeFloat32)
|
||||
("Float64", new DataTypeFloat64)
|
||||
("VarUInt", new DataTypeVarUInt)
|
||||
("VarInt", new DataTypeVarInt)
|
||||
("Date", new DataTypeDate)
|
||||
("DateTime", new DataTypeDateTime)
|
||||
("String", new DataTypeString)
|
||||
;
|
||||
}
|
||||
|
||||
|
76
dbms/src/Interpreters/InterpreterCreateQuery.cpp
Normal file
76
dbms/src/Interpreters/InterpreterCreateQuery.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
#include <DB/Parsers/ASTCreateQuery.h>
|
||||
#include <DB/Parsers/ASTNameTypePair.h>
|
||||
|
||||
#include <DB/Storages/StorageLog.h>
|
||||
#include <DB/Storages/StorageSystemNumbers.h>
|
||||
|
||||
#include <DB/Interpreters/InterpreterCreateQuery.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
|
||||
StoragePtr InterpreterCreateQuery::execute(ASTPtr query, Context & context)
|
||||
{
|
||||
ASTCreateQuery & create = dynamic_cast<ASTCreateQuery &>(*query);
|
||||
|
||||
String database_name = context.current_database;
|
||||
String table_name = create.name;
|
||||
SharedPtr<NamesAndTypes> columns = new NamesAndTypes;
|
||||
String data_path = context.path + "data/" + database_name + "/" + table_name + "/"; /// TODO: эскейпинг
|
||||
String metadata_path = context.path + "metadata/" + database_name + "/" + table_name + ".sql";
|
||||
|
||||
if (context.databases[database_name].end() != context.databases[database_name].find(table_name))
|
||||
throw Exception("Table " + database_name + "." + table_name + " already exists.", ErrorCodes::TABLE_ALREADY_EXISTS);
|
||||
|
||||
ASTExpressionList & columns_list = dynamic_cast<ASTExpressionList &>(*create.columns);
|
||||
for (ASTs::iterator it = columns_list.children.begin(); it != columns_list.children.end(); ++it)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
ASTFunction & storage_expr = dynamic_cast<ASTFunction &>(*create.storage);
|
||||
String storage_str(storage_expr.range.first, storage_expr.range.second - storage_expr.range.first);
|
||||
StoragePtr res;
|
||||
|
||||
/// Выбор нужного движка таблицы
|
||||
|
||||
if (storage_expr.name == "Log")
|
||||
{
|
||||
if (storage_expr.arguments)
|
||||
throw Exception("Storage Log doesn't allow parameters", ErrorCodes::STORAGE_DOESNT_ALLOW_PARAMETERS);
|
||||
|
||||
res = new StorageLog(data_path, table_name, columns);
|
||||
}
|
||||
else if (storage_expr.name == "SystemNumbers")
|
||||
{
|
||||
if (storage_expr.arguments)
|
||||
throw Exception("Storage SystemNumbers doesn't allow parameters", ErrorCodes::STORAGE_DOESNT_ALLOW_PARAMETERS);
|
||||
if (columns->size() != 1 || columns->begin()->first != "number" || columns->begin()->second->getName() != "UInt64")
|
||||
throw Exception("Storage SystemNumbers only allows one column with name 'number' and type 'UInt64'", ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
res = new StorageSystemNumbers(table_name);
|
||||
}
|
||||
else
|
||||
throw Exception("Unknown storage " + storage_str, ErrorCodes::UNKNOWN_STORAGE);
|
||||
|
||||
if (!create.attach)
|
||||
{
|
||||
/// Проверка наличия метаданных таблицы на диске и создание метаданных
|
||||
|
||||
if (Poco::File(metadata_path).exists())
|
||||
throw Exception("Table " + database_name + "." + table_name + " already exists.", ErrorCodes::TABLE_ALREADY_EXISTS);
|
||||
|
||||
Poco::FileOutputStream metadata_file(metadata_path);
|
||||
metadata_file << String(create.range.first, create.range.second - create.range.first) << std::endl;
|
||||
}
|
||||
|
||||
context.databases[database_name][table_name] = res;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
}
|
110
dbms/src/Interpreters/tests/create_query.cpp
Normal file
110
dbms/src/Interpreters/tests/create_query.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
#include <DB/Parsers/ParserCreateQuery.h>
|
||||
#include <DB/Parsers/formatAST.h>
|
||||
|
||||
#include <DB/Interpreters/InterpreterCreateQuery.h>
|
||||
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
try
|
||||
{
|
||||
DB::ParserCreateQuery parser;
|
||||
DB::ASTPtr ast;
|
||||
std::string input = "CREATE TABLE hits (\n"
|
||||
"WatchID UInt64,\n"
|
||||
"JavaEnable UInt8,\n"
|
||||
"Title String,\n"
|
||||
"GoodEvent UInt32,\n"
|
||||
"EventTime DateTime,\n"
|
||||
"CounterID UInt32,\n"
|
||||
"ClientIP UInt32,\n"
|
||||
"RegionID UInt32,\n"
|
||||
"UniqID UInt64,\n"
|
||||
"CounterClass UInt8,\n"
|
||||
"OS UInt8,\n"
|
||||
"UserAgent UInt8,\n"
|
||||
"URL String,\n"
|
||||
"Referer String,\n"
|
||||
"Refresh UInt8,\n"
|
||||
"ResolutionWidth UInt16,\n"
|
||||
"ResolutionHeight UInt16,\n"
|
||||
"ResolutionDepth UInt8,\n"
|
||||
"FlashMajor UInt8,\n"
|
||||
"FlashMinor UInt8,\n"
|
||||
"FlashMinor2 String,\n"
|
||||
"NetMajor UInt8,\n"
|
||||
"NetMinor UInt8,\n"
|
||||
"UserAgentMajor UInt16,\n"
|
||||
"UserAgentMinor FixedString(2),\n"
|
||||
"CookieEnable UInt8,\n"
|
||||
"JavascriptEnable UInt8,\n"
|
||||
"IsMobile UInt8,\n"
|
||||
"MobilePhone UInt8,\n"
|
||||
"MobilePhoneModel String,\n"
|
||||
"Params String,\n"
|
||||
"IPNetworkID UInt32,\n"
|
||||
"TraficSourceID Int8,\n"
|
||||
"SearchEngineID UInt16,\n"
|
||||
"SearchPhrase String,\n"
|
||||
"AdvEngineID UInt8,\n"
|
||||
"IsArtifical UInt8,\n"
|
||||
"WindowClientWidth UInt16,\n"
|
||||
"WindowClientHeight UInt16,\n"
|
||||
"ClientTimeZone Int16,\n"
|
||||
"ClientEventTime DateTime,\n"
|
||||
"SilverlightVersion1 UInt8,\n"
|
||||
"SilverlightVersion2 UInt8,\n"
|
||||
"SilverlightVersion3 UInt32,\n"
|
||||
"SilverlightVersion4 UInt16,\n"
|
||||
"PageCharset String,\n"
|
||||
"CodeVersion UInt32,\n"
|
||||
"IsLink UInt8,\n"
|
||||
"IsDownload UInt8,\n"
|
||||
"IsNotBounce UInt8,\n"
|
||||
"FUniqID UInt64,\n"
|
||||
"OriginalURL String,\n"
|
||||
"HID UInt32,\n"
|
||||
"IsOldCounter UInt8,\n"
|
||||
"IsEvent UInt8,\n"
|
||||
"IsParameter UInt8,\n"
|
||||
"DontCountHits UInt8,\n"
|
||||
"WithHash UInt8\n"
|
||||
") ENGINE = Log";
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Failed at position " << (pos - begin) << ": "
|
||||
<< mysqlxx::quote << input.substr(pos - begin, 10)
|
||||
<< ", expected " << expected << "." << std::endl;
|
||||
}
|
||||
|
||||
DB::Context context;
|
||||
|
||||
context.path = "./";
|
||||
context.databases["test"];
|
||||
context.current_database = "test";
|
||||
|
||||
DB::InterpreterCreateQuery interpreter;
|
||||
interpreter.execute(ast, context);
|
||||
}
|
||||
catch (const DB::Exception & e)
|
||||
{
|
||||
std::cerr << e.message() << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -39,7 +39,8 @@ Block NumbersBlockInputStream::read()
|
||||
}
|
||||
|
||||
|
||||
StorageSystemNumbers::StorageSystemNumbers()
|
||||
StorageSystemNumbers::StorageSystemNumbers(const std::string & name_)
|
||||
: name(name_)
|
||||
{
|
||||
columns["number"] = new DataTypeUInt64;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ int main(int argc, char ** argv)
|
||||
{
|
||||
try
|
||||
{
|
||||
DB::StorageSystemNumbers table;
|
||||
DB::StorageSystemNumbers table("Numbers");
|
||||
|
||||
DB::Names column_names;
|
||||
column_names.push_back("number");
|
||||
|
Loading…
Reference in New Issue
Block a user