283 lines
9.2 KiB
Go
283 lines
9.2 KiB
Go
|
package clickhouse
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"net/url"
|
||
|
"strconv"
|
||
|
|
||
|
"github.com/kshvakov/clickhouse/lib/binary"
|
||
|
)
|
||
|
|
||
|
type querySettingType int
|
||
|
|
||
|
// all possible query setting's data type
|
||
|
const (
|
||
|
uintQS querySettingType = iota + 1
|
||
|
intQS
|
||
|
boolQS
|
||
|
timeQS
|
||
|
)
|
||
|
|
||
|
// description of single query setting
|
||
|
type querySettingInfo struct {
|
||
|
name string
|
||
|
qsType querySettingType
|
||
|
}
|
||
|
|
||
|
// all possible query settings
|
||
|
var querySettingList = []querySettingInfo{
|
||
|
{"min_compress_block_size", uintQS},
|
||
|
{"max_compress_block_size", uintQS},
|
||
|
{"max_block_size", uintQS},
|
||
|
{"max_insert_block_size", uintQS},
|
||
|
{"min_insert_block_size_rows", uintQS},
|
||
|
{"min_insert_block_size_bytes", uintQS},
|
||
|
{"max_read_buffer_size", uintQS},
|
||
|
{"max_distributed_connections", uintQS},
|
||
|
{"max_query_size", uintQS},
|
||
|
{"interactive_delay", uintQS},
|
||
|
{"poll_interval", uintQS},
|
||
|
{"distributed_connections_pool_size", uintQS},
|
||
|
{"connections_with_failover_max_tries", uintQS},
|
||
|
{"background_pool_size", uintQS},
|
||
|
{"background_schedule_pool_size", uintQS},
|
||
|
{"replication_alter_partitions_sync", uintQS},
|
||
|
{"replication_alter_columns_timeout", uintQS},
|
||
|
{"min_count_to_compile", uintQS},
|
||
|
{"min_count_to_compile_expression", uintQS},
|
||
|
{"group_by_two_level_threshold", uintQS},
|
||
|
{"group_by_two_level_threshold_bytes", uintQS},
|
||
|
{"aggregation_memory_efficient_merge_threads", uintQS},
|
||
|
{"max_parallel_replicas", uintQS},
|
||
|
{"parallel_replicas_count", uintQS},
|
||
|
{"parallel_replica_offset", uintQS},
|
||
|
{"merge_tree_min_rows_for_concurrent_read", uintQS},
|
||
|
{"merge_tree_min_bytes_for_concurrent_read", uintQS},
|
||
|
{"merge_tree_min_rows_for_seek", uintQS},
|
||
|
{"merge_tree_min_bytes_for_seek", uintQS},
|
||
|
{"merge_tree_coarse_index_granularity", uintQS},
|
||
|
{"merge_tree_max_rows_to_use_cache", uintQS},
|
||
|
{"merge_tree_max_bytes_to_use_cache", uintQS},
|
||
|
{"mysql_max_rows_to_insert", uintQS},
|
||
|
{"optimize_min_equality_disjunction_chain_length", uintQS},
|
||
|
{"min_bytes_to_use_direct_io", uintQS},
|
||
|
{"mark_cache_min_lifetime", uintQS},
|
||
|
{"priority", uintQS},
|
||
|
{"log_queries_cut_to_length", uintQS},
|
||
|
{"max_concurrent_queries_for_user", uintQS},
|
||
|
{"insert_quorum", uintQS},
|
||
|
{"select_sequential_consistency", uintQS},
|
||
|
{"table_function_remote_max_addresses", uintQS},
|
||
|
{"read_backoff_max_throughput", uintQS},
|
||
|
{"read_backoff_min_events", uintQS},
|
||
|
{"output_format_pretty_max_rows", uintQS},
|
||
|
{"output_format_pretty_max_column_pad_width", uintQS},
|
||
|
{"output_format_parquet_row_group_size", uintQS},
|
||
|
{"http_headers_progress_interval_ms", uintQS},
|
||
|
{"input_format_allow_errors_num", uintQS},
|
||
|
{"preferred_block_size_bytes", uintQS},
|
||
|
{"max_replica_delay_for_distributed_queries", uintQS},
|
||
|
{"preferred_max_column_in_block_size_bytes", uintQS},
|
||
|
{"insert_distributed_timeout", uintQS},
|
||
|
{"odbc_max_field_size", uintQS},
|
||
|
{"max_rows_to_read", uintQS},
|
||
|
{"max_bytes_to_read", uintQS},
|
||
|
{"max_rows_to_group_by", uintQS},
|
||
|
{"max_bytes_before_external_group_by", uintQS},
|
||
|
{"max_rows_to_sort", uintQS},
|
||
|
{"max_bytes_to_sort", uintQS},
|
||
|
{"max_bytes_before_external_sort", uintQS},
|
||
|
{"max_bytes_before_remerge_sort", uintQS},
|
||
|
{"max_result_rows", uintQS},
|
||
|
{"max_result_bytes", uintQS},
|
||
|
{"min_execution_speed", uintQS},
|
||
|
{"max_execution_speed", uintQS},
|
||
|
{"min_execution_speed_bytes", uintQS},
|
||
|
{"max_execution_speed_bytes", uintQS},
|
||
|
{"max_columns_to_read", uintQS},
|
||
|
{"max_temporary_columns", uintQS},
|
||
|
{"max_temporary_non_const_columns", uintQS},
|
||
|
{"max_subquery_depth", uintQS},
|
||
|
{"max_pipeline_depth", uintQS},
|
||
|
{"max_ast_depth", uintQS},
|
||
|
{"max_ast_elements", uintQS},
|
||
|
{"max_expanded_ast_elements", uintQS},
|
||
|
{"readonly", uintQS},
|
||
|
{"max_rows_in_set", uintQS},
|
||
|
{"max_bytes_in_set", uintQS},
|
||
|
{"max_rows_in_join", uintQS},
|
||
|
{"max_bytes_in_join", uintQS},
|
||
|
{"max_rows_to_transfer", uintQS},
|
||
|
{"max_bytes_to_transfer", uintQS},
|
||
|
{"max_rows_in_distinct", uintQS},
|
||
|
{"max_bytes_in_distinct", uintQS},
|
||
|
{"max_memory_usage", uintQS},
|
||
|
{"max_memory_usage_for_user", uintQS},
|
||
|
{"max_memory_usage_for_all_queries", uintQS},
|
||
|
{"max_network_bandwidth", uintQS},
|
||
|
{"max_network_bytes", uintQS},
|
||
|
{"max_network_bandwidth_for_user", uintQS},
|
||
|
{"max_network_bandwidth_for_all_users", uintQS},
|
||
|
{"low_cardinality_max_dictionary_size", uintQS},
|
||
|
{"max_fetch_partition_retries_count", uintQS},
|
||
|
{"http_max_multipart_form_data_size", uintQS},
|
||
|
{"max_partitions_per_insert_block", uintQS},
|
||
|
|
||
|
{"network_zstd_compression_level", intQS},
|
||
|
{"http_zlib_compression_level", intQS},
|
||
|
{"distributed_ddl_task_timeout", intQS},
|
||
|
|
||
|
{"extremes", boolQS},
|
||
|
{"use_uncompressed_cache", boolQS},
|
||
|
{"replace_running_query", boolQS},
|
||
|
{"distributed_directory_monitor_batch_inserts", boolQS},
|
||
|
{"optimize_move_to_prewhere", boolQS},
|
||
|
{"compile", boolQS},
|
||
|
{"allow_suspicious_low_cardinality_types", boolQS},
|
||
|
{"compile_expressions", boolQS},
|
||
|
{"distributed_aggregation_memory_efficient", boolQS},
|
||
|
{"skip_unavailable_shards", boolQS},
|
||
|
{"distributed_group_by_no_merge", boolQS},
|
||
|
{"optimize_skip_unused_shards", boolQS},
|
||
|
{"merge_tree_uniform_read_distribution", boolQS},
|
||
|
{"force_index_by_date", boolQS},
|
||
|
{"force_primary_key", boolQS},
|
||
|
{"log_queries", boolQS},
|
||
|
{"insert_deduplicate", boolQS},
|
||
|
{"enable_http_compression", boolQS},
|
||
|
{"http_native_compression_disable_checksumming_on_decompress", boolQS},
|
||
|
{"output_format_write_statistics", boolQS},
|
||
|
{"add_http_cors_header", boolQS},
|
||
|
{"input_format_skip_unknown_fields", boolQS},
|
||
|
{"input_format_with_names_use_header", boolQS},
|
||
|
{"input_format_import_nested_json", boolQS},
|
||
|
{"input_format_defaults_for_omitted_fields", boolQS},
|
||
|
{"input_format_values_interpret_expressions", boolQS},
|
||
|
{"output_format_json_quote_64bit_integers", boolQS},
|
||
|
{"output_format_json_quote_denormals", boolQS},
|
||
|
{"output_format_json_escape_forward_slashes", boolQS},
|
||
|
{"output_format_pretty_color", boolQS},
|
||
|
{"use_client_time_zone", boolQS},
|
||
|
{"send_progress_in_http_headers", boolQS},
|
||
|
{"fsync_metadata", boolQS},
|
||
|
{"join_use_nulls", boolQS},
|
||
|
{"fallback_to_stale_replicas_for_distributed_queries", boolQS},
|
||
|
{"insert_distributed_sync", boolQS},
|
||
|
{"insert_allow_materialized_columns", boolQS},
|
||
|
{"optimize_throw_if_noop", boolQS},
|
||
|
{"use_index_for_in_with_subqueries", boolQS},
|
||
|
{"empty_result_for_aggregation_by_empty_set", boolQS},
|
||
|
{"allow_distributed_ddl", boolQS},
|
||
|
{"join_any_take_last_row", boolQS},
|
||
|
{"format_csv_allow_single_quotes", boolQS},
|
||
|
{"format_csv_allow_double_quotes", boolQS},
|
||
|
{"log_profile_events", boolQS},
|
||
|
{"log_query_settings", boolQS},
|
||
|
{"log_query_threads", boolQS},
|
||
|
{"enable_optimize_predicate_expression", boolQS},
|
||
|
{"low_cardinality_use_single_dictionary_for_part", boolQS},
|
||
|
{"decimal_check_overflow", boolQS},
|
||
|
{"prefer_localhost_replica", boolQS},
|
||
|
{"asterisk_left_columns_only", boolQS},
|
||
|
{"calculate_text_stack_trace", boolQS},
|
||
|
{"allow_ddl", boolQS},
|
||
|
{"parallel_view_processing", boolQS},
|
||
|
{"enable_debug_queries", boolQS},
|
||
|
{"enable_unaligned_array_join", boolQS},
|
||
|
{"low_cardinality_allow_in_native_format", boolQS},
|
||
|
{"allow_experimental_multiple_joins_emulation", boolQS},
|
||
|
{"allow_experimental_cross_to_join_conversion", boolQS},
|
||
|
{"cancel_http_readonly_queries_on_client_close", boolQS},
|
||
|
{"external_table_functions_use_nulls", boolQS},
|
||
|
{"allow_experimental_data_skipping_indices", boolQS},
|
||
|
{"allow_hyperscan", boolQS},
|
||
|
{"allow_simdjson", boolQS},
|
||
|
|
||
|
{"connect_timeout", timeQS},
|
||
|
{"connect_timeout_with_failover_ms", timeQS},
|
||
|
{"receive_timeout", timeQS},
|
||
|
{"send_timeout", timeQS},
|
||
|
{"tcp_keep_alive_timeout", timeQS},
|
||
|
{"queue_max_wait_ms", timeQS},
|
||
|
{"distributed_directory_monitor_sleep_time_ms", timeQS},
|
||
|
{"insert_quorum_timeout", timeQS},
|
||
|
{"read_backoff_min_latency_ms", timeQS},
|
||
|
{"read_backoff_min_interval_between_events_ms", timeQS},
|
||
|
{"stream_flush_interval_ms", timeQS},
|
||
|
{"stream_poll_timeout_ms", timeQS},
|
||
|
{"http_connection_timeout", timeQS},
|
||
|
{"http_send_timeout", timeQS},
|
||
|
{"http_receive_timeout", timeQS},
|
||
|
{"max_execution_time", timeQS},
|
||
|
{"timeout_before_checking_execution_speed", timeQS},
|
||
|
}
|
||
|
|
||
|
type querySettingValueEncoder func(enc *binary.Encoder) error
|
||
|
|
||
|
type querySettings struct {
|
||
|
settings map[string]querySettingValueEncoder
|
||
|
settingsStr string // used for debug output
|
||
|
}
|
||
|
|
||
|
func makeQuerySettings(query url.Values) (*querySettings, error) {
|
||
|
qs := &querySettings{
|
||
|
settings: make(map[string]querySettingValueEncoder),
|
||
|
settingsStr: "",
|
||
|
}
|
||
|
|
||
|
for _, info := range querySettingList {
|
||
|
valueStr := query.Get(info.name)
|
||
|
if valueStr == "" {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
switch info.qsType {
|
||
|
case uintQS, intQS, timeQS:
|
||
|
value, err := strconv.ParseUint(valueStr, 10, 64)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
qs.settings[info.name] = func(enc *binary.Encoder) error { return enc.Uvarint(value) }
|
||
|
|
||
|
case boolQS:
|
||
|
valueBool, err := strconv.ParseBool(valueStr)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
value := uint64(0)
|
||
|
if valueBool {
|
||
|
value = 1
|
||
|
}
|
||
|
qs.settings[info.name] = func(enc *binary.Encoder) error { return enc.Uvarint(value) }
|
||
|
|
||
|
default:
|
||
|
err := fmt.Errorf("query setting %s has unsupported data type", info.name)
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
if qs.settingsStr != "" {
|
||
|
qs.settingsStr += "&"
|
||
|
}
|
||
|
qs.settingsStr += info.name + "=" + valueStr
|
||
|
}
|
||
|
|
||
|
return qs, nil
|
||
|
}
|
||
|
|
||
|
func (qs *querySettings) IsEmpty() bool {
|
||
|
return len(qs.settings) == 0
|
||
|
}
|
||
|
|
||
|
func (qs *querySettings) Serialize(enc *binary.Encoder) error {
|
||
|
for name, fn := range qs.settings {
|
||
|
if err := enc.String(name); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if err := fn(enc); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|