mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 15:12:02 +00:00
Merge branch 'master' into blind_fix_of_read_in_order
This commit is contained in:
commit
945dd3aa59
@ -57,8 +57,8 @@ if (SANITIZE)
|
||||
endif ()
|
||||
|
||||
elseif (SANITIZE STREQUAL "undefined")
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SAN_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all -fno-sanitize=float-divide-by-zero")
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SAN_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all -fno-sanitize=float-divide-by-zero")
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SAN_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all -fno-sanitize=float-divide-by-zero -fsanitize-blacklist=${CMAKE_SOURCE_DIR}/tests/ubsan_suppressions.txt")
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SAN_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all -fno-sanitize=float-divide-by-zero -fsanitize-blacklist=${CMAKE_SOURCE_DIR}/tests/ubsan_suppressions.txt")
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined")
|
||||
endif()
|
||||
|
69
debian/clickhouse-server.init
vendored
69
debian/clickhouse-server.init
vendored
@ -153,82 +153,19 @@ initdb()
|
||||
|
||||
start()
|
||||
{
|
||||
[ -x $CLICKHOUSE_BINDIR/$PROGRAM ] || exit 0
|
||||
local EXIT_STATUS
|
||||
EXIT_STATUS=0
|
||||
|
||||
echo -n "Start $PROGRAM service: "
|
||||
|
||||
if is_running; then
|
||||
echo -n "already running "
|
||||
EXIT_STATUS=1
|
||||
else
|
||||
ulimit -n 262144
|
||||
mkdir -p $CLICKHOUSE_PIDDIR
|
||||
chown -R $CLICKHOUSE_USER:$CLICKHOUSE_GROUP $CLICKHOUSE_PIDDIR
|
||||
initdb
|
||||
if ! is_running; then
|
||||
# Lock should not be held while running child process, so we release the lock. Note: obviously, there is race condition.
|
||||
# But clickhouse-server has protection from simultaneous runs with same data directory.
|
||||
su -s $SHELL ${CLICKHOUSE_USER} -c "$FLOCK -u 9; $CLICKHOUSE_PROGRAM_ENV exec -a \"$PROGRAM\" \"$CLICKHOUSE_BINDIR/$PROGRAM\" --daemon --pid-file=\"$CLICKHOUSE_PIDFILE\" --config-file=\"$CLICKHOUSE_CONFIG\""
|
||||
EXIT_STATUS=$?
|
||||
if [ $EXIT_STATUS -ne 0 ]; then
|
||||
return $EXIT_STATUS
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $EXIT_STATUS -eq 0 ]; then
|
||||
attempts=0
|
||||
while ! is_running && [ $attempts -le ${CLICKHOUSE_START_TIMEOUT:=10} ]; do
|
||||
attempts=$(($attempts + 1))
|
||||
sleep 1
|
||||
done
|
||||
if is_running; then
|
||||
echo "DONE"
|
||||
else
|
||||
echo "UNKNOWN"
|
||||
fi
|
||||
else
|
||||
echo "FAILED"
|
||||
fi
|
||||
|
||||
return $EXIT_STATUS
|
||||
${CLICKHOUSE_GENERIC_PROGRAM} start --user "${CLICKHOUSE_USER}" --pid-path "${CLICKHOUSE_PIDDIR}" --config-path "${CLICKHOUSE_CONFDIR}" --binary-path "${CLICKHOUSE_BINDIR}"
|
||||
}
|
||||
|
||||
|
||||
stop()
|
||||
{
|
||||
#local EXIT_STATUS
|
||||
EXIT_STATUS=0
|
||||
|
||||
if [ -f $CLICKHOUSE_PIDFILE ]; then
|
||||
|
||||
echo -n "Stop $PROGRAM service: "
|
||||
|
||||
kill -TERM $(cat "$CLICKHOUSE_PIDFILE")
|
||||
|
||||
if ! wait_for_done ${CLICKHOUSE_STOP_TIMEOUT}; then
|
||||
EXIT_STATUS=2
|
||||
echo "TIMEOUT"
|
||||
else
|
||||
echo "DONE"
|
||||
fi
|
||||
|
||||
fi
|
||||
return $EXIT_STATUS
|
||||
${CLICKHOUSE_GENERIC_PROGRAM} stop --pid-path "${CLICKHOUSE_PIDDIR}"
|
||||
}
|
||||
|
||||
|
||||
restart()
|
||||
{
|
||||
check_config
|
||||
if stop; then
|
||||
if start; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
return 1
|
||||
${CLICKHOUSE_GENERIC_PROGRAM} restart --user "${CLICKHOUSE_USER}" --pid-path "${CLICKHOUSE_PIDDIR}" --config-path "${CLICKHOUSE_CONFDIR}" --binary-path "${CLICKHOUSE_BINDIR}"
|
||||
}
|
||||
|
||||
|
||||
|
104
debian/clickhouse-server.postinst
vendored
104
debian/clickhouse-server.postinst
vendored
@ -2,6 +2,7 @@
|
||||
set -e
|
||||
# set -x
|
||||
|
||||
PROGRAM=clickhouse-server
|
||||
CLICKHOUSE_USER=${CLICKHOUSE_USER:=clickhouse}
|
||||
CLICKHOUSE_GROUP=${CLICKHOUSE_GROUP:=${CLICKHOUSE_USER}}
|
||||
# Please note that we don't support paths with whitespaces. This is rather ignorant.
|
||||
@ -12,6 +13,7 @@ CLICKHOUSE_BINDIR=${CLICKHOUSE_BINDIR:=/usr/bin}
|
||||
CLICKHOUSE_GENERIC_PROGRAM=${CLICKHOUSE_GENERIC_PROGRAM:=clickhouse}
|
||||
EXTRACT_FROM_CONFIG=${CLICKHOUSE_GENERIC_PROGRAM}-extract-from-config
|
||||
CLICKHOUSE_CONFIG=$CLICKHOUSE_CONFDIR/config.xml
|
||||
CLICKHOUSE_PIDDIR=/var/run/$PROGRAM
|
||||
|
||||
[ -f /usr/share/debconf/confmodule ] && . /usr/share/debconf/confmodule
|
||||
[ -f /etc/default/clickhouse ] && . /etc/default/clickhouse
|
||||
@ -41,105 +43,5 @@ if [ "$1" = configure ] || [ -n "$not_deb_os" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Make sure the administrative user exists
|
||||
if ! getent passwd ${CLICKHOUSE_USER} > /dev/null; then
|
||||
if [ -n "$not_deb_os" ]; then
|
||||
useradd -r -s /bin/false --home-dir /nonexistent ${CLICKHOUSE_USER} > /dev/null
|
||||
else
|
||||
adduser --system --disabled-login --no-create-home --home /nonexistent \
|
||||
--shell /bin/false --group --gecos "ClickHouse server" ${CLICKHOUSE_USER} > /dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
# if the user was created manually, make sure the group is there as well
|
||||
if ! getent group ${CLICKHOUSE_GROUP} > /dev/null; then
|
||||
groupadd -r ${CLICKHOUSE_GROUP} > /dev/null
|
||||
fi
|
||||
|
||||
# make sure user is in the correct group
|
||||
if ! id -Gn ${CLICKHOUSE_USER} | grep -qw ${CLICKHOUSE_USER}; then
|
||||
usermod -a -G ${CLICKHOUSE_GROUP} ${CLICKHOUSE_USER} > /dev/null
|
||||
fi
|
||||
|
||||
# check validity of user and group
|
||||
if [ "$(id -u ${CLICKHOUSE_USER})" -eq 0 ]; then
|
||||
echo "The ${CLICKHOUSE_USER} system user must not have uid 0 (root).
|
||||
Please fix this and reinstall this package." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$(id -g ${CLICKHOUSE_GROUP})" -eq 0 ]; then
|
||||
echo "The ${CLICKHOUSE_USER} system user must not have root as primary group.
|
||||
Please fix this and reinstall this package." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -x "$CLICKHOUSE_BINDIR/$EXTRACT_FROM_CONFIG" ] && [ -f "$CLICKHOUSE_CONFIG" ]; then
|
||||
if [ -z "$SHELL" ]; then
|
||||
SHELL="/bin/sh"
|
||||
fi
|
||||
CLICKHOUSE_DATADIR_FROM_CONFIG=$(su -s $SHELL ${CLICKHOUSE_USER} -c "$CLICKHOUSE_BINDIR/$EXTRACT_FROM_CONFIG --config-file=\"$CLICKHOUSE_CONFIG\" --key=path") ||:
|
||||
echo "Path to data directory in ${CLICKHOUSE_CONFIG}: ${CLICKHOUSE_DATADIR_FROM_CONFIG}"
|
||||
fi
|
||||
CLICKHOUSE_DATADIR_FROM_CONFIG=${CLICKHOUSE_DATADIR_FROM_CONFIG:=$CLICKHOUSE_DATADIR}
|
||||
|
||||
if [ ! -d ${CLICKHOUSE_DATADIR_FROM_CONFIG} ]; then
|
||||
mkdir -p ${CLICKHOUSE_DATADIR_FROM_CONFIG}
|
||||
chown ${CLICKHOUSE_USER}:${CLICKHOUSE_GROUP} ${CLICKHOUSE_DATADIR_FROM_CONFIG}
|
||||
chmod 700 ${CLICKHOUSE_DATADIR_FROM_CONFIG}
|
||||
fi
|
||||
|
||||
if [ -d ${CLICKHOUSE_CONFDIR} ]; then
|
||||
mkdir -p ${CLICKHOUSE_CONFDIR}/users.d
|
||||
mkdir -p ${CLICKHOUSE_CONFDIR}/config.d
|
||||
rm -fv ${CLICKHOUSE_CONFDIR}/*-preprocessed.xml ||:
|
||||
fi
|
||||
|
||||
[ -e ${CLICKHOUSE_CONFDIR}/preprocessed ] || ln -s ${CLICKHOUSE_DATADIR_FROM_CONFIG}/preprocessed_configs ${CLICKHOUSE_CONFDIR}/preprocessed ||:
|
||||
|
||||
if [ ! -d ${CLICKHOUSE_LOGDIR} ]; then
|
||||
mkdir -p ${CLICKHOUSE_LOGDIR}
|
||||
chown root:${CLICKHOUSE_GROUP} ${CLICKHOUSE_LOGDIR}
|
||||
# Allow everyone to read logs, root and clickhouse to read-write
|
||||
chmod 775 ${CLICKHOUSE_LOGDIR}
|
||||
fi
|
||||
|
||||
# Set net_admin capabilities to support introspection of "taskstats" performance metrics from the kernel
|
||||
# and ipc_lock capabilities to allow mlock of clickhouse binary.
|
||||
|
||||
# 1. Check that "setcap" tool exists.
|
||||
# 2. Check that an arbitrary program with installed capabilities can run.
|
||||
# 3. Set the capabilities.
|
||||
|
||||
# The second is important for Docker and systemd-nspawn.
|
||||
# When the container has no capabilities,
|
||||
# but the executable file inside the container has capabilities,
|
||||
# then attempt to run this file will end up with a cryptic "Operation not permitted" message.
|
||||
|
||||
TMPFILE=/tmp/test_setcap.sh
|
||||
|
||||
command -v setcap >/dev/null \
|
||||
&& echo > $TMPFILE && chmod a+x $TMPFILE && $TMPFILE && setcap "cap_net_admin,cap_ipc_lock,cap_sys_nice+ep" $TMPFILE && $TMPFILE && rm $TMPFILE \
|
||||
&& setcap "cap_net_admin,cap_ipc_lock,cap_sys_nice+ep" "${CLICKHOUSE_BINDIR}/${CLICKHOUSE_GENERIC_PROGRAM}" \
|
||||
|| echo "Cannot set 'net_admin' or 'ipc_lock' or 'sys_nice' capability for clickhouse binary. This is optional. Taskstats accounting will be disabled. To enable taskstats accounting you may add the required capability later manually."
|
||||
|
||||
# Clean old dynamic compilation results
|
||||
if [ -d "${CLICKHOUSE_DATADIR_FROM_CONFIG}/build" ]; then
|
||||
rm -f ${CLICKHOUSE_DATADIR_FROM_CONFIG}/build/*.cpp ${CLICKHOUSE_DATADIR_FROM_CONFIG}/build/*.so ||:
|
||||
fi
|
||||
|
||||
if [ -f /usr/share/debconf/confmodule ]; then
|
||||
db_get clickhouse-server/default-password
|
||||
defaultpassword="$RET"
|
||||
if [ -n "$defaultpassword" ]; then
|
||||
echo "<yandex><users><default><password>$defaultpassword</password></default></users></yandex>" > ${CLICKHOUSE_CONFDIR}/users.d/default-password.xml
|
||||
chown ${CLICKHOUSE_USER}:${CLICKHOUSE_GROUP} ${CLICKHOUSE_CONFDIR}/users.d/default-password.xml
|
||||
chmod 600 ${CLICKHOUSE_CONFDIR}/users.d/default-password.xml
|
||||
fi
|
||||
|
||||
# everything went well, so now let's reset the password
|
||||
db_set clickhouse-server/default-password ""
|
||||
# ... done with debconf here
|
||||
db_stop
|
||||
fi
|
||||
${CLICKHOUSE_GENERIC_PROGRAM} install --user "${CLICKHOUSE_USER}" --group "${CLICKHOUSE_GROUP}" --pid-path "${CLICKHOUSE_PIDDIR}" --config-path "${CLICKHOUSE_CONFDIR}" --binary-path "${CLICKHOUSE_BINDIR}" --log-path "${CLICKHOUSE_LOGDIR}" --data-path "${CLICKHOUSE_DATADIR}"
|
||||
fi
|
||||
|
@ -31,14 +31,10 @@ RUN curl -O https://clickhouse-builds.s3.yandex.net/utils/1/dpkg-deb \
|
||||
&& chmod +x dpkg-deb \
|
||||
&& cp dpkg-deb /usr/bin
|
||||
|
||||
ENV APACHE_PUBKEY_HASH="bba6987b63c63f710fd4ed476121c588bc3812e99659d27a855f8c4d312783ee66ad6adfce238765691b04d62fa3688f"
|
||||
|
||||
RUN export CODENAME="$(lsb_release --codename --short | tr 'A-Z' 'a-z')" \
|
||||
&& wget -nv -O /tmp/arrow-keyring.deb "https://apache.bintray.com/arrow/ubuntu/apache-arrow-archive-keyring-latest-${CODENAME}.deb" \
|
||||
&& echo "${APACHE_PUBKEY_HASH} /tmp/arrow-keyring.deb" | sha384sum -c \
|
||||
&& dpkg -i /tmp/arrow-keyring.deb
|
||||
|
||||
|
||||
# Libraries from OS are only needed to test the "unbundled" build (this is not used in production).
|
||||
RUN apt-get update \
|
||||
&& apt-get install \
|
||||
|
@ -219,6 +219,8 @@ TESTS_TO_SKIP=(
|
||||
01268_dictionary_direct_layout
|
||||
01280_ssd_complex_key_dictionary
|
||||
01281_group_by_limit_memory_tracking # max_memory_usage_for_user can interfere another queries running concurrently
|
||||
01318_encrypt # Depends on OpenSSL
|
||||
01318_decrypt # Depends on OpenSSL
|
||||
01281_unsucceeded_insert_select_queries_counter
|
||||
01292_create_user
|
||||
01294_lazy_database_concurrent
|
||||
|
@ -48,12 +48,13 @@ This table shows queries that take significantly longer to process on the client
|
||||
#### Unexpected Query Duration
|
||||
Action required for every item -- these are errors that must be fixed.
|
||||
|
||||
Queries that have "short" duration (on the order of 0.1 s) can't be reliably tested in a normal way, where we perform a small (about ten) measurements for each server, because the signal-to-noise ratio is much smaller. There is a special mode for such queries that instead runs them for a fixed amount of time, normally with much higher number of measurements (up to thousands). This mode must be explicitly enabled by the test author to avoid accidental errors. It must be used only for queries that are meant to complete "immediately", such as `select count(*)`. If your query is not supposed to be "immediate", try to make it run longer, by e.g. processing more data.
|
||||
A query is supposed to run longer than 0.1 second. If your query runs faster, increase the amount of processed data to bring the run time above this threshold. You can use a bigger table (e.g. `hits_100m` instead of `hits_10m`), increase a `LIMIT`, make a query single-threaded, and so on. Queries that are too fast suffer from poor stability and precision.
|
||||
|
||||
This table shows queries for which the "short" marking is not consistent with the actual query run time -- i.e., a query runs for a long time but is marked as short, or it runs very fast but is not marked as short.
|
||||
Sometimes you want to test a query that is supposed to complete "instantaneously", i.e. in sublinear time. This might be `count(*)`, or parsing a complicated tuple. It might not be practical or even possible to increase the run time of such queries by adding more data. For such queries there is a specal comparison mode which runs them for a fixed amount of time, instead of a fixed number of iterations like we do normally. This mode is inferior to the normal mode, because the influence of noise and overhead is higher, which leads to less precise and stable results.
|
||||
|
||||
If your query is really supposed to complete "immediately" and can't be made to run longer, you have to mark it as "short". To do so, write `<query short="1">...` in the test file. The value of "short" attribute is evaluated as a python expression, and substitutions are performed, so you can write something like `<query short="{column1} = {column2}">select count(*) from table where {column1} > {column2}</query>`, to mark only a particular combination of variables as short.
|
||||
If it is impossible to increase the run time of a query and it is supposed to complete "immediately", you have to explicitly mark this in the test. To do so, add a `short` attribute to the query tag in the test file: `<query short="1">...`. The value of the `short` attribute is evaluated as a python expression, and substitutions are performed, so you can write something like `<query short="{column1} = {column2}">select count(*) from table where {column1} > {column2}</query>`, to mark only a particular combination of variables as short.
|
||||
|
||||
This table shows queries for which the `short` marking is not consistent with the actual query run time -- i.e., a query runs for a normal time but is marked as `short`, or it runs faster than normal but is not marked as `short`.
|
||||
|
||||
#### Partial Queries
|
||||
Action required for the cells marked in red.
|
||||
|
@ -468,14 +468,14 @@ if args.report == 'main':
|
||||
return
|
||||
|
||||
columns = [
|
||||
'Test', #0
|
||||
'Wall clock time, s', #1
|
||||
'Total client time, s', #2
|
||||
'Total queries', #3
|
||||
'Longest query<br>(sum for all runs), s', #4
|
||||
'Avg wall clock time<br>(sum for all runs), s', #5
|
||||
'Shortest query<br>(sum for all runs), s', #6
|
||||
'', # Runs #7
|
||||
'Test', #0
|
||||
'Wall clock time, entire test, s', #1
|
||||
'Total client time for measured query runs, s', #2
|
||||
'Queries', #3
|
||||
'Longest query, total for measured runs, s', #4
|
||||
'Wall clock time per query, s', #5
|
||||
'Shortest query, total for measured runs, s', #6
|
||||
'', # Runs #7
|
||||
]
|
||||
attrs = ['' for c in columns]
|
||||
attrs[7] = None
|
||||
|
@ -33,5 +33,8 @@ RUN mkdir -p /tmp/clickhouse-odbc-tmp \
|
||||
ENV TZ=Europe/Moscow
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
ENV NUM_TRIES=1
|
||||
ENV MAX_RUN_TIME=0
|
||||
|
||||
COPY run.sh /
|
||||
CMD ["/bin/bash", "/run.sh"]
|
||||
|
@ -1,6 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e -x
|
||||
# fail on errors, verbose and export all env variables
|
||||
set -e -x -a
|
||||
|
||||
dpkg -i package_folder/clickhouse-common-static_*.deb
|
||||
dpkg -i package_folder/clickhouse-common-static-dbg_*.deb
|
||||
@ -16,9 +17,17 @@ service clickhouse-server start && sleep 5
|
||||
if grep -q -- "--use-skip-list" /usr/bin/clickhouse-test; then
|
||||
SKIP_LIST_OPT="--use-skip-list"
|
||||
fi
|
||||
|
||||
# We can have several additional options so we path them as array because it's
|
||||
# more idiologically correct.
|
||||
read -ra ADDITIONAL_OPTIONS <<< "${ADDITIONAL_OPTIONS:-}"
|
||||
|
||||
clickhouse-test --testname --shard --zookeeper --hung-check --print-time "$SKIP_LIST_OPT" "${ADDITIONAL_OPTIONS[@]}" "$SKIP_TESTS_OPTION" 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee test_output/test_result.txt
|
||||
function run_tests()
|
||||
{
|
||||
for i in $(seq 1 $NUM_TRIES); do
|
||||
clickhouse-test --testname --shard --zookeeper --hung-check --print-time "$SKIP_LIST_OPT" "${ADDITIONAL_OPTIONS[@]}" "$SKIP_TESTS_OPTION" 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee -a test_output/test_result.txt
|
||||
done
|
||||
}
|
||||
|
||||
export -f run_tests
|
||||
|
||||
timeout $MAX_RUN_TIME bash -c run_tests ||:
|
||||
|
@ -305,6 +305,10 @@ When enabled, replace empty input fields in TSV with default values. For complex
|
||||
|
||||
Disabled by default.
|
||||
|
||||
## input_format_tsv_enum_as_number {#settings-input_format_tsv_enum_as_number}
|
||||
|
||||
For TSV input format switches to parsing enum values as enum ids.
|
||||
|
||||
## input_format_null_as_default {#settings-input-format-null-as-default}
|
||||
|
||||
Enables or disables using default values if input data contain `NULL`, but the data type of the corresponding column in not `Nullable(T)` (for text input formats).
|
||||
@ -1161,6 +1165,10 @@ The character is interpreted as a delimiter in the CSV data. By default, the del
|
||||
|
||||
For CSV input format enables or disables parsing of unquoted `NULL` as literal (synonym for `\N`).
|
||||
|
||||
## input_format_csv_enum_as_number {#settings-input_format_csv_enum_as_number}
|
||||
|
||||
For CSV input format switches to parsing enum values as enum ids.
|
||||
|
||||
## output_format_csv_crlf_end_of_line {#settings-output-format-csv-crlf-end-of-line}
|
||||
|
||||
Use DOS/Windows-style line separator (CRLF) in CSV instead of Unix style (LF).
|
||||
@ -1398,6 +1406,17 @@ Possible values:
|
||||
|
||||
Default value: 0
|
||||
|
||||
## allow_nondeterministic_optimize_skip_unused_shards {#allow-nondeterministic-optimize-skip-unused-shards}
|
||||
|
||||
Allow nondeterministic (like `rand` or `dictGet`, since later has some caveats with updates) functions in sharding key.
|
||||
|
||||
Possible values:
|
||||
|
||||
- 0 — Disallowed.
|
||||
- 1 — Allowed.
|
||||
|
||||
Default value: 0
|
||||
|
||||
## optimize_skip_unused_shards_nesting {#optimize-skip-unused-shards-nesting}
|
||||
|
||||
Controls [`optimize_skip_unused_shards`](#optimize-skip-unused-shards) (hence still requires [`optimize_skip_unused_shards`](#optimize-skip-unused-shards)) depends on the nesting level of the distributed query (case when you have `Distributed` table that look into another `Distributed` table).
|
||||
|
@ -34,6 +34,7 @@ ClickHouse не удаляет данные из таблица автомати
|
||||
- `event_date` ([Date](../../sql-reference/data-types/date.md)) — дата начала запроса.
|
||||
- `event_time` ([DateTime](../../sql-reference/data-types/datetime.md)) — время начала запроса.
|
||||
- `query_start_time` ([DateTime](../../sql-reference/data-types/datetime.md)) — время начала обработки запроса.
|
||||
- `query_start_time_microseconds` ([DateTime64](../../sql-reference/data-types/datetime64.md)) — время начала обработки запроса с точностью до микросекунд.
|
||||
- `query_duration_ms` ([UInt64](../../sql-reference/data-types/int-uint.md#uint-ranges)) — длительность выполнения запроса в миллисекундах.
|
||||
- `read_rows` ([UInt64](../../sql-reference/data-types/int-uint.md#uint-ranges)) — Общее количество строк, считанных из всех таблиц и табличных функций, участвующих в запросе. Включает в себя обычные подзапросы, подзапросы для `IN` и `JOIN`. Для распределенных запросов `read_rows` включает в себя общее количество строк, прочитанных на всех репликах. Каждая реплика передает собственное значение `read_rows`, а сервер-инициатор запроса суммирует все полученные и локальные значения. Объемы кэша не учитываюся.
|
||||
- `read_bytes` ([UInt64](../../sql-reference/data-types/int-uint.md#uint-ranges)) — Общее количество байтов, считанных из всех таблиц и табличных функций, участвующих в запросе. Включает в себя обычные подзапросы, подзапросы для `IN` и `JOIN`. Для распределенных запросов `read_bytes` включает в себя общее количество байтов, прочитанных на всех репликах. Каждая реплика передает собственное значение `read_bytes`, а сервер-инициатор запроса суммирует все полученные и локальные значения. Объемы кэша не учитываюся.
|
||||
|
@ -16,6 +16,7 @@ ClickHouse не удаляет данные из таблицы автомати
|
||||
- `event_date` ([Date](../../sql-reference/data-types/date.md)) — дата завершения выполнения запроса потоком.
|
||||
- `event_time` ([DateTime](../../sql-reference/data-types/datetime.md)) — дата и время завершения выполнения запроса потоком.
|
||||
- `query_start_time` ([DateTime](../../sql-reference/data-types/datetime.md)) — время начала обработки запроса.
|
||||
- `query_start_time_microseconds` ([DateTime64](../../sql-reference/data-types/datetime64.md)) — время начала обработки запроса с точностью до микросекунд.
|
||||
- `query_duration_ms` ([UInt64](../../sql-reference/data-types/int-uint.md#uint-ranges)) — длительность обработки запроса в миллисекундах.
|
||||
- `read_rows` ([UInt64](../../sql-reference/data-types/int-uint.md#uint-ranges)) — количество прочитанных строк.
|
||||
- `read_bytes` ([UInt64](../../sql-reference/data-types/int-uint.md#uint-ranges)) — количество прочитанных байтов.
|
||||
|
@ -14,7 +14,7 @@ Jinja2==2.11.2
|
||||
jinja2-highlight==0.6.1
|
||||
jsmin==2.2.2
|
||||
livereload==2.6.2
|
||||
Markdown==3.2.1
|
||||
Markdown==3.3.2
|
||||
MarkupSafe==1.1.1
|
||||
mkdocs==1.1.2
|
||||
mkdocs-htmlproofer-plugin==0.0.3
|
||||
|
@ -548,11 +548,27 @@ int mainEntryClickHouseInstall(int argc, char ** argv)
|
||||
users_config_file.string(), users_d.string());
|
||||
}
|
||||
|
||||
/// Set capabilities for the binary.
|
||||
/** Set capabilities for the binary.
|
||||
*
|
||||
* 1. Check that "setcap" tool exists.
|
||||
* 2. Check that an arbitrary program with installed capabilities can run.
|
||||
* 3. Set the capabilities.
|
||||
*
|
||||
* The second is important for Docker and systemd-nspawn.
|
||||
* When the container has no capabilities,
|
||||
* but the executable file inside the container has capabilities,
|
||||
* then attempt to run this file will end up with a cryptic "Operation not permitted" message.
|
||||
*/
|
||||
|
||||
#if defined(__linux__)
|
||||
fmt::print("Setting capabilities for clickhouse binary. This is optional.\n");
|
||||
std::string command = fmt::format("command -v setcap && setcap 'cap_net_admin,cap_ipc_lock,cap_sys_nice+ep' {}", main_bin_path.string());
|
||||
std::string command = fmt::format("command -v setcap >/dev/null"
|
||||
" && echo > {0} && chmod a+x {0} && {0} && setcap 'cap_net_admin,cap_ipc_lock,cap_sys_nice+ep' {0} && {0} && rm {0}"
|
||||
" && setcap 'cap_net_admin,cap_ipc_lock,cap_sys_nice+ep' {1}"
|
||||
" || echo \"Cannot set 'net_admin' or 'ipc_lock' or 'sys_nice' capability for clickhouse binary."
|
||||
" This is optional. Taskstats accounting will be disabled."
|
||||
" To enable taskstats accounting you may add the required capability later manually.\"",
|
||||
"/tmp/test_setcap.sh", main_bin_path.string());
|
||||
fmt::print(" {}\n", command);
|
||||
executeScript(command);
|
||||
#endif
|
||||
|
@ -722,18 +722,22 @@
|
||||
-->
|
||||
<format_schema_path>/var/lib/clickhouse/format_schemas/</format_schema_path>
|
||||
|
||||
<!-- Uncomment to use query masking rules.
|
||||
<!-- Default query masking rules, matching lines would be replaced with something else in the logs
|
||||
(both text logs and system.query_log).
|
||||
name - name for the rule (optional)
|
||||
regexp - RE2 compatible regular expression (mandatory)
|
||||
replace - substitution string for sensitive data (optional, by default - six asterisks)
|
||||
-->
|
||||
<query_masking_rules>
|
||||
<rule>
|
||||
<name>hide SSN</name>
|
||||
<regexp>\b\d{3}-\d{2}-\d{4}\b</regexp>
|
||||
<replace>000-00-0000</replace>
|
||||
<name>hide encrypt/decrypt arguments</name>
|
||||
<regexp>((?:aes_)?(?:encrypt|decrypt)(?:_mysql)?)\s*\(\s*(?:'(?:\\'|.)+'|.*?)\s*\)</regexp>
|
||||
<!-- or more secure, but also more invasive:
|
||||
(aes_\w+)\s*\(.*\)
|
||||
-->
|
||||
<replace>\1(???)</replace>
|
||||
</rule>
|
||||
</query_masking_rules>
|
||||
-->
|
||||
|
||||
<!-- Uncomment to use custom http handlers.
|
||||
rules are checked from top to bottom, first match runs the handler
|
||||
|
@ -47,7 +47,7 @@
|
||||
--button-active-color: #F00;
|
||||
--button-active-text-color: #FFF;
|
||||
--misc-text-color: #888;
|
||||
--error-color: #400; /* Light-pink on light-cyan is so neat, I even want to trigger errors to see this cool combination of colors. */
|
||||
--error-color: #400;
|
||||
--table-header-color: #102020;
|
||||
--table-hover-color: #003333;
|
||||
--null-color: #A88;
|
||||
@ -282,6 +282,9 @@
|
||||
|
||||
function post()
|
||||
{
|
||||
/// TODO: Avoid race condition on subsequent requests when responses may come out of order.
|
||||
/// TODO: Check if URL already contains query string (append parameters).
|
||||
|
||||
var url = document.getElementById('url').value +
|
||||
/// Ask server to allow cross-domain requests.
|
||||
'?add_http_cors_header=1' +
|
||||
@ -309,6 +312,7 @@
|
||||
renderUnparsedResult(this.response);
|
||||
}
|
||||
} else {
|
||||
/// TODO: Proper rendering of network errors.
|
||||
renderError(this.response);
|
||||
}
|
||||
} else {
|
||||
@ -376,6 +380,7 @@
|
||||
var is_null = (cell === null);
|
||||
var content = document.createTextNode(is_null ? 'ᴺᵁᴸᴸ' : cell);
|
||||
td.appendChild(content);
|
||||
/// TODO: Execute regexp only once for each column.
|
||||
td.className = response.meta[col_idx].type.match(/^(U?Int|Decimal|Float)/) ? 'right' : 'left';
|
||||
if (is_null) {
|
||||
td.className += ' null';
|
||||
@ -400,6 +405,12 @@
|
||||
{
|
||||
clear();
|
||||
var data = document.getElementById('data-unparsed')
|
||||
|
||||
if (response === '') {
|
||||
/// TODO: Fade or remove previous result when new request will be performed.
|
||||
response = 'Ok.';
|
||||
}
|
||||
|
||||
data.innerText = response;
|
||||
/// inline-block make width adjust to the size of content.
|
||||
data.style.display = 'inline-block';
|
||||
|
@ -143,13 +143,12 @@ void LinearModelData::updateState()
|
||||
|
||||
void LinearModelData::predict(
|
||||
ColumnVector<Float64>::Container & container,
|
||||
ColumnsWithTypeAndName & columns,
|
||||
ColumnsWithTypeAndName & arguments,
|
||||
size_t offset,
|
||||
size_t limit,
|
||||
const ColumnNumbers & arguments,
|
||||
const Context & context) const
|
||||
{
|
||||
gradient_computer->predict(container, columns, offset, limit, arguments, weights, bias, context);
|
||||
gradient_computer->predict(container, arguments, offset, limit, weights, bias, context);
|
||||
}
|
||||
|
||||
void LinearModelData::returnWeights(IColumn & to) const
|
||||
@ -449,15 +448,14 @@ void IWeightsUpdater::addToBatch(
|
||||
|
||||
void LogisticRegression::predict(
|
||||
ColumnVector<Float64>::Container & container,
|
||||
ColumnsWithTypeAndName & columns,
|
||||
ColumnsWithTypeAndName & arguments,
|
||||
size_t offset,
|
||||
size_t limit,
|
||||
const ColumnNumbers & arguments,
|
||||
const std::vector<Float64> & weights,
|
||||
Float64 bias,
|
||||
const Context & /*context*/) const
|
||||
{
|
||||
size_t rows_num = columns[arguments.front()].column->size();
|
||||
size_t rows_num = arguments.front().column->size();
|
||||
|
||||
if (offset > rows_num || offset + limit > rows_num)
|
||||
throw Exception("Invalid offset and limit for LogisticRegression::predict. "
|
||||
@ -468,7 +466,7 @@ void LogisticRegression::predict(
|
||||
|
||||
for (size_t i = 1; i < arguments.size(); ++i)
|
||||
{
|
||||
const ColumnWithTypeAndName & cur_col = columns[arguments[i]];
|
||||
const ColumnWithTypeAndName & cur_col = arguments[i];
|
||||
|
||||
if (!isNativeNumber(cur_col.type))
|
||||
throw Exception("Prediction arguments must have numeric type", ErrorCodes::BAD_ARGUMENTS);
|
||||
@ -518,10 +516,9 @@ void LogisticRegression::compute(
|
||||
|
||||
void LinearRegression::predict(
|
||||
ColumnVector<Float64>::Container & container,
|
||||
ColumnsWithTypeAndName & columns,
|
||||
ColumnsWithTypeAndName & arguments,
|
||||
size_t offset,
|
||||
size_t limit,
|
||||
const ColumnNumbers & arguments,
|
||||
const std::vector<Float64> & weights,
|
||||
Float64 bias,
|
||||
const Context & /*context*/) const
|
||||
@ -531,7 +528,7 @@ void LinearRegression::predict(
|
||||
throw Exception("In predict function number of arguments differs from the size of weights vector", ErrorCodes::LOGICAL_ERROR);
|
||||
}
|
||||
|
||||
size_t rows_num = columns[arguments.front()].column->size();
|
||||
size_t rows_num = arguments.front().column->size();
|
||||
|
||||
if (offset > rows_num || offset + limit > rows_num)
|
||||
throw Exception("Invalid offset and limit for LogisticRegression::predict. "
|
||||
@ -542,7 +539,7 @@ void LinearRegression::predict(
|
||||
|
||||
for (size_t i = 1; i < arguments.size(); ++i)
|
||||
{
|
||||
const ColumnWithTypeAndName & cur_col = columns[arguments[i]];
|
||||
const ColumnWithTypeAndName & cur_col = arguments[i];
|
||||
|
||||
if (!isNativeNumber(cur_col.type))
|
||||
throw Exception("Prediction arguments must have numeric type", ErrorCodes::BAD_ARGUMENTS);
|
||||
|
@ -39,10 +39,9 @@ public:
|
||||
|
||||
virtual void predict(
|
||||
ColumnVector<Float64>::Container & container,
|
||||
ColumnsWithTypeAndName & columns,
|
||||
ColumnsWithTypeAndName & arguments,
|
||||
size_t offset,
|
||||
size_t limit,
|
||||
const ColumnNumbers & arguments,
|
||||
const std::vector<Float64> & weights,
|
||||
Float64 bias,
|
||||
const Context & context) const = 0;
|
||||
@ -65,10 +64,9 @@ public:
|
||||
|
||||
void predict(
|
||||
ColumnVector<Float64>::Container & container,
|
||||
ColumnsWithTypeAndName & columns,
|
||||
ColumnsWithTypeAndName & arguments,
|
||||
size_t offset,
|
||||
size_t limit,
|
||||
const ColumnNumbers & arguments,
|
||||
const std::vector<Float64> & weights,
|
||||
Float64 bias,
|
||||
const Context & context) const override;
|
||||
@ -91,10 +89,9 @@ public:
|
||||
|
||||
void predict(
|
||||
ColumnVector<Float64>::Container & container,
|
||||
ColumnsWithTypeAndName & columns,
|
||||
ColumnsWithTypeAndName & arguments,
|
||||
size_t offset,
|
||||
size_t limit,
|
||||
const ColumnNumbers & arguments,
|
||||
const std::vector<Float64> & weights,
|
||||
Float64 bias,
|
||||
const Context & context) const override;
|
||||
@ -264,10 +261,9 @@ public:
|
||||
|
||||
void predict(
|
||||
ColumnVector<Float64>::Container & container,
|
||||
ColumnsWithTypeAndName & columns,
|
||||
ColumnsWithTypeAndName & arguments,
|
||||
size_t offset,
|
||||
size_t limit,
|
||||
const ColumnNumbers & arguments,
|
||||
const Context & context) const;
|
||||
|
||||
void returnWeights(IColumn & to) const;
|
||||
@ -364,10 +360,9 @@ public:
|
||||
void predictValues(
|
||||
ConstAggregateDataPtr place,
|
||||
IColumn & to,
|
||||
ColumnsWithTypeAndName & columns,
|
||||
ColumnsWithTypeAndName & arguments,
|
||||
size_t offset,
|
||||
size_t limit,
|
||||
const ColumnNumbers & arguments,
|
||||
const Context & context) const override
|
||||
{
|
||||
if (arguments.size() != param_num + 1)
|
||||
@ -382,7 +377,7 @@ public:
|
||||
throw Exception("Cast of column of predictions is incorrect. getReturnTypeToPredict must return same value as it is casted to",
|
||||
ErrorCodes::LOGICAL_ERROR);
|
||||
|
||||
this->data(place).predict(column->getData(), columns, offset, limit, arguments, context);
|
||||
this->data(place).predict(column->getData(), arguments, offset, limit, context);
|
||||
}
|
||||
|
||||
/** This function is called if aggregate function without State modifier is selected in a query.
|
||||
|
@ -21,10 +21,6 @@
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int BAD_ARGUMENTS;
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -138,23 +134,18 @@ public:
|
||||
const auto & value = this->data(place).values;
|
||||
size_t size = this->data(place).size_x;
|
||||
|
||||
if (size < 2)
|
||||
{
|
||||
throw Exception("Aggregate function " + getName() + " requires samples to be of size > 1", ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
//create a copy of values not to format data
|
||||
// create a copy of values not to format data
|
||||
PODArrayWithStackMemory<std::pair<Float64, Float64>, 32> tmp_values;
|
||||
tmp_values.resize(size);
|
||||
for (size_t j = 0; j < size; ++ j)
|
||||
tmp_values[j] = static_cast<std::pair<Float64, Float64>>(value[j]);
|
||||
|
||||
//sort x_values
|
||||
// sort x_values
|
||||
std::sort(std::begin(tmp_values), std::end(tmp_values), ComparePairFirst<std::greater>{});
|
||||
|
||||
for (size_t j = 0; j < size;)
|
||||
{
|
||||
//replace x_values with their ranks
|
||||
// replace x_values with their ranks
|
||||
size_t rank = j + 1;
|
||||
size_t same = 1;
|
||||
size_t cur_sum = rank;
|
||||
@ -166,9 +157,9 @@ public:
|
||||
{
|
||||
// rank of (j + 1)th number
|
||||
rank += 1;
|
||||
same++;
|
||||
++same;
|
||||
cur_sum += rank;
|
||||
j++;
|
||||
++j;
|
||||
}
|
||||
else
|
||||
break;
|
||||
@ -178,16 +169,16 @@ public:
|
||||
Float64 insert_rank = static_cast<Float64>(cur_sum) / same;
|
||||
for (size_t i = cur_start; i <= j; ++i)
|
||||
tmp_values[i].first = insert_rank;
|
||||
j++;
|
||||
++j;
|
||||
}
|
||||
|
||||
//sort y_values
|
||||
// sort y_values
|
||||
std::sort(std::begin(tmp_values), std::end(tmp_values), ComparePairSecond<std::greater>{});
|
||||
|
||||
//replace y_values with their ranks
|
||||
// replace y_values with their ranks
|
||||
for (size_t j = 0; j < size;)
|
||||
{
|
||||
//replace x_values with their ranks
|
||||
// replace x_values with their ranks
|
||||
size_t rank = j + 1;
|
||||
size_t same = 1;
|
||||
size_t cur_sum = rank;
|
||||
@ -199,9 +190,9 @@ public:
|
||||
{
|
||||
// rank of (j + 1)th number
|
||||
rank += 1;
|
||||
same++;
|
||||
++same;
|
||||
cur_sum += rank;
|
||||
j++;
|
||||
++j;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -213,10 +204,10 @@ public:
|
||||
Float64 insert_rank = static_cast<Float64>(cur_sum) / same;
|
||||
for (size_t i = cur_start; i <= j; ++i)
|
||||
tmp_values[i].second = insert_rank;
|
||||
j++;
|
||||
++j;
|
||||
}
|
||||
|
||||
//count d^2 sum
|
||||
// count d^2 sum
|
||||
Float64 answer = static_cast<Float64>(0);
|
||||
for (size_t j = 0; j < size; ++ j)
|
||||
answer += (tmp_values[j].first - tmp_values[j].second) * (tmp_values[j].first - tmp_values[j].second);
|
||||
|
@ -114,10 +114,9 @@ public:
|
||||
virtual void predictValues(
|
||||
ConstAggregateDataPtr /* place */,
|
||||
IColumn & /*to*/,
|
||||
ColumnsWithTypeAndName & /*block*/,
|
||||
ColumnsWithTypeAndName & /*arguments*/,
|
||||
size_t /*offset*/,
|
||||
size_t /*limit*/,
|
||||
const ColumnNumbers & /*arguments*/,
|
||||
const Context & /*context*/) const
|
||||
{
|
||||
throw Exception("Method predictValues is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED);
|
||||
|
@ -161,7 +161,7 @@ MutableColumnPtr ColumnAggregateFunction::convertToValues(MutableColumnPtr colum
|
||||
return res;
|
||||
}
|
||||
|
||||
MutableColumnPtr ColumnAggregateFunction::predictValues(ColumnsWithTypeAndName & block, const ColumnNumbers & arguments, const Context & context) const
|
||||
MutableColumnPtr ColumnAggregateFunction::predictValues(ColumnsWithTypeAndName & arguments, const Context & context) const
|
||||
{
|
||||
MutableColumnPtr res = func->getReturnTypeToPredict()->createColumn();
|
||||
res->reserve(data.size());
|
||||
@ -172,7 +172,7 @@ MutableColumnPtr ColumnAggregateFunction::predictValues(ColumnsWithTypeAndName &
|
||||
if (data.size() == 1)
|
||||
{
|
||||
/// Case for const column. Predict using single model.
|
||||
machine_learning_function->predictValues(data[0], *res, block, 0, block[arguments.front()].column->size(), arguments, context);
|
||||
machine_learning_function->predictValues(data[0], *res, arguments, 0, arguments.front().column->size(), context);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -180,7 +180,7 @@ MutableColumnPtr ColumnAggregateFunction::predictValues(ColumnsWithTypeAndName &
|
||||
size_t row_num = 0;
|
||||
for (auto * val : data)
|
||||
{
|
||||
machine_learning_function->predictValues(val, *res, block, row_num, 1, arguments, context);
|
||||
machine_learning_function->predictValues(val, *res, arguments, row_num, 1, context);
|
||||
++row_num;
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ public:
|
||||
const char * getFamilyName() const override { return "AggregateFunction"; }
|
||||
TypeIndex getDataType() const override { return TypeIndex::AggregateFunction; }
|
||||
|
||||
MutableColumnPtr predictValues(ColumnsWithTypeAndName & block, const ColumnNumbers & arguments, const Context & context) const;
|
||||
MutableColumnPtr predictValues(ColumnsWithTypeAndName & arguments, const Context & context) const;
|
||||
|
||||
size_t size() const override
|
||||
{
|
||||
|
@ -188,15 +188,10 @@ ColumnWithTypeAndName ColumnFunction::reduce() const
|
||||
"arguments but " + toString(captured) + " columns were captured.", ErrorCodes::LOGICAL_ERROR);
|
||||
|
||||
auto columns = captured_columns;
|
||||
columns.emplace_back(ColumnWithTypeAndName {nullptr, function->getReturnType(), ""});
|
||||
ColumnWithTypeAndName res{nullptr, function->getResultType(), ""};
|
||||
|
||||
ColumnNumbers arguments(captured_columns.size());
|
||||
for (size_t i = 0; i < captured_columns.size(); ++i)
|
||||
arguments[i] = i;
|
||||
|
||||
function->execute(columns, arguments, captured_columns.size(), size_);
|
||||
|
||||
return columns[captured_columns.size()];
|
||||
res.column = function->execute(columns, res.type, size_);
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -634,4 +634,10 @@ void ColumnString::protect()
|
||||
getOffsets().protect();
|
||||
}
|
||||
|
||||
void ColumnString::validate() const
|
||||
{
|
||||
if (!offsets.empty() && offsets.back() != chars.size())
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "ColumnString validation failed: size mismatch (internal logical error) {} != {}", offsets.back(), chars.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -267,6 +267,9 @@ public:
|
||||
|
||||
Offsets & getOffsets() { return offsets; }
|
||||
const Offsets & getOffsets() const { return offsets; }
|
||||
|
||||
// Throws an exception if offsets/chars are messed up
|
||||
void validate() const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -510,6 +510,8 @@ namespace ErrorCodes
|
||||
extern const int ROW_AND_ROWS_TOGETHER = 544;
|
||||
extern const int FIRST_AND_NEXT_TOGETHER = 545;
|
||||
extern const int NO_ROW_DELIMITER = 546;
|
||||
extern const int INVALID_RAID_TYPE = 547;
|
||||
extern const int UNKNOWN_VOLUME = 548;
|
||||
|
||||
extern const int KEEPER_EXCEPTION = 999;
|
||||
extern const int POCO_EXCEPTION = 1000;
|
||||
|
@ -30,6 +30,8 @@ namespace ProfileEvents
|
||||
|
||||
static constexpr size_t log_peak_memory_usage_every = 1ULL << 30;
|
||||
|
||||
thread_local bool MemoryTracker::BlockerInThread::is_blocked = false;
|
||||
|
||||
MemoryTracker total_memory_tracker(nullptr, VariableContext::Global);
|
||||
|
||||
|
||||
@ -56,13 +58,15 @@ MemoryTracker::~MemoryTracker()
|
||||
void MemoryTracker::logPeakMemoryUsage() const
|
||||
{
|
||||
const auto * description = description_ptr.load(std::memory_order_relaxed);
|
||||
LOG_DEBUG(&Poco::Logger::get("MemoryTracker"), "Peak memory usage{}: {}.", (description ? " " + std::string(description) : ""), ReadableSize(peak));
|
||||
LOG_DEBUG(&Poco::Logger::get("MemoryTracker"),
|
||||
"Peak memory usage{}: {}.", (description ? " " + std::string(description) : ""), ReadableSize(peak));
|
||||
}
|
||||
|
||||
void MemoryTracker::logMemoryUsage(Int64 current) const
|
||||
{
|
||||
const auto * description = description_ptr.load(std::memory_order_relaxed);
|
||||
LOG_DEBUG(&Poco::Logger::get("MemoryTracker"), "Current memory usage{}: {}.", (description ? " " + std::string(description) : ""), ReadableSize(current));
|
||||
LOG_DEBUG(&Poco::Logger::get("MemoryTracker"),
|
||||
"Current memory usage{}: {}.", (description ? " " + std::string(description) : ""), ReadableSize(current));
|
||||
}
|
||||
|
||||
|
||||
@ -71,7 +75,7 @@ void MemoryTracker::alloc(Int64 size)
|
||||
if (size < 0)
|
||||
throw DB::Exception(DB::ErrorCodes::LOGICAL_ERROR, "Negative size ({}) is passed to MemoryTracker. It is a bug.", size);
|
||||
|
||||
if (blocker.isCancelled())
|
||||
if (BlockerInThread::isBlocked())
|
||||
return;
|
||||
|
||||
/** Using memory_order_relaxed means that if allocations are done simultaneously,
|
||||
@ -86,12 +90,15 @@ void MemoryTracker::alloc(Int64 size)
|
||||
Int64 current_hard_limit = hard_limit.load(std::memory_order_relaxed);
|
||||
Int64 current_profiler_limit = profiler_limit.load(std::memory_order_relaxed);
|
||||
|
||||
/// Cap the limit to the total_memory_tracker, since it may include some drift.
|
||||
/// Cap the limit to the total_memory_tracker, since it may include some drift
|
||||
/// for user-level memory tracker.
|
||||
///
|
||||
/// And since total_memory_tracker is reset to the process resident
|
||||
/// memory peridically (in AsynchronousMetrics::update()), any limit can be
|
||||
/// capped to it, to avoid possible drift.
|
||||
if (unlikely(current_hard_limit && will_be > current_hard_limit))
|
||||
if (unlikely(current_hard_limit
|
||||
&& will_be > current_hard_limit
|
||||
&& level == VariableContext::User))
|
||||
{
|
||||
Int64 total_amount = total_memory_tracker.get();
|
||||
if (amount > total_amount)
|
||||
@ -104,10 +111,8 @@ void MemoryTracker::alloc(Int64 size)
|
||||
std::bernoulli_distribution fault(fault_probability);
|
||||
if (unlikely(fault_probability && fault(thread_local_rng)))
|
||||
{
|
||||
free(size);
|
||||
|
||||
/// Prevent recursion. Exception::ctor -> std::string -> new[] -> MemoryTracker::alloc
|
||||
auto untrack_lock = blocker.cancel(); // NOLINT
|
||||
BlockerInThread untrack_lock;
|
||||
|
||||
ProfileEvents::increment(ProfileEvents::QueryMemoryLimitExceeded);
|
||||
std::stringstream message;
|
||||
@ -118,12 +123,13 @@ void MemoryTracker::alloc(Int64 size)
|
||||
<< " (attempt to allocate chunk of " << size << " bytes)"
|
||||
<< ", maximum: " << formatReadableSizeWithBinarySuffix(current_hard_limit);
|
||||
|
||||
amount.fetch_sub(size, std::memory_order_relaxed);
|
||||
throw DB::Exception(message.str(), DB::ErrorCodes::MEMORY_LIMIT_EXCEEDED);
|
||||
}
|
||||
|
||||
if (unlikely(current_profiler_limit && will_be > current_profiler_limit))
|
||||
{
|
||||
auto no_track = blocker.cancel();
|
||||
BlockerInThread untrack_lock;
|
||||
DB::TraceCollector::collect(DB::TraceType::Memory, StackTrace(), size);
|
||||
setOrRaiseProfilerLimit((will_be + profiler_step - 1) / profiler_step * profiler_step);
|
||||
}
|
||||
@ -131,16 +137,14 @@ void MemoryTracker::alloc(Int64 size)
|
||||
std::bernoulli_distribution sample(sample_probability);
|
||||
if (unlikely(sample_probability && sample(thread_local_rng)))
|
||||
{
|
||||
auto no_track = blocker.cancel();
|
||||
BlockerInThread untrack_lock;
|
||||
DB::TraceCollector::collect(DB::TraceType::MemorySample, StackTrace(), size);
|
||||
}
|
||||
|
||||
if (unlikely(current_hard_limit && will_be > current_hard_limit))
|
||||
{
|
||||
free(size);
|
||||
|
||||
/// Prevent recursion. Exception::ctor -> std::string -> new[] -> MemoryTracker::alloc
|
||||
auto no_track = blocker.cancel(); // NOLINT
|
||||
BlockerInThread untrack_lock;
|
||||
|
||||
ProfileEvents::increment(ProfileEvents::QueryMemoryLimitExceeded);
|
||||
std::stringstream message;
|
||||
@ -151,6 +155,7 @@ void MemoryTracker::alloc(Int64 size)
|
||||
<< " (attempt to allocate chunk of " << size << " bytes)"
|
||||
<< ", maximum: " << formatReadableSizeWithBinarySuffix(current_hard_limit);
|
||||
|
||||
amount.fetch_sub(size, std::memory_order_relaxed);
|
||||
throw DB::Exception(message.str(), DB::ErrorCodes::MEMORY_LIMIT_EXCEEDED);
|
||||
}
|
||||
|
||||
@ -177,13 +182,13 @@ void MemoryTracker::updatePeak(Int64 will_be)
|
||||
|
||||
void MemoryTracker::free(Int64 size)
|
||||
{
|
||||
if (blocker.isCancelled())
|
||||
if (BlockerInThread::isBlocked())
|
||||
return;
|
||||
|
||||
std::bernoulli_distribution sample(sample_probability);
|
||||
if (unlikely(sample_probability && sample(thread_local_rng)))
|
||||
{
|
||||
auto no_track = blocker.cancel();
|
||||
BlockerInThread untrack_lock;
|
||||
DB::TraceCollector::collect(DB::TraceType::MemorySample, StackTrace(), -size);
|
||||
}
|
||||
|
||||
@ -298,11 +303,3 @@ namespace CurrentMemoryTracker
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DB::SimpleActionLock getCurrentMemoryTrackerActionLock()
|
||||
{
|
||||
auto * memory_tracker = DB::CurrentThread::getMemoryTracker();
|
||||
if (!memory_tracker)
|
||||
return {};
|
||||
return memory_tracker->blocker.cancel();
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
#include <atomic>
|
||||
#include <common/types.h>
|
||||
#include <Common/CurrentMetrics.h>
|
||||
#include <Common/SimpleActionBlocker.h>
|
||||
#include <Common/VariableContext.h>
|
||||
|
||||
|
||||
@ -131,8 +130,18 @@ public:
|
||||
/// Prints info about peak memory consumption into log.
|
||||
void logPeakMemoryUsage() const;
|
||||
|
||||
/// To be able to temporarily stop memory tracker
|
||||
DB::SimpleActionBlocker blocker;
|
||||
/// To be able to temporarily stop memory tracking from current thread.
|
||||
struct BlockerInThread
|
||||
{
|
||||
private:
|
||||
BlockerInThread(const BlockerInThread &) = delete;
|
||||
BlockerInThread & operator=(const BlockerInThread &) = delete;
|
||||
static thread_local bool is_blocked;
|
||||
public:
|
||||
BlockerInThread() { is_blocked = true; }
|
||||
~BlockerInThread() { is_blocked = false; }
|
||||
static bool isBlocked() { return is_blocked; }
|
||||
};
|
||||
};
|
||||
|
||||
extern MemoryTracker total_memory_tracker;
|
||||
@ -145,7 +154,3 @@ namespace CurrentMemoryTracker
|
||||
void realloc(Int64 old_size, Int64 new_size);
|
||||
void free(Int64 size);
|
||||
}
|
||||
|
||||
|
||||
/// Holding this object will temporarily disable memory tracking.
|
||||
DB::SimpleActionLock getCurrentMemoryTrackerActionLock();
|
||||
|
@ -164,6 +164,8 @@ public:
|
||||
void detachQuery(bool exit_if_already_detached = false, bool thread_exits = false);
|
||||
|
||||
protected:
|
||||
void applyQuerySettings();
|
||||
|
||||
void initPerformanceCounters();
|
||||
|
||||
void initQueryProfiler();
|
||||
|
@ -60,27 +60,17 @@ public:
|
||||
using ArrayA = typename ColVecA::Container;
|
||||
using ArrayB = typename ColVecB::Container;
|
||||
|
||||
DecimalComparison(ColumnsWithTypeAndName & data, size_t result, const ColumnWithTypeAndName & col_left, const ColumnWithTypeAndName & col_right)
|
||||
{
|
||||
if (!apply(data, result, col_left, col_right))
|
||||
throw Exception("Wrong decimal comparison with " + col_left.type->getName() + " and " + col_right.type->getName(),
|
||||
ErrorCodes::LOGICAL_ERROR);
|
||||
}
|
||||
|
||||
static bool apply(ColumnsWithTypeAndName & data, size_t result [[maybe_unused]],
|
||||
const ColumnWithTypeAndName & col_left, const ColumnWithTypeAndName & col_right)
|
||||
static ColumnPtr apply(const ColumnWithTypeAndName & col_left, const ColumnWithTypeAndName & col_right)
|
||||
{
|
||||
if constexpr (_actual)
|
||||
{
|
||||
ColumnPtr c_res;
|
||||
Shift shift = getScales<A, B>(col_left.type, col_right.type);
|
||||
|
||||
c_res = applyWithScale(col_left.column, col_right.column, shift);
|
||||
if (c_res)
|
||||
data[result].column = std::move(c_res);
|
||||
return true;
|
||||
return applyWithScale(col_left.column, col_right.column, shift);
|
||||
}
|
||||
return false;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool compare(A a, B b, UInt32 scale_a, UInt32 scale_b)
|
||||
|
@ -111,6 +111,7 @@ class IColumn;
|
||||
M(UInt64, distributed_group_by_no_merge, 0, "If 1, Do not merge aggregation states from different servers for distributed query processing - in case it is for certain that there are different keys on different shards. If 2 - same as 1 but also apply ORDER BY and LIMIT stages", 0) \
|
||||
M(Bool, optimize_distributed_group_by_sharding_key, false, "Optimize GROUP BY sharding_key queries (by avodiing costly aggregation on the initiator server).", 0) \
|
||||
M(Bool, optimize_skip_unused_shards, false, "Assumes that data is distributed by sharding_key. Optimization to skip unused shards if SELECT query filters by sharding_key.", 0) \
|
||||
M(Bool, allow_nondeterministic_optimize_skip_unused_shards, false, "Allow non-deterministic functions (includes dictGet) in sharding_key for optimize_skip_unused_shards", 0) \
|
||||
M(UInt64, force_optimize_skip_unused_shards, 0, "Throw an exception if unused shards cannot be skipped (1 - throw only if the table has the sharding key, 2 - always throw.", 0) \
|
||||
M(UInt64, optimize_skip_unused_shards_nesting, 0, "Same as optimize_skip_unused_shards, but accept nesting level until which it will work.", 0) \
|
||||
M(UInt64, force_optimize_skip_unused_shards_nesting, 0, "Same as force_optimize_skip_unused_shards, but accept nesting level until which it will work.", 0) \
|
||||
@ -153,6 +154,7 @@ class IColumn;
|
||||
\
|
||||
M(DistributedProductMode, distributed_product_mode, DistributedProductMode::DENY, "How are distributed subqueries performed inside IN or JOIN sections?", IMPORTANT) \
|
||||
\
|
||||
M(UInt64, max_concurrent_queries_for_all_users, 0, "The maximum number of concurrent requests for all users.", 0) \
|
||||
M(UInt64, max_concurrent_queries_for_user, 0, "The maximum number of concurrent requests per user.", 0) \
|
||||
\
|
||||
M(Bool, insert_deduplicate, true, "For INSERT queries in the replicated table, specifies that deduplication of insertings blocks should be performed", 0) \
|
||||
@ -411,12 +413,14 @@ class IColumn;
|
||||
M(Bool, format_csv_allow_double_quotes, 1, "If it is set to true, allow strings in double quotes.", 0) \
|
||||
M(Bool, output_format_csv_crlf_end_of_line, false, "If it is set true, end of line in CSV format will be \\r\\n instead of \\n.", 0) \
|
||||
M(Bool, input_format_csv_unquoted_null_literal_as_null, false, "Consider unquoted NULL literal as \\N", 0) \
|
||||
M(Bool, input_format_csv_enum_as_number, false, "Treat inserted enum values in CSV formats as enum indices \\N", 0) \
|
||||
M(Bool, input_format_skip_unknown_fields, false, "Skip columns with unknown names from input data (it works for JSONEachRow, CSVWithNames, TSVWithNames and TSKV formats).", 0) \
|
||||
M(Bool, input_format_with_names_use_header, true, "For TSVWithNames and CSVWithNames input formats this controls whether format parser is to assume that column data appear in the input exactly as they are specified in the header.", 0) \
|
||||
M(Bool, input_format_import_nested_json, false, "Map nested JSON data to nested tables (it works for JSONEachRow format).", 0) \
|
||||
M(Bool, optimize_aggregators_of_group_by_keys, true, "Eliminates min/max/any/anyLast aggregators of GROUP BY keys in SELECT section", 0) \
|
||||
M(Bool, input_format_defaults_for_omitted_fields, true, "For input data calculate default expressions for omitted fields (it works for JSONEachRow, CSV and TSV formats).", IMPORTANT) \
|
||||
M(Bool, input_format_tsv_empty_as_default, false, "Treat empty fields in TSV input as default values.", 0) \
|
||||
M(Bool, input_format_tsv_enum_as_number, false, "Treat inserted enum values in TSV formats as enum indices \\N", 0) \
|
||||
M(Bool, input_format_null_as_default, false, "For text input formats initialize null fields with default values if data type of this field is not nullable", 0) \
|
||||
\
|
||||
M(DateTimeInputFormat, date_time_input_format, FormatSettings::DateTimeInputFormat::Basic, "Method to read DateTime from text input formats. Possible values: 'basic' and 'best_effort'.", 0) \
|
||||
|
@ -146,12 +146,17 @@ void DataTypeEnum<Type>::serializeTextEscaped(const IColumn & column, size_t row
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void DataTypeEnum<Type>::deserializeTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings &) const
|
||||
void DataTypeEnum<Type>::deserializeTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const
|
||||
{
|
||||
/// NOTE It would be nice to do without creating a temporary object - at least extract std::string out.
|
||||
std::string field_name;
|
||||
readEscapedString(field_name, istr);
|
||||
assert_cast<ColumnType &>(column).getData().push_back(getValue(StringRef(field_name)));
|
||||
if (settings.tsv.input_format_enum_as_number)
|
||||
assert_cast<ColumnType &>(column).getData().push_back(readValue(istr));
|
||||
else
|
||||
{
|
||||
/// NOTE It would be nice to do without creating a temporary object - at least extract std::string out.
|
||||
std::string field_name;
|
||||
readEscapedString(field_name, istr);
|
||||
assert_cast<ColumnType &>(column).getData().push_back(getValue(StringRef(field_name)));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
@ -169,11 +174,16 @@ void DataTypeEnum<Type>::deserializeTextQuoted(IColumn & column, ReadBuffer & is
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void DataTypeEnum<Type>::deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings &) const
|
||||
void DataTypeEnum<Type>::deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const
|
||||
{
|
||||
std::string field_name;
|
||||
readString(field_name, istr);
|
||||
assert_cast<ColumnType &>(column).getData().push_back(getValue(StringRef(field_name)));
|
||||
if (settings.tsv.input_format_enum_as_number)
|
||||
assert_cast<ColumnType &>(column).getData().push_back(readValue(istr));
|
||||
else
|
||||
{
|
||||
std::string field_name;
|
||||
readString(field_name, istr);
|
||||
assert_cast<ColumnType &>(column).getData().push_back(getValue(StringRef(field_name)));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
@ -191,9 +201,14 @@ void DataTypeEnum<Type>::serializeTextXML(const IColumn & column, size_t row_num
|
||||
template <typename Type>
|
||||
void DataTypeEnum<Type>::deserializeTextJSON(IColumn & column, ReadBuffer & istr, const FormatSettings &) const
|
||||
{
|
||||
std::string field_name;
|
||||
readJSONString(field_name, istr);
|
||||
assert_cast<ColumnType &>(column).getData().push_back(getValue(StringRef(field_name)));
|
||||
if (!istr.eof() && *istr.position() != '"')
|
||||
assert_cast<ColumnType &>(column).getData().push_back(readValue(istr));
|
||||
else
|
||||
{
|
||||
std::string field_name;
|
||||
readJSONString(field_name, istr);
|
||||
assert_cast<ColumnType &>(column).getData().push_back(getValue(StringRef(field_name)));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
@ -205,9 +220,14 @@ void DataTypeEnum<Type>::serializeTextCSV(const IColumn & column, size_t row_num
|
||||
template <typename Type>
|
||||
void DataTypeEnum<Type>::deserializeTextCSV(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const
|
||||
{
|
||||
std::string field_name;
|
||||
readCSVString(field_name, istr, settings.csv);
|
||||
assert_cast<ColumnType &>(column).getData().push_back(getValue(StringRef(field_name)));
|
||||
if (settings.csv.input_format_enum_as_number)
|
||||
assert_cast<ColumnType &>(column).getData().push_back(readValue(istr));
|
||||
else
|
||||
{
|
||||
std::string field_name;
|
||||
readCSVString(field_name, istr, settings.csv);
|
||||
assert_cast<ColumnType &>(column).getData().push_back(getValue(StringRef(field_name)));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
|
@ -66,13 +66,18 @@ public:
|
||||
|
||||
TypeIndex getTypeId() const override { return sizeof(FieldType) == 1 ? TypeIndex::Enum8 : TypeIndex::Enum16; }
|
||||
|
||||
const StringRef & getNameForValue(const FieldType & value) const
|
||||
auto findByValue(const FieldType & value) const
|
||||
{
|
||||
const auto it = value_to_name_map.find(value);
|
||||
if (it == std::end(value_to_name_map))
|
||||
throw Exception{"Unexpected value " + toString(value) + " for type " + getName(), ErrorCodes::BAD_ARGUMENTS};
|
||||
|
||||
return it->second;
|
||||
return it;
|
||||
}
|
||||
|
||||
const StringRef & getNameForValue(const FieldType & value) const
|
||||
{
|
||||
return findByValue(value)->second;
|
||||
}
|
||||
|
||||
FieldType getValue(StringRef field_name) const
|
||||
@ -84,6 +89,13 @@ public:
|
||||
return it->getMapped();
|
||||
}
|
||||
|
||||
FieldType readValue(ReadBuffer & istr) const
|
||||
{
|
||||
FieldType x;
|
||||
readText(x, istr);
|
||||
return findByValue(x)->first;
|
||||
}
|
||||
|
||||
Field castToName(const Field & value_or_name) const override;
|
||||
Field castToValue(const Field & value_or_name) const override;
|
||||
|
||||
|
@ -32,7 +32,7 @@ FileDictionarySource::FileDictionarySource(
|
||||
{
|
||||
const String user_files_path = context.getUserFilesPath();
|
||||
if (!startsWith(filepath, user_files_path))
|
||||
throw Exception("File path " + filepath + " is not inside " + user_files_path, ErrorCodes::PATH_ACCESS_DENIED);
|
||||
throw Exception(ErrorCodes::PATH_ACCESS_DENIED, "File path {} is not inside {}", filepath, user_files_path);
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ BlockInputStreamPtr FileDictionarySource::loadAll()
|
||||
|
||||
std::string FileDictionarySource::toString() const
|
||||
{
|
||||
return "File: " + filepath + ' ' + format;
|
||||
return fmt::format("File: {}, {}", filepath, format);
|
||||
}
|
||||
|
||||
|
||||
|
@ -23,8 +23,11 @@ public:
|
||||
DiskSelector(const Poco::Util::AbstractConfiguration & config, const String & config_prefix, const Context & context);
|
||||
DiskSelector(const DiskSelector & from) : disks(from.disks) { }
|
||||
|
||||
DiskSelectorPtr
|
||||
updateFromConfig(const Poco::Util::AbstractConfiguration & config, const String & config_prefix, const Context & context) const;
|
||||
DiskSelectorPtr updateFromConfig(
|
||||
const Poco::Util::AbstractConfiguration & config,
|
||||
const String & config_prefix,
|
||||
const Context & context
|
||||
) const;
|
||||
|
||||
/// Get disk by name
|
||||
DiskPtr get(const String & name) const;
|
||||
|
@ -9,7 +9,7 @@ namespace DB
|
||||
{
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int EXCESSIVE_ELEMENT_IN_CONFIG;
|
||||
extern const int NO_ELEMENTS_IN_CONFIG;
|
||||
extern const int INCONSISTENT_RESERVATIONS;
|
||||
extern const int NO_RESERVATIONS_PROVIDED;
|
||||
extern const int UNKNOWN_VOLUME_TYPE;
|
||||
@ -51,7 +51,7 @@ IVolume::IVolume(
|
||||
}
|
||||
|
||||
if (disks.empty())
|
||||
throw Exception("Volume must contain at least one disk.", ErrorCodes::EXCESSIVE_ELEMENT_IN_CONFIG);
|
||||
throw Exception("Volume must contain at least one disk", ErrorCodes::NO_ELEMENTS_IN_CONFIG);
|
||||
}
|
||||
|
||||
UInt64 IVolume::getMaxUnreservedFreeSpace() const
|
||||
|
@ -64,6 +64,12 @@ public:
|
||||
virtual DiskPtr getDisk(size_t i) const { return disks[i]; }
|
||||
const Disks & getDisks() const { return disks; }
|
||||
|
||||
/// Returns effective value of whether merges are allowed on this volume (true) or not (false).
|
||||
virtual bool areMergesAvoided() const { return false; }
|
||||
|
||||
/// User setting for enabling and disabling merges on volume.
|
||||
virtual void setAvoidMergesUserOverride(bool /*avoid*/) {}
|
||||
|
||||
protected:
|
||||
Disks disks;
|
||||
const String name;
|
||||
|
@ -8,7 +8,7 @@ namespace DB
|
||||
class SingleDiskVolume : public IVolume
|
||||
{
|
||||
public:
|
||||
SingleDiskVolume(const String & name_, DiskPtr disk): IVolume(name_, {disk})
|
||||
SingleDiskVolume(const String & name_, DiskPtr disk, size_t max_data_part_size_ = 0): IVolume(name_, {disk}, max_data_part_size_)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,13 @@
|
||||
#include <Poco/File.h>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
const auto DEFAULT_STORAGE_POLICY_NAME = "default";
|
||||
const auto DEFAULT_VOLUME_NAME = "default";
|
||||
const auto DEFAULT_DISK_NAME = "default";
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
@ -18,11 +25,14 @@ namespace ErrorCodes
|
||||
{
|
||||
extern const int BAD_ARGUMENTS;
|
||||
extern const int EXCESSIVE_ELEMENT_IN_CONFIG;
|
||||
extern const int NO_ELEMENTS_IN_CONFIG;
|
||||
extern const int UNKNOWN_DISK;
|
||||
extern const int UNKNOWN_POLICY;
|
||||
extern const int UNKNOWN_VOLUME;
|
||||
extern const int LOGICAL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
StoragePolicy::StoragePolicy(
|
||||
String name_,
|
||||
const Poco::Util::AbstractConfiguration & config,
|
||||
@ -30,44 +40,42 @@ StoragePolicy::StoragePolicy(
|
||||
DiskSelectorPtr disks)
|
||||
: name(std::move(name_))
|
||||
{
|
||||
String volumes_prefix = config_prefix + ".volumes";
|
||||
if (!config.has(volumes_prefix))
|
||||
throw Exception("StoragePolicy must contain at least one volume (.volumes)", ErrorCodes::EXCESSIVE_ELEMENT_IN_CONFIG);
|
||||
|
||||
Poco::Util::AbstractConfiguration::Keys keys;
|
||||
config.keys(volumes_prefix, keys);
|
||||
String volumes_prefix = config_prefix + ".volumes";
|
||||
|
||||
if (!config.has(volumes_prefix))
|
||||
{
|
||||
if (name != DEFAULT_STORAGE_POLICY_NAME)
|
||||
throw Exception("Storage policy " + backQuote(name) + " must contain at least one volume (.volumes)", ErrorCodes::NO_ELEMENTS_IN_CONFIG);
|
||||
}
|
||||
else
|
||||
{
|
||||
config.keys(volumes_prefix, keys);
|
||||
}
|
||||
|
||||
for (const auto & attr_name : keys)
|
||||
{
|
||||
if (!std::all_of(attr_name.begin(), attr_name.end(), isWordCharASCII))
|
||||
throw Exception(
|
||||
"Volume name can contain only alphanumeric and '_' (" + attr_name + ")", ErrorCodes::EXCESSIVE_ELEMENT_IN_CONFIG);
|
||||
volumes.push_back(std::make_shared<VolumeJBOD>(attr_name, config, volumes_prefix + "." + attr_name, disks));
|
||||
if (volumes_names.find(attr_name) != volumes_names.end())
|
||||
throw Exception("Volumes names must be unique (" + attr_name + " duplicated)", ErrorCodes::UNKNOWN_POLICY);
|
||||
volumes_names[attr_name] = volumes.size() - 1;
|
||||
"Volume name can contain only alphanumeric and '_' in storage policy " + backQuote(name) + " (" + attr_name + ")", ErrorCodes::EXCESSIVE_ELEMENT_IN_CONFIG);
|
||||
volumes.emplace_back(createVolumeFromConfig(attr_name, config, volumes_prefix + "." + attr_name, disks));
|
||||
}
|
||||
|
||||
if (volumes.empty() && name == DEFAULT_STORAGE_POLICY_NAME)
|
||||
{
|
||||
auto default_volume = std::make_shared<VolumeJBOD>(DEFAULT_VOLUME_NAME, std::vector<DiskPtr>{disks->get(DEFAULT_DISK_NAME)}, 0, false);
|
||||
volumes.emplace_back(std::move(default_volume));
|
||||
}
|
||||
|
||||
if (volumes.empty())
|
||||
throw Exception("StoragePolicy must contain at least one volume.", ErrorCodes::EXCESSIVE_ELEMENT_IN_CONFIG);
|
||||
throw Exception("Storage policy " + backQuote(name) + " must contain at least one volume.", ErrorCodes::NO_ELEMENTS_IN_CONFIG);
|
||||
|
||||
/// Check that disks are unique in Policy
|
||||
std::set<String> disk_names;
|
||||
for (const auto & volume : volumes)
|
||||
{
|
||||
for (const auto & disk : volume->getDisks())
|
||||
{
|
||||
if (disk_names.find(disk->getName()) != disk_names.end())
|
||||
throw Exception(
|
||||
"Duplicate disk '" + disk->getName() + "' in storage policy '" + name + "'", ErrorCodes::EXCESSIVE_ELEMENT_IN_CONFIG);
|
||||
|
||||
disk_names.insert(disk->getName());
|
||||
}
|
||||
}
|
||||
|
||||
move_factor = config.getDouble(config_prefix + ".move_factor", 0.1);
|
||||
const double default_move_factor = volumes.size() > 1 ? 0.1 : 0.0;
|
||||
move_factor = config.getDouble(config_prefix + ".move_factor", default_move_factor);
|
||||
if (move_factor > 1)
|
||||
throw Exception("Disk move factor have to be in [0., 1.] interval, but set to " + toString(move_factor), ErrorCodes::LOGICAL_ERROR);
|
||||
throw Exception("Disk move factor have to be in [0., 1.] interval, but set to " + toString(move_factor) + " in storage policy " + backQuote(name), ErrorCodes::LOGICAL_ERROR);
|
||||
|
||||
buildVolumeIndices();
|
||||
}
|
||||
|
||||
|
||||
@ -75,16 +83,43 @@ StoragePolicy::StoragePolicy(String name_, Volumes volumes_, double move_factor_
|
||||
: volumes(std::move(volumes_)), name(std::move(name_)), move_factor(move_factor_)
|
||||
{
|
||||
if (volumes.empty())
|
||||
throw Exception("StoragePolicy must contain at least one Volume.", ErrorCodes::UNKNOWN_POLICY);
|
||||
throw Exception("Storage policy " + backQuote(name) + " must contain at least one Volume.", ErrorCodes::NO_ELEMENTS_IN_CONFIG);
|
||||
|
||||
if (move_factor > 1)
|
||||
throw Exception("Disk move factor have to be in [0., 1.] interval, but set to " + toString(move_factor), ErrorCodes::LOGICAL_ERROR);
|
||||
throw Exception("Disk move factor have to be in [0., 1.] interval, but set to " + toString(move_factor) + " in storage policy " + backQuote(name), ErrorCodes::LOGICAL_ERROR);
|
||||
|
||||
for (size_t i = 0; i < volumes.size(); ++i)
|
||||
buildVolumeIndices();
|
||||
}
|
||||
|
||||
|
||||
StoragePolicy::StoragePolicy(const StoragePolicy & storage_policy,
|
||||
const Poco::Util::AbstractConfiguration & config,
|
||||
const String & config_prefix,
|
||||
DiskSelectorPtr disks)
|
||||
: StoragePolicy(storage_policy.getName(), config, config_prefix, disks)
|
||||
{
|
||||
for (auto & volume : volumes)
|
||||
{
|
||||
if (volumes_names.find(volumes[i]->getName()) != volumes_names.end())
|
||||
throw Exception("Volumes names must be unique (" + volumes[i]->getName() + " duplicated).", ErrorCodes::UNKNOWN_POLICY);
|
||||
volumes_names[volumes[i]->getName()] = i;
|
||||
if (storage_policy.volume_index_by_volume_name.count(volume->getName()) > 0)
|
||||
{
|
||||
auto old_volume = storage_policy.getVolumeByName(volume->getName());
|
||||
try
|
||||
{
|
||||
auto new_volume = updateVolumeFromConfig(old_volume, config, config_prefix + ".volumes." + volume->getName(), disks);
|
||||
volume = std::move(new_volume);
|
||||
}
|
||||
catch (Exception & e)
|
||||
{
|
||||
/// Default policies are allowed to be missed in configuration.
|
||||
if (e.code() != ErrorCodes::NO_ELEMENTS_IN_CONFIG || storage_policy.getName() != DEFAULT_STORAGE_POLICY_NAME)
|
||||
throw;
|
||||
|
||||
Poco::Util::AbstractConfiguration::Keys keys;
|
||||
config.keys(config_prefix, keys);
|
||||
if (!keys.empty())
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,20 +128,20 @@ bool StoragePolicy::isDefaultPolicy() const
|
||||
{
|
||||
/// Guessing if this policy is default, not 100% correct though.
|
||||
|
||||
if (getName() != "default")
|
||||
if (getName() != DEFAULT_STORAGE_POLICY_NAME)
|
||||
return false;
|
||||
|
||||
if (volumes.size() != 1)
|
||||
return false;
|
||||
|
||||
if (volumes[0]->getName() != "default")
|
||||
if (volumes[0]->getName() != DEFAULT_VOLUME_NAME)
|
||||
return false;
|
||||
|
||||
const auto & disks = volumes[0]->getDisks();
|
||||
if (disks.size() != 1)
|
||||
return false;
|
||||
|
||||
if (disks[0]->getName() != "default")
|
||||
if (disks[0]->getName() != DEFAULT_DISK_NAME)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -128,10 +163,10 @@ DiskPtr StoragePolicy::getAnyDisk() const
|
||||
/// StoragePolicy must contain at least one Volume
|
||||
/// Volume must contain at least one Disk
|
||||
if (volumes.empty())
|
||||
throw Exception("StoragePolicy has no volumes. It's a bug.", ErrorCodes::LOGICAL_ERROR);
|
||||
throw Exception("Storage policy " + backQuote(name) + " has no volumes. It's a bug.", ErrorCodes::LOGICAL_ERROR);
|
||||
|
||||
if (volumes[0]->getDisks().empty())
|
||||
throw Exception("Volume '" + volumes[0]->getName() + "' has no disks. It's a bug.", ErrorCodes::LOGICAL_ERROR);
|
||||
throw Exception("Volume " + backQuote(name) + "." + backQuote(volumes[0]->getName()) + " has no disks. It's a bug.", ErrorCodes::LOGICAL_ERROR);
|
||||
|
||||
return volumes[0]->getDisks()[0];
|
||||
}
|
||||
@ -195,6 +230,24 @@ ReservationPtr StoragePolicy::makeEmptyReservationOnLargestDisk() const
|
||||
}
|
||||
|
||||
|
||||
VolumePtr StoragePolicy::getVolume(size_t index) const
|
||||
{
|
||||
if (index < volume_index_by_volume_name.size())
|
||||
return volumes[index];
|
||||
else
|
||||
throw Exception("No volume with index " + std::to_string(index) + " in storage policy " + backQuote(name), ErrorCodes::UNKNOWN_VOLUME);
|
||||
}
|
||||
|
||||
|
||||
VolumePtr StoragePolicy::getVolumeByName(const String & volume_name) const
|
||||
{
|
||||
auto it = volume_index_by_volume_name.find(volume_name);
|
||||
if (it == volume_index_by_volume_name.end())
|
||||
throw Exception("No such volume " + backQuote(volume_name) + " in storage policy " + backQuote(name), ErrorCodes::UNKNOWN_VOLUME);
|
||||
return getVolume(it->second);
|
||||
}
|
||||
|
||||
|
||||
void StoragePolicy::checkCompatibleWith(const StoragePolicyPtr & new_storage_policy) const
|
||||
{
|
||||
std::unordered_set<String> new_volume_names;
|
||||
@ -204,7 +257,7 @@ void StoragePolicy::checkCompatibleWith(const StoragePolicyPtr & new_storage_pol
|
||||
for (const auto & volume : getVolumes())
|
||||
{
|
||||
if (new_volume_names.count(volume->getName()) == 0)
|
||||
throw Exception("New storage policy shall contain volumes of old one", ErrorCodes::BAD_ARGUMENTS);
|
||||
throw Exception("New storage policy " + backQuote(name) + " shall contain volumes of old one", ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
std::unordered_set<String> new_disk_names;
|
||||
for (const auto & disk : new_storage_policy->getVolumeByName(volume->getName())->getDisks())
|
||||
@ -212,21 +265,46 @@ void StoragePolicy::checkCompatibleWith(const StoragePolicyPtr & new_storage_pol
|
||||
|
||||
for (const auto & disk : volume->getDisks())
|
||||
if (new_disk_names.count(disk->getName()) == 0)
|
||||
throw Exception("New storage policy shall contain disks of old one", ErrorCodes::BAD_ARGUMENTS);
|
||||
throw Exception("New storage policy " + backQuote(name) + " shall contain disks of old one", ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size_t StoragePolicy::getVolumeIndexByDisk(const DiskPtr & disk_ptr) const
|
||||
{
|
||||
for (size_t i = 0; i < volumes.size(); ++i)
|
||||
auto it = volume_index_by_disk_name.find(disk_ptr->getName());
|
||||
if (it != volume_index_by_disk_name.end())
|
||||
return it->second;
|
||||
else
|
||||
throw Exception("No disk " + backQuote(disk_ptr->getName()) + " in policy " + backQuote(name), ErrorCodes::UNKNOWN_DISK);
|
||||
}
|
||||
|
||||
|
||||
void StoragePolicy::buildVolumeIndices()
|
||||
{
|
||||
for (size_t index = 0; index < volumes.size(); ++index)
|
||||
{
|
||||
const auto & volume = volumes[i];
|
||||
const VolumePtr & volume = volumes[index];
|
||||
|
||||
if (volume_index_by_volume_name.find(volume->getName()) != volume_index_by_volume_name.end())
|
||||
throw Exception("Volume names must be unique in storage policy "
|
||||
+ backQuote(name) + " (" + backQuote(volume->getName()) + " is duplicated)"
|
||||
, ErrorCodes::EXCESSIVE_ELEMENT_IN_CONFIG);
|
||||
|
||||
volume_index_by_volume_name[volume->getName()] = index;
|
||||
|
||||
for (const auto & disk : volume->getDisks())
|
||||
if (disk->getName() == disk_ptr->getName())
|
||||
return i;
|
||||
{
|
||||
const String & disk_name = disk->getName();
|
||||
|
||||
if (volume_index_by_disk_name.find(disk_name) != volume_index_by_disk_name.end())
|
||||
throw Exception("Disk names must be unique in storage policy "
|
||||
+ backQuote(name) + " (" + backQuote(disk_name) + " is duplicated)"
|
||||
, ErrorCodes::EXCESSIVE_ELEMENT_IN_CONFIG);
|
||||
|
||||
volume_index_by_disk_name[disk_name] = index;
|
||||
}
|
||||
}
|
||||
throw Exception("No disk " + disk_ptr->getName() + " in policy " + name, ErrorCodes::UNKNOWN_DISK);
|
||||
}
|
||||
|
||||
|
||||
@ -242,44 +320,40 @@ StoragePolicySelector::StoragePolicySelector(
|
||||
{
|
||||
if (!std::all_of(name.begin(), name.end(), isWordCharASCII))
|
||||
throw Exception(
|
||||
"StoragePolicy name can contain only alphanumeric and '_' (" + name + ")", ErrorCodes::EXCESSIVE_ELEMENT_IN_CONFIG);
|
||||
"Storage policy name can contain only alphanumeric and '_' (" + backQuote(name) + ")", ErrorCodes::EXCESSIVE_ELEMENT_IN_CONFIG);
|
||||
|
||||
policies.emplace(name, std::make_shared<StoragePolicy>(name, config, config_prefix + "." + name, disks));
|
||||
LOG_INFO(&Poco::Logger::get("StoragePolicySelector"), "Storage policy {} loaded", backQuote(name));
|
||||
}
|
||||
|
||||
constexpr auto default_storage_policy_name = "default";
|
||||
constexpr auto default_volume_name = "default";
|
||||
constexpr auto default_disk_name = "default";
|
||||
|
||||
/// Add default policy if it's not specified explicetly
|
||||
if (policies.find(default_storage_policy_name) == policies.end())
|
||||
/// Add default policy if it isn't explicitly specified.
|
||||
if (policies.find(DEFAULT_STORAGE_POLICY_NAME) == policies.end())
|
||||
{
|
||||
auto default_volume = std::make_shared<VolumeJBOD>(default_volume_name, std::vector<DiskPtr>{disks->get(default_disk_name)}, 0);
|
||||
|
||||
auto default_policy = std::make_shared<StoragePolicy>(default_storage_policy_name, Volumes{default_volume}, 0.0);
|
||||
policies.emplace(default_storage_policy_name, default_policy);
|
||||
auto default_policy = std::make_shared<StoragePolicy>(DEFAULT_STORAGE_POLICY_NAME, config, config_prefix + "." + DEFAULT_STORAGE_POLICY_NAME, disks);
|
||||
policies.emplace(DEFAULT_STORAGE_POLICY_NAME, std::move(default_policy));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StoragePolicySelectorPtr StoragePolicySelector::updateFromConfig(const Poco::Util::AbstractConfiguration & config, const String & config_prefix, DiskSelectorPtr disks) const
|
||||
{
|
||||
Poco::Util::AbstractConfiguration::Keys keys;
|
||||
config.keys(config_prefix, keys);
|
||||
|
||||
std::shared_ptr<StoragePolicySelector> result = std::make_shared<StoragePolicySelector>(config, config_prefix, disks);
|
||||
|
||||
constexpr auto default_storage_policy_name = "default";
|
||||
|
||||
/// First pass, check.
|
||||
for (const auto & [name, policy] : policies)
|
||||
{
|
||||
if (name != default_storage_policy_name && result->policies.count(name) == 0)
|
||||
if (result->policies.count(name) == 0)
|
||||
throw Exception("Storage policy " + backQuote(name) + " is missing in new configuration", ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
policy->checkCompatibleWith(result->policies[name]);
|
||||
}
|
||||
|
||||
/// Second pass, load.
|
||||
for (const auto & [name, policy] : policies)
|
||||
{
|
||||
result->policies[name] = std::make_shared<StoragePolicy>(*policy, config, config_prefix + "." + name, disks);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -288,7 +362,7 @@ StoragePolicyPtr StoragePolicySelector::get(const String & name) const
|
||||
{
|
||||
auto it = policies.find(name);
|
||||
if (it == policies.end())
|
||||
throw Exception("Unknown StoragePolicy " + name, ErrorCodes::UNKNOWN_POLICY);
|
||||
throw Exception("Unknown storage policy " + backQuote(name), ErrorCodes::UNKNOWN_POLICY);
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <unistd.h>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <Poco/Util/AbstractConfiguration.h>
|
||||
@ -36,6 +37,13 @@ public:
|
||||
|
||||
StoragePolicy(String name_, Volumes volumes_, double move_factor_);
|
||||
|
||||
StoragePolicy(
|
||||
const StoragePolicy & storage_policy,
|
||||
const Poco::Util::AbstractConfiguration & config,
|
||||
const String & config_prefix,
|
||||
DiskSelectorPtr disks
|
||||
);
|
||||
|
||||
bool isDefaultPolicy() const;
|
||||
|
||||
/// Returns disks ordered by volumes priority
|
||||
@ -72,16 +80,10 @@ public:
|
||||
/// which should be kept with help of background moves
|
||||
double getMoveFactor() const { return move_factor; }
|
||||
|
||||
/// Get volume by index from storage_policy
|
||||
VolumePtr getVolume(size_t i) const { return (i < volumes_names.size() ? volumes[i] : VolumePtr()); }
|
||||
/// Get volume by index.
|
||||
VolumePtr getVolume(size_t index) const;
|
||||
|
||||
VolumePtr getVolumeByName(const String & volume_name) const
|
||||
{
|
||||
auto it = volumes_names.find(volume_name);
|
||||
if (it == volumes_names.end())
|
||||
return {};
|
||||
return getVolume(it->second);
|
||||
}
|
||||
VolumePtr getVolumeByName(const String & volume_name) const;
|
||||
|
||||
/// Checks if storage policy can be replaced by another one.
|
||||
void checkCompatibleWith(const StoragePolicyPtr & new_storage_policy) const;
|
||||
@ -89,12 +91,15 @@ public:
|
||||
private:
|
||||
Volumes volumes;
|
||||
const String name;
|
||||
std::map<String, size_t> volumes_names;
|
||||
std::unordered_map<String, size_t> volume_index_by_volume_name;
|
||||
std::unordered_map<String, size_t> volume_index_by_disk_name;
|
||||
|
||||
/// move_factor from interval [0., 1.]
|
||||
/// We move something if disk from this policy
|
||||
/// filled more than total_size * move_factor
|
||||
double move_factor = 0.1; /// by default move factor is 10%
|
||||
|
||||
void buildVolumeIndices();
|
||||
};
|
||||
|
||||
|
||||
|
@ -56,11 +56,23 @@ VolumeJBOD::VolumeJBOD(
|
||||
|
||||
/// Default value is 'true' due to backward compatibility.
|
||||
perform_ttl_move_on_insert = config.getBool(config_prefix + ".perform_ttl_move_on_insert", true);
|
||||
|
||||
are_merges_avoided = config.getBool(config_prefix + ".prefer_not_to_merge", false);
|
||||
}
|
||||
|
||||
VolumeJBOD::VolumeJBOD(const VolumeJBOD & volume_jbod,
|
||||
const Poco::Util::AbstractConfiguration & config,
|
||||
const String & config_prefix,
|
||||
DiskSelectorPtr disk_selector)
|
||||
: VolumeJBOD(volume_jbod.name, config, config_prefix, disk_selector)
|
||||
{
|
||||
are_merges_avoided_user_override = volume_jbod.are_merges_avoided_user_override.load(std::memory_order_relaxed);
|
||||
last_used = volume_jbod.last_used.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
DiskPtr VolumeJBOD::getDisk(size_t /* index */) const
|
||||
{
|
||||
size_t start_from = last_used.fetch_add(1u, std::memory_order_relaxed);
|
||||
size_t start_from = last_used.fetch_add(1u, std::memory_order_acq_rel);
|
||||
size_t index = start_from % disks.size();
|
||||
return disks[index];
|
||||
}
|
||||
@ -73,7 +85,7 @@ ReservationPtr VolumeJBOD::reserve(UInt64 bytes)
|
||||
if (max_data_part_size != 0 && bytes > max_data_part_size)
|
||||
return {};
|
||||
|
||||
size_t start_from = last_used.fetch_add(1u, std::memory_order_relaxed);
|
||||
size_t start_from = last_used.fetch_add(1u, std::memory_order_acq_rel);
|
||||
size_t disks_num = disks.size();
|
||||
for (size_t i = 0; i < disks_num; ++i)
|
||||
{
|
||||
@ -87,4 +99,19 @@ ReservationPtr VolumeJBOD::reserve(UInt64 bytes)
|
||||
return {};
|
||||
}
|
||||
|
||||
bool VolumeJBOD::areMergesAvoided() const
|
||||
{
|
||||
auto are_merges_avoided_user_override_value = are_merges_avoided_user_override.load(std::memory_order_acquire);
|
||||
if (are_merges_avoided_user_override_value)
|
||||
return *are_merges_avoided_user_override_value;
|
||||
else
|
||||
return are_merges_avoided;
|
||||
}
|
||||
|
||||
void VolumeJBOD::setAvoidMergesUserOverride(bool avoid)
|
||||
{
|
||||
are_merges_avoided_user_override.store(avoid, std::memory_order_release);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,10 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include <Disks/IVolume.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
class VolumeJBOD;
|
||||
|
||||
using VolumeJBODPtr = std::shared_ptr<VolumeJBOD>;
|
||||
using VolumesJBOD = std::vector<VolumeJBODPtr>;
|
||||
|
||||
/**
|
||||
* Implements something similar to JBOD (https://en.wikipedia.org/wiki/Non-RAID_drive_architectures#JBOD).
|
||||
* When MergeTree engine wants to write part — it requests VolumeJBOD to reserve space on the next available
|
||||
@ -13,8 +22,9 @@ namespace DB
|
||||
class VolumeJBOD : public IVolume
|
||||
{
|
||||
public:
|
||||
VolumeJBOD(String name_, Disks disks_, UInt64 max_data_part_size_)
|
||||
VolumeJBOD(String name_, Disks disks_, UInt64 max_data_part_size_, bool are_merges_avoided_)
|
||||
: IVolume(name_, disks_, max_data_part_size_)
|
||||
, are_merges_avoided(are_merges_avoided_)
|
||||
{
|
||||
}
|
||||
|
||||
@ -25,6 +35,13 @@ public:
|
||||
DiskSelectorPtr disk_selector
|
||||
);
|
||||
|
||||
VolumeJBOD(
|
||||
const VolumeJBOD & volume_jbod,
|
||||
const Poco::Util::AbstractConfiguration & config,
|
||||
const String & config_prefix,
|
||||
DiskSelectorPtr disk_selector
|
||||
);
|
||||
|
||||
VolumeType getType() const override { return VolumeType::JBOD; }
|
||||
|
||||
/// Always returns next disk (round-robin), ignores argument.
|
||||
@ -38,11 +55,19 @@ public:
|
||||
/// Returns valid reservation or nullptr if there is no space left on any disk.
|
||||
ReservationPtr reserve(UInt64 bytes) override;
|
||||
|
||||
bool areMergesAvoided() const override;
|
||||
|
||||
void setAvoidMergesUserOverride(bool avoid) override;
|
||||
|
||||
/// True if parts on this volume participate in merges according to configuration.
|
||||
bool are_merges_avoided = true;
|
||||
|
||||
private:
|
||||
/// Index of last used disk.
|
||||
mutable std::atomic<size_t> last_used = 0;
|
||||
|
||||
/// True if parts on this volume participate in merges according to START/STOP MERGES ON VOLUME.
|
||||
std::atomic<std::optional<bool>> are_merges_avoided_user_override{std::nullopt};
|
||||
};
|
||||
|
||||
using VolumeJBODPtr = std::shared_ptr<VolumeJBOD>;
|
||||
using VolumesJBOD = std::vector<VolumeJBODPtr>;
|
||||
|
||||
}
|
||||
|
@ -3,18 +3,23 @@
|
||||
#include <Disks/createVolume.h>
|
||||
#include <Disks/VolumeJBOD.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/// Volume which reserserves space on each underlying disk.
|
||||
class VolumeRAID1;
|
||||
|
||||
using VolumeRAID1Ptr = std::shared_ptr<VolumeRAID1>;
|
||||
|
||||
/// Volume which reserves space on each underlying disk.
|
||||
///
|
||||
/// NOTE: Just interface implementation, doesn't used in codebase,
|
||||
/// also not available for user.
|
||||
class VolumeRAID1 : public VolumeJBOD
|
||||
{
|
||||
public:
|
||||
VolumeRAID1(String name_, Disks disks_, UInt64 max_data_part_size_)
|
||||
: VolumeJBOD(name_, disks_, max_data_part_size_)
|
||||
VolumeRAID1(String name_, Disks disks_, UInt64 max_data_part_size_, bool are_merges_avoided_in_config_)
|
||||
: VolumeJBOD(name_, disks_, max_data_part_size_, are_merges_avoided_in_config_)
|
||||
{
|
||||
}
|
||||
|
||||
@ -27,11 +32,18 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
VolumeRAID1(
|
||||
VolumeRAID1 & volume_raid1,
|
||||
const Poco::Util::AbstractConfiguration & config,
|
||||
const String & config_prefix,
|
||||
DiskSelectorPtr disk_selector)
|
||||
: VolumeJBOD(volume_raid1, config, config_prefix, disk_selector)
|
||||
{
|
||||
}
|
||||
|
||||
VolumeType getType() const override { return VolumeType::RAID1; }
|
||||
|
||||
ReservationPtr reserve(UInt64 bytes) override;
|
||||
};
|
||||
|
||||
using VolumeRAID1Ptr = std::shared_ptr<VolumeRAID1>;
|
||||
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ namespace DB
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int UNKNOWN_RAID_TYPE;
|
||||
extern const int INVALID_RAID_TYPE;
|
||||
}
|
||||
|
||||
VolumePtr createVolumeFromReservation(const ReservationPtr & reservation, VolumePtr other_volume)
|
||||
@ -20,12 +21,12 @@ VolumePtr createVolumeFromReservation(const ReservationPtr & reservation, Volume
|
||||
{
|
||||
/// Since reservation on JBOD chooses one of disks and makes reservation there, volume
|
||||
/// for such type of reservation will be with one disk.
|
||||
return std::make_shared<SingleDiskVolume>(other_volume->getName(), reservation->getDisk());
|
||||
return std::make_shared<SingleDiskVolume>(other_volume->getName(), reservation->getDisk(), other_volume->max_data_part_size);
|
||||
}
|
||||
if (other_volume->getType() == VolumeType::RAID1)
|
||||
{
|
||||
auto volume = std::dynamic_pointer_cast<VolumeRAID1>(other_volume);
|
||||
return std::make_shared<VolumeRAID1>(volume->getName(), reservation->getDisks(), volume->max_data_part_size);
|
||||
return std::make_shared<VolumeRAID1>(volume->getName(), reservation->getDisks(), volume->max_data_part_size, volume->are_merges_avoided);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -37,17 +38,31 @@ VolumePtr createVolumeFromConfig(
|
||||
DiskSelectorPtr disk_selector
|
||||
)
|
||||
{
|
||||
auto has_raid_type = config.has(config_prefix + ".raid_type");
|
||||
if (!has_raid_type)
|
||||
{
|
||||
return std::make_shared<VolumeJBOD>(name, config, config_prefix, disk_selector);
|
||||
}
|
||||
String raid_type = config.getString(config_prefix + ".raid_type");
|
||||
String raid_type = config.getString(config_prefix + ".raid_type", "JBOD");
|
||||
if (raid_type == "JBOD")
|
||||
{
|
||||
return std::make_shared<VolumeJBOD>(name, config, config_prefix, disk_selector);
|
||||
}
|
||||
throw Exception("Unknown raid type '" + raid_type + "'", ErrorCodes::UNKNOWN_RAID_TYPE);
|
||||
throw Exception("Unknown RAID type '" + raid_type + "'", ErrorCodes::UNKNOWN_RAID_TYPE);
|
||||
}
|
||||
|
||||
VolumePtr updateVolumeFromConfig(
|
||||
VolumePtr volume,
|
||||
const Poco::Util::AbstractConfiguration & config,
|
||||
const String & config_prefix,
|
||||
DiskSelectorPtr & disk_selector
|
||||
)
|
||||
{
|
||||
String raid_type = config.getString(config_prefix + ".raid_type", "JBOD");
|
||||
if (raid_type == "JBOD")
|
||||
{
|
||||
VolumeJBODPtr volume_jbod = std::dynamic_pointer_cast<VolumeJBOD>(volume);
|
||||
if (!volume_jbod)
|
||||
throw Exception("Invalid RAID type '" + raid_type + "', shall be JBOD", ErrorCodes::INVALID_RAID_TYPE);
|
||||
|
||||
return std::make_shared<VolumeJBOD>(*volume_jbod, config, config_prefix, disk_selector);
|
||||
}
|
||||
throw Exception("Unknown RAID type '" + raid_type + "'", ErrorCodes::UNKNOWN_RAID_TYPE);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ namespace DB
|
||||
{
|
||||
|
||||
VolumePtr createVolumeFromReservation(const ReservationPtr & reservation, VolumePtr other_volume);
|
||||
|
||||
VolumePtr createVolumeFromConfig(
|
||||
String name_,
|
||||
const Poco::Util::AbstractConfiguration & config,
|
||||
@ -13,4 +14,11 @@ VolumePtr createVolumeFromConfig(
|
||||
DiskSelectorPtr disk_selector
|
||||
);
|
||||
|
||||
VolumePtr updateVolumeFromConfig(
|
||||
VolumePtr volume,
|
||||
const Poco::Util::AbstractConfiguration & config,
|
||||
const String & config_prefix,
|
||||
DiskSelectorPtr & disk_selector
|
||||
);
|
||||
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ static FormatSettings getInputFormatSetting(const Settings & settings, const Con
|
||||
format_settings.csv.allow_double_quotes = settings.format_csv_allow_double_quotes;
|
||||
format_settings.csv.unquoted_null_literal_as_null = settings.input_format_csv_unquoted_null_literal_as_null;
|
||||
format_settings.csv.empty_as_default = settings.input_format_defaults_for_omitted_fields;
|
||||
format_settings.csv.input_format_enum_as_number = settings.input_format_csv_enum_as_number;
|
||||
format_settings.null_as_default = settings.input_format_null_as_default;
|
||||
format_settings.values.interpret_expressions = settings.input_format_values_interpret_expressions;
|
||||
format_settings.values.deduce_templates_of_expressions = settings.input_format_values_deduce_templates_of_expressions;
|
||||
@ -63,6 +64,7 @@ static FormatSettings getInputFormatSetting(const Settings & settings, const Con
|
||||
format_settings.template_settings.row_format = settings.format_template_row;
|
||||
format_settings.template_settings.row_between_delimiter = settings.format_template_rows_between_delimiter;
|
||||
format_settings.tsv.empty_as_default = settings.input_format_tsv_empty_as_default;
|
||||
format_settings.tsv.input_format_enum_as_number = settings.input_format_tsv_enum_as_number;
|
||||
format_settings.schema.format_schema = settings.format_schema;
|
||||
format_settings.schema.format_schema_path = context.getFormatSchemaPath();
|
||||
format_settings.schema.is_server = context.hasGlobalContext() && (context.getGlobalContext().getApplicationType() == Context::ApplicationType::SERVER);
|
||||
|
@ -34,6 +34,7 @@ struct FormatSettings
|
||||
bool unquoted_null_literal_as_null = false;
|
||||
bool empty_as_default = false;
|
||||
bool crlf_end_of_line = false;
|
||||
bool input_format_enum_as_number = false;
|
||||
};
|
||||
|
||||
CSV csv;
|
||||
@ -81,6 +82,7 @@ struct FormatSettings
|
||||
bool empty_as_default = false;
|
||||
bool crlf_end_of_line = false;
|
||||
String null_representation = "\\N";
|
||||
bool input_format_enum_as_number = false;
|
||||
};
|
||||
|
||||
TSV tsv;
|
||||
|
@ -92,7 +92,7 @@ struct ToStartOfWeekImpl
|
||||
template <typename FromType, typename ToType, typename Transform>
|
||||
struct Transformer
|
||||
{
|
||||
Transformer(Transform transform_)
|
||||
explicit Transformer(Transform transform_)
|
||||
: transform(std::move(transform_))
|
||||
{}
|
||||
|
||||
@ -116,29 +116,29 @@ template <typename FromDataType, typename ToDataType>
|
||||
struct CustomWeekTransformImpl
|
||||
{
|
||||
template <typename Transform>
|
||||
static void execute(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/, Transform transform = {})
|
||||
static ColumnPtr execute(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/, Transform transform = {})
|
||||
{
|
||||
const auto op = Transformer<typename FromDataType::FieldType, typename ToDataType::FieldType, Transform>{std::move(transform)};
|
||||
|
||||
UInt8 week_mode = DEFAULT_WEEK_MODE;
|
||||
if (arguments.size() > 1)
|
||||
{
|
||||
if (const auto week_mode_column = checkAndGetColumnConst<ColumnUInt8>(columns[arguments[1]].column.get()))
|
||||
if (const auto * week_mode_column = checkAndGetColumnConst<ColumnUInt8>(arguments[1].column.get()))
|
||||
week_mode = week_mode_column->getValue<UInt8>();
|
||||
}
|
||||
|
||||
const DateLUTImpl & time_zone = extractTimeZoneFromFunctionArguments(columns, arguments, 2, 0);
|
||||
const ColumnPtr source_col = columns[arguments[0]].column;
|
||||
const DateLUTImpl & time_zone = extractTimeZoneFromFunctionArguments(arguments, 2, 0);
|
||||
const ColumnPtr source_col = arguments[0].column;
|
||||
if (const auto * sources = checkAndGetColumn<typename FromDataType::ColumnType>(source_col.get()))
|
||||
{
|
||||
auto col_to = ToDataType::ColumnType::create();
|
||||
op.vector(sources->getData(), col_to->getData(), week_mode, time_zone);
|
||||
columns[result].column = std::move(col_to);
|
||||
return col_to;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Exception(
|
||||
"Illegal column " + columns[arguments[0]].column->getName() + " of first argument of function "
|
||||
"Illegal column " + arguments[0].column->getName() + " of first argument of function "
|
||||
+ Transform::name,
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
|
@ -683,25 +683,25 @@ struct Transformer
|
||||
template <typename FromDataType, typename ToDataType, typename Transform>
|
||||
struct DateTimeTransformImpl
|
||||
{
|
||||
static void execute(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/, const Transform & transform = {})
|
||||
static ColumnPtr execute(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t /*input_rows_count*/, const Transform & transform = {})
|
||||
{
|
||||
using Op = Transformer<typename FromDataType::FieldType, typename ToDataType::FieldType, Transform>;
|
||||
|
||||
const DateLUTImpl & time_zone = extractTimeZoneFromFunctionArguments(columns, arguments, 1, 0);
|
||||
const DateLUTImpl & time_zone = extractTimeZoneFromFunctionArguments(arguments, 1, 0);
|
||||
|
||||
const ColumnPtr source_col = columns[arguments[0]].column;
|
||||
const ColumnPtr source_col = arguments[0].column;
|
||||
if (const auto * sources = checkAndGetColumn<typename FromDataType::ColumnType>(source_col.get()))
|
||||
{
|
||||
auto mutable_result_col = columns[result].type->createColumn();
|
||||
auto mutable_result_col = result_type->createColumn();
|
||||
auto * col_to = assert_cast<typename ToDataType::ColumnType *>(mutable_result_col.get());
|
||||
|
||||
Op::vector(sources->getData(), col_to->getData(), time_zone, transform);
|
||||
|
||||
columns[result].column = std::move(mutable_result_col);
|
||||
return mutable_result_col;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of first argument of function " + Transform::name,
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
|
@ -91,14 +91,14 @@ public:
|
||||
return std::make_shared<DataTypeString>();
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
|
||||
{
|
||||
const ColumnPtr column_string = columns[arguments[0]].column;
|
||||
const ColumnPtr column_string = arguments[0].column;
|
||||
const ColumnString * input = checkAndGetColumn<ColumnString>(column_string.get());
|
||||
|
||||
if (!input)
|
||||
throw Exception(
|
||||
"Illegal column " + columns[arguments[0]].column->getName() + " of first argument of function " + getName(),
|
||||
"Illegal column " + arguments[0].column->getName() + " of first argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
auto dst_column = ColumnString::create();
|
||||
@ -111,9 +111,9 @@ public:
|
||||
|
||||
const ColumnString::Offsets & src_offsets = input->getOffsets();
|
||||
|
||||
auto source = input->getChars().data();
|
||||
auto dst = dst_data.data();
|
||||
auto dst_pos = dst;
|
||||
const auto * source = input->getChars().data();
|
||||
auto * dst = dst_data.data();
|
||||
auto * dst_pos = dst;
|
||||
|
||||
size_t src_offset_prev = 0;
|
||||
|
||||
@ -141,7 +141,7 @@ public:
|
||||
{
|
||||
// during decoding character array can be partially polluted
|
||||
// if fail, revert back and clean
|
||||
auto savepoint = dst_pos;
|
||||
auto * savepoint = dst_pos;
|
||||
outlen = _tb64d(reinterpret_cast<const uint8_t *>(source), srclen, reinterpret_cast<uint8_t *>(dst_pos));
|
||||
if (!outlen)
|
||||
{
|
||||
@ -166,7 +166,7 @@ public:
|
||||
|
||||
dst_data.resize(dst_pos - dst);
|
||||
|
||||
columns[result].column = std::move(dst_column);
|
||||
return dst_column;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -613,17 +613,17 @@ class FunctionBinaryArithmetic : public IFunction
|
||||
}
|
||||
|
||||
/// Multiply aggregation state by integer constant: by merging it with itself specified number of times.
|
||||
void executeAggregateMultiply(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const
|
||||
ColumnPtr executeAggregateMultiply(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const
|
||||
{
|
||||
ColumnNumbers new_arguments = arguments;
|
||||
if (WhichDataType(columns[new_arguments[1]].type).isAggregateFunction())
|
||||
ColumnsWithTypeAndName new_arguments = arguments;
|
||||
if (WhichDataType(new_arguments[1].type).isAggregateFunction())
|
||||
std::swap(new_arguments[0], new_arguments[1]);
|
||||
|
||||
if (!isColumnConst(*columns[new_arguments[1]].column))
|
||||
throw Exception{"Illegal column " + columns[new_arguments[1]].column->getName()
|
||||
if (!isColumnConst(*new_arguments[1].column))
|
||||
throw Exception{"Illegal column " + new_arguments[1].column->getName()
|
||||
+ " of argument of aggregation state multiply. Should be integer constant", ErrorCodes::ILLEGAL_COLUMN};
|
||||
|
||||
const IColumn & agg_state_column = *columns[new_arguments[0]].column;
|
||||
const IColumn & agg_state_column = *new_arguments[0].column;
|
||||
bool agg_state_is_const = isColumnConst(agg_state_column);
|
||||
const ColumnAggregateFunction & column = typeid_cast<const ColumnAggregateFunction &>(
|
||||
agg_state_is_const ? assert_cast<const ColumnConst &>(agg_state_column).getDataColumn() : agg_state_column);
|
||||
@ -647,7 +647,7 @@ class FunctionBinaryArithmetic : public IFunction
|
||||
auto & vec_to = column_to->getData();
|
||||
auto & vec_from = column_from->getData();
|
||||
|
||||
UInt64 m = typeid_cast<const ColumnConst *>(columns[new_arguments[1]].column.get())->getValue<UInt64>();
|
||||
UInt64 m = typeid_cast<const ColumnConst *>(new_arguments[1].column.get())->getValue<UInt64>();
|
||||
|
||||
// Since we merge the function states by ourselves, we have to have an
|
||||
// Arena for this. Pass it to the resulting column so that the arena
|
||||
@ -674,16 +674,16 @@ class FunctionBinaryArithmetic : public IFunction
|
||||
}
|
||||
|
||||
if (agg_state_is_const)
|
||||
columns[result].column = ColumnConst::create(std::move(column_to), input_rows_count);
|
||||
return ColumnConst::create(std::move(column_to), input_rows_count);
|
||||
else
|
||||
columns[result].column = std::move(column_to);
|
||||
return column_to;
|
||||
}
|
||||
|
||||
/// Merge two aggregation states together.
|
||||
void executeAggregateAddition(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const
|
||||
ColumnPtr executeAggregateAddition(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const
|
||||
{
|
||||
const IColumn & lhs_column = *columns[arguments[0]].column;
|
||||
const IColumn & rhs_column = *columns[arguments[1]].column;
|
||||
const IColumn & lhs_column = *arguments[0].column;
|
||||
const IColumn & rhs_column = *arguments[1].column;
|
||||
|
||||
bool lhs_is_const = isColumnConst(lhs_column);
|
||||
bool rhs_is_const = isColumnConst(rhs_column);
|
||||
@ -707,37 +707,33 @@ class FunctionBinaryArithmetic : public IFunction
|
||||
}
|
||||
|
||||
if (lhs_is_const && rhs_is_const)
|
||||
columns[result].column = ColumnConst::create(std::move(column_to), input_rows_count);
|
||||
return ColumnConst::create(std::move(column_to), input_rows_count);
|
||||
else
|
||||
columns[result].column = std::move(column_to);
|
||||
return column_to;
|
||||
}
|
||||
|
||||
void executeDateTimeIntervalPlusMinus(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments,
|
||||
size_t result, size_t input_rows_count, const FunctionOverloadResolverPtr & function_builder) const
|
||||
ColumnPtr executeDateTimeIntervalPlusMinus(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type,
|
||||
size_t input_rows_count, const FunctionOverloadResolverPtr & function_builder) const
|
||||
{
|
||||
ColumnNumbers new_arguments = arguments;
|
||||
ColumnsWithTypeAndName new_arguments = arguments;
|
||||
|
||||
/// Interval argument must be second.
|
||||
if (WhichDataType(columns[arguments[1]].type).isDateOrDateTime())
|
||||
if (WhichDataType(arguments[1].type).isDateOrDateTime())
|
||||
std::swap(new_arguments[0], new_arguments[1]);
|
||||
|
||||
/// Change interval argument type to its representation
|
||||
ColumnsWithTypeAndName new_columns = columns;
|
||||
new_columns[new_arguments[1]].type = std::make_shared<DataTypeNumber<DataTypeInterval::FieldType>>();
|
||||
new_arguments[1].type = std::make_shared<DataTypeNumber<DataTypeInterval::FieldType>>();
|
||||
|
||||
ColumnsWithTypeAndName new_arguments_with_type_and_name =
|
||||
{new_columns[new_arguments[0]], new_columns[new_arguments[1]]};
|
||||
auto function = function_builder->build(new_arguments_with_type_and_name);
|
||||
auto function = function_builder->build(new_arguments);
|
||||
|
||||
function->execute(new_columns, new_arguments, result, input_rows_count);
|
||||
columns[result].column = new_columns[result].column;
|
||||
return function->execute(new_arguments, result_type, input_rows_count);
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr auto name = Name::name;
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionBinaryArithmetic>(context); }
|
||||
|
||||
FunctionBinaryArithmetic(const Context & context_)
|
||||
explicit FunctionBinaryArithmetic(const Context & context_)
|
||||
: context(context_),
|
||||
check_decimal_overflow(decimalCheckArithmeticOverflow(context))
|
||||
{}
|
||||
@ -790,7 +786,7 @@ public:
|
||||
new_arguments[1].type = std::make_shared<DataTypeNumber<DataTypeInterval::FieldType>>();
|
||||
|
||||
auto function = function_builder->build(new_arguments);
|
||||
return function->getReturnType();
|
||||
return function->getResultType();
|
||||
}
|
||||
|
||||
DataTypePtr type_res;
|
||||
@ -851,20 +847,20 @@ public:
|
||||
return type_res;
|
||||
}
|
||||
|
||||
bool executeFixedString(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result) const
|
||||
ColumnPtr executeFixedString(ColumnsWithTypeAndName & arguments) const
|
||||
{
|
||||
using OpImpl = FixedStringOperationImpl<Op<UInt8, UInt8>>;
|
||||
|
||||
auto col_left_raw = columns[arguments[0]].column.get();
|
||||
auto col_right_raw = columns[arguments[1]].column.get();
|
||||
if (auto col_left_const = checkAndGetColumnConst<ColumnFixedString>(col_left_raw))
|
||||
const auto * col_left_raw = arguments[0].column.get();
|
||||
const auto * col_right_raw = arguments[1].column.get();
|
||||
if (const auto * col_left_const = checkAndGetColumnConst<ColumnFixedString>(col_left_raw))
|
||||
{
|
||||
if (auto col_right_const = checkAndGetColumnConst<ColumnFixedString>(col_right_raw))
|
||||
if (const auto * col_right_const = checkAndGetColumnConst<ColumnFixedString>(col_right_raw))
|
||||
{
|
||||
auto col_left = checkAndGetColumn<ColumnFixedString>(col_left_const->getDataColumn());
|
||||
auto col_right = checkAndGetColumn<ColumnFixedString>(col_right_const->getDataColumn());
|
||||
const auto * col_left = checkAndGetColumn<ColumnFixedString>(col_left_const->getDataColumn());
|
||||
const auto * col_right = checkAndGetColumn<ColumnFixedString>(col_right_const->getDataColumn());
|
||||
if (col_left->getN() != col_right->getN())
|
||||
return false;
|
||||
return nullptr;
|
||||
auto col_res = ColumnFixedString::create(col_left->getN());
|
||||
auto & out_chars = col_res->getChars();
|
||||
out_chars.resize(col_left->getN());
|
||||
@ -872,25 +868,24 @@ public:
|
||||
col_right->getChars().data(),
|
||||
out_chars.data(),
|
||||
out_chars.size());
|
||||
columns[result].column = ColumnConst::create(std::move(col_res), col_left_raw->size());
|
||||
return true;
|
||||
return ColumnConst::create(std::move(col_res), col_left_raw->size());
|
||||
}
|
||||
}
|
||||
|
||||
bool is_left_column_const = checkAndGetColumnConst<ColumnFixedString>(col_left_raw) != nullptr;
|
||||
bool is_right_column_const = checkAndGetColumnConst<ColumnFixedString>(col_right_raw) != nullptr;
|
||||
|
||||
auto col_left = is_left_column_const
|
||||
const auto * col_left = is_left_column_const
|
||||
? checkAndGetColumn<ColumnFixedString>(checkAndGetColumnConst<ColumnFixedString>(col_left_raw)->getDataColumn())
|
||||
: checkAndGetColumn<ColumnFixedString>(col_left_raw);
|
||||
auto col_right = is_right_column_const
|
||||
const auto * col_right = is_right_column_const
|
||||
? checkAndGetColumn<ColumnFixedString>(checkAndGetColumnConst<ColumnFixedString>(col_right_raw)->getDataColumn())
|
||||
: checkAndGetColumn<ColumnFixedString>(col_right_raw);
|
||||
|
||||
if (col_left && col_right)
|
||||
{
|
||||
if (col_left->getN() != col_right->getN())
|
||||
return false;
|
||||
return nullptr;
|
||||
|
||||
auto col_res = ColumnFixedString::create(col_left->getN());
|
||||
auto & out_chars = col_res->getChars();
|
||||
@ -922,14 +917,13 @@ public:
|
||||
out_chars.size(),
|
||||
col_left->getN());
|
||||
}
|
||||
columns[result].column = std::move(col_res);
|
||||
return true;
|
||||
return col_res;
|
||||
}
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename A, typename B>
|
||||
bool executeNumeric(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result [[maybe_unused]], const A & left, const B & right) const
|
||||
ColumnPtr executeNumeric(ColumnsWithTypeAndName & arguments, const A & left, const B & right) const
|
||||
{
|
||||
using LeftDataType = std::decay_t<decltype(left)>;
|
||||
using RightDataType = std::decay_t<decltype(right)>;
|
||||
@ -944,8 +938,8 @@ public:
|
||||
using ColVecT1 = std::conditional_t<IsDecimalNumber<T1>, ColumnDecimal<T1>, ColumnVector<T1>>;
|
||||
using ColVecResult = std::conditional_t<IsDecimalNumber<ResultType>, ColumnDecimal<ResultType>, ColumnVector<ResultType>>;
|
||||
|
||||
auto col_left_raw = columns[arguments[0]].column.get();
|
||||
auto col_right_raw = columns[arguments[1]].column.get();
|
||||
const auto * col_left_raw = arguments[0].column.get();
|
||||
const auto * col_right_raw = arguments[1].column.get();
|
||||
|
||||
auto col_left_const = checkAndGetColumnConst<ColVecT0>(col_left_raw);
|
||||
auto col_right_const = checkAndGetColumnConst<ColVecT1>(col_right_raw);
|
||||
@ -981,9 +975,8 @@ public:
|
||||
OpImplCheck::template constantConstant<dec_a, dec_b>(const_a, const_b, scale_a, scale_b) :
|
||||
OpImpl::template constantConstant<dec_a, dec_b>(const_a, const_b, scale_a, scale_b);
|
||||
|
||||
columns[result].column = ResultDataType(type.getPrecision(), type.getScale()).createColumnConst(
|
||||
return ResultDataType(type.getPrecision(), type.getScale()).createColumnConst(
|
||||
col_left_const->size(), toField(res, type.getScale()));
|
||||
return true;
|
||||
}
|
||||
|
||||
col_res = ColVecResult::create(0, type.getScale());
|
||||
@ -1016,7 +1009,7 @@ public:
|
||||
OpImpl::template vectorConstant<dec_a, dec_b>(col_left->getData(), const_b, vec_res, scale_a, scale_b);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1026,8 +1019,7 @@ public:
|
||||
if (col_left_const && col_right_const)
|
||||
{
|
||||
auto res = OpImpl::constantConstant(col_left_const->template getValue<T0>(), col_right_const->template getValue<T1>());
|
||||
columns[result].column = ResultDataType().createColumnConst(col_left_const->size(), toField(res));
|
||||
return true;
|
||||
return ResultDataType().createColumnConst(col_left_const->size(), toField(res));
|
||||
}
|
||||
|
||||
col_res = ColVecResult::create();
|
||||
@ -1047,43 +1039,40 @@ public:
|
||||
OpImpl::vectorConstant(col_left->getData().data(), col_right_const->template getValue<T1>(), vec_res.data(), vec_res.size());
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return true;
|
||||
return col_res;
|
||||
}
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||
{
|
||||
/// Special case when multiply aggregate function state
|
||||
if (isAggregateMultiply(columns[arguments[0]].type, columns[arguments[1]].type))
|
||||
if (isAggregateMultiply(arguments[0].type, arguments[1].type))
|
||||
{
|
||||
executeAggregateMultiply(columns, arguments, result, input_rows_count);
|
||||
return;
|
||||
return executeAggregateMultiply(arguments, result_type, input_rows_count);
|
||||
}
|
||||
|
||||
/// Special case - addition of two aggregate functions states
|
||||
if (isAggregateAddition(columns[arguments[0]].type, columns[arguments[1]].type))
|
||||
if (isAggregateAddition(arguments[0].type, arguments[1].type))
|
||||
{
|
||||
executeAggregateAddition(columns, arguments, result, input_rows_count);
|
||||
return;
|
||||
return executeAggregateAddition(arguments, result_type, input_rows_count);
|
||||
}
|
||||
|
||||
/// Special case when the function is plus or minus, one of arguments is Date/DateTime and another is Interval.
|
||||
if (auto function_builder
|
||||
= getFunctionForIntervalArithmetic(columns[arguments[0]].type, columns[arguments[1]].type, context))
|
||||
= getFunctionForIntervalArithmetic(arguments[0].type, arguments[1].type, context))
|
||||
{
|
||||
executeDateTimeIntervalPlusMinus(columns, arguments, result, input_rows_count, function_builder);
|
||||
return;
|
||||
return executeDateTimeIntervalPlusMinus(arguments, result_type, input_rows_count, function_builder);
|
||||
}
|
||||
|
||||
const auto & left_argument = columns[arguments[0]];
|
||||
const auto & right_argument = columns[arguments[1]];
|
||||
auto * left_generic = left_argument.type.get();
|
||||
auto * right_generic = right_argument.type.get();
|
||||
const auto & left_argument = arguments[0];
|
||||
const auto & right_argument = arguments[1];
|
||||
const auto * left_generic = left_argument.type.get();
|
||||
const auto * right_generic = right_argument.type.get();
|
||||
ColumnPtr res;
|
||||
bool valid = castBothTypes(left_generic, right_generic, [&](const auto & left, const auto & right)
|
||||
{
|
||||
using LeftDataType = std::decay_t<decltype(left)>;
|
||||
@ -1093,10 +1082,10 @@ public:
|
||||
if constexpr (!Op<DataTypeFixedString, DataTypeFixedString>::allow_fixed_string)
|
||||
return false;
|
||||
else
|
||||
return executeFixedString(columns, arguments, result);
|
||||
return (res = executeFixedString(arguments)) != nullptr;
|
||||
}
|
||||
else
|
||||
return executeNumeric(columns, arguments, result, left, right);
|
||||
return (res = executeNumeric(arguments, left, right)) != nullptr;
|
||||
});
|
||||
|
||||
if (!valid)
|
||||
@ -1109,6 +1098,8 @@ public:
|
||||
left_argument.name, left_argument.type->getName(),
|
||||
right_argument.name, right_argument.type->getName());
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#if USE_EMBEDDED_COMPILER
|
||||
@ -1190,30 +1181,26 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||
{
|
||||
if (left.column && isColumnConst(*left.column) && arguments.size() == 1)
|
||||
{
|
||||
ColumnsWithTypeAndName columns_with_constant
|
||||
= {{left.column->cloneResized(input_rows_count), left.type, left.name},
|
||||
columns[arguments[0]],
|
||||
columns[result]};
|
||||
arguments[0]};
|
||||
|
||||
Base::executeImpl(columns_with_constant, {0, 1}, 2, input_rows_count);
|
||||
columns[result] = columns_with_constant[2];
|
||||
return Base::executeImpl(columns_with_constant, result_type, input_rows_count);
|
||||
}
|
||||
else if (right.column && isColumnConst(*right.column) && arguments.size() == 1)
|
||||
{
|
||||
ColumnsWithTypeAndName columns_with_constant
|
||||
= {columns[arguments[0]],
|
||||
{right.column->cloneResized(input_rows_count), right.type, right.name},
|
||||
columns[result]};
|
||||
= {arguments[0],
|
||||
{right.column->cloneResized(input_rows_count), right.type, right.name}};
|
||||
|
||||
Base::executeImpl(columns_with_constant, {0, 1}, 2, input_rows_count);
|
||||
columns[result] = columns_with_constant[2];
|
||||
return Base::executeImpl(columns_with_constant, result_type, input_rows_count);
|
||||
}
|
||||
else
|
||||
Base::executeImpl(columns, arguments, result, input_rows_count);
|
||||
return Base::executeImpl(arguments, result_type, input_rows_count);
|
||||
}
|
||||
|
||||
bool hasInformationAboutMonotonicity() const override
|
||||
@ -1246,12 +1233,11 @@ public:
|
||||
{
|
||||
ColumnsWithTypeAndName columns_with_constant
|
||||
= {{left.column->cloneResized(1), left.type, left.name},
|
||||
{right.type->createColumnConst(1, point), right.type, right.name},
|
||||
{nullptr, return_type, ""}};
|
||||
{right.type->createColumnConst(1, point), right.type, right.name}};
|
||||
|
||||
Base::executeImpl(columns_with_constant, {0, 1}, 2, 1);
|
||||
auto col = Base::executeImpl(columns_with_constant, return_type, 1);
|
||||
Field point_transformed;
|
||||
columns_with_constant[2].column->get(0, point_transformed);
|
||||
col->get(0, point_transformed);
|
||||
return point_transformed;
|
||||
};
|
||||
transform(left_point);
|
||||
@ -1282,12 +1268,11 @@ public:
|
||||
{
|
||||
ColumnsWithTypeAndName columns_with_constant
|
||||
= {{left.type->createColumnConst(1, point), left.type, left.name},
|
||||
{right.column->cloneResized(1), right.type, right.name},
|
||||
{nullptr, return_type, ""}};
|
||||
{right.column->cloneResized(1), right.type, right.name}};
|
||||
|
||||
Base::executeImpl(columns_with_constant, {0, 1}, 2, 1);
|
||||
auto col = Base::executeImpl(columns_with_constant, return_type, 1);
|
||||
Field point_transformed;
|
||||
columns_with_constant[2].column->get(0, point_transformed);
|
||||
col->get(0, point_transformed);
|
||||
return point_transformed;
|
||||
};
|
||||
|
||||
|
@ -54,32 +54,35 @@ public:
|
||||
return std::make_shared<DataTypeUInt8>();
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns , const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const auto value_col = columns[arguments.front()].column.get();
|
||||
const auto * value_col = arguments.front().column.get();
|
||||
|
||||
if (!execute<UInt8>(columns, arguments, result, value_col)
|
||||
&& !execute<UInt16>(columns, arguments, result, value_col)
|
||||
&& !execute<UInt32>(columns, arguments, result, value_col)
|
||||
&& !execute<UInt64>(columns, arguments, result, value_col)
|
||||
&& !execute<Int8>(columns, arguments, result, value_col)
|
||||
&& !execute<Int16>(columns, arguments, result, value_col)
|
||||
&& !execute<Int32>(columns, arguments, result, value_col)
|
||||
&& !execute<Int64>(columns, arguments, result, value_col))
|
||||
ColumnPtr res;
|
||||
if (!((res = execute<UInt8>(arguments, result_type, value_col))
|
||||
|| (res = execute<UInt16>(arguments, result_type, value_col))
|
||||
|| (res = execute<UInt32>(arguments, result_type, value_col))
|
||||
|| (res = execute<UInt64>(arguments, result_type, value_col))
|
||||
|| (res = execute<Int8>(arguments, result_type, value_col))
|
||||
|| (res = execute<Int16>(arguments, result_type, value_col))
|
||||
|| (res = execute<Int32>(arguments, result_type, value_col))
|
||||
|| (res = execute<Int64>(arguments, result_type, value_col))))
|
||||
throw Exception{"Illegal column " + value_col->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_COLUMN};
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
bool execute(
|
||||
ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, const size_t result,
|
||||
ColumnPtr execute(
|
||||
ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type,
|
||||
const IColumn * const value_col_untyped) const
|
||||
{
|
||||
if (const auto value_col = checkAndGetColumn<ColumnVector<T>>(value_col_untyped))
|
||||
{
|
||||
const auto size = value_col->size();
|
||||
bool is_const;
|
||||
const auto const_mask = createConstMaskIfConst<T>(columns, arguments, is_const);
|
||||
const auto const_mask = createConstMaskIfConst<T>(arguments, is_const);
|
||||
const auto & val = value_col->getData();
|
||||
|
||||
auto out_col = ColumnVector<UInt8>::create(size);
|
||||
@ -92,29 +95,28 @@ private:
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto mask = createMask<T>(size, columns, arguments);
|
||||
const auto mask = createMask<T>(size, arguments);
|
||||
|
||||
for (const auto i : ext::range(0, size))
|
||||
out[i] = Impl::apply(val[i], mask[i]);
|
||||
}
|
||||
|
||||
columns[result].column = std::move(out_col);
|
||||
return true;
|
||||
return out_col;
|
||||
}
|
||||
else if (const auto value_col_const = checkAndGetColumnConst<ColumnVector<T>>(value_col_untyped))
|
||||
{
|
||||
const auto size = value_col_const->size();
|
||||
bool is_const;
|
||||
const auto const_mask = createConstMaskIfConst<T>(columns, arguments, is_const);
|
||||
const auto const_mask = createConstMaskIfConst<T>(arguments, is_const);
|
||||
const auto val = value_col_const->template getValue<T>();
|
||||
|
||||
if (is_const)
|
||||
{
|
||||
columns[result].column = columns[result].type->createColumnConst(size, toField(Impl::apply(val, const_mask)));
|
||||
return result_type->createColumnConst(size, toField(Impl::apply(val, const_mask)));
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto mask = createMask<T>(size, columns, arguments);
|
||||
const auto mask = createMask<T>(size, arguments);
|
||||
auto out_col = ColumnVector<UInt8>::create(size);
|
||||
|
||||
auto & out = out_col->getData();
|
||||
@ -122,24 +124,22 @@ private:
|
||||
for (const auto i : ext::range(0, size))
|
||||
out[i] = Impl::apply(val, mask[i]);
|
||||
|
||||
columns[result].column = std::move(out_col);
|
||||
return out_col;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
ValueType createConstMaskIfConst(const ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, bool & out_is_const) const
|
||||
ValueType createConstMaskIfConst(const ColumnsWithTypeAndName & arguments, bool & out_is_const) const
|
||||
{
|
||||
out_is_const = true;
|
||||
ValueType mask = 0;
|
||||
|
||||
for (const auto i : ext::range(1, arguments.size()))
|
||||
{
|
||||
if (auto pos_col_const = checkAndGetColumnConst<ColumnVector<ValueType>>(columns[arguments[i]].column.get()))
|
||||
if (auto pos_col_const = checkAndGetColumnConst<ColumnVector<ValueType>>(arguments[i].column.get()))
|
||||
{
|
||||
const auto pos = pos_col_const->getUInt(0);
|
||||
if (pos < 8 * sizeof(ValueType))
|
||||
@ -156,13 +156,13 @@ private:
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
PaddedPODArray<ValueType> createMask(const size_t size, const ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments) const
|
||||
PaddedPODArray<ValueType> createMask(const size_t size, const ColumnsWithTypeAndName & arguments) const
|
||||
{
|
||||
PaddedPODArray<ValueType> mask(size, ValueType{});
|
||||
|
||||
for (const auto i : ext::range(1, arguments.size()))
|
||||
{
|
||||
const auto pos_col = columns[arguments[i]].column.get();
|
||||
const auto * pos_col = arguments[i].column.get();
|
||||
|
||||
if (!addToMaskImpl<UInt8>(mask, pos_col)
|
||||
&& !addToMaskImpl<UInt16>(mask, pos_col)
|
||||
|
@ -96,26 +96,26 @@ public:
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {1, 2}; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||
{
|
||||
const IDataType * from_type = columns[arguments[0]].type.get();
|
||||
const IDataType * from_type = arguments[0].type.get();
|
||||
WhichDataType which(from_type);
|
||||
|
||||
if (which.isDate())
|
||||
CustomWeekTransformImpl<DataTypeDate, ToDataType>::execute(
|
||||
columns, arguments, result, input_rows_count, Transform{});
|
||||
return CustomWeekTransformImpl<DataTypeDate, ToDataType>::execute(
|
||||
arguments, result_type, input_rows_count, Transform{});
|
||||
else if (which.isDateTime())
|
||||
CustomWeekTransformImpl<DataTypeDateTime, ToDataType>::execute(
|
||||
columns, arguments, result, input_rows_count, Transform{});
|
||||
return CustomWeekTransformImpl<DataTypeDateTime, ToDataType>::execute(
|
||||
arguments, result_type, input_rows_count, Transform{});
|
||||
else if (which.isDateTime64())
|
||||
{
|
||||
CustomWeekTransformImpl<DataTypeDateTime64, ToDataType>::execute(
|
||||
columns, arguments, result, input_rows_count,
|
||||
return CustomWeekTransformImpl<DataTypeDateTime64, ToDataType>::execute(
|
||||
arguments, result_type, input_rows_count,
|
||||
TransformDateTime64<Transform>{assert_cast<const DataTypeDateTime64 *>(from_type)->getScale()});
|
||||
}
|
||||
else
|
||||
throw Exception(
|
||||
"Illegal type " + columns[arguments[0]].type->getName() + " of argument of function " + getName(),
|
||||
"Illegal type " + arguments[0].type->getName() + " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
}
|
||||
|
||||
|
@ -305,7 +305,7 @@ private:
|
||||
template <typename FromDataType, typename ToDataType, typename Transform>
|
||||
struct DateTimeAddIntervalImpl
|
||||
{
|
||||
static void execute(Transform transform, ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result)
|
||||
static ColumnPtr execute(Transform transform, ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type)
|
||||
{
|
||||
using FromValueType = typename FromDataType::FieldType;
|
||||
using FromColumnType = typename FromDataType::ColumnType;
|
||||
@ -313,16 +313,16 @@ struct DateTimeAddIntervalImpl
|
||||
|
||||
auto op = Adder<Transform>{std::move(transform)};
|
||||
|
||||
const DateLUTImpl & time_zone = extractTimeZoneFromFunctionArguments(columns, arguments, 2, 0);
|
||||
const DateLUTImpl & time_zone = extractTimeZoneFromFunctionArguments(arguments, 2, 0);
|
||||
|
||||
const ColumnPtr source_col = columns[arguments[0]].column;
|
||||
const ColumnPtr source_col = arguments[0].column;
|
||||
|
||||
auto result_col = columns[result].type->createColumn();
|
||||
auto result_col = result_type->createColumn();
|
||||
auto col_to = assert_cast<ToColumnType *>(result_col.get());
|
||||
|
||||
if (const auto * sources = checkAndGetColumn<FromColumnType>(source_col.get()))
|
||||
{
|
||||
const IColumn & delta_column = *columns[arguments[1]].column;
|
||||
const IColumn & delta_column = *arguments[1].column;
|
||||
|
||||
if (const auto * delta_const_column = typeid_cast<const ColumnConst *>(&delta_column))
|
||||
op.vectorConstant(sources->getData(), col_to->getData(), delta_const_column->getInt(0), time_zone);
|
||||
@ -334,16 +334,16 @@ struct DateTimeAddIntervalImpl
|
||||
op.constantVector(
|
||||
sources_const->template getValue<FromValueType>(),
|
||||
col_to->getData(),
|
||||
*columns[arguments[1]].column, time_zone);
|
||||
*arguments[1].column, time_zone);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of first argument of function " + Transform::name,
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
|
||||
columns[result].column = std::move(result_col);
|
||||
return result_col;
|
||||
}
|
||||
};
|
||||
|
||||
@ -463,28 +463,28 @@ public:
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {2}; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const IDataType * from_type = columns[arguments[0]].type.get();
|
||||
const IDataType * from_type = arguments[0].type.get();
|
||||
WhichDataType which(from_type);
|
||||
|
||||
if (which.isDate())
|
||||
{
|
||||
DateTimeAddIntervalImpl<DataTypeDate, TransformResultDataType<DataTypeDate>, Transform>::execute(
|
||||
Transform{}, columns, arguments, result);
|
||||
return DateTimeAddIntervalImpl<DataTypeDate, TransformResultDataType<DataTypeDate>, Transform>::execute(
|
||||
Transform{}, arguments, result_type);
|
||||
}
|
||||
else if (which.isDateTime())
|
||||
{
|
||||
DateTimeAddIntervalImpl<DataTypeDateTime, TransformResultDataType<DataTypeDateTime>, Transform>::execute(
|
||||
Transform{}, columns, arguments, result);
|
||||
return DateTimeAddIntervalImpl<DataTypeDateTime, TransformResultDataType<DataTypeDateTime>, Transform>::execute(
|
||||
Transform{}, arguments, result_type);
|
||||
}
|
||||
else if (const auto * datetime64_type = assert_cast<const DataTypeDateTime64 *>(from_type))
|
||||
{
|
||||
DateTimeAddIntervalImpl<DataTypeDateTime64, TransformResultDataType<DataTypeDateTime64>, Transform>::execute(
|
||||
Transform{datetime64_type->getScale()}, columns, arguments, result);
|
||||
return DateTimeAddIntervalImpl<DataTypeDateTime64, TransformResultDataType<DataTypeDateTime64>, Transform>::execute(
|
||||
Transform{datetime64_type->getScale()}, arguments, result_type);
|
||||
}
|
||||
else
|
||||
throw Exception("Illegal type " + columns[arguments[0]].type->getName() + " of first argument of function " + getName(),
|
||||
throw Exception("Illegal type " + arguments[0].type->getName() + " of first argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
}
|
||||
};
|
||||
|
@ -95,23 +95,23 @@ public:
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {1}; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||
{
|
||||
const IDataType * from_type = columns[arguments[0]].type.get();
|
||||
const IDataType * from_type = arguments[0].type.get();
|
||||
WhichDataType which(from_type);
|
||||
|
||||
if (which.isDate())
|
||||
DateTimeTransformImpl<DataTypeDate, ToDataType, Transform>::execute(columns, arguments, result, input_rows_count);
|
||||
return DateTimeTransformImpl<DataTypeDate, ToDataType, Transform>::execute(arguments, result_type, input_rows_count);
|
||||
else if (which.isDateTime())
|
||||
DateTimeTransformImpl<DataTypeDateTime, ToDataType, Transform>::execute(columns, arguments, result, input_rows_count);
|
||||
return DateTimeTransformImpl<DataTypeDateTime, ToDataType, Transform>::execute(arguments, result_type, input_rows_count);
|
||||
else if (which.isDateTime64())
|
||||
{
|
||||
const auto scale = static_cast<const DataTypeDateTime64 *>(from_type)->getScale();
|
||||
const TransformDateTime64<Transform> transformer(scale);
|
||||
DateTimeTransformImpl<DataTypeDateTime64, ToDataType, decltype(transformer)>::execute(columns, arguments, result, input_rows_count, transformer);
|
||||
return DateTimeTransformImpl<DataTypeDateTime64, ToDataType, decltype(transformer)>::execute(arguments, result_type, input_rows_count, transformer);
|
||||
}
|
||||
else
|
||||
throw Exception("Illegal type " + columns[arguments[0]].type->getName() + " of argument of function " + getName(),
|
||||
throw Exception("Illegal type " + arguments[0].type->getName() + " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
}
|
||||
|
||||
|
@ -34,9 +34,9 @@ public:
|
||||
return std::make_shared<DataTypeString>();
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers &, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName &, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||
{
|
||||
columns[result].column = columns[result].type->createColumnConst(
|
||||
return result_type->createColumnConst(
|
||||
input_rows_count, getFQDNOrHostName())->convertToFullColumnIfConst();
|
||||
}
|
||||
};
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include <Columns/ColumnLowCardinality.h>
|
||||
#include <Common/assert_cast.h>
|
||||
#include <DataTypes/DataTypeNullable.h>
|
||||
#include <DataTypes/DataTypeLowCardinality.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -51,16 +50,12 @@ Columns convertConstTupleToConstantElements(const ColumnConst & column)
|
||||
}
|
||||
|
||||
|
||||
static ColumnsWithTypeAndName createBlockWithNestedColumnsImpl(const ColumnsWithTypeAndName & columns, const std::unordered_set<size_t> & args)
|
||||
ColumnsWithTypeAndName createBlockWithNestedColumns(const ColumnsWithTypeAndName & columns)
|
||||
{
|
||||
ColumnsWithTypeAndName res;
|
||||
size_t num_columns = columns.size();
|
||||
|
||||
for (size_t i = 0; i < num_columns; ++i)
|
||||
for (const auto & col : columns)
|
||||
{
|
||||
const auto & col = columns[i];
|
||||
|
||||
if (args.count(i) && col.type->isNullable())
|
||||
if (col.type->isNullable())
|
||||
{
|
||||
const DataTypePtr & nested_type = static_cast<const DataTypeNullable &>(*col.type).getNestedType();
|
||||
|
||||
@ -88,20 +83,6 @@ static ColumnsWithTypeAndName createBlockWithNestedColumnsImpl(const ColumnsWith
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
ColumnsWithTypeAndName createBlockWithNestedColumns(const ColumnsWithTypeAndName & columns, const ColumnNumbers & args)
|
||||
{
|
||||
std::unordered_set<size_t> args_set(args.begin(), args.end());
|
||||
return createBlockWithNestedColumnsImpl(columns, args_set);
|
||||
}
|
||||
|
||||
ColumnsWithTypeAndName createBlockWithNestedColumns(const ColumnsWithTypeAndName & columns, const ColumnNumbers & args, size_t result)
|
||||
{
|
||||
std::unordered_set<size_t> args_set(args.begin(), args.end());
|
||||
args_set.insert(result);
|
||||
return createBlockWithNestedColumnsImpl(columns, args_set);
|
||||
}
|
||||
|
||||
void validateArgumentType(const IFunction & func, const DataTypes & arguments,
|
||||
size_t argument_index, bool (* validator_func)(const IDataType &),
|
||||
const char * expected_type_description)
|
||||
@ -137,7 +118,7 @@ void validateArgumentsImpl(const IFunction & func,
|
||||
const auto & arg = arguments[i + argument_offset];
|
||||
const auto descriptor = descriptors[i];
|
||||
if (int error_code = descriptor.isValid(arg.type, arg.column); error_code != 0)
|
||||
throw Exception("Illegal type of argument #" + std::to_string(i)
|
||||
throw Exception("Illegal type of argument #" + std::to_string(argument_offset + i + 1) // +1 is for human-friendly 1-based indexing
|
||||
+ (descriptor.argument_name ? " '" + std::string(descriptor.argument_name) + "'" : String{})
|
||||
+ " of function " + func.getName()
|
||||
+ (descriptor.expected_type_description ? String(", expected ") + descriptor.expected_type_description : String{})
|
||||
|
@ -82,13 +82,9 @@ inline std::enable_if_t<IsDecimalNumber<T>, Field> toField(const T & x, UInt32 s
|
||||
Columns convertConstTupleToConstantElements(const ColumnConst & column);
|
||||
|
||||
|
||||
/// Returns the copy of a given columns in which each column specified in
|
||||
/// the "arguments" parameter is replaced with its respective nested
|
||||
/// Returns the copy of a given columns in which each column is replaced with its respective nested
|
||||
/// column if it is nullable.
|
||||
ColumnsWithTypeAndName createBlockWithNestedColumns(const ColumnsWithTypeAndName & columns, const ColumnNumbers & args);
|
||||
|
||||
/// Similar function as above. Additionally transform the result type if needed.
|
||||
ColumnsWithTypeAndName createBlockWithNestedColumns(const ColumnsWithTypeAndName & columns, const ColumnNumbers & args, size_t result);
|
||||
ColumnsWithTypeAndName createBlockWithNestedColumns(const ColumnsWithTypeAndName & columns);
|
||||
|
||||
/// Checks argument type at specified index with predicate.
|
||||
/// throws if there is no argument at specified index or if predicate returns false.
|
||||
|
@ -17,19 +17,19 @@ namespace ErrorCodes
|
||||
}
|
||||
|
||||
template <bool or_null>
|
||||
void ExecutableFunctionJoinGet<or_null>::execute(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t)
|
||||
ColumnPtr ExecutableFunctionJoinGet<or_null>::execute(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t)
|
||||
{
|
||||
ColumnsWithTypeAndName keys;
|
||||
for (size_t i = 2; i < arguments.size(); ++i)
|
||||
{
|
||||
auto key = columns[arguments[i]];
|
||||
auto key = arguments[i];
|
||||
keys.emplace_back(std::move(key));
|
||||
}
|
||||
columns[result] = join->joinGet(keys, result_columns);
|
||||
return join->joinGet(keys, result_columns).column;
|
||||
}
|
||||
|
||||
template <bool or_null>
|
||||
ExecutableFunctionImplPtr FunctionJoinGet<or_null>::prepare(const ColumnsWithTypeAndName &, const ColumnNumbers &, size_t) const
|
||||
ExecutableFunctionImplPtr FunctionJoinGet<or_null>::prepare(const ColumnsWithTypeAndName &) const
|
||||
{
|
||||
return std::make_unique<ExecutableFunctionJoinGet<or_null>>(join, DB::Block{{return_type->createColumn(), return_type, attr_name}});
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ public:
|
||||
bool useDefaultImplementationForLowCardinalityColumns() const override { return true; }
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void execute(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override;
|
||||
ColumnPtr execute(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) override;
|
||||
|
||||
String getName() const override { return name; }
|
||||
|
||||
@ -54,9 +54,9 @@ public:
|
||||
String getName() const override { return name; }
|
||||
|
||||
const DataTypes & getArgumentTypes() const override { return argument_types; }
|
||||
const DataTypePtr & getReturnType() const override { return return_type; }
|
||||
const DataTypePtr & getResultType() const override { return return_type; }
|
||||
|
||||
ExecutableFunctionImplPtr prepare(const ColumnsWithTypeAndName & sample_columns, const ColumnNumbers & arguments, size_t result) const override;
|
||||
ExecutableFunctionImplPtr prepare(const ColumnsWithTypeAndName &) const override;
|
||||
|
||||
private:
|
||||
TableLockHolder table_lock;
|
||||
|
@ -54,7 +54,7 @@ private:
|
||||
}
|
||||
|
||||
template <typename LeftType, typename RightType>
|
||||
bool executeTyped(ColumnsWithTypeAndName & columns, const size_t result, const ColumnConst * left_arg, const IColumn * right_arg) const
|
||||
ColumnPtr executeTyped(const ColumnConst * left_arg, const IColumn * right_arg) const
|
||||
{
|
||||
if (const auto right_arg_typed = checkAndGetColumn<ColumnVector<RightType>>(right_arg))
|
||||
{
|
||||
@ -95,15 +95,14 @@ private:
|
||||
memcpy(&dst_data[rows_size], dst_remaining, rows_remaining * sizeof(Float64));
|
||||
}
|
||||
|
||||
columns[result].column = std::move(dst);
|
||||
return true;
|
||||
return dst;
|
||||
}
|
||||
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename LeftType, typename RightType>
|
||||
bool executeTyped(ColumnsWithTypeAndName & columns, const size_t result, const ColumnVector<LeftType> * left_arg, const IColumn * right_arg) const
|
||||
ColumnPtr executeTyped(const ColumnVector<LeftType> * left_arg, const IColumn * right_arg) const
|
||||
{
|
||||
if (const auto right_arg_typed = checkAndGetColumn<ColumnVector<RightType>>(right_arg))
|
||||
{
|
||||
@ -157,8 +156,7 @@ private:
|
||||
memcpy(&dst_data[rows_size], dst_remaining, rows_remaining * sizeof(Float64));
|
||||
}
|
||||
|
||||
columns[result].column = std::move(dst);
|
||||
return true;
|
||||
return dst;
|
||||
}
|
||||
if (const auto right_arg_typed = checkAndGetColumnConst<ColumnVector<RightType>>(right_arg))
|
||||
{
|
||||
@ -200,17 +198,17 @@ private:
|
||||
memcpy(&dst_data[rows_size], dst_remaining, rows_remaining * sizeof(Float64));
|
||||
}
|
||||
|
||||
columns[result].column = std::move(dst);
|
||||
return true;
|
||||
return dst;
|
||||
}
|
||||
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const ColumnWithTypeAndName & col_left = columns[arguments[0]];
|
||||
const ColumnWithTypeAndName & col_right = columns[arguments[1]];
|
||||
const ColumnWithTypeAndName & col_left = arguments[0];
|
||||
const ColumnWithTypeAndName & col_right = arguments[1];
|
||||
ColumnPtr res;
|
||||
|
||||
auto call = [&](const auto & types) -> bool
|
||||
{
|
||||
@ -224,7 +222,7 @@ private:
|
||||
|
||||
if (const auto left_arg_typed = checkAndGetColumn<ColVecLeft>(left_arg))
|
||||
{
|
||||
if (executeTyped<LeftType, RightType>(columns, result, left_arg_typed, right_arg))
|
||||
if ((res = executeTyped<LeftType, RightType>(left_arg_typed, right_arg)))
|
||||
return true;
|
||||
|
||||
throw Exception{"Illegal column " + right_arg->getName() + " of second argument of function " + getName(),
|
||||
@ -232,7 +230,7 @@ private:
|
||||
}
|
||||
if (const auto left_arg_typed = checkAndGetColumnConst<ColVecLeft>(left_arg))
|
||||
{
|
||||
if (executeTyped<LeftType, RightType>(columns, result, left_arg_typed, right_arg))
|
||||
if ((res = executeTyped<LeftType, RightType>(left_arg_typed, right_arg)))
|
||||
return true;
|
||||
|
||||
throw Exception{"Illegal column " + right_arg->getName() + " of second argument of function " + getName(),
|
||||
@ -248,6 +246,8 @@ private:
|
||||
if (!callOnBasicTypes<true, true, false, false>(left_index, right_index, call))
|
||||
throw Exception{"Illegal column " + col_left.column->getName() + " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN};
|
||||
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -25,9 +25,9 @@ private:
|
||||
return std::make_shared<DataTypeFloat64>();
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers &, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName &, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||
{
|
||||
columns[result].column = columns[result].type->createColumnConst(input_rows_count, Impl::value);
|
||||
return result_type->createColumnConst(input_rows_count, Impl::value);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -113,7 +113,7 @@ private:
|
||||
}
|
||||
|
||||
template <typename T, typename ReturnType>
|
||||
static bool execute(ColumnsWithTypeAndName & columns, const ColumnVector<T> * col, const size_t result)
|
||||
static ColumnPtr execute(const ColumnVector<T> * col)
|
||||
{
|
||||
const auto & src_data = col->getData();
|
||||
const size_t size = src_data.size();
|
||||
@ -124,12 +124,11 @@ private:
|
||||
|
||||
executeInIterations(src_data.data(), dst_data.data(), size);
|
||||
|
||||
columns[result].column = std::move(dst);
|
||||
return true;
|
||||
return dst;
|
||||
}
|
||||
|
||||
template <typename T, typename ReturnType>
|
||||
static bool execute(ColumnsWithTypeAndName & columns, const ColumnDecimal<T> * col, const size_t result)
|
||||
static ColumnPtr execute(const ColumnDecimal<T> * col)
|
||||
{
|
||||
const auto & src_data = col->getData();
|
||||
const size_t size = src_data.size();
|
||||
@ -144,15 +143,15 @@ private:
|
||||
|
||||
executeInIterations(dst_data.data(), dst_data.data(), size);
|
||||
|
||||
columns[result].column = std::move(dst);
|
||||
return true;
|
||||
return dst;
|
||||
}
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const ColumnWithTypeAndName & col = columns[arguments[0]];
|
||||
const ColumnWithTypeAndName & col = arguments[0];
|
||||
ColumnPtr res;
|
||||
|
||||
auto call = [&](const auto & types) -> bool
|
||||
{
|
||||
@ -162,12 +161,14 @@ private:
|
||||
using ColVecType = std::conditional_t<IsDecimalNumber<Type>, ColumnDecimal<Type>, ColumnVector<Type>>;
|
||||
|
||||
const auto col_vec = checkAndGetColumn<ColVecType>(col.column.get());
|
||||
return execute<Type, ReturnType>(columns, col_vec, result);
|
||||
return (res = execute<Type, ReturnType>(col_vec)) != nullptr;
|
||||
};
|
||||
|
||||
if (!callOnBasicType<void, true, true, true, false>(col.type->getTypeId(), call))
|
||||
throw Exception{"Illegal column " + col.column->getName() + " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN};
|
||||
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -46,25 +46,28 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const auto in = columns[arguments.front()].column.get();
|
||||
const auto * in = arguments.front().column.get();
|
||||
|
||||
if ( !execute<UInt8>(columns, in, result)
|
||||
&& !execute<UInt16>(columns, in, result)
|
||||
&& !execute<UInt32>(columns, in, result)
|
||||
&& !execute<UInt64>(columns, in, result)
|
||||
&& !execute<Int8>(columns, in, result)
|
||||
&& !execute<Int16>(columns, in, result)
|
||||
&& !execute<Int32>(columns, in, result)
|
||||
&& !execute<Int64>(columns, in, result)
|
||||
&& !execute<Float32>(columns, in, result)
|
||||
&& !execute<Float64>(columns, in, result))
|
||||
ColumnPtr res;
|
||||
if (!((res = execute<UInt8>(in))
|
||||
|| (res = execute<UInt16>(in))
|
||||
|| (res = execute<UInt32>(in))
|
||||
|| (res = execute<UInt64>(in))
|
||||
|| (res = execute<Int8>(in))
|
||||
|| (res = execute<Int16>(in))
|
||||
|| (res = execute<Int32>(in))
|
||||
|| (res = execute<Int64>(in))
|
||||
|| (res = execute<Float32>(in))
|
||||
|| (res = execute<Float64>(in))))
|
||||
throw Exception{"Illegal column " + in->getName() + " of first argument of function " + getName(), ErrorCodes::ILLEGAL_COLUMN};
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool execute(ColumnsWithTypeAndName & columns, const IColumn * in_untyped, const size_t result) const
|
||||
ColumnPtr execute(const IColumn * in_untyped) const
|
||||
{
|
||||
if (const auto in = checkAndGetColumn<ColumnVector<T>>(in_untyped))
|
||||
{
|
||||
@ -78,11 +81,10 @@ public:
|
||||
for (const auto i : ext::range(0, size))
|
||||
out_data[i] = Impl::execute(in_data[i]);
|
||||
|
||||
columns[result].column = std::move(out);
|
||||
return true;
|
||||
return out;
|
||||
}
|
||||
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -63,10 +63,10 @@ public:
|
||||
return std::make_shared<DataTypeUInt8>();
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
|
||||
{
|
||||
const IColumn * haystack_column = columns[arguments[0]].column.get();
|
||||
const IColumn * needle_column = columns[arguments[1]].column.get();
|
||||
const IColumn * haystack_column = arguments[0].column.get();
|
||||
const IColumn * needle_column = arguments[1].column.get();
|
||||
|
||||
auto col_res = ColumnVector<UInt8>::create();
|
||||
typename ColumnVector<UInt8>::Container & vec_res = col_res->getData();
|
||||
@ -84,7 +84,7 @@ public:
|
||||
else
|
||||
throw Exception("Illegal combination of columns as arguments of function " + getName(), ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -159,9 +159,9 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||
{
|
||||
selector.selectAndExecute(columns, arguments, result, input_rows_count);
|
||||
return selector.selectAndExecute(arguments, result_type, input_rows_count);
|
||||
}
|
||||
|
||||
static FunctionPtr create(const Context & context)
|
||||
|
@ -50,9 +50,9 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const ColumnPtr column = columns[arguments[0]].column;
|
||||
const ColumnPtr column = arguments[0].column;
|
||||
if (const ColumnString * col = checkAndGetColumn<ColumnString>(column.get()))
|
||||
{
|
||||
auto col_res = ColumnVector<ResultType>::create();
|
||||
@ -61,7 +61,7 @@ public:
|
||||
vec_res.resize(col->size());
|
||||
Impl::vector(col->getChars(), col->getOffsets(), vec_res);
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
else if (const ColumnFixedString * col_fixed = checkAndGetColumn<ColumnFixedString>(column.get()))
|
||||
{
|
||||
@ -70,7 +70,7 @@ public:
|
||||
ResultType res = 0;
|
||||
Impl::vectorFixedToConstant(col_fixed->getChars(), col_fixed->getN(), res);
|
||||
|
||||
columns[result].column = columns[result].type->createColumnConst(col_fixed->size(), toField(res));
|
||||
return result_type->createColumnConst(col_fixed->size(), toField(res));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -80,7 +80,7 @@ public:
|
||||
vec_res.resize(col_fixed->size());
|
||||
Impl::vectorFixedToVector(col_fixed->getChars(), col_fixed->getN(), vec_res);
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
}
|
||||
else if (const ColumnArray * col_arr = checkAndGetColumn<ColumnArray>(column.get()))
|
||||
@ -91,10 +91,10 @@ public:
|
||||
vec_res.resize(col_arr->size());
|
||||
Impl::array(col_arr->getOffsets(), vec_res);
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
else
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName() + " of argument of function " + getName(),
|
||||
throw Exception("Illegal column " + arguments[0].column->getName() + " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
};
|
||||
|
@ -52,17 +52,17 @@ public:
|
||||
return std::make_shared<DataTypeString>();
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const ColumnPtr column_src = columns[arguments[0]].column;
|
||||
const ColumnPtr column_needle = columns[arguments[1]].column;
|
||||
const ColumnPtr column_replacement = columns[arguments[2]].column;
|
||||
const ColumnPtr column_src = arguments[0].column;
|
||||
const ColumnPtr column_needle = arguments[1].column;
|
||||
const ColumnPtr column_replacement = arguments[2].column;
|
||||
|
||||
if (!isColumnConst(*column_needle) || !isColumnConst(*column_replacement))
|
||||
throw Exception("2nd and 3rd arguments of function " + getName() + " must be constants.", ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
const IColumn * c1 = columns[arguments[1]].column.get();
|
||||
const IColumn * c2 = columns[arguments[2]].column.get();
|
||||
const IColumn * c1 = arguments[1].column.get();
|
||||
const IColumn * c2 = arguments[2].column.get();
|
||||
const ColumnConst * c1_const = typeid_cast<const ColumnConst *>(c1);
|
||||
const ColumnConst * c2_const = typeid_cast<const ColumnConst *>(c2);
|
||||
String needle = c1_const->getValue<String>();
|
||||
@ -75,17 +75,17 @@ public:
|
||||
{
|
||||
auto col_res = ColumnString::create();
|
||||
Impl::vector(col->getChars(), col->getOffsets(), needle, replacement, col_res->getChars(), col_res->getOffsets());
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
else if (const ColumnFixedString * col_fixed = checkAndGetColumn<ColumnFixedString>(column_src.get()))
|
||||
{
|
||||
auto col_res = ColumnString::create();
|
||||
Impl::vectorFixed(col_fixed->getChars(), col_fixed->getN(), needle, replacement, col_res->getChars(), col_res->getOffsets());
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
else
|
||||
throw Exception(
|
||||
"Illegal column " + columns[arguments[0]].column->getName() + " of first argument of function " + getName(),
|
||||
"Illegal column " + arguments[0].column->getName() + " of first argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
};
|
||||
|
@ -52,24 +52,24 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const ColumnPtr column = columns[arguments[0]].column;
|
||||
const ColumnPtr column = arguments[0].column;
|
||||
if (const ColumnString * col = checkAndGetColumn<ColumnString>(column.get()))
|
||||
{
|
||||
auto col_res = ColumnString::create();
|
||||
Impl::vector(col->getChars(), col->getOffsets(), col_res->getChars(), col_res->getOffsets());
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
else if (const ColumnFixedString * col_fixed = checkAndGetColumn<ColumnFixedString>(column.get()))
|
||||
{
|
||||
auto col_res = ColumnFixedString::create(col_fixed->getN());
|
||||
Impl::vectorFixed(col_fixed->getChars(), col_fixed->getN(), col_res->getChars());
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
else
|
||||
throw Exception(
|
||||
"Illegal column " + columns[arguments[0]].column->getName() + " of argument of function " + getName(),
|
||||
"Illegal column " + arguments[0].column->getName() + " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
};
|
||||
|
@ -154,9 +154,10 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
bool valid = castType(columns[arguments[0]].type.get(), [&](const auto & type)
|
||||
ColumnPtr result_column;
|
||||
bool valid = castType(arguments[0].type.get(), [&](const auto & type)
|
||||
{
|
||||
using DataType = std::decay_t<decltype(type)>;
|
||||
|
||||
@ -164,13 +165,13 @@ public:
|
||||
{
|
||||
if constexpr (allow_fixed_string)
|
||||
{
|
||||
if (auto col = checkAndGetColumn<ColumnFixedString>(columns[arguments[0]].column.get()))
|
||||
if (const auto * col = checkAndGetColumn<ColumnFixedString>(arguments[0].column.get()))
|
||||
{
|
||||
auto col_res = ColumnFixedString::create(col->getN());
|
||||
auto & vec_res = col_res->getChars();
|
||||
vec_res.resize(col->size() * col->getN());
|
||||
FixedStringUnaryOperationImpl<Op<UInt8>>::vector(col->getChars(), vec_res);
|
||||
columns[result].column = std::move(col_res);
|
||||
result_column = std::move(col_res);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -180,13 +181,13 @@ public:
|
||||
using T0 = typename DataType::FieldType;
|
||||
if constexpr (allow_decimal)
|
||||
{
|
||||
if (auto col = checkAndGetColumn<ColumnDecimal<T0>>(columns[arguments[0]].column.get()))
|
||||
if (auto col = checkAndGetColumn<ColumnDecimal<T0>>(arguments[0].column.get()))
|
||||
{
|
||||
auto col_res = ColumnDecimal<typename Op<T0>::ResultType>::create(0, type.getScale());
|
||||
auto & vec_res = col_res->getData();
|
||||
vec_res.resize(col->getData().size());
|
||||
UnaryOperationImpl<T0, Op<T0>>::vector(col->getData(), vec_res);
|
||||
columns[result].column = std::move(col_res);
|
||||
result_column = std::move(col_res);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -194,13 +195,13 @@ public:
|
||||
else
|
||||
{
|
||||
using T0 = typename DataType::FieldType;
|
||||
if (auto col = checkAndGetColumn<ColumnVector<T0>>(columns[arguments[0]].column.get()))
|
||||
if (auto col = checkAndGetColumn<ColumnVector<T0>>(arguments[0].column.get()))
|
||||
{
|
||||
auto col_res = ColumnVector<typename Op<T0>::ResultType>::create();
|
||||
auto & vec_res = col_res->getData();
|
||||
vec_res.resize(col->getData().size());
|
||||
UnaryOperationImpl<T0, Op<T0>>::vector(col->getData(), vec_res);
|
||||
columns[result].column = std::move(col_res);
|
||||
result_column = std::move(col_res);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -209,6 +210,8 @@ public:
|
||||
});
|
||||
if (!valid)
|
||||
throw Exception(getName() + "'s argument does not match the expected data type", ErrorCodes::LOGICAL_ERROR);
|
||||
|
||||
return result_column;
|
||||
}
|
||||
|
||||
#if USE_EMBEDDED_COMPILER
|
||||
|
@ -65,13 +65,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||
{
|
||||
using SourceColumnType = typename SourceDataType::ColumnType;
|
||||
using ResultColumnType = typename ResultDataType::ColumnType;
|
||||
|
||||
const auto & src = columns[arguments[0]];
|
||||
auto & res = columns[result];
|
||||
const auto & src = arguments[0];
|
||||
const auto & col = *src.column;
|
||||
|
||||
const SourceColumnType * source_col_typed = checkAndGetColumn<SourceColumnType>(col);
|
||||
@ -80,16 +79,16 @@ public:
|
||||
+ std::string(SourceDataType::family_name),
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
res.column = res.type->createColumn();
|
||||
auto res_column = result_type->createColumn();
|
||||
|
||||
if (input_rows_count == 0)
|
||||
return;
|
||||
return res_column;
|
||||
|
||||
auto & result_data = assert_cast<ResultColumnType &>(res.column->assumeMutableRef()).getData();
|
||||
auto & result_data = assert_cast<ResultColumnType &>(res_column->assumeMutableRef()).getData();
|
||||
result_data.reserve(source_col_typed->size());
|
||||
const auto & source_data = source_col_typed->getData();
|
||||
|
||||
const auto scale_diff = getScaleDiff(*checkAndGetDataType<SourceDataType>(src.type.get()), *checkAndGetDataType<ResultDataType>(res.type.get()));
|
||||
const auto scale_diff = getScaleDiff(*checkAndGetDataType<SourceDataType>(src.type.get()), *checkAndGetDataType<ResultDataType>(result_type.get()));
|
||||
if (scale_diff == 0)
|
||||
{
|
||||
static_assert(sizeof(typename SourceColumnType::Container::value_type) == sizeof(typename ResultColumnType::Container::value_type));
|
||||
@ -114,6 +113,8 @@ public:
|
||||
for (const auto & v : source_data)
|
||||
result_data.push_back(static_cast<Int64>(toDestValue(v) / scale_multiplier));
|
||||
}
|
||||
|
||||
return res_column;
|
||||
}
|
||||
|
||||
private:
|
||||
|
63
src/Functions/FunctionsAES.cpp
Normal file
63
src/Functions/FunctionsAES.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
#include <Functions/FunctionsAES.h>
|
||||
|
||||
#if USE_SSL
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int OPENSSL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
namespace OpenSSLDetails
|
||||
{
|
||||
void onError(std::string error_message)
|
||||
{
|
||||
error_message += ". OpenSSL error code: " + std::to_string(ERR_get_error());
|
||||
throw DB::Exception(error_message, DB::ErrorCodes::OPENSSL_ERROR);
|
||||
}
|
||||
|
||||
StringRef foldEncryptionKeyInMySQLCompatitableMode(size_t cipher_key_size, const StringRef & key, std::array<char, EVP_MAX_KEY_LENGTH> & folded_key)
|
||||
{
|
||||
assert(cipher_key_size <= EVP_MAX_KEY_LENGTH);
|
||||
memcpy(folded_key.data(), key.data, cipher_key_size);
|
||||
|
||||
for (size_t i = cipher_key_size; i < key.size; ++i)
|
||||
{
|
||||
folded_key[i % cipher_key_size] ^= key.data[i];
|
||||
}
|
||||
|
||||
return StringRef(folded_key.data(), cipher_key_size);
|
||||
}
|
||||
|
||||
const EVP_CIPHER * getCipherByName(const StringRef & cipher_name)
|
||||
{
|
||||
const auto * evp_cipher = EVP_get_cipherbyname(cipher_name.data);
|
||||
if (evp_cipher == nullptr)
|
||||
{
|
||||
// For some reasons following ciphers can't be found by name.
|
||||
if (cipher_name == "aes-128-cfb128")
|
||||
evp_cipher = EVP_aes_128_cfb128();
|
||||
else if (cipher_name == "aes-192-cfb128")
|
||||
evp_cipher = EVP_aes_192_cfb128();
|
||||
else if (cipher_name == "aes-256-cfb128")
|
||||
evp_cipher = EVP_aes_256_cfb128();
|
||||
}
|
||||
|
||||
// NOTE: cipher obtained not via EVP_CIPHER_fetch() would cause extra work on each context reset
|
||||
// with EVP_CIPHER_CTX_reset() or EVP_EncryptInit_ex(), but using EVP_CIPHER_fetch()
|
||||
// causes data race, so we stick to the slower but safer alternative here.
|
||||
return evp_cipher;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
693
src/Functions/FunctionsAES.h
Normal file
693
src/Functions/FunctionsAES.h
Normal file
@ -0,0 +1,693 @@
|
||||
#pragma once
|
||||
|
||||
#if !defined(ARCADIA_BUILD)
|
||||
# include <Common/config.h>
|
||||
#endif
|
||||
|
||||
#if USE_SSL
|
||||
#include <DataTypes/DataTypeString.h>
|
||||
#include <Columns/ColumnString.h>
|
||||
#include <Functions/IFunction.h>
|
||||
#include <Functions/FunctionFactory.h>
|
||||
#include <Functions/FunctionHelpers.h>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/engine.h>
|
||||
|
||||
#include <string_view>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int BAD_ARGUMENTS;
|
||||
}
|
||||
}
|
||||
|
||||
namespace OpenSSLDetails
|
||||
{
|
||||
[[noreturn]] void onError(std::string error_message);
|
||||
StringRef foldEncryptionKeyInMySQLCompatitableMode(size_t cipher_key_size, const StringRef & key, std::array<char, EVP_MAX_KEY_LENGTH> & folded_key);
|
||||
|
||||
const EVP_CIPHER * getCipherByName(const StringRef & name);
|
||||
|
||||
enum class CompatibilityMode
|
||||
{
|
||||
MySQL,
|
||||
OpenSSL
|
||||
};
|
||||
|
||||
enum class CipherMode
|
||||
{
|
||||
MySQLCompatibility, // with key folding
|
||||
OpenSSLCompatibility, // just as regular openssl's enc application does (AEAD modes, like GCM and CCM are not supported)
|
||||
RFC5116_AEAD_AES_GCM // AEAD GCM with custom IV length and tag (HMAC) appended to the ciphertext, see https://tools.ietf.org/html/rfc5116#section-5.1
|
||||
};
|
||||
|
||||
|
||||
template <CipherMode mode>
|
||||
struct KeyHolder
|
||||
{
|
||||
inline StringRef setKey(size_t cipher_key_size, const StringRef & key) const
|
||||
{
|
||||
if (key.size != cipher_key_size)
|
||||
throw DB::Exception(fmt::format("Invalid key size: {} expected {}", key.size, cipher_key_size),
|
||||
DB::ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
return key;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct KeyHolder<CipherMode::MySQLCompatibility>
|
||||
{
|
||||
inline StringRef setKey(size_t cipher_key_size, const StringRef & key)
|
||||
{
|
||||
if (key.size < cipher_key_size)
|
||||
throw DB::Exception(fmt::format("Invalid key size: {} expected {}", key.size, cipher_key_size),
|
||||
DB::ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
// MySQL does something fancy with the keys that are too long,
|
||||
// ruining compatibility with OpenSSL and not improving security.
|
||||
// But we have to do the same to be compatitable with MySQL.
|
||||
// see https://github.com/mysql/mysql-server/blob/8.0/router/src/harness/src/my_aes_openssl.cc#L71
|
||||
// (my_aes_create_key function)
|
||||
return foldEncryptionKeyInMySQLCompatitableMode(cipher_key_size, key, folded_key);
|
||||
}
|
||||
|
||||
~KeyHolder()
|
||||
{
|
||||
OPENSSL_cleanse(folded_key.data(), folded_key.size());
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<char, EVP_MAX_KEY_LENGTH> folded_key;
|
||||
};
|
||||
|
||||
template <CompatibilityMode compatibility_mode>
|
||||
inline void validateCipherMode(const EVP_CIPHER * evp_cipher)
|
||||
{
|
||||
if constexpr (compatibility_mode == CompatibilityMode::MySQL)
|
||||
{
|
||||
switch (EVP_CIPHER_mode(evp_cipher))
|
||||
{
|
||||
case EVP_CIPH_ECB_MODE: [[fallthrough]];
|
||||
case EVP_CIPH_CBC_MODE: [[fallthrough]];
|
||||
case EVP_CIPH_CFB_MODE: [[fallthrough]];
|
||||
case EVP_CIPH_OFB_MODE:
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if constexpr (compatibility_mode == CompatibilityMode::OpenSSL)
|
||||
{
|
||||
switch (EVP_CIPHER_mode(evp_cipher))
|
||||
{
|
||||
case EVP_CIPH_ECB_MODE: [[fallthrough]];
|
||||
case EVP_CIPH_CBC_MODE: [[fallthrough]];
|
||||
case EVP_CIPH_CFB_MODE: [[fallthrough]];
|
||||
case EVP_CIPH_OFB_MODE: [[fallthrough]];
|
||||
case EVP_CIPH_CTR_MODE: [[fallthrough]];
|
||||
case EVP_CIPH_GCM_MODE:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw DB::Exception("Unsupported cipher mode " + std::string(EVP_CIPHER_name(evp_cipher)), DB::ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
template <CipherMode mode>
|
||||
inline void validateIV(const StringRef & iv_value, const size_t cipher_iv_size)
|
||||
{
|
||||
// In MySQL mode we don't care if IV is longer than expected, only if shorter.
|
||||
if ((mode == CipherMode::MySQLCompatibility && iv_value.size != 0 && iv_value.size < cipher_iv_size)
|
||||
|| (mode == CipherMode::OpenSSLCompatibility && iv_value.size != 0 && iv_value.size != cipher_iv_size))
|
||||
throw DB::Exception(fmt::format("Invalid IV size: {} expected {}", iv_value.size, cipher_iv_size),
|
||||
DB::ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
template <typename Impl>
|
||||
class FunctionEncrypt : public IFunction
|
||||
{
|
||||
public:
|
||||
static constexpr OpenSSLDetails::CompatibilityMode compatibility_mode = Impl::compatibility_mode;
|
||||
static constexpr auto name = Impl::name;
|
||||
static FunctionPtr create(const Context &) { return std::make_shared<FunctionEncrypt>(); }
|
||||
|
||||
private:
|
||||
using CipherMode = OpenSSLDetails::CipherMode;
|
||||
|
||||
String getName() const override { return name; }
|
||||
bool isVariadic() const override { return true; }
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {0}; }
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
||||
{
|
||||
auto optional_args = FunctionArgumentDescriptors{
|
||||
{"IV", isStringOrFixedString, nullptr, "Initialization vector binary string"},
|
||||
};
|
||||
|
||||
if constexpr (compatibility_mode == OpenSSLDetails::CompatibilityMode::OpenSSL)
|
||||
{
|
||||
optional_args.emplace_back(FunctionArgumentDescriptor{
|
||||
"AAD", isStringOrFixedString, nullptr, "Additional authenticated data binary string for GCM mode"
|
||||
});
|
||||
}
|
||||
|
||||
validateFunctionArgumentTypes(*this, arguments,
|
||||
FunctionArgumentDescriptors{
|
||||
{"mode", isStringOrFixedString, isColumnConst, "encryption mode string"},
|
||||
{"input", nullptr, nullptr, "plaintext"},
|
||||
{"key", isStringOrFixedString, nullptr, "encryption key binary string"},
|
||||
},
|
||||
optional_args
|
||||
);
|
||||
|
||||
return std::make_shared<DataTypeString>();
|
||||
}
|
||||
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
|
||||
{
|
||||
using namespace OpenSSLDetails;
|
||||
|
||||
const auto mode = arguments[0].column->getDataAt(0);
|
||||
|
||||
if (mode.size == 0 || !std::string_view(mode).starts_with("aes-"))
|
||||
throw Exception("Invalid mode: " + mode.toString(), ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
const auto * evp_cipher = getCipherByName(mode);
|
||||
if (evp_cipher == nullptr)
|
||||
throw Exception("Invalid mode: " + mode.toString(), ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
const auto cipher_mode = EVP_CIPHER_mode(evp_cipher);
|
||||
|
||||
const auto input_column = arguments[1].column;
|
||||
const auto key_column = arguments[2].column;
|
||||
|
||||
OpenSSLDetails::validateCipherMode<compatibility_mode>(evp_cipher);
|
||||
|
||||
ColumnPtr result_column;
|
||||
if (arguments.size() <= 3)
|
||||
result_column = doEncrypt(evp_cipher, input_rows_count, input_column, key_column, nullptr, nullptr);
|
||||
else
|
||||
{
|
||||
const auto iv_column = arguments[3].column;
|
||||
if (compatibility_mode != OpenSSLDetails::CompatibilityMode::MySQL && EVP_CIPHER_iv_length(evp_cipher) == 0)
|
||||
throw Exception(mode.toString() + " does not support IV", ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
if (arguments.size() <= 4)
|
||||
{
|
||||
result_column = doEncrypt(evp_cipher, input_rows_count, input_column, key_column, iv_column, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cipher_mode != EVP_CIPH_GCM_MODE)
|
||||
throw Exception("AAD can be only set for GCM-mode", ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
const auto aad_column = arguments[4].column;
|
||||
result_column = doEncrypt(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column);
|
||||
}
|
||||
}
|
||||
|
||||
return result_column;
|
||||
}
|
||||
|
||||
template <typename InputColumnType, typename KeyColumnType, typename IvColumnType, typename AadColumnType>
|
||||
static ColumnPtr doEncrypt(const EVP_CIPHER * evp_cipher,
|
||||
size_t input_rows_count,
|
||||
const InputColumnType & input_column,
|
||||
const KeyColumnType & key_column,
|
||||
const IvColumnType & iv_column,
|
||||
const AadColumnType & aad_column)
|
||||
{
|
||||
if constexpr (compatibility_mode == OpenSSLDetails::CompatibilityMode::MySQL)
|
||||
{
|
||||
return doEncryptImpl<CipherMode::MySQLCompatibility>(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (EVP_CIPHER_mode(evp_cipher) == EVP_CIPH_GCM_MODE)
|
||||
{
|
||||
return doEncryptImpl<CipherMode::RFC5116_AEAD_AES_GCM>(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column);
|
||||
}
|
||||
else
|
||||
{
|
||||
return doEncryptImpl<CipherMode::OpenSSLCompatibility>(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <CipherMode mode, typename InputColumnType, typename KeyColumnType, typename IvColumnType, typename AadColumnType>
|
||||
static ColumnPtr doEncryptImpl(const EVP_CIPHER * evp_cipher,
|
||||
size_t input_rows_count,
|
||||
const InputColumnType & input_column,
|
||||
const KeyColumnType & key_column,
|
||||
[[maybe_unused]] const IvColumnType & iv_column,
|
||||
[[maybe_unused]] const AadColumnType & aad_column)
|
||||
{
|
||||
using namespace OpenSSLDetails;
|
||||
|
||||
auto evp_ctx_ptr = std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)>(EVP_CIPHER_CTX_new(), &EVP_CIPHER_CTX_free);
|
||||
auto * evp_ctx = evp_ctx_ptr.get();
|
||||
|
||||
const auto block_size = static_cast<size_t>(EVP_CIPHER_block_size(evp_cipher));
|
||||
const auto key_size = static_cast<size_t>(EVP_CIPHER_key_length(evp_cipher));
|
||||
[[maybe_unused]] const auto iv_size = static_cast<size_t>(EVP_CIPHER_iv_length(evp_cipher));
|
||||
const auto tag_size = 16; // https://tools.ietf.org/html/rfc5116#section-5.1
|
||||
|
||||
auto encrypted_result_column = ColumnString::create();
|
||||
auto & encrypted_result_column_data = encrypted_result_column->getChars();
|
||||
auto & encrypted_result_column_offsets = encrypted_result_column->getOffsets();
|
||||
|
||||
{
|
||||
size_t resulting_size = 0;
|
||||
// for modes with block_size > 1, plaintext is padded up to a block_size,
|
||||
// which may result in allocating to much for block_size = 1.
|
||||
// That may lead later to reading unallocated data from underlying PaddedPODArray
|
||||
// due to assumption that it is safe to read up to 15 bytes past end.
|
||||
const auto pad_to_next_block = block_size == 1 ? 0 : 1;
|
||||
for (size_t r = 0; r < input_rows_count; ++r)
|
||||
{
|
||||
resulting_size += (input_column->getDataAt(r).size / block_size + pad_to_next_block) * block_size + 1;
|
||||
if constexpr (mode == CipherMode::RFC5116_AEAD_AES_GCM)
|
||||
resulting_size += tag_size;
|
||||
}
|
||||
#if defined(MEMORY_SANITIZER)
|
||||
encrypted_result_column_data.resize_fill(resulting_size, 0xFF);
|
||||
#else
|
||||
encrypted_result_column_data.resize(resulting_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
auto * encrypted = encrypted_result_column_data.data();
|
||||
|
||||
KeyHolder<mode> key_holder;
|
||||
|
||||
for (size_t r = 0; r < input_rows_count; ++r)
|
||||
{
|
||||
const auto key_value = key_holder.setKey(key_size, key_column->getDataAt(r));
|
||||
auto iv_value = StringRef{};
|
||||
if constexpr (!std::is_same_v<std::nullptr_t, std::decay_t<IvColumnType>>)
|
||||
{
|
||||
iv_value = iv_column->getDataAt(r);
|
||||
}
|
||||
|
||||
const auto input_value = input_column->getDataAt(r);
|
||||
auto aad_value = StringRef{};
|
||||
if constexpr (mode == CipherMode::RFC5116_AEAD_AES_GCM && !std::is_same_v<std::nullptr_t, std::decay_t<AadColumnType>>)
|
||||
{
|
||||
aad_value = aad_column->getDataAt(r);
|
||||
}
|
||||
|
||||
if constexpr (mode != CipherMode::MySQLCompatibility)
|
||||
{
|
||||
// in GCM mode IV can be of arbitrary size (>0), IV is optional for other modes.
|
||||
if (mode == CipherMode::RFC5116_AEAD_AES_GCM && iv_value.size == 0)
|
||||
{
|
||||
throw Exception("Invalid IV size " + std::to_string(iv_value.size) + " != expected size " + std::to_string(iv_size),
|
||||
DB::ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
if (mode != CipherMode::RFC5116_AEAD_AES_GCM && key_value.size != key_size)
|
||||
{
|
||||
throw Exception("Invalid key size " + std::to_string(key_value.size) + " != expected size " + std::to_string(key_size),
|
||||
DB::ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
// Avoid extra work on empty ciphertext/plaintext for some ciphers
|
||||
if (!(input_value.size == 0 && block_size == 1 && mode != CipherMode::RFC5116_AEAD_AES_GCM))
|
||||
{
|
||||
// 1: Init CTX
|
||||
if constexpr (mode == CipherMode::RFC5116_AEAD_AES_GCM)
|
||||
{
|
||||
// 1.a.1: Init CTX with custom IV length and optionally with AAD
|
||||
if (EVP_EncryptInit_ex(evp_ctx, evp_cipher, nullptr, nullptr, nullptr) != 1)
|
||||
onError("Failed to initialize encryption context with cipher");
|
||||
|
||||
if (EVP_CIPHER_CTX_ctrl(evp_ctx, EVP_CTRL_AEAD_SET_IVLEN, iv_value.size, nullptr) != 1)
|
||||
onError("Failed to set custom IV length to " + std::to_string(iv_value.size));
|
||||
|
||||
if (EVP_EncryptInit_ex(evp_ctx, nullptr, nullptr,
|
||||
reinterpret_cast<const unsigned char*>(key_value.data),
|
||||
reinterpret_cast<const unsigned char*>(iv_value.data)) != 1)
|
||||
onError("Failed to set key and IV");
|
||||
|
||||
// 1.a.2 Set AAD
|
||||
if constexpr (!std::is_same_v<std::nullptr_t, std::decay_t<AadColumnType>>)
|
||||
{
|
||||
const auto aad_data = aad_column->getDataAt(r);
|
||||
int tmp_len = 0;
|
||||
if (aad_data.size != 0 && EVP_EncryptUpdate(evp_ctx, nullptr, &tmp_len,
|
||||
reinterpret_cast<const unsigned char *>(aad_data.data), aad_data.size) != 1)
|
||||
onError("Failed to set AAD data");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 1.b: Init CTX
|
||||
validateIV<mode>(iv_value, iv_size);
|
||||
|
||||
if (EVP_EncryptInit_ex(evp_ctx, evp_cipher, nullptr,
|
||||
reinterpret_cast<const unsigned char*>(key_value.data),
|
||||
reinterpret_cast<const unsigned char*>(iv_value.data)) != 1)
|
||||
onError("Failed to initialize cipher context");
|
||||
}
|
||||
|
||||
int output_len = 0;
|
||||
// 2: Feed the data to the cipher
|
||||
if (EVP_EncryptUpdate(evp_ctx,
|
||||
reinterpret_cast<unsigned char*>(encrypted), &output_len,
|
||||
reinterpret_cast<const unsigned char*>(input_value.data), static_cast<int>(input_value.size)) != 1)
|
||||
onError("Failed to encrypt");
|
||||
encrypted += output_len;
|
||||
|
||||
// 3: retrieve encrypted data (ciphertext)
|
||||
if (EVP_EncryptFinal_ex(evp_ctx,
|
||||
reinterpret_cast<unsigned char*>(encrypted), &output_len) != 1)
|
||||
onError("Failed to fetch ciphertext");
|
||||
encrypted += output_len;
|
||||
|
||||
// 4: optionally retrieve a tag and append it to the ciphertext (RFC5116):
|
||||
// https://tools.ietf.org/html/rfc5116#section-5.1
|
||||
if constexpr (mode == CipherMode::RFC5116_AEAD_AES_GCM)
|
||||
{
|
||||
if (EVP_CIPHER_CTX_ctrl(evp_ctx, EVP_CTRL_AEAD_GET_TAG, tag_size, encrypted) != 1)
|
||||
onError("Failed to retrieve GCM tag");
|
||||
encrypted += tag_size;
|
||||
}
|
||||
}
|
||||
|
||||
*encrypted = '\0';
|
||||
++encrypted;
|
||||
|
||||
encrypted_result_column_offsets.push_back(encrypted - encrypted_result_column_data.data());
|
||||
}
|
||||
|
||||
// in case of block size of 1, we overestimate buffer required for encrypted data, fix it up.
|
||||
if (!encrypted_result_column_offsets.empty() && encrypted_result_column_data.size() > encrypted_result_column_offsets.back())
|
||||
{
|
||||
encrypted_result_column_data.resize(encrypted_result_column_offsets.back());
|
||||
}
|
||||
|
||||
encrypted_result_column->validate();
|
||||
return encrypted_result_column;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// AES_decrypt(string, key, block_mode[, init_vector])
|
||||
template <typename Impl>
|
||||
class FunctionDecrypt : public IFunction
|
||||
{
|
||||
public:
|
||||
static constexpr OpenSSLDetails::CompatibilityMode compatibility_mode = Impl::compatibility_mode;
|
||||
static constexpr auto name = Impl::name;
|
||||
static FunctionPtr create(const Context &) { return std::make_shared<FunctionDecrypt>(); }
|
||||
|
||||
private:
|
||||
using CipherMode = OpenSSLDetails::CipherMode;
|
||||
|
||||
String getName() const override { return name; }
|
||||
bool isVariadic() const override { return true; }
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {0}; }
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
||||
{
|
||||
auto optional_args = FunctionArgumentDescriptors{
|
||||
{"IV", isStringOrFixedString, nullptr, "Initialization vector binary string"},
|
||||
};
|
||||
|
||||
if constexpr (compatibility_mode == OpenSSLDetails::CompatibilityMode::OpenSSL)
|
||||
{
|
||||
optional_args.emplace_back(FunctionArgumentDescriptor{
|
||||
"AAD", isStringOrFixedString, nullptr, "Additional authenticated data binary string for GCM mode"
|
||||
});
|
||||
}
|
||||
|
||||
validateFunctionArgumentTypes(*this, arguments,
|
||||
FunctionArgumentDescriptors{
|
||||
{"mode", isStringOrFixedString, isColumnConst, "decryption mode string"},
|
||||
{"input", nullptr, nullptr, "ciphertext"},
|
||||
{"key", isStringOrFixedString, nullptr, "decryption key binary string"},
|
||||
},
|
||||
optional_args
|
||||
);
|
||||
|
||||
return std::make_shared<DataTypeString>();
|
||||
}
|
||||
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
|
||||
{
|
||||
using namespace OpenSSLDetails;
|
||||
|
||||
const auto mode = arguments[0].column->getDataAt(0);
|
||||
if (mode.size == 0 || !std::string_view(mode).starts_with("aes-"))
|
||||
throw Exception("Invalid mode: " + mode.toString(), ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
const auto * evp_cipher = getCipherByName(mode);
|
||||
if (evp_cipher == nullptr)
|
||||
throw Exception("Invalid mode: " + mode.toString(), ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
OpenSSLDetails::validateCipherMode<compatibility_mode>(evp_cipher);
|
||||
|
||||
const auto input_column = arguments[1].column;
|
||||
const auto key_column = arguments[2].column;
|
||||
|
||||
ColumnPtr result_column;
|
||||
if (arguments.size() <= 3)
|
||||
result_column = doDecrypt(evp_cipher, input_rows_count, input_column, key_column, nullptr, nullptr);
|
||||
else
|
||||
{
|
||||
const auto iv_column = arguments[3].column;
|
||||
if (compatibility_mode != OpenSSLDetails::CompatibilityMode::MySQL && EVP_CIPHER_iv_length(evp_cipher) == 0)
|
||||
throw Exception(mode.toString() + " does not support IV", ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
if (arguments.size() <= 4)
|
||||
{
|
||||
result_column = doDecrypt(evp_cipher, input_rows_count, input_column, key_column, iv_column, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (EVP_CIPHER_mode(evp_cipher) != EVP_CIPH_GCM_MODE)
|
||||
throw Exception("AAD can be only set for GCM-mode", ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
const auto aad_column = arguments[4].column;
|
||||
result_column = doDecrypt(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column);
|
||||
}
|
||||
}
|
||||
|
||||
return result_column;
|
||||
}
|
||||
|
||||
template <typename InputColumnType, typename KeyColumnType, typename IvColumnType, typename AadColumnType>
|
||||
static ColumnPtr doDecrypt(const EVP_CIPHER * evp_cipher,
|
||||
size_t input_rows_count,
|
||||
const InputColumnType & input_column,
|
||||
const KeyColumnType & key_column,
|
||||
const IvColumnType & iv_column,
|
||||
const AadColumnType & aad_column)
|
||||
{
|
||||
if constexpr (compatibility_mode == OpenSSLDetails::CompatibilityMode::MySQL)
|
||||
{
|
||||
return doDecryptImpl<CipherMode::MySQLCompatibility>(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto cipher_mode = EVP_CIPHER_mode(evp_cipher);
|
||||
if (cipher_mode == EVP_CIPH_GCM_MODE)
|
||||
{
|
||||
return doDecryptImpl<CipherMode::RFC5116_AEAD_AES_GCM>(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column);
|
||||
}
|
||||
else
|
||||
{
|
||||
return doDecryptImpl<CipherMode::OpenSSLCompatibility>(evp_cipher, input_rows_count, input_column, key_column, iv_column, aad_column);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <CipherMode mode, typename InputColumnType, typename KeyColumnType, typename IvColumnType, typename AadColumnType>
|
||||
static ColumnPtr doDecryptImpl(const EVP_CIPHER * evp_cipher,
|
||||
size_t input_rows_count,
|
||||
const InputColumnType & input_column,
|
||||
const KeyColumnType & key_column,
|
||||
[[maybe_unused]] const IvColumnType & iv_column,
|
||||
[[maybe_unused]] const AadColumnType & aad_column)
|
||||
{
|
||||
using namespace OpenSSLDetails;
|
||||
|
||||
auto evp_ctx_ptr = std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)>(EVP_CIPHER_CTX_new(), &EVP_CIPHER_CTX_free);
|
||||
auto * evp_ctx = evp_ctx_ptr.get();
|
||||
|
||||
[[maybe_unused]] const auto block_size = static_cast<size_t>(EVP_CIPHER_block_size(evp_cipher));
|
||||
[[maybe_unused]] const auto iv_size = static_cast<size_t>(EVP_CIPHER_iv_length(evp_cipher));
|
||||
const auto key_size = static_cast<size_t>(EVP_CIPHER_key_length(evp_cipher));
|
||||
const auto tag_size = 16; // https://tools.ietf.org/html/rfc5116#section-5.1
|
||||
|
||||
auto decrypted_result_column = ColumnString::create();
|
||||
auto & decrypted_result_column_data = decrypted_result_column->getChars();
|
||||
auto & decrypted_result_column_offsets = decrypted_result_column->getOffsets();
|
||||
|
||||
{
|
||||
size_t resulting_size = 0;
|
||||
for (size_t r = 0; r < input_rows_count; ++r)
|
||||
{
|
||||
resulting_size += input_column->getDataAt(r).size + 1;
|
||||
if constexpr (mode == CipherMode::RFC5116_AEAD_AES_GCM)
|
||||
resulting_size -= tag_size;
|
||||
}
|
||||
|
||||
#if defined(MEMORY_SANITIZER)
|
||||
// Pre-fill result column with values to prevent MSAN from dropping dead on
|
||||
// aes-X-ecb mode with "WARNING: MemorySanitizer: use-of-uninitialized-value".
|
||||
// This is most likely to be caused by the underlying assembler implementation:
|
||||
// see crypto/aes/aesni-x86_64.s, function aesni_ecb_encrypt
|
||||
// which msan seems to fail instrument correctly.
|
||||
decrypted_result_column_data.resize_fill(resulting_size, 0xFF);
|
||||
#else
|
||||
decrypted_result_column_data.resize(resulting_size);
|
||||
#endif
|
||||
}
|
||||
auto * decrypted = decrypted_result_column_data.data();
|
||||
|
||||
KeyHolder<mode> key_holder;
|
||||
for (size_t r = 0; r < input_rows_count; ++r)
|
||||
{
|
||||
// 0: prepare key if required
|
||||
auto key_value = key_holder.setKey(key_size, key_column->getDataAt(r));
|
||||
auto iv_value = StringRef{};
|
||||
if constexpr (!std::is_same_v<std::nullptr_t, std::decay_t<IvColumnType>>)
|
||||
{
|
||||
iv_value = iv_column->getDataAt(r);
|
||||
}
|
||||
|
||||
auto input_value = input_column->getDataAt(r);
|
||||
if constexpr (mode == CipherMode::RFC5116_AEAD_AES_GCM)
|
||||
{
|
||||
// empty plaintext results in empty ciphertext + tag, means there should be atleast tag_size bytes.
|
||||
if (input_value.size < tag_size)
|
||||
throw Exception(fmt::format("Encrypted data is too short: only {} bytes, "
|
||||
"should contain at least {} bytes of a tag.",
|
||||
input_value.size, block_size, tag_size), ErrorCodes::BAD_ARGUMENTS);
|
||||
input_value.size -= tag_size;
|
||||
}
|
||||
|
||||
if constexpr (mode != CipherMode::MySQLCompatibility)
|
||||
{
|
||||
// in GCM mode IV can be of arbitrary size (>0), for other modes IV is optional.
|
||||
if (mode == CipherMode::RFC5116_AEAD_AES_GCM && iv_value.size == 0)
|
||||
{
|
||||
throw Exception("Invalid IV size " + std::to_string(iv_value.size) + " != expected size " + std::to_string(iv_size),
|
||||
DB::ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
if (key_value.size != key_size)
|
||||
{
|
||||
throw Exception("Invalid key size " + std::to_string(key_value.size) + " != expected size " + std::to_string(key_size),
|
||||
DB::ErrorCodes::BAD_ARGUMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
// Avoid extra work on empty ciphertext/plaintext for some ciphers
|
||||
if (!(input_value.size == 0 && block_size == 1 && mode != CipherMode::RFC5116_AEAD_AES_GCM))
|
||||
{
|
||||
// 1: Init CTX
|
||||
if constexpr (mode == CipherMode::RFC5116_AEAD_AES_GCM)
|
||||
{
|
||||
if (EVP_DecryptInit_ex(evp_ctx, evp_cipher, nullptr, nullptr, nullptr) != 1)
|
||||
onError("Failed to initialize cipher context 1");
|
||||
|
||||
// 1.a.1 : Set custom IV length
|
||||
if (EVP_CIPHER_CTX_ctrl(evp_ctx, EVP_CTRL_AEAD_SET_IVLEN, iv_value.size, nullptr) != 1)
|
||||
onError("Failed to set custom IV length to " + std::to_string(iv_value.size));
|
||||
|
||||
// 1.a.1 : Init CTX with key and IV
|
||||
if (EVP_DecryptInit_ex(evp_ctx, nullptr, nullptr,
|
||||
reinterpret_cast<const unsigned char*>(key_value.data),
|
||||
reinterpret_cast<const unsigned char*>(iv_value.data)) != 1)
|
||||
onError("Failed to set key and IV");
|
||||
|
||||
// 1.a.2: Set AAD if present
|
||||
if constexpr (!std::is_same_v<std::nullptr_t, std::decay_t<AadColumnType>>)
|
||||
{
|
||||
const auto aad_data = aad_column->getDataAt(r);
|
||||
int tmp_len = 0;
|
||||
if (aad_data.size != 0 && EVP_DecryptUpdate(evp_ctx, nullptr, &tmp_len,
|
||||
reinterpret_cast<const unsigned char *>(aad_data.data), aad_data.size) != 1)
|
||||
onError("Failed to sed AAD data");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 1.b: Init CTX
|
||||
validateIV<mode>(iv_value, iv_size);
|
||||
|
||||
if (EVP_DecryptInit_ex(evp_ctx, evp_cipher, nullptr,
|
||||
reinterpret_cast<const unsigned char*>(key_value.data),
|
||||
reinterpret_cast<const unsigned char*>(iv_value.data)) != 1)
|
||||
onError("Failed to initialize cipher context");
|
||||
}
|
||||
|
||||
// 2: Feed the data to the cipher
|
||||
int output_len = 0;
|
||||
if (EVP_DecryptUpdate(evp_ctx,
|
||||
reinterpret_cast<unsigned char*>(decrypted), &output_len,
|
||||
reinterpret_cast<const unsigned char*>(input_value.data), static_cast<int>(input_value.size)) != 1)
|
||||
onError("Failed to decrypt");
|
||||
decrypted += output_len;
|
||||
|
||||
// 3: optionally get tag from the ciphertext (RFC5116) and feed it to the context
|
||||
if constexpr (mode == CipherMode::RFC5116_AEAD_AES_GCM)
|
||||
{
|
||||
void * tag = const_cast<void *>(reinterpret_cast<const void *>(input_value.data + input_value.size));
|
||||
if (EVP_CIPHER_CTX_ctrl(evp_ctx, EVP_CTRL_AEAD_SET_TAG, tag_size, tag) != 1)
|
||||
onError("Failed to set tag");
|
||||
}
|
||||
|
||||
// 4: retrieve encrypted data (ciphertext)
|
||||
if (EVP_DecryptFinal_ex(evp_ctx,
|
||||
reinterpret_cast<unsigned char*>(decrypted), &output_len) != 1)
|
||||
onError("Failed to decrypt");
|
||||
decrypted += output_len;
|
||||
}
|
||||
|
||||
*decrypted = '\0';
|
||||
++decrypted;
|
||||
|
||||
decrypted_result_column_offsets.push_back(decrypted - decrypted_result_column_data.data());
|
||||
|
||||
}
|
||||
|
||||
// in case we overestimate buffer required for decrypted data, fix it up.
|
||||
if (!decrypted_result_column_offsets.empty() && decrypted_result_column_data.size() > decrypted_result_column_offsets.back())
|
||||
{
|
||||
decrypted_result_column_data.resize(decrypted_result_column_offsets.back());
|
||||
}
|
||||
|
||||
decrypted_result_column->validate();
|
||||
return decrypted_result_column;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@ -104,7 +104,7 @@ public:
|
||||
if (arguments[0]->onlyNull())
|
||||
return arguments[0];
|
||||
|
||||
auto array_type = typeid_cast<const DataTypeArray *>(arguments[0].get());
|
||||
const auto * array_type = typeid_cast<const DataTypeArray *>(arguments[0].get());
|
||||
if (!array_type)
|
||||
throw Exception(
|
||||
"First argument for function " + getName() + " must be an array but it has type " + arguments[0]->getName() + ".",
|
||||
@ -122,23 +122,23 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /* input_rows_count */) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /* input_rows_count */) const override
|
||||
{
|
||||
const IDataType * from_type = columns[arguments[0]].type.get();
|
||||
auto array_type = typeid_cast<const DataTypeArray *>(from_type);
|
||||
auto nested_type = array_type->getNestedType();
|
||||
const IDataType * from_type = arguments[0].type.get();
|
||||
const auto * array_type = typeid_cast<const DataTypeArray *>(from_type);
|
||||
const auto & nested_type = array_type->getNestedType();
|
||||
|
||||
DataTypes argument_types = {nested_type};
|
||||
|
||||
WhichDataType which(nested_type);
|
||||
if (which.isUInt8())
|
||||
executeBitmapData<UInt8>(columns, argument_types, arguments, result);
|
||||
return executeBitmapData<UInt8>(argument_types, arguments);
|
||||
else if (which.isUInt16())
|
||||
executeBitmapData<UInt16>(columns, argument_types, arguments, result);
|
||||
return executeBitmapData<UInt16>(argument_types, arguments);
|
||||
else if (which.isUInt32())
|
||||
executeBitmapData<UInt32>(columns, argument_types, arguments, result);
|
||||
return executeBitmapData<UInt32>(argument_types, arguments);
|
||||
else if (which.isUInt64())
|
||||
executeBitmapData<UInt64>(columns, argument_types, arguments, result);
|
||||
return executeBitmapData<UInt64>(argument_types, arguments);
|
||||
else
|
||||
throw Exception(
|
||||
"Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
@ -146,11 +146,11 @@ public:
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
void executeBitmapData(ColumnsWithTypeAndName & columns, DataTypes & argument_types, const ColumnNumbers & arguments, size_t result) const
|
||||
ColumnPtr executeBitmapData(DataTypes & argument_types, ColumnsWithTypeAndName & arguments) const
|
||||
{
|
||||
// input data
|
||||
const ColumnArray * array = typeid_cast<const ColumnArray *>(columns[arguments[0]].column.get());
|
||||
ColumnPtr mapped = array->getDataPtr();
|
||||
const ColumnArray * array = typeid_cast<const ColumnArray *>(arguments[0].column.get());
|
||||
const ColumnPtr & mapped = array->getDataPtr();
|
||||
const ColumnArray::Offsets & offsets = array->getOffsets();
|
||||
const ColumnVector<T> * column = checkAndGetColumn<ColumnVector<T>>(&*mapped);
|
||||
const typename ColumnVector<T>::Container & input_data = column->getData();
|
||||
@ -174,7 +174,7 @@ private:
|
||||
bitmap_data.rbs.add(input_data[pos]);
|
||||
}
|
||||
}
|
||||
columns[result].column = std::move(col_to);
|
||||
return col_to;
|
||||
}
|
||||
};
|
||||
|
||||
@ -207,32 +207,32 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||
{
|
||||
// input data
|
||||
const auto & return_type = columns[result].type;
|
||||
const auto & return_type = result_type;
|
||||
auto res_ptr = return_type->createColumn();
|
||||
ColumnArray & res = assert_cast<ColumnArray &>(*res_ptr);
|
||||
|
||||
IColumn & res_data = res.getData();
|
||||
ColumnArray::Offsets & res_offsets = res.getOffsets();
|
||||
|
||||
const IDataType * from_type = columns[arguments[0]].type.get();
|
||||
const IDataType * from_type = arguments[0].type.get();
|
||||
const DataTypeAggregateFunction * aggr_type = typeid_cast<const DataTypeAggregateFunction *>(from_type);
|
||||
WhichDataType which(aggr_type->getArgumentsDataTypes()[0]);
|
||||
if (which.isUInt8())
|
||||
executeIntType<UInt8>(columns, arguments, input_rows_count, res_data, res_offsets);
|
||||
executeIntType<UInt8>(arguments, input_rows_count, res_data, res_offsets);
|
||||
else if (which.isUInt16())
|
||||
executeIntType<UInt16>(columns, arguments, input_rows_count, res_data, res_offsets);
|
||||
executeIntType<UInt16>(arguments, input_rows_count, res_data, res_offsets);
|
||||
else if (which.isUInt32())
|
||||
executeIntType<UInt32>(columns, arguments, input_rows_count, res_data, res_offsets);
|
||||
executeIntType<UInt32>(arguments, input_rows_count, res_data, res_offsets);
|
||||
else if (which.isUInt64())
|
||||
executeIntType<UInt64>(columns, arguments, input_rows_count, res_data, res_offsets);
|
||||
executeIntType<UInt64>(arguments, input_rows_count, res_data, res_offsets);
|
||||
else
|
||||
throw Exception(
|
||||
"Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
columns[result].column = std::move(res_ptr);
|
||||
return res_ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -240,11 +240,11 @@ private:
|
||||
|
||||
template <typename T>
|
||||
void executeIntType(
|
||||
ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t input_rows_count, IColumn & res_data_col, ColumnArray::Offsets & res_offsets)
|
||||
ColumnsWithTypeAndName & arguments, size_t input_rows_count, IColumn & res_data_col, ColumnArray::Offsets & res_offsets)
|
||||
const
|
||||
{
|
||||
const ColumnAggregateFunction * column
|
||||
= typeid_cast<const ColumnAggregateFunction *>(columns[arguments[0]].column.get());
|
||||
= typeid_cast<const ColumnAggregateFunction *>(arguments[0].column.get());
|
||||
|
||||
PaddedPODArray<T> & res_data = typeid_cast<ColumnVector<T> &>(res_data_col).getData();
|
||||
ColumnArray::Offset res_offset = 0;
|
||||
@ -282,13 +282,13 @@ public:
|
||||
"First argument for function " + getName() + " must be a bitmap but it has type " + arguments[0]->getName() + ".",
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
auto arg_type1 = typeid_cast<const DataTypeNumber<UInt32> *>(arguments[1].get());
|
||||
const auto * arg_type1 = typeid_cast<const DataTypeNumber<UInt32> *>(arguments[1].get());
|
||||
if (!(arg_type1))
|
||||
throw Exception(
|
||||
"Second argument for function " + getName() + " must be UInt32 but it has type " + arguments[1]->getName() + ".",
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
auto arg_type2 = typeid_cast<const DataTypeNumber<UInt32> *>(arguments[1].get());
|
||||
const auto * arg_type2 = typeid_cast<const DataTypeNumber<UInt32> *>(arguments[1].get());
|
||||
if (!(arg_type2))
|
||||
throw Exception(
|
||||
"Third argument for function " + getName() + " must be UInt32 but it has type " + arguments[2]->getName() + ".",
|
||||
@ -299,19 +299,19 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
|
||||
{
|
||||
const IDataType * from_type = columns[arguments[0]].type.get();
|
||||
const IDataType * from_type = arguments[0].type.get();
|
||||
const DataTypeAggregateFunction * aggr_type = typeid_cast<const DataTypeAggregateFunction *>(from_type);
|
||||
WhichDataType which(aggr_type->getArgumentsDataTypes()[0]);
|
||||
if (which.isUInt8())
|
||||
executeIntType<UInt8>(columns, arguments, result, input_rows_count);
|
||||
return executeIntType<UInt8>(arguments, input_rows_count);
|
||||
else if (which.isUInt16())
|
||||
executeIntType<UInt16>(columns, arguments, result, input_rows_count);
|
||||
return executeIntType<UInt16>(arguments, input_rows_count);
|
||||
else if (which.isUInt32())
|
||||
executeIntType<UInt32>(columns, arguments, result, input_rows_count);
|
||||
return executeIntType<UInt32>(arguments, input_rows_count);
|
||||
else if (which.isUInt64())
|
||||
executeIntType<UInt64>(columns, arguments, result, input_rows_count);
|
||||
return executeIntType<UInt64>(arguments, input_rows_count);
|
||||
else
|
||||
throw Exception(
|
||||
"Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
@ -321,9 +321,7 @@ private:
|
||||
using ToType = UInt64;
|
||||
|
||||
template <typename T>
|
||||
void executeIntType(
|
||||
ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count)
|
||||
const
|
||||
ColumnPtr executeIntType(ColumnsWithTypeAndName & arguments, size_t input_rows_count) const
|
||||
{
|
||||
const IColumn * column_ptrs[3];
|
||||
bool is_column_const[3];
|
||||
@ -333,7 +331,7 @@ private:
|
||||
|
||||
for (size_t i = 0; i < 3; ++i)
|
||||
{
|
||||
column_ptrs[i] = columns[arguments[i]].column.get();
|
||||
column_ptrs[i] = arguments[i].column.get();
|
||||
is_column_const[i] = isColumnConst(*column_ptrs[i]);
|
||||
}
|
||||
if (is_column_const[0])
|
||||
@ -367,7 +365,7 @@ private:
|
||||
= *reinterpret_cast<AggregateFunctionGroupBitmapData<T> *>(col_to->getData()[i]);
|
||||
Impl::apply(bitmap_data_0, range_start, range_end, bitmap_data_2);
|
||||
}
|
||||
columns[result].column = std::move(col_to);
|
||||
return col_to;
|
||||
}
|
||||
};
|
||||
|
||||
@ -435,19 +433,19 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
|
||||
{
|
||||
const IDataType * from_type = columns[arguments[0]].type.get();
|
||||
const IDataType * from_type = arguments[0].type.get();
|
||||
const DataTypeAggregateFunction * aggr_type = typeid_cast<const DataTypeAggregateFunction *>(from_type);
|
||||
WhichDataType which(aggr_type->getArgumentsDataTypes()[0]);
|
||||
if (which.isUInt8())
|
||||
executeIntType<UInt8>(columns, arguments, result, input_rows_count);
|
||||
return executeIntType<UInt8>(arguments, input_rows_count);
|
||||
else if (which.isUInt16())
|
||||
executeIntType<UInt16>(columns, arguments, result, input_rows_count);
|
||||
return executeIntType<UInt16>(arguments, input_rows_count);
|
||||
else if (which.isUInt32())
|
||||
executeIntType<UInt32>(columns, arguments, result, input_rows_count);
|
||||
return executeIntType<UInt32>(arguments, input_rows_count);
|
||||
else if (which.isUInt64())
|
||||
executeIntType<UInt64>(columns, arguments, result, input_rows_count);
|
||||
return executeIntType<UInt64>(arguments, input_rows_count);
|
||||
else
|
||||
throw Exception(
|
||||
"Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
@ -457,8 +455,7 @@ private:
|
||||
using ToType = UInt64;
|
||||
|
||||
template <typename T>
|
||||
void executeIntType(
|
||||
ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const
|
||||
ColumnPtr executeIntType(ColumnsWithTypeAndName & arguments, size_t input_rows_count) const
|
||||
{
|
||||
const IColumn * column_ptrs[3];
|
||||
bool is_column_const[3];
|
||||
@ -468,7 +465,7 @@ private:
|
||||
|
||||
for (size_t i = 0; i < 3; ++i)
|
||||
{
|
||||
column_ptrs[i] = columns[arguments[i]].column.get();
|
||||
column_ptrs[i] = arguments[i].column.get();
|
||||
is_column_const[i] = isColumnConst(*column_ptrs[i]);
|
||||
}
|
||||
if (is_column_const[0])
|
||||
@ -485,7 +482,7 @@ private:
|
||||
array = typeid_cast<const ColumnArray*>(typeid_cast<const ColumnConst*>(column_ptrs[1])->getDataColumnPtr().get());
|
||||
else
|
||||
{
|
||||
array = typeid_cast<const ColumnArray *>(columns[arguments[1]].column.get());
|
||||
array = typeid_cast<const ColumnArray *>(arguments[1].column.get());
|
||||
}
|
||||
const ColumnArray::Offsets & from_offsets = array->getOffsets();
|
||||
const ColumnVector<UInt32>::Container & from_container = typeid_cast<const ColumnVector<UInt32> *>(&array->getData())->getData();
|
||||
@ -493,7 +490,7 @@ private:
|
||||
if (is_column_const[2])
|
||||
array = typeid_cast<const ColumnArray*>(typeid_cast<const ColumnConst*>(column_ptrs[2])->getDataColumnPtr().get());
|
||||
else
|
||||
array = typeid_cast<const ColumnArray *>(columns[arguments[2]].column.get());
|
||||
array = typeid_cast<const ColumnArray *>(arguments[2].column.get());
|
||||
|
||||
const ColumnArray::Offsets & to_offsets = array->getOffsets();
|
||||
const ColumnVector<UInt32>::Container & to_container = typeid_cast<const ColumnVector<UInt32> *>(&array->getData())->getData();
|
||||
@ -538,7 +535,7 @@ private:
|
||||
bitmap_data_2.rbs.merge(bitmap_data_0.rbs);
|
||||
bitmap_data_2.rbs.rb_replace(&from_container[from_start], &to_container[to_start], from_end - from_start);
|
||||
}
|
||||
columns[result].column = std::move(col_to);
|
||||
return col_to;
|
||||
}
|
||||
};
|
||||
|
||||
@ -558,7 +555,7 @@ public:
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
auto bitmap_type = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get());
|
||||
const auto * bitmap_type = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get());
|
||||
if (!(bitmap_type && bitmap_type->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name()))
|
||||
throw Exception(
|
||||
"First argument for function " + getName() + " must be a bitmap but it has type " + arguments[0]->getName() + ".",
|
||||
@ -568,27 +565,27 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
|
||||
{
|
||||
auto col_to = ColumnVector<ToType>::create(input_rows_count);
|
||||
typename ColumnVector<ToType>::Container & vec_to = col_to->getData();
|
||||
const IDataType * from_type = columns[arguments[0]].type.get();
|
||||
const IDataType * from_type = arguments[0].type.get();
|
||||
|
||||
const DataTypeAggregateFunction * aggr_type = typeid_cast<const DataTypeAggregateFunction *>(from_type);
|
||||
WhichDataType which(aggr_type->getArgumentsDataTypes()[0]);
|
||||
if (which.isUInt8())
|
||||
executeIntType<UInt8>(columns, arguments, input_rows_count, vec_to);
|
||||
executeIntType<UInt8>(arguments, input_rows_count, vec_to);
|
||||
else if (which.isUInt16())
|
||||
executeIntType<UInt16>(columns, arguments, input_rows_count, vec_to);
|
||||
executeIntType<UInt16>(arguments, input_rows_count, vec_to);
|
||||
else if (which.isUInt32())
|
||||
executeIntType<UInt32>(columns, arguments, input_rows_count, vec_to);
|
||||
executeIntType<UInt32>(arguments, input_rows_count, vec_to);
|
||||
else if (which.isUInt64())
|
||||
executeIntType<UInt64>(columns, arguments, input_rows_count, vec_to);
|
||||
executeIntType<UInt64>(arguments, input_rows_count, vec_to);
|
||||
else
|
||||
throw Exception(
|
||||
"Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
columns[result].column = std::move(col_to);
|
||||
return col_to;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -596,10 +593,10 @@ private:
|
||||
|
||||
template <typename T>
|
||||
void executeIntType(
|
||||
ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t input_rows_count, typename ColumnVector<ToType>::Container & vec_to) const
|
||||
ColumnsWithTypeAndName & arguments, size_t input_rows_count, typename ColumnVector<ToType>::Container & vec_to) const
|
||||
{
|
||||
const ColumnAggregateFunction * column
|
||||
= typeid_cast<const ColumnAggregateFunction *>(columns[arguments[0]].column.get());
|
||||
= typeid_cast<const ColumnAggregateFunction *>(arguments[0].column.get());
|
||||
for (size_t i = 0; i < input_rows_count; ++i)
|
||||
{
|
||||
const AggregateFunctionGroupBitmapData<T> & bitmap_data
|
||||
@ -722,12 +719,12 @@ public:
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
auto bitmap_type0 = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get());
|
||||
const auto * bitmap_type0 = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get());
|
||||
if (!(bitmap_type0 && bitmap_type0->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name()))
|
||||
throw Exception(
|
||||
"First argument for function " + getName() + " must be a bitmap but it has type " + arguments[0]->getName() + ".",
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
auto arg_type1 = typeid_cast<const DataTypeNumber<UInt32> *>(arguments[1].get());
|
||||
const auto * arg_type1 = typeid_cast<const DataTypeNumber<UInt32> *>(arguments[1].get());
|
||||
if (!(arg_type1))
|
||||
throw Exception(
|
||||
"Second argument for function " + getName() + " must be UInt32 but it has type " + arguments[1]->getName() + ".",
|
||||
@ -738,33 +735,33 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
|
||||
{
|
||||
auto col_to = ColumnVector<UInt8>::create(input_rows_count);
|
||||
typename ColumnVector<UInt8>::Container & vec_to = col_to->getData();
|
||||
const IDataType * from_type = columns[arguments[0]].type.get();
|
||||
const IDataType * from_type = arguments[0].type.get();
|
||||
|
||||
const DataTypeAggregateFunction * aggr_type = typeid_cast<const DataTypeAggregateFunction *>(from_type);
|
||||
WhichDataType which(aggr_type->getArgumentsDataTypes()[0]);
|
||||
if (which.isUInt8())
|
||||
executeIntType<UInt8>(columns, arguments, input_rows_count, vec_to);
|
||||
executeIntType<UInt8>(arguments, input_rows_count, vec_to);
|
||||
else if (which.isUInt16())
|
||||
executeIntType<UInt16>(columns, arguments, input_rows_count, vec_to);
|
||||
executeIntType<UInt16>(arguments, input_rows_count, vec_to);
|
||||
else if (which.isUInt32())
|
||||
executeIntType<UInt32>(columns, arguments, input_rows_count, vec_to);
|
||||
executeIntType<UInt32>(arguments, input_rows_count, vec_to);
|
||||
else if (which.isUInt64())
|
||||
executeIntType<UInt64>(columns, arguments, input_rows_count, vec_to);
|
||||
executeIntType<UInt64>(arguments, input_rows_count, vec_to);
|
||||
else
|
||||
throw Exception(
|
||||
"Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
columns[result].column = std::move(col_to);
|
||||
return col_to;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
void executeIntType(
|
||||
ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t input_rows_count, typename ColumnVector<UInt8>::Container & vec_to) const
|
||||
ColumnsWithTypeAndName & arguments, size_t input_rows_count, typename ColumnVector<UInt8>::Container & vec_to) const
|
||||
{
|
||||
const IColumn * column_ptrs[2];
|
||||
bool is_column_const[2];
|
||||
@ -773,7 +770,7 @@ private:
|
||||
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
{
|
||||
column_ptrs[i] = columns[arguments[i]].column.get();
|
||||
column_ptrs[i] = arguments[i].column.get();
|
||||
is_column_const[i] = isColumnConst(*column_ptrs[i]);
|
||||
}
|
||||
if (is_column_const[0])
|
||||
@ -812,13 +809,13 @@ public:
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
auto bitmap_type0 = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get());
|
||||
const auto * bitmap_type0 = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get());
|
||||
if (!(bitmap_type0 && bitmap_type0->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name()))
|
||||
throw Exception(
|
||||
"First argument for function " + getName() + " must be a bitmap but it has type " + arguments[0]->getName() + ".",
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
auto bitmap_type1 = typeid_cast<const DataTypeAggregateFunction *>(arguments[1].get());
|
||||
const auto * bitmap_type1 = typeid_cast<const DataTypeAggregateFunction *>(arguments[1].get());
|
||||
if (!(bitmap_type1 && bitmap_type1->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name()))
|
||||
throw Exception(
|
||||
"Second argument for function " + getName() + " must be a bitmap but it has type " + arguments[1]->getName() + ".",
|
||||
@ -835,46 +832,46 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
|
||||
{
|
||||
auto col_to = ColumnVector<ToType>::create(input_rows_count);
|
||||
typename ColumnVector<ToType>::Container & vec_to = col_to->getData();
|
||||
const IDataType * from_type = columns[arguments[0]].type.get();
|
||||
const IDataType * from_type = arguments[0].type.get();
|
||||
|
||||
const DataTypeAggregateFunction * aggr_type = typeid_cast<const DataTypeAggregateFunction *>(from_type);
|
||||
WhichDataType which(aggr_type->getArgumentsDataTypes()[0]);
|
||||
if (which.isUInt8())
|
||||
executeIntType<UInt8>(columns, arguments, input_rows_count, vec_to);
|
||||
executeIntType<UInt8>(arguments, input_rows_count, vec_to);
|
||||
else if (which.isUInt16())
|
||||
executeIntType<UInt16>(columns, arguments, input_rows_count, vec_to);
|
||||
executeIntType<UInt16>(arguments, input_rows_count, vec_to);
|
||||
else if (which.isUInt32())
|
||||
executeIntType<UInt32>(columns, arguments, input_rows_count, vec_to);
|
||||
executeIntType<UInt32>(arguments, input_rows_count, vec_to);
|
||||
else if (which.isUInt64())
|
||||
executeIntType<UInt64>(columns, arguments, input_rows_count, vec_to);
|
||||
executeIntType<UInt64>(arguments, input_rows_count, vec_to);
|
||||
else
|
||||
throw Exception(
|
||||
"Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
columns[result].column = std::move(col_to);
|
||||
return col_to;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
void executeIntType(
|
||||
ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t input_rows_count, typename ColumnVector<ToType>::Container & vec_to) const
|
||||
ColumnsWithTypeAndName & arguments, size_t input_rows_count, typename ColumnVector<ToType>::Container & vec_to) const
|
||||
{
|
||||
const ColumnAggregateFunction * column_ptrs[2];
|
||||
bool is_column_const[2];
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
{
|
||||
if (auto argument_column_const = checkAndGetColumn<ColumnConst>(columns[arguments[i]].column.get()))
|
||||
if (const auto * argument_column_const = checkAndGetColumn<ColumnConst>(arguments[i].column.get()))
|
||||
{
|
||||
column_ptrs[i] = typeid_cast<const ColumnAggregateFunction*>(argument_column_const->getDataColumnPtr().get());
|
||||
is_column_const[i] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
column_ptrs[i] = typeid_cast<const ColumnAggregateFunction*>(columns[arguments[i]].column.get());
|
||||
column_ptrs[i] = typeid_cast<const ColumnAggregateFunction*>(arguments[i].column.get());
|
||||
is_column_const[i] = false;
|
||||
}
|
||||
}
|
||||
@ -947,13 +944,13 @@ public:
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
auto bitmap_type0 = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get());
|
||||
const auto * bitmap_type0 = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get());
|
||||
if (!(bitmap_type0 && bitmap_type0->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name()))
|
||||
throw Exception(
|
||||
"First argument for function " + getName() + " must be a bitmap but it has type " + arguments[0]->getName() + ".",
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
auto bitmap_type1 = typeid_cast<const DataTypeAggregateFunction *>(arguments[1].get());
|
||||
const auto * bitmap_type1 = typeid_cast<const DataTypeAggregateFunction *>(arguments[1].get());
|
||||
if (!(bitmap_type1 && bitmap_type1->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name()))
|
||||
throw Exception(
|
||||
"Second argument for function " + getName() + " must be a bitmap but it has type " + arguments[1]->getName() + ".",
|
||||
@ -970,19 +967,19 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
|
||||
{
|
||||
const IDataType * from_type = columns[arguments[0]].type.get();
|
||||
const IDataType * from_type = arguments[0].type.get();
|
||||
const DataTypeAggregateFunction * aggr_type = typeid_cast<const DataTypeAggregateFunction *>(from_type);
|
||||
WhichDataType which(aggr_type->getArgumentsDataTypes()[0]);
|
||||
if (which.isUInt8())
|
||||
executeBitmapData<UInt8>(columns, arguments, result, input_rows_count);
|
||||
return executeBitmapData<UInt8>(arguments, input_rows_count);
|
||||
else if (which.isUInt16())
|
||||
executeBitmapData<UInt16>(columns, arguments, result, input_rows_count);
|
||||
return executeBitmapData<UInt16>(arguments, input_rows_count);
|
||||
else if (which.isUInt32())
|
||||
executeBitmapData<UInt32>(columns, arguments, result, input_rows_count);
|
||||
return executeBitmapData<UInt32>(arguments, input_rows_count);
|
||||
else if (which.isUInt64())
|
||||
executeBitmapData<UInt64>(columns, arguments, result, input_rows_count);
|
||||
return executeBitmapData<UInt64>(arguments, input_rows_count);
|
||||
else
|
||||
throw Exception(
|
||||
"Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
@ -990,20 +987,20 @@ public:
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
void executeBitmapData(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const
|
||||
ColumnPtr executeBitmapData(ColumnsWithTypeAndName & arguments, size_t input_rows_count) const
|
||||
{
|
||||
const ColumnAggregateFunction * column_ptrs[2];
|
||||
bool is_column_const[2];
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
{
|
||||
if (auto argument_column_const = typeid_cast<const ColumnConst *>(columns[arguments[i]].column.get()))
|
||||
if (const auto * argument_column_const = typeid_cast<const ColumnConst *>(arguments[i].column.get()))
|
||||
{
|
||||
column_ptrs[i] = typeid_cast<const ColumnAggregateFunction *>(argument_column_const->getDataColumnPtr().get());
|
||||
is_column_const[i] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
column_ptrs[i] = typeid_cast<const ColumnAggregateFunction *>(columns[arguments[i]].column.get());
|
||||
column_ptrs[i] = typeid_cast<const ColumnAggregateFunction *>(arguments[i].column.get());
|
||||
is_column_const[i] = false;
|
||||
}
|
||||
}
|
||||
@ -1026,7 +1023,7 @@ private:
|
||||
= *reinterpret_cast<const AggregateFunctionGroupBitmapData<T> *>(data_ptr_1);
|
||||
Impl<T>::apply(bitmap_data_1, bitmap_data_2);
|
||||
}
|
||||
columns[result].column = std::move(col_to);
|
||||
return col_to;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -76,7 +76,7 @@ public:
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
const auto ptr = checkAndGetDataType<DataTypeFixedString>(arguments[0].get());
|
||||
const auto * ptr = checkAndGetDataType<DataTypeFixedString>(arguments[0].get());
|
||||
if (!ptr || ptr->getN() != IPV6_BINARY_LENGTH)
|
||||
throw Exception("Illegal type " + arguments[0]->getName() +
|
||||
" of argument of function " + getName() +
|
||||
@ -88,12 +88,12 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const auto & col_type_name = columns[arguments[0]];
|
||||
const auto & col_type_name = arguments[0];
|
||||
const ColumnPtr & column = col_type_name.column;
|
||||
|
||||
if (const auto col_in = checkAndGetColumn<ColumnFixedString>(column.get()))
|
||||
if (const auto * col_in = checkAndGetColumn<ColumnFixedString>(column.get()))
|
||||
{
|
||||
if (col_in->getN() != IPV6_BINARY_LENGTH)
|
||||
throw Exception("Illegal type " + col_type_name.type->getName() +
|
||||
@ -112,8 +112,8 @@ public:
|
||||
vec_res.resize(size * (IPV6_MAX_TEXT_LENGTH + 1));
|
||||
offsets_res.resize(size);
|
||||
|
||||
auto begin = reinterpret_cast<char *>(vec_res.data());
|
||||
auto pos = begin;
|
||||
auto * begin = reinterpret_cast<char *>(vec_res.data());
|
||||
auto * pos = begin;
|
||||
|
||||
for (size_t offset = 0, i = 0; offset < vec_in.size(); offset += IPV6_BINARY_LENGTH, ++i)
|
||||
{
|
||||
@ -123,10 +123,10 @@ public:
|
||||
|
||||
vec_res.resize(pos - begin);
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
else
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
@ -145,7 +145,7 @@ public:
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
const auto ptr = checkAndGetDataType<DataTypeFixedString>(arguments[0].get());
|
||||
const auto * ptr = checkAndGetDataType<DataTypeFixedString>(arguments[0].get());
|
||||
if (!ptr || ptr->getN() != IPV6_BINARY_LENGTH)
|
||||
throw Exception("Illegal type " + arguments[0]->getName() +
|
||||
" of argument 1 of function " + getName() +
|
||||
@ -168,17 +168,17 @@ public:
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {1, 2}; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const auto & col_type_name = columns[arguments[0]];
|
||||
const auto & col_type_name = arguments[0];
|
||||
const ColumnPtr & column = col_type_name.column;
|
||||
|
||||
const auto & col_ipv6_zeroed_tail_bytes_type = columns[arguments[1]];
|
||||
const auto & col_ipv6_zeroed_tail_bytes_type = arguments[1];
|
||||
const auto & col_ipv6_zeroed_tail_bytes = col_ipv6_zeroed_tail_bytes_type.column;
|
||||
const auto & col_ipv4_zeroed_tail_bytes_type = columns[arguments[2]];
|
||||
const auto & col_ipv4_zeroed_tail_bytes_type = arguments[2];
|
||||
const auto & col_ipv4_zeroed_tail_bytes = col_ipv4_zeroed_tail_bytes_type.column;
|
||||
|
||||
if (const auto col_in = checkAndGetColumn<ColumnFixedString>(column.get()))
|
||||
if (const auto * col_in = checkAndGetColumn<ColumnFixedString>(column.get()))
|
||||
{
|
||||
if (col_in->getN() != IPV6_BINARY_LENGTH)
|
||||
throw Exception("Illegal type " + col_type_name.type->getName() +
|
||||
@ -187,7 +187,7 @@ public:
|
||||
", expected FixedString(" + toString(IPV6_BINARY_LENGTH) + ")",
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
const auto ipv6_zeroed_tail_bytes = checkAndGetColumnConst<ColumnVector<UInt8>>(col_ipv6_zeroed_tail_bytes.get());
|
||||
const auto * ipv6_zeroed_tail_bytes = checkAndGetColumnConst<ColumnVector<UInt8>>(col_ipv6_zeroed_tail_bytes.get());
|
||||
if (!ipv6_zeroed_tail_bytes)
|
||||
throw Exception("Illegal type " + col_ipv6_zeroed_tail_bytes_type.type->getName() +
|
||||
" of argument 2 of function " + getName(),
|
||||
@ -199,7 +199,7 @@ public:
|
||||
" of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
const auto ipv4_zeroed_tail_bytes = checkAndGetColumnConst<ColumnVector<UInt8>>(col_ipv4_zeroed_tail_bytes.get());
|
||||
const auto * ipv4_zeroed_tail_bytes = checkAndGetColumnConst<ColumnVector<UInt8>>(col_ipv4_zeroed_tail_bytes.get());
|
||||
if (!ipv4_zeroed_tail_bytes)
|
||||
throw Exception("Illegal type " + col_ipv4_zeroed_tail_bytes_type.type->getName() +
|
||||
" of argument 3 of function " + getName(),
|
||||
@ -221,12 +221,12 @@ public:
|
||||
vec_res.resize(size * (IPV6_MAX_TEXT_LENGTH + 1));
|
||||
offsets_res.resize(size);
|
||||
|
||||
auto begin = reinterpret_cast<char *>(vec_res.data());
|
||||
auto pos = begin;
|
||||
auto * begin = reinterpret_cast<char *>(vec_res.data());
|
||||
auto * pos = begin;
|
||||
|
||||
for (size_t offset = 0, i = 0; offset < vec_in.size(); offset += IPV6_BINARY_LENGTH, ++i)
|
||||
{
|
||||
const auto address = &vec_in[offset];
|
||||
const auto * address = &vec_in[offset];
|
||||
UInt8 zeroed_tail_bytes_count = isIPv4Mapped(address) ? ipv4_zeroed_tail_bytes_count : ipv6_zeroed_tail_bytes_count;
|
||||
cutAddress(reinterpret_cast<const unsigned char *>(address), pos, zeroed_tail_bytes_count);
|
||||
offsets_res[i] = pos - begin;
|
||||
@ -234,22 +234,22 @@ public:
|
||||
|
||||
vec_res.resize(pos - begin);
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
else
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
|
||||
private:
|
||||
bool isIPv4Mapped(const UInt8 * address) const
|
||||
static bool isIPv4Mapped(const UInt8 * address)
|
||||
{
|
||||
return (unalignedLoad<UInt64>(address) == 0) &&
|
||||
((unalignedLoad<UInt64>(address + 8) & 0x00000000FFFFFFFFull) == 0x00000000FFFF0000ull);
|
||||
}
|
||||
|
||||
void cutAddress(const unsigned char * address, char *& dst, UInt8 zeroed_tail_bytes_count) const
|
||||
static void cutAddress(const unsigned char * address, char *& dst, UInt8 zeroed_tail_bytes_count)
|
||||
{
|
||||
formatIPv6(address, dst, zeroed_tail_bytes_count);
|
||||
}
|
||||
@ -277,11 +277,11 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const ColumnPtr & column = columns[arguments[0]].column;
|
||||
const ColumnPtr & column = arguments[0].column;
|
||||
|
||||
if (const auto col_in = checkAndGetColumn<ColumnString>(column.get()))
|
||||
if (const auto * col_in = checkAndGetColumn<ColumnString>(column.get()))
|
||||
{
|
||||
auto col_res = ColumnFixedString::create(IPV6_BINARY_LENGTH);
|
||||
|
||||
@ -301,10 +301,10 @@ public:
|
||||
src_offset = offsets_src[i];
|
||||
}
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
else
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
@ -339,9 +339,9 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const ColumnPtr & column = columns[arguments[0]].column;
|
||||
const ColumnPtr & column = arguments[0].column;
|
||||
|
||||
if (const ColumnUInt32 * col = typeid_cast<const ColumnUInt32 *>(column.get()))
|
||||
{
|
||||
@ -365,10 +365,10 @@ public:
|
||||
|
||||
vec_res.resize(pos - begin);
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
else
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
@ -407,9 +407,9 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const ColumnPtr & column = columns[arguments[0]].column;
|
||||
const ColumnPtr & column = arguments[0].column;
|
||||
|
||||
if (const ColumnString * col = checkAndGetColumn<ColumnString>(column.get()))
|
||||
{
|
||||
@ -428,10 +428,10 @@ public:
|
||||
prev_offset = offsets_src[i];
|
||||
}
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
else
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
@ -460,12 +460,12 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const auto & col_type_name = columns[arguments[0]];
|
||||
const auto & col_type_name = arguments[0];
|
||||
const ColumnPtr & column = col_type_name.column;
|
||||
|
||||
if (const auto col_in = typeid_cast<const ColumnUInt32 *>(column.get()))
|
||||
if (const auto * col_in = typeid_cast<const ColumnUInt32 *>(column.get()))
|
||||
{
|
||||
auto col_res = ColumnFixedString::create(IPV6_BINARY_LENGTH);
|
||||
|
||||
@ -477,16 +477,16 @@ public:
|
||||
for (size_t out_offset = 0, i = 0; out_offset < vec_res.size(); out_offset += IPV6_BINARY_LENGTH, ++i)
|
||||
mapIPv4ToIPv6(vec_in[i], &vec_res[out_offset]);
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
else
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
|
||||
private:
|
||||
void mapIPv4ToIPv6(UInt32 in, UInt8 * buf) const
|
||||
static void mapIPv4ToIPv6(UInt32 in, UInt8 * buf)
|
||||
{
|
||||
unalignedStore<UInt64>(buf, 0);
|
||||
unalignedStore<UInt64>(buf + 8, 0x00000000FFFF0000ull | (static_cast<UInt64>(ntohl(in)) << 32));
|
||||
@ -578,9 +578,9 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const ColumnPtr & column = columns[arguments[0]].column;
|
||||
const ColumnPtr & column = arguments[0].column;
|
||||
|
||||
if (const ColumnUInt64 * col = typeid_cast<const ColumnUInt64 *>(column.get()))
|
||||
{
|
||||
@ -602,10 +602,10 @@ public:
|
||||
offsets_res[i] = current_offset;
|
||||
}
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
else
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
@ -688,9 +688,9 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const ColumnPtr & column = columns[arguments[0]].column;
|
||||
const ColumnPtr & column = arguments[0].column;
|
||||
|
||||
if (const ColumnString * col = checkAndGetColumn<ColumnString>(column.get()))
|
||||
{
|
||||
@ -716,10 +716,10 @@ public:
|
||||
prev_offset = current_offset;
|
||||
}
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
else
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
@ -743,7 +743,7 @@ public:
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
const auto ptr = checkAndGetDataType<DataTypeFixedString>(arguments[0].get());
|
||||
const auto * ptr = checkAndGetDataType<DataTypeFixedString>(arguments[0].get());
|
||||
if (!ptr || ptr->getN() != uuid_bytes_length)
|
||||
throw Exception("Illegal type " + arguments[0]->getName() +
|
||||
" of argument of function " + getName() +
|
||||
@ -755,12 +755,12 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const ColumnWithTypeAndName & col_type_name = columns[arguments[0]];
|
||||
const ColumnWithTypeAndName & col_type_name = arguments[0];
|
||||
const ColumnPtr & column = col_type_name.column;
|
||||
|
||||
if (const auto col_in = checkAndGetColumn<ColumnFixedString>(column.get()))
|
||||
if (const auto * col_in = checkAndGetColumn<ColumnFixedString>(column.get()))
|
||||
{
|
||||
if (col_in->getN() != uuid_bytes_length)
|
||||
throw Exception("Illegal type " + col_type_name.type->getName() +
|
||||
@ -792,10 +792,10 @@ public:
|
||||
offsets_res[i] = dst_offset;
|
||||
}
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
else
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
@ -844,7 +844,7 @@ public:
|
||||
/// String or FixedString(36)
|
||||
if (!isString(arguments[0]))
|
||||
{
|
||||
const auto ptr = checkAndGetDataType<DataTypeFixedString>(arguments[0].get());
|
||||
const auto * ptr = checkAndGetDataType<DataTypeFixedString>(arguments[0].get());
|
||||
if (!ptr || ptr->getN() != uuid_text_length)
|
||||
throw Exception("Illegal type " + arguments[0]->getName() +
|
||||
" of argument of function " + getName() +
|
||||
@ -857,12 +857,12 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const ColumnWithTypeAndName & col_type_name = columns[arguments[0]];
|
||||
const ColumnWithTypeAndName & col_type_name = arguments[0];
|
||||
const ColumnPtr & column = col_type_name.column;
|
||||
|
||||
if (const auto col_in = checkAndGetColumn<ColumnString>(column.get()))
|
||||
if (const auto * col_in = checkAndGetColumn<ColumnString>(column.get()))
|
||||
{
|
||||
const auto & vec_in = col_in->getChars();
|
||||
const auto & offsets_in = col_in->getOffsets();
|
||||
@ -891,9 +891,9 @@ public:
|
||||
src_offset += string_size;
|
||||
}
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
else if (const auto col_in_fixed = checkAndGetColumn<ColumnFixedString>(column.get()))
|
||||
else if (const auto * col_in_fixed = checkAndGetColumn<ColumnFixedString>(column.get()))
|
||||
{
|
||||
if (col_in_fixed->getN() != uuid_text_length)
|
||||
throw Exception("Illegal type " + col_type_name.type->getName() +
|
||||
@ -920,10 +920,10 @@ public:
|
||||
dst_offset += uuid_bytes_length;
|
||||
}
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
else
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of argument of function " + getName(), ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
};
|
||||
@ -1083,7 +1083,7 @@ public:
|
||||
}
|
||||
|
||||
|
||||
void executeOneString(const UInt8 * pos, const UInt8 * end, char *& out) const
|
||||
static void executeOneString(const UInt8 * pos, const UInt8 * end, char *& out)
|
||||
{
|
||||
while (pos < end)
|
||||
{
|
||||
@ -1095,7 +1095,7 @@ public:
|
||||
++out;
|
||||
}
|
||||
|
||||
bool tryExecuteString(const IColumn * col, ColumnPtr & col_res) const
|
||||
static bool tryExecuteString(const IColumn * col, ColumnPtr & col_res)
|
||||
{
|
||||
const ColumnString * col_str_in = checkAndGetColumn<ColumnString>(col);
|
||||
|
||||
@ -1139,7 +1139,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool tryExecuteFixedString(const IColumn * col, ColumnPtr & col_res) const
|
||||
static bool tryExecuteFixedString(const IColumn * col, ColumnPtr & col_res)
|
||||
{
|
||||
const ColumnFixedString * col_fstr_in = checkAndGetColumn<ColumnFixedString>(col);
|
||||
|
||||
@ -1187,10 +1187,10 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const IColumn * column = columns[arguments[0]].column.get();
|
||||
ColumnPtr & res_column = columns[result].column;
|
||||
const IColumn * column = arguments[0].column.get();
|
||||
ColumnPtr res_column;
|
||||
|
||||
if (tryExecuteUInt<UInt8>(column, res_column) ||
|
||||
tryExecuteUInt<UInt16>(column, res_column) ||
|
||||
@ -1203,9 +1203,9 @@ public:
|
||||
tryExecuteDecimal<Decimal32>(column, res_column) ||
|
||||
tryExecuteDecimal<Decimal64>(column, res_column) ||
|
||||
tryExecuteDecimal<Decimal128>(column, res_column))
|
||||
return;
|
||||
return res_column;
|
||||
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
@ -1235,7 +1235,7 @@ public:
|
||||
return std::make_shared<DataTypeString>();
|
||||
}
|
||||
|
||||
void unhexOne(const char * pos, const char * end, char *& out) const
|
||||
static void unhexOne(const char * pos, const char * end, char *& out)
|
||||
{
|
||||
if ((end - pos) & 1)
|
||||
{
|
||||
@ -1255,9 +1255,9 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const ColumnPtr & column = columns[arguments[0]].column;
|
||||
const ColumnPtr & column = arguments[0].column;
|
||||
|
||||
if (const ColumnString * col = checkAndGetColumn<ColumnString>(column.get()))
|
||||
{
|
||||
@ -1290,11 +1290,11 @@ public:
|
||||
|
||||
out_vec.resize(pos - begin);
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
@ -1335,7 +1335,7 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
|
||||
{
|
||||
auto col_str = ColumnString::create();
|
||||
ColumnString::Chars & out_vec = col_str->getChars();
|
||||
@ -1355,7 +1355,7 @@ public:
|
||||
for (size_t idx = 0; idx < arguments.size(); ++idx)
|
||||
{
|
||||
//partial const column
|
||||
columns_holder[idx] = columns[arguments[idx]].column->convertToFullColumnIfConst();
|
||||
columns_holder[idx] = arguments[idx].column->convertToFullColumnIfConst();
|
||||
const IColumn * column = columns_holder[idx].get();
|
||||
|
||||
if (!(executeNumber<UInt8>(*column, out_vec, idx, input_rows_count, size_per_row)
|
||||
@ -1369,12 +1369,12 @@ public:
|
||||
|| executeNumber<Float32>(*column, out_vec, idx, input_rows_count, size_per_row)
|
||||
|| executeNumber<Float64>(*column, out_vec, idx, input_rows_count, size_per_row)))
|
||||
{
|
||||
throw Exception{"Illegal column " + columns[arguments[idx]].column->getName()
|
||||
throw Exception{"Illegal column " + arguments[idx].column->getName()
|
||||
+ " of first argument of function " + getName(), ErrorCodes::ILLEGAL_COLUMN};
|
||||
}
|
||||
}
|
||||
|
||||
columns[result].column = std::move(col_str);
|
||||
return col_str;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -1461,10 +1461,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const IColumn * in_column = columns[arguments[0]].column.get();
|
||||
ColumnPtr & out_column = columns[result].column;
|
||||
const IColumn * in_column = arguments[0].column.get();
|
||||
ColumnPtr out_column;
|
||||
|
||||
if (tryExecute<UInt8>(in_column, out_column) ||
|
||||
tryExecute<UInt16>(in_column, out_column) ||
|
||||
@ -1474,9 +1474,9 @@ public:
|
||||
tryExecute<Int16>(in_column, out_column) ||
|
||||
tryExecute<Int32>(in_column, out_column) ||
|
||||
tryExecute<Int64>(in_column, out_column))
|
||||
return;
|
||||
return out_column;
|
||||
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of first argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
@ -1506,7 +1506,7 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
bool tryExecuteString(const IColumn * col, ColumnPtr & col_res) const
|
||||
static bool tryExecuteString(const IColumn * col, ColumnPtr & col_res)
|
||||
{
|
||||
const ColumnString * col_str_in = checkAndGetColumn<ColumnString>(col);
|
||||
|
||||
@ -1553,7 +1553,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool tryExecuteFixedString(const IColumn * col, ColumnPtr & col_res) const
|
||||
static bool tryExecuteFixedString(const IColumn * col, ColumnPtr & col_res)
|
||||
{
|
||||
const ColumnFixedString * col_fstr_in = checkAndGetColumn<ColumnFixedString>(col);
|
||||
|
||||
@ -1599,15 +1599,15 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const IColumn * column = columns[arguments[0]].column.get();
|
||||
ColumnPtr & res_column = columns[result].column;
|
||||
const IColumn * column = arguments[0].column.get();
|
||||
ColumnPtr res_column;
|
||||
|
||||
if (tryExecuteFixedString(column, res_column) || tryExecuteString(column, res_column))
|
||||
return;
|
||||
return res_column;
|
||||
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
@ -1648,7 +1648,7 @@ public:
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
const auto first_argument = checkAndGetDataType<DataTypeFixedString>(arguments[0].get());
|
||||
const auto * first_argument = checkAndGetDataType<DataTypeFixedString>(arguments[0].get());
|
||||
if (!first_argument || first_argument->getN() != IPV6_BINARY_LENGTH)
|
||||
throw Exception("Illegal type " + arguments[0]->getName() +
|
||||
" of first argument of function " + getName() +
|
||||
@ -1659,7 +1659,7 @@ public:
|
||||
if (!isUInt8(second_argument))
|
||||
throw Exception{"Illegal type " + second_argument->getName()
|
||||
+ " of second argument of function " + getName()
|
||||
+ ", expected numeric type.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT};
|
||||
+ ", expected UInt8", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT};
|
||||
|
||||
DataTypePtr element = DataTypeFactory::instance().get("IPv6");
|
||||
return std::make_shared<DataTypeTuple>(DataTypes{element, element});
|
||||
@ -1668,38 +1668,38 @@ public:
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
|
||||
{
|
||||
const auto & col_type_name_ip = columns[arguments[0]];
|
||||
const auto & col_type_name_ip = arguments[0];
|
||||
const ColumnPtr & column_ip = col_type_name_ip.column;
|
||||
|
||||
const auto col_ip_in = checkAndGetColumn<ColumnFixedString>(column_ip.get());
|
||||
const auto * col_const_ip_in = checkAndGetColumnConst<ColumnFixedString>(column_ip.get());
|
||||
const auto * col_ip_in = checkAndGetColumn<ColumnFixedString>(column_ip.get());
|
||||
|
||||
if (!col_ip_in)
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
if (!col_ip_in && !col_const_ip_in)
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
if (col_ip_in->getN() != IPV6_BINARY_LENGTH)
|
||||
throw Exception("Illegal type " + col_type_name_ip.type->getName() +
|
||||
" of column " + col_ip_in->getName() +
|
||||
" argument of function " + getName() +
|
||||
", expected FixedString(" + toString(IPV6_BINARY_LENGTH) + ")",
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
if ((col_const_ip_in && col_const_ip_in->getValue<String>().size() != IPV6_BINARY_LENGTH) ||
|
||||
(col_ip_in && col_ip_in->getN() != IPV6_BINARY_LENGTH))
|
||||
throw Exception("Illegal type " + col_type_name_ip.type->getName() +
|
||||
" of column " + column_ip->getName() +
|
||||
" argument of function " + getName() +
|
||||
", expected FixedString(" + toString(IPV6_BINARY_LENGTH) + ")",
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
const auto & col_type_name_cidr = columns[arguments[1]];
|
||||
const auto & col_type_name_cidr = arguments[1];
|
||||
const ColumnPtr & column_cidr = col_type_name_cidr.column;
|
||||
|
||||
const auto col_const_cidr_in = checkAndGetColumnConst<ColumnUInt8>(column_cidr.get());
|
||||
const auto col_cidr_in = checkAndGetColumn<ColumnUInt8>(column_cidr.get());
|
||||
const auto * col_const_cidr_in = checkAndGetColumnConst<ColumnUInt8>(column_cidr.get());
|
||||
const auto * col_cidr_in = checkAndGetColumn<ColumnUInt8>(column_cidr.get());
|
||||
|
||||
if (!col_const_cidr_in && !col_cidr_in)
|
||||
throw Exception("Illegal column " + columns[arguments[1]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[1].column->getName()
|
||||
+ " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
const auto & vec_in = col_ip_in->getChars();
|
||||
|
||||
auto col_res_lower_range = ColumnFixedString::create(IPV6_BINARY_LENGTH);
|
||||
auto col_res_upper_range = ColumnFixedString::create(IPV6_BINARY_LENGTH);
|
||||
|
||||
@ -1711,17 +1711,27 @@ public:
|
||||
|
||||
static constexpr UInt8 max_cidr_mask = IPV6_BINARY_LENGTH * 8;
|
||||
|
||||
const String col_const_ip_str = col_const_ip_in ? col_const_ip_in->getValue<String>() : "";
|
||||
const UInt8 * col_const_ip_value = col_const_ip_in ? reinterpret_cast<const UInt8 *>(col_const_ip_str.c_str()) : nullptr;
|
||||
|
||||
for (size_t offset = 0; offset < input_rows_count; ++offset)
|
||||
{
|
||||
const size_t offset_ipv6 = offset * IPV6_BINARY_LENGTH;
|
||||
|
||||
const UInt8 * ip = col_const_ip_in
|
||||
? col_const_ip_value
|
||||
: &col_ip_in->getChars()[offset_ipv6];
|
||||
|
||||
UInt8 cidr = col_const_cidr_in
|
||||
? col_const_cidr_in->getValue<UInt8>()
|
||||
: col_cidr_in->getData()[offset];
|
||||
|
||||
cidr = std::min(cidr, max_cidr_mask);
|
||||
applyCIDRMask(&vec_in[offset_ipv6], &vec_res_lower_range[offset_ipv6], &vec_res_upper_range[offset_ipv6], cidr);
|
||||
|
||||
applyCIDRMask(ip, &vec_res_lower_range[offset_ipv6], &vec_res_upper_range[offset_ipv6], cidr);
|
||||
}
|
||||
|
||||
columns[result].column = ColumnTuple::create(Columns{std::move(col_res_lower_range), std::move(col_res_upper_range)});
|
||||
return ColumnTuple::create(Columns{std::move(col_res_lower_range), std::move(col_res_upper_range)});
|
||||
}
|
||||
};
|
||||
|
||||
@ -1763,7 +1773,7 @@ public:
|
||||
if (!isUInt8(second_argument))
|
||||
throw Exception{"Illegal type " + second_argument->getName()
|
||||
+ " of second argument of function " + getName()
|
||||
+ ", expected numeric type.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT};
|
||||
+ ", expected UInt8", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT};
|
||||
|
||||
DataTypePtr element = DataTypeFactory::instance().get("IPv4");
|
||||
return std::make_shared<DataTypeTuple>(DataTypes{element, element});
|
||||
@ -1772,30 +1782,29 @@ public:
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
|
||||
{
|
||||
const auto & col_type_name_ip = columns[arguments[0]];
|
||||
const auto & col_type_name_ip = arguments[0];
|
||||
const ColumnPtr & column_ip = col_type_name_ip.column;
|
||||
|
||||
const auto col_ip_in = checkAndGetColumn<ColumnUInt32>(column_ip.get());
|
||||
if (!col_ip_in)
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
const auto * col_const_ip_in = checkAndGetColumnConst<ColumnUInt32>(column_ip.get());
|
||||
const auto * col_ip_in = checkAndGetColumn<ColumnUInt32>(column_ip.get());
|
||||
if (!col_const_ip_in && !col_ip_in)
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
const auto & col_type_name_cidr = columns[arguments[1]];
|
||||
const auto & col_type_name_cidr = arguments[1];
|
||||
const ColumnPtr & column_cidr = col_type_name_cidr.column;
|
||||
|
||||
const auto col_const_cidr_in = checkAndGetColumnConst<ColumnUInt8>(column_cidr.get());
|
||||
const auto col_cidr_in = checkAndGetColumn<ColumnUInt8>(column_cidr.get());
|
||||
const auto * col_const_cidr_in = checkAndGetColumnConst<ColumnUInt8>(column_cidr.get());
|
||||
const auto * col_cidr_in = checkAndGetColumn<ColumnUInt8>(column_cidr.get());
|
||||
|
||||
if (!col_const_cidr_in && !col_cidr_in)
|
||||
throw Exception("Illegal column " + columns[arguments[1]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[1].column->getName()
|
||||
+ " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
const auto & vec_in = col_ip_in->getData();
|
||||
|
||||
auto col_res_lower_range = ColumnUInt32::create();
|
||||
auto col_res_upper_range = ColumnUInt32::create();
|
||||
|
||||
@ -1807,14 +1816,18 @@ public:
|
||||
|
||||
for (size_t i = 0; i < input_rows_count; ++i)
|
||||
{
|
||||
UInt32 ip = col_const_ip_in
|
||||
? col_const_ip_in->getValue<UInt32>()
|
||||
: col_ip_in->getData()[i];
|
||||
|
||||
UInt8 cidr = col_const_cidr_in
|
||||
? col_const_cidr_in->getValue<UInt8>()
|
||||
: col_cidr_in->getData()[i];
|
||||
|
||||
std::tie(vec_res_lower_range[i], vec_res_upper_range[i]) = applyCIDRMask(vec_in[i], cidr);
|
||||
std::tie(vec_res_lower_range[i], vec_res_upper_range[i]) = applyCIDRMask(ip, cidr);
|
||||
}
|
||||
|
||||
columns[result].column = ColumnTuple::create(Columns{std::move(col_res_lower_range), std::move(col_res_upper_range)});
|
||||
return ColumnTuple::create(Columns{std::move(col_res_lower_range), std::move(col_res_upper_range)});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -561,7 +561,7 @@ public:
|
||||
static constexpr auto name = Name::name;
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionComparison>(context); }
|
||||
|
||||
FunctionComparison(const Context & context_)
|
||||
explicit FunctionComparison(const Context & context_)
|
||||
: context(context_),
|
||||
check_decimal_overflow(decimalCheckComparisonOverflow(context))
|
||||
{}
|
||||
@ -571,7 +571,7 @@ private:
|
||||
bool check_decimal_overflow = true;
|
||||
|
||||
template <typename T0, typename T1>
|
||||
bool executeNumRightType(ColumnsWithTypeAndName & columns, size_t result, const ColumnVector<T0> * col_left, const IColumn * col_right_untyped) const
|
||||
ColumnPtr executeNumRightType(const ColumnVector<T0> * col_left, const IColumn * col_right_untyped) const
|
||||
{
|
||||
if (const ColumnVector<T1> * col_right = checkAndGetColumn<ColumnVector<T1>>(col_right_untyped))
|
||||
{
|
||||
@ -581,8 +581,7 @@ private:
|
||||
vec_res.resize(col_left->getData().size());
|
||||
NumComparisonImpl<T0, T1, Op<T0, T1>>::vectorVector(col_left->getData(), col_right->getData(), vec_res);
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return true;
|
||||
return col_res;
|
||||
}
|
||||
else if (auto col_right_const = checkAndGetColumnConst<ColumnVector<T1>>(col_right_untyped))
|
||||
{
|
||||
@ -592,15 +591,14 @@ private:
|
||||
vec_res.resize(col_left->size());
|
||||
NumComparisonImpl<T0, T1, Op<T0, T1>>::vectorConstant(col_left->getData(), col_right_const->template getValue<T1>(), vec_res);
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return true;
|
||||
return col_res;
|
||||
}
|
||||
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename T0, typename T1>
|
||||
bool executeNumConstRightType(ColumnsWithTypeAndName & columns, size_t result, const ColumnConst * col_left, const IColumn * col_right_untyped) const
|
||||
ColumnPtr executeNumConstRightType(const ColumnConst * col_left, const IColumn * col_right_untyped) const
|
||||
{
|
||||
if (const ColumnVector<T1> * col_right = checkAndGetColumn<ColumnVector<T1>>(col_right_untyped))
|
||||
{
|
||||
@ -610,41 +608,40 @@ private:
|
||||
vec_res.resize(col_left->size());
|
||||
NumComparisonImpl<T0, T1, Op<T0, T1>>::constantVector(col_left->template getValue<T0>(), col_right->getData(), vec_res);
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return true;
|
||||
return col_res;
|
||||
}
|
||||
else if (auto col_right_const = checkAndGetColumnConst<ColumnVector<T1>>(col_right_untyped))
|
||||
{
|
||||
UInt8 res = 0;
|
||||
NumComparisonImpl<T0, T1, Op<T0, T1>>::constantConstant(col_left->template getValue<T0>(), col_right_const->template getValue<T1>(), res);
|
||||
|
||||
columns[result].column = DataTypeUInt8().createColumnConst(col_left->size(), toField(res));
|
||||
return true;
|
||||
return DataTypeUInt8().createColumnConst(col_left->size(), toField(res));
|
||||
}
|
||||
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename T0>
|
||||
bool executeNumLeftType(ColumnsWithTypeAndName & columns, size_t result, const IColumn * col_left_untyped, const IColumn * col_right_untyped) const
|
||||
ColumnPtr executeNumLeftType(const IColumn * col_left_untyped, const IColumn * col_right_untyped) const
|
||||
{
|
||||
ColumnPtr res = nullptr;
|
||||
if (const ColumnVector<T0> * col_left = checkAndGetColumn<ColumnVector<T0>>(col_left_untyped))
|
||||
{
|
||||
if ( executeNumRightType<T0, UInt8>(columns, result, col_left, col_right_untyped)
|
||||
|| executeNumRightType<T0, UInt16>(columns, result, col_left, col_right_untyped)
|
||||
|| executeNumRightType<T0, UInt32>(columns, result, col_left, col_right_untyped)
|
||||
|| executeNumRightType<T0, UInt64>(columns, result, col_left, col_right_untyped)
|
||||
|| executeNumRightType<T0, UInt128>(columns, result, col_left, col_right_untyped)
|
||||
|| executeNumRightType<T0, UInt256>(columns, result, col_left, col_right_untyped)
|
||||
|| executeNumRightType<T0, Int8>(columns, result, col_left, col_right_untyped)
|
||||
|| executeNumRightType<T0, Int16>(columns, result, col_left, col_right_untyped)
|
||||
|| executeNumRightType<T0, Int32>(columns, result, col_left, col_right_untyped)
|
||||
|| executeNumRightType<T0, Int64>(columns, result, col_left, col_right_untyped)
|
||||
|| executeNumRightType<T0, Int128>(columns, result, col_left, col_right_untyped)
|
||||
|| executeNumRightType<T0, Int256>(columns, result, col_left, col_right_untyped)
|
||||
|| executeNumRightType<T0, Float32>(columns, result, col_left, col_right_untyped)
|
||||
|| executeNumRightType<T0, Float64>(columns, result, col_left, col_right_untyped))
|
||||
return true;
|
||||
if ( (res = executeNumRightType<T0, UInt8>(col_left, col_right_untyped))
|
||||
|| (res = executeNumRightType<T0, UInt16>(col_left, col_right_untyped))
|
||||
|| (res = executeNumRightType<T0, UInt32>(col_left, col_right_untyped))
|
||||
|| (res = executeNumRightType<T0, UInt64>(col_left, col_right_untyped))
|
||||
|| (res = executeNumRightType<T0, UInt128>(col_left, col_right_untyped))
|
||||
|| (res = executeNumRightType<T0, UInt256>(col_left, col_right_untyped))
|
||||
|| (res = executeNumRightType<T0, Int8>(col_left, col_right_untyped))
|
||||
|| (res = executeNumRightType<T0, Int16>(col_left, col_right_untyped))
|
||||
|| (res = executeNumRightType<T0, Int32>(col_left, col_right_untyped))
|
||||
|| (res = executeNumRightType<T0, Int64>(col_left, col_right_untyped))
|
||||
|| (res = executeNumRightType<T0, Int128>(col_left, col_right_untyped))
|
||||
|| (res = executeNumRightType<T0, Int256>(col_left, col_right_untyped))
|
||||
|| (res = executeNumRightType<T0, Float32>(col_left, col_right_untyped))
|
||||
|| (res = executeNumRightType<T0, Float64>(col_left, col_right_untyped)))
|
||||
return res;
|
||||
else
|
||||
throw Exception("Illegal column " + col_right_untyped->getName()
|
||||
+ " of second argument of function " + getName(),
|
||||
@ -652,34 +649,35 @@ private:
|
||||
}
|
||||
else if (auto col_left_const = checkAndGetColumnConst<ColumnVector<T0>>(col_left_untyped))
|
||||
{
|
||||
if ( executeNumConstRightType<T0, UInt8>(columns, result, col_left_const, col_right_untyped)
|
||||
|| executeNumConstRightType<T0, UInt16>(columns, result, col_left_const, col_right_untyped)
|
||||
|| executeNumConstRightType<T0, UInt32>(columns, result, col_left_const, col_right_untyped)
|
||||
|| executeNumConstRightType<T0, UInt64>(columns, result, col_left_const, col_right_untyped)
|
||||
|| executeNumConstRightType<T0, UInt128>(columns, result, col_left_const, col_right_untyped)
|
||||
|| executeNumConstRightType<T0, UInt256>(columns, result, col_left_const, col_right_untyped)
|
||||
|| executeNumConstRightType<T0, Int8>(columns, result, col_left_const, col_right_untyped)
|
||||
|| executeNumConstRightType<T0, Int16>(columns, result, col_left_const, col_right_untyped)
|
||||
|| executeNumConstRightType<T0, Int32>(columns, result, col_left_const, col_right_untyped)
|
||||
|| executeNumConstRightType<T0, Int64>(columns, result, col_left_const, col_right_untyped)
|
||||
|| executeNumConstRightType<T0, Int128>(columns, result, col_left_const, col_right_untyped)
|
||||
|| executeNumConstRightType<T0, Int256>(columns, result, col_left_const, col_right_untyped)
|
||||
|| executeNumConstRightType<T0, Float32>(columns, result, col_left_const, col_right_untyped)
|
||||
|| executeNumConstRightType<T0, Float64>(columns, result, col_left_const, col_right_untyped))
|
||||
return true;
|
||||
if ( (res = executeNumConstRightType<T0, UInt8>(col_left_const, col_right_untyped))
|
||||
|| (res = executeNumConstRightType<T0, UInt16>(col_left_const, col_right_untyped))
|
||||
|| (res = executeNumConstRightType<T0, UInt32>(col_left_const, col_right_untyped))
|
||||
|| (res = executeNumConstRightType<T0, UInt64>(col_left_const, col_right_untyped))
|
||||
|| (res = executeNumConstRightType<T0, UInt128>(col_left_const, col_right_untyped))
|
||||
|| (res = executeNumConstRightType<T0, UInt256>(col_left_const, col_right_untyped))
|
||||
|| (res = executeNumConstRightType<T0, Int8>(col_left_const, col_right_untyped))
|
||||
|| (res = executeNumConstRightType<T0, Int16>(col_left_const, col_right_untyped))
|
||||
|| (res = executeNumConstRightType<T0, Int32>(col_left_const, col_right_untyped))
|
||||
|| (res = executeNumConstRightType<T0, Int64>(col_left_const, col_right_untyped))
|
||||
|| (res = executeNumConstRightType<T0, Int128>(col_left_const, col_right_untyped))
|
||||
|| (res = executeNumConstRightType<T0, Int256>(col_left_const, col_right_untyped))
|
||||
|| (res = executeNumConstRightType<T0, Float32>(col_left_const, col_right_untyped))
|
||||
|| (res = executeNumConstRightType<T0, Float64>(col_left_const, col_right_untyped)))
|
||||
return res;
|
||||
else
|
||||
throw Exception("Illegal column " + col_right_untyped->getName()
|
||||
+ " of second argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void executeDecimal(ColumnsWithTypeAndName & columns, size_t result, const ColumnWithTypeAndName & col_left, const ColumnWithTypeAndName & col_right) const
|
||||
ColumnPtr executeDecimal(const ColumnWithTypeAndName & col_left, const ColumnWithTypeAndName & col_right) const
|
||||
{
|
||||
TypeIndex left_number = col_left.type->getTypeId();
|
||||
TypeIndex right_number = col_right.type->getTypeId();
|
||||
ColumnPtr res;
|
||||
|
||||
auto call = [&](const auto & types) -> bool
|
||||
{
|
||||
@ -688,18 +686,19 @@ private:
|
||||
using RightDataType = typename Types::RightType;
|
||||
|
||||
if (check_decimal_overflow)
|
||||
DecimalComparison<LeftDataType, RightDataType, Op, true>(columns, result, col_left, col_right);
|
||||
return (res = DecimalComparison<LeftDataType, RightDataType, Op, true>::apply(col_left, col_right)) != nullptr;
|
||||
else
|
||||
DecimalComparison<LeftDataType, RightDataType, Op, false>(columns, result, col_left, col_right);
|
||||
return true;
|
||||
return (res = DecimalComparison<LeftDataType, RightDataType, Op, false>::apply(col_left, col_right)) != nullptr;
|
||||
};
|
||||
|
||||
if (!callOnBasicTypes<true, false, true, true>(left_number, right_number, call))
|
||||
throw Exception("Wrong call for " + getName() + " with " + col_left.type->getName() + " and " + col_right.type->getName(),
|
||||
ErrorCodes::LOGICAL_ERROR);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool executeString(ColumnsWithTypeAndName & columns, size_t result, const IColumn * c0, const IColumn * c1) const
|
||||
ColumnPtr executeString(const IColumn * c0, const IColumn * c1) const
|
||||
{
|
||||
const ColumnString * c0_string = checkAndGetColumn<ColumnString>(c0);
|
||||
const ColumnString * c1_string = checkAndGetColumn<ColumnString>(c1);
|
||||
@ -710,7 +709,7 @@ private:
|
||||
const ColumnConst * c1_const = checkAndGetColumnConstStringOrFixedString(c1);
|
||||
|
||||
if (!((c0_string || c0_fixed_string || c0_const) && (c1_string || c1_fixed_string || c1_const)))
|
||||
return false;
|
||||
return nullptr;
|
||||
|
||||
const ColumnString::Chars * c0_const_chars = nullptr;
|
||||
const ColumnString::Chars * c1_const_chars = nullptr;
|
||||
@ -759,12 +758,11 @@ private:
|
||||
|
||||
if (c0_const && c1_const)
|
||||
{
|
||||
auto res = executeString(columns, result, &c0_const->getDataColumn(), &c1_const->getDataColumn());
|
||||
auto res = executeString(&c0_const->getDataColumn(), &c1_const->getDataColumn());
|
||||
if (!res)
|
||||
return false;
|
||||
return nullptr;
|
||||
|
||||
columns[result].column = ColumnConst::create(columns[result].column, c0_const->size());
|
||||
return true;
|
||||
return ColumnConst::create(res, c0_const->size());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -818,13 +816,12 @@ private:
|
||||
+ " of arguments of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
columns[result].column = std::move(c_res);
|
||||
return true;
|
||||
return c_res;
|
||||
}
|
||||
}
|
||||
|
||||
bool executeWithConstString(
|
||||
ColumnsWithTypeAndName & columns, size_t result, const IColumn * col_left_untyped, const IColumn * col_right_untyped,
|
||||
ColumnPtr executeWithConstString(
|
||||
const DataTypePtr & result_type, const IColumn * col_left_untyped, const IColumn * col_right_untyped,
|
||||
const DataTypePtr & left_type, const DataTypePtr & right_type, size_t input_rows_count) const
|
||||
{
|
||||
/// To compare something with const string, we cast constant to appropriate type and compare as usual.
|
||||
@ -835,7 +832,7 @@ private:
|
||||
const ColumnConst * right_const = checkAndGetColumnConstStringOrFixedString(col_right_untyped);
|
||||
|
||||
if (!left_const && !right_const)
|
||||
return false;
|
||||
return nullptr;
|
||||
|
||||
const IDataType * type_string = left_const ? left_type.get() : right_type.get();
|
||||
const DataTypePtr & type_to_compare = !left_const ? left_type : right_type;
|
||||
@ -846,29 +843,25 @@ private:
|
||||
/// If not possible to convert, comparison with =, <, >, <=, >= yields to false and comparison with != yields to true.
|
||||
if (converted.isNull())
|
||||
{
|
||||
columns[result].column = DataTypeUInt8().createColumnConst(input_rows_count, IsOperation<Op>::not_equals);
|
||||
return DataTypeUInt8().createColumnConst(input_rows_count, IsOperation<Op>::not_equals);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto column_converted = type_to_compare->createColumnConst(input_rows_count, converted);
|
||||
|
||||
ColumnsWithTypeAndName tmp_columns_columns
|
||||
ColumnsWithTypeAndName tmp_columns
|
||||
{
|
||||
{ left_const ? column_converted : col_left_untyped->getPtr(), type_to_compare, "" },
|
||||
{ !left_const ? column_converted : col_right_untyped->getPtr(), type_to_compare, "" },
|
||||
columns[result]
|
||||
};
|
||||
|
||||
executeImpl(tmp_columns_columns, {0, 1}, 2, input_rows_count);
|
||||
|
||||
columns[result].column = std::move(tmp_columns_columns[2].column);
|
||||
return executeImpl(tmp_columns, result_type, input_rows_count);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void executeTuple(ColumnsWithTypeAndName & columns, size_t result, const ColumnWithTypeAndName & c0, const ColumnWithTypeAndName & c1,
|
||||
size_t input_rows_count) const
|
||||
ColumnPtr executeTuple(
|
||||
const DataTypePtr & result_type, const ColumnWithTypeAndName & c0, const ColumnWithTypeAndName & c1,
|
||||
size_t input_rows_count) const
|
||||
{
|
||||
/** We will lexicographically compare the tuples. This is done as follows:
|
||||
* x == y : x1 == y1 && x2 == y2 ...
|
||||
@ -892,12 +885,8 @@ private:
|
||||
if (tuple_size != typeid_cast<const DataTypeTuple &>(*c1.type).getElements().size())
|
||||
throw Exception("Cannot compare tuples of different sizes.", ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
auto & res = columns[result];
|
||||
if (res.type->onlyNull())
|
||||
{
|
||||
res.column = res.type->createColumnConstWithDefaultValue(input_rows_count);
|
||||
return;
|
||||
}
|
||||
if (result_type->onlyNull())
|
||||
return result_type->createColumnConstWithDefaultValue(input_rows_count);
|
||||
|
||||
ColumnsWithTypeAndName x(tuple_size);
|
||||
ColumnsWithTypeAndName y(tuple_size);
|
||||
@ -927,18 +916,16 @@ private:
|
||||
y[i].column = y_columns[i];
|
||||
}
|
||||
|
||||
executeTupleImpl(columns, result, x, y, tuple_size, input_rows_count);
|
||||
return executeTupleImpl(x, y, tuple_size, input_rows_count);
|
||||
}
|
||||
|
||||
void executeTupleImpl(ColumnsWithTypeAndName & columns, size_t result, const ColumnsWithTypeAndName & x,
|
||||
ColumnPtr executeTupleImpl(const ColumnsWithTypeAndName & x,
|
||||
const ColumnsWithTypeAndName & y, size_t tuple_size,
|
||||
size_t input_rows_count) const;
|
||||
|
||||
void executeTupleEqualityImpl(
|
||||
ColumnPtr executeTupleEqualityImpl(
|
||||
std::shared_ptr<IFunctionOverloadResolver> func_compare,
|
||||
std::shared_ptr<IFunctionOverloadResolver> func_convolution,
|
||||
ColumnsWithTypeAndName & columns,
|
||||
size_t result,
|
||||
const ColumnsWithTypeAndName & x,
|
||||
const ColumnsWithTypeAndName & y,
|
||||
size_t tuple_size,
|
||||
@ -947,84 +934,70 @@ private:
|
||||
if (0 == tuple_size)
|
||||
throw Exception("Comparison of zero-sized tuples is not implemented.", ErrorCodes::NOT_IMPLEMENTED);
|
||||
|
||||
ColumnsWithTypeAndName convolution_types(tuple_size);
|
||||
ColumnsWithTypeAndName convolution_columns(tuple_size);
|
||||
ColumnsWithTypeAndName tmp_columns(2);
|
||||
|
||||
ColumnsWithTypeAndName tmp_columns;
|
||||
for (size_t i = 0; i < tuple_size; ++i)
|
||||
{
|
||||
tmp_columns.emplace_back(x[i]);
|
||||
tmp_columns.emplace_back(y[i]);
|
||||
tmp_columns[0] = x[i];
|
||||
tmp_columns[1] = y[i];
|
||||
|
||||
auto impl = func_compare->build({x[i], y[i]});
|
||||
convolution_types[i].type = impl->getReturnType();
|
||||
auto impl = func_compare->build(tmp_columns);
|
||||
convolution_columns[i].type = impl->getResultType();
|
||||
|
||||
/// Comparison of the elements.
|
||||
tmp_columns.emplace_back(ColumnWithTypeAndName{ nullptr, impl->getReturnType(), "" });
|
||||
impl->execute(tmp_columns, {i * 3, i * 3 + 1}, i * 3 + 2, input_rows_count);
|
||||
convolution_columns[i].column = impl->execute(tmp_columns, impl->getResultType(), input_rows_count);
|
||||
}
|
||||
|
||||
if (tuple_size == 1)
|
||||
{
|
||||
/// Do not call AND for single-element tuple.
|
||||
columns[result].column = tmp_columns[2].column;
|
||||
return;
|
||||
return convolution_columns[0].column;
|
||||
}
|
||||
|
||||
/// Logical convolution.
|
||||
|
||||
ColumnNumbers convolution_args(tuple_size);
|
||||
for (size_t i = 0; i < tuple_size; ++i)
|
||||
convolution_args[i] = i * 3 + 2;
|
||||
|
||||
auto impl = func_convolution->build(convolution_types);
|
||||
tmp_columns.emplace_back(ColumnWithTypeAndName{ nullptr, impl->getReturnType(), "" });
|
||||
|
||||
impl->execute(tmp_columns, convolution_args, tuple_size * 3, input_rows_count);
|
||||
columns[result].column = tmp_columns[tuple_size * 3].column;
|
||||
auto impl = func_convolution->build(convolution_columns);
|
||||
return impl->execute(convolution_columns, impl->getResultType(), input_rows_count);
|
||||
}
|
||||
|
||||
void executeTupleLessGreaterImpl(
|
||||
ColumnPtr executeTupleLessGreaterImpl(
|
||||
std::shared_ptr<IFunctionOverloadResolver> func_compare_head,
|
||||
std::shared_ptr<IFunctionOverloadResolver> func_compare_tail,
|
||||
std::shared_ptr<IFunctionOverloadResolver> func_and,
|
||||
std::shared_ptr<IFunctionOverloadResolver> func_or,
|
||||
std::shared_ptr<IFunctionOverloadResolver> func_equals,
|
||||
ColumnsWithTypeAndName & columns,
|
||||
size_t result,
|
||||
const ColumnsWithTypeAndName & x,
|
||||
const ColumnsWithTypeAndName & y,
|
||||
size_t tuple_size,
|
||||
size_t input_rows_count) const
|
||||
{
|
||||
ColumnsWithTypeAndName tmp_columns;
|
||||
ColumnsWithTypeAndName less_columns(tuple_size);
|
||||
ColumnsWithTypeAndName equal_columns(tuple_size - 1);
|
||||
ColumnsWithTypeAndName tmp_columns(2);
|
||||
|
||||
/// Pairwise comparison of the inequality of all elements; on the equality of all elements except the last.
|
||||
/// (x[i], y[i], x[i] < y[i], x[i] == y[i])
|
||||
for (size_t i = 0; i < tuple_size; ++i)
|
||||
{
|
||||
tmp_columns.emplace_back(x[i]);
|
||||
tmp_columns.emplace_back(y[i]);
|
||||
|
||||
tmp_columns.emplace_back(ColumnWithTypeAndName()); // pos == i * 4 + 2
|
||||
tmp_columns[0] = x[i];
|
||||
tmp_columns[1] = y[i];
|
||||
|
||||
if (i + 1 != tuple_size)
|
||||
{
|
||||
auto impl_head = func_compare_head->build({x[i], y[i]});
|
||||
tmp_columns[i * 4 + 2].type = impl_head->getReturnType();
|
||||
impl_head->execute(tmp_columns, {i * 4, i * 4 + 1}, i * 4 + 2, input_rows_count);
|
||||
auto impl_head = func_compare_head->build(tmp_columns);
|
||||
less_columns[i].type = impl_head->getResultType();
|
||||
less_columns[i].column = impl_head->execute(tmp_columns, less_columns[i].type, input_rows_count);
|
||||
|
||||
tmp_columns.emplace_back(ColumnWithTypeAndName()); // i * 4 + 3
|
||||
|
||||
auto impl_equals = func_equals->build({x[i], y[i]});
|
||||
tmp_columns[i * 4 + 3].type = impl_equals->getReturnType();
|
||||
impl_equals->execute(tmp_columns, {i * 4, i * 4 + 1}, i * 4 + 3, input_rows_count);
|
||||
auto impl_equals = func_equals->build(tmp_columns);
|
||||
equal_columns[i].type = impl_equals->getResultType();
|
||||
equal_columns[i].column = impl_equals->execute(tmp_columns, equal_columns[i].type, input_rows_count);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
auto impl_tail = func_compare_tail->build({x[i], y[i]});
|
||||
tmp_columns[i * 4 + 2].type = impl_tail->getReturnType();
|
||||
impl_tail->execute(tmp_columns, {i * 4, i * 4 + 1}, i * 4 + 2, input_rows_count);
|
||||
auto impl_tail = func_compare_tail->build(tmp_columns);
|
||||
less_columns[i].type = impl_tail->getResultType();
|
||||
less_columns[i].column = impl_tail->execute(tmp_columns, less_columns[i].type, input_rows_count);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1035,38 +1008,28 @@ private:
|
||||
/// for (int i = tuple_size - 2; i >= 0; --i)
|
||||
/// res = (res && `x == y`[i]) || `x < y`[i];
|
||||
size_t i = tuple_size - 1;
|
||||
tmp_columns[0] = less_columns[i];
|
||||
while (i > 0)
|
||||
{
|
||||
--i;
|
||||
|
||||
size_t and_lhs_pos = tmp_columns.size() - 1; // res
|
||||
size_t and_rhs_pos = i * 4 + 3; // `x == y`[i]
|
||||
tmp_columns.emplace_back(ColumnWithTypeAndName());
|
||||
tmp_columns[1] = equal_columns[i];
|
||||
auto func_and_adaptor = func_and->build(tmp_columns);
|
||||
|
||||
ColumnsWithTypeAndName and_args = {{ nullptr, tmp_columns[and_lhs_pos].type, "" },
|
||||
{ nullptr, tmp_columns[and_rhs_pos].type, "" }};
|
||||
tmp_columns[0].column = func_and_adaptor->execute(tmp_columns, func_and_adaptor->getResultType(), input_rows_count);
|
||||
tmp_columns[0].type = func_and_adaptor->getResultType();
|
||||
|
||||
auto func_and_adaptor = func_and->build(and_args);
|
||||
tmp_columns[tmp_columns.size() - 1].type = func_and_adaptor->getReturnType();
|
||||
func_and_adaptor->execute(tmp_columns, {and_lhs_pos, and_rhs_pos}, tmp_columns.size() - 1, input_rows_count);
|
||||
|
||||
size_t or_lhs_pos = tmp_columns.size() - 1; // (res && `x == y`[i])
|
||||
size_t or_rhs_pos = i * 4 + 2; // `x < y`[i]
|
||||
tmp_columns.emplace_back(ColumnWithTypeAndName());
|
||||
|
||||
ColumnsWithTypeAndName or_args = {{ nullptr, tmp_columns[or_lhs_pos].type, "" },
|
||||
{ nullptr, tmp_columns[or_rhs_pos].type, "" }};
|
||||
|
||||
auto func_or_adaptor = func_or->build(or_args);
|
||||
tmp_columns[tmp_columns.size() - 1].type = func_or_adaptor->getReturnType();
|
||||
func_or_adaptor->execute(tmp_columns, {or_lhs_pos, or_rhs_pos}, tmp_columns.size() - 1, input_rows_count);
|
||||
tmp_columns[1] = less_columns[i];
|
||||
auto func_or_adaptor = func_or->build(tmp_columns);
|
||||
|
||||
tmp_columns[0].column = func_or_adaptor->execute(tmp_columns, func_or_adaptor->getResultType(), input_rows_count);
|
||||
tmp_columns[tmp_columns.size() - 1].type = func_or_adaptor->getResultType();
|
||||
}
|
||||
|
||||
columns[result].column = tmp_columns[tmp_columns.size() - 1].column;
|
||||
return tmp_columns[0].column;
|
||||
}
|
||||
|
||||
void executeGenericIdenticalTypes(ColumnsWithTypeAndName & columns, size_t result, const IColumn * c0, const IColumn * c1) const
|
||||
ColumnPtr executeGenericIdenticalTypes(const IColumn * c0, const IColumn * c1) const
|
||||
{
|
||||
bool c0_const = isColumnConst(*c0);
|
||||
bool c1_const = isColumnConst(*c1);
|
||||
@ -1075,7 +1038,7 @@ private:
|
||||
{
|
||||
UInt8 res = 0;
|
||||
GenericComparisonImpl<Op<int, int>>::constantConstant(*c0, *c1, res);
|
||||
columns[result].column = DataTypeUInt8().createColumnConst(c0->size(), toField(res));
|
||||
return DataTypeUInt8().createColumnConst(c0->size(), toField(res));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1090,18 +1053,18 @@ private:
|
||||
else
|
||||
GenericComparisonImpl<Op<int, int>>::vectorVector(*c0, *c1, vec_res);
|
||||
|
||||
columns[result].column = std::move(c_res);
|
||||
return c_res;
|
||||
}
|
||||
}
|
||||
|
||||
void executeGeneric(ColumnsWithTypeAndName & columns, size_t result, const ColumnWithTypeAndName & c0, const ColumnWithTypeAndName & c1) const
|
||||
ColumnPtr executeGeneric(const ColumnWithTypeAndName & c0, const ColumnWithTypeAndName & c1) const
|
||||
{
|
||||
DataTypePtr common_type = getLeastSupertype({c0.type, c1.type});
|
||||
|
||||
ColumnPtr c0_converted = castColumn(c0, common_type);
|
||||
ColumnPtr c1_converted = castColumn(c1, common_type);
|
||||
|
||||
executeGenericIdenticalTypes(columns, result, c0_converted.get(), c1_converted.get());
|
||||
return executeGenericIdenticalTypes(c0_converted.get(), c1_converted.get());
|
||||
}
|
||||
|
||||
public:
|
||||
@ -1157,7 +1120,7 @@ public:
|
||||
{
|
||||
ColumnsWithTypeAndName args = {{nullptr, left_tuple->getElements()[i], ""},
|
||||
{nullptr, right_tuple->getElements()[i], ""}};
|
||||
auto element_type = adaptor.build(args)->getReturnType();
|
||||
auto element_type = adaptor.build(args)->getResultType();
|
||||
has_nullable = has_nullable || element_type->isNullable();
|
||||
has_null = has_null || element_type->onlyNull();
|
||||
}
|
||||
@ -1173,10 +1136,10 @@ public:
|
||||
return std::make_shared<DataTypeUInt8>();
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||
{
|
||||
const auto & col_with_type_and_name_left = columns[arguments[0]];
|
||||
const auto & col_with_type_and_name_right = columns[arguments[1]];
|
||||
const auto & col_with_type_and_name_left = arguments[0];
|
||||
const auto & col_with_type_and_name_right = arguments[1];
|
||||
const IColumn * col_left_untyped = col_with_type_and_name_left.column.get();
|
||||
const IColumn * col_right_untyped = col_with_type_and_name_right.column.get();
|
||||
|
||||
@ -1194,13 +1157,11 @@ public:
|
||||
|| IsOperation<Op>::less_or_equals
|
||||
|| IsOperation<Op>::greater_or_equals)
|
||||
{
|
||||
columns[result].column = DataTypeUInt8().createColumnConst(input_rows_count, 1u);
|
||||
return;
|
||||
return DataTypeUInt8().createColumnConst(input_rows_count, 1u);
|
||||
}
|
||||
else
|
||||
{
|
||||
columns[result].column = DataTypeUInt8().createColumnConst(input_rows_count, 0u);
|
||||
return;
|
||||
return DataTypeUInt8().createColumnConst(input_rows_count, 0u);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1216,39 +1177,44 @@ public:
|
||||
bool date_and_datetime = (which_left.idx != which_right.idx) &&
|
||||
which_left.isDateOrDateTime() && which_right.isDateOrDateTime();
|
||||
|
||||
ColumnPtr res;
|
||||
if (left_is_num && right_is_num && !date_and_datetime)
|
||||
{
|
||||
if (!(executeNumLeftType<UInt8>(columns, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<UInt16>(columns, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<UInt32>(columns, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<UInt64>(columns, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<UInt128>(columns, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<UInt256>(columns, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<Int8>(columns, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<Int16>(columns, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<Int32>(columns, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<Int64>(columns, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<Int128>(columns, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<Int256>(columns, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<Float32>(columns, result, col_left_untyped, col_right_untyped)
|
||||
|| executeNumLeftType<Float64>(columns, result, col_left_untyped, col_right_untyped)))
|
||||
if (!((res = executeNumLeftType<UInt8>(col_left_untyped, col_right_untyped))
|
||||
|| (res = executeNumLeftType<UInt16>(col_left_untyped, col_right_untyped))
|
||||
|| (res = executeNumLeftType<UInt32>(col_left_untyped, col_right_untyped))
|
||||
|| (res = executeNumLeftType<UInt64>(col_left_untyped, col_right_untyped))
|
||||
|| (res = executeNumLeftType<UInt128>(col_left_untyped, col_right_untyped))
|
||||
|| (res = executeNumLeftType<UInt256>(col_left_untyped, col_right_untyped))
|
||||
|| (res = executeNumLeftType<Int8>(col_left_untyped, col_right_untyped))
|
||||
|| (res = executeNumLeftType<Int16>(col_left_untyped, col_right_untyped))
|
||||
|| (res = executeNumLeftType<Int32>(col_left_untyped, col_right_untyped))
|
||||
|| (res = executeNumLeftType<Int64>(col_left_untyped, col_right_untyped))
|
||||
|| (res = executeNumLeftType<Int128>(col_left_untyped, col_right_untyped))
|
||||
|| (res = executeNumLeftType<Int256>(col_left_untyped, col_right_untyped))
|
||||
|| (res = executeNumLeftType<Float32>(col_left_untyped, col_right_untyped))
|
||||
|| (res = executeNumLeftType<Float64>(col_left_untyped, col_right_untyped))))
|
||||
throw Exception("Illegal column " + col_left_untyped->getName()
|
||||
+ " of first argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
return res;
|
||||
}
|
||||
else if (checkAndGetDataType<DataTypeTuple>(left_type.get())
|
||||
&& checkAndGetDataType<DataTypeTuple>(right_type.get()))
|
||||
{
|
||||
executeTuple(columns, result, col_with_type_and_name_left, col_with_type_and_name_right, input_rows_count);
|
||||
return executeTuple(result_type, col_with_type_and_name_left, col_with_type_and_name_right, input_rows_count);
|
||||
}
|
||||
else if (left_is_string && right_is_string && executeString(columns, result, col_left_untyped, col_right_untyped))
|
||||
else if (left_is_string && right_is_string && (res = executeString(col_left_untyped, col_right_untyped)))
|
||||
{
|
||||
return res;
|
||||
}
|
||||
else if (executeWithConstString(
|
||||
columns, result, col_left_untyped, col_right_untyped,
|
||||
else if ((res = executeWithConstString(
|
||||
result_type, col_left_untyped, col_right_untyped,
|
||||
left_type, right_type,
|
||||
input_rows_count))
|
||||
input_rows_count)))
|
||||
{
|
||||
return res;
|
||||
}
|
||||
else if (isColumnedAsDecimal(left_type) || isColumnedAsDecimal(right_type))
|
||||
{
|
||||
@ -1257,15 +1223,15 @@ public:
|
||||
throw Exception("No operation " + getName() + " between " + left_type->getName() + " and " + right_type->getName(),
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
executeDecimal(columns, result, col_with_type_and_name_left, col_with_type_and_name_right);
|
||||
return executeDecimal(col_with_type_and_name_left, col_with_type_and_name_right);
|
||||
}
|
||||
else if (left_type->equals(*right_type))
|
||||
{
|
||||
executeGenericIdenticalTypes(columns, result, col_left_untyped, col_right_untyped);
|
||||
return executeGenericIdenticalTypes(col_left_untyped, col_right_untyped);
|
||||
}
|
||||
else
|
||||
{
|
||||
executeGeneric(columns, result, col_with_type_and_name_left, col_with_type_and_name_right);
|
||||
return executeGeneric(col_with_type_and_name_left, col_with_type_and_name_right);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,10 +65,10 @@ public:
|
||||
return {1};
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
if (isColumnConst(*columns[arguments[1]].column))
|
||||
executeConstBuckets(columns, arguments, result);
|
||||
if (isColumnConst(*arguments[1].column))
|
||||
return executeConstBuckets(arguments);
|
||||
else
|
||||
throw Exception(
|
||||
"The second argument of function " + getName() + " (number of buckets) must be constant", ErrorCodes::BAD_ARGUMENTS);
|
||||
@ -93,9 +93,9 @@ private:
|
||||
return static_cast<BucketsType>(buckets);
|
||||
}
|
||||
|
||||
void executeConstBuckets(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result) const
|
||||
ColumnPtr executeConstBuckets(ColumnsWithTypeAndName & arguments) const
|
||||
{
|
||||
Field buckets_field = (*columns[arguments[1]].column)[0];
|
||||
Field buckets_field = (*arguments[1].column)[0];
|
||||
BucketsType num_buckets;
|
||||
|
||||
if (buckets_field.getType() == Field::Types::Int64)
|
||||
@ -106,8 +106,8 @@ private:
|
||||
throw Exception("Illegal type " + String(buckets_field.getTypeName()) + " of the second argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
const auto & hash_col = columns[arguments[0]].column;
|
||||
const IDataType * hash_type = columns[arguments[0]].type.get();
|
||||
const auto & hash_col = arguments[0].column;
|
||||
const IDataType * hash_type = arguments[0].type.get();
|
||||
auto res_col = ColumnVector<ResultType>::create();
|
||||
|
||||
WhichDataType which(hash_type);
|
||||
@ -132,7 +132,7 @@ private:
|
||||
throw Exception("Illegal type " + hash_type->getName() + " of the first argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
columns[result].column = std::move(res_col);
|
||||
return res_col;
|
||||
}
|
||||
|
||||
template <typename CurrentHashType>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -183,17 +183,17 @@ public:
|
||||
|
||||
bool isDeterministic() const override { return false; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
/// The dictionary key that defines the "point of view".
|
||||
std::string dict_key;
|
||||
|
||||
if (arguments.size() == 2)
|
||||
{
|
||||
const ColumnConst * key_col = checkAndGetColumnConst<ColumnString>(columns[arguments[1]].column.get());
|
||||
const ColumnConst * key_col = checkAndGetColumnConst<ColumnString>(arguments[1].column.get());
|
||||
|
||||
if (!key_col)
|
||||
throw Exception("Illegal column " + columns[arguments[1]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[1].column->getName()
|
||||
+ " of second ('point of view') argument of function " + name
|
||||
+ ". Must be constant string.",
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
@ -203,7 +203,7 @@ public:
|
||||
|
||||
const typename DictGetter::Dst & dict = DictGetter::get(*owned_dict, dict_key);
|
||||
|
||||
if (const ColumnVector<T> * col_from = checkAndGetColumn<ColumnVector<T>>(columns[arguments[0]].column.get()))
|
||||
if (const ColumnVector<T> * col_from = checkAndGetColumn<ColumnVector<T>>(arguments[0].column.get()))
|
||||
{
|
||||
auto col_to = ColumnVector<T>::create();
|
||||
|
||||
@ -215,10 +215,10 @@ public:
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
vec_to[i] = Transform::apply(vec_from[i], dict);
|
||||
|
||||
columns[result].column = std::move(col_to);
|
||||
return col_to;
|
||||
}
|
||||
else
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of first argument of function " + name,
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
@ -279,17 +279,17 @@ public:
|
||||
|
||||
bool isDeterministic() const override { return false; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
/// The dictionary key that defines the "point of view".
|
||||
std::string dict_key;
|
||||
|
||||
if (arguments.size() == 3)
|
||||
{
|
||||
const ColumnConst * key_col = checkAndGetColumnConst<ColumnString>(columns[arguments[2]].column.get());
|
||||
const ColumnConst * key_col = checkAndGetColumnConst<ColumnString>(arguments[2].column.get());
|
||||
|
||||
if (!key_col)
|
||||
throw Exception("Illegal column " + columns[arguments[2]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[2].column->getName()
|
||||
+ " of third ('point of view') argument of function " + name
|
||||
+ ". Must be constant string.",
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
@ -299,10 +299,10 @@ public:
|
||||
|
||||
const typename DictGetter::Dst & dict = DictGetter::get(*owned_dict, dict_key);
|
||||
|
||||
const ColumnVector<T> * col_vec1 = checkAndGetColumn<ColumnVector<T>>(columns[arguments[0]].column.get());
|
||||
const ColumnVector<T> * col_vec2 = checkAndGetColumn<ColumnVector<T>>(columns[arguments[1]].column.get());
|
||||
const ColumnConst * col_const1 = checkAndGetColumnConst<ColumnVector<T>>(columns[arguments[0]].column.get());
|
||||
const ColumnConst * col_const2 = checkAndGetColumnConst<ColumnVector<T>>(columns[arguments[1]].column.get());
|
||||
const ColumnVector<T> * col_vec1 = checkAndGetColumn<ColumnVector<T>>(arguments[0].column.get());
|
||||
const ColumnVector<T> * col_vec2 = checkAndGetColumn<ColumnVector<T>>(arguments[1].column.get());
|
||||
const ColumnConst * col_const1 = checkAndGetColumnConst<ColumnVector<T>>(arguments[0].column.get());
|
||||
const ColumnConst * col_const2 = checkAndGetColumnConst<ColumnVector<T>>(arguments[1].column.get());
|
||||
|
||||
if (col_vec1 && col_vec2)
|
||||
{
|
||||
@ -317,7 +317,7 @@ public:
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
vec_to[i] = Transform::apply(vec_from1[i], vec_from2[i], dict);
|
||||
|
||||
columns[result].column = std::move(col_to);
|
||||
return col_to;
|
||||
}
|
||||
else if (col_vec1 && col_const2)
|
||||
{
|
||||
@ -332,7 +332,7 @@ public:
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
vec_to[i] = Transform::apply(vec_from1[i], const_from2, dict);
|
||||
|
||||
columns[result].column = std::move(col_to);
|
||||
return col_to;
|
||||
}
|
||||
else if (col_const1 && col_vec2)
|
||||
{
|
||||
@ -347,16 +347,16 @@ public:
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
vec_to[i] = Transform::apply(const_from1, vec_from2[i], dict);
|
||||
|
||||
columns[result].column = std::move(col_to);
|
||||
return col_to;
|
||||
}
|
||||
else if (col_const1 && col_const2)
|
||||
{
|
||||
columns[result].column = DataTypeUInt8().createColumnConst(col_const1->size(),
|
||||
return DataTypeUInt8().createColumnConst(col_const1->size(),
|
||||
toField(Transform::apply(col_const1->template getValue<T>(), col_const2->template getValue<T>(), dict)));
|
||||
}
|
||||
else
|
||||
throw Exception("Illegal columns " + columns[arguments[0]].column->getName()
|
||||
+ " and " + columns[arguments[1]].column->getName()
|
||||
throw Exception("Illegal columns " + arguments[0].column->getName()
|
||||
+ " and " + arguments[1].column->getName()
|
||||
+ " of arguments of function " + name,
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
@ -415,17 +415,17 @@ public:
|
||||
|
||||
bool isDeterministic() const override { return false; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
/// The dictionary key that defines the "point of view".
|
||||
std::string dict_key;
|
||||
|
||||
if (arguments.size() == 2)
|
||||
{
|
||||
const ColumnConst * key_col = checkAndGetColumnConst<ColumnString>(columns[arguments[1]].column.get());
|
||||
const ColumnConst * key_col = checkAndGetColumnConst<ColumnString>(arguments[1].column.get());
|
||||
|
||||
if (!key_col)
|
||||
throw Exception("Illegal column " + columns[arguments[1]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[1].column->getName()
|
||||
+ " of second ('point of view') argument of function " + name
|
||||
+ ". Must be constant string.",
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
@ -435,7 +435,7 @@ public:
|
||||
|
||||
const typename DictGetter::Dst & dict = DictGetter::get(*owned_dict, dict_key);
|
||||
|
||||
if (const ColumnVector<T> * col_from = checkAndGetColumn<ColumnVector<T>>(columns[arguments[0]].column.get()))
|
||||
if (const ColumnVector<T> * col_from = checkAndGetColumn<ColumnVector<T>>(arguments[0].column.get()))
|
||||
{
|
||||
auto col_values = ColumnVector<T>::create();
|
||||
auto col_offsets = ColumnArray::ColumnOffsets::create();
|
||||
@ -459,10 +459,10 @@ public:
|
||||
res_offsets[i] = res_values.size();
|
||||
}
|
||||
|
||||
columns[result].column = ColumnArray::create(std::move(col_values), std::move(col_offsets));
|
||||
return ColumnArray::create(std::move(col_values), std::move(col_offsets));
|
||||
}
|
||||
else
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of first argument of function " + name,
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
@ -620,24 +620,24 @@ public:
|
||||
|
||||
bool isDeterministic() const override { return false; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
RegionsNames::Language language = RegionsNames::Language::ru;
|
||||
|
||||
/// If the result language is specified
|
||||
if (arguments.size() == 2)
|
||||
{
|
||||
if (const ColumnConst * col_language = checkAndGetColumnConst<ColumnString>(columns[arguments[1]].column.get()))
|
||||
if (const ColumnConst * col_language = checkAndGetColumnConst<ColumnString>(arguments[1].column.get()))
|
||||
language = RegionsNames::getLanguageEnum(col_language->getValue<String>());
|
||||
else
|
||||
throw Exception("Illegal column " + columns[arguments[1]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[1].column->getName()
|
||||
+ " of the second argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
|
||||
const RegionsNames & dict = *owned_dict;
|
||||
|
||||
if (const ColumnUInt32 * col_from = typeid_cast<const ColumnUInt32 *>(columns[arguments[0]].column.get()))
|
||||
if (const ColumnUInt32 * col_from = typeid_cast<const ColumnUInt32 *>(arguments[0].column.get()))
|
||||
{
|
||||
auto col_to = ColumnString::create();
|
||||
|
||||
@ -649,10 +649,10 @@ public:
|
||||
col_to->insertDataWithTerminatingZero(name_ref.data, name_ref.size + 1);
|
||||
}
|
||||
|
||||
columns[result].column = std::move(col_to);
|
||||
return col_to;
|
||||
}
|
||||
else
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of the first argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -69,9 +69,9 @@ DataTypePtr FunctionModelEvaluate::getReturnTypeImpl(const ColumnsWithTypeAndNam
|
||||
return type;
|
||||
}
|
||||
|
||||
void FunctionModelEvaluate::executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const
|
||||
ColumnPtr FunctionModelEvaluate::executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const
|
||||
{
|
||||
const auto * name_col = checkAndGetColumnConst<ColumnString>(columns[arguments[0]].column.get());
|
||||
const auto * name_col = checkAndGetColumnConst<ColumnString>(arguments[0].column.get());
|
||||
if (!name_col)
|
||||
throw Exception("First argument of function " + getName() + " must be a constant string",
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
@ -85,7 +85,7 @@ void FunctionModelEvaluate::executeImpl(ColumnsWithTypeAndName & columns, const
|
||||
column_ptrs.reserve(arguments.size());
|
||||
for (auto arg : ext::range(1, arguments.size()))
|
||||
{
|
||||
auto & column = columns[arguments[arg]].column;
|
||||
auto & column = arguments[arg].column;
|
||||
column_ptrs.push_back(column.get());
|
||||
if (auto full_column = column->convertToFullColumnIfConst())
|
||||
{
|
||||
@ -130,7 +130,7 @@ void FunctionModelEvaluate::executeImpl(ColumnsWithTypeAndName & columns, const
|
||||
res = ColumnNullable::create(res, null_map);
|
||||
}
|
||||
|
||||
columns[result].column = res;
|
||||
return res;
|
||||
}
|
||||
|
||||
void registerFunctionsExternalModels(FunctionFactory & factory)
|
||||
|
@ -32,7 +32,7 @@ public:
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override;
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override;
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override;
|
||||
|
||||
private:
|
||||
const ExternalModelsLoader & models_loader;
|
||||
|
@ -543,9 +543,9 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
if (const ColumnString * col_from = checkAndGetColumn<ColumnString>(columns[arguments[0]].column.get()))
|
||||
if (const ColumnString * col_from = checkAndGetColumn<ColumnString>(arguments[0].column.get()))
|
||||
{
|
||||
auto col_to = ColumnFixedString::create(Impl::length);
|
||||
|
||||
@ -566,10 +566,10 @@ public:
|
||||
current_offset = offsets[i];
|
||||
}
|
||||
|
||||
columns[result].column = std::move(col_to);
|
||||
return col_to;
|
||||
}
|
||||
else if (
|
||||
const ColumnFixedString * col_from_fix = checkAndGetColumn<ColumnFixedString>(columns[arguments[0]].column.get()))
|
||||
const ColumnFixedString * col_from_fix = checkAndGetColumn<ColumnFixedString>(arguments[0].column.get()))
|
||||
{
|
||||
auto col_to = ColumnFixedString::create(Impl::length);
|
||||
const typename ColumnFixedString::Chars & data = col_from_fix->getChars();
|
||||
@ -582,10 +582,10 @@ public:
|
||||
Impl::apply(
|
||||
reinterpret_cast<const char *>(&data[i * length]), length, reinterpret_cast<uint8_t *>(&chars_to[i * Impl::length]));
|
||||
}
|
||||
columns[result].column = std::move(col_to);
|
||||
return col_to;
|
||||
}
|
||||
else
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of first argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
@ -604,11 +604,11 @@ private:
|
||||
using ToType = typename Impl::ReturnType;
|
||||
|
||||
template <typename FromType>
|
||||
void executeType(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result) const
|
||||
ColumnPtr executeType(ColumnsWithTypeAndName & arguments) const
|
||||
{
|
||||
using ColVecType = std::conditional_t<IsDecimalNumber<FromType>, ColumnDecimal<FromType>, ColumnVector<FromType>>;
|
||||
|
||||
if (const ColVecType * col_from = checkAndGetColumn<ColVecType>(columns[arguments[0]].column.get()))
|
||||
if (const ColVecType * col_from = checkAndGetColumn<ColVecType>(arguments[0].column.get()))
|
||||
{
|
||||
auto col_to = ColumnVector<ToType>::create();
|
||||
|
||||
@ -620,10 +620,10 @@ private:
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
vec_to[i] = Impl::apply(vec_from[i]);
|
||||
|
||||
columns[result].column = std::move(col_to);
|
||||
return col_to;
|
||||
}
|
||||
else
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of first argument of function " + Name::name,
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
@ -647,25 +647,37 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const IDataType * from_type = columns[arguments[0]].type.get();
|
||||
const IDataType * from_type = arguments[0].type.get();
|
||||
WhichDataType which(from_type);
|
||||
|
||||
if (which.isUInt8()) executeType<UInt8>(columns, arguments, result);
|
||||
else if (which.isUInt16()) executeType<UInt16>(columns, arguments, result);
|
||||
else if (which.isUInt32()) executeType<UInt32>(columns, arguments, result);
|
||||
else if (which.isUInt64()) executeType<UInt64>(columns, arguments, result);
|
||||
else if (which.isInt8()) executeType<Int8>(columns, arguments, result);
|
||||
else if (which.isInt16()) executeType<Int16>(columns, arguments, result);
|
||||
else if (which.isInt32()) executeType<Int32>(columns, arguments, result);
|
||||
else if (which.isInt64()) executeType<Int64>(columns, arguments, result);
|
||||
else if (which.isDate()) executeType<UInt16>(columns, arguments, result);
|
||||
else if (which.isDateTime()) executeType<UInt32>(columns, arguments, result);
|
||||
else if (which.isDecimal32()) executeType<Decimal32>(columns, arguments, result);
|
||||
else if (which.isDecimal64()) executeType<Decimal64>(columns, arguments, result);
|
||||
if (which.isUInt8())
|
||||
return executeType<UInt8>(arguments);
|
||||
else if (which.isUInt16())
|
||||
return executeType<UInt16>(arguments);
|
||||
else if (which.isUInt32())
|
||||
return executeType<UInt32>(arguments);
|
||||
else if (which.isUInt64())
|
||||
return executeType<UInt64>(arguments);
|
||||
else if (which.isInt8())
|
||||
return executeType<Int8>(arguments);
|
||||
else if (which.isInt16())
|
||||
return executeType<Int16>(arguments);
|
||||
else if (which.isInt32())
|
||||
return executeType<Int32>(arguments);
|
||||
else if (which.isInt64())
|
||||
return executeType<Int64>(arguments);
|
||||
else if (which.isDate())
|
||||
return executeType<UInt16>(arguments);
|
||||
else if (which.isDateTime())
|
||||
return executeType<UInt32>(arguments);
|
||||
else if (which.isDecimal32())
|
||||
return executeType<Decimal32>(arguments);
|
||||
else if (which.isDecimal64())
|
||||
return executeType<Decimal64>(arguments);
|
||||
else
|
||||
throw Exception("Illegal type " + columns[arguments[0]].type->getName() + " of argument of function " + getName(),
|
||||
throw Exception("Illegal type " + arguments[0].type->getName() + " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
}
|
||||
};
|
||||
@ -689,9 +701,9 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||
{
|
||||
selector.selectAndExecute(columns, arguments, result, input_rows_count);
|
||||
return selector.selectAndExecute(arguments, result_type, input_rows_count);
|
||||
}
|
||||
|
||||
static FunctionPtr create(const Context & context)
|
||||
@ -886,7 +898,7 @@ private:
|
||||
}
|
||||
else if (const ColumnConst * col_from_const = checkAndGetColumnConstStringOrFixedString(column))
|
||||
{
|
||||
String value = col_from_const->getValue<String>().data();
|
||||
String value = col_from_const->getValue<String>();
|
||||
const ToType hash = Impl::apply(value.data(), value.size());
|
||||
const size_t size = vec_to.size();
|
||||
|
||||
@ -1041,7 +1053,7 @@ public:
|
||||
return std::make_shared<DataTypeNumber<ToType>>();
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
|
||||
{
|
||||
size_t rows = input_rows_count;
|
||||
auto col_to = ColumnVector<ToType>::create(rows);
|
||||
@ -1057,13 +1069,10 @@ public:
|
||||
/// The function supports arbitrary number of arguments of arbitrary types.
|
||||
|
||||
bool is_first_argument = true;
|
||||
for (size_t i = 0; i < arguments.size(); ++i)
|
||||
{
|
||||
const ColumnWithTypeAndName & col = columns[arguments[i]];
|
||||
for (const auto & col : arguments)
|
||||
executeForArgument(col.type.get(), col.column.get(), vec_to, is_first_argument);
|
||||
}
|
||||
|
||||
columns[result].column = std::move(col_to);
|
||||
return col_to;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1086,9 +1095,9 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||
{
|
||||
selector.selectAndExecute(columns, arguments, result, input_rows_count);
|
||||
return selector.selectAndExecute(arguments, result_type, input_rows_count);
|
||||
}
|
||||
|
||||
static FunctionPtr create(const Context & context)
|
||||
@ -1118,7 +1127,7 @@ struct URLHierarchyHashImpl
|
||||
{
|
||||
static size_t findLevelLength(const UInt64 level, const char * begin, const char * end)
|
||||
{
|
||||
auto pos = begin;
|
||||
const auto * pos = begin;
|
||||
|
||||
/// Let's parse everything that goes before the path
|
||||
|
||||
@ -1192,7 +1201,7 @@ public:
|
||||
throw Exception{"Number of arguments for function " + getName() + " doesn't match: passed " +
|
||||
toString(arg_count) + ", should be 1 or 2.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH};
|
||||
|
||||
const auto first_arg = arguments.front().get();
|
||||
const auto * first_arg = arguments.front().get();
|
||||
if (!WhichDataType(first_arg).isString())
|
||||
throw Exception{"Illegal type " + first_arg->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT};
|
||||
|
||||
@ -1209,24 +1218,24 @@ public:
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {1}; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const auto arg_count = arguments.size();
|
||||
|
||||
if (arg_count == 1)
|
||||
executeSingleArg(columns, arguments, result);
|
||||
return executeSingleArg(arguments);
|
||||
else if (arg_count == 2)
|
||||
executeTwoArgs(columns, arguments, result);
|
||||
return executeTwoArgs(arguments);
|
||||
else
|
||||
throw Exception{"got into IFunction::execute with unexpected number of arguments", ErrorCodes::LOGICAL_ERROR};
|
||||
}
|
||||
|
||||
private:
|
||||
void executeSingleArg(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, const size_t result) const
|
||||
ColumnPtr executeSingleArg(ColumnsWithTypeAndName & arguments) const
|
||||
{
|
||||
const auto col_untyped = columns[arguments.front()].column.get();
|
||||
const auto * col_untyped = arguments.front().column.get();
|
||||
|
||||
if (const auto col_from = checkAndGetColumn<ColumnString>(col_untyped))
|
||||
if (const auto * col_from = checkAndGetColumn<ColumnString>(col_untyped))
|
||||
{
|
||||
const auto size = col_from->size();
|
||||
auto col_to = ColumnUInt64::create(size);
|
||||
@ -1245,23 +1254,23 @@ private:
|
||||
current_offset = offsets[i];
|
||||
}
|
||||
|
||||
columns[result].column = std::move(col_to);
|
||||
return col_to;
|
||||
}
|
||||
else
|
||||
throw Exception{"Illegal column " + columns[arguments[0]].column->getName() +
|
||||
throw Exception{"Illegal column " + arguments[0].column->getName() +
|
||||
" of argument of function " + getName(), ErrorCodes::ILLEGAL_COLUMN};
|
||||
}
|
||||
|
||||
void executeTwoArgs(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, const size_t result) const
|
||||
ColumnPtr executeTwoArgs(ColumnsWithTypeAndName & arguments) const
|
||||
{
|
||||
const auto level_col = columns[arguments.back()].column.get();
|
||||
const auto * level_col = arguments.back().column.get();
|
||||
if (!isColumnConst(*level_col))
|
||||
throw Exception{"Second argument of function " + getName() + " must be an integral constant", ErrorCodes::ILLEGAL_COLUMN};
|
||||
|
||||
const auto level = level_col->get64(0);
|
||||
|
||||
const auto col_untyped = columns[arguments.front()].column.get();
|
||||
if (const auto col_from = checkAndGetColumn<ColumnString>(col_untyped))
|
||||
const auto * col_untyped = arguments.front().column.get();
|
||||
if (const auto * col_from = checkAndGetColumn<ColumnString>(col_untyped))
|
||||
{
|
||||
const auto size = col_from->size();
|
||||
auto col_to = ColumnUInt64::create(size);
|
||||
@ -1281,10 +1290,10 @@ private:
|
||||
current_offset = offsets[i];
|
||||
}
|
||||
|
||||
columns[result].column = std::move(col_to);
|
||||
return col_to;
|
||||
}
|
||||
else
|
||||
throw Exception{"Illegal column " + columns[arguments[0]].column->getName() +
|
||||
throw Exception{"Illegal column " + arguments[0].column->getName() +
|
||||
" of argument of function " + getName(), ErrorCodes::ILLEGAL_COLUMN};
|
||||
}
|
||||
};
|
||||
|
@ -10,13 +10,13 @@ namespace ErrorCodes
|
||||
}
|
||||
|
||||
|
||||
std::vector<FunctionJSONHelpers::Move> FunctionJSONHelpers::prepareMoves(const char * function_name, ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t first_index_argument, size_t num_index_arguments)
|
||||
std::vector<FunctionJSONHelpers::Move> FunctionJSONHelpers::prepareMoves(const char * function_name, ColumnsWithTypeAndName & columns, size_t first_index_argument, size_t num_index_arguments)
|
||||
{
|
||||
std::vector<Move> moves;
|
||||
moves.reserve(num_index_arguments);
|
||||
for (const auto i : ext::range(first_index_argument, first_index_argument + num_index_arguments))
|
||||
{
|
||||
const auto & column = columns[arguments[i]];
|
||||
const auto & column = columns[i];
|
||||
if (!isString(column.type) && !isInteger(column.type))
|
||||
throw Exception{"The argument " + std::to_string(i + 1) + " of function " + String(function_name)
|
||||
+ " should be a string specifying key or an integer specifying index, illegal type: " + column.type->getName(),
|
||||
|
@ -55,22 +55,22 @@ public:
|
||||
class Executor
|
||||
{
|
||||
public:
|
||||
static void run(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result_pos, size_t input_rows_count)
|
||||
static ColumnPtr run(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count)
|
||||
{
|
||||
MutableColumnPtr to{columns[result_pos].type->createColumn()};
|
||||
MutableColumnPtr to{result_type->createColumn()};
|
||||
to->reserve(input_rows_count);
|
||||
|
||||
if (arguments.size() < 1)
|
||||
if (arguments.empty())
|
||||
throw Exception{"Function " + String(Name::name) + " requires at least one argument", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH};
|
||||
|
||||
const auto & first_column = columns[arguments[0]];
|
||||
const auto & first_column = arguments[0];
|
||||
if (!isString(first_column.type))
|
||||
throw Exception{"The first argument of function " + String(Name::name) + " should be a string containing JSON, illegal type: " + first_column.type->getName(),
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT};
|
||||
|
||||
const ColumnPtr & arg_json = first_column.column;
|
||||
auto col_json_const = typeid_cast<const ColumnConst *>(arg_json.get());
|
||||
auto col_json_string
|
||||
const auto * col_json_const = typeid_cast<const ColumnConst *>(arg_json.get());
|
||||
const auto * col_json_string
|
||||
= typeid_cast<const ColumnString *>(col_json_const ? col_json_const->getDataColumnPtr().get() : arg_json.get());
|
||||
|
||||
if (!col_json_string)
|
||||
@ -79,8 +79,8 @@ public:
|
||||
const ColumnString::Chars & chars = col_json_string->getChars();
|
||||
const ColumnString::Offsets & offsets = col_json_string->getOffsets();
|
||||
|
||||
size_t num_index_arguments = Impl<JSONParser>::getNumberOfIndexArguments(columns, arguments);
|
||||
std::vector<Move> moves = prepareMoves(Name::name, columns, arguments, 1, num_index_arguments);
|
||||
size_t num_index_arguments = Impl<JSONParser>::getNumberOfIndexArguments(arguments);
|
||||
std::vector<Move> moves = prepareMoves(Name::name, arguments, 1, num_index_arguments);
|
||||
|
||||
/// Preallocate memory in parser if necessary.
|
||||
JSONParser parser;
|
||||
@ -94,8 +94,8 @@ public:
|
||||
Impl<JSONParser> impl;
|
||||
|
||||
/// prepare() does Impl-specific preparation before handling each row.
|
||||
if constexpr (has_member_function_prepare<void (Impl<JSONParser>::*)(const char *, const ColumnsWithTypeAndName &, const ColumnNumbers &, size_t)>::value)
|
||||
impl.prepare(Name::name, columns, arguments, result_pos);
|
||||
if constexpr (has_member_function_prepare<void (Impl<JSONParser>::*)(const char *, const ColumnsWithTypeAndName &, const DataTypePtr &)>::value)
|
||||
impl.prepare(Name::name, arguments, result_type);
|
||||
|
||||
using Element = typename JSONParser::Element;
|
||||
|
||||
@ -121,7 +121,7 @@ public:
|
||||
/// Perform moves.
|
||||
Element element;
|
||||
std::string_view last_key;
|
||||
bool moves_ok = performMoves<JSONParser>(columns, arguments, i, document, moves, element, last_key);
|
||||
bool moves_ok = performMoves<JSONParser>(arguments, i, document, moves, element, last_key);
|
||||
|
||||
if (moves_ok)
|
||||
added_to_column = impl.insertResultToColumn(*to, element, last_key);
|
||||
@ -131,7 +131,7 @@ public:
|
||||
if (!added_to_column)
|
||||
to->insertDefault();
|
||||
}
|
||||
columns[result_pos].column = std::move(to);
|
||||
return to;
|
||||
}
|
||||
};
|
||||
|
||||
@ -166,11 +166,11 @@ private:
|
||||
String key;
|
||||
};
|
||||
|
||||
static std::vector<Move> prepareMoves(const char * function_name, ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t first_index_argument, size_t num_index_arguments);
|
||||
static std::vector<Move> prepareMoves(const char * function_name, ColumnsWithTypeAndName & columns, size_t first_index_argument, size_t num_index_arguments);
|
||||
|
||||
/// Performs moves of types MoveType::Index and MoveType::ConstIndex.
|
||||
template <typename JSONParser>
|
||||
static bool performMoves(const ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t row,
|
||||
static bool performMoves(const ColumnsWithTypeAndName & arguments, size_t row,
|
||||
const typename JSONParser::Element & document, const std::vector<Move> & moves,
|
||||
typename JSONParser::Element & element, std::string_view & last_key)
|
||||
{
|
||||
@ -196,14 +196,14 @@ private:
|
||||
}
|
||||
case MoveType::Index:
|
||||
{
|
||||
Int64 index = (*columns[arguments[j + 1]].column)[row].get<Int64>();
|
||||
Int64 index = (*arguments[j + 1].column)[row].get<Int64>();
|
||||
if (!moveToElementByIndex<JSONParser>(res_element, index, key))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case MoveType::Key:
|
||||
{
|
||||
key = std::string_view{(*columns[arguments[j + 1]].column).getDataAt(row)};
|
||||
key = std::string_view{(*arguments[j + 1].column).getDataAt(row)};
|
||||
if (!moveToElementByKey<JSONParser>(res_element, key))
|
||||
return false;
|
||||
break;
|
||||
@ -286,21 +286,18 @@ public:
|
||||
return Impl<DummyJSONParser>::getReturnType(Name::name, arguments);
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result_pos, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||
{
|
||||
/// Choose JSONParser.
|
||||
#if USE_SIMDJSON
|
||||
if (context.getSettingsRef().allow_simdjson)
|
||||
{
|
||||
FunctionJSONHelpers::Executor<Name, Impl, SimdJSONParser>::run(columns, arguments, result_pos, input_rows_count);
|
||||
return;
|
||||
}
|
||||
return FunctionJSONHelpers::Executor<Name, Impl, SimdJSONParser>::run(arguments, result_type, input_rows_count);
|
||||
#endif
|
||||
|
||||
#if USE_RAPIDJSON
|
||||
FunctionJSONHelpers::Executor<Name, Impl, RapidJSONParser>::run(columns, arguments, result_pos, input_rows_count);
|
||||
return FunctionJSONHelpers::Executor<Name, Impl, RapidJSONParser>::run(arguments, result_type, input_rows_count);
|
||||
#else
|
||||
FunctionJSONHelpers::Executor<Name, Impl, DummyJSONParser>::run(columns, arguments, result_pos, input_rows_count);
|
||||
return FunctionJSONHelpers::Executor<Name, Impl, DummyJSONParser>::run(arguments, result_type, input_rows_count);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -334,7 +331,7 @@ public:
|
||||
|
||||
static DataTypePtr getReturnType(const char *, const ColumnsWithTypeAndName &) { return std::make_shared<DataTypeUInt8>(); }
|
||||
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName &, const ColumnNumbers & arguments) { return arguments.size() - 1; }
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
||||
|
||||
static bool insertResultToColumn(IColumn & dest, const Element &, const std::string_view &)
|
||||
{
|
||||
@ -362,7 +359,7 @@ public:
|
||||
return std::make_shared<DataTypeUInt8>();
|
||||
}
|
||||
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName &, const ColumnNumbers &) { return 0; }
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName &) { return 0; }
|
||||
|
||||
static bool insertResultToColumn(IColumn & dest, const Element &, const std::string_view &)
|
||||
{
|
||||
@ -386,7 +383,7 @@ public:
|
||||
return std::make_shared<DataTypeUInt64>();
|
||||
}
|
||||
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName &, const ColumnNumbers & arguments) { return arguments.size() - 1; }
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
||||
|
||||
static bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
||||
{
|
||||
@ -416,7 +413,7 @@ public:
|
||||
return std::make_shared<DataTypeString>();
|
||||
}
|
||||
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName &, const ColumnNumbers & arguments) { return arguments.size() - 1; }
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
||||
|
||||
static bool insertResultToColumn(IColumn & dest, const Element &, const std::string_view & last_key)
|
||||
{
|
||||
@ -450,7 +447,7 @@ public:
|
||||
return std::make_shared<DataTypeEnum<Int8>>(values);
|
||||
}
|
||||
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName &, const ColumnNumbers & arguments) { return arguments.size() - 1; }
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
||||
|
||||
static bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
||||
{
|
||||
@ -492,7 +489,7 @@ public:
|
||||
return std::make_shared<DataTypeNumber<NumberType>>();
|
||||
}
|
||||
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName &, const ColumnNumbers & arguments) { return arguments.size() - 1; }
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
||||
|
||||
static bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
||||
{
|
||||
@ -557,7 +554,7 @@ public:
|
||||
return std::make_shared<DataTypeUInt8>();
|
||||
}
|
||||
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName &, const ColumnNumbers & arguments) { return arguments.size() - 1; }
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
||||
|
||||
static bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
||||
{
|
||||
@ -582,7 +579,7 @@ public:
|
||||
return std::make_shared<DataTypeString>();
|
||||
}
|
||||
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName &, const ColumnNumbers & arguments) { return arguments.size() - 1; }
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
||||
|
||||
static bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
||||
{
|
||||
@ -909,11 +906,11 @@ public:
|
||||
return DataTypeFactory::instance().get(col_type_const->getValue<String>());
|
||||
}
|
||||
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName &, const ColumnNumbers & arguments) { return arguments.size() - 2; }
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 2; }
|
||||
|
||||
void prepare(const char * function_name, const ColumnsWithTypeAndName & columns, const ColumnNumbers &, size_t result_pos)
|
||||
void prepare(const char * function_name, const ColumnsWithTypeAndName &, const DataTypePtr & result_type)
|
||||
{
|
||||
extract_tree = JSONExtractTree<JSONParser>::build(function_name, columns[result_pos].type);
|
||||
extract_tree = JSONExtractTree<JSONParser>::build(function_name, result_type);
|
||||
}
|
||||
|
||||
bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
||||
@ -950,11 +947,10 @@ public:
|
||||
return std::make_unique<DataTypeArray>(tuple_type);
|
||||
}
|
||||
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName &, const ColumnNumbers & arguments) { return arguments.size() - 2; }
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 2; }
|
||||
|
||||
void prepare(const char * function_name, const ColumnsWithTypeAndName & columns, const ColumnNumbers &, size_t result_pos)
|
||||
void prepare(const char * function_name, const ColumnsWithTypeAndName &, const DataTypePtr & result_type)
|
||||
{
|
||||
const auto & result_type = columns[result_pos].type;
|
||||
const auto tuple_type = typeid_cast<const DataTypeArray *>(result_type.get())->getNestedType();
|
||||
const auto value_type = typeid_cast<const DataTypeTuple *>(tuple_type.get())->getElements()[1];
|
||||
extract_tree = JSONExtractTree<JSONParser>::build(function_name, value_type);
|
||||
@ -1002,7 +998,7 @@ public:
|
||||
return std::make_shared<DataTypeString>();
|
||||
}
|
||||
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName &, const ColumnNumbers & arguments) { return arguments.size() - 1; }
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
||||
|
||||
static bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
||||
{
|
||||
@ -1106,7 +1102,7 @@ public:
|
||||
return std::make_shared<DataTypeArray>(std::make_shared<DataTypeString>());
|
||||
}
|
||||
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName &, const ColumnNumbers & arguments) { return arguments.size() - 1; }
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
||||
|
||||
static bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
||||
{
|
||||
@ -1138,7 +1134,7 @@ public:
|
||||
return std::make_unique<DataTypeArray>(tuple_type);
|
||||
}
|
||||
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName &, const ColumnNumbers & arguments) { return arguments.size() - 1; }
|
||||
static size_t getNumberOfIndexArguments(const ColumnsWithTypeAndName & arguments) { return arguments.size() - 1; }
|
||||
|
||||
bool insertResultToColumn(IColumn & dest, const Element & element, const std::string_view &)
|
||||
{
|
||||
|
@ -342,7 +342,7 @@ struct OperationApplier<Op, OperationApplierImpl, 0>
|
||||
|
||||
|
||||
template <class Op>
|
||||
static void executeForTernaryLogicImpl(ColumnRawPtrs arguments, ColumnWithTypeAndName & result_info, size_t input_rows_count)
|
||||
static ColumnPtr executeForTernaryLogicImpl(ColumnRawPtrs arguments, const DataTypePtr & result_type, size_t input_rows_count)
|
||||
{
|
||||
/// Combine all constant columns into a single constant value.
|
||||
UInt8 const_3v_value = 0;
|
||||
@ -351,11 +351,10 @@ static void executeForTernaryLogicImpl(ColumnRawPtrs arguments, ColumnWithTypeAn
|
||||
/// If the constant value uniquely determines the result, return it.
|
||||
if (has_consts && (arguments.empty() || Op::isSaturatedValueTernary(const_3v_value)))
|
||||
{
|
||||
result_info.column = ColumnConst::create(
|
||||
buildColumnFromTernaryData(UInt8Container({const_3v_value}), result_info.type->isNullable()),
|
||||
return ColumnConst::create(
|
||||
buildColumnFromTernaryData(UInt8Container({const_3v_value}), result_type->isNullable()),
|
||||
input_rows_count
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto result_column = has_consts ?
|
||||
@ -363,7 +362,7 @@ static void executeForTernaryLogicImpl(ColumnRawPtrs arguments, ColumnWithTypeAn
|
||||
|
||||
OperationApplier<Op, AssociativeGenericApplierImpl>::apply(arguments, result_column->getData(), has_consts);
|
||||
|
||||
result_info.column = buildColumnFromTernaryData(result_column->getData(), result_info.type->isNullable());
|
||||
return buildColumnFromTernaryData(result_column->getData(), result_type->isNullable());
|
||||
}
|
||||
|
||||
|
||||
@ -418,7 +417,7 @@ struct TypedExecutorInvoker<Op>
|
||||
|
||||
/// Types of all of the arguments are guaranteed to be non-nullable here
|
||||
template <class Op>
|
||||
static void basicExecuteImpl(ColumnRawPtrs arguments, ColumnWithTypeAndName & result_info, size_t input_rows_count)
|
||||
static ColumnPtr basicExecuteImpl(ColumnRawPtrs arguments, size_t input_rows_count)
|
||||
{
|
||||
/// Combine all constant columns into a single constant value.
|
||||
UInt8 const_val = 0;
|
||||
@ -429,8 +428,7 @@ static void basicExecuteImpl(ColumnRawPtrs arguments, ColumnWithTypeAndName & re
|
||||
{
|
||||
if (!arguments.empty())
|
||||
const_val = Op::apply(const_val, 0);
|
||||
result_info.column = DataTypeUInt8().createColumnConst(input_rows_count, toField(const_val));
|
||||
return;
|
||||
return DataTypeUInt8().createColumnConst(input_rows_count, toField(const_val));
|
||||
}
|
||||
|
||||
/// If the constant value is a neutral element, let's forget about it.
|
||||
@ -448,8 +446,7 @@ static void basicExecuteImpl(ColumnRawPtrs arguments, ColumnWithTypeAndName & re
|
||||
else
|
||||
FastApplierImpl<Op>::apply(*arguments[0], *arguments[1], col_res->getData());
|
||||
|
||||
result_info.column = std::move(col_res);
|
||||
return;
|
||||
return col_res;
|
||||
}
|
||||
|
||||
/// Convert all columns to UInt8
|
||||
@ -470,7 +467,7 @@ static void basicExecuteImpl(ColumnRawPtrs arguments, ColumnWithTypeAndName & re
|
||||
|
||||
OperationApplier<Op, AssociativeApplierImpl>::apply(uint8_args, col_res->getData(), has_consts);
|
||||
|
||||
result_info.column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
|
||||
}
|
||||
@ -511,18 +508,17 @@ DataTypePtr FunctionAnyArityLogical<Impl, Name>::getReturnTypeImpl(const DataTyp
|
||||
}
|
||||
|
||||
template <typename Impl, typename Name>
|
||||
void FunctionAnyArityLogical<Impl, Name>::executeImpl(
|
||||
ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result_index, size_t input_rows_count) const
|
||||
ColumnPtr FunctionAnyArityLogical<Impl, Name>::executeImpl(
|
||||
ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const
|
||||
{
|
||||
ColumnRawPtrs args_in;
|
||||
for (const auto arg_index : arguments)
|
||||
args_in.push_back(columns[arg_index].column.get());
|
||||
for (const auto & arg_index : arguments)
|
||||
args_in.push_back(arg_index.column.get());
|
||||
|
||||
auto & result_info = columns[result_index];
|
||||
if (result_info.type->isNullable())
|
||||
executeForTernaryLogicImpl<Impl>(std::move(args_in), result_info, input_rows_count);
|
||||
if (result_type->isNullable())
|
||||
return executeForTernaryLogicImpl<Impl>(std::move(args_in), result_type, input_rows_count);
|
||||
else
|
||||
basicExecuteImpl<Impl>(std::move(args_in), result_info, input_rows_count);
|
||||
return basicExecuteImpl<Impl>(std::move(args_in), input_rows_count);
|
||||
}
|
||||
|
||||
|
||||
@ -554,9 +550,9 @@ DataTypePtr FunctionUnaryLogical<Impl, Name>::getReturnTypeImpl(const DataTypes
|
||||
}
|
||||
|
||||
template <template <typename> class Impl, typename T>
|
||||
bool functionUnaryExecuteType(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result)
|
||||
ColumnPtr functionUnaryExecuteType(ColumnsWithTypeAndName & arguments)
|
||||
{
|
||||
if (auto col = checkAndGetColumn<ColumnVector<T>>(columns[arguments[0]].column.get()))
|
||||
if (auto col = checkAndGetColumn<ColumnVector<T>>(arguments[0].column.get()))
|
||||
{
|
||||
auto col_res = ColumnUInt8::create();
|
||||
|
||||
@ -564,29 +560,31 @@ bool functionUnaryExecuteType(ColumnsWithTypeAndName & columns, const ColumnNumb
|
||||
vec_res.resize(col->getData().size());
|
||||
UnaryOperationImpl<T, Impl<T>>::vector(col->getData(), vec_res);
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return true;
|
||||
return col_res;
|
||||
}
|
||||
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <template <typename> class Impl, typename Name>
|
||||
void FunctionUnaryLogical<Impl, Name>::executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const
|
||||
ColumnPtr FunctionUnaryLogical<Impl, Name>::executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const
|
||||
{
|
||||
if (!(functionUnaryExecuteType<Impl, UInt8>(columns, arguments, result)
|
||||
|| functionUnaryExecuteType<Impl, UInt16>(columns, arguments, result)
|
||||
|| functionUnaryExecuteType<Impl, UInt32>(columns, arguments, result)
|
||||
|| functionUnaryExecuteType<Impl, UInt64>(columns, arguments, result)
|
||||
|| functionUnaryExecuteType<Impl, Int8>(columns, arguments, result)
|
||||
|| functionUnaryExecuteType<Impl, Int16>(columns, arguments, result)
|
||||
|| functionUnaryExecuteType<Impl, Int32>(columns, arguments, result)
|
||||
|| functionUnaryExecuteType<Impl, Int64>(columns, arguments, result)
|
||||
|| functionUnaryExecuteType<Impl, Float32>(columns, arguments, result)
|
||||
|| functionUnaryExecuteType<Impl, Float64>(columns, arguments, result)))
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
ColumnPtr res;
|
||||
if (!((res = functionUnaryExecuteType<Impl, UInt8>(arguments))
|
||||
|| (res = functionUnaryExecuteType<Impl, UInt16>(arguments))
|
||||
|| (res = functionUnaryExecuteType<Impl, UInt32>(arguments))
|
||||
|| (res = functionUnaryExecuteType<Impl, UInt64>(arguments))
|
||||
|| (res = functionUnaryExecuteType<Impl, Int8>(arguments))
|
||||
|| (res = functionUnaryExecuteType<Impl, Int16>(arguments))
|
||||
|| (res = functionUnaryExecuteType<Impl, Int32>(arguments))
|
||||
|| (res = functionUnaryExecuteType<Impl, Int64>(arguments))
|
||||
|| (res = functionUnaryExecuteType<Impl, Float32>(arguments))
|
||||
|| (res = functionUnaryExecuteType<Impl, Float64>(arguments))))
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ public:
|
||||
/// Get result types by argument types. If the function does not apply to these arguments, throw an exception.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override;
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result_index, size_t input_rows_count) const override;
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override;
|
||||
|
||||
#if USE_EMBEDDED_COMPILER
|
||||
bool isCompilableImpl(const DataTypes &) const override { return useDefaultImplementationForNulls(); }
|
||||
@ -217,7 +217,7 @@ public:
|
||||
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override;
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override;
|
||||
|
||||
#if USE_EMBEDDED_COMPILER
|
||||
bool isCompilableImpl(const DataTypes &) const override { return true; }
|
||||
|
@ -35,19 +35,19 @@ public:
|
||||
|
||||
String getName() const override { return "FunctionExpression"; }
|
||||
|
||||
void execute(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) override
|
||||
ColumnPtr execute(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) override
|
||||
{
|
||||
DB::Block expr_columns;
|
||||
for (size_t i = 0; i < arguments.size(); ++i)
|
||||
{
|
||||
const auto & argument = columns[arguments[i]];
|
||||
const auto & argument = arguments[i];
|
||||
/// Replace column name with value from argument_names.
|
||||
expr_columns.insert({argument.column, argument.type, signature->argument_names[i]});
|
||||
}
|
||||
|
||||
expression_actions->execute(expr_columns);
|
||||
|
||||
columns[result].column = expr_columns.getByName(signature->return_name).column;
|
||||
return expr_columns.getByName(signature->return_name).column;
|
||||
}
|
||||
|
||||
bool useDefaultImplementationForNulls() const override { return false; }
|
||||
@ -79,9 +79,9 @@ public:
|
||||
bool isDeterministicInScopeOfQuery() const override { return true; }
|
||||
|
||||
const DataTypes & getArgumentTypes() const override { return argument_types; }
|
||||
const DataTypePtr & getReturnType() const override { return return_type; }
|
||||
const DataTypePtr & getResultType() const override { return return_type; }
|
||||
|
||||
ExecutableFunctionImplPtr prepare(const ColumnsWithTypeAndName &, const ColumnNumbers &, size_t) const override
|
||||
ExecutableFunctionImplPtr prepare(const ColumnsWithTypeAndName &) const override
|
||||
{
|
||||
return std::make_unique<ExecutableFunctionExpression>(expression_actions, signature);
|
||||
}
|
||||
@ -119,11 +119,8 @@ public:
|
||||
bool useDefaultImplementationForNulls() const override { return false; }
|
||||
bool useDefaultImplementationForLowCardinalityColumns() const override { return false; }
|
||||
|
||||
void execute(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
|
||||
ColumnPtr execute(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) override
|
||||
{
|
||||
ColumnsWithTypeAndName columns_to_catpure;
|
||||
columns_to_catpure.reserve(arguments.size());
|
||||
|
||||
Names names;
|
||||
DataTypes types;
|
||||
|
||||
@ -139,13 +136,10 @@ public:
|
||||
types.push_back(lambda_argument.type);
|
||||
}
|
||||
|
||||
for (const auto & argument : arguments)
|
||||
columns_to_catpure.push_back(columns[argument]);
|
||||
|
||||
auto function = std::make_unique<FunctionExpression>(expression_actions, types, names,
|
||||
capture->return_type, capture->return_name);
|
||||
auto function_adaptor = std::make_shared<FunctionBaseAdaptor>(std::move(function));
|
||||
columns[result].column = ColumnFunction::create(input_rows_count, std::move(function_adaptor), columns_to_catpure);
|
||||
return ColumnFunction::create(input_rows_count, std::move(function_adaptor), arguments);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -177,9 +171,9 @@ public:
|
||||
bool isDeterministicInScopeOfQuery() const override { return true; }
|
||||
|
||||
const DataTypes & getArgumentTypes() const override { return capture->captured_types; }
|
||||
const DataTypePtr & getReturnType() const override { return return_type; }
|
||||
const DataTypePtr & getResultType() const override { return return_type; }
|
||||
|
||||
ExecutableFunctionImplPtr prepare(const ColumnsWithTypeAndName &, const ColumnNumbers &, size_t) const override
|
||||
ExecutableFunctionImplPtr prepare(const ColumnsWithTypeAndName &) const override
|
||||
{
|
||||
return std::make_unique<ExecutableFunctionCapture>(expression_actions, capture);
|
||||
}
|
||||
|
@ -66,15 +66,15 @@ public:
|
||||
return Impl::getReturnType();
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
using ResultType = typename Impl::ResultType;
|
||||
|
||||
const ColumnPtr & column_haystack = columns[arguments[0]].column;
|
||||
const ColumnPtr & column_haystack = arguments[0].column;
|
||||
|
||||
const ColumnString * col_haystack_vector = checkAndGetColumn<ColumnString>(&*column_haystack);
|
||||
|
||||
const ColumnPtr & num_ptr = columns[arguments[1]].column;
|
||||
const ColumnPtr & num_ptr = arguments[1].column;
|
||||
const ColumnConst * col_const_num = nullptr;
|
||||
UInt32 edit_distance = 0;
|
||||
|
||||
@ -86,17 +86,17 @@ public:
|
||||
edit_distance = col_const_num->getValue<UInt32>();
|
||||
else
|
||||
throw Exception(
|
||||
"Illegal column " + columns[arguments[1]].column->getName()
|
||||
"Illegal column " + arguments[1].column->getName()
|
||||
+ ". The number is not const or does not fit in UInt32",
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
|
||||
const ColumnPtr & arr_ptr = columns[arguments[2]].column;
|
||||
const ColumnPtr & arr_ptr = arguments[2].column;
|
||||
const ColumnConst * col_const_arr = checkAndGetColumnConst<ColumnArray>(arr_ptr.get());
|
||||
|
||||
if (!col_const_arr)
|
||||
throw Exception(
|
||||
"Illegal column " + columns[arguments[2]].column->getName() + ". The array is not const",
|
||||
"Illegal column " + arguments[2].column->getName() + ". The array is not const",
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
Array src_arr = col_const_arr->getValue<Array>();
|
||||
@ -124,12 +124,12 @@ public:
|
||||
Impl::vectorConstant(
|
||||
col_haystack_vector->getChars(), col_haystack_vector->getOffsets(), refs, vec_res, offsets_res, edit_distance);
|
||||
else
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName(), ErrorCodes::ILLEGAL_COLUMN);
|
||||
throw Exception("Illegal column " + arguments[0].column->getName(), ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
if constexpr (Impl::is_column_array)
|
||||
columns[result].column = ColumnArray::create(std::move(col_res), std::move(col_offsets));
|
||||
return ColumnArray::create(std::move(col_res), std::move(col_offsets));
|
||||
else
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -73,20 +73,20 @@ public:
|
||||
return std::make_shared<DataTypeArray>(std::make_shared<DataTypeUInt64>());
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
using ResultType = typename Impl::ResultType;
|
||||
|
||||
const ColumnPtr & column_haystack = columns[arguments[0]].column;
|
||||
const ColumnPtr & column_haystack = arguments[0].column;
|
||||
|
||||
const ColumnString * col_haystack_vector = checkAndGetColumn<ColumnString>(&*column_haystack);
|
||||
|
||||
const ColumnPtr & arr_ptr = columns[arguments[1]].column;
|
||||
const ColumnPtr & arr_ptr = arguments[1].column;
|
||||
const ColumnConst * col_const_arr = checkAndGetColumnConst<ColumnArray>(arr_ptr.get());
|
||||
|
||||
if (!col_const_arr)
|
||||
throw Exception(
|
||||
"Illegal column " + columns[arguments[1]].column->getName() + ". The array is not const",
|
||||
"Illegal column " + arguments[1].column->getName() + ". The array is not const",
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
Array src_arr = col_const_arr->getValue<Array>();
|
||||
@ -114,7 +114,7 @@ public:
|
||||
if (col_haystack_vector)
|
||||
Impl::vectorConstant(col_haystack_vector->getChars(), col_haystack_vector->getOffsets(), refs, vec_res);
|
||||
else
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName(), ErrorCodes::ILLEGAL_COLUMN);
|
||||
throw Exception("Illegal column " + arguments[0].column->getName(), ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
size_t refs_size = refs.size();
|
||||
size_t accum = refs_size;
|
||||
@ -122,7 +122,7 @@ public:
|
||||
for (size_t i = 0; i < column_haystack_size; ++i, accum += refs_size)
|
||||
offsets_res[i] = accum;
|
||||
|
||||
columns[result].column = ColumnArray::create(std::move(col_res), std::move(col_offsets));
|
||||
return ColumnArray::create(std::move(col_res), std::move(col_offsets));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -75,20 +75,20 @@ public:
|
||||
return Impl::getReturnType();
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
using ResultType = typename Impl::ResultType;
|
||||
|
||||
const ColumnPtr & column_haystack = columns[arguments[0]].column;
|
||||
const ColumnPtr & column_haystack = arguments[0].column;
|
||||
|
||||
const ColumnString * col_haystack_vector = checkAndGetColumn<ColumnString>(&*column_haystack);
|
||||
|
||||
const ColumnPtr & arr_ptr = columns[arguments[1]].column;
|
||||
const ColumnPtr & arr_ptr = arguments[1].column;
|
||||
const ColumnConst * col_const_arr = checkAndGetColumnConst<ColumnArray>(arr_ptr.get());
|
||||
|
||||
if (!col_const_arr)
|
||||
throw Exception(
|
||||
"Illegal column " + columns[arguments[1]].column->getName() + ". The array is not const",
|
||||
"Illegal column " + arguments[1].column->getName() + ". The array is not const",
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
Array src_arr = col_const_arr->getValue<Array>();
|
||||
@ -115,12 +115,12 @@ public:
|
||||
if (col_haystack_vector)
|
||||
Impl::vectorConstant(col_haystack_vector->getChars(), col_haystack_vector->getOffsets(), refs, vec_res, offsets_res);
|
||||
else
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName(), ErrorCodes::ILLEGAL_COLUMN);
|
||||
throw Exception("Illegal column " + arguments[0].column->getName(), ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
if constexpr (Impl::is_column_array)
|
||||
columns[result].column = ColumnArray::create(std::move(col_res), std::move(col_offsets));
|
||||
return ColumnArray::create(std::move(col_res), std::move(col_offsets));
|
||||
else
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -74,7 +74,7 @@ public:
|
||||
return std::make_shared<DataTypeNumber<ToType>>();
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers &, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName &, const DataTypePtr &, size_t input_rows_count) const override
|
||||
{
|
||||
auto col_to = ColumnVector<ToType>::create();
|
||||
typename ColumnVector<ToType>::Container & vec_to = col_to->getData();
|
||||
@ -83,7 +83,7 @@ public:
|
||||
vec_to.resize(size);
|
||||
RandImpl::execute(reinterpret_cast<char *>(vec_to.data()), vec_to.size() * sizeof(ToType));
|
||||
|
||||
columns[result].column = std::move(col_to);
|
||||
return col_to;
|
||||
}
|
||||
};
|
||||
|
||||
@ -102,9 +102,9 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
|
||||
{
|
||||
selector.selectAndExecute(columns, arguments, result, input_rows_count);
|
||||
return selector.selectAndExecute(arguments, result_type, input_rows_count);
|
||||
}
|
||||
|
||||
static FunctionPtr create(const Context & context)
|
||||
|
@ -458,7 +458,7 @@ class Dispatcher
|
||||
FloatRoundingImpl<T, rounding_mode, scale_mode>,
|
||||
IntegerRoundingImpl<T, rounding_mode, scale_mode, tie_breaking_mode>>;
|
||||
|
||||
static void apply(ColumnsWithTypeAndName & columns, const ColumnVector<T> * col, Int64 scale_arg, size_t result)
|
||||
static ColumnPtr apply(const ColumnVector<T> * col, Int64 scale_arg)
|
||||
{
|
||||
auto col_res = ColumnVector<T>::create();
|
||||
|
||||
@ -484,10 +484,10 @@ class Dispatcher
|
||||
}
|
||||
}
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
|
||||
static void apply(ColumnsWithTypeAndName & columns, const ColumnDecimal<T> * col, Int64 scale_arg, size_t result)
|
||||
static ColumnPtr apply(const ColumnDecimal<T> * col, Int64 scale_arg)
|
||||
{
|
||||
const typename ColumnDecimal<T>::Container & vec_src = col->getData();
|
||||
|
||||
@ -497,16 +497,16 @@ class Dispatcher
|
||||
if (!vec_res.empty())
|
||||
DecimalRoundingImpl<T, rounding_mode, tie_breaking_mode>::apply(col->getData(), vec_res, scale_arg);
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
|
||||
public:
|
||||
static void apply(ColumnsWithTypeAndName & columns, const IColumn * column, Int64 scale_arg, size_t result)
|
||||
static ColumnPtr apply(const IColumn * column, Int64 scale_arg)
|
||||
{
|
||||
if constexpr (IsNumber<T>)
|
||||
apply(columns, checkAndGetColumn<ColumnVector<T>>(column), scale_arg, result);
|
||||
return apply(checkAndGetColumn<ColumnVector<T>>(column), scale_arg);
|
||||
else if constexpr (IsDecimalNumber<T>)
|
||||
apply(columns, checkAndGetColumn<ColumnDecimal<T>>(column), scale_arg, result);
|
||||
return apply(checkAndGetColumn<ColumnDecimal<T>>(column), scale_arg);
|
||||
}
|
||||
};
|
||||
|
||||
@ -520,7 +520,6 @@ public:
|
||||
static constexpr auto name = Name::name;
|
||||
static FunctionPtr create(const Context &) { return std::make_shared<FunctionRounding>(); }
|
||||
|
||||
public:
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -532,7 +531,7 @@ public:
|
||||
/// Get result types by argument types. If the function does not apply to these arguments, throw an exception.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if ((arguments.size() < 1) || (arguments.size() > 2))
|
||||
if ((arguments.empty()) || (arguments.size() > 2))
|
||||
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
|
||||
+ toString(arguments.size()) + ", should be 1 or 2.",
|
||||
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
@ -545,11 +544,11 @@ public:
|
||||
return arguments[0];
|
||||
}
|
||||
|
||||
static Int64 getScaleArg(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments)
|
||||
static Int64 getScaleArg(ColumnsWithTypeAndName & arguments)
|
||||
{
|
||||
if (arguments.size() == 2)
|
||||
{
|
||||
const IColumn & scale_column = *columns[arguments[1]].column;
|
||||
const IColumn & scale_column = *arguments[1].column;
|
||||
if (!isColumnConst(scale_column))
|
||||
throw Exception("Scale argument for rounding functions must be constant.", ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
@ -566,11 +565,12 @@ public:
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {1}; }
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const ColumnWithTypeAndName & column = columns[arguments[0]];
|
||||
Int64 scale_arg = getScaleArg(columns, arguments);
|
||||
const ColumnWithTypeAndName & column = arguments[0];
|
||||
Int64 scale_arg = getScaleArg(arguments);
|
||||
|
||||
ColumnPtr res;
|
||||
auto call = [&](const auto & types) -> bool
|
||||
{
|
||||
using Types = std::decay_t<decltype(types)>;
|
||||
@ -579,7 +579,7 @@ public:
|
||||
if constexpr (IsDataTypeNumber<DataType> || IsDataTypeDecimal<DataType>)
|
||||
{
|
||||
using FieldType = typename DataType::FieldType;
|
||||
Dispatcher<FieldType, rounding_mode, tie_breaking_mode>::apply(columns, column.column.get(), scale_arg, result);
|
||||
res = Dispatcher<FieldType, rounding_mode, tie_breaking_mode>::apply(column.column.get(), scale_arg);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -590,6 +590,8 @@ public:
|
||||
throw Exception("Illegal column " + column.name + " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool hasInformationAboutMonotonicity() const override
|
||||
@ -613,7 +615,6 @@ public:
|
||||
static constexpr auto name = "roundDown";
|
||||
static FunctionPtr create(const Context &) { return std::make_shared<FunctionRoundDown>(); }
|
||||
|
||||
public:
|
||||
String getName() const override { return name; }
|
||||
|
||||
bool isVariadic() const override { return false; }
|
||||
@ -646,25 +647,25 @@ public:
|
||||
return getLeastSupertype({type_x, type_arr_nested});
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t) const override
|
||||
{
|
||||
auto in_column = columns[arguments[0]].column;
|
||||
const auto & in_type = columns[arguments[0]].type;
|
||||
auto in_column = arguments[0].column;
|
||||
const auto & in_type = arguments[0].type;
|
||||
|
||||
auto array_column = columns[arguments[1]].column;
|
||||
const auto & array_type = columns[arguments[1]].type;
|
||||
auto array_column = arguments[1].column;
|
||||
const auto & array_type = arguments[1].type;
|
||||
|
||||
const auto & return_type = columns[result].type;
|
||||
const auto & return_type = result_type;
|
||||
auto column_result = return_type->createColumn();
|
||||
auto out = column_result.get();
|
||||
auto * out = column_result.get();
|
||||
|
||||
if (!in_type->equals(*return_type))
|
||||
in_column = castColumn(columns[arguments[0]], return_type);
|
||||
in_column = castColumn(arguments[0], return_type);
|
||||
|
||||
if (!array_type->equals(*return_type))
|
||||
array_column = castColumn(columns[arguments[1]], std::make_shared<DataTypeArray>(return_type));
|
||||
array_column = castColumn(arguments[1], std::make_shared<DataTypeArray>(return_type));
|
||||
|
||||
const auto in = in_column.get();
|
||||
const auto * in = in_column.get();
|
||||
auto boundaries = typeid_cast<const ColumnConst &>(*array_column).getValue<Array>();
|
||||
size_t num_boundaries = boundaries.size();
|
||||
if (!num_boundaries)
|
||||
@ -687,7 +688,7 @@ public:
|
||||
throw Exception{"Illegal column " + in->getName() + " of first argument of function " + getName(), ErrorCodes::ILLEGAL_COLUMN};
|
||||
}
|
||||
|
||||
columns[result].column = std::move(column_result);
|
||||
return column_result;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -75,7 +75,7 @@ public:
|
||||
}
|
||||
|
||||
/// Initialize by the function arguments.
|
||||
void init(ColumnsWithTypeAndName & /*columns*/, const ColumnNumbers & /*arguments*/) {}
|
||||
void init(ColumnsWithTypeAndName & /*arguments*/) {}
|
||||
|
||||
/// Called for each next string.
|
||||
void set(Pos pos_, Pos end_)
|
||||
@ -136,12 +136,12 @@ public:
|
||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
}
|
||||
|
||||
void init(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments)
|
||||
void init(ColumnsWithTypeAndName & arguments)
|
||||
{
|
||||
const ColumnConst * col = checkAndGetColumnConstStringOrFixedString(columns[arguments[0]].column.get());
|
||||
const ColumnConst * col = checkAndGetColumnConstStringOrFixedString(arguments[0].column.get());
|
||||
|
||||
if (!col)
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of first argument of function " + getName() + ". Must be constant string.",
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
@ -204,12 +204,12 @@ public:
|
||||
SplitByCharImpl::checkArguments(arguments);
|
||||
}
|
||||
|
||||
void init(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments)
|
||||
void init(ColumnsWithTypeAndName & arguments)
|
||||
{
|
||||
const ColumnConst * col = checkAndGetColumnConstStringOrFixedString(columns[arguments[0]].column.get());
|
||||
const ColumnConst * col = checkAndGetColumnConstStringOrFixedString(arguments[0].column.get());
|
||||
|
||||
if (!col)
|
||||
throw Exception("Illegal column " + columns[arguments[0]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[0].column->getName()
|
||||
+ " of first argument of function " + getName() + ". Must be constant string.",
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
@ -284,12 +284,12 @@ public:
|
||||
}
|
||||
|
||||
/// Initialize by the function arguments.
|
||||
void init(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments)
|
||||
void init(ColumnsWithTypeAndName & arguments)
|
||||
{
|
||||
const ColumnConst * col = checkAndGetColumnConstStringOrFixedString(columns[arguments[1]].column.get());
|
||||
const ColumnConst * col = checkAndGetColumnConstStringOrFixedString(arguments[1].column.get());
|
||||
|
||||
if (!col)
|
||||
throw Exception("Illegal column " + columns[arguments[1]].column->getName()
|
||||
throw Exception("Illegal column " + arguments[1].column->getName()
|
||||
+ " of first argument of function " + getName() + ". Must be constant string.",
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
@ -361,15 +361,15 @@ public:
|
||||
return std::make_shared<DataTypeArray>(std::make_shared<DataTypeString>());
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
Generator generator;
|
||||
generator.init(columns, arguments);
|
||||
size_t array_argument_position = arguments[generator.getStringsArgumentPosition()];
|
||||
generator.init(arguments);
|
||||
const auto & array_argument = arguments[generator.getStringsArgumentPosition()];
|
||||
|
||||
const ColumnString * col_str = checkAndGetColumn<ColumnString>(columns[array_argument_position].column.get());
|
||||
const ColumnString * col_str = checkAndGetColumn<ColumnString>(array_argument.column.get());
|
||||
const ColumnConst * col_const_str =
|
||||
checkAndGetColumnConstStringOrFixedString(columns[array_argument_position].column.get());
|
||||
checkAndGetColumnConstStringOrFixedString(array_argument.column.get());
|
||||
|
||||
auto col_res = ColumnArray::create(ColumnString::create());
|
||||
ColumnString & res_strings = typeid_cast<ColumnString &>(col_res->getData());
|
||||
@ -419,7 +419,7 @@ public:
|
||||
res_offsets.push_back(current_dst_offset);
|
||||
}
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
else if (col_const_str)
|
||||
{
|
||||
@ -433,11 +433,11 @@ public:
|
||||
while (generator.get(token_begin, token_end))
|
||||
dst.push_back(String(token_begin, token_end - token_begin));
|
||||
|
||||
columns[result].column = columns[result].type->createColumnConst(col_const_str->size(), dst);
|
||||
return result_type->createColumnConst(col_const_str->size(), dst);
|
||||
}
|
||||
else
|
||||
throw Exception("Illegal columns " + columns[array_argument_position].column->getName()
|
||||
+ ", " + columns[array_argument_position].column->getName()
|
||||
throw Exception("Illegal columns " + array_argument.column->getName()
|
||||
+ ", " + array_argument.column->getName()
|
||||
+ " of arguments of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
@ -536,19 +536,19 @@ public:
|
||||
return std::make_shared<DataTypeString>();
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
String delimiter;
|
||||
if (arguments.size() == 2)
|
||||
{
|
||||
const ColumnConst * col_delim = checkAndGetColumnConstStringOrFixedString(columns[arguments[1]].column.get());
|
||||
const ColumnConst * col_delim = checkAndGetColumnConstStringOrFixedString(arguments[1].column.get());
|
||||
if (!col_delim)
|
||||
throw Exception("Second argument for function " + getName() + " must be constant string.", ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
delimiter = col_delim->getValue<String>();
|
||||
}
|
||||
|
||||
if (const ColumnConst * col_const_arr = checkAndGetColumnConst<ColumnArray>(columns[arguments[0]].column.get()))
|
||||
if (const ColumnConst * col_const_arr = checkAndGetColumnConst<ColumnArray>(arguments[0].column.get()))
|
||||
{
|
||||
Array src_arr = col_const_arr->getValue<Array>();
|
||||
String dst_str;
|
||||
@ -559,11 +559,11 @@ public:
|
||||
dst_str += src_arr[i].get<const String &>();
|
||||
}
|
||||
|
||||
columns[result].column = columns[result].type->createColumnConst(col_const_arr->size(), dst_str);
|
||||
return result_type->createColumnConst(col_const_arr->size(), dst_str);
|
||||
}
|
||||
else
|
||||
{
|
||||
const ColumnArray & col_arr = assert_cast<const ColumnArray &>(*columns[arguments[0]].column);
|
||||
const ColumnArray & col_arr = assert_cast<const ColumnArray &>(*arguments[0].column);
|
||||
const ColumnString & col_string = assert_cast<const ColumnString &>(col_arr.getData());
|
||||
|
||||
auto col_res = ColumnString::create();
|
||||
@ -573,7 +573,7 @@ public:
|
||||
delimiter.data(), delimiter.size(),
|
||||
col_res->getChars(), col_res->getOffsets());
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -97,16 +97,16 @@ public:
|
||||
return std::make_shared<DataTypeNumber<typename Impl::ResultType>>();
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
using ResultType = typename Impl::ResultType;
|
||||
|
||||
const ColumnPtr & column_haystack = columns[arguments[0]].column;
|
||||
const ColumnPtr & column_needle = columns[arguments[1]].column;
|
||||
const ColumnPtr & column_haystack = arguments[0].column;
|
||||
const ColumnPtr & column_needle = arguments[1].column;
|
||||
|
||||
ColumnPtr column_start_pos = nullptr;
|
||||
if (arguments.size() >= 3)
|
||||
column_start_pos = columns[arguments[2]].column;
|
||||
column_start_pos = arguments[2].column;
|
||||
|
||||
const ColumnConst * col_haystack_const = typeid_cast<const ColumnConst *>(&*column_haystack);
|
||||
const ColumnConst * col_needle_const = typeid_cast<const ColumnConst *>(&*column_needle);
|
||||
@ -127,12 +127,9 @@ public:
|
||||
vec_res);
|
||||
|
||||
if (is_col_start_pos_const)
|
||||
columns[result].column
|
||||
= columns[result].type->createColumnConst(col_haystack_const->size(), toField(vec_res[0]));
|
||||
return result_type->createColumnConst(col_haystack_const->size(), toField(vec_res[0]));
|
||||
else
|
||||
columns[result].column = std::move(col_res);
|
||||
|
||||
return;
|
||||
return col_res;
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,11 +172,11 @@ public:
|
||||
vec_res);
|
||||
else
|
||||
throw Exception(
|
||||
"Illegal columns " + columns[arguments[0]].column->getName() + " and "
|
||||
+ columns[arguments[1]].column->getName() + " of arguments of function " + getName(),
|
||||
"Illegal columns " + arguments[0].column->getName() + " and "
|
||||
+ arguments[1].column->getName() + " of arguments of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -58,10 +58,10 @@ public:
|
||||
return std::make_shared<DataTypeString>();
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
const ColumnPtr column = columns[arguments[0]].column;
|
||||
const ColumnPtr column_needle = columns[arguments[1]].column;
|
||||
const ColumnPtr column = arguments[0].column;
|
||||
const ColumnPtr column_needle = arguments[1].column;
|
||||
|
||||
const ColumnConst * col_needle = typeid_cast<const ColumnConst *>(&*column_needle);
|
||||
if (!col_needle)
|
||||
@ -75,11 +75,11 @@ public:
|
||||
ColumnString::Offsets & offsets_res = col_res->getOffsets();
|
||||
Impl::vector(col->getChars(), col->getOffsets(), col_needle->getValue<String>(), vec_res, offsets_res);
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
else
|
||||
throw Exception(
|
||||
"Illegal column " + columns[arguments[0]].column->getName() + " of argument of function " + getName(),
|
||||
"Illegal column " + arguments[0].column->getName() + " of argument of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
};
|
||||
|
@ -51,12 +51,12 @@ public:
|
||||
return std::make_shared<DataTypeNumber<typename Impl::ResultType>>();
|
||||
}
|
||||
|
||||
void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) const override
|
||||
ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t /*input_rows_count*/) const override
|
||||
{
|
||||
using ResultType = typename Impl::ResultType;
|
||||
|
||||
const ColumnPtr & column_haystack = columns[arguments[0]].column;
|
||||
const ColumnPtr & column_needle = columns[arguments[1]].column;
|
||||
const ColumnPtr & column_haystack = arguments[0].column;
|
||||
const ColumnPtr & column_needle = arguments[1].column;
|
||||
|
||||
const ColumnConst * col_haystack_const = typeid_cast<const ColumnConst *>(&*column_haystack);
|
||||
const ColumnConst * col_needle_const = typeid_cast<const ColumnConst *>(&*column_needle);
|
||||
@ -73,9 +73,7 @@ public:
|
||||
ErrorCodes::TOO_LARGE_STRING_SIZE);
|
||||
}
|
||||
Impl::constantConstant(col_haystack_const->getValue<String>(), needle, res);
|
||||
columns[result].column
|
||||
= columns[result].type->createColumnConst(col_haystack_const->size(), toField(res));
|
||||
return;
|
||||
return result_type->createColumnConst(col_haystack_const->size(), toField(res));
|
||||
}
|
||||
|
||||
auto col_res = ColumnVector<ResultType>::create();
|
||||
@ -122,12 +120,12 @@ public:
|
||||
else
|
||||
{
|
||||
throw Exception(
|
||||
"Illegal columns " + columns[arguments[0]].column->getName() + " and "
|
||||
+ columns[arguments[1]].column->getName() + " of arguments of function " + getName(),
|
||||
"Illegal columns " + arguments[0].column->getName() + " and "
|
||||
+ arguments[1].column->getName() + " of arguments of function " + getName(),
|
||||
ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
|
||||
columns[result].column = std::move(col_res);
|
||||
return col_res;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include <Functions/FunctionHelpers.h>
|
||||
#include <Interpreters/ExpressionActions.h>
|
||||
#include <IO/WriteHelpers.h>
|
||||
#include <ext/range.h>
|
||||
#include <ext/collection_cast.h>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
@ -104,7 +103,7 @@ void ExecutableFunctionAdaptor::createLowCardinalityResultCache(size_t cache_siz
|
||||
}
|
||||
|
||||
|
||||
ColumnPtr wrapInNullable(const ColumnPtr & src, const ColumnsWithTypeAndName & columns, const ColumnNumbers & args, size_t result, size_t input_rows_count)
|
||||
ColumnPtr wrapInNullable(const ColumnPtr & src, const ColumnsWithTypeAndName & args, const DataTypePtr & result_type, size_t input_rows_count)
|
||||
{
|
||||
ColumnPtr result_null_map_column;
|
||||
|
||||
@ -119,16 +118,14 @@ ColumnPtr wrapInNullable(const ColumnPtr & src, const ColumnsWithTypeAndName & c
|
||||
result_null_map_column = nullable->getNullMapColumnPtr();
|
||||
}
|
||||
|
||||
for (const auto & arg : args)
|
||||
for (const auto & elem : args)
|
||||
{
|
||||
const ColumnWithTypeAndName & elem = columns[arg];
|
||||
if (!elem.type->isNullable())
|
||||
continue;
|
||||
|
||||
/// Const Nullable that are NULL.
|
||||
if (elem.column->onlyNull())
|
||||
{
|
||||
auto result_type = columns[result].type;
|
||||
assert(result_type->isNullable());
|
||||
return result_type->createColumnConstWithDefaultValue(input_rows_count);
|
||||
}
|
||||
@ -175,23 +172,6 @@ struct NullPresence
|
||||
bool has_null_constant = false;
|
||||
};
|
||||
|
||||
NullPresence getNullPresense(const ColumnsWithTypeAndName & columns, const ColumnNumbers & args)
|
||||
{
|
||||
NullPresence res;
|
||||
|
||||
for (const auto & arg : args)
|
||||
{
|
||||
const auto & elem = columns[arg];
|
||||
|
||||
if (!res.has_nullable)
|
||||
res.has_nullable = elem.type->isNullable();
|
||||
if (!res.has_null_constant)
|
||||
res.has_null_constant = elem.type->onlyNull();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
NullPresence getNullPresense(const ColumnsWithTypeAndName & args)
|
||||
{
|
||||
NullPresence res;
|
||||
@ -207,35 +187,36 @@ NullPresence getNullPresense(const ColumnsWithTypeAndName & args)
|
||||
return res;
|
||||
}
|
||||
|
||||
bool allArgumentsAreConstants(const ColumnsWithTypeAndName & columns, const ColumnNumbers & args)
|
||||
bool allArgumentsAreConstants(const ColumnsWithTypeAndName & args)
|
||||
{
|
||||
for (auto arg : args)
|
||||
if (!isColumnConst(*columns[arg].column))
|
||||
for (const auto & arg : args)
|
||||
if (!isColumnConst(*arg.column))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool ExecutableFunctionAdaptor::defaultImplementationForConstantArguments(
|
||||
ColumnsWithTypeAndName & columns, const ColumnNumbers & args, size_t result, size_t input_rows_count, bool dry_run)
|
||||
ColumnPtr ExecutableFunctionAdaptor::defaultImplementationForConstantArguments(
|
||||
ColumnsWithTypeAndName & args, const DataTypePtr & result_type, size_t input_rows_count, bool dry_run)
|
||||
{
|
||||
ColumnNumbers arguments_to_remain_constants = impl->getArgumentsThatAreAlwaysConstant();
|
||||
|
||||
/// Check that these arguments are really constant.
|
||||
for (auto arg_num : arguments_to_remain_constants)
|
||||
if (arg_num < args.size() && !isColumnConst(*columns[args[arg_num]].column))
|
||||
if (arg_num < args.size() && !isColumnConst(*args[arg_num].column))
|
||||
throw Exception("Argument at index " + toString(arg_num) + " for function " + getName() + " must be constant", ErrorCodes::ILLEGAL_COLUMN);
|
||||
|
||||
if (args.empty() || !impl->useDefaultImplementationForConstants() || !allArgumentsAreConstants(columns, args))
|
||||
return false;
|
||||
if (args.empty() || !impl->useDefaultImplementationForConstants() || !allArgumentsAreConstants(args))
|
||||
return nullptr;
|
||||
|
||||
ColumnsWithTypeAndName temporary_columns;
|
||||
bool have_converted_columns = false;
|
||||
|
||||
size_t arguments_size = args.size();
|
||||
temporary_columns.reserve(arguments_size);
|
||||
for (size_t arg_num = 0; arg_num < arguments_size; ++arg_num)
|
||||
{
|
||||
const ColumnWithTypeAndName & column = columns[args[arg_num]];
|
||||
const ColumnWithTypeAndName & column = args[arg_num];
|
||||
|
||||
if (arguments_to_remain_constants.end() != std::find(arguments_to_remain_constants.begin(), arguments_to_remain_constants.end(), arg_num))
|
||||
{
|
||||
@ -255,80 +236,72 @@ bool ExecutableFunctionAdaptor::defaultImplementationForConstantArguments(
|
||||
throw Exception("Number of arguments for function " + getName() + " doesn't match: the function requires more arguments",
|
||||
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
|
||||
temporary_columns.emplace_back(columns[result]);
|
||||
ColumnPtr result_column = executeWithoutLowCardinalityColumns(temporary_columns, result_type, 1, dry_run);
|
||||
|
||||
ColumnNumbers temporary_argument_numbers(arguments_size);
|
||||
for (size_t i = 0; i < arguments_size; ++i)
|
||||
temporary_argument_numbers[i] = i;
|
||||
|
||||
executeWithoutLowCardinalityColumns(temporary_columns, temporary_argument_numbers, arguments_size, 1, dry_run);
|
||||
|
||||
ColumnPtr result_column;
|
||||
/// extremely rare case, when we have function with completely const arguments
|
||||
/// but some of them produced by non isDeterministic function
|
||||
if (temporary_columns[arguments_size].column->size() > 1)
|
||||
result_column = temporary_columns[arguments_size].column->cloneResized(1);
|
||||
else
|
||||
result_column = temporary_columns[arguments_size].column;
|
||||
if (result_column->size() > 1)
|
||||
result_column = result_column->cloneResized(1);
|
||||
|
||||
columns[result].column = ColumnConst::create(result_column, input_rows_count);
|
||||
return true;
|
||||
return ColumnConst::create(result_column, input_rows_count);
|
||||
}
|
||||
|
||||
|
||||
bool ExecutableFunctionAdaptor::defaultImplementationForNulls(
|
||||
ColumnsWithTypeAndName & columns, const ColumnNumbers & args, size_t result, size_t input_rows_count, bool dry_run)
|
||||
ColumnPtr ExecutableFunctionAdaptor::defaultImplementationForNulls(ColumnsWithTypeAndName & args, const DataTypePtr & result_type, size_t input_rows_count, bool dry_run)
|
||||
{
|
||||
if (args.empty() || !impl->useDefaultImplementationForNulls())
|
||||
return false;
|
||||
return nullptr;
|
||||
|
||||
NullPresence null_presence = getNullPresense(columns, args);
|
||||
NullPresence null_presence = getNullPresense(args);
|
||||
|
||||
if (null_presence.has_null_constant)
|
||||
{
|
||||
auto & result_column = columns[result].column;
|
||||
auto result_type = columns[result].type;
|
||||
// Default implementation for nulls returns null result for null arguments,
|
||||
// so the result type must be nullable.
|
||||
assert(result_type->isNullable());
|
||||
|
||||
result_column = result_type->createColumnConstWithDefaultValue(input_rows_count);
|
||||
return true;
|
||||
return result_type->createColumnConstWithDefaultValue(input_rows_count);
|
||||
}
|
||||
|
||||
if (null_presence.has_nullable)
|
||||
{
|
||||
ColumnsWithTypeAndName temporary_columns = createBlockWithNestedColumns(columns, args, result);
|
||||
executeWithoutLowCardinalityColumns(temporary_columns, args, result, input_rows_count, dry_run);
|
||||
columns[result].column = wrapInNullable(temporary_columns[result].column, columns, args, result, input_rows_count);
|
||||
return true;
|
||||
ColumnsWithTypeAndName temporary_columns = createBlockWithNestedColumns(args);
|
||||
auto temporary_result_type = removeNullable(result_type);
|
||||
|
||||
auto res = executeWithoutLowCardinalityColumns(temporary_columns, temporary_result_type, input_rows_count, dry_run);
|
||||
return wrapInNullable(res, args, result_type, input_rows_count);
|
||||
}
|
||||
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ExecutableFunctionAdaptor::executeWithoutLowCardinalityColumns(
|
||||
ColumnsWithTypeAndName & columns, const ColumnNumbers & args, size_t result, size_t input_rows_count, bool dry_run)
|
||||
ColumnPtr ExecutableFunctionAdaptor::executeWithoutLowCardinalityColumns(
|
||||
ColumnsWithTypeAndName & args, const DataTypePtr & result_type, size_t input_rows_count, bool dry_run)
|
||||
{
|
||||
if (defaultImplementationForConstantArguments(columns, args, result, input_rows_count, dry_run))
|
||||
return;
|
||||
if (auto res = defaultImplementationForConstantArguments(args, result_type, input_rows_count, dry_run))
|
||||
return res;
|
||||
|
||||
if (defaultImplementationForNulls(columns, args, result, input_rows_count, dry_run))
|
||||
return;
|
||||
if (auto res = defaultImplementationForNulls(args, result_type, input_rows_count, dry_run))
|
||||
return res;
|
||||
|
||||
ColumnPtr res;
|
||||
if (dry_run)
|
||||
impl->executeDryRun(columns, args, result, input_rows_count);
|
||||
res = impl->executeDryRun(args, result_type, input_rows_count);
|
||||
else
|
||||
impl->execute(columns, args, result, input_rows_count);
|
||||
res = impl->execute(args, result_type, input_rows_count);
|
||||
|
||||
if (!res)
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Empty column was returned by function {}", getName());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static const ColumnLowCardinality * findLowCardinalityArgument(const ColumnsWithTypeAndName & columns, const ColumnNumbers & args)
|
||||
static const ColumnLowCardinality * findLowCardinalityArgument(const ColumnsWithTypeAndName & arguments)
|
||||
{
|
||||
const ColumnLowCardinality * result_column = nullptr;
|
||||
|
||||
for (auto arg : args)
|
||||
for (const auto & column : arguments)
|
||||
{
|
||||
const ColumnWithTypeAndName & column = columns[arg];
|
||||
if (const auto * low_cardinality_column = checkAndGetColumn<ColumnLowCardinality>(column.column.get()))
|
||||
{
|
||||
if (result_column)
|
||||
@ -342,15 +315,14 @@ static const ColumnLowCardinality * findLowCardinalityArgument(const ColumnsWith
|
||||
}
|
||||
|
||||
static ColumnPtr replaceLowCardinalityColumnsByNestedAndGetDictionaryIndexes(
|
||||
ColumnsWithTypeAndName & columns, const ColumnNumbers & args, bool can_be_executed_on_default_arguments, size_t input_rows_count)
|
||||
ColumnsWithTypeAndName & args, bool can_be_executed_on_default_arguments, size_t input_rows_count)
|
||||
{
|
||||
size_t num_rows = input_rows_count;
|
||||
ColumnPtr indexes;
|
||||
|
||||
/// Find first LowCardinality column and replace it to nested dictionary.
|
||||
for (auto arg : args)
|
||||
for (auto & column : args)
|
||||
{
|
||||
ColumnWithTypeAndName & column = columns[arg];
|
||||
if (const auto * low_cardinality_column = checkAndGetColumn<ColumnLowCardinality>(column.column.get()))
|
||||
{
|
||||
/// Single LowCardinality column is supported now.
|
||||
@ -384,9 +356,8 @@ static ColumnPtr replaceLowCardinalityColumnsByNestedAndGetDictionaryIndexes(
|
||||
}
|
||||
|
||||
/// Change size of constants.
|
||||
for (auto arg : args)
|
||||
for (auto & column : args)
|
||||
{
|
||||
ColumnWithTypeAndName & column = columns[arg];
|
||||
if (const auto * column_const = checkAndGetColumn<ColumnConst>(column.column.get()))
|
||||
{
|
||||
column.column = column_const->removeLowCardinality()->cloneResized(num_rows);
|
||||
@ -397,41 +368,24 @@ static ColumnPtr replaceLowCardinalityColumnsByNestedAndGetDictionaryIndexes(
|
||||
return indexes;
|
||||
}
|
||||
|
||||
static void convertLowCardinalityColumnsToFull(ColumnsWithTypeAndName & columns, const ColumnNumbers & args)
|
||||
static void convertLowCardinalityColumnsToFull(ColumnsWithTypeAndName & args)
|
||||
{
|
||||
for (auto arg : args)
|
||||
for (auto & column : args)
|
||||
{
|
||||
ColumnWithTypeAndName & column = columns[arg];
|
||||
|
||||
column.column = recursiveRemoveLowCardinality(column.column);
|
||||
column.type = recursiveRemoveLowCardinality(column.type);
|
||||
}
|
||||
}
|
||||
|
||||
static ColumnsWithTypeAndName cloneWithEmptyColumns(const ColumnsWithTypeAndName & columns)
|
||||
{
|
||||
ColumnsWithTypeAndName res;
|
||||
|
||||
size_t num_columns = columns.size();
|
||||
for (size_t i = 0; i < num_columns; ++i)
|
||||
res.emplace_back(ColumnWithTypeAndName{ nullptr, columns[i].type, columns[i].name });
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void ExecutableFunctionAdaptor::execute(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count, bool dry_run)
|
||||
ColumnPtr ExecutableFunctionAdaptor::execute(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count, bool dry_run)
|
||||
{
|
||||
if (impl->useDefaultImplementationForLowCardinalityColumns())
|
||||
{
|
||||
auto & res = columns[result];
|
||||
ColumnsWithTypeAndName columns_without_low_cardinality = cloneWithEmptyColumns(columns);
|
||||
ColumnsWithTypeAndName columns_without_low_cardinality = arguments;
|
||||
|
||||
for (auto arg : arguments)
|
||||
columns_without_low_cardinality[arg].column = columns[arg].column;
|
||||
|
||||
if (const auto * res_low_cardinality_type = typeid_cast<const DataTypeLowCardinality *>(res.type.get()))
|
||||
if (const auto * res_low_cardinality_type = typeid_cast<const DataTypeLowCardinality *>(result_type.get()))
|
||||
{
|
||||
const auto * low_cardinality_column = findLowCardinalityArgument(columns, arguments);
|
||||
const auto * low_cardinality_column = findLowCardinalityArgument(arguments);
|
||||
bool can_be_executed_on_default_arguments = impl->canBeExecutedOnDefaultArguments();
|
||||
bool use_cache = low_cardinality_result_cache && can_be_executed_on_default_arguments
|
||||
&& low_cardinality_column && low_cardinality_column->isSharedDictionary();
|
||||
@ -446,22 +400,20 @@ void ExecutableFunctionAdaptor::execute(ColumnsWithTypeAndName & columns, const
|
||||
if (cached_values)
|
||||
{
|
||||
auto indexes = cached_values->index_mapping->index(low_cardinality_column->getIndexes(), 0);
|
||||
res.column = ColumnLowCardinality::create(cached_values->function_result, indexes, true);
|
||||
return;
|
||||
return ColumnLowCardinality::create(cached_values->function_result, indexes, true);
|
||||
}
|
||||
}
|
||||
|
||||
columns_without_low_cardinality[result].type = res_low_cardinality_type->getDictionaryType();
|
||||
const auto & dictionary_type = res_low_cardinality_type->getDictionaryType();
|
||||
ColumnPtr indexes = replaceLowCardinalityColumnsByNestedAndGetDictionaryIndexes(
|
||||
columns_without_low_cardinality, arguments, can_be_executed_on_default_arguments, input_rows_count);
|
||||
columns_without_low_cardinality, can_be_executed_on_default_arguments, input_rows_count);
|
||||
|
||||
size_t new_input_rows_count = arguments.empty()
|
||||
size_t new_input_rows_count = columns_without_low_cardinality.empty()
|
||||
? input_rows_count
|
||||
: columns_without_low_cardinality[arguments.front()].column->size();
|
||||
: columns_without_low_cardinality.front().column->size();
|
||||
|
||||
executeWithoutLowCardinalityColumns(columns_without_low_cardinality, arguments, result, new_input_rows_count, dry_run);
|
||||
|
||||
auto keys = columns_without_low_cardinality[result].column->convertToFullColumnIfConst();
|
||||
auto res = executeWithoutLowCardinalityColumns(columns_without_low_cardinality, dictionary_type, new_input_rows_count, dry_run);
|
||||
auto keys = res->convertToFullColumnIfConst();
|
||||
|
||||
auto res_mut_dictionary = DataTypeLowCardinality::createColumnUnique(*res_low_cardinality_type->getDictionaryType());
|
||||
ColumnPtr res_indexes = res_mut_dictionary->uniqueInsertRangeFrom(*keys, 0, keys->size());
|
||||
@ -481,22 +433,21 @@ void ExecutableFunctionAdaptor::execute(ColumnsWithTypeAndName & columns, const
|
||||
res_indexes = cache_values->index_mapping;
|
||||
}
|
||||
|
||||
res.column = ColumnLowCardinality::create(res_dictionary, res_indexes->index(*indexes, 0), use_cache);
|
||||
return ColumnLowCardinality::create(res_dictionary, res_indexes->index(*indexes, 0), use_cache);
|
||||
}
|
||||
else
|
||||
{
|
||||
res.column = ColumnLowCardinality::create(res_dictionary, res_indexes);
|
||||
return ColumnLowCardinality::create(res_dictionary, res_indexes);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
convertLowCardinalityColumnsToFull(columns_without_low_cardinality, arguments);
|
||||
executeWithoutLowCardinalityColumns(columns_without_low_cardinality, arguments, result, input_rows_count, dry_run);
|
||||
res.column = columns_without_low_cardinality[result].column;
|
||||
convertLowCardinalityColumnsToFull(columns_without_low_cardinality);
|
||||
return executeWithoutLowCardinalityColumns(columns_without_low_cardinality, result_type, input_rows_count, dry_run);
|
||||
}
|
||||
}
|
||||
else
|
||||
executeWithoutLowCardinalityColumns(columns, arguments, result, input_rows_count, dry_run);
|
||||
return executeWithoutLowCardinalityColumns(arguments, result_type, input_rows_count, dry_run);
|
||||
}
|
||||
|
||||
void FunctionOverloadResolverAdaptor::checkNumberOfArguments(size_t number_of_arguments) const
|
||||
@ -526,9 +477,7 @@ DataTypePtr FunctionOverloadResolverAdaptor::getReturnTypeWithoutLowCardinality(
|
||||
}
|
||||
if (null_presence.has_nullable)
|
||||
{
|
||||
Block nested_columns = createBlockWithNestedColumns(
|
||||
arguments,
|
||||
ext::collection_cast<ColumnNumbers>(ext::range(0, arguments.size())));
|
||||
Block nested_columns = createBlockWithNestedColumns(arguments);
|
||||
auto return_type = impl->getReturnType(ColumnsWithTypeAndName(nested_columns.begin(), nested_columns.end()));
|
||||
return makeNullable(return_type);
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ public:
|
||||
/// Get the main function name.
|
||||
virtual String getName() const = 0;
|
||||
|
||||
virtual void execute(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count, bool dry_run) = 0;
|
||||
virtual ColumnPtr execute(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count, bool dry_run) = 0;
|
||||
|
||||
virtual void createLowCardinalityResultCache(size_t cache_size) = 0;
|
||||
};
|
||||
@ -67,16 +67,16 @@ public:
|
||||
virtual String getName() const = 0;
|
||||
|
||||
virtual const DataTypes & getArgumentTypes() const = 0;
|
||||
virtual const DataTypePtr & getReturnType() const = 0;
|
||||
virtual const DataTypePtr & getResultType() const = 0;
|
||||
|
||||
/// Do preparations and return executable.
|
||||
/// sample_columns should contain data types of arguments and values of constants, if relevant.
|
||||
virtual ExecutableFunctionPtr prepare(const ColumnsWithTypeAndName & sample_columns, const ColumnNumbers & arguments, size_t result) const = 0;
|
||||
virtual ExecutableFunctionPtr prepare(const ColumnsWithTypeAndName & arguments) const = 0;
|
||||
|
||||
/// TODO: make const
|
||||
virtual void execute(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count, bool dry_run = false)
|
||||
virtual ColumnPtr execute(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count, bool dry_run = false)
|
||||
{
|
||||
return prepare(columns, arguments, result)->execute(columns, arguments, result, input_rows_count, dry_run);
|
||||
return prepare(arguments)->execute(arguments, result_type, input_rows_count, dry_run);
|
||||
}
|
||||
|
||||
#if USE_EMBEDDED_COMPILER
|
||||
@ -111,7 +111,7 @@ public:
|
||||
* There is no need to implement function if it has zero arguments.
|
||||
* Must return ColumnConst with single row or nullptr.
|
||||
*/
|
||||
virtual ColumnPtr getResultIfAlwaysReturnsConstantAndHasArguments(const ColumnsWithTypeAndName & /*columns*/, const ColumnNumbers & /*arguments*/) const { return nullptr; }
|
||||
virtual ColumnPtr getResultIfAlwaysReturnsConstantAndHasArguments(const ColumnsWithTypeAndName & /*columns*/) const { return nullptr; }
|
||||
|
||||
/** Function is called "injective" if it returns different result for different values of arguments.
|
||||
* Example: hex, negate, tuple...
|
||||
@ -226,9 +226,9 @@ public:
|
||||
using FunctionOverloadResolverPtr = std::shared_ptr<IFunctionOverloadResolver>;
|
||||
|
||||
|
||||
/** Return ColumnNullable of src, with null map as OR-ed null maps of args columns in columnss.
|
||||
/** Return ColumnNullable of src, with null map as OR-ed null maps of args columns.
|
||||
* Or ColumnConst(ColumnNullable) if the result is always NULL or if the result is constant and always not NULL.
|
||||
*/
|
||||
ColumnPtr wrapInNullable(const ColumnPtr & src, const ColumnsWithTypeAndName & columns, const ColumnNumbers & args, size_t result, size_t input_rows_count);
|
||||
ColumnPtr wrapInNullable(const ColumnPtr & src, const ColumnsWithTypeAndName & args, const DataTypePtr & result_type, size_t input_rows_count);
|
||||
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ public:
|
||||
|
||||
String getName() const final { return impl->getName(); }
|
||||
|
||||
void execute(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count, bool dry_run) final;
|
||||
ColumnPtr execute(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count, bool dry_run) final;
|
||||
|
||||
void createLowCardinalityResultCache(size_t cache_size) override;
|
||||
|
||||
@ -24,14 +24,14 @@ private:
|
||||
/// Cache is created by function createLowCardinalityResultCache()
|
||||
ExecutableFunctionLowCardinalityResultCachePtr low_cardinality_result_cache;
|
||||
|
||||
bool defaultImplementationForConstantArguments(
|
||||
ColumnsWithTypeAndName & columns, const ColumnNumbers & args, size_t result, size_t input_rows_count, bool dry_run);
|
||||
ColumnPtr defaultImplementationForConstantArguments(
|
||||
ColumnsWithTypeAndName & args, const DataTypePtr & result_type, size_t input_rows_count, bool dry_run);
|
||||
|
||||
bool defaultImplementationForNulls(
|
||||
ColumnsWithTypeAndName & columns, const ColumnNumbers & args, size_t result, size_t input_rows_count, bool dry_run);
|
||||
ColumnPtr defaultImplementationForNulls(
|
||||
ColumnsWithTypeAndName & args, const DataTypePtr & result_type, size_t input_rows_count, bool dry_run);
|
||||
|
||||
void executeWithoutLowCardinalityColumns(
|
||||
ColumnsWithTypeAndName & columns, const ColumnNumbers & args, size_t result, size_t input_rows_count, bool dry_run);
|
||||
ColumnPtr executeWithoutLowCardinalityColumns(
|
||||
ColumnsWithTypeAndName & args, const DataTypePtr & result_type, size_t input_rows_count, bool dry_run);
|
||||
};
|
||||
|
||||
class FunctionBaseAdaptor final : public IFunctionBase
|
||||
@ -42,12 +42,11 @@ public:
|
||||
String getName() const final { return impl->getName(); }
|
||||
|
||||
const DataTypes & getArgumentTypes() const final { return impl->getArgumentTypes(); }
|
||||
const DataTypePtr & getReturnType() const final { return impl->getReturnType(); }
|
||||
const DataTypePtr & getResultType() const final { return impl->getResultType(); }
|
||||
|
||||
ExecutableFunctionPtr prepare(const ColumnsWithTypeAndName & sample_columns, const ColumnNumbers & arguments, size_t result) const final
|
||||
ExecutableFunctionPtr prepare(const ColumnsWithTypeAndName & arguments) const final
|
||||
{
|
||||
ColumnsWithTypeAndName columns(const_cast<ColumnsWithTypeAndName &>(sample_columns));
|
||||
return std::make_shared<ExecutableFunctionAdaptor>(impl->prepare(columns, arguments, result));
|
||||
return std::make_shared<ExecutableFunctionAdaptor>(impl->prepare(arguments));
|
||||
}
|
||||
|
||||
#if USE_EMBEDDED_COMPILER
|
||||
@ -64,9 +63,9 @@ public:
|
||||
bool isStateful() const final { return impl->isStateful(); }
|
||||
bool isSuitableForConstantFolding() const final { return impl->isSuitableForConstantFolding(); }
|
||||
|
||||
ColumnPtr getResultIfAlwaysReturnsConstantAndHasArguments(const ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments) const final
|
||||
ColumnPtr getResultIfAlwaysReturnsConstantAndHasArguments(const ColumnsWithTypeAndName & arguments) const final
|
||||
{
|
||||
return impl->getResultIfAlwaysReturnsConstantAndHasArguments(columns, arguments);
|
||||
return impl->getResultIfAlwaysReturnsConstantAndHasArguments(arguments);
|
||||
}
|
||||
|
||||
bool isInjective(const ColumnsWithTypeAndName & sample_columns) const final { return impl->isInjective(sample_columns); }
|
||||
@ -148,13 +147,13 @@ public:
|
||||
String getName() const override { return function->getName(); }
|
||||
|
||||
protected:
|
||||
void execute(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) final
|
||||
ColumnPtr execute(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) final
|
||||
{
|
||||
return function->executeImpl(columns, arguments, result, input_rows_count);
|
||||
return function->executeImpl(arguments, result_type, input_rows_count);
|
||||
}
|
||||
void executeDryRun(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) final
|
||||
ColumnPtr executeDryRun(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) final
|
||||
{
|
||||
return function->executeImplDryRun(columns, arguments, result, input_rows_count);
|
||||
return function->executeImplDryRun(arguments, result_type, input_rows_count);
|
||||
}
|
||||
bool useDefaultImplementationForNulls() const final { return function->useDefaultImplementationForNulls(); }
|
||||
bool useDefaultImplementationForConstants() const final { return function->useDefaultImplementationForConstants(); }
|
||||
@ -169,31 +168,31 @@ private:
|
||||
class DefaultFunction final : public IFunctionBaseImpl
|
||||
{
|
||||
public:
|
||||
DefaultFunction(std::shared_ptr<IFunction> function_, DataTypes arguments_, DataTypePtr return_type_)
|
||||
: function(std::move(function_)), arguments(std::move(arguments_)), return_type(std::move(return_type_)) {}
|
||||
DefaultFunction(std::shared_ptr<IFunction> function_, DataTypes arguments_, DataTypePtr result_type_)
|
||||
: function(std::move(function_)), arguments(std::move(arguments_)), result_type(std::move(result_type_)) {}
|
||||
|
||||
String getName() const override { return function->getName(); }
|
||||
|
||||
const DataTypes & getArgumentTypes() const override { return arguments; }
|
||||
const DataTypePtr & getReturnType() const override { return return_type; }
|
||||
const DataTypePtr & getResultType() const override { return result_type; }
|
||||
|
||||
#if USE_EMBEDDED_COMPILER
|
||||
|
||||
bool isCompilable() const override { return function->isCompilable(arguments); }
|
||||
bool isCompilable() const override { return function->isCompilable(getArgumentTypes()); }
|
||||
|
||||
llvm::Value * compile(llvm::IRBuilderBase & builder, ValuePlaceholders values) const override { return function->compile(builder, arguments, std::move(values)); }
|
||||
llvm::Value * compile(llvm::IRBuilderBase & builder, ValuePlaceholders values) const override { return function->compile(builder, getArgumentTypes(), std::move(values)); }
|
||||
|
||||
#endif
|
||||
|
||||
ExecutableFunctionImplPtr prepare(const ColumnsWithTypeAndName & /*sample_columns*/, const ColumnNumbers & /*arguments*/, size_t /*result*/) const override
|
||||
ExecutableFunctionImplPtr prepare(const ColumnsWithTypeAndName & /*arguments*/) const override
|
||||
{
|
||||
return std::make_unique<DefaultExecutable>(function);
|
||||
}
|
||||
|
||||
bool isSuitableForConstantFolding() const override { return function->isSuitableForConstantFolding(); }
|
||||
ColumnPtr getResultIfAlwaysReturnsConstantAndHasArguments(const ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments_) const override
|
||||
ColumnPtr getResultIfAlwaysReturnsConstantAndHasArguments(const ColumnsWithTypeAndName & arguments_) const override
|
||||
{
|
||||
return function->getResultIfAlwaysReturnsConstantAndHasArguments(columns, arguments_);
|
||||
return function->getResultIfAlwaysReturnsConstantAndHasArguments(arguments_);
|
||||
}
|
||||
|
||||
bool isStateful() const override { return function->isStateful(); }
|
||||
@ -214,7 +213,7 @@ public:
|
||||
private:
|
||||
std::shared_ptr<IFunction> function;
|
||||
DataTypes arguments;
|
||||
DataTypePtr return_type;
|
||||
DataTypePtr result_type;
|
||||
};
|
||||
|
||||
class DefaultOverloadResolver : public IFunctionOverloadResolverImpl
|
||||
@ -244,12 +243,12 @@ public:
|
||||
bool useDefaultImplementationForLowCardinalityColumns() const override { return function->useDefaultImplementationForLowCardinalityColumns(); }
|
||||
bool canBeExecutedOnLowCardinalityDictionary() const override { return function->canBeExecutedOnLowCardinalityDictionary(); }
|
||||
|
||||
FunctionBaseImplPtr build(const ColumnsWithTypeAndName & arguments, const DataTypePtr & return_type) const override
|
||||
FunctionBaseImplPtr build(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type) const override
|
||||
{
|
||||
DataTypes data_types(arguments.size());
|
||||
for (size_t i = 0; i < arguments.size(); ++i)
|
||||
data_types[i] = arguments[i].type;
|
||||
return std::make_unique<DefaultFunction>(function, data_types, return_type);
|
||||
return std::make_unique<DefaultFunction>(function, data_types, result_type);
|
||||
}
|
||||
|
||||
void getLambdaArgumentTypes(DataTypes & arguments) const override { function->getLambdaArgumentTypes(arguments); }
|
||||
|
@ -35,10 +35,10 @@ public:
|
||||
|
||||
virtual String getName() const = 0;
|
||||
|
||||
virtual void execute(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) = 0;
|
||||
virtual void executeDryRun(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count)
|
||||
virtual ColumnPtr execute(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) = 0;
|
||||
virtual ColumnPtr executeDryRun(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count)
|
||||
{
|
||||
execute(columns, arguments, result, input_rows_count);
|
||||
return execute(arguments, result_type, input_rows_count);
|
||||
}
|
||||
|
||||
/** Default implementation in presence of Nullable arguments or NULL constants as arguments is the following:
|
||||
@ -87,9 +87,9 @@ public:
|
||||
virtual String getName() const = 0;
|
||||
|
||||
virtual const DataTypes & getArgumentTypes() const = 0;
|
||||
virtual const DataTypePtr & getReturnType() const = 0;
|
||||
virtual const DataTypePtr & getResultType() const = 0;
|
||||
|
||||
virtual ExecutableFunctionImplPtr prepare(const ColumnsWithTypeAndName & sample_columns, const ColumnNumbers & arguments, size_t result) const = 0;
|
||||
virtual ExecutableFunctionImplPtr prepare(const ColumnsWithTypeAndName & arguments) const = 0;
|
||||
|
||||
#if USE_EMBEDDED_COMPILER
|
||||
|
||||
@ -105,7 +105,7 @@ public:
|
||||
virtual bool isStateful() const { return false; }
|
||||
|
||||
virtual bool isSuitableForConstantFolding() const { return true; }
|
||||
virtual ColumnPtr getResultIfAlwaysReturnsConstantAndHasArguments(const ColumnsWithTypeAndName & /*columns*/, const ColumnNumbers & /*arguments*/) const { return nullptr; }
|
||||
virtual ColumnPtr getResultIfAlwaysReturnsConstantAndHasArguments(const ColumnsWithTypeAndName & /*arguments*/) const { return nullptr; }
|
||||
|
||||
virtual bool isInjective(const ColumnsWithTypeAndName & /*sample_columns*/) const { return false; }
|
||||
virtual bool isDeterministic() const { return true; }
|
||||
@ -130,7 +130,7 @@ public:
|
||||
|
||||
virtual String getName() const = 0;
|
||||
|
||||
virtual FunctionBaseImplPtr build(const ColumnsWithTypeAndName & arguments, const DataTypePtr & return_type) const = 0;
|
||||
virtual FunctionBaseImplPtr build(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type) const = 0;
|
||||
|
||||
virtual DataTypePtr getReturnType(const DataTypes & /*arguments*/) const
|
||||
{
|
||||
@ -197,10 +197,10 @@ public:
|
||||
|
||||
virtual String getName() const = 0;
|
||||
|
||||
virtual void executeImpl(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const = 0;
|
||||
virtual void executeImplDryRun(ColumnsWithTypeAndName & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const
|
||||
virtual ColumnPtr executeImpl(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const = 0;
|
||||
virtual ColumnPtr executeImplDryRun(ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const
|
||||
{
|
||||
executeImpl(columns, arguments, result, input_rows_count);
|
||||
return executeImpl(arguments, result_type, input_rows_count);
|
||||
}
|
||||
|
||||
/** Default implementation in presence of Nullable arguments or NULL constants as arguments is the following:
|
||||
@ -252,7 +252,7 @@ public:
|
||||
|
||||
/// Properties from IFunctionBase (see IFunction.h)
|
||||
virtual bool isSuitableForConstantFolding() const { return true; }
|
||||
virtual ColumnPtr getResultIfAlwaysReturnsConstantAndHasArguments(const ColumnsWithTypeAndName & /*columns*/, const ColumnNumbers & /*arguments*/) const { return nullptr; }
|
||||
virtual ColumnPtr getResultIfAlwaysReturnsConstantAndHasArguments(const ColumnsWithTypeAndName & /*arguments*/) const { return nullptr; }
|
||||
virtual bool isInjective(const ColumnsWithTypeAndName & /*sample_columns*/) const { return false; }
|
||||
virtual bool isDeterministic() const { return true; }
|
||||
virtual bool isDeterministicInScopeOfQuery() const { return true; }
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user