ClickHouse/dbms/src/Interpreters/InterpreterCreateQuery.cpp

89 lines
3.2 KiB
C++
Raw Normal View History

2011-08-18 20:33:20 +00:00
#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;
2011-08-19 18:31:14 +00:00
String data_path = context.path + "data/" + database_name + "/"; /// TODO: эскейпинг
2011-08-18 20:33:20 +00:00
String metadata_path = context.path + "metadata/" + database_name + "/" + table_name + ".sql";
2011-08-19 18:31:14 +00:00
{
Poco::ScopedLock<Poco::FastMutex> lock(*context.mutex);
if ((*context.databases)[database_name].end() != (*context.databases)[database_name].find(table_name))
{
if (create.if_not_exists)
return (*context.databases)[database_name][table_name];
else
throw Exception("Table " + database_name + "." + table_name + " already exists.", ErrorCodes::TABLE_ALREADY_EXISTS);
}
}
2011-08-18 20:33:20 +00:00
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;
2011-08-28 05:13:24 +00:00
(*columns)[name_and_type_pair.name] = context.data_type_factory->get(String(type_range.first, type_range.second - type_range.first));
2011-08-18 20:33:20 +00:00
}
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);
2011-08-19 18:31:14 +00:00
/// Проверка наличия метаданных таблицы на диске и создание метаданных
2011-08-18 20:33:20 +00:00
2011-08-19 18:31:14 +00:00
if (Poco::File(metadata_path).exists())
throw Exception("Metadata for table " + database_name + "." + table_name + " already exists.",
ErrorCodes::TABLE_METADATA_ALREADY_EXISTS);
2011-08-18 20:33:20 +00:00
2011-08-19 18:31:14 +00:00
Poco::FileOutputStream metadata_file(metadata_path);
metadata_file << String(create.range.first, create.range.second - create.range.first) << std::endl;
{
Poco::ScopedLock<Poco::FastMutex> lock(*context.mutex);
2011-08-18 20:33:20 +00:00
2011-08-19 18:31:14 +00:00
(*context.databases)[database_name][table_name] = res;
}
2011-08-18 20:33:20 +00:00
return res;
}
}