dbms: development [#CONV-2944].

This commit is contained in:
Alexey Milovidov 2011-08-18 20:33:20 +00:00
parent bf1e7e85f0
commit 492cb89aa9
13 changed files with 261 additions and 30 deletions

View File

@ -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,
};
}

View File

@ -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

View File

@ -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;

View File

@ -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
{

View File

@ -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; /// Столбцы текущей обрабатываемой таблицы.
};

View 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);
};
}

View File

@ -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;
};

View File

@ -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");

View File

@ -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)
;
}

View 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;
}
}

View 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;
}

View File

@ -39,7 +39,8 @@ Block NumbersBlockInputStream::read()
}
StorageSystemNumbers::StorageSystemNumbers()
StorageSystemNumbers::StorageSystemNumbers(const std::string & name_)
: name(name_)
{
columns["number"] = new DataTypeUInt64;
}

View File

@ -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");