```sql
CREATE TABLE test_tbl
(   `ip` String, `ipv6` IPv6 MATERIALIZED toIPv6(ip) )
ENGINE = Memory;

insert into test_tbl(ip) values ( 'fe80::9801:43ff:fe1f:7690'), ('1.1.1.1'), (''), ('::ffff:1.1.1.1' );

 DB::Exception: Invalid IPv6 value: while executing 'FUNCTION _CAST(toIPv6(ip) :: 2, 'IPv6' :: 1)


set cast_ipv4_ipv6_default_on_conversion_error=1;
insert into test_tbl(ip) values ( 'fe80::9801:43ff:fe1f:7690'), ('1.1.1.1'), (''), ('::ffff:1.1.1.1' );
 
 DB::Exception: Invalid IPv6 value: while executing 'FUNCTION _CAST(toIPv6(ip)
```

`toIPv6OrDefault` does not help in this case.

```sql
CREATE TABLE test_tbl
(   `ip` String, `ipv6` IPv6 MATERIALIZED toIPv6OrDefault(ip) )
ENGINE = Memory;

insert into test_tbl(ip) values ( 'fe80::9801:43ff:fe1f:7690'), ('1.1.1.1'), (''), ('::ffff:1.1.1.1' );
  DB::Exception: Invalid IPv6 value: while executing 'FUNCTION _CAST(toIPv6OrD

insert into test_tbl(ip) values ( 'fe80::9801:43ff:fe1f:7690'), ('1.1.1.1'), (''), ('::ffff:1.1.1.1' ), ('garbudge');
  DB::Exception: Invalid IPv6 value: while executing 'FUNCTION
```

WA:

```sql
CREATE TABLE test_tbl
(   `ip` String, `ipv6` IPv6 MATERIALIZED if(ip='', '::', ip) )
ENGINE = Memory;

insert into test_tbl(ip) values ( 'fe80::9801:43ff:fe1f:7690'), ('1.1.1.1'), (''), ('::ffff:1.1.1.1' );

select ip, ipv6 from test_tbl;
┌─ip────────────────────────┬─ipv6──────────────────────┐
│ fe80::9801:43ff:fe1f:7690 │ fe80::9801:43ff:fe1f:7690 │
│ 1.1.1.1                   │ ::ffff:1.1.1.1            │
│                           │ ::                        │
│ ::ffff:1.1.1.1            │ ::ffff:1.1.1.1            │
└───────────────────────────┴───────────────────────────┘
```
M(OverflowMode, transfer_overflow_mode, OverflowMode::THROW, "What to do when the limit is exceeded.", 0) \
    \
    M(UInt64, max_rows_in_distinct, 0, "Maximum number of elements during execution of DISTINCT.", 0) \
    M(UInt64, max_bytes_in_distinct, 0, "Maximum total size of state (in uncompressed bytes) in memory for the execution of DISTINCT.", 0) \
    M(OverflowMode, distinct_overflow_mode, OverflowMode::THROW, "What to do when the limit is exceeded.", 0) \
    \
    M(UInt64, max_memory_usage, 0, "Maximum memory usage for processing of single query. Zero means unlimited.", 0) \
    M(UInt64, max_guaranteed_memory_usage, 0, "Maximum guaranteed memory usage for processing of single query. It represents soft limit. Zero means unlimited.", 0) \
    M(UInt64, max_memory_usage_for_user, 0, "Maximum memory usage for processing all concurrently running queries for the user. Zero means unlimited.", 0) \
    M(UInt64, max_guaranteed_memory_usage_for_user, 0, "Maximum guaranteed memory usage for processing all concurrently running queries for the user. It represents soft limit. Zero means unlimited.", 0) \
    M(UInt64, max_untracked_memory, (4 * 1024 * 1024), "Small allocations and deallocations are grouped in thread local variable and tracked or profiled only when amount (in absolute value) becomes larger than specified value. If the value is higher than 'memory_profiler_step' it will be effectively lowered to 'memory_profiler_step'.", 0) \
    M(UInt64, memory_profiler_step, (4 * 1024 * 1024), "Whenever query memory usage becomes larger than every next step in number of bytes the memory profiler will collect the allocating stack trace. Zero means disabled memory profiler. Values lower than a few megabytes will slow down query processing.", 0) \
    M(Float, memory_profiler_sample_probability, 0., "Collect random allocations and deallocations and write them into system.trace_log with 'MemorySample' trace_type. The probability is for every alloc/free regardless to the size of the allocation. Note that sampling happens only when the amount of untracked memory exceeds 'max_untracked_memory'. You may want to set 'max_untracked_memory' to 0 for extra fine grained sampling.", 0) \
    \
    M(UInt64, memory_usage_overcommit_max_wait_microseconds, 0, "Maximum time thread will wait for memory to be freed in the case of memory overcommit. If timeout is reached and memory is not freed, exception is thrown", 0) \
    \
    M(UInt64, max_network_bandwidth, 0, "The maximum speed of data exchange over the network in bytes per second for a query. Zero means unlimited.", 0) \
    M(UInt64, max_network_bytes, 0, "The maximum number of bytes (compressed) to receive or transmit over the network for execution of the query.", 0) \
    M(UInt64, max_network_bandwidth_for_user, 0, "The maximum speed of data exchange over the network in bytes per second for all concurrently running user queries. Zero means unlimited.", 0)\
    M(UInt64, max_network_bandwidth_for_all_users, 0, "The maximum speed of data exchange over the network in bytes per second for all concurrently running queries. Zero means unlimited.", 0) \
    \
    M(UInt64, max_backup_threads, 0, "The maximum number of threads to execute a BACKUP or RESTORE request. By default, it is determined automatically.", 0) \
    \
    M(Bool, log_profile_events, true, "Log query performance statistics into the query_log, query_thread_log and query_views_log.", 0) \
    M(Bool, log_query_settings, true, "Log query settings into the query_log.", 0) \
    M(Bool, log_query_threads, true, "Log query threads into system.query_thread_log table. This setting have effect only when 'log_queries' is true.", 0) \
    M(Bool, log_query_views, true, "Log query dependent views into system.query_views_log table. This setting have effect only when 'log_queries' is true.", 0) \
    M(String, log_comment, "", "Log comment into system.query_log table and server log. It can be set to arbitrary string no longer than max_query_size.", 0) \
    M(LogsLevel, send_logs_level, LogsLevel::fatal, "Send server text logs with specified minimum level to client. Valid values: 'trace', 'debug', 'information', 'warning', 'error', 'fatal', 'none'", 0) \
    M(Bool, enable_optimize_predicate_expression, true, "If it is set to true, optimize predicates to subqueries.", 0) \