2018-06-05 21:39:01 +00:00
|
|
|
#pragma once
|
|
|
|
|
2021-11-05 11:55:30 +00:00
|
|
|
#include <Core/Names.h>
|
2022-06-30 16:14:30 +00:00
|
|
|
#include <Core/Defines.h>
|
2021-10-02 07:13:14 +00:00
|
|
|
#include <base/types.h>
|
2023-03-17 03:44:14 +00:00
|
|
|
#include <base/unit.h>
|
2018-06-08 01:51:55 +00:00
|
|
|
|
|
|
|
|
2018-06-05 21:39:01 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2020-11-07 08:53:39 +00:00
|
|
|
/**
|
|
|
|
* Various tweaks for input/output formats. Text serialization/deserialization
|
|
|
|
* of data types also depend on some of these settings. It is different from
|
|
|
|
* FormatFactorySettings in that it has all necessary user-provided settings
|
|
|
|
* combined with information from context etc, that we can use directly during
|
|
|
|
* serialization. In contrast, FormatFactorySettings' job is to reflect the
|
|
|
|
* changes made to user-visible format settings, such as when tweaking the
|
|
|
|
* the format for File engine.
|
|
|
|
* NOTE Parameters for unrelated formats and unrelated data types are collected
|
|
|
|
* in this struct - it prevents modularity, but they are difficult to separate.
|
2018-06-08 01:51:55 +00:00
|
|
|
*/
|
2018-06-05 21:39:01 +00:00
|
|
|
struct FormatSettings
|
|
|
|
{
|
2020-04-27 15:21:53 +00:00
|
|
|
/// Format will be used for streaming. Not every formats support it
|
|
|
|
/// Option means that each chunk of data need to be formatted independently. Also each chunk will be flushed at the end of processing.
|
2020-04-26 13:44:11 +00:00
|
|
|
bool enable_streaming = false;
|
|
|
|
|
2018-06-08 01:51:55 +00:00
|
|
|
bool skip_unknown_fields = false;
|
2019-04-22 13:31:17 +00:00
|
|
|
bool with_names_use_header = false;
|
2021-10-14 10:32:49 +00:00
|
|
|
bool with_types_use_header = false;
|
2018-06-08 01:51:55 +00:00
|
|
|
bool write_statistics = true;
|
2018-09-14 13:43:57 +00:00
|
|
|
bool import_nested_json = false;
|
2021-04-02 21:05:40 +00:00
|
|
|
bool null_as_default = true;
|
2021-08-16 08:03:23 +00:00
|
|
|
bool decimal_trailing_zeros = false;
|
2021-10-14 10:32:49 +00:00
|
|
|
bool defaults_for_omitted_fields = true;
|
2018-06-08 01:51:55 +00:00
|
|
|
|
2021-10-31 19:53:24 +00:00
|
|
|
bool seekable_read = true;
|
2021-12-15 11:30:57 +00:00
|
|
|
UInt64 max_rows_to_read_for_schema_inference = 100;
|
2021-10-31 19:53:24 +00:00
|
|
|
|
2022-06-28 11:29:07 +00:00
|
|
|
String column_names_for_schema_inference;
|
2022-08-16 09:41:32 +00:00
|
|
|
String schema_inference_hints;
|
|
|
|
|
2022-07-13 15:57:55 +00:00
|
|
|
bool try_infer_integers = false;
|
|
|
|
bool try_infer_dates = false;
|
|
|
|
bool try_infer_datetimes = false;
|
2022-03-24 12:54:12 +00:00
|
|
|
|
2018-06-05 21:39:01 +00:00
|
|
|
enum class DateTimeInputFormat
|
|
|
|
{
|
2022-03-02 08:00:06 +00:00
|
|
|
Basic, /// Default format for fast parsing: YYYY-MM-DD hh:mm:ss (ISO-8601 without fractional part and timezone) or NNNNNNNNNN unix timestamp.
|
|
|
|
BestEffort, /// Use sophisticated rules to parse whatever possible.
|
|
|
|
BestEffortUS /// Use sophisticated rules to parse American style: mm/dd/yyyy
|
2018-06-05 21:39:01 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
DateTimeInputFormat date_time_input_format = DateTimeInputFormat::Basic;
|
2018-06-10 19:22:49 +00:00
|
|
|
|
2020-10-13 10:59:43 +00:00
|
|
|
enum class DateTimeOutputFormat
|
|
|
|
{
|
|
|
|
Simple,
|
|
|
|
ISO,
|
|
|
|
UnixTimestamp
|
|
|
|
};
|
|
|
|
|
2021-11-09 13:14:07 +00:00
|
|
|
enum class EscapingRule
|
|
|
|
{
|
|
|
|
None,
|
|
|
|
Escaped,
|
|
|
|
Quoted,
|
|
|
|
CSV,
|
|
|
|
JSON,
|
|
|
|
XML,
|
|
|
|
Raw
|
|
|
|
};
|
|
|
|
|
2022-12-07 21:19:27 +00:00
|
|
|
bool schema_inference_make_columns_nullable = true;
|
|
|
|
|
2020-10-13 10:59:43 +00:00
|
|
|
DateTimeOutputFormat date_time_output_format = DateTimeOutputFormat::Simple;
|
|
|
|
|
2022-03-30 10:54:19 +00:00
|
|
|
bool input_format_ipv4_default_on_conversion_error = false;
|
|
|
|
bool input_format_ipv6_default_on_conversion_error = false;
|
|
|
|
|
2018-06-10 19:22:49 +00:00
|
|
|
UInt64 input_allow_errors_num = 0;
|
2019-01-07 19:56:53 +00:00
|
|
|
Float32 input_allow_errors_ratio = 0;
|
2019-02-19 20:51:44 +00:00
|
|
|
|
2023-03-17 03:44:14 +00:00
|
|
|
UInt64 max_binary_string_size = 1_GiB;
|
|
|
|
UInt64 max_binary_array_size = 1_GiB;
|
2023-02-10 10:47:06 +00:00
|
|
|
UInt64 client_protocol_version = 0;
|
2022-12-02 12:57:11 +00:00
|
|
|
|
2022-12-12 22:00:45 +00:00
|
|
|
UInt64 max_parser_depth = DBMS_DEFAULT_MAX_PARSER_DEPTH;
|
|
|
|
|
2023-03-01 21:27:46 +00:00
|
|
|
enum class ArrowCompression
|
|
|
|
{
|
|
|
|
NONE,
|
|
|
|
LZ4_FRAME,
|
|
|
|
ZSTD
|
|
|
|
};
|
|
|
|
|
2020-11-02 07:50:38 +00:00
|
|
|
struct
|
2020-05-03 12:26:39 +00:00
|
|
|
{
|
|
|
|
UInt64 row_group_size = 1000000;
|
2021-05-25 12:01:28 +00:00
|
|
|
bool low_cardinality_as_dictionary = false;
|
2021-07-01 17:59:28 +00:00
|
|
|
bool import_nested = false;
|
2021-12-02 08:14:25 +00:00
|
|
|
bool allow_missing_columns = false;
|
2022-03-24 12:54:12 +00:00
|
|
|
bool skip_columns_with_unsupported_types_in_schema_inference = false;
|
2022-03-22 10:55:10 +00:00
|
|
|
bool case_insensitive_column_matching = false;
|
2022-05-18 14:51:21 +00:00
|
|
|
bool output_string_as_string = false;
|
2023-01-16 21:01:31 +00:00
|
|
|
bool output_fixed_string_as_fixed_byte_array = true;
|
2023-03-01 21:27:46 +00:00
|
|
|
ArrowCompression output_compression_method = ArrowCompression::NONE;
|
2020-05-03 12:26:39 +00:00
|
|
|
} arrow;
|
|
|
|
|
2020-11-02 07:50:38 +00:00
|
|
|
struct
|
2019-02-19 20:51:44 +00:00
|
|
|
{
|
2020-11-02 07:50:38 +00:00
|
|
|
String schema_registry_url;
|
|
|
|
String output_codec;
|
|
|
|
UInt64 output_sync_interval = 16 * 1024;
|
|
|
|
bool allow_missing_fields = false;
|
2021-07-09 16:18:22 +00:00
|
|
|
String string_column_pattern;
|
2021-11-02 11:06:10 +00:00
|
|
|
UInt64 output_rows_in_file = 1;
|
2020-11-02 07:50:38 +00:00
|
|
|
} avro;
|
2019-02-19 20:51:44 +00:00
|
|
|
|
2021-11-19 05:22:44 +00:00
|
|
|
String bool_true_representation = "true";
|
|
|
|
String bool_false_representation = "false";
|
2021-11-10 08:08:24 +00:00
|
|
|
|
2020-11-02 07:50:38 +00:00
|
|
|
struct CSV
|
2019-12-25 19:17:41 +00:00
|
|
|
{
|
2020-11-02 07:50:38 +00:00
|
|
|
char delimiter = ',';
|
|
|
|
bool allow_single_quotes = true;
|
|
|
|
bool allow_double_quotes = true;
|
|
|
|
bool empty_as_default = false;
|
|
|
|
bool crlf_end_of_line = false;
|
2022-08-19 16:39:13 +00:00
|
|
|
bool enum_as_number = false;
|
|
|
|
bool arrays_as_nested_csv = false;
|
2021-09-17 02:18:01 +00:00
|
|
|
String null_representation = "\\N";
|
2021-12-20 16:25:54 +00:00
|
|
|
char tuple_delimiter = ',';
|
2022-08-19 16:39:13 +00:00
|
|
|
bool use_best_effort_in_schema_inference = true;
|
2022-05-25 15:00:11 +00:00
|
|
|
UInt64 skip_first_lines = 0;
|
2022-11-17 15:21:38 +00:00
|
|
|
String custom_delimiter;
|
2023-01-05 22:57:25 +00:00
|
|
|
bool try_detect_header = true;
|
2020-11-02 07:50:38 +00:00
|
|
|
} csv;
|
2019-12-25 19:17:41 +00:00
|
|
|
|
2021-12-02 08:14:25 +00:00
|
|
|
struct HiveText
|
|
|
|
{
|
|
|
|
char fields_delimiter = '\x01';
|
|
|
|
char collection_items_delimiter = '\x02';
|
|
|
|
char map_keys_delimiter = '\x03';
|
2022-03-24 13:08:58 +00:00
|
|
|
Names input_field_names;
|
2021-12-02 08:14:25 +00:00
|
|
|
} hive_text;
|
|
|
|
|
2019-12-25 19:17:41 +00:00
|
|
|
struct Custom
|
|
|
|
{
|
|
|
|
std::string result_before_delimiter;
|
|
|
|
std::string result_after_delimiter;
|
|
|
|
std::string row_before_delimiter;
|
|
|
|
std::string row_after_delimiter;
|
|
|
|
std::string row_between_delimiter;
|
|
|
|
std::string field_delimiter;
|
2021-11-09 13:14:07 +00:00
|
|
|
EscapingRule escaping_rule = EscapingRule::Escaped;
|
2023-01-05 22:57:25 +00:00
|
|
|
bool try_detect_header = true;
|
2020-11-02 07:50:38 +00:00
|
|
|
} custom;
|
2019-12-25 19:17:41 +00:00
|
|
|
|
2020-11-02 07:50:38 +00:00
|
|
|
struct
|
|
|
|
{
|
2020-11-17 19:50:47 +00:00
|
|
|
bool array_of_rows = false;
|
2020-11-02 07:50:38 +00:00
|
|
|
bool quote_64bit_integers = true;
|
2022-09-20 13:49:17 +00:00
|
|
|
bool quote_64bit_floats = false;
|
2020-11-02 07:50:38 +00:00
|
|
|
bool quote_denormals = true;
|
2022-09-08 16:07:20 +00:00
|
|
|
bool quote_decimals = false;
|
2020-11-02 07:50:38 +00:00
|
|
|
bool escape_forward_slashes = true;
|
2023-01-12 16:36:44 +00:00
|
|
|
bool read_named_tuples_as_objects = false;
|
|
|
|
bool write_named_tuples_as_objects = false;
|
|
|
|
bool defaults_for_missing_elements_in_named_tuple = false;
|
2023-01-26 15:47:56 +00:00
|
|
|
bool ignore_unknown_keys_in_named_tuple = false;
|
2020-11-02 07:50:38 +00:00
|
|
|
bool serialize_as_strings = false;
|
2022-03-29 17:37:31 +00:00
|
|
|
bool read_bools_as_numbers = true;
|
2022-09-08 16:07:20 +00:00
|
|
|
bool read_numbers_as_strings = true;
|
2022-12-08 18:58:18 +00:00
|
|
|
bool read_objects_as_strings = true;
|
2022-07-13 15:57:55 +00:00
|
|
|
bool try_infer_numbers_from_strings = false;
|
2022-09-20 13:49:17 +00:00
|
|
|
bool validate_types_from_metadata = true;
|
2022-09-01 19:00:24 +00:00
|
|
|
bool validate_utf8 = false;
|
2022-12-21 21:21:30 +00:00
|
|
|
bool allow_object_type = false;
|
2020-11-02 07:50:38 +00:00
|
|
|
} json;
|
2020-01-08 09:13:12 +00:00
|
|
|
|
2022-09-22 16:48:54 +00:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
String column_for_object_name;
|
|
|
|
} json_object_each_row;
|
|
|
|
|
2023-02-23 16:14:10 +00:00
|
|
|
enum class ParquetVersion
|
|
|
|
{
|
|
|
|
V1_0,
|
|
|
|
V2_4,
|
|
|
|
V2_6,
|
|
|
|
V2_LATEST,
|
|
|
|
};
|
|
|
|
|
2023-03-01 21:27:46 +00:00
|
|
|
enum class ParquetCompression
|
|
|
|
{
|
|
|
|
NONE,
|
|
|
|
SNAPPY,
|
|
|
|
ZSTD,
|
|
|
|
LZ4,
|
|
|
|
GZIP,
|
|
|
|
BROTLI,
|
|
|
|
};
|
|
|
|
|
2020-11-02 07:50:38 +00:00
|
|
|
struct
|
2020-01-08 09:13:12 +00:00
|
|
|
{
|
2023-04-29 02:29:51 +00:00
|
|
|
UInt64 row_group_rows = 1000000;
|
|
|
|
UInt64 row_group_bytes = 512 * 1024 * 1024;
|
2021-07-01 17:59:28 +00:00
|
|
|
bool import_nested = false;
|
2021-12-02 08:14:25 +00:00
|
|
|
bool allow_missing_columns = false;
|
2022-03-24 12:54:12 +00:00
|
|
|
bool skip_columns_with_unsupported_types_in_schema_inference = false;
|
2022-03-21 07:47:37 +00:00
|
|
|
bool case_insensitive_column_matching = false;
|
2022-04-06 08:40:22 +00:00
|
|
|
std::unordered_set<int> skip_row_groups = {};
|
2022-05-18 14:51:21 +00:00
|
|
|
bool output_string_as_string = false;
|
2023-01-16 21:01:31 +00:00
|
|
|
bool output_fixed_string_as_fixed_byte_array = true;
|
2023-03-28 20:28:28 +00:00
|
|
|
// TODO: This should probably be shared among all formats and with
|
2023-03-24 01:34:24 +00:00
|
|
|
// https://github.com/ClickHouse/ClickHouse/issues/38755
|
|
|
|
bool preserve_order = false;
|
2023-03-13 18:22:09 +00:00
|
|
|
UInt64 max_block_size = 8192;
|
2023-02-23 16:14:10 +00:00
|
|
|
ParquetVersion output_version;
|
2023-03-01 21:27:46 +00:00
|
|
|
ParquetCompression output_compression_method = ParquetCompression::SNAPPY;
|
2023-05-19 02:07:30 +00:00
|
|
|
bool output_compliant_nested_types = true;
|
2020-11-02 07:50:38 +00:00
|
|
|
} parquet;
|
|
|
|
|
|
|
|
struct Pretty
|
|
|
|
{
|
|
|
|
UInt64 max_rows = 10000;
|
|
|
|
UInt64 max_column_pad_width = 250;
|
|
|
|
UInt64 max_value_width = 10000;
|
|
|
|
bool color = true;
|
|
|
|
|
|
|
|
bool output_format_pretty_row_numbers = false;
|
|
|
|
|
|
|
|
enum class Charset
|
|
|
|
{
|
|
|
|
UTF8,
|
|
|
|
ASCII,
|
|
|
|
};
|
2020-01-11 07:01:20 +00:00
|
|
|
|
2020-11-02 07:50:38 +00:00
|
|
|
Charset charset = Charset::UTF8;
|
|
|
|
} pretty;
|
2020-01-08 09:13:12 +00:00
|
|
|
|
2020-11-02 07:50:38 +00:00
|
|
|
struct
|
|
|
|
{
|
2022-04-27 11:47:28 +00:00
|
|
|
bool input_flatten_google_wrappers = false;
|
|
|
|
bool output_nullables_with_google_wrappers = false;
|
2020-11-02 07:50:38 +00:00
|
|
|
/**
|
2020-11-07 08:53:39 +00:00
|
|
|
* Some buffers (kafka / rabbit) split the rows internally using callback,
|
|
|
|
* and always send one row per message, so we can push there formats
|
|
|
|
* without framing / delimiters (like ProtobufSingle). In other cases,
|
|
|
|
* we have to enforce exporting at most one row in the format output,
|
|
|
|
* because Protobuf without delimiters is not generally useful.
|
2020-11-02 07:50:38 +00:00
|
|
|
*/
|
2021-01-11 01:50:30 +00:00
|
|
|
bool allow_multiple_rows_without_delimiter = false;
|
2022-07-20 11:16:25 +00:00
|
|
|
bool skip_fields_with_unsupported_types_in_schema_inference = false;
|
2020-11-02 07:50:38 +00:00
|
|
|
} protobuf;
|
|
|
|
|
2021-07-16 10:10:56 +00:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
uint32_t client_capabilities = 0;
|
|
|
|
size_t max_packet_size = 0;
|
|
|
|
uint8_t * sequence_id = nullptr; /// Not null if it's MySQLWire output format used to handle MySQL protocol connections.
|
|
|
|
} mysql_wire;
|
|
|
|
|
2020-11-02 07:50:38 +00:00
|
|
|
struct
|
2020-02-14 19:48:45 +00:00
|
|
|
{
|
|
|
|
std::string regexp;
|
2021-11-09 13:14:07 +00:00
|
|
|
EscapingRule escaping_rule = EscapingRule::Raw;
|
2020-02-14 19:48:45 +00:00
|
|
|
bool skip_unmatched = false;
|
2020-11-02 07:50:38 +00:00
|
|
|
} regexp;
|
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
std::string format_schema;
|
|
|
|
std::string format_schema_path;
|
|
|
|
bool is_server = false;
|
|
|
|
} schema;
|
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
String resultset_format;
|
|
|
|
String row_format;
|
|
|
|
String row_between_delimiter;
|
|
|
|
} template_settings;
|
2020-02-14 19:48:45 +00:00
|
|
|
|
2020-11-02 07:50:38 +00:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
bool empty_as_default = false;
|
|
|
|
bool crlf_end_of_line = false;
|
|
|
|
String null_representation = "\\N";
|
2022-08-19 16:39:13 +00:00
|
|
|
bool enum_as_number = false;
|
|
|
|
bool use_best_effort_in_schema_inference = true;
|
2022-05-25 15:00:11 +00:00
|
|
|
UInt64 skip_first_lines = 0;
|
2023-01-05 22:57:25 +00:00
|
|
|
bool try_detect_header = true;
|
2020-11-02 07:50:38 +00:00
|
|
|
} tsv;
|
2020-02-14 19:48:45 +00:00
|
|
|
|
2020-11-02 07:50:38 +00:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
bool interpret_expressions = true;
|
|
|
|
bool deduce_templates_of_expressions = true;
|
|
|
|
bool accurate_types_of_literals = true;
|
|
|
|
} values;
|
2021-07-01 17:59:28 +00:00
|
|
|
|
2023-03-01 21:27:46 +00:00
|
|
|
enum class ORCCompression
|
|
|
|
{
|
|
|
|
NONE,
|
|
|
|
LZ4,
|
|
|
|
SNAPPY,
|
|
|
|
ZSTD,
|
|
|
|
ZLIB,
|
|
|
|
};
|
|
|
|
|
2021-07-01 17:59:28 +00:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
bool import_nested = false;
|
2021-12-02 08:14:25 +00:00
|
|
|
bool allow_missing_columns = false;
|
2021-12-18 09:25:25 +00:00
|
|
|
int64_t row_batch_size = 100'000;
|
2022-03-24 12:54:12 +00:00
|
|
|
bool skip_columns_with_unsupported_types_in_schema_inference = false;
|
2022-03-21 07:47:37 +00:00
|
|
|
bool case_insensitive_column_matching = false;
|
2022-04-06 08:40:22 +00:00
|
|
|
std::unordered_set<int> skip_stripes = {};
|
2022-05-18 14:51:21 +00:00
|
|
|
bool output_string_as_string = false;
|
2023-03-01 21:27:46 +00:00
|
|
|
ORCCompression output_compression_method = ORCCompression::NONE;
|
2021-07-01 17:59:28 +00:00
|
|
|
} orc;
|
2021-09-28 12:59:22 +00:00
|
|
|
|
2021-09-28 13:07:00 +00:00
|
|
|
/// For capnProto format we should determine how to
|
2021-09-28 12:59:22 +00:00
|
|
|
/// compare ClickHouse Enum and Enum from schema.
|
|
|
|
enum class EnumComparingMode
|
|
|
|
{
|
|
|
|
BY_NAMES, // Names in enums should be the same, values can be different.
|
|
|
|
BY_NAMES_CASE_INSENSITIVE, // Case-insensitive name comparison.
|
|
|
|
BY_VALUES, // Values should be the same, names can be different.
|
|
|
|
};
|
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
EnumComparingMode enum_comparing_mode = EnumComparingMode::BY_VALUES;
|
2022-07-20 11:16:25 +00:00
|
|
|
bool skip_fields_with_unsupported_types_in_schema_inference = false;
|
2021-09-28 12:59:22 +00:00
|
|
|
} capn_proto;
|
2021-12-15 11:30:57 +00:00
|
|
|
|
2022-01-27 16:54:15 +00:00
|
|
|
enum class MsgPackUUIDRepresentation
|
|
|
|
{
|
|
|
|
STR, // Output UUID as a string of 36 characters.
|
|
|
|
BIN, // Output UUID as 16-bytes binary.
|
|
|
|
EXT, // Output UUID as ExtType = 2
|
|
|
|
};
|
|
|
|
|
2021-12-15 11:30:57 +00:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
UInt64 number_of_columns = 0;
|
2022-01-27 16:54:15 +00:00
|
|
|
MsgPackUUIDRepresentation output_uuid_representation = MsgPackUUIDRepresentation::EXT;
|
2021-12-15 11:30:57 +00:00
|
|
|
} msgpack;
|
2022-04-26 10:42:56 +00:00
|
|
|
|
|
|
|
struct MySQLDump
|
|
|
|
{
|
|
|
|
String table_name;
|
|
|
|
bool map_column_names = true;
|
|
|
|
} mysql_dump;
|
2022-06-27 18:31:57 +00:00
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
2022-06-30 16:14:30 +00:00
|
|
|
UInt64 max_batch_size = DEFAULT_BLOCK_SIZE;
|
2022-06-27 18:31:57 +00:00
|
|
|
String table_name = "table";
|
|
|
|
bool include_column_names = true;
|
|
|
|
bool use_replace = false;
|
2022-06-30 16:14:30 +00:00
|
|
|
bool quote_names = true;
|
2022-06-27 18:31:57 +00:00
|
|
|
} sql_insert;
|
2022-11-10 20:15:14 +00:00
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
bool output_string_as_string;
|
|
|
|
bool skip_fields_with_unsupported_types_in_schema_inference;
|
|
|
|
} bson;
|
2023-02-27 19:28:19 +00:00
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
bool allow_types_conversion = true;
|
|
|
|
} native;
|
2018-06-05 21:39:01 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|