diff --git a/tests/testflows/extended_precision_data_types/common.py b/tests/testflows/extended_precision_data_types/common.py new file mode 100644 index 00000000000..1c852bbf935 --- /dev/null +++ b/tests/testflows/extended_precision_data_types/common.py @@ -0,0 +1,118 @@ +import uuid + +from contextlib import contextmanager + +from testflows.core.name import basename, parentname +from testflows._core.testtype import TestSubType +from testflows.asserts import values, error, snapshot + +from helpers.common import * + +@contextmanager +def allow_experimental_bigint(node): + """Enable experimental big int setting in Clickhouse. + """ + setting = ("allow_experimental_bigint_types", 1) + default_query_settings = None + + try: + with Given("I add allow_experimental_bigint to the default query settings"): + default_query_settings = getsattr(current().context, "default_query_settings", []) + default_query_settings.append(setting) + yield + finally: + with Finally("I remove allow_experimental_bigint from the default query settings"): + if default_query_settings: + try: + default_query_settings.pop(default_query_settings.index(setting)) + except ValueError: + pass + +@TestStep(Given) +def allow_experimental_map_type(self): + """Set allow_experimental_map_type = 1 + """ + setting = ("allow_experimental_map_type", 1) + default_query_settings = None + + try: + with By("adding allow_experimental_map_type to the default query settings"): + default_query_settings = getsattr(current().context, "default_query_settings", []) + default_query_settings.append(setting) + yield + finally: + with Finally("I remove allow_experimental_map_type from the default query settings"): + if default_query_settings: + try: + default_query_settings.pop(default_query_settings.index(setting)) + except ValueError: + pass + +def execute_query(sql, expected=None, format="TabSeparatedWithNames", compare_func=None): + """Execute SQL query and compare the output to the snapshot. + """ + name = basename(current().name) + + with When("I execute query", description=sql): + r = current().context.node.query(sql + " FORMAT " + format) + + if expected is not None: + with Then("I check output against expected"): + + if compare_func is None: + assert r.output.strip() == expected, error() + + else: + assert compare_func(r.output.strip(), expected), error() + + else: + with Then("I check output against snapshot"): + with values() as that: + assert that(snapshot("\n" + r.output.strip() + "\n", "tests", name=name, encoder=str)), error() + +@TestStep(Given) +def table(self, data_type, name="table0"): + """Create a table. + """ + node = current().context.node + + try: + with By("creating table"): + node.query(f"CREATE TABLE {name}(a {data_type}) ENGINE = Memory") + yield + + finally: + with Finally("drop the table"): + node.query(f"DROP TABLE IF EXISTS {name}") + +def getuid(): + """Create a unique variable name based on the test it is called from. + """ + if current().subtype == TestSubType.Example: + testname = f"{basename(parentname(current().name)).replace(' ', '_').replace(',','')}" + else: + testname = f"{basename(current().name).replace(' ', '_').replace(',','')}" + + for char in ['(', ')', '[', ']','\'']: + testname = testname.replace(f'{char}', '') + + return testname + "_" + str(uuid.uuid1()).replace('-', '_') + +def to_data_type(data_type, value): + """Return a conversion statement based on the data type provided + """ + if data_type in ['Decimal256(0)']: + return f'toDecimal256(\'{value}\',0)' + + else: + return f'to{data_type}(\'{value}\')' + + +data_types = [ + ('Int128', '-170141183460469231731687303715884105728', '170141183460469231731687303715884105727'), + ('Int256', '-57896044618658097711785492504343953926634992332820282019728792003956564819968', '57896044618658097711785492504343953926634992332820282019728792003956564819967'), + ('UInt128','0','340282366920938463463374607431768211455'), + ('UInt256', '0', '115792089237316195423570985008687907853269984665640564039457584007913129639935'), +] + +Decimal256_min_max = -1000000000000000000000000000000000000000000000000000000000000000000000000000,1000000000000000000000000000000000000000000000000000000000000000000000000000 diff --git a/tests/testflows/extended_precision_data_types/configs/clickhouse/common.xml b/tests/testflows/extended_precision_data_types/configs/clickhouse/common.xml new file mode 100644 index 00000000000..567c8c05e32 --- /dev/null +++ b/tests/testflows/extended_precision_data_types/configs/clickhouse/common.xml @@ -0,0 +1,6 @@ + + Europe/Moscow + :: + /var/lib/clickhouse/ + /var/lib/clickhouse/tmp/ + diff --git a/tests/testflows/extended_precision_data_types/configs/clickhouse/config.d/logs.xml b/tests/testflows/extended_precision_data_types/configs/clickhouse/config.d/logs.xml new file mode 100644 index 00000000000..bdf1bbc11c1 --- /dev/null +++ b/tests/testflows/extended_precision_data_types/configs/clickhouse/config.d/logs.xml @@ -0,0 +1,17 @@ + + 3 + + trace + /var/log/clickhouse-server/log.log + /var/log/clickhouse-server/log.err.log + 1000M + 10 + /var/log/clickhouse-server/stderr.log + /var/log/clickhouse-server/stdout.log + + + system + part_log
+ 500 +
+
diff --git a/tests/testflows/extended_precision_data_types/configs/clickhouse/config.d/storage.xml b/tests/testflows/extended_precision_data_types/configs/clickhouse/config.d/storage.xml new file mode 100644 index 00000000000..618fd6b6d24 --- /dev/null +++ b/tests/testflows/extended_precision_data_types/configs/clickhouse/config.d/storage.xml @@ -0,0 +1,20 @@ + + + + + + 1024 + + + + + + + default + + + + + + + diff --git a/tests/testflows/extended_precision_data_types/configs/clickhouse/config.xml b/tests/testflows/extended_precision_data_types/configs/clickhouse/config.xml new file mode 100644 index 00000000000..4ec12232539 --- /dev/null +++ b/tests/testflows/extended_precision_data_types/configs/clickhouse/config.xml @@ -0,0 +1,448 @@ + + + + + + trace + /var/log/clickhouse-server/clickhouse-server.log + /var/log/clickhouse-server/clickhouse-server.err.log + 1000M + 10 + + + + 8123 + 9000 + + + + + + + + + /etc/clickhouse-server/server.crt + /etc/clickhouse-server/server.key + + /etc/clickhouse-server/dhparam.pem + none + true + true + sslv2,sslv3 + true + + + + true + true + sslv2,sslv3 + true + + + + RejectCertificateHandler + + + + + + + + + 9009 + + + + + + + + 0.0.0.0 + + + + + + + + + + + + 4096 + 3 + + + 100 + + + + + + 8589934592 + + + 5368709120 + + + + /var/lib/clickhouse/ + + + /var/lib/clickhouse/tmp/ + + + /var/lib/clickhouse/user_files/ + + + /var/lib/clickhouse/access/ + + + + + + users.xml + + + + /var/lib/clickhouse/access/ + + + + + users.xml + + + default + + + + + + default + + + + + + + + + false + + + + + + + + localhost + 9000 + + + + + + + localhost + 9000 + + + + + localhost + 9000 + + + + + + + localhost + 9440 + 1 + + + + + + + localhost + 9000 + + + + + localhost + 1 + + + + + + + + + + + + + + + + + 3600 + + + + 3600 + + + 60 + + + + + + + + + + system + query_log
+ + toYYYYMM(event_date) + + 7500 +
+ + + + system + trace_log
+ + toYYYYMM(event_date) + 7500 +
+ + + + system + query_thread_log
+ toYYYYMM(event_date) + 7500 +
+ + + + + + + + + + + + + + + + *_dictionary.xml + + + + + + + + + + /clickhouse/task_queue/ddl + + + + + + + + + + + + + + + + click_cost + any + + 0 + 3600 + + + 86400 + 60 + + + + max + + 0 + 60 + + + 3600 + 300 + + + 86400 + 3600 + + + + + + /var/lib/clickhouse/format_schemas/ + + + +
diff --git a/tests/testflows/extended_precision_data_types/configs/clickhouse/users.xml b/tests/testflows/extended_precision_data_types/configs/clickhouse/users.xml new file mode 100644 index 00000000000..86b2cd9e1e3 --- /dev/null +++ b/tests/testflows/extended_precision_data_types/configs/clickhouse/users.xml @@ -0,0 +1,133 @@ + + + + + + + + 10000000000 + + + 0 + + + random + + + + + 1 + + + + + + + + + + + + + ::/0 + + + + default + + + default + + + 1 + + + + + + + + + + + + + + + + + 3600 + + + 0 + 0 + 0 + 0 + 0 + + + + diff --git a/tests/testflows/extended_precision_data_types/errors.py b/tests/testflows/extended_precision_data_types/errors.py new file mode 100644 index 00000000000..63b82f3368d --- /dev/null +++ b/tests/testflows/extended_precision_data_types/errors.py @@ -0,0 +1,11 @@ +def not_implemented_bigints(name): + return(48, f"Exception: {name} is not implemented for big integers") + +def bigints_not_implements(name): + return(48, f'Exception: {name} for big integers is not implemented') + +def illegal_type(): + return(43, 'Exception: Illegal type') + +def illegal_column(): + return(44, 'Exception: Illegal column') \ No newline at end of file diff --git a/tests/testflows/extended_precision_data_types/extended-precision-data-type_env/clickhouse-service.yml b/tests/testflows/extended_precision_data_types/extended-precision-data-type_env/clickhouse-service.yml new file mode 100644 index 00000000000..fdd4a8057a9 --- /dev/null +++ b/tests/testflows/extended_precision_data_types/extended-precision-data-type_env/clickhouse-service.yml @@ -0,0 +1,27 @@ +version: '2.3' + +services: + clickhouse: + image: yandex/clickhouse-integration-test + expose: + - "9000" + - "9009" + - "8123" + volumes: + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse/config.d:/etc/clickhouse-server/config.d" + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse/users.d:/etc/clickhouse-server/users.d" + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse/config.xml:/etc/clickhouse-server/config.xml" + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse/users.xml:/etc/clickhouse-server/users.xml" + - "${CLICKHOUSE_TESTS_SERVER_BIN_PATH:-/usr/bin/clickhouse}:/usr/bin/clickhouse" + - "${CLICKHOUSE_TESTS_ODBC_BRIDGE_BIN_PATH:-/usr/bin/clickhouse-odbc-bridge}:/usr/bin/clickhouse-odbc-bridge" + entrypoint: bash -c "clickhouse server --config-file=/etc/clickhouse-server/config.xml --log-file=/var/log/clickhouse-server/clickhouse-server.log --errorlog-file=/var/log/clickhouse-server/clickhouse-server.err.log" + healthcheck: + test: clickhouse client --query='select 1' + interval: 10s + timeout: 10s + retries: 3 + start_period: 300s + cap_add: + - SYS_PTRACE + security_opt: + - label:disable diff --git a/tests/testflows/extended_precision_data_types/extended-precision-data-type_env/docker-compose.yml b/tests/testflows/extended_precision_data_types/extended-precision-data-type_env/docker-compose.yml new file mode 100644 index 00000000000..74d17d40e66 --- /dev/null +++ b/tests/testflows/extended_precision_data_types/extended-precision-data-type_env/docker-compose.yml @@ -0,0 +1,30 @@ +version: '2.3' + +services: + + mysql1: + extends: + file: mysql-service.yml + service: mysql + hostname: mysql1 + volumes: + - "${CLICKHOUSE_TESTS_DIR}/_instances/mysql1/database:/var/lib/mysql" + + clickhouse1: + extends: + file: clickhouse-service.yml + service: clickhouse + hostname: clickhouse1 + volumes: + - "${CLICKHOUSE_TESTS_DIR}/_instances/clickhouse1/database/:/var/lib/clickhouse/" + - "${CLICKHOUSE_TESTS_DIR}/_instances/clickhouse1/logs/:/var/log/clickhouse-server/" + + # dummy service which does nothing, but allows to postpone + # 'docker-compose up -d' till all dependecies will go healthy + all_services_ready: + image: hello-world + depends_on: + clickhouse1: + condition: service_healthy + mysql1: + condition: service_healthy diff --git a/tests/testflows/extended_precision_data_types/extended-precision-data-type_env/mysql-service.yml b/tests/testflows/extended_precision_data_types/extended-precision-data-type_env/mysql-service.yml new file mode 100644 index 00000000000..6924bccfad5 --- /dev/null +++ b/tests/testflows/extended_precision_data_types/extended-precision-data-type_env/mysql-service.yml @@ -0,0 +1,19 @@ +version: '2.3' + +services: + mysql: + image: mysql:5.7.30 + restart: always + environment: + MYSQL_DATABASE: 'db' + MYSQL_USER: 'user' + MYSQL_PASSWORD: 'password' + MYSQL_ROOT_PASSWORD: 'password' + expose: + - '3306' + healthcheck: + test: mysql -D db -u user --password=password -e "select 1;" + interval: 3s + timeout: 2s + retries: 40 + start_period: 2s diff --git a/tests/testflows/extended_precision_data_types/regression.py b/tests/testflows/extended_precision_data_types/regression.py new file mode 100755 index 00000000000..a0c3186c961 --- /dev/null +++ b/tests/testflows/extended_precision_data_types/regression.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +import os +import sys + +from testflows.core import * + +append_path(sys.path, "..") + +from helpers.cluster import Cluster +from helpers.argparser import argparser +from extended_precision_data_types.requirements import * + +xfails = { +} + +xflags = { +} + +@TestModule +@ArgumentParser(argparser) +@XFails(xfails) +@XFlags(xflags) +@Name("extended precision data types") +@Specifications( + QA_SRS020_ClickHouse_Extended_Precision_Data_Types +) +@Requirements( + RQ_SRS_020_ClickHouse_Extended_Precision("1.0"), +) +def regression(self, local, clickhouse_binary_path, stress=None, parallel=None): + """Extended precision data type regression. + """ + + top().terminating = False + + nodes = { + "clickhouse": + ("clickhouse1",) + } + with Cluster(local, clickhouse_binary_path, nodes=nodes, + docker_compose_project_dir=os.path.join(current_dir(), "extended-precision-data-type_env")) as cluster: + + self.context.cluster = cluster + self.context.stress = stress + + if parallel is not None: + self.context.parallel = parallel + + Feature(run=load("extended_precision_data_types.tests.feature", "feature")) + +if main(): + regression() diff --git a/tests/testflows/extended_precision_data_types/requirements/__init__.py b/tests/testflows/extended_precision_data_types/requirements/__init__.py new file mode 100644 index 00000000000..75e9d5b4bb8 --- /dev/null +++ b/tests/testflows/extended_precision_data_types/requirements/__init__.py @@ -0,0 +1 @@ +from .requirements import * \ No newline at end of file diff --git a/tests/testflows/extended_precision_data_types/requirements/requirements.md b/tests/testflows/extended_precision_data_types/requirements/requirements.md new file mode 100644 index 00000000000..9bbd59a14d5 --- /dev/null +++ b/tests/testflows/extended_precision_data_types/requirements/requirements.md @@ -0,0 +1,565 @@ +# QA-SRS020 ClickHouse Extended Precision Data Types +# Software Requirements Specification + +## Table of Contents + +* 1 [Revision History](#revision-history) +* 2 [Introduction](#introduction) +* 3 [Terminology](#terminology) + * 3.1 [Extended Precision Data Types](#extended-precision-data-types) +* 4 [Requirements](#requirements) + * 4.1 [RQ.SRS-020.ClickHouse.Extended.Precision](#rqsrs-020clickhouseextendedprecision) + * 4.2 [Conversion](#conversion) + * 4.2.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toInt128](#rqsrs-020clickhouseextendedprecisionconversiontoint128) + * 4.2.2 [RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toUInt128](#rqsrs-020clickhouseextendedprecisionconversiontouint128) + * 4.2.3 [RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toInt256](#rqsrs-020clickhouseextendedprecisionconversiontoint256) + * 4.2.4 [RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toUInt256](#rqsrs-020clickhouseextendedprecisionconversiontouint256) + * 4.2.5 [RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toDecimal256](#rqsrs-020clickhouseextendedprecisionconversiontodecimal256) + * 4.2.6 [RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.FromMySQL](#rqsrs-020clickhouseextendedprecisionconversionfrommysql) + * 4.2.7 [RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.ToMySQL](#rqsrs-020clickhouseextendedprecisionconversiontomysql) + * 4.3 [Arithmetic](#arithmetic) + * 4.3.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Arithmetic.Int.Supported](#rqsrs-020clickhouseextendedprecisionarithmeticintsupported) + * 4.3.2 [RQ.SRS-020.ClickHouse.Extended.Precision.Arithmetic.Dec.Supported](#rqsrs-020clickhouseextendedprecisionarithmeticdecsupported) + * 4.3.3 [RQ.SRS-020.ClickHouse.Extended.Precision.Arithmetic.Dec.NotSupported](#rqsrs-020clickhouseextendedprecisionarithmeticdecnotsupported) + * 4.4 [Arrays](#arrays) + * 4.4.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Int.Supported](#rqsrs-020clickhouseextendedprecisionarraysintsupported) + * 4.4.2 [RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Int.NotSupported](#rqsrs-020clickhouseextendedprecisionarraysintnotsupported) + * 4.4.3 [RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Dec.Supported](#rqsrs-020clickhouseextendedprecisionarraysdecsupported) + * 4.4.4 [RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Dec.NotSupported](#rqsrs-020clickhouseextendedprecisionarraysdecnotsupported) + * 4.5 [Comparison](#comparison) + * 4.5.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Comparison](#rqsrs-020clickhouseextendedprecisioncomparison) + * 4.6 [Logical Functions](#logical-functions) + * 4.6.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Logical](#rqsrs-020clickhouseextendedprecisionlogical) + * 4.7 [Mathematical Functions](#mathematical-functions) + * 4.7.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Mathematical.Supported](#rqsrs-020clickhouseextendedprecisionmathematicalsupported) + * 4.7.2 [RQ.SRS-020.ClickHouse.Extended.Precision.Mathematical.NotSupported](#rqsrs-020clickhouseextendedprecisionmathematicalnotsupported) + * 4.8 [Rounding Functions](#rounding-functions) + * 4.8.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Int.Supported](#rqsrs-020clickhouseextendedprecisionroundingintsupported) + * 4.8.2 [RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Int.NotSupported](#rqsrs-020clickhouseextendedprecisionroundingintnotsupported) + * 4.8.3 [RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Dec.Supported](#rqsrs-020clickhouseextendedprecisionroundingdecsupported) + * 4.8.4 [RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Dec.NotSupported](#rqsrs-020clickhouseextendedprecisionroundingdecnotsupported) + * 4.9 [Bit Functions](#bit-functions) + * 4.9.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Bit.Int.Supported](#rqsrs-020clickhouseextendedprecisionbitintsupported) + * 4.9.2 [RQ.SRS-020.ClickHouse.Extended.Precision.Bit.Int.NotSupported](#rqsrs-020clickhouseextendedprecisionbitintnotsupported) + * 4.9.3 [RQ.SRS-020.ClickHouse.Extended.Precision.Bit.Dec.NotSupported](#rqsrs-020clickhouseextendedprecisionbitdecnotsupported) + * 4.10 [Null Functions](#null-functions) + * 4.10.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Null](#rqsrs-020clickhouseextendedprecisionnull) + * 4.11 [Tuple Functions](#tuple-functions) + * 4.11.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Tuple](#rqsrs-020clickhouseextendedprecisiontuple) + * 4.12 [Map Functions](#map-functions) + * 4.12.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Map.Supported](#rqsrs-020clickhouseextendedprecisionmapsupported) + * 4.12.2 [RQ.SRS-020.ClickHouse.Extended.Precision.Map.NotSupported](#rqsrs-020clickhouseextendedprecisionmapnotsupported) + * 4.13 [Create](#create) + * 4.13.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Create.Table](#rqsrs-020clickhouseextendedprecisioncreatetable) +* 5 [References](#references) + +## Revision History + +This document is stored in an electronic form using [Git] source control management software +hosted in a [GitHub Repository]. +All the updates are tracked using the [Revision History]. + +## Introduction + +This software requirements specification covers requirements related to [ClickHouse] +using extended precision data types. + +## Terminology + +### Extended Precision Data Types + +Inclusive bounds: +* Int128 - [-170141183460469231731687303715884105728 : 170141183460469231731687303715884105727] +* UInt128 - [0 : 340282366920938463463374607431768211455] +* Int256 - [-57896044618658097711785492504343953926634992332820282019728792003956564819968 : 57896044618658097711785492504343953926634992332820282019728792003956564819967] +* UInt256 - [0 : 115792089237316195423570985008687907853269984665640564039457584007913129639935] + +Exclusive bounds: +* Decimal256 - (10^(76 - S): 10^(76 - S)), where S is the scale. + +## Requirements + +### RQ.SRS-020.ClickHouse.Extended.Precision +version: 1.0 + +[ClickHouse] SHALL support using [Extended Precision Data Types]. + +### Conversion + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toInt128 +version: 1.0 + +[ClickHouse] SHALL support converting values to `Int128` using the `toInt128` function. + +For example, + +```sql +SELECT toInt128(1) +``` + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toUInt128 +version: 1.0 + +[ClickHouse] SHALL support converting values to `UInt128` format using `toUInt128` function. + +For example, + +```sql +SELECT toUInt128(1) +``` + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toInt256 +version: 1.0 + +[ClickHouse] SHALL support converting values to `Int256` using `toInt256` function. + +For example, + +```sql +SELECT toInt256(1) +``` + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toUInt256 +version: 1.0 + +[ClickHouse] SHALL support converting values to `UInt256` format using `toUInt256` function. + +For example, + +```sql +SELECT toUInt256(1) +``` + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toDecimal256 +version: 1.0 + +[ClickHouse] SHALL support converting values to `Decimal256` format using `toDecimal256` function. + +For example, + +```sql +SELECT toDecimal256(1,2) +``` + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.FromMySQL +version: 1.0 + +[ClickHouse] SHALL support converting to [Extended Precision Data Types] from MySQL. + + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.ToMySQL +version: 1.0 + +[ClickHouse] MAY not support converting from [Extended Precision Data Types] to MySQL. + +### Arithmetic + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Arithmetic.Int.Supported +version: 1.0 + +[ClickHouse] SHALL support using [Arithmetic functions] with Int128, UInt128, Int256, and UInt256. + +Arithmetic functions: +* plus +* minus +* multiply +* divide +* intDiv +* intDivOrZero +* modulo +* moduloOrZero +* negate +* abs +* gcd +* lcm + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Arithmetic.Dec.Supported +version: 1.0 + +[ClickHouse] SHALL support using the following [Arithmetic functions] with Decimal256: + +* plus +* minus +* multiply +* divide +* intDiv +* intDivOrZero +* negate +* abs + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Arithmetic.Dec.NotSupported +version: 1.0 + +[ClickHouse] MAY not support using the following [Arithmetic functions] with Decimal256: + +* modulo +* moduloOrZero +* gcd +* lcm + +### Arrays + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Int.Supported +version: 1.0 + +[ClickHouse] SHALL support using the following [Array functions] with Int128, UInt128, Int256, and UInt256. + +* empty +* notEmpty +* length +* arrayCount +* arrayPopBack +* arrayPopFront +* arraySort +* arrayReverseSort +* arrayUniq +* arrayJoin +* arrayDistinct +* arrayEnumerate +* arrayEnumerateDense +* arrayEnumerateUniq +* arrayReverse +* reverse +* arrayFlatten +* arrayCompact +* arrayExists +* arrayAll +* arrayMin +* arrayMax +* arraySum +* arrayAvg +* arrayReduce +* arrayReduceInRanges +* arrayZip +* arrayMap +* arrayFilter +* arrayFill +* arrayReverseFill +* arraySplit +* arrayFirst +* arrayFirstIndex +* arrayConcat +* hasAll +* hasAny +* hasSubstr +* arrayElement +* has +* indexOf +* countEqual +* arrayPushBack +* arrayPushFront +* arrayResize +* arraySlice + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Int.NotSupported +version: 1.0 + +[ClickHouse] MAY not support using the following [Array functions] with Int128, UInt128, Int256, and UInt256: + +* arrayDifference +* arrayCumSum +* arrayCumSumNonNegative + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Dec.Supported +version: 1.0 + +[ClickHouse] SHALL support using the following [Array functions] with Decimal256: + +* empty +* notEmpty +* length +* arrayCount +* arrayPopBack +* arrayPopFront +* arraySort +* arrayReverseSort +* arrayUniq +* arrayJoin +* arrayDistinct +* arrayEnumerate +* arrayEnumerateDense +* arrayEnumerateUniq +* arrayReverse +* reverse +* arrayFlatten +* arrayCompact +* arrayExists +* arrayAll +* arrayReduce +* arrayReduceInRanges +* arrayZip +* arrayMap +* arrayFilter +* arrayFill +* arrayReverseFill +* arraySplit +* arrayFirst +* arrayFirstIndex +* arrayConcat +* hasAll +* hasAny +* hasSubstr +* arrayElement +* has +* indexOf +* countEqual +* arrayPushBack +* arrayPushFront +* arrayResize +* arraySlice + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Dec.NotSupported +version: 1.0 + +[ClickHouse] MAY not support using the following [Array functions] with Decimal256: + +* arrayMin +* arrayMax +* arraaySum +* arrayAvg +* arrayDifference +* arrayCumSum +* arrayCumSumNonNegative + +### Comparison + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Comparison +version: 1.0 + +[ClickHouse] SHALL support using [Comparison functions] with [Extended Precision Data Types]. + +Comparison functions: +* equals +* notEquals +* less +* greater +* lessOrEquals +* greaterOrEquals + +### Logical Functions + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Logical +version: 1.0 + +[ClickHouse] MAY not support using [Logical functions] with [Extended Precision Data Types]. + +Logical functions: +* and +* or +* not +* xor + +### Mathematical Functions + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Mathematical.Supported +version: 1.0 + +[ClickHouse] SHALL support using the following [Mathematical functions] with [Extended Precision Data Types]: + +* exp +* log, ln +* exp2 +* log2 +* exp10 +* log10 +* sqrt +* cbrt +* erf +* erfc +* lgamma +* tgamma +* sin +* cos +* tan +* asin +* acos +* atan +* cosh +* acosh +* sinh +* asinh +* tanh +* atanh +* log1p +* sign + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Mathematical.NotSupported +version: 1.0 + +[ClickHouse] MAY not support using the following [Mathematical functions] with [Extended Precision Data Types]: + +* pow, power +* intExp2 +* intExp10 +* atan2 +* hypot + +### Rounding Functions + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Int.Supported +version: 1.0 + +[ClickHouse] SHALL support using the following [Rounding functions] with Int128, UInt128, Int256, and UInt256: + +* floor +* ceil +* trunc +* round +* roundBankers +* roundDuration +* roundAge + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Int.NotSupported +version: 1.0 + +[ClickHouse] MAY not support using the following [Rounding functions] with Int128, UInt128, Int256, and UInt256: + +* roundDown +* roundToExp2 + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Dec.Supported +version: 1.0 + +[ClickHouse] SHALL support using the following [Rounding functions] with Decimal256: + +* floor +* ceil +* trunc +* round +* roundBankers + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Dec.NotSupported +version: 1.0 + +[ClickHouse] MAY not support using the following [Rounding functions] with Decimal256: + +* roundDuration +* roundAge +* roundDown +* roundToExp2 + +### Bit Functions + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Bit.Int.Supported +version: 1.0 + +[ClickHouse] SHALL support using the following [Bit functions] with Int128, UInt128, Int256, and UInt256: + +* bitAnd +* bitOr +* bitXor +* bitNot +* bitShiftLeft +* bitShiftRight +* bitCount + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Bit.Int.NotSupported +version: 1.0 + +[ClickHouse] MAY not support using the following [Bit functions] with Int128, UInt128, Int256, and UInt256: + +* bitRotateLeft +* bitRotateRight +* bitTest +* bitTestAll +* bitTestAny + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Bit.Dec.NotSupported +version: 1.0 + +[ClickHouse] MAY not support using [Bit functions] with Decimal256. + +Bit functions: +* bitAnd +* bitOr +* bitXor +* bitNot +* bitShiftLeft +* bitShiftRight +* bitCount +* bitRotateLeft +* bitRotateRight +* bitTest +* bitTestAll +* bitTestAny + +### Null Functions + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Null +version: 1.0 + +[ClickHouse] SHALL support using [Null functions] with [Extended Precision Data Types]. + +Null functions: +* isNull +* isNotNull +* coalesce +* ifNull +* nullIf +* assumeNotNull +* toNullable + +### Tuple Functions + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Tuple +version: 1.0 + +[ClickHouse] SHALL support using [Tuple functions] with [Extended Precision Data Types]. + +Tuple functions: +* tuple +* tupleElement +* untuple + +### Map Functions + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Map.Supported +version: 1.0 + +[ClickHouse] SHALL support using the following [Map functions] with [Extended Precision Data Types]: + +* map +* mapContains +* mapKeys +* mapValues + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Map.NotSupported +version: 1.0 + +[ClickHouse] MAY not support using the following [Map functions] with [Extended Precision Data Types]: + +* mapAdd +* mapSubtract +* mapPopulateSeries + +### Create + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Create.Table +version: 1.0 + +[ClickHouse] SHALL support creating table with columns that use [Extended Precision Data Types]. + +## References + +* **ClickHouse:** https://clickhouse.tech +* **GitHub Repository**: https://github.com/ClickHouse/ClickHouse/blob/master/tests/testflows/extended_precision_data_types/requirements/requirements.md +* **Revision History**: https://github.com/ClickHouse/ClickHouse/blob/master/tests/testflows/extended_precision_data_types/requirements/requirements.md +* **Git:** https://git-scm.com/ + +[Extended Precision Data Types]: #extended-precision-data-types +[Arithmetic functions]: https://clickhouse.tech/docs/en/sql-reference/functions/arithmetic-functions/ +[Array functions]: https://clickhouse.tech/docs/en/sql-reference/functions/array-functions/ +[Comparison functions]: https://clickhouse.tech/docs/en/sql-reference/functions/comparison-functions/ +[Logical Functions]: https://clickhouse.tech/docs/en/sql-reference/functions/logical-functions/ +[Mathematical Functions]: https://clickhouse.tech/docs/en/sql-reference/functions/math-functions/ +[Rounding Functions]: https://clickhouse.tech/docs/en/sql-reference/functions/rounding-functions/ +[Bit Functions]: https://clickhouse.tech/docs/en/sql-reference/functions/bit-functions/ +[Null Functions]: https://clickhouse.tech/docs/en/sql-reference/functions/functions-for-nulls/ +[Tuple Functions]: https://clickhouse.tech/docs/en/sql-reference/functions/tuple-functions/ +[Map Functions]: https://clickhouse.tech/docs/en/sql-reference/functions/tuple-map-functions/ +[SRS]: #srs +[ClickHouse]: https://clickhouse.tech +[GitHub Repository]: https://github.com/ClickHouse/ClickHouse/blob/master/tests/testflows/extended_precision_data_types/requirements/requirements.md +[Revision History]: https://github.com/ClickHouse/ClickHouse/blob/master/tests/testflows/extended_precision_data_types/requirements/requirements.md +[Git]: https://git-scm.com/ +[GitHub]: https://github.com diff --git a/tests/testflows/extended_precision_data_types/requirements/requirements.py b/tests/testflows/extended_precision_data_types/requirements/requirements.py new file mode 100644 index 00000000000..3fcf7798651 --- /dev/null +++ b/tests/testflows/extended_precision_data_types/requirements/requirements.py @@ -0,0 +1,1423 @@ +# These requirements were auto generated +# from software requirements specification (SRS) +# document by TestFlows v1.6.210505.1133630. +# Do not edit by hand but re-generate instead +# using 'tfs requirements generate' command. +from testflows.core import Specification +from testflows.core import Requirement + +Heading = Specification.Heading + +RQ_SRS_020_ClickHouse_Extended_Precision = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using [Extended Precision Data Types].\n' + '\n' + ), + link=None, + level=2, + num='4.1') + +RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_toInt128 = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toInt128', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support converting values to `Int128` using the `toInt128` function.\n' + '\n' + 'For example,\n' + '\n' + '```sql\n' + 'SELECT toInt128(1)\n' + '```\n' + '\n' + ), + link=None, + level=3, + num='4.2.1') + +RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_toUInt128 = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toUInt128', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support converting values to `UInt128` format using `toUInt128` function.\n' + '\n' + 'For example,\n' + '\n' + '```sql\n' + 'SELECT toUInt128(1)\n' + '```\n' + '\n' + ), + link=None, + level=3, + num='4.2.2') + +RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_toInt256 = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toInt256', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support converting values to `Int256` using `toInt256` function.\n' + '\n' + 'For example,\n' + '\n' + '```sql\n' + 'SELECT toInt256(1)\n' + '```\n' + '\n' + ), + link=None, + level=3, + num='4.2.3') + +RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_toUInt256 = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toUInt256', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support converting values to `UInt256` format using `toUInt256` function.\n' + '\n' + 'For example,\n' + '\n' + '```sql\n' + 'SELECT toUInt256(1)\n' + '```\n' + '\n' + ), + link=None, + level=3, + num='4.2.4') + +RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_toDecimal256 = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toDecimal256', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support converting values to `Decimal256` format using `toDecimal256` function.\n' + '\n' + 'For example,\n' + '\n' + '```sql\n' + 'SELECT toDecimal256(1,2)\n' + '```\n' + '\n' + ), + link=None, + level=3, + num='4.2.5') + +RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_FromMySQL = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.FromMySQL', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support converting to [Extended Precision Data Types] from MySQL.\n' + '\n' + '\n' + ), + link=None, + level=3, + num='4.2.6') + +RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_ToMySQL = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.ToMySQL', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] MAY not support converting from [Extended Precision Data Types] to MySQL.\n' + '\n' + ), + link=None, + level=3, + num='4.2.7') + +RQ_SRS_020_ClickHouse_Extended_Precision_Arithmetic_Int_Supported = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Arithmetic.Int.Supported', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using [Arithmetic functions] with Int128, UInt128, Int256, and UInt256.\n' + '\n' + 'Arithmetic functions:\n' + '* plus\n' + '* minus\n' + '* multiply\n' + '* divide\n' + '* intDiv\n' + '* intDivOrZero\n' + '* modulo\n' + '* moduloOrZero\n' + '* negate\n' + '* abs\n' + '* gcd\n' + '* lcm\n' + '\n' + ), + link=None, + level=3, + num='4.3.1') + +RQ_SRS_020_ClickHouse_Extended_Precision_Arithmetic_Dec_Supported = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Arithmetic.Dec.Supported', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using the following [Arithmetic functions] with Decimal256:\n' + '\n' + '* plus\n' + '* minus\n' + '* multiply\n' + '* divide\n' + '* intDiv\n' + '* intDivOrZero\n' + '* negate\n' + '* abs\n' + '\n' + ), + link=None, + level=3, + num='4.3.2') + +RQ_SRS_020_ClickHouse_Extended_Precision_Arithmetic_Dec_NotSupported = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Arithmetic.Dec.NotSupported', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] MAY not support using the following [Arithmetic functions] with Decimal256:\n' + '\n' + '* modulo\n' + '* moduloOrZero\n' + '* gcd\n' + '* lcm\n' + '\n' + ), + link=None, + level=3, + num='4.3.3') + +RQ_SRS_020_ClickHouse_Extended_Precision_Arrays_Int_Supported = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Int.Supported', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using the following [Array functions] with Int128, UInt128, Int256, and UInt256.\n' + '\n' + '* empty\n' + '* notEmpty\n' + '* length\n' + '* arrayCount\n' + '* arrayPopBack\n' + '* arrayPopFront\n' + '* arraySort\n' + '* arrayReverseSort\n' + '* arrayUniq\n' + '* arrayJoin\n' + '* arrayDistinct\n' + '* arrayEnumerate\n' + '* arrayEnumerateDense\n' + '* arrayEnumerateUniq\n' + '* arrayReverse\n' + '* reverse\n' + '* arrayFlatten\n' + '* arrayCompact\n' + '* arrayExists\n' + '* arrayAll\n' + '* arrayMin\n' + '* arrayMax\n' + '* arraySum\n' + '* arrayAvg\n' + '* arrayReduce\n' + '* arrayReduceInRanges\n' + '* arrayZip\n' + '* arrayMap\n' + '* arrayFilter\n' + '* arrayFill\n' + '* arrayReverseFill\n' + '* arraySplit\n' + '* arrayFirst\n' + '* arrayFirstIndex\n' + '* arrayConcat\n' + '* hasAll\n' + '* hasAny\n' + '* hasSubstr\n' + '* arrayElement\n' + '* has\n' + '* indexOf\n' + '* countEqual\n' + '* arrayPushBack\n' + '* arrayPushFront\n' + '* arrayResize\n' + '* arraySlice\n' + '\n' + ), + link=None, + level=3, + num='4.4.1') + +RQ_SRS_020_ClickHouse_Extended_Precision_Arrays_Int_NotSupported = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Int.NotSupported', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] MAY not support using the following [Array functions] with Int128, UInt128, Int256, and UInt256:\n' + '\n' + '* arrayDifference\n' + '* arrayCumSum\n' + '* arrayCumSumNonNegative\n' + '\n' + ), + link=None, + level=3, + num='4.4.2') + +RQ_SRS_020_ClickHouse_Extended_Precision_Arrays_Dec_Supported = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Dec.Supported', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using the following [Array functions] with Decimal256:\n' + '\n' + '* empty\n' + '* notEmpty\n' + '* length\n' + '* arrayCount\n' + '* arrayPopBack\n' + '* arrayPopFront\n' + '* arraySort\n' + '* arrayReverseSort\n' + '* arrayUniq\n' + '* arrayJoin\n' + '* arrayDistinct\n' + '* arrayEnumerate\n' + '* arrayEnumerateDense\n' + '* arrayEnumerateUniq\n' + '* arrayReverse\n' + '* reverse\n' + '* arrayFlatten\n' + '* arrayCompact\n' + '* arrayExists\n' + '* arrayAll\n' + '* arrayReduce\n' + '* arrayReduceInRanges\n' + '* arrayZip\n' + '* arrayMap\n' + '* arrayFilter\n' + '* arrayFill\n' + '* arrayReverseFill\n' + '* arraySplit\n' + '* arrayFirst\n' + '* arrayFirstIndex\n' + '* arrayConcat\n' + '* hasAll\n' + '* hasAny\n' + '* hasSubstr\n' + '* arrayElement\n' + '* has\n' + '* indexOf\n' + '* countEqual\n' + '* arrayPushBack\n' + '* arrayPushFront\n' + '* arrayResize\n' + '* arraySlice\n' + '\n' + ), + link=None, + level=3, + num='4.4.3') + +RQ_SRS_020_ClickHouse_Extended_Precision_Arrays_Dec_NotSupported = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Dec.NotSupported', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] MAY not support using the following [Array functions] with Decimal256:\n' + '\n' + '* arrayMin\n' + '* arrayMax\n' + '* arraaySum\n' + '* arrayAvg\n' + '* arrayDifference\n' + '* arrayCumSum\n' + '* arrayCumSumNonNegative\n' + '\n' + ), + link=None, + level=3, + num='4.4.4') + +RQ_SRS_020_ClickHouse_Extended_Precision_Comparison = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Comparison', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using [Comparison functions] with [Extended Precision Data Types].\n' + '\n' + 'Comparison functions:\n' + '* equals\n' + '* notEquals\n' + '* less\n' + '* greater\n' + '* lessOrEquals\n' + '* greaterOrEquals\n' + '\n' + ), + link=None, + level=3, + num='4.5.1') + +RQ_SRS_020_ClickHouse_Extended_Precision_Logical = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Logical', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] MAY not support using [Logical functions] with [Extended Precision Data Types].\n' + '\n' + 'Logical functions:\n' + '* and\n' + '* or\n' + '* not\n' + '* xor\n' + '\n' + ), + link=None, + level=3, + num='4.6.1') + +RQ_SRS_020_ClickHouse_Extended_Precision_Mathematical_Supported = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Mathematical.Supported', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using the following [Mathematical functions] with [Extended Precision Data Types]:\n' + '\n' + '* exp\n' + '* log, ln\n' + '* exp2\n' + '* log2\n' + '* exp10\n' + '* log10\n' + '* sqrt\n' + '* cbrt\n' + '* erf\n' + '* erfc\n' + '* lgamma\n' + '* tgamma\n' + '* sin\n' + '* cos\n' + '* tan\n' + '* asin\n' + '* acos\n' + '* atan\n' + '* cosh\n' + '* acosh\n' + '* sinh\n' + '* asinh\n' + '* tanh\n' + '* atanh\n' + '* log1p\n' + '* sign\n' + '\n' + ), + link=None, + level=3, + num='4.7.1') + +RQ_SRS_020_ClickHouse_Extended_Precision_Mathematical_NotSupported = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Mathematical.NotSupported', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] MAY not support using the following [Mathematical functions] with [Extended Precision Data Types]:\n' + '\n' + '* pow, power\n' + '* intExp2\n' + '* intExp10\n' + '* atan2\n' + '* hypot\n' + '\n' + ), + link=None, + level=3, + num='4.7.2') + +RQ_SRS_020_ClickHouse_Extended_Precision_Rounding_Int_Supported = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Int.Supported', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using the following [Rounding functions] with Int128, UInt128, Int256, and UInt256:\n' + '\n' + '* floor\n' + '* ceil\n' + '* trunc\n' + '* round\n' + '* roundBankers\n' + '* roundDuration\n' + '* roundAge\n' + '\n' + ), + link=None, + level=3, + num='4.8.1') + +RQ_SRS_020_ClickHouse_Extended_Precision_Rounding_Int_NotSupported = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Int.NotSupported', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] MAY not support using the following [Rounding functions] with Int128, UInt128, Int256, and UInt256:\n' + '\n' + '* roundDown\n' + '* roundToExp2\n' + '\n' + ), + link=None, + level=3, + num='4.8.2') + +RQ_SRS_020_ClickHouse_Extended_Precision_Rounding_Dec_Supported = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Dec.Supported', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using the following [Rounding functions] with Decimal256:\n' + '\n' + '* floor\n' + '* ceil\n' + '* trunc\n' + '* round\n' + '* roundBankers\n' + '\n' + ), + link=None, + level=3, + num='4.8.3') + +RQ_SRS_020_ClickHouse_Extended_Precision_Rounding_Dec_NotSupported = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Dec.NotSupported', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] MAY not support using the following [Rounding functions] with Decimal256:\n' + '\n' + '* roundDuration\n' + '* roundAge\n' + '* roundDown\n' + '* roundToExp2\n' + '\n' + ), + link=None, + level=3, + num='4.8.4') + +RQ_SRS_020_ClickHouse_Extended_Precision_Bit_Int_Supported = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Bit.Int.Supported', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using the following [Bit functions] with Int128, UInt128, Int256, and UInt256:\n' + '\n' + '* bitAnd\n' + '* bitOr\n' + '* bitXor\n' + '* bitNot\n' + '* bitShiftLeft\n' + '* bitShiftRight\n' + '* bitCount\n' + '\n' + ), + link=None, + level=3, + num='4.9.1') + +RQ_SRS_020_ClickHouse_Extended_Precision_Bit_Int_NotSupported = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Bit.Int.NotSupported', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] MAY not support using the following [Bit functions] with Int128, UInt128, Int256, and UInt256:\n' + '\n' + '* bitRotateLeft\n' + '* bitRotateRight\n' + '* bitTest\n' + '* bitTestAll\n' + '* bitTestAny\n' + '\n' + ), + link=None, + level=3, + num='4.9.2') + +RQ_SRS_020_ClickHouse_Extended_Precision_Bit_Dec_NotSupported = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Bit.Dec.NotSupported', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] MAY not support using [Bit functions] with Decimal256.\n' + '\n' + 'Bit functions:\n' + '* bitAnd\n' + '* bitOr\n' + '* bitXor\n' + '* bitNot\n' + '* bitShiftLeft\n' + '* bitShiftRight\n' + '* bitCount\n' + '* bitRotateLeft\n' + '* bitRotateRight\n' + '* bitTest\n' + '* bitTestAll\n' + '* bitTestAny\n' + '\n' + ), + link=None, + level=3, + num='4.9.3') + +RQ_SRS_020_ClickHouse_Extended_Precision_Null = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Null', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using [Null functions] with [Extended Precision Data Types].\n' + '\n' + 'Null functions:\n' + '* isNull\n' + '* isNotNull\n' + '* coalesce\n' + '* ifNull\n' + '* nullIf\n' + '* assumeNotNull\n' + '* toNullable\n' + '\n' + ), + link=None, + level=3, + num='4.10.1') + +RQ_SRS_020_ClickHouse_Extended_Precision_Tuple = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Tuple', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using [Tuple functions] with [Extended Precision Data Types].\n' + '\n' + 'Tuple functions:\n' + '* tuple\n' + '* tupleElement\n' + '* untuple\n' + '\n' + ), + link=None, + level=3, + num='4.11.1') + +RQ_SRS_020_ClickHouse_Extended_Precision_Map_Supported = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Map.Supported', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support using the following [Map functions] with [Extended Precision Data Types]:\n' + '\n' + '* map\n' + '* mapContains\n' + '* mapKeys\n' + '* mapValues\n' + '\n' + ), + link=None, + level=3, + num='4.12.1') + +RQ_SRS_020_ClickHouse_Extended_Precision_Map_NotSupported = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Map.NotSupported', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] MAY not support using the following [Map functions] with [Extended Precision Data Types]:\n' + '\n' + '* mapAdd\n' + '* mapSubtract\n' + '* mapPopulateSeries\n' + '\n' + ), + link=None, + level=3, + num='4.12.2') + +RQ_SRS_020_ClickHouse_Extended_Precision_Create_Table = Requirement( + name='RQ.SRS-020.ClickHouse.Extended.Precision.Create.Table', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support creating table with columns that use [Extended Precision Data Types].\n' + '\n' + ), + link=None, + level=3, + num='4.13.1') + +QA_SRS020_ClickHouse_Extended_Precision_Data_Types = Specification( + name='QA-SRS020 ClickHouse Extended Precision Data Types', + description=None, + author=None, + date=None, + status=None, + approved_by=None, + approved_date=None, + approved_version=None, + version=None, + group=None, + type=None, + link=None, + uid=None, + parent=None, + children=None, + headings=( + Heading(name='Revision History', level=1, num='1'), + Heading(name='Introduction', level=1, num='2'), + Heading(name='Terminology', level=1, num='3'), + Heading(name='Extended Precision Data Types', level=2, num='3.1'), + Heading(name='Requirements', level=1, num='4'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision', level=2, num='4.1'), + Heading(name='Conversion', level=2, num='4.2'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toInt128', level=3, num='4.2.1'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toUInt128', level=3, num='4.2.2'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toInt256', level=3, num='4.2.3'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toUInt256', level=3, num='4.2.4'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toDecimal256', level=3, num='4.2.5'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.FromMySQL', level=3, num='4.2.6'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.ToMySQL', level=3, num='4.2.7'), + Heading(name='Arithmetic', level=2, num='4.3'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Arithmetic.Int.Supported', level=3, num='4.3.1'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Arithmetic.Dec.Supported', level=3, num='4.3.2'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Arithmetic.Dec.NotSupported', level=3, num='4.3.3'), + Heading(name='Arrays', level=2, num='4.4'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Int.Supported', level=3, num='4.4.1'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Int.NotSupported', level=3, num='4.4.2'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Dec.Supported', level=3, num='4.4.3'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Dec.NotSupported', level=3, num='4.4.4'), + Heading(name='Comparison', level=2, num='4.5'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Comparison', level=3, num='4.5.1'), + Heading(name='Logical Functions', level=2, num='4.6'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Logical', level=3, num='4.6.1'), + Heading(name='Mathematical Functions', level=2, num='4.7'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Mathematical.Supported', level=3, num='4.7.1'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Mathematical.NotSupported', level=3, num='4.7.2'), + Heading(name='Rounding Functions', level=2, num='4.8'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Int.Supported', level=3, num='4.8.1'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Int.NotSupported', level=3, num='4.8.2'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Dec.Supported', level=3, num='4.8.3'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Dec.NotSupported', level=3, num='4.8.4'), + Heading(name='Bit Functions', level=2, num='4.9'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Bit.Int.Supported', level=3, num='4.9.1'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Bit.Int.NotSupported', level=3, num='4.9.2'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Bit.Dec.NotSupported', level=3, num='4.9.3'), + Heading(name='Null Functions', level=2, num='4.10'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Null', level=3, num='4.10.1'), + Heading(name='Tuple Functions', level=2, num='4.11'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Tuple', level=3, num='4.11.1'), + Heading(name='Map Functions', level=2, num='4.12'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Map.Supported', level=3, num='4.12.1'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Map.NotSupported', level=3, num='4.12.2'), + Heading(name='Create', level=2, num='4.13'), + Heading(name='RQ.SRS-020.ClickHouse.Extended.Precision.Create.Table', level=3, num='4.13.1'), + Heading(name='References', level=1, num='5'), + ), + requirements=( + RQ_SRS_020_ClickHouse_Extended_Precision, + RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_toInt128, + RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_toUInt128, + RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_toInt256, + RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_toUInt256, + RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_toDecimal256, + RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_FromMySQL, + RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_ToMySQL, + RQ_SRS_020_ClickHouse_Extended_Precision_Arithmetic_Int_Supported, + RQ_SRS_020_ClickHouse_Extended_Precision_Arithmetic_Dec_Supported, + RQ_SRS_020_ClickHouse_Extended_Precision_Arithmetic_Dec_NotSupported, + RQ_SRS_020_ClickHouse_Extended_Precision_Arrays_Int_Supported, + RQ_SRS_020_ClickHouse_Extended_Precision_Arrays_Int_NotSupported, + RQ_SRS_020_ClickHouse_Extended_Precision_Arrays_Dec_Supported, + RQ_SRS_020_ClickHouse_Extended_Precision_Arrays_Dec_NotSupported, + RQ_SRS_020_ClickHouse_Extended_Precision_Comparison, + RQ_SRS_020_ClickHouse_Extended_Precision_Logical, + RQ_SRS_020_ClickHouse_Extended_Precision_Mathematical_Supported, + RQ_SRS_020_ClickHouse_Extended_Precision_Mathematical_NotSupported, + RQ_SRS_020_ClickHouse_Extended_Precision_Rounding_Int_Supported, + RQ_SRS_020_ClickHouse_Extended_Precision_Rounding_Int_NotSupported, + RQ_SRS_020_ClickHouse_Extended_Precision_Rounding_Dec_Supported, + RQ_SRS_020_ClickHouse_Extended_Precision_Rounding_Dec_NotSupported, + RQ_SRS_020_ClickHouse_Extended_Precision_Bit_Int_Supported, + RQ_SRS_020_ClickHouse_Extended_Precision_Bit_Int_NotSupported, + RQ_SRS_020_ClickHouse_Extended_Precision_Bit_Dec_NotSupported, + RQ_SRS_020_ClickHouse_Extended_Precision_Null, + RQ_SRS_020_ClickHouse_Extended_Precision_Tuple, + RQ_SRS_020_ClickHouse_Extended_Precision_Map_Supported, + RQ_SRS_020_ClickHouse_Extended_Precision_Map_NotSupported, + RQ_SRS_020_ClickHouse_Extended_Precision_Create_Table, + ), + content=''' +# QA-SRS020 ClickHouse Extended Precision Data Types +# Software Requirements Specification + +## Table of Contents + +* 1 [Revision History](#revision-history) +* 2 [Introduction](#introduction) +* 3 [Terminology](#terminology) + * 3.1 [Extended Precision Data Types](#extended-precision-data-types) +* 4 [Requirements](#requirements) + * 4.1 [RQ.SRS-020.ClickHouse.Extended.Precision](#rqsrs-020clickhouseextendedprecision) + * 4.2 [Conversion](#conversion) + * 4.2.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toInt128](#rqsrs-020clickhouseextendedprecisionconversiontoint128) + * 4.2.2 [RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toUInt128](#rqsrs-020clickhouseextendedprecisionconversiontouint128) + * 4.2.3 [RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toInt256](#rqsrs-020clickhouseextendedprecisionconversiontoint256) + * 4.2.4 [RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toUInt256](#rqsrs-020clickhouseextendedprecisionconversiontouint256) + * 4.2.5 [RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toDecimal256](#rqsrs-020clickhouseextendedprecisionconversiontodecimal256) + * 4.2.6 [RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.FromMySQL](#rqsrs-020clickhouseextendedprecisionconversionfrommysql) + * 4.2.7 [RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.ToMySQL](#rqsrs-020clickhouseextendedprecisionconversiontomysql) + * 4.3 [Arithmetic](#arithmetic) + * 4.3.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Arithmetic.Int.Supported](#rqsrs-020clickhouseextendedprecisionarithmeticintsupported) + * 4.3.2 [RQ.SRS-020.ClickHouse.Extended.Precision.Arithmetic.Dec.Supported](#rqsrs-020clickhouseextendedprecisionarithmeticdecsupported) + * 4.3.3 [RQ.SRS-020.ClickHouse.Extended.Precision.Arithmetic.Dec.NotSupported](#rqsrs-020clickhouseextendedprecisionarithmeticdecnotsupported) + * 4.4 [Arrays](#arrays) + * 4.4.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Int.Supported](#rqsrs-020clickhouseextendedprecisionarraysintsupported) + * 4.4.2 [RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Int.NotSupported](#rqsrs-020clickhouseextendedprecisionarraysintnotsupported) + * 4.4.3 [RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Dec.Supported](#rqsrs-020clickhouseextendedprecisionarraysdecsupported) + * 4.4.4 [RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Dec.NotSupported](#rqsrs-020clickhouseextendedprecisionarraysdecnotsupported) + * 4.5 [Comparison](#comparison) + * 4.5.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Comparison](#rqsrs-020clickhouseextendedprecisioncomparison) + * 4.6 [Logical Functions](#logical-functions) + * 4.6.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Logical](#rqsrs-020clickhouseextendedprecisionlogical) + * 4.7 [Mathematical Functions](#mathematical-functions) + * 4.7.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Mathematical.Supported](#rqsrs-020clickhouseextendedprecisionmathematicalsupported) + * 4.7.2 [RQ.SRS-020.ClickHouse.Extended.Precision.Mathematical.NotSupported](#rqsrs-020clickhouseextendedprecisionmathematicalnotsupported) + * 4.8 [Rounding Functions](#rounding-functions) + * 4.8.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Int.Supported](#rqsrs-020clickhouseextendedprecisionroundingintsupported) + * 4.8.2 [RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Int.NotSupported](#rqsrs-020clickhouseextendedprecisionroundingintnotsupported) + * 4.8.3 [RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Dec.Supported](#rqsrs-020clickhouseextendedprecisionroundingdecsupported) + * 4.8.4 [RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Dec.NotSupported](#rqsrs-020clickhouseextendedprecisionroundingdecnotsupported) + * 4.9 [Bit Functions](#bit-functions) + * 4.9.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Bit.Int.Supported](#rqsrs-020clickhouseextendedprecisionbitintsupported) + * 4.9.2 [RQ.SRS-020.ClickHouse.Extended.Precision.Bit.Int.NotSupported](#rqsrs-020clickhouseextendedprecisionbitintnotsupported) + * 4.9.3 [RQ.SRS-020.ClickHouse.Extended.Precision.Bit.Dec.NotSupported](#rqsrs-020clickhouseextendedprecisionbitdecnotsupported) + * 4.10 [Null Functions](#null-functions) + * 4.10.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Null](#rqsrs-020clickhouseextendedprecisionnull) + * 4.11 [Tuple Functions](#tuple-functions) + * 4.11.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Tuple](#rqsrs-020clickhouseextendedprecisiontuple) + * 4.12 [Map Functions](#map-functions) + * 4.12.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Map.Supported](#rqsrs-020clickhouseextendedprecisionmapsupported) + * 4.12.2 [RQ.SRS-020.ClickHouse.Extended.Precision.Map.NotSupported](#rqsrs-020clickhouseextendedprecisionmapnotsupported) + * 4.13 [Create](#create) + * 4.13.1 [RQ.SRS-020.ClickHouse.Extended.Precision.Create.Table](#rqsrs-020clickhouseextendedprecisioncreatetable) +* 5 [References](#references) + +## Revision History + +This document is stored in an electronic form using [Git] source control management software +hosted in a [GitHub Repository]. +All the updates are tracked using the [Revision History]. + +## Introduction + +This software requirements specification covers requirements related to [ClickHouse] +using extended precision data types. + +## Terminology + +### Extended Precision Data Types + +Inclusive bounds: +* Int128 - [-170141183460469231731687303715884105728 : 170141183460469231731687303715884105727] +* UInt128 - [0 : 340282366920938463463374607431768211455] +* Int256 - [-57896044618658097711785492504343953926634992332820282019728792003956564819968 : 57896044618658097711785492504343953926634992332820282019728792003956564819967] +* UInt256 - [0 : 115792089237316195423570985008687907853269984665640564039457584007913129639935] + +Exclusive bounds: +* Decimal256 - (10^(76 - S): 10^(76 - S)), where S is the scale. + +## Requirements + +### RQ.SRS-020.ClickHouse.Extended.Precision +version: 1.0 + +[ClickHouse] SHALL support using [Extended Precision Data Types]. + +### Conversion + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toInt128 +version: 1.0 + +[ClickHouse] SHALL support converting values to `Int128` using the `toInt128` function. + +For example, + +```sql +SELECT toInt128(1) +``` + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toUInt128 +version: 1.0 + +[ClickHouse] SHALL support converting values to `UInt128` format using `toUInt128` function. + +For example, + +```sql +SELECT toUInt128(1) +``` + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toInt256 +version: 1.0 + +[ClickHouse] SHALL support converting values to `Int256` using `toInt256` function. + +For example, + +```sql +SELECT toInt256(1) +``` + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toUInt256 +version: 1.0 + +[ClickHouse] SHALL support converting values to `UInt256` format using `toUInt256` function. + +For example, + +```sql +SELECT toUInt256(1) +``` + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.toDecimal256 +version: 1.0 + +[ClickHouse] SHALL support converting values to `Decimal256` format using `toDecimal256` function. + +For example, + +```sql +SELECT toDecimal256(1,2) +``` + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.FromMySQL +version: 1.0 + +[ClickHouse] SHALL support converting to [Extended Precision Data Types] from MySQL. + + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Conversion.ToMySQL +version: 1.0 + +[ClickHouse] MAY not support converting from [Extended Precision Data Types] to MySQL. + +### Arithmetic + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Arithmetic.Int.Supported +version: 1.0 + +[ClickHouse] SHALL support using [Arithmetic functions] with Int128, UInt128, Int256, and UInt256. + +Arithmetic functions: +* plus +* minus +* multiply +* divide +* intDiv +* intDivOrZero +* modulo +* moduloOrZero +* negate +* abs +* gcd +* lcm + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Arithmetic.Dec.Supported +version: 1.0 + +[ClickHouse] SHALL support using the following [Arithmetic functions] with Decimal256: + +* plus +* minus +* multiply +* divide +* intDiv +* intDivOrZero +* negate +* abs + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Arithmetic.Dec.NotSupported +version: 1.0 + +[ClickHouse] MAY not support using the following [Arithmetic functions] with Decimal256: + +* modulo +* moduloOrZero +* gcd +* lcm + +### Arrays + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Int.Supported +version: 1.0 + +[ClickHouse] SHALL support using the following [Array functions] with Int128, UInt128, Int256, and UInt256. + +* empty +* notEmpty +* length +* arrayCount +* arrayPopBack +* arrayPopFront +* arraySort +* arrayReverseSort +* arrayUniq +* arrayJoin +* arrayDistinct +* arrayEnumerate +* arrayEnumerateDense +* arrayEnumerateUniq +* arrayReverse +* reverse +* arrayFlatten +* arrayCompact +* arrayExists +* arrayAll +* arrayMin +* arrayMax +* arraySum +* arrayAvg +* arrayReduce +* arrayReduceInRanges +* arrayZip +* arrayMap +* arrayFilter +* arrayFill +* arrayReverseFill +* arraySplit +* arrayFirst +* arrayFirstIndex +* arrayConcat +* hasAll +* hasAny +* hasSubstr +* arrayElement +* has +* indexOf +* countEqual +* arrayPushBack +* arrayPushFront +* arrayResize +* arraySlice + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Int.NotSupported +version: 1.0 + +[ClickHouse] MAY not support using the following [Array functions] with Int128, UInt128, Int256, and UInt256: + +* arrayDifference +* arrayCumSum +* arrayCumSumNonNegative + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Dec.Supported +version: 1.0 + +[ClickHouse] SHALL support using the following [Array functions] with Decimal256: + +* empty +* notEmpty +* length +* arrayCount +* arrayPopBack +* arrayPopFront +* arraySort +* arrayReverseSort +* arrayUniq +* arrayJoin +* arrayDistinct +* arrayEnumerate +* arrayEnumerateDense +* arrayEnumerateUniq +* arrayReverse +* reverse +* arrayFlatten +* arrayCompact +* arrayExists +* arrayAll +* arrayReduce +* arrayReduceInRanges +* arrayZip +* arrayMap +* arrayFilter +* arrayFill +* arrayReverseFill +* arraySplit +* arrayFirst +* arrayFirstIndex +* arrayConcat +* hasAll +* hasAny +* hasSubstr +* arrayElement +* has +* indexOf +* countEqual +* arrayPushBack +* arrayPushFront +* arrayResize +* arraySlice + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Arrays.Dec.NotSupported +version: 1.0 + +[ClickHouse] MAY not support using the following [Array functions] with Decimal256: + +* arrayMin +* arrayMax +* arraaySum +* arrayAvg +* arrayDifference +* arrayCumSum +* arrayCumSumNonNegative + +### Comparison + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Comparison +version: 1.0 + +[ClickHouse] SHALL support using [Comparison functions] with [Extended Precision Data Types]. + +Comparison functions: +* equals +* notEquals +* less +* greater +* lessOrEquals +* greaterOrEquals + +### Logical Functions + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Logical +version: 1.0 + +[ClickHouse] MAY not support using [Logical functions] with [Extended Precision Data Types]. + +Logical functions: +* and +* or +* not +* xor + +### Mathematical Functions + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Mathematical.Supported +version: 1.0 + +[ClickHouse] SHALL support using the following [Mathematical functions] with [Extended Precision Data Types]: + +* exp +* log, ln +* exp2 +* log2 +* exp10 +* log10 +* sqrt +* cbrt +* erf +* erfc +* lgamma +* tgamma +* sin +* cos +* tan +* asin +* acos +* atan +* cosh +* acosh +* sinh +* asinh +* tanh +* atanh +* log1p +* sign + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Mathematical.NotSupported +version: 1.0 + +[ClickHouse] MAY not support using the following [Mathematical functions] with [Extended Precision Data Types]: + +* pow, power +* intExp2 +* intExp10 +* atan2 +* hypot + +### Rounding Functions + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Int.Supported +version: 1.0 + +[ClickHouse] SHALL support using the following [Rounding functions] with Int128, UInt128, Int256, and UInt256: + +* floor +* ceil +* trunc +* round +* roundBankers +* roundDuration +* roundAge + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Int.NotSupported +version: 1.0 + +[ClickHouse] MAY not support using the following [Rounding functions] with Int128, UInt128, Int256, and UInt256: + +* roundDown +* roundToExp2 + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Dec.Supported +version: 1.0 + +[ClickHouse] SHALL support using the following [Rounding functions] with Decimal256: + +* floor +* ceil +* trunc +* round +* roundBankers + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Rounding.Dec.NotSupported +version: 1.0 + +[ClickHouse] MAY not support using the following [Rounding functions] with Decimal256: + +* roundDuration +* roundAge +* roundDown +* roundToExp2 + +### Bit Functions + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Bit.Int.Supported +version: 1.0 + +[ClickHouse] SHALL support using the following [Bit functions] with Int128, UInt128, Int256, and UInt256: + +* bitAnd +* bitOr +* bitXor +* bitNot +* bitShiftLeft +* bitShiftRight +* bitCount + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Bit.Int.NotSupported +version: 1.0 + +[ClickHouse] MAY not support using the following [Bit functions] with Int128, UInt128, Int256, and UInt256: + +* bitRotateLeft +* bitRotateRight +* bitTest +* bitTestAll +* bitTestAny + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Bit.Dec.NotSupported +version: 1.0 + +[ClickHouse] MAY not support using [Bit functions] with Decimal256. + +Bit functions: +* bitAnd +* bitOr +* bitXor +* bitNot +* bitShiftLeft +* bitShiftRight +* bitCount +* bitRotateLeft +* bitRotateRight +* bitTest +* bitTestAll +* bitTestAny + +### Null Functions + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Null +version: 1.0 + +[ClickHouse] SHALL support using [Null functions] with [Extended Precision Data Types]. + +Null functions: +* isNull +* isNotNull +* coalesce +* ifNull +* nullIf +* assumeNotNull +* toNullable + +### Tuple Functions + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Tuple +version: 1.0 + +[ClickHouse] SHALL support using [Tuple functions] with [Extended Precision Data Types]. + +Tuple functions: +* tuple +* tupleElement +* untuple + +### Map Functions + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Map.Supported +version: 1.0 + +[ClickHouse] SHALL support using the following [Map functions] with [Extended Precision Data Types]: + +* map +* mapContains +* mapKeys +* mapValues + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Map.NotSupported +version: 1.0 + +[ClickHouse] MAY not support using the following [Map functions] with [Extended Precision Data Types]: + +* mapAdd +* mapSubtract +* mapPopulateSeries + +### Create + +#### RQ.SRS-020.ClickHouse.Extended.Precision.Create.Table +version: 1.0 + +[ClickHouse] SHALL support creating table with columns that use [Extended Precision Data Types]. + +## References + +* **ClickHouse:** https://clickhouse.tech +* **GitHub Repository**: https://github.com/ClickHouse/ClickHouse/blob/master/tests/testflows/extended_precision_data_types/requirements/requirements.md +* **Revision History**: https://github.com/ClickHouse/ClickHouse/blob/master/tests/testflows/extended_precision_data_types/requirements/requirements.md +* **Git:** https://git-scm.com/ + +[Extended Precision Data Types]: #extended-precision-data-types +[Arithmetic functions]: https://clickhouse.tech/docs/en/sql-reference/functions/arithmetic-functions/ +[Array functions]: https://clickhouse.tech/docs/en/sql-reference/functions/array-functions/ +[Comparison functions]: https://clickhouse.tech/docs/en/sql-reference/functions/comparison-functions/ +[Logical Functions]: https://clickhouse.tech/docs/en/sql-reference/functions/logical-functions/ +[Mathematical Functions]: https://clickhouse.tech/docs/en/sql-reference/functions/math-functions/ +[Rounding Functions]: https://clickhouse.tech/docs/en/sql-reference/functions/rounding-functions/ +[Bit Functions]: https://clickhouse.tech/docs/en/sql-reference/functions/bit-functions/ +[Null Functions]: https://clickhouse.tech/docs/en/sql-reference/functions/functions-for-nulls/ +[Tuple Functions]: https://clickhouse.tech/docs/en/sql-reference/functions/tuple-functions/ +[Map Functions]: https://clickhouse.tech/docs/en/sql-reference/functions/tuple-map-functions/ +[SRS]: #srs +[ClickHouse]: https://clickhouse.tech +[GitHub Repository]: https://github.com/ClickHouse/ClickHouse/blob/master/tests/testflows/extended_precision_data_types/requirements/requirements.md +[Revision History]: https://github.com/ClickHouse/ClickHouse/blob/master/tests/testflows/extended_precision_data_types/requirements/requirements.md +[Git]: https://git-scm.com/ +[GitHub]: https://github.com +''') diff --git a/tests/testflows/extended_precision_data_types/tests/__init__.py b/tests/testflows/extended_precision_data_types/tests/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/testflows/extended_precision_data_types/tests/arithmetic.py b/tests/testflows/extended_precision_data_types/tests/arithmetic.py new file mode 100644 index 00000000000..d939569d5a7 --- /dev/null +++ b/tests/testflows/extended_precision_data_types/tests/arithmetic.py @@ -0,0 +1,217 @@ +import os +import textwrap + +from extended_precision_data_types.requirements import * +from extended_precision_data_types.common import * + +funcs = [ + ('plus', '2'), + ('minus', '0'), + ('multiply', '1'), + ('divide', '1'), + ('intDiv', '1'), + ('intDivOrZero', '1'), + ('modulo', '0'), + ('moduloOrZero', '0'), + ('negate', '-1'), + ('abs', '1'), + ('gcd', '1'), + ('lcm', '1'), +] + +Examples_list = [tuple(list(func)+list(data_type)+[Name(f'{func[0]} - {data_type[0]}')]) for func in funcs for data_type in data_types] +Examples_dec_list = [tuple(list(func)+[Name(f'{func[0]} - Decimal256')]) for func in funcs] + +@TestOutline +@Examples('arithmetic_func expected_result int_type min max', Examples_list) +def inline_check(self, arithmetic_func, expected_result, int_type, min, max, node=None): + """Check that arithmetic functions work using inline tests with Int128, UInt128, Int256, and UInt256. + """ + + if node is None: + node = self.context.node + + if arithmetic_func in ['negate','abs']: + + with When(f"I check {arithmetic_func} with {int_type}"): + output = node.query(f"SELECT {arithmetic_func}(to{int_type}(1))").output + assert output == expected_result, error() + + with When(f"I check {arithmetic_func} with {int_type} max and min value"): + execute_query(f""" + SELECT {arithmetic_func}(to{int_type}(\'{max}\')), {arithmetic_func}(to{int_type}(\'{min}\')) + """) + + else: + + with When(f"I check {arithmetic_func} with {int_type}"): + output = node.query(f"SELECT {arithmetic_func}(to{int_type}(1), to{int_type}(1))").output + assert output == expected_result, error() + + if arithmetic_func in ['gcd','lcm']: + + if int_type in ['UInt128','UInt256']: + exitcode=153 + else: + exitcode=151 + + with When(f"I check {arithmetic_func} with {int_type} max and min value"): + node.query(f"SELECT {arithmetic_func}(to{int_type}(\'{max}\'), to{int_type}(1)), {arithmetic_func}(to{int_type}(\'{min}\'), to{int_type}(1))", + exitcode = exitcode, message = 'Exception:') + + else: + + with When(f"I check {arithmetic_func} with {int_type} max and min value"): + execute_query(f""" + SELECT {arithmetic_func}(to{int_type}(\'{max}\'), to{int_type}(1)), {arithmetic_func}(to{int_type}(\'{min}\'), to{int_type}(1)) + """) + +@TestOutline +@Examples('arithmetic_func expected_result int_type min max', Examples_list) +def table_check(self, arithmetic_func, expected_result, int_type, min, max, node=None): + """Check that arithmetic functions work using tables with Int128, UInt128, Int256, and UInt256. + """ + + if node is None: + node = self.context.node + + table_name = f'table_{getuid()}' + + with Given(f"I have a table"): + table(name = table_name, data_type = int_type) + + if arithmetic_func in ['negate','abs']: + + for value in [1, min, max]: + + with When(f"I insert {arithmetic_func} with {int_type} {value} into the table"): + node.query(f"INSERT INTO {table_name} SELECT {arithmetic_func}(to{int_type}(\'{value}\'))") + + with Then(f"I check the table output of {arithmetic_func} with {int_type}"): + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + else: + + with When(f"I insert {arithmetic_func} with {int_type} into the table"): + node.query(f"INSERT INTO {table_name} SELECT {arithmetic_func}(to{int_type}(1), to{int_type}(1))") + + with Then("I check that the output matches the expected value"): + output = node.query(f"SELECT * FROM {table_name}").output + assert output == expected_result, error() + + if arithmetic_func in ['gcd', 'lcm']: + + if int_type in ['UInt128', 'UInt256']: + + with When(f"I insert {arithmetic_func} with {int_type} {min} into the table"): + node.query(f"INSERT INTO {table_name} SELECT {arithmetic_func}(to{int_type}(\'{min}\'), to{int_type}(1))", + exitcode = 153, message = 'Exception:') + + with And(f"I insert {arithmetic_func} with {int_type} {max} into the table"): + node.query(f"INSERT INTO {table_name} SELECT {arithmetic_func}(to{int_type}(\'{max}\'), to{int_type}(1))") + + else: + + for value in [min, max]: + + with When(f"I insert {arithmetic_func} with {int_type} {value} into the table"): + node.query(f"INSERT INTO {table_name} SELECT {arithmetic_func}(to{int_type}(\'{value}\'), to{int_type}(1))", + exitcode = 151, message = 'Exception:') + + else: + + for value in [min, max]: + + with When(f"I insert {arithmetic_func} with {int_type} {value} into the table"): + node.query(f"INSERT INTO {table_name} SELECT {arithmetic_func}(to{int_type}(\'{value}\'), to{int_type}(1))") + + with Then(f"I check the table output of {arithmetic_func} with {int_type}"): + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + +@TestOutline +@Examples('arithmetic_func expected_result', Examples_dec_list) +def inline_check_dec(self, arithmetic_func, expected_result, node=None): + """Check that arithmetic functions work using inline with Decimal256. + """ + + if node is None: + node = self.context.node + + if arithmetic_func is 'negate' or arithmetic_func is 'abs': + + with When(f"I check {arithmetic_func} with toDecimal256"): + output = node.query(f"SELECT {arithmetic_func}(toDecimal256(1,0))").output + assert output == expected_result, error() + + elif arithmetic_func in ['modulo', 'moduloOrZero', 'gcd', 'lcm']: + + with When(f"I check {arithmetic_func} with toDecimal256"): + node.query(f"SELECT {arithmetic_func}(toDecimal256(1,0), toDecimal256(1,0))", + exitcode=43, message = 'Exception:') + + else: + + with When(f"I check {arithmetic_func} with toDecimal256"): + output = node.query(f"SELECT {arithmetic_func}(toDecimal256(1,0), toDecimal256(1,0))").output + assert output == expected_result, error() + +@TestOutline +@Examples('arithmetic_func expected_result', Examples_dec_list) +def table_check_dec(self, arithmetic_func, expected_result, node=None): + """Check that arithmetic functions work using tables with Decimal256. + """ + + if node is None: + node = self.context.node + + table_name = f'table_{getuid()}' + + with Given(f"I have a table"): + table(name = table_name, data_type = 'Decimal256(0)') + + if arithmetic_func in ['negate','abs']: + + with When(f"I insert {arithmetic_func} with toDecimal256 into the table"): + node.query(f"INSERT INTO {table_name} SELECT {arithmetic_func}(toDecimal256(1,0))") + + with Then(f"I check the table for output of {arithmetic_func} with Decimal256"): + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + elif arithmetic_func in ['modulo', 'moduloOrZero', 'gcd', 'lcm']: + + with When(f"I check {arithmetic_func} with toDecimal256"): + node.query(f"INSERT INTO {table_name} SELECT {arithmetic_func}(toDecimal256(1,0), toDecimal256(1,0))", + exitcode=43, message = 'Exception:') + + else: + with When(f"I insert {arithmetic_func} with toDecimal256 into the table"): + node.query(f"INSERT INTO {table_name} SELECT {arithmetic_func}(toDecimal256(1,0), toDecimal256(1,0))") + + with Then("I check that the output matches the expected value"): + output = node.query(f"SELECT * FROM {table_name}").output + assert output == expected_result, error() + +@TestFeature +@Name("arithmetic") +@Requirements( + RQ_SRS_020_ClickHouse_Extended_Precision_Arithmetic_Int_Supported("1.0"), + RQ_SRS_020_ClickHouse_Extended_Precision_Arithmetic_Dec_Supported("1.0"), + RQ_SRS_020_ClickHouse_Extended_Precision_Arithmetic_Dec_NotSupported("1.0"), +) +def feature(self, node="clickhouse1", mysql_node="mysql1", stress=None, parallel=None): + """Check that arithmetic functions work with extended precision data types. + """ + self.context.node = self.context.cluster.node(node) + self.context.mysql_node = self.context.cluster.node(mysql_node) + + with allow_experimental_bigint(self.context.node): + Scenario(run = inline_check) + Scenario(run = table_check) + Scenario(run = inline_check_dec) + Scenario(run = table_check_dec) diff --git a/tests/testflows/extended_precision_data_types/tests/array_tuple_map.py b/tests/testflows/extended_precision_data_types/tests/array_tuple_map.py new file mode 100644 index 00000000000..6efa122ffdf --- /dev/null +++ b/tests/testflows/extended_precision_data_types/tests/array_tuple_map.py @@ -0,0 +1,484 @@ +import uuid + +from extended_precision_data_types.requirements import * +from extended_precision_data_types.common import * + +def get_table_name(): + return "table" + "_" + str(uuid.uuid1()).replace('-', '_') + +@TestOutline(Suite) +@Requirements( + RQ_SRS_020_ClickHouse_Extended_Precision_Arrays_Int_Supported("1.0"), + RQ_SRS_020_ClickHouse_Extended_Precision_Arrays_Int_NotSupported("1.0"), + RQ_SRS_020_ClickHouse_Extended_Precision_Arrays_Dec_Supported("1.0"), + RQ_SRS_020_ClickHouse_Extended_Precision_Arrays_Dec_NotSupported("1.0"), +) +def array_func(self, data_type, node=None): + """Check array functions with extended precision data types. + """ + + if node is None: + node = self.context.node + + for func in ['arrayPopBack(', + 'arrayPopFront(', + 'arraySort(', + 'arrayReverseSort(', + 'arrayDistinct(', + 'arrayEnumerate(', + 'arrayEnumerateDense(', + 'arrayEnumerateUniq(', + 'arrayReverse(', + 'reverse(', + 'arrayFlatten(', + 'arrayCompact(', + 'arrayReduceInRanges(\'sum\', [(1, 5)],', + 'arrayMap(x -> (x + 2),', + 'arrayFill(x -> x=3,', + 'arrayReverseFill(x -> x=3,', + f'arrayConcat([{to_data_type(data_type,3)}, {to_data_type(data_type,2)}, {to_data_type(data_type,1)}],', + 'arrayFilter(x -> x == 1, ']: + + with Scenario(f"Inline - {data_type} - {func}"): + execute_query(f""" + SELECT {func}array({to_data_type(data_type,3)}, {to_data_type(data_type,2)}, {to_data_type(data_type,1)})) + """) + + with Scenario(f"Table - {data_type} - {func}"): + table_name = get_table_name() + + table(name = table_name, data_type = f'Array({data_type})') + + with When("I insert the output into the table"): + node.query(f"INSERT INTO {table_name} SELECT {func}array({to_data_type(data_type,3)}, {to_data_type(data_type,2)}, {to_data_type(data_type,1)}))") + + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + for func in ['arraySplit((x, y) -> x=y, [0, 0, 0],']: + + with Scenario(f"Inline - {data_type} - {func}"): + execute_query(f""" + SELECT {func}array({to_data_type(data_type,3)}, {to_data_type(data_type,2)}, {to_data_type(data_type,1)})) + """) + + with Scenario(f"Table - {data_type} - {func}"): + table_name = get_table_name() + + table(name = table_name, data_type = f'Array(Array({data_type}))') + + with When("I insert the output into the table"): + node.query(f"INSERT INTO {table_name} SELECT {func}array({to_data_type(data_type,3)}, {to_data_type(data_type,2)}, {to_data_type(data_type,1)}))") + + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + for func in [f'arrayZip([{to_data_type(data_type,1)}],']: + + with Scenario(f"Inline - {data_type} - {func}"): + execute_query(f""" + SELECT {func}array({to_data_type(data_type,3)})) + """) + + with Scenario(f"Table - {data_type} - {func}"): + table_name = get_table_name() + + table(name = table_name, data_type = f'Array(Tuple({data_type}, {data_type}))') + + with When("I insert the output into the table"): + node.query(f"INSERT INTO {table_name} SELECT {func}array({to_data_type(data_type,1)}))") + + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + for func in ['empty(', + 'notEmpty(', + 'length(', + 'arrayCount(x -> x == 1, ', + 'arrayUniq(', + 'arrayJoin(', + 'arrayExists(x -> x==1,', + 'arrayAll(x -> x==1,', + 'arrayMin(', + 'arrayMax(', + 'arraySum(', + 'arrayAvg(', + 'arrayReduce(\'max\', ', + 'arrayFirst(x -> x==3,', + 'arrayFirstIndex(x -> x==3,', + f'hasAll([{to_data_type(data_type,3)}, {to_data_type(data_type,2)}, {to_data_type(data_type,1)}], ', + f'hasAny([{to_data_type(data_type,2)}, {to_data_type(data_type,1)}], ', + f'hasSubstr([{to_data_type(data_type,2)}, {to_data_type(data_type,1)}], ']: + + if func in ['arrayMin(','arrayMax(','arraySum(', 'arrayAvg('] and data_type in ['Decimal256(0)']: + + with Scenario(f"Inline - {data_type} - {func}"): + node.query(f"SELECT {func}array({to_data_type(data_type,3)}, {to_data_type(data_type,2)}, {to_data_type(data_type,1)}))", + exitcode = 44, message = 'Exception:') + + with Scenario(f"Table - {data_type} - {func}"): + table_name = get_table_name() + + table(name = table_name, data_type = data_type) + + with When("I insert the output into the table"): + node.query(f"INSERT INTO {table_name} SELECT {func}array({to_data_type(data_type,3)}, {to_data_type(data_type,2)}, {to_data_type(data_type,1)}))", + exitcode = 44, message = 'Exception:') + + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + else: + + with Scenario(f"Inline - {data_type} - {func}"): + + execute_query(f""" + SELECT {func}array({to_data_type(data_type,3)}, {to_data_type(data_type,2)}, {to_data_type(data_type,1)})) + """) + + with Scenario(f"Table - {data_type} - {func}"): + table_name = get_table_name() + + table(name = table_name, data_type = data_type) + + with When("I insert the output into the table"): + node.query(f"INSERT INTO {table_name} SELECT {func}array({to_data_type(data_type,3)}, {to_data_type(data_type,2)}, {to_data_type(data_type,1)}))") + + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + for func in ['arrayDifference(', + 'arrayCumSum(', + 'arrayCumSumNonNegative(']: + + if data_type in ['Decimal256(0)']: + exitcode = 44 + else: + exitcode = 43 + + with Scenario(f"Inline - {data_type} - {func}"): + node.query(f"SELECT {func}array({to_data_type(data_type,3)}, {to_data_type(data_type,2)}, {to_data_type(data_type,1)}))", + exitcode = exitcode, message = 'Exception:') + + with Scenario(f"Table - {data_type} - {func}"): + table_name = get_table_name() + + table(name = table_name, data_type = data_type) + + with When("I insert the output into the table"): + node.query(f"INSERT INTO {table_name} SELECT {func}array({to_data_type(data_type,3)}, {to_data_type(data_type,2)}, {to_data_type(data_type,1)}))", + exitcode = exitcode, message = 'Exception:') + + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + for func in ['arrayElement']: + + with Scenario(f"Inline - {data_type} - {func}"): + + execute_query(f""" + SELECT {func}(array({to_data_type(data_type,3)}, {to_data_type(data_type,2)}, {to_data_type(data_type,1)}), 1) + """) + + with Scenario(f"Table - {data_type} - {func}"): + table_name = get_table_name() + + table(name = table_name, data_type = data_type) + + with When("I insert the output into the table"): + node.query(f"INSERT INTO {table_name} SELECT {func}(array({to_data_type(data_type,3)}, {to_data_type(data_type,2)}, {to_data_type(data_type,1)}), 1)") + + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + for func in ['arrayPushBack', + 'arrayPushFront']: + + with Scenario(f"Inline - {data_type} - {func}"): + + execute_query(f""" + SELECT {func}(array({to_data_type(data_type,3)}, {to_data_type(data_type,2)}, {to_data_type(data_type,1)}), {to_data_type(data_type,1)}) + """) + + with Scenario(f"Table - {data_type} - {func}"): + table_name = get_table_name() + + table(name = table_name, data_type = f'Array({data_type})') + + with When("I insert the output into the table"): + node.query(f"INSERT INTO {table_name} SELECT {func}(array({to_data_type(data_type,3)}, {to_data_type(data_type,2)}, {to_data_type(data_type,1)}), {to_data_type(data_type,1)})") + + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + for func in ['arrayResize', + 'arraySlice']: + + with Scenario(f"Inline - {data_type} - {func}"): + + execute_query(f""" + SELECT {func}(array({to_data_type(data_type,3)}, {to_data_type(data_type,2)}, {to_data_type(data_type,1)}), 1) + """) + + with Scenario(f"Table - {data_type} - {func}"): + table_name = get_table_name() + + table(name = table_name, data_type = f'Array({data_type})') + + with When("I insert the output into the table"): + node.query(f"INSERT INTO {table_name} SELECT {func}(array({to_data_type(data_type,3)}, {to_data_type(data_type,2)}, {to_data_type(data_type,1)}), 1)") + + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + for func in ['has', + 'indexOf', + 'countEqual']: + + with Scenario(f"Inline - {data_type} - {func}"): + execute_query(f""" + SELECT {func}(array({to_data_type(data_type,3)}, {to_data_type(data_type,2)}, {to_data_type(data_type,1)}), NULL) + """) + + with Scenario(f"Table - {data_type} - {func}"): + table_name = get_table_name() + + table(name = table_name, data_type = data_type) + + with When("I insert the output into the table"): + node.query(f"INSERT INTO {table_name} SELECT {func}(array({to_data_type(data_type,3)}, {to_data_type(data_type,2)}, {to_data_type(data_type,1)}), NULL)") + + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + +@TestOutline(Suite) +@Requirements( + RQ_SRS_020_ClickHouse_Extended_Precision_Tuple("1.0"), +) +def tuple_func(self, data_type, node=None): + """Check tuple functions with extended precision data types. + """ + + if node is None: + node = self.context.node + + with Scenario(f"Creating a tuple with {data_type}"): + node.query(f"SELECT tuple({to_data_type(data_type,1)}, {to_data_type(data_type,1)}, {to_data_type(data_type,1)})") + + with Scenario(f"Creating a tuple with {data_type} on a table"): + table_name = get_table_name() + + table(name = table_name, data_type = f'Tuple({data_type}, {data_type}, {data_type})') + + with When("I insert the output into a table"): + node.query(f"INSERT INTO {table_name} SELECT tuple({to_data_type(data_type,1)}, {to_data_type(data_type,1)}, {to_data_type(data_type,1)})") + + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + with Scenario(f"tupleElement with {data_type}"): + node.query(f"SELECT tupleElement(({to_data_type(data_type,1)}, {to_data_type(data_type,1)}), 1)") + + with Scenario(f"tupleElement with {data_type} on a table"): + table_name = get_table_name() + + table(name = table_name, data_type = data_type) + + with When("I insert the output into a table"): + node.query(f"INSERT INTO {table_name} SELECT tupleElement(({to_data_type(data_type,1)}, {to_data_type(data_type,1)}), 1)") + + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + with Scenario(f"untuple with {data_type}"): + node.query(f"SELECT untuple(({to_data_type(data_type,1)},))") + + with Scenario(f"untuple with {data_type} on a table"): + table_name = get_table_name() + + table(name = table_name, data_type = data_type) + + with When("I insert the output into a table"): + node.query(f"INSERT INTO {table_name} SELECT untuple(({to_data_type(data_type,1)},))") + + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + with Scenario(f"tupleHammingDistance with {data_type}"): + node.query(f"SELECT tupleHammingDistance(({to_data_type(data_type,1)}, {to_data_type(data_type,1)}), ({to_data_type(data_type,2)}, {to_data_type(data_type,2)}))") + + with Scenario(f"tupleHammingDistance with {data_type} on a table"): + table_name = get_table_name() + + table(name = table_name, data_type = data_type) + + with When("I insert the output into a table"): + node.query(f"INSERT INTO {table_name} SELECT tupleHammingDistance(({to_data_type(data_type,1)}, {to_data_type(data_type,1)}), ({to_data_type(data_type,2)}, {to_data_type(data_type,2)}))") + + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + +@TestOutline(Suite) +@Requirements( + RQ_SRS_020_ClickHouse_Extended_Precision_Map_Supported("1.0"), + RQ_SRS_020_ClickHouse_Extended_Precision_Map_NotSupported("1.0"), +) +def map_func(self, data_type, node=None): + """Check Map functions with extended precision data types. + """ + + if node is None: + node = self.context.node + + with Scenario(f"Creating a map with {data_type}"): + node.query(f"SELECT map('key1', {to_data_type(data_type,1)}, 'key2', {to_data_type(data_type,2)})") + + with Scenario(f"Creating a map with {data_type} on a table"): + table_name = get_table_name() + + table(name = table_name, data_type = f'Map(String, {data_type})') + + with When("I insert the output into a table"): + node.query(f"INSERT INTO {table_name} SELECT map('key1', {to_data_type(data_type,1)}, 'key2', {to_data_type(data_type,2)})") + + execute_query(f""" + SELECT * FROM {table_name} + """) + + with Scenario(f"mapAdd with {data_type}"): + node.query(f"SELECT mapAdd(([{to_data_type(data_type,1)}, {to_data_type(data_type,2)}], [{to_data_type(data_type,1)}, {to_data_type(data_type,2)}]), ([{to_data_type(data_type,1)}, {to_data_type(data_type,2)}], [{to_data_type(data_type,1)}, {to_data_type(data_type,2)}]))", + exitcode = 44, message='Exception:') + + with Scenario(f"mapAdd with {data_type} on a table"): + table_name = get_table_name() + + table(name = table_name, data_type = f'Tuple(Array({data_type}), Array({data_type}))') + + with When("I insert the output into a table"): + node.query(f"INSERT INTO {table_name} SELECT mapAdd(([{to_data_type(data_type,1)}, {to_data_type(data_type,2)}], [{to_data_type(data_type,1)}, {to_data_type(data_type,2)}]), ([{to_data_type(data_type,1)}, {to_data_type(data_type,2)}], [{to_data_type(data_type,1)}, {to_data_type(data_type,2)}]))", + exitcode = 44, message='Exception:') + + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + with Scenario(f"mapSubtract with {data_type}"): + node.query(f"SELECT mapSubtract(([{to_data_type(data_type,1)}, {to_data_type(data_type,2)}], [{to_data_type(data_type,1)}, {to_data_type(data_type,2)}]), ([{to_data_type(data_type,1)}, {to_data_type(data_type,2)}], [{to_data_type(data_type,1)}, {to_data_type(data_type,2)}]))", + exitcode = 44, message='Exception:') + + with Scenario(f"mapSubtract with {data_type} on a table"): + table_name = get_table_name() + + table(name = table_name, data_type = f'Tuple(Array({data_type}), Array({data_type}))') + + with When("I insert the output into a table"): + node.query(f"INSERT INTO {table_name} SELECT mapSubtract(([{to_data_type(data_type,1)}, {to_data_type(data_type,2)}], [{to_data_type(data_type,1)}, {to_data_type(data_type,2)}]), ([{to_data_type(data_type,1)}, {to_data_type(data_type,2)}], [{to_data_type(data_type,1)}, {to_data_type(data_type,2)}]))", + exitcode = 44, message='Exception:') + + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + with Scenario(f"mapPopulateSeries with {data_type}"): + node.query(f"SELECT mapPopulateSeries([1,2,3], [{to_data_type(data_type,1)}, {to_data_type(data_type,2)}, {to_data_type(data_type,3)}], 5)", + exitcode = 44, message='Exception:') + + with Scenario(f"mapPopulateSeries with {data_type} on a table"): + table_name = get_table_name() + + table(name = table_name, data_type = f'Tuple(Array({data_type}), Array({data_type}))') + + with When("I insert the output into a table"): + node.query(f"INSERT INTO {table_name} SELECT mapPopulateSeries([1,2,3], [{to_data_type(data_type,1)}, {to_data_type(data_type,2)}, {to_data_type(data_type,3)}], 5)", + exitcode = 44, message='Exception:') + + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + with Scenario(f"mapContains with {data_type}"): + node.query(f"SELECT mapContains( map('key1', {to_data_type(data_type,1)}, 'key2', {to_data_type(data_type,2)}), 'key1')") + + with Scenario(f"mapContains with {data_type} on a table"): + table_name = get_table_name() + + table(name = table_name, data_type = data_type) + + with When("I insert the output into a table"): + node.query(f"INSERT INTO {table_name} SELECT mapContains( map('key1', {to_data_type(data_type,1)}, 'key2', {to_data_type(data_type,2)}), 'key1')") + + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + with Scenario(f"mapKeys with {data_type}"): + node.query(f"SELECT mapKeys( map('key1', {to_data_type(data_type,1)}, 'key2', {to_data_type(data_type,2)}))") + + with Scenario(f"mapKeys with {data_type} on a table"): + table_name = get_table_name() + + table(name = table_name, data_type = 'Array(String)') + + with When("I insert the output into a table"): + node.query(f"INSERT INTO {table_name} SELECT mapKeys( map('key1', {to_data_type(data_type,1)}, 'key2', {to_data_type(data_type,2)}))") + + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + with Scenario(f"mapValues with {data_type}"): + node.query(f"SELECT mapValues( map('key1', {to_data_type(data_type,1)}, 'key2', {to_data_type(data_type,2)}))") + + with Scenario(f"mapValues with {data_type} on a table"): + table_name = get_table_name() + + table(name = table_name, data_type = f'Array({data_type})') + + with When("I insert the output into a table"): + node.query(f"INSERT INTO {table_name} SELECT mapValues( map('key1', {to_data_type(data_type,1)}, 'key2', {to_data_type(data_type,2)}))") + + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + +@TestFeature +@Name("array, tuple, map") +@Examples("data_type",[ + ('Int128',), + ('Int256',), + ('UInt128',), + ('UInt256',), + ('Decimal256(0)',), +]) +def feature(self, node="clickhouse1", stress=None, parallel=None): + """Check that array, tuple, and map functions work with extended precision data types. + """ + self.context.node = self.context.cluster.node(node) + + with allow_experimental_bigint(self.context.node): + for example in self.examples: + data_type, = example + + with Feature(data_type): + + Suite(test=array_func)(data_type=data_type) + Suite(test=tuple_func)(data_type=data_type) + + with Given("I allow experimental map type"): + allow_experimental_map_type() + + Suite(test=map_func)(data_type=data_type) diff --git a/tests/testflows/extended_precision_data_types/tests/bit.py b/tests/testflows/extended_precision_data_types/tests/bit.py new file mode 100644 index 00000000000..24f63532c74 --- /dev/null +++ b/tests/testflows/extended_precision_data_types/tests/bit.py @@ -0,0 +1,179 @@ +from extended_precision_data_types.requirements import * +from extended_precision_data_types.common import * +from extended_precision_data_types.errors import * + +funcs = [ + ('bitAnd', True, None), + ('bitOr', True, None), + ('bitXor', True, None), + ('bitShiftLeft', True, None), + ('bitShiftRight', True, None), + ('bitRotateLeft', False, not_implemented_bigints('Bit rotate')), + ('bitRotateRight', False, not_implemented_bigints('Bit rotate')), + ('bitTest', False, not_implemented_bigints('bitTest')), + ('bitTestAll', False, illegal_column()), + ('bitTestAny', False, illegal_column()), + ('bitNot', True, None), + ('bitCount', True, None) +] + +Examples_list = [tuple(list(func)+list(data_type)+[Name(f'{func[0]} - {data_type[0]}')]) for func in funcs for data_type in data_types] +Examples_dec_list = [tuple(list(func)+[Name(f'{func[0]} - Decimal256')]) for func in funcs] + +@TestOutline(Scenario) +@Examples('func supported error int_type min max', Examples_list) +def bit_int_inline(self, func, supported, error, int_type, min, max, node=None): + """ Check bit functions with Int128, UInt128, Int256, and UInt256 using inline tests. + """ + + if error is not None: + exitcode,message = error + + if node is None: + node = self.context.node + + if func in ["bitNot", "bitCount"]: + + with When(f"Check {func} with {int_type}"): + execute_query(f""" + SELECT {func}(to{int_type}(1)), {func}(to{int_type}(\'{max}\')), {func}(to{int_type}(\'{min}\')) + """) + + elif supported: + + with When(f"I check {func} with {int_type}"): + execute_query(f""" + SELECT {func}(to{int_type}(1), 1), {func}(to{int_type}(\'{max}\'), 1), {func}(to{int_type}(\'{min}\'), 1) + """) + + else: + + with When(f"I check {func} with {int_type}"): + node.query(f"SELECT {func}(to{int_type}(1), 1), {func}(to{int_type}(\'{max}\'), 1), {func}(to{int_type}(\'{min}\'), 1)", + exitcode=exitcode, message = message) + +@TestOutline(Scenario) +@Examples('func supported error int_type min max', Examples_list) +def bit_int_table(self, func, supported, error, int_type, min, max, node=None): + """ Check bit functions with Int128, UInt128, Int256, and UInt256 using table tests. + """ + + table_name = f"table_{getuid()}" + + if node is None: + node = self.context.node + + if error is not None: + exitcode,message = error + + with Given(f"I have a table"): + table(name = table_name, data_type = int_type) + + if func in ["bitNot", "bitCount"]: + + for value in [1, min, max]: + + with When(f"I insert the output of {func} with {int_type} and {value}"): + node.query(f"INSERT INTO {table_name} SELECT {func}(to{int_type}(\'{value}\'))") + + with Then(f"I check the table with values of {func} and {int_type}"): + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + elif supported: + + for value in [1, min, max]: + + with When(f"I insert the output of {func} with {int_type} and {value}"): + node.query(f"INSERT INTO {table_name} SELECT {func}(to{int_type}(\'{value}\'), 1)") + + with Then(f"I check the table with values of {func} and {int_type}"): + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + else: + + for value in [1, min, max]: + + with When(f"I insert the output of {func} with {int_type} and {value}"): + node.query(f"INSERT INTO {table_name} SELECT {func}(to{int_type}(\'{value}\'), 1)", + exitcode=exitcode, message=message) + +@TestOutline(Scenario) +@Examples('func supported error', Examples_dec_list) +def bit_dec_inline(self, func, supported, error, node=None): + """ Check bit functions with Decimal256 using inline tests. + """ + min = Decimal256_min_max[0] + max = Decimal256_min_max[1] + + exitcode, message = illegal_type() + + if node is None: + node = self.context.node + + if func in ["bitNot", "bitCount"]: + + with When(f"Check {func} with Decimal256"): + node.query(f"SELECT {func}(toDecimal256(1,0)), {func}(toDecimal256(\'{max}\',0)), {func}(toDecimal256(\'{min}\',0))", + exitcode=exitcode, message = message) + + else: + + with When(f"I check {func} with Decimal256"): + node.query(f"SELECT {func}(toDecimal256(1,0), 1), {func}(toDecimal256(\'{max}\',0), 1), {func}(toDecimal256(\'{min}\',0), 1)", + exitcode=exitcode, message = message) + +@TestOutline(Scenario) +@Examples('func supported error', Examples_dec_list) +def bit_dec_table(self, func, supported, error, node=None): + """ Check bit functions with Decimal256 using table tests. + """ + min = Decimal256_min_max[0] + max = Decimal256_min_max[1] + + table_name = f"table_{getuid()}" + exitcode, message = illegal_type() + + if node is None: + node = self.context.node + + with Given(f"I have a table"): + table(name = table_name, data_type = 'Decimal256(0)') + + if func in ["bitNot", "bitCount"]: + + for value in [1, min, max]: + + with When(f"I insert the output of {func} with Decimal256 and {value}"): + node.query(f"INSERT INTO {table_name} SELECT {func}(toDecimal256(\'{value}\',0))", + exitcode=exitcode, message = message) + + else: + + for value in [1, min, max]: + + with When(f"I insert the output of {func} with Decimal256 and {value}"): + node.query(f"INSERT INTO {table_name} SELECT {func}(toDecimal256(\'{value}\',0), 1)", + exitcode=exitcode, message=message) + +@TestFeature +@Name("bit") +@Requirements( + RQ_SRS_020_ClickHouse_Extended_Precision_Bit_Int_Supported("1.0"), + RQ_SRS_020_ClickHouse_Extended_Precision_Bit_Int_NotSupported("1.0"), + RQ_SRS_020_ClickHouse_Extended_Precision_Bit_Dec_NotSupported("1.0"), +) +def feature(self, node="clickhouse1", mysql_node="mysql1", stress=None, parallel=None): + """Check that bit functions work with extended precision data types. + """ + self.context.node = self.context.cluster.node(node) + self.context.mysql_node = self.context.cluster.node(mysql_node) + + with allow_experimental_bigint(self.context.node): + Scenario(run=bit_int_inline) + Scenario(run=bit_int_table) + Scenario(run=bit_dec_inline) + Scenario(run=bit_dec_table) diff --git a/tests/testflows/extended_precision_data_types/tests/comparison.py b/tests/testflows/extended_precision_data_types/tests/comparison.py new file mode 100644 index 00000000000..d3e5dcc0dbd --- /dev/null +++ b/tests/testflows/extended_precision_data_types/tests/comparison.py @@ -0,0 +1,110 @@ +from extended_precision_data_types.requirements import * +from extended_precision_data_types.common import * + +funcs = [ + ('equals',), + ('notEquals',), + ('less',), + ('greater',), + ('lessOrEquals',), + ('greaterOrEquals',) +] + +Examples_list = [tuple(list(func)+list(data_type)+[Name(f'{func[0]} - {data_type[0]}')]) for func in funcs for data_type in data_types] + +@TestOutline(Scenario) +@Examples('func int_type min max', Examples_list) +def comp_int_inline(self, func, int_type, min, max, node=None): + """Check comparison functions with Int128, UInt128, Int256, and UInt256 using inline tests. + """ + + if node is None: + node = self.context.node + + with When(f"I check {func} with {int_type}"): + execute_query(f""" + SELECT {func}(to{int_type}(1), to{int_type}(1)), {func}(to{int_type}(\'{max}\'), to{int_type}(\'{min}\')) + """) + +@TestOutline(Scenario) +@Examples('func int_type min max', Examples_list) +def comp_int_table(self, func, int_type, min, max, node=None): + """Check comparison functions with Int128, UInt128, Int256, and UInt256 using table tests. + """ + + if node is None: + node = self.context.node + + table_name = f'table_{getuid()}' + + with Given(f"I have a table"): + table(name = table_name, data_type = int_type) + + for value in [1, max, min]: + + with When(f"I insert into a table the output {func} with {int_type} and {value}"): + node.query(f"INSERT INTO {table_name} SELECT {func}(to{int_type}(\'{value}\'), to{int_type}(1))") + + with Then(f"I check the table for the output of {func} with {int_type}"): + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + +@TestOutline(Scenario) +@Examples('func', funcs) +def comp_dec_inline(self, func, node=None): + """Check comparison functions with Decimal256 using inline tests. + """ + min = Decimal256_min_max[0] + max = Decimal256_min_max[1] + + if node is None: + node = self.context.node + + with When(f"I check {func} with Decimal256"): + execute_query(f""" + SELECT {func}(toDecimal256(1,0), toDecimal256(1,0)), {func}(toDecimal256(\'{max}\',0), toDecimal256(\'{min}\',0)) + """) + +@TestOutline(Scenario) +@Examples('func', funcs) +def comp_dec_table(self, func, node=None): + """Check comparison functions with Decimal256 using table tests. + """ + min = Decimal256_min_max[0] + max = Decimal256_min_max[1] + + if node is None: + node = self.context.node + + table_name = f'table_{getuid()}' + + with Given(f"I have a table"): + table(name = table_name, data_type = 'Decimal256(0)') + + for value in [1, max, min]: + + with When(f"I insert into a table the output {func} with Decimal256 and {value}"): + node.query(f"INSERT INTO {table_name} SELECT {func}(toDecimal256(\'{value}\',0), toDecimal256(1,0))") + + with Then(f"I check the table for the output of {func} with Decimal256"): + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + +@TestFeature +@Name("comparison") +@Requirements( + RQ_SRS_020_ClickHouse_Extended_Precision_Comparison("1.0"), +) +def feature(self, node="clickhouse1", mysql_node="mysql1", stress=None, parallel=None): + """Check that comparison functions work with extended precision data types. + """ + self.context.node = self.context.cluster.node(node) + self.context.mysql_node = self.context.cluster.node(mysql_node) + + with allow_experimental_bigint(self.context.node): + Scenario(run=comp_int_inline) + Scenario(run=comp_int_table) + Scenario(run=comp_dec_inline) + Scenario(run=comp_dec_table) diff --git a/tests/testflows/extended_precision_data_types/tests/conversion.py b/tests/testflows/extended_precision_data_types/tests/conversion.py new file mode 100644 index 00000000000..e46031ad29f --- /dev/null +++ b/tests/testflows/extended_precision_data_types/tests/conversion.py @@ -0,0 +1,275 @@ +import os +import textwrap + +from extended_precision_data_types.requirements import * +from extended_precision_data_types.common import * + +@contextmanager +def dictionary(name, node, mysql_node): + """Create a table in MySQL and use it a source for a dictionary. + """ + try: + with Given("table in MySQL"): + sql = f""" + CREATE TABLE {name}( + id INT NOT NULL AUTO_INCREMENT, + int128 BIGINT, + uint128 BIGINT, + int256 BIGINT, + uint256 BIGINT, + dec256 DECIMAL, + PRIMARY KEY ( id ) + ); + """ + with When("I drop the table if exists"): + mysql_node.command(f"MYSQL_PWD=password mysql -D db -u user -e \"DROP TABLE IF EXISTS {name};\"", exitcode=0) + with And("I create a table"): + mysql_node.command(f"MYSQL_PWD=password mysql -D db -u user <<'EOF'{textwrap.dedent(sql)}\nEOF", exitcode=0) + + with And("dictionary that uses MySQL table as the external source"): + with When("I drop the dictionary if exists"): + node.query(f"DROP DICTIONARY IF EXISTS dict_{name}") + with And("I create the dictionary"): + sql = f""" + CREATE DICTIONARY dict_{name} + ( + id UInt8, + int128 Int128, + uint128 UInt128, + int256 Int256, + uint256 UInt256, + dec256 Decimal256(0) + ) + PRIMARY KEY id + SOURCE(MYSQL( + USER 'user' + PASSWORD 'password' + DB 'db' + TABLE '{name}' + REPLICA(PRIORITY 1 HOST '{mysql_node.name}' PORT 3306) + )) + LAYOUT(HASHED()) + LIFETIME(0) + """ + node.query(textwrap.dedent(sql)) + + yield f"dict_{name}" + + finally: + with Finally("I drop the dictionary", flags=TE): + node.query(f"DROP DICTIONARY IF EXISTS dict_{name}") + + with And("I drop a table in MySQL", flags=TE): + mysql_node.command(f"MYSQL_PWD=password mysql -D db -u user -e \"DROP TABLE IF EXISTS {name};\"", exitcode=0) + +@contextmanager +def table(name, node, mysql_node): + """Create a table in MySQL and use it a source for a table in ClickHouse. + """ + try: + with Given("table in MySQL"): + sql = f""" + CREATE TABLE {name}( + id INT NOT NULL AUTO_INCREMENT, + int128 BIGINT, + uint128 BIGINT, + int256 BIGINT, + uint256 BIGINT, + dec256 DECIMAL, + PRIMARY KEY ( id ) + ); + """ + with When("I drop the table if exists"): + mysql_node.command(f"MYSQL_PWD=password mysql -D db -u user -e \"DROP TABLE IF EXISTS {name};\"", exitcode=0) + + with And("I create a table"): + mysql_node.command(f"MYSQL_PWD=password mysql -D db -u user <<'EOF'{textwrap.dedent(sql)}\nEOF", exitcode=0) + + with And("table that uses MySQL table as the external source"): + + with When("I drop the table if exists"): + node.query(f"DROP TABLE IF EXISTS {name}") + with And("I create the table"): + sql = f""" + CREATE TABLE {name} + ( + id UInt8, + int128 Int128, + uint128 UInt128, + int256 Int256, + uint256 UInt256, + dec256 Decimal256(0) + ) + ENGINE = MySQL('{mysql_node.name}:3306', 'default', '{name}', 'default', 'password') + """ + node.query(textwrap.dedent(sql)) + + yield f"table_{name}" + + finally: + with Finally("I drop the table", flags=TE): + node.query(f"DROP TABLE IF EXISTS {name}") + + with And("I drop a table in MySQL", flags=TE): + mysql_node.command(f"MYSQL_PWD=password mysql -D db -u user -e \"DROP TABLE IF EXISTS {name};\"", exitcode=0) + +@contextmanager +def table_func(name, node, mysql_node): + """Create a table in MySQL and use it a source for a table using mysql table function. + """ + try: + with Given("table in MySQL"): + sql = f""" + CREATE TABLE {name}( + id INT NOT NULL AUTO_INCREMENT, + int128 BIGINT, + uint128 BIGINT, + int256 BIGINT, + uint256 BIGINT, + dec256 DECIMAL, + PRIMARY KEY ( id ) + ); + """ + with When("I drop the table if exists"): + mysql_node.command(f"MYSQL_PWD=password mysql -D db -u user -e \"DROP TABLE IF EXISTS {name};\"", exitcode=0) + with And("I create a table"): + mysql_node.command(f"MYSQL_PWD=password mysql -D db -u user <<'EOF'{textwrap.dedent(sql)}\nEOF", exitcode=0) + + yield f"mysql('{mysql_node.name}:3306', 'db', '{name}', 'user', 'password')" + + finally: + + with Finally("I drop the table", flags=TE): + node.query(f"DROP TABLE IF EXISTS {name}") + + with And("I drop a table in MySQL", flags=TE): + mysql_node.command(f"MYSQL_PWD=password mysql -D db -u user -e \"DROP TABLE IF EXISTS {name};\"", exitcode=0) + +@TestOutline(Scenario) +@Examples('int_type min max',[ + ('Int128', '-170141183460469231731687303715884105728', '170141183460469231731687303715884105727', Requirements(RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_toInt128("1.0")), Name('Int128')), + ('Int256', '-57896044618658097711785492504343953926634992332820282019728792003956564819968', '57896044618658097711785492504343953926634992332820282019728792003956564819967', Requirements(RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_toInt256("1.0")), Name('Int256')), + ('UInt128','0','340282366920938463463374607431768211455', Requirements(RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_toUInt128("1.0")), Name('UInt128')), + ('UInt256', '0', '115792089237316195423570985008687907853269984665640564039457584007913129639935', Requirements(RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_toUInt256("1.0")), Name('UInt256')), +]) +def int_conversion(self, int_type, min, max, node=None): + """Check that ClickHouse converts values to Int128. + """ + + if node is None: + node = self.context.node + + with When(f"I convert {min}, {max}, 1 to {int_type}"): + output = node.query(f"SELECT to{int_type}(\'{min}\'), to{int_type}(\'{max}\'), to{int_type}(1) format TabSeparatedRaw").output + assert output == f'{min}\t{max}\t1', error() + +@TestScenario +@Requirements( + RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_toDecimal256("1.0"), +) +def to_decimal256(self, node=None): + """Check that ClickHouse converts values to Int128. + """ + min = Decimal256_min_max[0] + max = Decimal256_min_max[1] + + if node is None: + node = self.context.node + + for value in [1,min,max]: + output = node.query(f"SELECT toDecimal256(\'{value}\',0)").output + assert output == str(value), error() + +@TestScenario +@Requirements( + RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_ToMySQL("1.0"), +) +def MySQL_table(self, node=None): + """Check that ClickHouse converts MySQL values from MySQL table into ClickHouse table. + """ + table_name = f'table_{getuid()}' + + node = self.context.node + mysql_node = self.context.mysql_node + + with table(table_name, node, mysql_node): + + with When("I insert parameters values in MySQL"): + sql = f""" + INSERT INTO {table_name}(int128, uint128, int256, uint256, dec256) VALUES (1,1,1,1,1); + """ + mysql_node.command(f"MYSQL_PWD=password mysql -D db -u user <<'EOF'{textwrap.dedent(sql)}\nEOF", exitcode=0) + + with Then("I select from the table on top of the mysql table"): + node.query(f"SELECT * FROM {table_name}", + exitcode=50, message='Exception:') + +@TestScenario +@Requirements( + RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_FromMySQL("1.0"), +) +def MySQL_func(self, node=None): + """Check that ClickHouse converts MySQL values into a ClickHouse table using the MySQL table function. + """ + table_name = f'table_{getuid()}' + + node = self.context.node + mysql_node = self.context.mysql_node + + with table_func(table_name, node, mysql_node) as table_function: + + with When("I insert parameters values in MySQL"): + sql = f""" + INSERT INTO {table_name}(int128, uint128, int256, uint256, dec256) VALUES (1,1,1,1,1); + """ + mysql_node.command(f"MYSQL_PWD=password mysql -D db -u user <<'EOF'{textwrap.dedent(sql)}\nEOF", exitcode=0) + + with And("I make sure the table doesn't exist"): + node.query(f"DROP TABLE IF EXISTS {table_name}") + + with And("I create the table"): + node.query(f"CREATE TABLE {table_name} (id UInt8, int128 Int128, uint128 UInt128, int256 Int256, uint256 UInt256, dec256 Decimal256(0)) Engine = Memory") + + with And("I insert into the clickhouse table from the mysql table"): + node.query(f"INSERT INTO {table_name} SELECT * FROM {table_function}") + + with Then("I select from the clickhouse table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert output == '1\t1\t1\t1\t1\t1', error() + +@TestScenario +@Requirements( + RQ_SRS_020_ClickHouse_Extended_Precision_Conversion_ToMySQL("1.0"), +) +def MySQL_dict(self, node=None): + """Check that ClickHouse converts MySQL values from MySQL table into ClickHouse dictionary. + """ + + node = self.context.node + mysql_node = self.context.mysql_node + + table_name = f'table_{getuid()}' + + with dictionary(table_name, node, mysql_node): + + with When("I insert parameters values in MySQL"): + sql = f""" + INSERT INTO {table_name}(int128, uint128, int256, uint256, dec256) VALUES (1,1,1,1,1); + """ + mysql_node.command(f"MYSQL_PWD=password mysql -D db -u user <<'EOF'{textwrap.dedent(sql)}\nEOF", exitcode=0) + + with Then("I select from the table on top of the mysql table"): + node.query(f"SELECT * FROM dict_{table_name}", + exitcode=50, message='Exception:') + +@TestFeature +@Name("conversion") +def feature(self, node="clickhouse1", mysql_node="mysql1", stress=None, parallel=None): + """Check the conversion of extended precision data types. + """ + self.context.node = self.context.cluster.node(node) + self.context.mysql_node = self.context.cluster.node(mysql_node) + + for scenario in loads(current_module(), Scenario): + with allow_experimental_bigint(self.context.node): + Scenario(run=scenario) diff --git a/tests/testflows/extended_precision_data_types/tests/feature.py b/tests/testflows/extended_precision_data_types/tests/feature.py new file mode 100644 index 00000000000..83293b61f35 --- /dev/null +++ b/tests/testflows/extended_precision_data_types/tests/feature.py @@ -0,0 +1,19 @@ +from testflows.core import * +from testflows.core.name import basename, parentname +from testflows._core.testtype import TestSubType + +@TestFeature +@Name("tests") +def feature(self): + """Check functions with Int128, Int256, UInt256, and Decimal256. + """ + Feature(run=load("extended_precision_data_types.tests.conversion", "feature")) + Feature(run=load("extended_precision_data_types.tests.arithmetic", "feature")) + Feature(run=load("extended_precision_data_types.tests.array_tuple_map", "feature")) + Feature(run=load("extended_precision_data_types.tests.comparison", "feature")) + Feature(run=load("extended_precision_data_types.tests.logical", "feature")) + Feature(run=load("extended_precision_data_types.tests.mathematical", "feature")) + Feature(run=load("extended_precision_data_types.tests.rounding", "feature")) + Feature(run=load("extended_precision_data_types.tests.bit", "feature")) + Feature(run=load("extended_precision_data_types.tests.null", "feature")) + Feature(run=load("extended_precision_data_types.tests.table", "feature")) diff --git a/tests/testflows/extended_precision_data_types/tests/logical.py b/tests/testflows/extended_precision_data_types/tests/logical.py new file mode 100644 index 00000000000..36dbc97da97 --- /dev/null +++ b/tests/testflows/extended_precision_data_types/tests/logical.py @@ -0,0 +1,99 @@ +from extended_precision_data_types.requirements import * +from extended_precision_data_types.common import * + +funcs = [ + ('and',), + ('or',), + ('not',), + ('xor',), +] + +Examples_list = [tuple(list(func)+list(data_type)+[Name(f'{func[0]} - {data_type[0]}')]) for func in funcs for data_type in data_types] + +@TestOutline(Scenario) +@Examples('func int_type min max', Examples_list) +def log_int_inline(self, func, int_type, min, max, node=None): + """Check logical functions with Int128, Int256, and UInt256 using inline tests. + """ + table_name = f'table_{getuid()}' + + if node is None: + node = self.context.node + + with When(f"Check {func} with {int_type}"): + node.query(f"SELECT {func}(to{int_type}(1), to{int_type}(1)), {func}(to{int_type}(\'{max}\'), to{int_type}(1)), {func}(to{int_type}(\'{min}\'), to{int_type}(1))", + exitcode=43, message = 'Exception: Illegal type ') + +@TestOutline(Scenario) +@Examples('func int_type min max', Examples_list) +def log_int_table(self, func, int_type, min, max, node=None): + """Check logical functions with Int128, Int256, and UInt256 using table tests. + """ + + if node is None: + node = self.context.node + + table_name = f'table_{getuid()}' + + with Given(f"I have a table"): + table(name = table_name, data_type = int_type) + + for value in [1, min, max]: + + with When(f"Check {func} with {int_type} and {value}"): + node.query(f"INSERT INTO {table_name} SELECT {func}(to{int_type}(\'{value}\'), to{int_type}(\'{value}\'))", + exitcode=43, message = 'Exception: Illegal type') + +@TestOutline(Scenario) +@Examples('func', funcs) +def log_dec_inline(self, func, node=None): + """Check logical functions with Decimal256 using inline tests. + """ + min = Decimal256_min_max[0] + max = Decimal256_min_max[1] + + if node is None: + node = self.context.node + + with When(f"Check {func} with Decimal256"): + node.query(f"SELECT {func}(toDecimal256(1,0), toDecimal256(1,0)), {func}(toDecimal256(\'{max}\',0), toDecimal256(1)), {func}(toDecimal256(\'{min}\',0), toDecimal256(1))", + exitcode=43, message = 'Exception: Illegal type ') + +@TestOutline(Scenario) +@Examples('func', funcs) +def log_dec_table(self, func, node=None): + """Check logical functions with Decimal256 using table tests. + """ + min = Decimal256_min_max[0] + max = Decimal256_min_max[1] + + if node is None: + node = self.context.node + + table_name = f'table_{getuid()}' + + with Given(f"I have a table"): + table(name = table_name, data_type = 'Decimal256(0)') + + for value in [1, min, max]: + + with When(f"Check {func} with Decimal256 and {value}"): + node.query(f"INSERT INTO {table_name} SELECT {func}(toDecimal256(\'{value}\',0), toDecimal256(\'{value}\',0))", + exitcode=43, message = 'Exception: Illegal type ') + +@TestFeature +@Name("logical") +@Requirements( + RQ_SRS_020_ClickHouse_Extended_Precision_Logical("1.0"), +) +def feature(self, node="clickhouse1", mysql_node="mysql1", stress=None, parallel=None): + """Check that comparison functions work with extended precision data types. + """ + self.context.node = self.context.cluster.node(node) + self.context.mysql_node = self.context.cluster.node(mysql_node) + + with allow_experimental_bigint(self.context.node): + Scenario(run=log_int_inline) + Scenario(run=log_int_table) + Scenario(run=log_dec_inline) + Scenario(run=log_dec_table) diff --git a/tests/testflows/extended_precision_data_types/tests/mathematical.py b/tests/testflows/extended_precision_data_types/tests/mathematical.py new file mode 100644 index 00000000000..6062a00a7c9 --- /dev/null +++ b/tests/testflows/extended_precision_data_types/tests/mathematical.py @@ -0,0 +1,187 @@ +from extended_precision_data_types.requirements import * +from extended_precision_data_types.common import * + +funcs = [ + ('exp(', 3, 0), + ('log(', 0, 0), + ('ln(', 0, 0), + ('exp2(', 2, 0), + ('log2(', 0, 0), + ('exp10(', 10, 0), + ('log10(', 0, 0), + ('sqrt(', 1, 0), + ('cbrt(', 1, 0), + ('erf(', 1, 0), + ('erfc(', 0, 0), + ('lgamma(', 0, 0), + ('tgamma(', 1, 0), + ('sin(', 1, 0), + ('cos(', 1, 0), + ('tan(', 2, 0), + ('asin(', 2, 0), + ('acos(', 0, 0), + ('atan(', 1, 0), + ('intExp2(', 2, 48), + ('intExp10(', 10, 48), + ('cosh(', 2, 0), + ('acosh(', 0, 0), + ('sinh(', 1, 0), + ('asinh(', 1, 0), + ('tanh(', 1, 0), + ('atanh(', 'inf', 0), + ('log1p(', 1, 0), + ('sign(', 1, 0), + ('pow(1,', 1, 43), + ('power(1,', 1, 43), + ('atan2(1,', 1, 43), + ('hypot(1,', 1, 43), +] + +Examples_list = [tuple(list(func)+list(data_type)+[Name(f'{func[0]} - {data_type[0]}')]) for func in funcs for data_type in data_types] +Examples_dec_list = [tuple(list(func)+[Name(f'{func[0]} - Decimal256')]) for func in funcs] + +@TestOutline(Scenario) +@Examples('func expected_result exitcode int_type min max', Examples_list) +def math_int_inline(self, func, expected_result, exitcode, int_type, min, max, node=None): + """Check mathematical functions with Int128, UInt128, Int256, and UInt256 using inline tests. + """ + if node is None: + node = self.context.node + + if func in ['intExp2(', 'intExp10(', 'pow(1,', 'power(1,', 'atan2(1,', 'hypot(1,']: + + with When(f"I check {func} with {int_type} using 1, max, and min"): + node.query(f"SELECT {func} to{int_type}(1)), {func} to{int_type}(\'{max}\')), {func} to{int_type}(\'{min}\'))", + exitcode=exitcode, message = 'Exception:') + + else: + + with When(f"I check {func} with {int_type} using 1"): + output = node.query(f"SELECT {func} to{int_type}(1))").output + if output == 'inf': + pass + else: + assert round(float(output)) == expected_result, error() + + with And(f"I check {func} with {int_type} using max and min"): + execute_query(f""" + SELECT {func} to{int_type}(\'{max}\')), {func} to{int_type}(\'{min}\')) + """) + +@TestOutline(Scenario) +@Examples('func expected_result exitcode int_type min max', Examples_list) +def math_int_table(self, func, expected_result, exitcode, int_type, min, max, node=None): + """Check mathematical functions with Int128, UInt128, Int256, and UInt256 using table tests. + """ + if node is None: + node = self.context.node + + table_name = f'table_{getuid()}' + + with Given(f"I have a table"): + table(name = table_name, data_type = f'Nullable({int_type})') + + if func in ['intExp2(', 'intExp10(', 'pow(1,', 'power(1,', 'atan2(1,', 'hypot(1,']: + + for value in [1, max, min]: + + with When(f"I insert the output of {func} with {int_type} using {value} into a table"): + node.query(f"INSERT INTO {table_name} SELECT {func} to{int_type}(\'{value}\'))", + exitcode=exitcode, message = 'Exception:') + + else: + + for value in [1, max, min]: + + with And(f"I insert the output of {func} with {int_type} using {value} into a table"): + node.query(f"INSERT INTO {table_name} SELECT to{int_type}OrZero( toString({func} to{int_type}(\'{value}\'))))") + + with Then(f"I check the outputs of {func} with {int_type}"): + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + +@TestOutline(Scenario) +@Examples('func expected_result exitcode', Examples_dec_list) +def math_dec_inline(self, func, expected_result, exitcode, node=None): + """Check mathematical functions with Decimal256 using inline tests. + """ + min = Decimal256_min_max[0] + max = Decimal256_min_max[1] + + if node is None: + node = self.context.node + + if func in ['intExp2(', 'intExp10(', 'pow(1,', 'power(1,', 'atan2(1,', 'hypot(1,']: + + with When(f"I check {func} with Decimal256 using 1, max, and min"): + node.query(f"SELECT {func} toDecimal256(1,0)), {func} toDecimal256(\'{max}\',0)), {func} toDecimal256(\'{min}\',0))", + exitcode=43, message = 'Exception: Illegal type ') + + else: + + with When(f"I check {func} with Decimal256 using 1"): + output = node.query(f"SELECT {func} toDecimal256(1,0))").output + if output == 'inf': + pass + else: + assert round(float(output)) == expected_result, error() + + with And(f"I check {func} with Decimal256 using max and min"): + execute_query(f""" + SELECT {func} toDecimal256(\'{max}\',0)), {func} toDecimal256(\'{min}\',0)) + """) + +@TestOutline(Scenario) +@Examples('func expected_result exitcode', Examples_dec_list) +def math_dec_table(self, func, expected_result, exitcode, node=None): + """Check mathematical functions with Decimal256 using table tests. + """ + min = Decimal256_min_max[0] + max = Decimal256_min_max[1] + + if node is None: + node = self.context.node + + table_name = f'table_{getuid()}' + + with Given(f"I have a table"): + table(name = table_name, data_type = 'Decimal256(0)') + + if func in ['intExp2(', 'intExp10(', 'pow(1,', 'power(1,', 'atan2(1,', 'hypot(1,']: + + for value in [1, max, min]: + + with When(f"I insert the output of {func} with Decimal256 using {value} into a table"): + node.query(f"INSERT INTO {table_name} SELECT {func} toDecimal256(\'{value}\',0))", + exitcode=43, message = 'Exception: Illegal type ') + + else: + + for value in [1, max, min]: + + with When(f"I insert the output of {func} with Decimal256 using {value} into a table"): + node.query(f"INSERT INTO {table_name} SELECT toDecimal256OrZero( toString({func} toDecimal256(\'{value}\',0))),0)") + + with Then(f"I check the outputs of {func} with Decimal256"): + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + +@TestFeature +@Name("mathematical") +@Requirements( + RQ_SRS_020_ClickHouse_Extended_Precision_Mathematical_Supported("1.0"), + RQ_SRS_020_ClickHouse_Extended_Precision_Mathematical_NotSupported("1.0"), +) +def feature(self, node="clickhouse1", mysql_node="mysql1", stress=None, parallel=None): + """Check that mathematical functions work with extended precision data types. + """ + self.context.node = self.context.cluster.node(node) + self.context.mysql_node = self.context.cluster.node(mysql_node) + + with allow_experimental_bigint(self.context.node): + Scenario(run=math_int_inline) + Scenario(run=math_int_table) + Scenario(run=math_dec_inline) + Scenario(run=math_dec_table) diff --git a/tests/testflows/extended_precision_data_types/tests/null.py b/tests/testflows/extended_precision_data_types/tests/null.py new file mode 100644 index 00000000000..9ddaa94a245 --- /dev/null +++ b/tests/testflows/extended_precision_data_types/tests/null.py @@ -0,0 +1,119 @@ +from extended_precision_data_types.requirements import * +from extended_precision_data_types.common import * + +funcs = [ + ('isNull(', 0), + ('isNotNull(', 1), + ('coalesce(', 1), + ('assumeNotNull(', 1), + ('toNullable(', 1), + ('ifNull(1,', 1), + ('nullIf(1,', '\\N'), +] + +Examples_list = [tuple(list(func)+list(data_type)+[Name(f'{func[0]} - {data_type[0]}')]) for func in funcs for data_type in data_types] + +@TestOutline(Scenario) +@Examples('func expected_result int_type min max', Examples_list) +def null_int_inline(self, func, expected_result, int_type, min, max, node=None): + """Check null function with Int128, UInt128, Int256, and UInt256 using inline tests. + """ + + if node is None: + node = self.context.node + + with When(f"I check {func} with {int_type}"): + output = node.query(f"SELECT {func} to{int_type}(1))").output + assert output == str(expected_result), error() + + with And(f"I check {func} with {int_type} using min and max"): + execute_query(f""" + SELECT {func} to{int_type}(\'{min}\')), {func} to{int_type}(\'{max}\')) + """) + +@TestOutline(Scenario) +@Examples('func expected_result int_type min max', Examples_list) +def null_int_table(self, func, expected_result, int_type, min, max, node=None): + """Check null function with Int128, UInt128, Int256, and UInt256 using table tests. + """ + + table_name = f"table_{getuid()}" + + if node is None: + node = self.context.node + + with Given("I have a table"): + table(name = table_name, data_type = f'Nullable({int_type})') + + for value in [1, min, max]: + + with When(f"I insert the output of {func} with {int_type} and {value}"): + node.query(f"INSERT INTO {table_name} SELECT {func} to{int_type}(\'{value}\'))") + + with Then(f"I check {func} with {int_type} on the table"): + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + +@TestOutline(Scenario) +@Examples('func expected_result', funcs) +def null_dec_inline(self, func, expected_result, node=None): + """Check null function with Decimal256 using inline tests. + """ + min = Decimal256_min_max[0] + max = Decimal256_min_max[1] + + if node is None: + node = self.context.node + + with When(f"I check {func} with Decimal256"): + output = node.query(f"SELECT {func} toDecimal256(1,0))").output + assert output == str(expected_result), error() + + with And(f"I check {func} with Decimal256 using min and max"): + execute_query(f""" + SELECT {func} toDecimal256(\'{min}\',0)), {func} toDecimal256(\'{max}\',0)) + """) + +@TestOutline(Scenario) +@Examples('func expected_result', funcs) +def null_dec_table(self, func, expected_result, node=None): + """Check null function with Decimal256 using table tests. + """ + min = Decimal256_min_max[0] + max = Decimal256_min_max[1] + + table_name = f"table_{getuid()}" + + if node is None: + node = self.context.node + + with Given("I have a table"): + table(name = table_name, data_type = 'Nullable(Decimal256(0))') + + for value in [1, min, max]: + + with When(f"I insert the output of {func} with Decimal256 and {value}"): + node.query(f"INSERT INTO {table_name} SELECT {func} toDecimal256(\'{value}\',0))") + + with Then(f"I check {func} with Decimal256 on the table"): + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + +@TestFeature +@Name("null") +@Requirements( + RQ_SRS_020_ClickHouse_Extended_Precision_Null("1.0"), +) +def feature(self, node="clickhouse1", mysql_node="mysql1", stress=None, parallel=None): + """Check that null functions work with extended precision data types. + """ + self.context.node = self.context.cluster.node(node) + self.context.mysql_node = self.context.cluster.node(mysql_node) + + with allow_experimental_bigint(self.context.node): + Scenario(run=null_int_inline) + Scenario(run=null_int_table) + Scenario(run=null_dec_inline) + Scenario(run=null_dec_table) diff --git a/tests/testflows/extended_precision_data_types/tests/rounding.py b/tests/testflows/extended_precision_data_types/tests/rounding.py new file mode 100644 index 00000000000..f01d6898b32 --- /dev/null +++ b/tests/testflows/extended_precision_data_types/tests/rounding.py @@ -0,0 +1,191 @@ +from extended_precision_data_types.requirements import * +from extended_precision_data_types.common import * + +funcs = [ + ('ceil', 1, True), + ('floor', 1, True), + ('trunc', 1, True), + ('round', 1, True), + ('roundBankers', 1, True), + ('roundToExp2', 1, False), + ('roundDuration', 1, True), + ('roundAge', 17, True), + ('roundDown', 1, False) +] + +Examples_list = [tuple(list(func)+list(data_type)+[Name(f'{func[0]} - {data_type[0]}')]) for func in funcs for data_type in data_types] +Examples_dec_list = [tuple(list(func)+[Name(f'{func[0]} - Decimal256')]) for func in funcs] + +@TestOutline(Scenario) +@Examples('func expected_result supported int_type min max', Examples_list) +def round_int_inline(self, func, expected_result, supported, int_type, min, max, node=None): + """Check rounding functions with Int128, UInt128, Int256, and UInt256 using inline tests. + """ + + if node is None: + node = self.context.node + + if func is 'roundDown': + + with When(f"I check roundDown with {int_type}"): + node.query(f"SELECT roundDown(to{int_type}(1), [0,2]), roundDown(to{int_type}(\'{max}\'), [0,2]), roundDown(to{int_type}(\'{min}\'), [0,2])", + exitcode=44, message=f'Exception: Illegal column {int_type} of first argument of function roundDown') + + elif supported: + + with When(f"I check {func} with {int_type}"): + output = node.query(f"SELECT {func}(to{int_type}(1))").output + assert output == str(expected_result), error() + + with And(f'I check {func} with {int_type} using min and max values'): + execute_query(f""" + SELECT {func}(to{int_type}(\'{min}\')), {func}(to{int_type}(\'{max}\')) + """) + + else: + + with When(f"I check {func} with {int_type}"): + node.query(f"SELECT {func}(to{int_type}(1)), {func}(to{int_type}(\'{max}\')), {func}(to{int_type}(\'{min}\'))", + exitcode=48, message=f'Exception: {func}() for big integers is not implemented:') + +@TestOutline(Scenario) +@Examples('func expected_result supported int_type min max', Examples_list) +def round_int_table(self, func, expected_result, supported, int_type, min, max, node=None): + """Check rounding functions with Int128, UInt128, Int256, and UInt256 using table tests. + """ + + table_name = f"table_{getuid()}" + + if node is None: + node = self.context.node + + with Given("I have a table"): + table(name = table_name, data_type = int_type) + + if func is 'roundDown': + + for value in [1,max,min]: + + with When(f"I check roundDown with {int_type} and {value}"): + node.query(f"INSERT INTO {table_name} SELECT roundDown(to{int_type}(\'{value}\'), [0,2])", + exitcode=44, message=f'Exception: Illegal column {int_type} of first argument of function roundDown') + + elif supported: + + for value in [1,max,min]: + + with When(f"I insert the output of {func} with {int_type} and {value} into the table"): + node.query(f"INSERT INTO {table_name} SELECT {func}(to{int_type}(\'{value}\'))") + + with Then(f"I select the output of {func} with {int_type} from the table"): + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + else: + + for value in [1,max,min]: + + with When(f"I insert the output of {func} with {int_type} and {value} into the table"): + node.query(f"INSERT INTO {table_name} SELECT {func}(to{int_type}(1))", + exitcode=48, message=f'Exception: {func}() for big integers is not implemented:') + +@TestOutline(Scenario) +@Examples('func expected_result supported', Examples_dec_list) +def round_dec_inline(self, func, expected_result, supported, node=None): + """Check rounding functions with Decimal256 using inline tests. + """ + min = Decimal256_min_max[0] + max = Decimal256_min_max[1] + + if node is None: + node = self.context.node + + if func is 'roundDown': + + with When(f"I check roundDown with Decimal256"): + node.query(f"""SELECT roundDown(toDecimal256(1,0), [toDecimal256(0,0),toDecimal256(2,0)]), + roundDown(toDecimal256(\'{max}\',0), [toDecimal256(0,0),toDecimal256(2,0)]), + roundDown(toDecimal256(\'{min}\',0), [toDecimal256(0,0),toDecimal256(2,0)])""", + exitcode=44, message=f'Exception: Illegal column Decimal256 of first argument of function roundDown') + + elif func not in ['roundDuration', 'roundAge', 'roundToExp2']: + + with When(f"I check {func} with Decimal256"): + output = node.query(f"SELECT {func}(toDecimal256(1,0))").output + assert output == str(expected_result), error() + + with And(f'I check {func} with Decimal256 using min and max values'): + execute_query(f""" + SELECT {func}(toDecimal256(\'{min}\',0)), {func}(toDecimal256(\'{max}\',0)) + """) + + else: + + with When(f"I check {func} with Decimal256"): + node.query(f"SELECT {func}(toDecimal256(1,0)), {func}(toDecimal256(\'{max}\',0)), {func}(toDecimal256(\'{min}\',0))", + exitcode=43, message=f'Exception: Illegal type Decimal(76, 0)') + +@TestOutline(Scenario) +@Examples('func expected_result supported', Examples_dec_list) +def round_dec_table(self, func, expected_result, supported, node=None): + """Check rounding functions with Decimal256 using table tests. + """ + min = Decimal256_min_max[0] + max = Decimal256_min_max[1] + + table_name = f"table_{getuid()}" + + if node is None: + node = self.context.node + + with Given("I have a table"): + table(name = table_name, data_type = 'Decimal256(0)') + + if func is 'roundDown': + + for value in [1, max, min]: + + with When(f"I check roundDown with Decimal256 and {value}"): + node.query(f"INSERT INTO {table_name} SELECT roundDown(toDecimal256(\'{value}\',0), [toDecimal256(0,0),toDecimal256(2,0)])", + exitcode=44, message=f'Exception: Illegal column Decimal256 of first argument of function roundDown') + + elif func not in ['roundDuration', 'roundAge', 'roundToExp2']: + + for value in [1, max, min]: + + with When(f"I insert the output of {func} with Decimal256 and {value} into the table"): + node.query(f"INSERT INTO {table_name} SELECT {func}(toDecimal256(\'{value}\',0))") + + with Then(f"I select the output of {func} with Decimal256 from the table"): + execute_query(f""" + SELECT * FROM {table_name} ORDER BY a ASC + """) + + else: + + for value in [1, max, min]: + + with When(f"I insert the output of {func} with Decimal256 and {value} into the table"): + node.query(f"INSERT INTO {table_name} SELECT {func}(toDecimal256(\'{value}\',0))", + exitcode=43, message=f'Exception: Illegal type Decimal(76, 0)') + +@TestFeature +@Name("rounding") +@Requirements( + RQ_SRS_020_ClickHouse_Extended_Precision_Rounding_Int_Supported("1.0"), + RQ_SRS_020_ClickHouse_Extended_Precision_Rounding_Int_NotSupported("1.0"), + RQ_SRS_020_ClickHouse_Extended_Precision_Rounding_Dec_Supported("1.0"), + RQ_SRS_020_ClickHouse_Extended_Precision_Rounding_Dec_NotSupported("1.0"), +) +def feature(self, node="clickhouse1", mysql_node="mysql1", stress=None, parallel=None): + """Check that rounding functions work with extended precision data types. + """ + self.context.node = self.context.cluster.node(node) + self.context.mysql_node = self.context.cluster.node(mysql_node) + + with allow_experimental_bigint(self.context.node): + Scenario(run=round_int_inline) + Scenario(run=round_int_table) + Scenario(run=round_dec_inline) + Scenario(run=round_dec_table) diff --git a/tests/testflows/extended_precision_data_types/tests/table.py b/tests/testflows/extended_precision_data_types/tests/table.py new file mode 100644 index 00000000000..1548d6b20c2 --- /dev/null +++ b/tests/testflows/extended_precision_data_types/tests/table.py @@ -0,0 +1,35 @@ +from testflows.core import * +from testflows.asserts import error +from contextlib import contextmanager + +from extended_precision_data_types.requirements import * +from extended_precision_data_types.common import * + +@TestFeature +@Name("table") +@Requirements( + RQ_SRS_020_ClickHouse_Extended_Precision_Create_Table("1.0"), +) +def feature(self, node="clickhouse1", mysql_node="mysql1", stress=None, parallel=None): + """Check that clickhouse is able to create a table with extended precision data types. + """ + node = self.context.cluster.node(node) + + table_name = f"table_{getuid()}" + + with allow_experimental_bigint(node): + + try: + with When("I create a table with Int128, UInt128, Int256, UInt256, Decimal256"): + node.query(f"CREATE TABLE {table_name}(a Int128, b UInt128, c Int256, d UInt256, e Decimal256(0)) ENGINE = Memory") + + with And("I insert values into the table"): + node.query(f"INSERT INTO {table_name} VALUES (toInt128(1), toUInt128(1), toInt256(1), toUInt256(1), toDecimal256(1,0))") + + with Then("I select from the table"): + output = node.query(f"SELECT * FROM {table_name}").output + assert output == '1\t1\t1\t1\t1', error() + + finally: + with Finally("I drop the table"): + node.query(f"DROP TABLE IF EXISTS {table_name}") diff --git a/tests/testflows/regression.py b/tests/testflows/regression.py index 2547463a91d..c7a264a9c27 100755 --- a/tests/testflows/regression.py +++ b/tests/testflows/regression.py @@ -30,6 +30,7 @@ def regression(self, local, clickhouse_binary_path, stress=None, parallel=None): run_scenario(pool, tasks, Feature(test=load("window_functions.regression", "regression")), args) run_scenario(pool, tasks, Feature(test=load("datetime64_extended_range.regression", "regression")), args) #run_scenario(pool, tasks, Feature(test=load("kerberos.regression", "regression")), args) + run_scenario(pool, tasks, Feature(test=load("extended_precision_data_types.regression", "regression")), args) finally: join(tasks)