2014-01-28 16:45:10 +00:00
# pragma once
# include <statdaemons/OptimizedRegularExpression.h>
# 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>
namespace DB
{
/*
* merge ( db_name , tables_regexp ) - с о з д а ё т в р е м е н н ы й StorageMerge .
* Cтр у кту р а т а б л и ц ы б е р ё т с я и з п е р в о й п о п а в ш е й с я т а б л и ц ы , п о д х о д я щ е й п о д р е г е к с п .
* Е с л и т а к о й т а б л и ц ы н е т - к и д а е т с я и с к л ю ч е н и е .
*/
class TableFunctionMerge : public ITableFunction
{
public :
std : : string getName ( ) const { return " merge " ; }
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
{
ASTs & args_func = dynamic_cast < ASTFunction & > ( * ast_function ) . children ;
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 ) ;
ASTs & args = dynamic_cast < ASTExpressionList & > ( * args_func . at ( 0 ) ) . children ;
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 ) ;
String source_database = dynamic_cast < ASTIdentifier & > ( * args [ 0 ] ) . name ;
2014-02-06 16:21:00 +00:00
String table_name_regexp = safeGet < const String & > ( dynamic_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-01-28 16:45:10 +00:00
dynamic_cast < ASTIdentifier & > ( * args [ 0 ] ) . kind = ASTIdentifier : : Database ;
2014-02-07 15:11:57 +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
}
} ;
}