2014-01-28 16:45:10 +00:00
# pragma once
2015-10-05 01:11:12 +00:00
# include <DB/Common/OptimizedRegularExpression.h>
2014-01-28 16:45:10 +00:00
# include <DB/Storages/StorageFactory.h>
# include <DB/Storages/StorageMerge.h>
# include <DB/Parsers/ASTExpressionList.h>
# include <DB/Parsers/ASTIdentifier.h>
# include <DB/Parsers/ASTLiteral.h>
# include <DB/TableFunctions/ITableFunction.h>
2014-09-23 16:02:04 +00:00
# include <DB/Interpreters/reinterpretAsIdentifier.h>
2014-01-28 16:45:10 +00:00
namespace DB
{
/*
* merge ( db_name , tables_regexp ) - с о з д а ё т в р е м е н н ы й StorageMerge .
* Cтр у кту р а т а б л и ц ы б е р ё т с я и з п е р в о й п о п а в ш е й с я т а б л и ц ы , п о д х о д я щ е й п о д р е г е к с п .
* Е с л и т а к о й т а б л и ц ы н е т - к и д а е т с я и с к л ю ч е н и е .
*/
class TableFunctionMerge : public ITableFunction
{
public :
2015-01-21 04:17:02 +00:00
std : : string getName ( ) const override { return " merge " ; }
2014-01-28 16:45:10 +00:00
2014-02-25 17:37:50 +00:00
StoragePtr execute ( ASTPtr ast_function , Context & context ) const override
2014-01-28 16:45:10 +00:00
{
2014-06-26 00:58:14 +00:00
ASTs & args_func = typeid_cast < ASTFunction & > ( * ast_function ) . children ;
2014-01-28 16:45:10 +00:00
if ( args_func . size ( ) ! = 1 )
throw Exception ( " Storage Merge requires exactly 2 parameters "
" - name of source database and regexp for table names. " ,
ErrorCodes : : NUMBER_OF_ARGUMENTS_DOESNT_MATCH ) ;
2014-06-26 00:58:14 +00:00
ASTs & args = typeid_cast < ASTExpressionList & > ( * args_func . at ( 0 ) ) . children ;
2014-01-28 16:45:10 +00:00
if ( args . size ( ) ! = 2 )
throw Exception ( " Storage Merge requires exactly 2 parameters "
" - name of source database and regexp for table names. " ,
ErrorCodes : : NUMBER_OF_ARGUMENTS_DOESNT_MATCH ) ;
2014-09-23 16:02:04 +00:00
String source_database = reinterpretAsIdentifier ( args [ 0 ] , context ) . name ;
2014-06-26 00:58:14 +00:00
String table_name_regexp = safeGet < const String & > ( typeid_cast < ASTLiteral & > ( * args [ 1 ] ) . value ) ;
2014-01-28 16:45:10 +00:00
/// В InterpreterSelectQuery будет создан ExpressionAnalzyer, который при обработке запроса наткнется на этот Identifier.
2014-03-24 13:24:47 +00:00
/// Нам необходимо е г о пометить как имя базы данных, поскольку по умолчанию стоит значение column
2014-06-26 00:58:14 +00:00
typeid_cast < ASTIdentifier & > ( * args [ 0 ] ) . kind = ASTIdentifier : : Database ;
2014-01-28 16:45:10 +00:00
2014-09-30 03:08:47 +00:00
return StorageMerge : : create ( getName ( ) , chooseColumns ( source_database , table_name_regexp , context ) ,
source_database , table_name_regexp , context ) ;
2014-01-28 16:45:10 +00:00
}
private :
2014-02-06 16:21:00 +00:00
NamesAndTypesListPtr chooseColumns ( const String & source_database , const String & table_name_regexp_ , Context & context ) const
2014-01-28 16:45:10 +00:00
{
OptimizedRegularExpression table_name_regexp ( table_name_regexp_ ) ;
2014-03-20 13:00:42 +00:00
StoragePtr any_table ;
{
/// Список таблиц могут менять в другом потоке.
Poco : : ScopedLock < Poco : : Mutex > lock ( context . getMutex ( ) ) ;
context . assertDatabaseExists ( source_database ) ;
const Tables & tables = context . getDatabases ( ) . at ( source_database ) ;
for ( Tables : : const_iterator it = tables . begin ( ) ; it ! = tables . end ( ) ; + + it )
if ( table_name_regexp . match ( it - > first ) )
{
any_table = it - > second ;
break ;
}
}
if ( ! any_table )
throw Exception ( " Error while executing table function merge. In database " + source_database + " no one matches regular expression: " + table_name_regexp_ , ErrorCodes : : UNKNOWN_TABLE ) ;
auto table_lock = any_table - > lockStructure ( false ) ;
return new NamesAndTypesList ( any_table - > getColumnsList ( ) ) ;
2014-01-28 16:45:10 +00:00
}
} ;
}