2016-10-25 12:14:27 +00:00
# include "LocalServer.h"
2017-03-14 18:39:06 +00:00
2023-02-25 02:20:47 +00:00
# include <sys/resource.h>
# include <Common/logger_useful.h>
# include <base/errnoToString.h>
2016-10-25 12:14:27 +00:00
# include <Poco/Util/XMLConfiguration.h>
2016-12-13 18:51:19 +00:00
# include <Poco/String.h>
2018-01-15 14:58:21 +00:00
# include <Poco/Logger.h>
# include <Poco/NullChannel.h>
2021-10-30 12:28:50 +00:00
# include <Poco/SimpleFileChannel.h>
2023-04-27 18:26:36 +00:00
# include <Databases/DatabaseFilesystem.h>
2018-03-23 20:46:43 +00:00
# include <Databases/DatabaseMemory.h>
2023-04-13 21:09:57 +00:00
# include <Databases/DatabasesOverlay.h>
2017-04-01 09:19:00 +00:00
# include <Storages/System/attachSystemTables.h>
2021-09-09 09:37:51 +00:00
# include <Storages/System/attachInformationSchemaTables.h>
2022-10-19 10:38:20 +00:00
# include <Interpreters/DatabaseCatalog.h>
# include <Interpreters/JIT/CompiledExpressionCache.h>
2017-04-01 09:19:00 +00:00
# include <Interpreters/ProcessList.h>
# include <Interpreters/loadMetadata.h>
2021-10-02 07:13:14 +00:00
# include <base/getFQDNOrHostName.h>
2022-04-27 15:05:45 +00:00
# include <Common/scope_guard_safe.h>
2021-08-12 15:16:55 +00:00
# include <Interpreters/Session.h>
2022-03-10 04:35:01 +00:00
# include <Access/AccessControl.h>
2017-04-01 09:19:00 +00:00
# include <Common/Exception.h>
# include <Common/Macros.h>
2018-02-28 20:34:25 +00:00
# include <Common/Config/ConfigProcessor.h>
2019-01-28 11:18:00 +00:00
# include <Common/ThreadStatus.h>
2021-10-25 18:12:45 +00:00
# include <Common/TLDListsHolder.h>
2019-10-08 18:42:22 +00:00
# include <Common/quoteString.h>
2021-10-25 18:12:45 +00:00
# include <Common/randomSeed.h>
2023-04-13 16:53:16 +00:00
# include <Common/ThreadPool.h>
2022-04-27 15:05:45 +00:00
# include <Loggers/Loggers.h>
2020-10-14 08:50:36 +00:00
# include <IO/ReadBufferFromFile.h>
2017-04-01 09:19:00 +00:00
# include <IO/ReadBufferFromString.h>
# include <IO/WriteBufferFromFileDescriptor.h>
2021-09-04 18:19:01 +00:00
# include <IO/UseSSL.h>
2023-05-03 16:56:45 +00:00
# include <IO/SharedThreadPools.h>
2017-04-01 09:19:00 +00:00
# include <Parsers/IAST.h>
2022-01-10 19:01:41 +00:00
# include <Parsers/ASTInsertQuery.h>
2022-04-27 15:05:45 +00:00
# include <Common/ErrorHandlers.h>
2022-09-24 21:24:39 +00:00
# include <Functions/UserDefined/IUserDefinedSQLObjectsLoader.h>
2017-04-21 17:47:27 +00:00
# include <Functions/registerFunctions.h>
2017-05-05 20:39:25 +00:00
# include <AggregateFunctions/registerAggregateFunctions.h>
2017-06-10 09:04:31 +00:00
# include <TableFunctions/registerTableFunctions.h>
2017-12-30 00:36:06 +00:00
# include <Storages/registerStorages.h>
2018-11-28 11:37:12 +00:00
# include <Dictionaries/registerDictionaries.h>
2019-11-27 09:39:44 +00:00
# include <Disks/registerDisks.h>
2020-10-29 03:39:43 +00:00
# include <Formats/registerFormats.h>
2022-01-20 12:55:28 +00:00
# include <Formats/FormatFactory.h>
2021-11-18 18:07:35 +00:00
# include <boost/algorithm/string/replace.hpp>
2018-04-20 19:31:19 +00:00
# include <boost/program_options/options_description.hpp>
2021-10-02 07:13:14 +00:00
# include <base/argsToConfig.h>
2020-06-24 19:03:28 +00:00
# include <filesystem>
2023-04-30 20:13:42 +00:00
# include "config.h"
2021-12-06 18:27:06 +00:00
# if defined(FUZZING_MODE)
# include <Functions/getFuzzerData.h>
# endif
2023-01-30 19:00:48 +00:00
# if USE_AZURE_BLOB_STORAGE
# include <azure / storage / common / internal / xml_wrapper.hpp>
# endif
2021-05-16 22:06:09 +00:00
namespace fs = std : : filesystem ;
2016-10-25 12:14:27 +00:00
2021-07-11 23:17:14 +00:00
2016-10-25 12:14:27 +00:00
namespace DB
{
2016-11-11 17:01:02 +00:00
namespace ErrorCodes
{
2020-06-24 22:07:01 +00:00
extern const int BAD_ARGUMENTS ;
2016-11-11 17:01:02 +00:00
extern const int CANNOT_LOAD_CONFIG ;
2020-10-23 09:53:35 +00:00
extern const int FILE_ALREADY_EXISTS ;
2016-11-11 17:01:02 +00:00
}
2021-10-04 15:23:08 +00:00
void LocalServer : : processError ( const String & ) const
2021-08-21 10:55:54 +00:00
{
2021-09-05 09:27:27 +00:00
if ( ignore_error )
2021-08-21 15:29:28 +00:00
return ;
2021-09-11 11:34:22 +00:00
if ( is_interactive )
2021-08-21 10:55:54 +00:00
{
2021-10-04 15:23:08 +00:00
String message ;
2021-09-11 11:34:22 +00:00
if ( server_exception )
{
2021-10-04 15:23:08 +00:00
message = getExceptionMessage ( * server_exception , print_stack_trace , true ) ;
2021-09-11 11:34:22 +00:00
}
2021-10-04 15:23:08 +00:00
else if ( client_exception )
2021-09-11 11:34:22 +00:00
{
2021-10-04 15:23:08 +00:00
message = client_exception - > message ( ) ;
2021-09-11 11:34:22 +00:00
}
2021-10-04 15:23:08 +00:00
fmt : : print ( stderr , " Received exception: \n {} \n " , message ) ;
fmt : : print ( stderr , " \n " ) ;
2021-08-21 10:55:54 +00:00
}
2021-09-11 11:34:22 +00:00
else
2021-08-21 10:55:54 +00:00
{
2021-09-11 11:34:22 +00:00
if ( server_exception )
server_exception - > rethrow ( ) ;
if ( client_exception )
client_exception - > rethrow ( ) ;
2021-08-21 10:55:54 +00:00
}
}
2016-11-11 17:01:02 +00:00
2016-10-25 12:14:27 +00:00
void LocalServer : : initialize ( Poco : : Util : : Application & self )
{
Poco : : Util : : Application : : initialize ( self ) ;
2018-01-15 14:58:21 +00:00
2019-06-14 14:00:37 +00:00
/// Load config files if exists
2021-05-16 22:06:09 +00:00
if ( config ( ) . has ( " config-file " ) | | fs : : exists ( " config.xml " ) )
2019-06-14 14:00:37 +00:00
{
const auto config_path = config ( ) . getString ( " config-file " , " config.xml " ) ;
ConfigProcessor config_processor ( config_path , false , true ) ;
2021-05-16 22:06:09 +00:00
config_processor . setConfigPath ( fs : : path ( config_path ) . parent_path ( ) ) ;
2019-06-14 14:00:37 +00:00
auto loaded_config = config_processor . loadConfig ( ) ;
config ( ) . add ( loaded_config . configuration . duplicate ( ) , PRIO_DEFAULT , false ) ;
}
2022-04-29 07:41:10 +00:00
GlobalThreadPool : : initialize (
config ( ) . getUInt ( " max_thread_pool_size " , 10000 ) ,
config ( ) . getUInt ( " max_thread_pool_free_size " , 1000 ) ,
config ( ) . getUInt ( " thread_pool_queue_size " , 10000 )
) ;
2023-01-30 19:00:48 +00:00
# if USE_AZURE_BLOB_STORAGE
/// See the explanation near the same line in Server.cpp
GlobalThreadPool : : instance ( ) . addOnDestroyCallback ( [ ]
{
Azure : : Storage : : _internal : : XmlGlobalDeinitialize ( ) ;
} ) ;
# endif
2023-06-06 12:42:56 +00:00
getIOThreadPool ( ) . initialize (
2022-04-29 07:41:10 +00:00
config ( ) . getUInt ( " max_io_thread_pool_size " , 100 ) ,
config ( ) . getUInt ( " max_io_thread_pool_free_size " , 0 ) ,
config ( ) . getUInt ( " io_thread_pool_queue_size " , 10000 ) ) ;
2023-05-03 16:56:45 +00:00
2023-06-06 12:42:56 +00:00
const size_t active_parts_loading_threads = config ( ) . getUInt ( " max_active_parts_loading_thread_pool_size " , 64 ) ;
getActivePartsLoadingThreadPool ( ) . initialize (
active_parts_loading_threads ,
0 , // We don't need any threads one all the parts will be loaded
active_parts_loading_threads ) ;
const size_t outdated_parts_loading_threads = config ( ) . getUInt ( " max_outdated_parts_loading_thread_pool_size " , 32 ) ;
getOutdatedPartsLoadingThreadPool ( ) . initialize (
outdated_parts_loading_threads ,
2023-05-03 16:56:45 +00:00
0 , // We don't need any threads one all the parts will be loaded
2023-06-06 12:42:56 +00:00
outdated_parts_loading_threads ) ;
getOutdatedPartsLoadingThreadPool ( ) . setMaxTurboThreads ( active_parts_loading_threads ) ;
const size_t cleanup_threads = config ( ) . getUInt ( " max_parts_cleaning_thread_pool_size " , 128 ) ;
getPartsCleaningThreadPool ( ) . initialize (
cleanup_threads ,
0 , // We don't need any threads one all the parts will be deleted
cleanup_threads ) ;
2016-10-25 12:14:27 +00:00
}
2016-10-31 14:31:26 +00:00
2021-09-09 12:43:12 +00:00
static DatabasePtr createMemoryDatabaseIfNotExists ( ContextPtr context , const String & database_name )
2018-04-20 15:32:40 +00:00
{
2021-09-09 12:43:12 +00:00
DatabasePtr system_database = DatabaseCatalog : : instance ( ) . tryGetDatabase ( database_name ) ;
if ( ! system_database )
{
/// TODO: add attachTableDelayed into DatabaseMemory to speedup loading
system_database = std : : make_shared < DatabaseMemory > ( database_name , context ) ;
DatabaseCatalog : : instance ( ) . attachDatabase ( database_name , system_database ) ;
}
return system_database ;
2016-10-31 14:31:26 +00:00
}
2023-04-27 18:26:36 +00:00
static DatabasePtr createClickHouseLocalDatabaseOverlay ( const String & name_ , ContextPtr context_ )
{
auto databaseCombiner = std : : make_shared < DatabasesOverlay > ( name_ , context_ ) ;
databaseCombiner - > registerNextDatabase ( std : : make_shared < DatabaseFilesystem > ( name_ , " " , context_ ) ) ;
databaseCombiner - > registerNextDatabase ( std : : make_shared < DatabaseMemory > ( name_ , context_ ) ) ;
return databaseCombiner ;
}
2021-09-09 12:43:12 +00:00
2016-12-13 18:51:19 +00:00
/// If path is specified and not empty, will try to setup server environment and load existing metadata
void LocalServer : : tryInitPath ( )
{
2020-06-24 19:03:28 +00:00
std : : string path ;
if ( config ( ) . has ( " path " ) )
{
// User-supplied path.
path = config ( ) . getString ( " path " ) ;
Poco : : trimInPlace ( path ) ;
2016-12-13 18:51:19 +00:00
2020-06-24 19:03:28 +00:00
if ( path . empty ( ) )
{
throw Exception ( ErrorCodes : : BAD_ARGUMENTS ,
2020-08-08 01:21:04 +00:00
" Cannot work with empty storage path that is explicitly specified "
2020-06-24 22:07:01 +00:00
" by the --path option. Please check the program options and "
2020-06-24 19:03:28 +00:00
" correct the --path. " ) ;
}
}
else
2018-04-20 15:32:40 +00:00
{
2020-10-26 07:59:15 +00:00
// The path is not provided explicitly - use a unique path in the system temporary directory
// (or in the current dir if temporary don't exist)
2020-10-23 09:53:35 +00:00
Poco : : Logger * log = & logger ( ) ;
std : : filesystem : : path parent_folder ;
std : : filesystem : : path default_path ;
2018-04-20 15:32:40 +00:00
2020-10-23 09:53:35 +00:00
try
2020-06-24 19:03:28 +00:00
{
2020-10-23 09:53:35 +00:00
// try to guess a tmp folder name, and check if it's a directory (throw exception otherwise)
parent_folder = std : : filesystem : : temp_directory_path ( ) ;
}
2023-02-25 02:20:47 +00:00
catch ( const fs : : filesystem_error & e )
2020-10-23 09:53:35 +00:00
{
2023-02-25 02:20:47 +00:00
// The tmp folder doesn't exist? Is it a misconfiguration? Or chroot?
2020-10-23 09:53:35 +00:00
LOG_DEBUG ( log , " Can not get temporary folder: {} " , e . what ( ) ) ;
parent_folder = std : : filesystem : : current_path ( ) ;
std : : filesystem : : is_directory ( parent_folder ) ; // that will throw an exception if it's not a directory
LOG_DEBUG ( log , " Will create working directory inside current directory: {} " , parent_folder . string ( ) ) ;
}
2020-10-26 07:59:15 +00:00
/// we can have another clickhouse-local running simultaneously, even with the same PID (for ex. - several dockers mounting the same folder)
2020-10-23 09:53:35 +00:00
/// or it can be some leftovers from other clickhouse-local runs
/// as we can't accurately distinguish those situations we don't touch any existent folders
/// we just try to pick some free name for our working folder
2020-10-23 14:57:06 +00:00
default_path = parent_folder / fmt : : format ( " clickhouse-local-{}-{}-{} " , getpid ( ) , time ( nullptr ) , randomSeed ( ) ) ;
2020-10-23 09:53:35 +00:00
2020-10-23 14:57:06 +00:00
if ( exists ( default_path ) )
2020-10-27 11:04:03 +00:00
throw Exception ( ErrorCodes : : FILE_ALREADY_EXISTS , " Unsuccessful attempt to create working directory: {} exist! " , default_path . string ( ) ) ;
2020-06-24 19:03:28 +00:00
create_directory ( default_path ) ;
temporary_directory_to_delete = default_path ;
path = default_path . string ( ) ;
2020-10-23 09:53:35 +00:00
LOG_DEBUG ( log , " Working directory created: {} " , path ) ;
2018-04-20 15:32:40 +00:00
}
2016-12-13 18:51:19 +00:00
2020-06-24 19:03:28 +00:00
if ( path . back ( ) ! = ' / ' )
path + = ' / ' ;
2022-03-29 10:02:21 +00:00
fs : : create_directories ( fs : : path ( path ) / " user_defined/ " ) ;
fs : : create_directories ( fs : : path ( path ) / " data/ " ) ;
fs : : create_directories ( fs : : path ( path ) / " metadata/ " ) ;
fs : : create_directories ( fs : : path ( path ) / " metadata_dropped/ " ) ;
2020-10-22 07:37:03 +00:00
global_context - > setPath ( path ) ;
2020-10-20 15:57:53 +00:00
2022-12-06 10:04:15 +00:00
global_context - > setTemporaryStoragePath ( path + " tmp/ " , 0 ) ;
2020-10-22 07:37:03 +00:00
global_context - > setFlagsPath ( path + " flags " ) ;
2020-10-20 15:57:53 +00:00
2020-10-22 07:37:03 +00:00
global_context - > setUserFilesPath ( " " ) ; // user's files are everywhere
2021-10-25 18:12:45 +00:00
/// top_level_domains_lists
const std : : string & top_level_domains_path = config ( ) . getString ( " top_level_domains_path " , path + " top_level_domains/ " ) ;
if ( ! top_level_domains_path . empty ( ) )
TLDListsHolder : : getInstance ( ) . parseConfig ( fs : : path ( top_level_domains_path ) / " " , config ( ) ) ;
2016-12-13 18:51:19 +00:00
}
2021-07-11 23:17:14 +00:00
void LocalServer : : cleanup ( )
2020-03-18 00:57:00 +00:00
{
2021-10-16 11:28:57 +00:00
try
2020-03-18 00:57:00 +00:00
{
2021-10-16 11:28:57 +00:00
connection . reset ( ) ;
2021-09-04 18:19:01 +00:00
2021-10-16 11:28:57 +00:00
if ( global_context )
{
global_context - > shutdown ( ) ;
global_context . reset ( ) ;
}
2021-09-04 18:19:01 +00:00
2022-09-05 21:10:03 +00:00
/// thread status should be destructed before shared context because it relies on process list.
2021-10-16 11:28:57 +00:00
status . reset ( ) ;
2021-09-04 18:19:01 +00:00
2021-10-16 11:28:57 +00:00
// Delete the temporary directory if needed.
if ( temporary_directory_to_delete )
{
const auto dir = * temporary_directory_to_delete ;
temporary_directory_to_delete . reset ( ) ;
LOG_DEBUG ( & logger ( ) , " Removing temporary directory: {} " , dir . string ( ) ) ;
remove_all ( dir ) ;
}
}
catch ( . . . )
2021-07-11 23:17:14 +00:00
{
2021-10-16 11:28:57 +00:00
tryLogCurrentException ( __PRETTY_FUNCTION__ ) ;
2020-03-18 00:57:00 +00:00
}
}
2021-07-11 23:17:14 +00:00
2022-02-10 13:57:32 +00:00
static bool checkIfStdinIsRegularFile ( )
2022-02-10 12:24:13 +00:00
{
struct stat file_stat ;
2022-02-10 13:57:32 +00:00
return fstat ( STDIN_FILENO , & file_stat ) = = 0 & & S_ISREG ( file_stat . st_mode ) ;
2022-02-10 12:24:13 +00:00
}
2021-07-11 23:17:14 +00:00
std : : string LocalServer : : getInitialCreateTableQuery ( )
2016-10-25 12:14:27 +00:00
{
2022-02-10 15:37:27 +00:00
if ( ! config ( ) . has ( " table-structure " ) & & ! config ( ) . has ( " table-file " ) & & ! config ( ) . has ( " table-data-format " ) & & ( ! checkIfStdinIsRegularFile ( ) | | ! config ( ) . has ( " query " ) ) )
2022-01-25 07:55:09 +00:00
return { } ;
2021-07-11 23:17:14 +00:00
auto table_name = backQuoteIfNeed ( config ( ) . getString ( " table-name " , " table " ) ) ;
2021-12-15 11:30:57 +00:00
auto table_structure = config ( ) . getString ( " table-structure " , " auto " ) ;
2017-04-01 07:20:54 +00:00
2021-07-11 23:17:14 +00:00
String table_file ;
2022-01-20 12:55:28 +00:00
String format_from_file_name ;
2021-07-11 23:17:14 +00:00
if ( ! config ( ) . has ( " table-file " ) | | config ( ) . getString ( " table-file " ) = = " - " )
{
/// Use Unix tools stdin naming convention
table_file = " stdin " ;
2022-01-24 19:06:43 +00:00
format_from_file_name = FormatFactory : : instance ( ) . getFormatFromFileDescriptor ( STDIN_FILENO ) ;
2016-10-31 14:31:26 +00:00
}
2021-07-11 23:17:14 +00:00
else
{
/// Use regular file
2022-01-20 12:55:28 +00:00
auto file_name = config ( ) . getString ( " table-file " ) ;
table_file = quoteString ( file_name ) ;
format_from_file_name = FormatFactory : : instance ( ) . getFormatFromFileName ( file_name , false ) ;
2021-07-11 23:17:14 +00:00
}
2022-02-06 04:17:03 +00:00
auto data_format = backQuoteIfNeed (
config ( ) . getString ( " table-data-format " , config ( ) . getString ( " format " , format_from_file_name . empty ( ) ? " TSV " : format_from_file_name ) ) ) ;
2022-01-20 12:55:28 +00:00
2021-12-15 11:30:57 +00:00
if ( table_structure = = " auto " )
table_structure = " " ;
else
table_structure = " ( " + table_structure + " ) " ;
return fmt : : format ( " CREATE TABLE {} {} ENGINE = File({}, {}); " ,
2021-07-11 23:17:14 +00:00
table_name , table_structure , data_format , table_file ) ;
}
static ConfigurationPtr getConfigurationFromXMLString ( const char * xml_data )
{
std : : stringstream ss { std : : string { xml_data } } ; // STYLE_CHECK_ALLOW_STD_STRING_STREAM
Poco : : XML : : InputSource input_source { ss } ;
return { new Poco : : Util : : XMLConfiguration { & input_source } } ;
}
void LocalServer : : setupUsers ( )
{
static const char * minimal_default_user_xml =
2021-10-25 18:15:41 +00:00
" <clickhouse> "
2021-07-11 23:17:14 +00:00
" <profiles> "
" <default></default> "
" </profiles> "
" <users> "
" <default> "
" <password></password> "
" <networks> "
" <ip>::/0</ip> "
" </networks> "
" <profile>default</profile> "
" <quota>default</quota> "
" </default> "
" </users> "
" <quotas> "
" <default></default> "
" </quotas> "
2021-10-25 18:15:41 +00:00
" </clickhouse> " ;
2021-07-11 23:17:14 +00:00
ConfigurationPtr users_config ;
2022-03-10 04:35:01 +00:00
auto & access_control = global_context - > getAccessControl ( ) ;
2022-03-14 14:32:58 +00:00
access_control . setNoPasswordAllowed ( config ( ) . getBool ( " allow_no_password " , true ) ) ;
access_control . setPlaintextPasswordAllowed ( config ( ) . getBool ( " allow_plaintext_password " , true ) ) ;
2022-07-22 02:46:36 +00:00
if ( config ( ) . has ( " config-file " ) | | fs : : exists ( " config.xml " ) )
2020-10-14 08:50:36 +00:00
{
2022-08-01 14:03:36 +00:00
String config_path = config ( ) . getString ( " config-file " , " " ) ;
2022-07-20 04:38:36 +00:00
bool has_user_directories = config ( ) . has ( " user_directories " ) ;
2022-08-01 14:03:36 +00:00
const auto config_dir = fs : : path { config_path } . remove_filename ( ) . string ( ) ;
String users_config_path = config ( ) . getString ( " users_config " , " " ) ;
if ( users_config_path . empty ( ) & & has_user_directories )
{
users_config_path = config ( ) . getString ( " user_directories.users_xml.path " ) ;
2022-08-01 14:05:50 +00:00
if ( fs : : path ( users_config_path ) . is_relative ( ) & & fs : : exists ( fs : : path ( config_dir ) / users_config_path ) )
users_config_path = fs : : path ( config_dir ) / users_config_path ;
2022-08-01 14:03:36 +00:00
}
if ( users_config_path . empty ( ) )
2022-07-22 02:46:36 +00:00
users_config = getConfigurationFromXMLString ( minimal_default_user_xml ) ;
else
2022-07-20 04:38:36 +00:00
{
2022-07-22 02:46:36 +00:00
ConfigProcessor config_processor ( users_config_path ) ;
const auto loaded_config = config_processor . loadConfig ( ) ;
users_config = loaded_config . configuration ;
2022-07-20 04:38:36 +00:00
}
2021-07-11 23:17:14 +00:00
}
else
users_config = getConfigurationFromXMLString ( minimal_default_user_xml ) ;
if ( users_config )
global_context - > setUsersConfig ( users_config ) ;
else
2023-01-23 21:13:58 +00:00
throw Exception ( ErrorCodes : : CANNOT_LOAD_CONFIG , " Can't load config for users " ) ;
2021-07-11 23:17:14 +00:00
}
2017-04-01 07:20:54 +00:00
2021-08-23 08:50:12 +00:00
void LocalServer : : connect ( )
{
connection_parameters = ConnectionParameters ( config ( ) ) ;
2022-03-05 06:22:56 +00:00
connection = LocalConnection : : createConnection (
connection_parameters , global_context , need_render_progress , need_render_profile_events , server_display_name ) ;
2021-08-23 08:50:12 +00:00
}
2017-04-01 07:20:54 +00:00
2021-09-04 18:19:01 +00:00
int LocalServer : : main ( const std : : vector < std : : string > & /*args*/ )
2021-07-31 12:34:29 +00:00
try
2016-10-25 12:14:27 +00:00
{
2021-09-04 18:19:01 +00:00
UseSSL use_ssl ;
2022-09-05 21:10:03 +00:00
thread_status . emplace ( ) ;
2022-07-29 23:50:45 +00:00
StackTrace : : setShowAddresses ( config ( ) . getBool ( " show_addresses_in_stack_traces " , true ) ) ;
2021-10-02 08:10:34 +00:00
setupSignalHandler ( ) ;
2021-07-31 12:34:29 +00:00
2021-12-06 18:27:06 +00:00
std : : cout < < std : : fixed < < std : : setprecision ( 3 ) ;
std : : cerr < < std : : fixed < < std : : setprecision ( 3 ) ;
2023-02-25 02:20:47 +00:00
/// Try to increase limit on number of open files.
{
rlimit rlim ;
if ( getrlimit ( RLIMIT_NOFILE , & rlim ) )
throw Poco : : Exception ( " Cannot getrlimit " ) ;
if ( rlim . rlim_cur < rlim . rlim_max )
{
rlim . rlim_cur = config ( ) . getUInt ( " max_open_files " , static_cast < unsigned > ( rlim . rlim_max ) ) ;
int rc = setrlimit ( RLIMIT_NOFILE , & rlim ) ;
if ( rc ! = 0 )
std : : cerr < < fmt : : format ( " Cannot set max number of file descriptors to {}. Try to specify max_open_files according to your system limits. error: {} " , rlim . rlim_cur , errnoToString ( ) ) < < ' \n ' ;
}
}
2021-12-06 18:27:06 +00:00
# if defined(FUZZING_MODE)
2021-10-07 18:01:36 +00:00
static bool first_time = true ;
if ( first_time )
{
2021-09-04 18:19:01 +00:00
2021-12-06 18:27:06 +00:00
if ( queries_files . empty ( ) & & ! config ( ) . has ( " query " ) )
{
std : : cerr < < " \033 [31m " < < " ClickHouse compiled in fuzzing mode. " < < " \033 [0m " < < std : : endl ;
std : : cerr < < " \033 [31m " < < " You have to provide a query with --query or --queries-file option. " < < " \033 [0m " < < std : : endl ;
std : : cerr < < " \033 [31m " < < " The query have to use function getFuzzerData() inside. " < < " \033 [0m " < < std : : endl ;
exit ( 1 ) ;
}
is_interactive = false ;
# else
2021-10-29 12:04:08 +00:00
is_interactive = stdin_is_a_tty
& & ( config ( ) . hasOption ( " interactive " )
2021-12-15 11:30:57 +00:00
| | ( ! config ( ) . has ( " query " ) & & ! config ( ) . has ( " table-structure " ) & & queries_files . empty ( ) & & ! config ( ) . has ( " table-file " ) ) ) ;
2021-12-06 18:27:06 +00:00
# endif
2021-10-01 13:47:39 +00:00
if ( ! is_interactive )
2021-09-29 19:17:26 +00:00
{
/// We will terminate process on error
static KillingErrorHandler error_handler ;
Poco : : ErrorHandler : : set ( & error_handler ) ;
}
2021-07-31 12:34:29 +00:00
/// Don't initialize DateLUT
2017-04-21 17:47:27 +00:00
registerFunctions ( ) ;
2017-05-05 20:39:25 +00:00
registerAggregateFunctions ( ) ;
2017-06-10 09:04:31 +00:00
registerTableFunctions ( ) ;
2017-12-30 00:36:06 +00:00
registerStorages ( ) ;
2018-11-28 11:37:12 +00:00
registerDictionaries ( ) ;
2022-11-19 08:09:24 +00:00
registerDisks ( /* global_skip_access_check= */ true ) ;
2020-10-29 03:39:43 +00:00
registerFormats ( ) ;
2017-04-21 17:47:27 +00:00
2021-07-31 12:34:29 +00:00
processConfig ( ) ;
2022-11-12 02:55:26 +00:00
initTtyBuffer ( toProgressOption ( config ( ) . getString ( " progress " , " default " ) ) ) ;
2021-08-19 11:07:47 +00:00
applyCmdSettings ( global_context ) ;
2021-08-17 19:59:51 +00:00
2021-07-31 12:34:29 +00:00
if ( is_interactive )
{
2021-09-04 18:19:01 +00:00
clearTerminal ( ) ;
showClientVersion ( ) ;
std : : cerr < < std : : endl ;
2021-11-14 07:19:59 +00:00
}
2021-08-23 08:50:12 +00:00
connect ( ) ;
2021-09-04 18:19:01 +00:00
2021-12-06 14:30:49 +00:00
# ifdef FUZZING_MODE
first_time = false ;
2021-12-06 18:27:06 +00:00
}
2021-12-06 14:30:49 +00:00
# endif
2021-12-10 18:46:26 +00:00
String initial_query = getInitialCreateTableQuery ( ) ;
if ( ! initial_query . empty ( ) )
processQueryText ( initial_query ) ;
2021-10-29 12:04:08 +00:00
if ( is_interactive & & ! delayed_interactive )
2021-07-31 12:34:29 +00:00
{
2021-08-18 21:01:17 +00:00
runInteractive ( ) ;
2021-07-31 12:34:29 +00:00
}
else
{
runNonInteractive ( ) ;
2021-10-29 12:04:08 +00:00
if ( delayed_interactive )
runInteractive ( ) ;
2021-07-31 12:34:29 +00:00
}
2021-10-07 18:01:36 +00:00
# ifndef FUZZING_MODE
2021-07-31 12:34:29 +00:00
cleanup ( ) ;
2021-10-07 18:01:36 +00:00
# endif
2021-07-31 12:34:29 +00:00
return Application : : EXIT_OK ;
}
2021-10-16 11:28:57 +00:00
catch ( const DB : : Exception & e )
2021-07-31 12:34:29 +00:00
{
2021-10-16 11:28:57 +00:00
cleanup ( ) ;
2021-07-23 20:54:49 +00:00
2021-10-25 08:00:55 +00:00
bool need_print_stack_trace = config ( ) . getBool ( " stacktrace " , false ) ;
std : : cerr < < getExceptionMessage ( e , need_print_stack_trace , true ) < < std : : endl ;
2021-10-16 11:28:57 +00:00
return e . code ( ) ? e . code ( ) : - 1 ;
}
catch ( . . . )
{
cleanup ( ) ;
2021-07-30 07:46:22 +00:00
2021-10-16 11:28:57 +00:00
std : : cerr < < getCurrentExceptionMessage ( false ) < < std : : endl ;
return getCurrentExceptionCode ( ) ;
2021-07-23 20:54:49 +00:00
}
2022-04-05 13:38:44 +00:00
void LocalServer : : updateLoggerLevel ( const String & logs_level )
2022-04-05 12:46:18 +00:00
{
2022-04-05 13:38:44 +00:00
if ( ! logging_initialized )
return ;
2022-04-05 12:46:18 +00:00
config ( ) . setString ( " logger.level " , logs_level ) ;
updateLevels ( config ( ) , logger ( ) ) ;
}
2021-07-23 20:54:49 +00:00
void LocalServer : : processConfig ( )
{
2023-05-28 22:25:40 +00:00
if ( config ( ) . has ( " query " ) & & config ( ) . has ( " queries-file " ) )
throw Exception ( ErrorCodes : : BAD_ARGUMENTS , " Options '--query' and '--queries-file' cannot be specified at the same time " ) ;
2021-10-29 12:04:08 +00:00
delayed_interactive = config ( ) . has ( " interactive " ) & & ( config ( ) . has ( " query " ) | | config ( ) . has ( " queries-file " ) ) ;
if ( is_interactive & & ! delayed_interactive )
2021-07-23 20:54:49 +00:00
{
2021-07-29 12:48:07 +00:00
if ( config ( ) . has ( " multiquery " ) )
is_multiquery = true ;
2021-07-23 20:54:49 +00:00
}
else
{
2021-07-29 09:45:09 +00:00
echo_queries = config ( ) . hasOption ( " echo " ) | | config ( ) . hasOption ( " verbose " ) ;
2021-07-23 20:54:49 +00:00
ignore_error = config ( ) . getBool ( " ignore-error " , false ) ;
2021-07-29 12:48:07 +00:00
is_multiquery = true ;
2021-07-23 20:54:49 +00:00
}
2022-02-12 19:26:01 +00:00
2021-10-16 11:28:57 +00:00
print_stack_trace = config ( ) . getBool ( " stacktrace " , false ) ;
2022-02-12 19:26:01 +00:00
load_suggestions = ( is_interactive | | delayed_interactive ) & & ! config ( ) . getBool ( " disable_suggestion " , false ) ;
2021-07-23 20:54:49 +00:00
2021-10-30 12:28:50 +00:00
auto logging = ( config ( ) . has ( " logger.console " )
| | config ( ) . has ( " logger.level " )
| | config ( ) . has ( " log-level " )
2022-03-29 11:33:17 +00:00
| | config ( ) . has ( " send_logs_level " )
2021-10-30 12:28:50 +00:00
| | config ( ) . has ( " logger.log " ) ) ;
2022-04-05 12:46:18 +00:00
auto level = config ( ) . getString ( " log-level " , " trace " ) ;
2021-10-30 12:28:50 +00:00
2022-03-29 11:33:17 +00:00
if ( config ( ) . has ( " server_logs_file " ) )
2021-10-30 12:28:50 +00:00
{
2022-04-05 12:46:18 +00:00
auto poco_logs_level = Poco : : Logger : : parseLevel ( level ) ;
Poco : : Logger : : root ( ) . setLevel ( poco_logs_level ) ;
2021-10-30 12:28:50 +00:00
Poco : : Logger : : root ( ) . setChannel ( Poco : : AutoPtr < Poco : : SimpleFileChannel > ( new Poco : : SimpleFileChannel ( server_logs_file ) ) ) ;
2022-04-05 13:38:44 +00:00
logging_initialized = true ;
2021-10-30 12:28:50 +00:00
}
2022-04-05 12:46:18 +00:00
else if ( logging | | is_interactive )
2021-10-30 12:28:50 +00:00
{
config ( ) . setString ( " logger " , " logger " ) ;
2022-04-05 12:46:18 +00:00
auto log_level_default = is_interactive & & ! logging ? " none " : level ;
config ( ) . setString ( " logger.level " , config ( ) . getString ( " log-level " , config ( ) . getString ( " send_logs_level " , log_level_default ) ) ) ;
2021-10-30 12:28:50 +00:00
buildLoggers ( config ( ) , logger ( ) , " clickhouse-local " ) ;
2022-04-05 13:38:44 +00:00
logging_initialized = true ;
2021-10-30 12:28:50 +00:00
}
else
{
Poco : : Logger : : root ( ) . setLevel ( " none " ) ;
Poco : : Logger : : root ( ) . setChannel ( Poco : : AutoPtr < Poco : : NullChannel > ( new Poco : : NullChannel ( ) ) ) ;
2022-04-05 13:38:44 +00:00
logging_initialized = false ;
2021-10-30 12:28:50 +00:00
}
2021-07-23 20:54:49 +00:00
shared_context = Context : : createShared ( ) ;
global_context = Context : : createGlobal ( shared_context . get ( ) ) ;
global_context - > makeGlobalContext ( ) ;
global_context - > setApplicationType ( Context : : ApplicationType : : LOCAL ) ;
tryInitPath ( ) ;
Poco : : Logger * log = & logger ( ) ;
2016-10-25 12:14:27 +00:00
/// Maybe useless
if ( config ( ) . has ( " macros " ) )
2020-10-22 07:37:03 +00:00
global_context - > setMacros ( std : : make_unique < Macros > ( config ( ) , " macros " , log ) ) ;
2017-04-01 07:20:54 +00:00
2021-08-20 08:38:50 +00:00
format = config ( ) . getString ( " output-format " , config ( ) . getString ( " format " , is_interactive ? " PrettyCompact " : " TSV " ) ) ;
2021-08-18 14:39:04 +00:00
insert_format = " Values " ;
2021-10-16 10:17:00 +00:00
2021-08-18 14:39:04 +00:00
/// Setting value from cmd arg overrides one from config
if ( global_context - > getSettingsRef ( ) . max_insert_block_size . changed )
2022-10-07 10:46:45 +00:00
{
2021-08-18 14:39:04 +00:00
insert_format_max_block_size = global_context - > getSettingsRef ( ) . max_insert_block_size ;
2022-10-07 10:46:45 +00:00
}
2021-08-18 14:39:04 +00:00
else
2022-10-07 10:46:45 +00:00
{
insert_format_max_block_size = config ( ) . getUInt64 ( " insert_format_max_block_size " ,
global_context - > getSettingsRef ( ) . max_insert_block_size ) ;
}
2021-08-18 14:39:04 +00:00
2021-03-11 20:41:10 +00:00
/// Sets external authenticators config (LDAP, Kerberos).
2020-10-22 07:37:03 +00:00
global_context - > setExternalAuthenticatorsConfig ( config ( ) ) ;
2020-06-10 22:48:15 +00:00
2016-10-25 12:14:27 +00:00
setupUsers ( ) ;
2017-04-01 07:20:54 +00:00
2016-11-11 17:01:02 +00:00
/// Limit on total number of concurrently executing queries.
2020-03-28 03:02:26 +00:00
/// There is no need for concurrent queries, override max_concurrent_queries.
2020-10-22 07:37:03 +00:00
global_context - > getProcessList ( ) . setMaxSize ( 0 ) ;
2017-04-01 07:20:54 +00:00
2016-10-25 12:14:27 +00:00
/// Size of cache for uncompressed blocks. Zero means disabled.
2022-04-28 05:56:26 +00:00
String uncompressed_cache_policy = config ( ) . getString ( " uncompressed_cache_policy " , " " ) ;
2017-04-12 16:37:19 +00:00
size_t uncompressed_cache_size = config ( ) . getUInt64 ( " uncompressed_cache_size " , 0 ) ;
2016-10-25 12:14:27 +00:00
if ( uncompressed_cache_size )
2023-03-13 09:06:58 +00:00
global_context - > setUncompressedCache ( uncompressed_cache_policy , uncompressed_cache_size ) ;
2017-04-01 07:20:54 +00:00
2022-05-18 13:23:58 +00:00
/// Size of cache for marks (index of MergeTree family of tables).
2022-06-14 07:08:40 +00:00
String mark_cache_policy = config ( ) . getString ( " mark_cache_policy " , " " ) ;
2017-04-12 16:37:19 +00:00
size_t mark_cache_size = config ( ) . getUInt64 ( " mark_cache_size " , 5368709120 ) ;
2016-10-25 12:14:27 +00:00
if ( mark_cache_size )
2023-03-13 09:06:58 +00:00
global_context - > setMarkCache ( mark_cache_policy , mark_cache_size ) ;
2017-04-01 07:20:54 +00:00
2021-08-21 17:27:22 +00:00
/// Size of cache for uncompressed blocks of MergeTree indices. Zero means disabled.
size_t index_uncompressed_cache_size = config ( ) . getUInt64 ( " index_uncompressed_cache_size " , 0 ) ;
if ( index_uncompressed_cache_size )
global_context - > setIndexUncompressedCache ( index_uncompressed_cache_size ) ;
2022-05-18 13:23:58 +00:00
/// Size of cache for index marks (index of MergeTree skip indices).
2021-08-21 17:27:22 +00:00
size_t index_mark_cache_size = config ( ) . getUInt64 ( " index_mark_cache_size " , 0 ) ;
if ( index_mark_cache_size )
global_context - > setIndexMarkCache ( index_mark_cache_size ) ;
2021-03-28 01:10:30 +00:00
/// A cache for mmapped files.
size_t mmap_cache_size = config ( ) . getUInt64 ( " mmap_cache_size " , 1000 ) ; /// The choice of default is arbitrary.
if ( mmap_cache_size )
2021-03-28 19:24:28 +00:00
global_context - > setMMappedFileCache ( mmap_cache_size ) ;
2021-03-28 01:10:30 +00:00
2022-10-19 10:27:00 +00:00
# if USE_EMBEDDED_COMPILER
/// 128 MB
constexpr size_t compiled_expression_cache_size_default = 1024 * 1024 * 128 ;
size_t compiled_expression_cache_size = config ( ) . getUInt64 ( " compiled_expression_cache_size " , compiled_expression_cache_size_default ) ;
constexpr size_t compiled_expression_cache_elements_size_default = 10000 ;
2022-10-19 10:38:20 +00:00
size_t compiled_expression_cache_elements_size
= config ( ) . getUInt64 ( " compiled_expression_cache_elements_size " , compiled_expression_cache_elements_size_default ) ;
2022-10-19 10:27:00 +00:00
CompiledExpressionCacheFactory : : instance ( ) . init ( compiled_expression_cache_size , compiled_expression_cache_elements_size ) ;
# endif
2021-03-28 01:10:30 +00:00
2018-02-01 13:52:29 +00:00
/// Load global settings from default_profile and system_profile.
2020-10-22 07:37:03 +00:00
global_context - > setDefaultProfiles ( config ( ) ) ;
2017-04-01 07:20:54 +00:00
2021-08-26 11:01:15 +00:00
/// We load temporary database first, because projections need it.
DatabaseCatalog : : instance ( ) . initializeAndLoadTemporaryDatabase ( ) ;
2016-12-13 18:51:19 +00:00
/** Init dummy default DB
2020-01-11 09:50:41 +00:00
* NOTE : We force using isolated default database to avoid conflicts with default database from server environment
2016-12-13 18:51:19 +00:00
* Otherwise , metadata of temporary File ( format , EXPLICIT_PATH ) tables will pollute metadata / directory ;
2018-01-15 14:58:21 +00:00
* if such tables will not be dropped , clickhouse - server will not be able to load them due to security reasons .
2016-12-13 18:51:19 +00:00
*/
2022-08-01 14:03:36 +00:00
std : : string default_database = config ( ) . getString ( " default_database " , " _local " ) ;
2023-04-27 18:26:36 +00:00
DatabaseCatalog : : instance ( ) . attachDatabase ( default_database , createClickHouseLocalDatabaseOverlay ( default_database , global_context ) ) ;
2020-10-22 07:37:03 +00:00
global_context - > setCurrentDatabase ( default_database ) ;
2021-04-10 23:33:54 +00:00
applyCmdOptions ( global_context ) ;
2017-04-01 07:20:54 +00:00
2021-01-16 15:08:21 +00:00
if ( config ( ) . has ( " path " ) )
2016-12-13 18:51:19 +00:00
{
2021-01-16 15:08:21 +00:00
String path = global_context - > getPath ( ) ;
2018-04-20 15:32:40 +00:00
/// Lock path directory before read
2021-07-23 20:54:49 +00:00
status . emplace ( fs : : path ( path ) / " status " , StatusFile : : write_full_info ) ;
2018-04-20 15:32:40 +00:00
2020-08-13 19:41:06 +00:00
LOG_DEBUG ( log , " Loading metadata from {} " , path ) ;
2021-04-10 23:33:54 +00:00
loadMetadataSystem ( global_context ) ;
2021-11-10 13:13:27 +00:00
attachSystemTablesLocal ( global_context , * createMemoryDatabaseIfNotExists ( global_context , DatabaseCatalog : : SYSTEM_DATABASE ) ) ;
2021-09-09 09:37:51 +00:00
attachInformationSchema ( global_context , * createMemoryDatabaseIfNotExists ( global_context , DatabaseCatalog : : INFORMATION_SCHEMA ) ) ;
attachInformationSchema ( global_context , * createMemoryDatabaseIfNotExists ( global_context , DatabaseCatalog : : INFORMATION_SCHEMA_UPPERCASE ) ) ;
2021-09-01 19:42:49 +00:00
startupSystemTables ( ) ;
2022-09-19 14:10:00 +00:00
if ( ! config ( ) . has ( " only-system-tables " ) )
{
2023-02-17 16:57:49 +00:00
DatabaseCatalog : : instance ( ) . createBackgroundTasks ( ) ;
2022-09-19 14:10:00 +00:00
loadMetadata ( global_context ) ;
2023-02-17 16:57:49 +00:00
DatabaseCatalog : : instance ( ) . startupBackgroundCleanup ( ) ;
2022-09-19 14:10:00 +00:00
}
2021-07-23 20:54:49 +00:00
2022-09-24 21:24:39 +00:00
/// For ClickHouse local if path is not set the loader will be disabled.
global_context - > getUserDefinedSQLObjectsLoader ( ) . loadObjects ( ) ;
2020-05-23 22:24:01 +00:00
LOG_DEBUG ( log , " Loaded metadata. " ) ;
2016-12-13 18:51:19 +00:00
}
2021-01-10 11:12:02 +00:00
else if ( ! config ( ) . has ( " no-system-tables " ) )
2017-06-15 20:08:26 +00:00
{
2021-11-10 13:13:27 +00:00
attachSystemTablesLocal ( global_context , * createMemoryDatabaseIfNotExists ( global_context , DatabaseCatalog : : SYSTEM_DATABASE ) ) ;
2021-09-09 09:37:51 +00:00
attachInformationSchema ( global_context , * createMemoryDatabaseIfNotExists ( global_context , DatabaseCatalog : : INFORMATION_SCHEMA ) ) ;
attachInformationSchema ( global_context , * createMemoryDatabaseIfNotExists ( global_context , DatabaseCatalog : : INFORMATION_SCHEMA_UPPERCASE ) ) ;
2017-06-15 20:08:26 +00:00
}
2021-09-30 13:51:15 +00:00
2021-07-23 20:54:49 +00:00
server_display_name = config ( ) . getString ( " display_name " , getFQDNOrHostName ( ) ) ;
2021-07-28 12:56:11 +00:00
prompt_by_server_display_name = config ( ) . getRawString ( " prompt_by_server_display_name.default " , " {display_name} :) " ) ;
std : : map < String , String > prompt_substitutions { { " display_name " , server_display_name } } ;
for ( const auto & [ key , value ] : prompt_substitutions )
boost : : replace_all ( prompt_by_server_display_name , " { " + key + " } " , value ) ;
2016-10-25 12:14:27 +00:00
2021-08-17 19:59:51 +00:00
ClientInfo & client_info = global_context - > getClientInfo ( ) ;
client_info . setInitialQuery ( ) ;
2022-05-17 11:48:06 +00:00
client_info . query_kind = query_kind ;
2017-10-13 19:13:41 +00:00
}
2021-12-06 18:27:06 +00:00
[[ maybe_unused ]] static std : : string getHelpHeader ( )
2018-04-20 19:31:19 +00:00
{
return
" usage: clickhouse-local [initial table definition] [--query <query>] \n "
" clickhouse-local allows to execute SQL queries on your data files via single command line call. "
" To do so, initially you need to define your data source and its format. "
" After you can execute your SQL queries in usual manner. \n "
" There are two ways to define initial table keeping your data. "
" Either just in first query like this: \n "
" CREATE TABLE <table> (<structure>) ENGINE = File(<input-format>, <file>); \n "
" Either through corresponding command line parameters --table --structure --input-format and --file. " ;
}
2021-07-11 23:17:14 +00:00
2021-12-06 18:27:06 +00:00
[[ maybe_unused ]] static std : : string getHelpFooter ( )
2018-04-20 19:31:19 +00:00
{
return
" Example printing memory used by each Unix user: \n "
" ps aux | tail -n +2 | awk '{ printf( \" %s \\ t%s \\ n \" , $1, $4) }' | "
" clickhouse-local -S \" user String, mem Float64 \" -q "
" \" SELECT user, round(sum(mem), 2) as mem_total FROM table GROUP BY user ORDER "
" BY mem_total DESC FORMAT PrettyCompact \" " ;
}
2021-07-11 23:17:14 +00:00
2021-12-06 18:27:06 +00:00
void LocalServer : : printHelpMessage ( [[maybe_unused]] const OptionsDescription & options_description )
2018-04-20 19:31:19 +00:00
{
2021-12-06 18:27:06 +00:00
# if defined(FUZZING_MODE)
std : : cout < <
2021-12-06 21:34:52 +00:00
" usage: clickhouse <clickhouse-local arguments> -- <libfuzzer arguments> \n "
" Note: It is important not to use only one letter keys with single dash for \n "
" for clickhouse-local arguments. It may work incorrectly. \n "
2021-12-06 18:27:06 +00:00
" ClickHouse is build with coverage guided fuzzer (libfuzzer) inside it. \n "
" You have to provide a query which contains getFuzzerData function. \n "
" This will take the data from fuzzing engine, pass it to getFuzzerData function and execute a query. \n "
" Each time the data will be different, and it will last until some segfault or sanitizer assertion is found. \n " ;
# else
2021-07-11 11:36:27 +00:00
std : : cout < < getHelpHeader ( ) < < " \n " ;
std : : cout < < options_description . main_description . value ( ) < < " \n " ;
std : : cout < < getHelpFooter ( ) < < " \n " ;
2021-12-06 18:27:06 +00:00
# endif
2021-07-11 11:36:27 +00:00
}
2018-05-23 16:12:46 +00:00
2018-04-20 19:31:19 +00:00
2021-10-14 13:34:05 +00:00
void LocalServer : : addOptions ( OptionsDescription & options_description )
2021-07-11 11:36:27 +00:00
{
options_description . main_description - > add_options ( )
2018-04-20 19:31:19 +00:00
( " table,N " , po : : value < std : : string > ( ) , " name of the initial table " )
2021-08-20 21:19:06 +00:00
2018-04-20 19:31:19 +00:00
/// If structure argument is omitted then initial query is not generated
( " structure,S " , po : : value < std : : string > ( ) , " structure of the initial table (list of column and type names) " )
( " file,f " , po : : value < std : : string > ( ) , " path to file with data of the initial table (stdin if not specified) " )
2021-08-20 21:19:06 +00:00
2018-04-20 19:31:19 +00:00
( " input-format " , po : : value < std : : string > ( ) , " input format of the initial table data " )
( " output-format " , po : : value < std : : string > ( ) , " default output format " )
2020-06-28 23:40:43 +00:00
( " logger.console " , po : : value < bool > ( ) - > implicit_value ( true ) , " Log to console " )
2019-06-14 14:00:37 +00:00
( " logger.log " , po : : value < std : : string > ( ) , " Log file name " )
( " logger.level " , po : : value < std : : string > ( ) , " Log level " )
2021-07-29 12:48:07 +00:00
2021-01-10 11:12:02 +00:00
( " no-system-tables " , " do not attach system tables (better startup time) " )
2021-10-15 15:29:27 +00:00
( " path " , po : : value < std : : string > ( ) , " Storage path " )
2022-09-19 14:10:00 +00:00
( " only-system-tables " , " attach only system tables from specified path " )
2021-10-25 18:12:45 +00:00
( " top_level_domains_path " , po : : value < std : : string > ( ) , " Path to lists with custom TLDs " )
2019-04-25 14:08:20 +00:00
;
2021-07-11 11:36:27 +00:00
}
2018-04-20 19:31:19 +00:00
2021-07-11 23:17:14 +00:00
void LocalServer : : applyCmdSettings ( ContextMutablePtr context )
{
context - > applySettingsChanges ( cmd_settings . changes ( ) ) ;
}
2018-04-20 19:31:19 +00:00
2021-07-11 23:17:14 +00:00
void LocalServer : : applyCmdOptions ( ContextMutablePtr context )
{
2021-07-29 09:45:09 +00:00
context - > setDefaultFormat ( config ( ) . getString ( " output-format " , config ( ) . getString ( " format " , is_interactive ? " PrettyCompact " : " TSV " ) ) ) ;
2021-07-11 23:17:14 +00:00
applyCmdSettings ( context ) ;
}
2018-04-20 19:31:19 +00:00
2021-07-11 23:17:14 +00:00
2022-02-10 09:43:08 +00:00
void LocalServer : : processOptions ( const OptionsDescription & , const CommandLineOptions & options , const std : : vector < Arguments > & , const std : : vector < Arguments > & )
2021-07-11 11:36:27 +00:00
{
2018-04-20 19:31:19 +00:00
if ( options . count ( " table " ) )
config ( ) . setString ( " table-name " , options [ " table " ] . as < std : : string > ( ) ) ;
if ( options . count ( " file " ) )
config ( ) . setString ( " table-file " , options [ " file " ] . as < std : : string > ( ) ) ;
if ( options . count ( " structure " ) )
config ( ) . setString ( " table-structure " , options [ " structure " ] . as < std : : string > ( ) ) ;
2021-08-20 21:19:06 +00:00
if ( options . count ( " no-system-tables " ) )
config ( ) . setBool ( " no-system-tables " , true ) ;
2022-09-19 14:10:00 +00:00
if ( options . count ( " only-system-tables " ) )
config ( ) . setBool ( " only-system-tables " , true ) ;
2021-08-20 21:19:06 +00:00
2018-04-20 19:31:19 +00:00
if ( options . count ( " input-format " ) )
config ( ) . setString ( " table-data-format " , options [ " input-format " ] . as < std : : string > ( ) ) ;
if ( options . count ( " output-format " ) )
config ( ) . setString ( " output-format " , options [ " output-format " ] . as < std : : string > ( ) ) ;
2020-06-28 23:40:43 +00:00
if ( options . count ( " logger.console " ) )
config ( ) . setBool ( " logger.console " , options [ " logger.console " ] . as < bool > ( ) ) ;
2019-06-14 14:00:37 +00:00
if ( options . count ( " logger.log " ) )
config ( ) . setString ( " logger.log " , options [ " logger.log " ] . as < std : : string > ( ) ) ;
if ( options . count ( " logger.level " ) )
config ( ) . setString ( " logger.level " , options [ " logger.level " ] . as < std : : string > ( ) ) ;
2022-03-29 11:33:17 +00:00
if ( options . count ( " send_logs_level " ) )
config ( ) . setString ( " send_logs_level " , options [ " send_logs_level " ] . as < std : : string > ( ) ) ;
2018-04-20 19:31:19 +00:00
}
2022-03-01 09:22:12 +00:00
void LocalServer : : readArguments ( int argc , char * * argv , Arguments & common_arguments , std : : vector < Arguments > & , std : : vector < Arguments > & )
{
for ( int arg_num = 1 ; arg_num < argc ; + + arg_num )
{
2023-05-17 03:43:35 +00:00
std : : string_view arg = argv [ arg_num ] ;
2023-05-23 00:27:17 +00:00
if ( arg = = " --multiquery " & & ( arg_num + 1 ) < argc & & ! std : : string_view ( argv [ arg_num + 1 ] ) . starts_with ( ' - ' ) )
2023-05-17 03:43:35 +00:00
{
2023-05-23 00:27:17 +00:00
/// Transform the abbreviated syntax '--multiquery <SQL>' into the full syntax '--multiquery -q <SQL>'
2023-05-17 03:43:35 +00:00
+ + arg_num ;
arg = argv [ arg_num ] ;
addMultiquery ( arg , common_arguments ) ;
}
else
common_arguments . emplace_back ( arg ) ;
2022-03-01 09:22:12 +00:00
}
}
2018-05-11 14:35:32 +00:00
}
2019-12-15 06:34:43 +00:00
# pragma GCC diagnostic ignored "-Wunused-function"
# pragma GCC diagnostic ignored "-Wmissing-declarations"
2017-12-02 02:47:12 +00:00
int mainEntryClickHouseLocal ( int argc , char * * argv )
{
try
{
2021-12-25 19:00:28 +00:00
DB : : LocalServer app ;
2017-12-02 02:47:12 +00:00
app . init ( argc , argv ) ;
return app . run ( ) ;
}
2021-10-14 13:34:05 +00:00
catch ( const DB : : Exception & e )
2021-10-12 14:08:47 +00:00
{
2021-10-14 13:34:05 +00:00
std : : cerr < < DB : : getExceptionMessage ( e , false ) < < std : : endl ;
auto code = DB : : getCurrentExceptionCode ( ) ;
return code ? code : 1 ;
2021-10-12 14:08:47 +00:00
}
2021-10-15 15:29:27 +00:00
catch ( const boost : : program_options : : error & e )
{
std : : cerr < < " Bad arguments: " < < e . what ( ) < < std : : endl ;
return DB : : ErrorCodes : : BAD_ARGUMENTS ;
}
2017-12-02 02:47:12 +00:00
catch ( . . . )
{
2018-08-23 00:14:26 +00:00
std : : cerr < < DB : : getCurrentExceptionMessage ( true ) < < ' \n ' ;
2017-12-02 02:47:12 +00:00
auto code = DB : : getCurrentExceptionCode ( ) ;
return code ? code : 1 ;
}
2021-10-07 18:01:36 +00:00
}
2021-12-06 18:27:06 +00:00
# if defined(FUZZING_MODE)
2021-10-07 18:01:36 +00:00
std : : optional < DB : : LocalServer > fuzz_app ;
extern " C " int LLVMFuzzerInitialize ( int * pargc , char * * * pargv )
{
int & argc = * pargc ;
char * * argv = * pargv ;
2021-12-06 21:34:52 +00:00
/// As a user you can add flags to clickhouse binary in fuzzing mode as follows
2021-12-07 10:31:48 +00:00
/// clickhouse <set of clickhouse-local specific flag> -- <set of libfuzzer flags>
2021-12-06 21:34:52 +00:00
/// Calculate the position of delimiter "--" that separates arguments
/// of clickhouse-local and libfuzzer
2021-10-07 18:01:36 +00:00
int pos_delim = argc ;
for ( int i = 0 ; i < argc ; + + i )
{
if ( strcmp ( argv [ i ] , " -- " ) = = 0 )
{
pos_delim = i ;
break ;
}
}
2021-12-06 21:34:52 +00:00
/// Initialize clickhouse-local app
2021-10-07 18:01:36 +00:00
fuzz_app . emplace ( ) ;
fuzz_app - > init ( pos_delim , argv ) ;
2021-12-06 21:34:52 +00:00
/// We will leave clickhouse-local specific arguments as is, because libfuzzer will ignore
/// all keys starting with --
2021-10-07 18:01:36 +00:00
return 0 ;
}
2021-12-06 18:27:06 +00:00
2021-10-07 18:01:36 +00:00
extern " C " int LLVMFuzzerTestOneInput ( const uint8_t * data , size_t size )
2021-12-06 21:34:52 +00:00
try
2021-10-07 18:01:36 +00:00
{
2021-12-06 21:34:52 +00:00
auto input = String ( reinterpret_cast < const char * > ( data ) , size ) ;
DB : : FunctionGetFuzzerData : : update ( input ) ;
fuzz_app - > run ( ) ;
return 0 ;
}
catch ( . . . )
{
return 1 ;
2021-10-07 18:01:36 +00:00
}
# endif