diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml deleted file mode 100644 index 87ad37a5d..000000000 --- a/.github/workflows/legacy.yml +++ /dev/null @@ -1,64 +0,0 @@ -name: Legacy - -on: - workflow_dispatch: - inputs: - version: - description: "Legacy driver version" - required: true - default: "0.3.3-SNAPSHOT" - -jobs: - release: - name: "Build and Publish Artifact" - runs-on: "ubuntu-latest" - - steps: - - name: Check out Git repository - uses: actions/checkout@v2 - - name: Install JDK 11 - uses: AdoptOpenJDK/install-jdk@v1 - with: - version: '11' - targets: 'JDK11_HOME' - - name: Setup Toolchain - shell: bash - run: | - mkdir -p $HOME/.m2 \ - && cat << EOF > $HOME/.m2/toolchains.xml - - - - jdk - - 11 - - - ${{ env.JDK11_HOME }} - - - - EOF - - name: Install JDK 8 and Maven - uses: actions/setup-java@v2 - with: - distribution: 'temurin' - java-version: 8 - - name: Update Configuration - run: | - rm -fv clickhouse-jdbc/pom.xml; - mv -fv clickhouse-jdbc/legacy.xml clickhouse-jdbc/pom.xml; - find . -type f -name "pom.xml" -exec sed -i -e 's|${revision}|${{ github.event.inputs.version }}|g' \ - -e 's|^\( \).*\(\)$|\1${{ github.event.inputs.version }}\2|' \ - -e 's|${parent.groupId}|com.clickhouse|g' -e 's|${project.parent.groupId}|com.clickhouse|g' '{}' \; - find . -type f -name "simplelogger.*" -exec rm -fv '{}' \; - - name: Release Maven package - uses: samuelmeuli/action-maven-publish@v1 - with: - directory: clickhouse-jdbc - maven_profiles: release - maven_args: -q --batch-mode - gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} - gpg_passphrase: ${{ secrets.GPG_PASSPHRASE }} - nexus_username: ${{ secrets.SONATYPE_USER }} - nexus_password: ${{ secrets.SONATYPE_PASSWD }} diff --git a/CHANGELOG b/CHANGELOG deleted file mode 100644 index 5463a629f..000000000 --- a/CHANGELOG +++ /dev/null @@ -1,364 +0,0 @@ -0.3.1-patch - * fix incorrect database used in DDL - * fix batch insert issue when no VALUES used in SQL statement - * fix issue of handling negative decimal128/256 values - -0.3.1 - * BREAKING CHANGE - move query from url to request body - * BREAKING CHANGE - always parse SQL(use extended API to skip that) - * BREAKING CHANGE - remove keepAliveTimeout and useNewParser from ClickHouseProperties - * BREAKING CHANGE - exclude RoaringBitmap from shaded jar - * add new connection setting useSharedCookieStore for load balancing - * add new query parameters: allow_experimental_bigint_types, allow_experimental_map_type, and join_algorithm - * add new format: CustomSeparated and RowBinaryWithNamesAndTypes - * fix 400 bad request error when dealing with large query - * fix parser issue when DESC statement contains alias - * support batch processing with arbitrary query - update and delete are not recommended so there'll be warnings - * support multi-statement sql - session will be used automatically and only the last result will be returned - -0.3.0 - * BREAKING CHANGE - dropped JDK 7 support - * BREAKING CHANGE - removed Guava dependency(and so is UnsignedLong) - * JDBC 4.2 support - * add connection setting client_name for load-balancing and troubleshooting - * add writeBytes & writeUUIDArray and remove UnsignedLong related methods in ClickHouseRowBinaryStream - * support more data types: IPv4, IPv6, Int128, UInt128, Int256, UInt256, Decimal256, DateTime*, and Map - * support ORC/Parquet streaming - * support read/write Bitmap from/into AggregateFunction(groupBitmap, UInt[8-64]) column - * throw SQLException instead of RuntimeException when instantiating ClickHouseConnectionImpl - * fix error when using ClickHouseCompression.none against 19.16 - * fix NegativeArraySizeException when dealing with large array - * fix datetime/date display issue caused by timezone differences(between client and column/server) - -0.2.6 - * add new feature for sending compressed files/streams - * introduce an experimental SQL parser to fix parsing related issues - set connection setting use_new_parser to false to disable - * restore String[] getColumnNames() method for backward compatibility - * retry idempotent operation up to 3 times when server closed connection - set connection setting maxRetries to zero to disable - * return inserted rows(not accurate) when query parameter send_progress_in_http_headers is set to true - * set socket timeout in ClickHouseConnectionImpl.isValid() - * upgrade to lz4-java and improve performance of LZ4 stream - * use HTTP Basic Auth for credentials instead of query parameters - * use static version instead of property-based revision in pom.xml - -0.2.5 - * bump dependencies and include lz4 in shaded jar - * new API: ClickHouseRowBinaryStream.writeUInt64Array(UnsignedLong[]) - * support column comments - * support explain queries - * fix keep-alive timeout issue by reusing validated connection - * fix ResultSet.findColumn(String) issue - * fix the issue of not being able to use NULL constant in PreparedStatement - * fix toLowerCase issue for Turkish - -0.2.4 - * fix FORMAT clause append for queries, ending with comment - -0.2.3 - * added support for Decimals in RowBinary protocol - -0.2.2 - * close certificate keystore - * fix for Boolean data type - -0.2.1 - * implement some ResultSet metadata methods - * added support for "any_join_distinct_right_table_keys" setting - * nested array support - -0.2 - * new API for writing streams of data - * deprecation of send* methods in ClickHouseStatement interface - -0.1.55 -NOTE: behavior for byte[] parameters changed. See https://github.com/yandex/clickhouse-jdbc/pull/352 - * support for sending stream of CSV data - * support for 307 redirects and paths in url (when ClickHouse is behind balancer) - * query parameters and types handling improved - * strict ssl fixed - * support for array of decimals - -0.1.54 - * added error codes - * multi-line statement parsing fixed - * correct class names for arrays - * prepared statements with functions fixed - * max_partitions_per_insert_block, max_insert_block_size, insert_deduplicate, insert_distributed_sync added - * BalancedClickHouseDatasource parameters handling fixed - * DateTime with timezone type support. NOTE: zones in values parsing are not handled - * prepared statements with back quotes fixed - -0.1.53 - * fixed timezone initialization - * added max_memory_usage_for_user and max_memory_usage_for_all_queries - -0.1.52 - * fixed executeQuery additionalParams copy - -0.1.51 - * fixed sendStream - * fixed LEB128 encoding - * cancel by query_id implementation - * improved ResultSetMetadata for Decimal data types - * PreparedStatement single and double quotes support - * NoopHostnameVerifier for sslMode none - -0.1.50 - * Array(FixedString(N)) insert support - * ENABLE_OPTIMIZE_PREDICATE_EXPRESSION query param - * clearBatch implementation - * getMetadata implementation if query was not executed yet - * setQueryTimeout implementation - * RowBinaryInputStream to support nullability - * test plugins settings updated - -0.1.49 skipped - -0.1.48 - * SELECT_SEQUENTIAL_CONSISTENCY param - * scrollable ResultSet - * metadata updates - * Decimal type - -0.1.47 - * connection cleaner in daemon mode - * insert-quorum params - -0.1.46 - * nullable in RowBinaryStream - * fix null in arrays - * database regex (asterisks and dashes allowed) - -0.1.45 - * added shaded version of the jar - * http authorization header - * setTime implementation - -0.1.44 - * add public methods to BalancedClickhouseDataSource - * TYPE_NAME without Nullable - * sendRowBinaryStream with additional parameters - * support constant NULL values in prepared statements - * fix parsing parameter at last position of statement - -0.1.43 - * fix determining statement type in presence of comments - * improved support for prepared statements, including batch inserts - * fix parameters copy - * support for writing UUIDs in binary stream - * removed joda-time dependency - migration node for users of ClickHouseRowBinaryStream: - manually calculate daysSinceEpoch and use method writeUInt16(): - for joda-time: Days.daysBetween(LocalDate.parse("1970-01-01"), date).getDays() - for java 8: LocalDate.toEpochDay()) - or use conversion to Date: - for joda-time: localDate.toDate() - for java 8: java.sql.Date.valueOf(LocalDate date) - -0.1.42 - * additional query params for executeBatch - * query preprocessing optimization - * UUID support - * isClosed - * isLast - * isNullable - * default connection config for pooling connection manager - -0.1.41 - * arbitrary query params - * checksum fix - -0.1.40 - * fix encoding - * insert array of nullables - * NaN support - * fix checksum calculation - -0.1.39 - * fix nullable metadata - * fix nested arrays insert - -0.1.38 - * decompress errors on inserts - * handle comments in bind variables parsing - -0.1.37 - * writeBytes for binary - * fix for read after last - * zero-valued dates are returned as nul - * column size metadata fixes - -0.1.36 - * allow send stream in native format - -0.1.35 - * with totals support - * nullable metadata fixes - * specialize on connection type in balanced data source - -0.1.34 - * support for select queries starting with "WITH ... SELECT" - * add executeQueryClickhouseResponse - * add session query parameters - -0.1.33 - * json parse optitimzation - * BalancedClickHouseDataSource url pattern fix - -0.1.32 - * fix getObject() for DOUBLE - -0.1.31 - * fix: parse errors compressed and uncompressed - -0.1.30 - * fix batch insert with 'values' column - -0.1.29 - * fix for empty long arrays - * use_objects_in_arrays option - * position of missing placeholder in error - * fix selectObject and types for nullable columns - -0.1.28 - * fix getUpdateCount - * handle null string values correctly - * inner tables in metadata - -0.1.27 - * setCatalog/getCatalog - * fix `ClickHousePreparedStatement.setObject(int, List)` for Number - -0.1.26 - NOTE: starting from this release local application timezone is used by default for Date conversions. - Time, Timestamp are converted using server timezone as starting from release 0.1.18. - Set use_server_time_zone_for_dates = true to use server timezone for Date conversions as before. - * use local timezone for Date conversions - * more arrays support - * fix metadata request from system.columns - * pass correct properties to initTimeZone - -0.1.25 - * binary format fixes - * extremes fix - -0.1.24 - * max_query_size property - -0.1.23 - NOTE: default connection timeout had changed to conform with ClickHouse core and support IDEs in default settings. - The setting may be overridden by passing ClickHouseProperties or Properties on connection init. - * default connection timeout 50ms -> 10s - * fixed metadata on mixed-case identifiers - -0.1.22 - * preferred_block_size_bytes property - -0.1.21 - * getSchema/setSchema - * table types in database metadata - * BalancedDataSource - * ssl/tls support - * RowBinary format for inserts - -0.1.20 - * checksum validation when using compress/decompress - * max_memory_usage param - * set boolean params as 0/1 - * fix getTableTypes - * extra trace logging - * null values support - -0.1.19 - * fix getColumns - -0.1.18 - NOTE: starting from this release server timezone is used by default. - This will work with server version >= 1.1.54159. - Set use_server_time_zone = false and use_time_zone to desired timezone name for using with earlier server versions. - * use server timezone - * is_generatedcolumn support - * fix error parsing - * escaping of non IOS-8859-1 characters - -0.1.17 - * fix passing additionalDBParams - * add query_id param - * add CH params to executeQuery in preparedStatement - * fix setting properties - * propagate parameters from jdbc url - -0.1.16 - * fix use Property class for configuration - * Add settings to ClickHouseQueryParam - -0.1.15 - * lz4 support - * External data support - * Disable extremes for ResultSet query methods - * Consistent charsets and rounding - * Fix for configuration options - -0.1.14 - * Testing with travis - * Unsigned types support - * Improvement on setMaxRows - * Configuration options for external sort and aggregation - -0.1.13 - * Lazy init on cleaner executor - * Auto-load meta-file - * Implemented getArray() - * Fix exception specifier - * JDBC compliance improvements - -0.1.12 - * Fix setArray - * Improve isValid - * Fix single column result set - -0.1.11 - * Fix exception specifier - * Fix SimpleDateFormat usage - -0.1.10 - * Support ipv6 jdbc url - * Return correct default value for COLUMN_DEF - * getColumnClassName - -0.1.9 - * Skip jdbc url to another DB - * Statement to ResultSet - * Correct return value for execute(sql) - * Arrays support - -0.1.8 - * Improved performance of batch operations - * Don't create cleaner executer for every connection - -0.1.7 - * Don't set implicit max_execution_time - * LogProxy only for trace - -0.1.6 - * Don't fail on fetchSize hint - -0.1.5 - * Nan and inf values support for double - * Fix ClickHouseException - * Database from properties priority over url - -0.1.4 - * Fix batch support - * Fix timestamp mapping - -0.1.3 - * Batch support - -0.1.2 - * BigDecimal support - * Assembly plugin - * Fix isSelect - -0.1.1 - * Initial release diff --git a/LICENSE b/LICENSE index d64569567..cfd4df13e 100644 --- a/LICENSE +++ b/LICENSE @@ -187,7 +187,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2016-2022 ClickHouse, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/clickhouse-benchmark/src/main/java/com/clickhouse/benchmark/jdbc/JdbcDriver.java b/clickhouse-benchmark/src/main/java/com/clickhouse/benchmark/jdbc/JdbcDriver.java index c645cb3ab..f04ad56a4 100644 --- a/clickhouse-benchmark/src/main/java/com/clickhouse/benchmark/jdbc/JdbcDriver.java +++ b/clickhouse-benchmark/src/main/java/com/clickhouse/benchmark/jdbc/JdbcDriver.java @@ -31,7 +31,6 @@ public enum JdbcDriver { ClickhouseLegacyJdbc("ru.yandex.clickhouse.ClickHouseDriver", "jdbc:clickhouse://%s:%s/%s?ssl=false&user=%s&password=%s&use_server_time_zone=false&use_time_zone=UTC&compress=%s%s", Constants.HTTP_PORT), - // ClickHouse4j Clickhouse4j("cc.blynk.clickhouse.ClickHouseDriver", "jdbc:clickhouse://%s:%s/%s?ssl=false&user=%s&password=%s&use_server_time_zone=false&use_time_zone=UTC&compress=%s%s", diff --git a/clickhouse-http-client/pom.xml b/clickhouse-http-client/pom.xml index 4edd2ecae..47d14b0a4 100644 --- a/clickhouse-http-client/pom.xml +++ b/clickhouse-http-client/pom.xml @@ -25,16 +25,6 @@ gson provided - - org.apache.httpcomponents - httpclient - provided - - - org.apache.httpcomponents - httpmime - provided - org.lz4 lz4-java diff --git a/clickhouse-jdbc/AUTHORS b/clickhouse-jdbc/AUTHORS deleted file mode 100644 index 207b0be1c..000000000 --- a/clickhouse-jdbc/AUTHORS +++ /dev/null @@ -1,12 +0,0 @@ -The following authors have created the source code of "clickhouse-jdbc" -published and distributed by YANDEX LLC as the owner: - -Artur Suilin -Sergey Lazarev -Viktor Tarnavsky -Pavel Yakunin -Aleksandr Lopashev -Olga Mazur -Yuriy Galitskiy -Sergey Serebryanik -Sergey Zhuravlev \ No newline at end of file diff --git a/clickhouse-jdbc/legacy.xml b/clickhouse-jdbc/legacy.xml deleted file mode 100644 index c6b986a24..000000000 --- a/clickhouse-jdbc/legacy.xml +++ /dev/null @@ -1,277 +0,0 @@ - - 4.0.0 - - - com.clickhouse - clickhouse-java - ${revision} - - - ru.yandex.clickhouse - clickhouse-jdbc - ${revision} - jar - - ${project.artifactId} - JDBC driver for ClickHouse - https://github.com/ClickHouse/clickhouse-jdbc/tree/master/clickhouse-jdbc - - - - serebrserg - Sergey Serebryanik - serebrserg@yandex-team.ru - - - jkee - Viktor Tarnavsky - jkee@yandex-team.ru - - - orantius - Yuriy Galitskiy - orantius@yandex-team.ru - - - krash - Alexandr Krasheninnikov - krash3@gmail.com - - - zhicwu - Zhichun Wu - zhicwu@gmail.com - - - - - 4.5.13 - 4.1.4 - ru.yandex.clickhouse.jdbc.internal - JDBC - 4.2 - - - - - ${project.parent.groupId} - clickhouse-http-client - ${revision} - - - ${project.parent.groupId} - org.roaringbitmap - ${repackaged.version} - provided - - - * - * - - - - - com.google.code.gson - gson - - - org.apache.httpcomponents - httpclient - ${httpclient.version} - - - org.apache.httpcomponents - httpmime - ${httpclient.version} - - - org.lz4 - lz4-java - - - - ${project.parent.groupId} - clickhouse-client - ${revision} - test-jar - test - - - org.slf4j - slf4j-simple - test - - - org.mockito - mockito-core - test - - - com.github.tomakehurst - wiremock-jre8 - test - - - org.testcontainers - testcontainers - test - - - org.testng - testng - test - - - mysql - mysql-connector-java - test - - - org.mariadb.jdbc - mariadb-java-client - test - - - org.postgresql - postgresql - test - - - - - - - org.apache.maven.plugins - maven-failsafe-plugin - - - org.apache.maven.plugins - maven-surefire-plugin - - - com.helger.maven - ph-javacc-maven-plugin - ${javacc-plugin.version} - - - jjc - generate-sources - - javacc - - - 1.8 - true - com.clickhouse.jdbc.parser - src/main/javacc - src/main/java - - - - - - io.github.git-commit-id - git-commit-id-maven-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - - true - true - true - - - ${spec.title} - ${spec.version} - ${project.groupId} - ${project.artifactId} ${project.version} (revision: ${git.commit.id.abbrev}) - - - - - - org.apache.maven.plugins - maven-assembly-plugin - - - jar-with-dependencies - - - - true - true - - - - - - org.apache.maven.plugins - maven-shade-plugin - - - shade - package - - shade - - - true - true - true - shaded - - - com.google.gson - ${shade.base}.gson - - - org.apache - ${shade.base}.apache - - - net.jpountz - ${shade.base}.jpountz - - - - - - - - - - ${spec.title} - ${spec.version} - ${project.name} - ${project.groupId} - ${project.artifactId} ${project.version} (revision: ${git.commit.id.abbrev}) - - - - - - *:* - - mozilla/** - **/darwin/** - **/linux/** - **/win32/** - META-INF/DEPENDENCIES - META-INF/MANIFEST.MF - META-INF/maven/** - META-INF/native-image/** - META-INF/versions/** - META-INF/*.xml - - - - - - - - - - \ No newline at end of file diff --git a/clickhouse-jdbc/pom.xml b/clickhouse-jdbc/pom.xml index f4d879f70..dbcddc671 100644 --- a/clickhouse-jdbc/pom.xml +++ b/clickhouse-jdbc/pom.xml @@ -73,16 +73,6 @@ com.google.code.gson gson - - org.apache.httpcomponents - httpclient - ${httpclient.version} - - - org.apache.httpcomponents - httpmime - ${httpclient.version} - ${project.parent.groupId} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/BalancedClickhouseDataSource.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/BalancedClickhouseDataSource.java deleted file mode 100644 index c5bae8357..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/BalancedClickhouseDataSource.java +++ /dev/null @@ -1,342 +0,0 @@ -package ru.yandex.clickhouse; - -import ru.yandex.clickhouse.settings.ClickHouseProperties; - -import javax.sql.DataSource; - -import com.clickhouse.client.ClickHouseChecker; -import com.clickhouse.client.logging.Logger; -import com.clickhouse.client.logging.LoggerFactory; - -import java.io.PrintWriter; -import java.net.URISyntaxException; -import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; -import java.util.*; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static ru.yandex.clickhouse.ClickhouseJdbcUrlParser.JDBC_CLICKHOUSE_PREFIX; - -/** - *

Database for clickhouse jdbc connections. - *

It has list of database urls. - * For every {@link #getConnection() getConnection} invocation, it returns connection to random host from the list. - * Furthermore, this class has method {@link #scheduleActualization(int, TimeUnit) scheduleActualization} - * which test hosts for availability. By default, this option is turned off. - */ -public class BalancedClickhouseDataSource implements DataSource { - private static final Logger log = LoggerFactory.getLogger(BalancedClickhouseDataSource.class); - private static final Pattern URL_TEMPLATE = Pattern.compile(JDBC_CLICKHOUSE_PREFIX + "" + - "//([a-zA-Z0-9_\\[\\]:,.-]+)" + - "(/[a-zA-Z0-9_]+" + - "([?][a-zA-Z0-9_]+[=][a-zA-Z0-9_]+([&][a-zA-Z0-9_]+[=][a-zA-Z0-9_]+)*)?" + - ")?"); - - private PrintWriter printWriter; - private int loginTimeoutSeconds = 0; - - private final ThreadLocal randomThreadLocal = new ThreadLocal(); - private final List allUrls; - private volatile List enabledUrls; - - private final ClickHouseProperties properties; - private final ClickHouseDriver driver = new ClickHouseDriver(); - - /** - * create Datasource for clickhouse JDBC connections - * - * @param url address for connection to the database - * must have the next format {@code jdbc:clickhouse://:,:/?param1=value1¶m2=value2 } - * for example, {@code jdbc:clickhouse://localhost:8123,localhost:8123/database?compress=1&decompress=2 } - * @throws IllegalArgumentException if param have not correct format, or error happens when checking host availability - */ - public BalancedClickhouseDataSource(final String url) { - this(splitUrl(url), getFromUrl(url)); - } - - /** - * create Datasource for clickhouse JDBC connections - * - * @param url address for connection to the database - * @param properties database properties - * @see #BalancedClickhouseDataSource(String) - */ - public BalancedClickhouseDataSource(final String url, Properties properties) { - this(splitUrl(url), new ClickHouseProperties(properties)); - } - - /** - * create Datasource for clickhouse JDBC connections - * - * @param url address for connection to the database - * @param properties database properties - * @see #BalancedClickhouseDataSource(String) - */ - public BalancedClickhouseDataSource(final String url, ClickHouseProperties properties) { - this(splitUrl(url), properties.merge(getFromUrlWithoutDefault(url))); - } - - private BalancedClickhouseDataSource(final List urls) { - this(urls, new ClickHouseProperties()); - } - - private BalancedClickhouseDataSource(final List urls, Properties info) { - this(urls, new ClickHouseProperties(info)); - } - - private BalancedClickhouseDataSource(final List urls, ClickHouseProperties properties) { - if (urls.isEmpty()) { - throw new IllegalArgumentException("Incorrect ClickHouse jdbc url list. It must be not empty"); - } - - try { - ClickHouseProperties localProperties = ClickhouseJdbcUrlParser.parse(urls.get(0), properties.asProperties()); - localProperties.setHost(null); - localProperties.setPort(-1); - - this.properties = localProperties; - } catch (URISyntaxException e) { - throw new IllegalArgumentException(e); - } - - - List allUrls = new ArrayList(urls.size()); - for (final String url : urls) { - try { - if (driver.acceptsURL(url)) { - allUrls.add(url); - } else { - log.error("that url is has not correct format: %s", url); - } - } catch (SQLException e) { - throw new IllegalArgumentException("error while checking url: " + url, e); - } - } - - if (allUrls.isEmpty()) { - throw new IllegalArgumentException("there are no correct urls"); - } - - this.allUrls = Collections.unmodifiableList(allUrls); - this.enabledUrls = this.allUrls; - } - - static List splitUrl(final String url) { - Matcher m = URL_TEMPLATE.matcher(url); - if (!m.matches()) { - throw new IllegalArgumentException("Incorrect url"); - } - String database = m.group(2); - if (database == null) { - database = ""; - } - String[] hosts = m.group(1).split(","); - final List result = new ArrayList(hosts.length); - for (final String host : hosts) { - result.add(JDBC_CLICKHOUSE_PREFIX + "//" + host + database); - } - return result; - } - - - private boolean ping(final String url) { - try { - driver.connect(url, properties).createStatement().execute("SELECT 1"); - return true; - } catch (Exception e) { - log.debug("Unable to connect using %s", url, e); - return false; - } - } - - /** - * Checks if clickhouse on url is alive, if it isn't, disable url, else enable. - * - * @return number of avaliable clickhouse urls - */ - public synchronized int actualize() { - List enabledUrls = new ArrayList(allUrls.size()); - - for (String url : allUrls) { - log.debug("Pinging disabled url: %s", url); - if (ping(url)) { - log.debug("Url is alive now: %s", url); - enabledUrls.add(url); - } else { - log.debug("Url is dead now: %s", url); - } - } - - this.enabledUrls = Collections.unmodifiableList(enabledUrls); - return enabledUrls.size(); - } - - - private String getAnyUrl() throws SQLException { - List localEnabledUrls = enabledUrls; - if (localEnabledUrls.isEmpty()) { - throw new SQLException("Unable to get connection: there are no enabled urls"); - } - Random random = this.randomThreadLocal.get(); - if (random == null) { - this.randomThreadLocal.set(new Random()); - random = this.randomThreadLocal.get(); - } - - int index = random.nextInt(localEnabledUrls.size()); - return localEnabledUrls.get(index); - } - - /** - * {@inheritDoc} - */ - @Override - public ClickHouseConnection getConnection() throws SQLException { - return driver.connect(getAnyUrl(), properties); - } - - /** - * {@inheritDoc} - */ - @Override - public ClickHouseConnection getConnection(String username, String password) throws SQLException { - return driver.connect(getAnyUrl(), properties.withCredentials(username, password)); - } - - /** - * {@inheritDoc} - */ - @Override - public T unwrap(Class iface) throws SQLException { - if (iface.isAssignableFrom(getClass())) { - return iface.cast(this); - } - throw new SQLException("Cannot unwrap to " + iface.getName()); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isWrapperFor(Class iface) throws SQLException { - return iface.isAssignableFrom(getClass()); - } - - /** - * {@inheritDoc} - */ - @Override - public PrintWriter getLogWriter() throws SQLException { - return printWriter; - } - - /** - * {@inheritDoc} - */ - @Override - public void setLogWriter(PrintWriter printWriter) throws SQLException { - this.printWriter = printWriter; - } - - /** - * {@inheritDoc} - */ - @Override - public void setLoginTimeout(int seconds) throws SQLException { -// throw new SQLFeatureNotSupportedException(); - loginTimeoutSeconds = seconds; - } - - /** - * {@inheritDoc} - */ - @Override - public int getLoginTimeout() throws SQLException { - return loginTimeoutSeconds; - } - - /** - * {@inheritDoc} - */ - public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException { - throw new SQLFeatureNotSupportedException(); - } - - /** - * set time period of removing connections - * - * @param rate value for time unit - * @param timeUnit time unit for checking - * @return this datasource with changed settings - * @see ClickHouseDriver#scheduleConnectionsCleaning - */ - public BalancedClickhouseDataSource withConnectionsCleaning(int rate, TimeUnit timeUnit) { - driver.scheduleConnectionsCleaning(rate, timeUnit); - return this; - } - - /** - * set time period for checking availability connections - * - * @param delay value for time unit - * @param timeUnit time unit for checking - * @return this datasource with changed settings - */ - public BalancedClickhouseDataSource scheduleActualization(int delay, TimeUnit timeUnit) { - ClickHouseDriver.ScheduledConnectionCleaner.INSTANCE.scheduleWithFixedDelay(new Runnable() { - @Override - public void run() { - try { - actualize(); - } catch (Exception e) { - log.error("Unable to actualize urls", e); - } - } - }, 0, delay, timeUnit); - - return this; - } - - public List getAllClickhouseUrls() { - return allUrls; - } - - public List getEnabledClickHouseUrls() { - return enabledUrls; - } - - public List getDisabledUrls() { - List enabledUrls = this.enabledUrls; - if (!hasDisabledUrls()) { - return Collections.emptyList(); - } - List disabledUrls = new ArrayList(allUrls); - disabledUrls.removeAll(enabledUrls); - return disabledUrls; - } - - public boolean hasDisabledUrls() { - return allUrls.size() != enabledUrls.size(); - } - - public ClickHouseProperties getProperties() { - return properties; - } - - private static ClickHouseProperties getFromUrl(String url) { - return new ClickHouseProperties(getFromUrlWithoutDefault(url)); - } - - private static Properties getFromUrlWithoutDefault(String url) { - if (ClickHouseChecker.isNullOrBlank(url)) - return new Properties(); - - int index = url.indexOf("?"); - if (index == -1) - return new Properties(); - - return ClickhouseJdbcUrlParser.parseUriQueryPart(url.substring(index + 1), new Properties()); - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/BodyEntityWrapper.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/BodyEntityWrapper.java deleted file mode 100644 index 0b7cb8861..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/BodyEntityWrapper.java +++ /dev/null @@ -1,51 +0,0 @@ -package ru.yandex.clickhouse; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.charset.StandardCharsets; - -import org.apache.http.HttpEntity; -import org.apache.http.entity.AbstractHttpEntity; -import org.apache.http.entity.StringEntity; - -/** - * Allow to inject sql query in the body, followed by row data - */ -public class BodyEntityWrapper extends AbstractHttpEntity { - private final StringEntity sql; - private final HttpEntity delegate; - - public BodyEntityWrapper(String sql, HttpEntity content) { - this.sql = new StringEntity(sql+"\n", StandardCharsets.UTF_8); - this.delegate = content; - } - - @Override - public boolean isRepeatable() { - return delegate.isRepeatable(); - } - - @Override - public long getContentLength() { - return -1; - } - - @Override - public InputStream getContent() throws IOException, UnsupportedOperationException { - throw new UnsupportedOperationException(); - } - - @Override - public void writeTo(OutputStream outstream) throws IOException { - sql.writeTo(outstream); - delegate.writeTo(outstream); - outstream.flush(); - } - - @Override - public boolean isStreaming() { - return delegate.isStreaming(); - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseArray.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseArray.java deleted file mode 100644 index bcb3f994f..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseArray.java +++ /dev/null @@ -1,87 +0,0 @@ -package ru.yandex.clickhouse; - -import java.sql.Array; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; -import java.util.Map; - -import ru.yandex.clickhouse.domain.ClickHouseDataType; - -/** - * @author Dmitry Andreev - */ -public class ClickHouseArray implements Array { - - private ClickHouseDataType elementType; - private Object array; - - public ClickHouseArray(ClickHouseDataType elementType, Object array) { - if (array == null) { - throw new IllegalArgumentException("array cannot be null"); - } - if (!array.getClass().isArray()) { - throw new IllegalArgumentException("not array"); - } - this.elementType = elementType; - this.array = array; - } - - @Override - public String getBaseTypeName() throws SQLException { - return elementType.name(); - } - - @Override - public int getBaseType() throws SQLException { - return elementType.getSqlType(); - } - - @Override - public Object getArray() throws SQLException { - if (array == null){ - throw new SQLException("Call after free"); - } - return array; - } - - @Override - public Object getArray(Map> map) throws SQLException { - return getArray(); - } - - @Override - public Object getArray(long index, int count) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public Object getArray(long index, int count, Map> map) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public ResultSet getResultSet() throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public ResultSet getResultSet(Map> map) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public ResultSet getResultSet(long index, int count) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public ResultSet getResultSet(long index, int count, Map> map) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public void free() throws SQLException { - array = null; - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseConnection.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseConnection.java deleted file mode 100644 index 78a9cb12f..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseConnection.java +++ /dev/null @@ -1,20 +0,0 @@ -package ru.yandex.clickhouse; - -import java.sql.Connection; -import java.sql.SQLException; -import java.util.TimeZone; - - -public interface ClickHouseConnection extends Connection { - TimeZone getServerTimeZone(); - - TimeZone getTimeZone(); - - @Override - ClickHouseStatement createStatement() throws SQLException; - - @Override - ClickHouseStatement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException; - - String getServerVersion() throws SQLException; -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseConnectionImpl.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseConnectionImpl.java deleted file mode 100644 index 96bcf7da6..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseConnectionImpl.java +++ /dev/null @@ -1,537 +0,0 @@ -package ru.yandex.clickhouse; - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.sql.Array; -import java.sql.Blob; -import java.sql.CallableStatement; -import java.sql.Clob; -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.NClob; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLClientInfoException; -import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; -import java.sql.SQLWarning; -import java.sql.SQLXML; -import java.sql.Savepoint; -import java.sql.Statement; -import java.sql.Struct; -import java.util.Collections; -import java.util.Map; -import java.util.Properties; -import java.util.TimeZone; -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; - -import com.clickhouse.client.logging.Logger; -import com.clickhouse.client.logging.LoggerFactory; - -import org.apache.http.conn.ConnectTimeoutException; -import org.apache.http.impl.client.CloseableHttpClient; - -import ru.yandex.clickhouse.domain.ClickHouseDataType; -import ru.yandex.clickhouse.except.ClickHouseUnknownException; -import ru.yandex.clickhouse.settings.ClickHouseConnectionSettings; -import ru.yandex.clickhouse.settings.ClickHouseProperties; -import ru.yandex.clickhouse.settings.ClickHouseQueryParam; -import ru.yandex.clickhouse.util.ClickHouseHttpClientBuilder; -import ru.yandex.clickhouse.util.LogProxy; -import ru.yandex.clickhouse.util.Utils; - -public class ClickHouseConnectionImpl implements ClickHouseConnection { - - private static final int DEFAULT_RESULTSET_TYPE = ResultSet.TYPE_FORWARD_ONLY; - - private static final Logger log = LoggerFactory.getLogger(ClickHouseConnectionImpl.class); - - private final CloseableHttpClient httpclient; - - private final ClickHouseProperties properties; - - private String url; - - private boolean closed = false; - - private TimeZone serverTimeZone; - private TimeZone timezone; - private String serverVersion; - - public ClickHouseConnectionImpl(String url) throws SQLException { - this(url, new ClickHouseProperties()); - } - - public ClickHouseConnectionImpl(String url, ClickHouseProperties properties) throws SQLException { - this.url = url; - try { - this.properties = ClickhouseJdbcUrlParser.parse(url, properties.asProperties()); - } catch (URISyntaxException e) { - throw new IllegalArgumentException(e); - } - ClickHouseHttpClientBuilder clientBuilder = new ClickHouseHttpClientBuilder(this.properties); - log.debug("Create a new connection to %s", url); - try { - httpclient = clientBuilder.buildClient(); - }catch (Exception e) { - throw new IllegalStateException("cannot initialize http client", e); - } - initConnection(this.properties); - } - - private void initConnection(ClickHouseProperties properties) throws SQLException { - // timezone - if (properties.isUseServerTimeZone() && !Utils.isNullOrEmptyString(properties.getUseTimeZone())) { - throw new IllegalArgumentException(String.format("only one of %s or %s must be enabled", ClickHouseConnectionSettings.USE_SERVER_TIME_ZONE.getKey(), ClickHouseConnectionSettings.USE_TIME_ZONE.getKey())); - } - if (!properties.isUseServerTimeZone() && Utils.isNullOrEmptyString(properties.getUseTimeZone())) { - throw new IllegalArgumentException(String.format("one of %s or %s must be enabled", ClickHouseConnectionSettings.USE_SERVER_TIME_ZONE.getKey(), ClickHouseConnectionSettings.USE_TIME_ZONE.getKey())); - } - - serverTimeZone = TimeZone.getTimeZone("UTC"); // just for next query - timezone = serverTimeZone; - serverVersion = ""; - - try (ClickHouseStatement s = createStatement(); - ResultSet rs = s.executeQuery("select timezone(), version()", - Collections.singletonMap(ClickHouseQueryParam.DATABASE, ""))) { - if (rs.next()) { - serverTimeZone = TimeZone.getTimeZone(rs.getString(1)); - serverVersion = rs.getString(2); - } - } - - timezone = serverTimeZone; - if (!properties.isUseServerTimeZone()) { - timezone = Utils.isNullOrEmptyString(properties.getUseTimeZone()) - ? TimeZone.getDefault() - : TimeZone.getTimeZone(properties.getUseTimeZone()); - } - - if (serverVersion == null) { - serverVersion = ""; - } - } - - @Override - public ClickHouseStatement createStatement() throws SQLException { - return createStatement(DEFAULT_RESULTSET_TYPE); - } - - public ClickHouseStatement createStatement(int resultSetType) throws SQLException { - return LogProxy.wrap( - ClickHouseStatement.class, - new ClickHouseStatementImpl( - httpclient, - this, - properties, - resultSetType)); - } - - @Override - public TimeZone getTimeZone() { - return timezone; - } - - @Override - public TimeZone getServerTimeZone() { - return serverTimeZone; - } - - private ClickHouseStatement createClickHouseStatement(CloseableHttpClient httpClient) throws SQLException { - return LogProxy.wrap( - ClickHouseStatement.class, - new ClickHouseStatementImpl( - httpClient, - this, - properties, - DEFAULT_RESULTSET_TYPE)); - } - - public PreparedStatement createPreparedStatement(String sql, int resultSetType) throws SQLException { - return LogProxy.wrap( - PreparedStatement.class, - new ClickHousePreparedStatementImpl( - httpclient, - this, - properties, - sql, - getTimeZone(), - resultSetType)); - } - - public ClickHousePreparedStatement createClickHousePreparedStatement(String sql, int resultSetType) throws SQLException { - return LogProxy.wrap( - ClickHousePreparedStatement.class, - new ClickHousePreparedStatementImpl( - httpclient, - this, - properties, - sql, - getTimeZone(), - resultSetType)); - } - - - @Override - public ClickHouseStatement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { - return createStatement(resultSetType, resultSetConcurrency, ResultSet.CLOSE_CURSORS_AT_COMMIT); - } - - /** - * lazily calculates and returns server version - * @return server version string - * @throws SQLException if something has gone wrong - */ - @Override - public String getServerVersion() throws SQLException { - return serverVersion; - } - - @Override - public ClickHouseStatement createStatement(int resultSetType, int resultSetConcurrency, - int resultSetHoldability) throws SQLException { - if (resultSetType == ResultSet.TYPE_SCROLL_SENSITIVE || resultSetConcurrency != ResultSet.CONCUR_READ_ONLY - || resultSetHoldability != ResultSet.CLOSE_CURSORS_AT_COMMIT) { - throw new SQLFeatureNotSupportedException(); - } - return createStatement(resultSetType); - } - - @Override - public PreparedStatement prepareStatement(String sql) throws SQLException { - return createPreparedStatement(sql, DEFAULT_RESULTSET_TYPE); - } - - @Override - public CallableStatement prepareCall(String sql) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public String nativeSQL(String sql) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public void setAutoCommit(boolean autoCommit) throws SQLException { - if (autoCommit) { - return; - } - throw new SQLFeatureNotSupportedException("Transactions are not supported"); - } - - @Override - public boolean getAutoCommit() throws SQLException { - return true; - } - - @Override - public void commit() throws SQLException { - throw new SQLException("Cannot commit when auto-commit is enabled"); - } - - @Override - public void rollback() throws SQLException { - throw new SQLException("Cannot rollback when auto-commit is enabled"); - } - - @Override - public void close() throws SQLException { - try { - httpclient.close(); - closed = true; - } catch (IOException e) { - throw new ClickHouseUnknownException("HTTP client close exception", e, properties.getHost(), properties.getPort()); - } - } - - @Override - public boolean isClosed() throws SQLException { - return closed; - } - - @Override - public DatabaseMetaData getMetaData() throws SQLException { - return LogProxy.wrap(DatabaseMetaData.class, new ClickHouseDatabaseMetadata(url, this)); - } - - @Override - public void setReadOnly(boolean readOnly) throws SQLException { - - } - - @Override - public boolean isReadOnly() throws SQLException { - return false; - } - - @Override - public void setCatalog(String catalog) throws SQLException { - properties.setDatabase(catalog); - URI old = URI.create(url.substring(ClickhouseJdbcUrlParser.JDBC_PREFIX.length())); - try { - url = ClickhouseJdbcUrlParser.JDBC_PREFIX + - new URI(old.getScheme(), old.getUserInfo(), old.getHost(), old.getPort(), - "/" + catalog, old.getQuery(), old.getFragment()); - } catch (URISyntaxException e) { - throw new IllegalStateException(e); - } - } - - @Override - public String getCatalog() throws SQLException { - return properties.getDatabase(); - } - - @Override - public void setTransactionIsolation(int level) throws SQLException { - - } - - @Override - public int getTransactionIsolation() throws SQLException { - return Connection.TRANSACTION_NONE; - } - - @Override - public SQLWarning getWarnings() throws SQLException { - return null; - } - - @Override - public void clearWarnings() throws SQLException { - - } - - - @Override - public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { - return createPreparedStatement(sql, resultSetType); - } - - @Override - public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public Map> getTypeMap() throws SQLException { - return null; - } - - @Override - public void setTypeMap(Map> map) throws SQLException { - - } - - @Override - public void setHoldability(int holdability) throws SQLException { - - } - - @Override - public int getHoldability() throws SQLException { - return 0; - } - - @Override - public Savepoint setSavepoint() throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public Savepoint setSavepoint(String name) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public void rollback(Savepoint savepoint) throws SQLException { - - } - - @Override - public void releaseSavepoint(Savepoint savepoint) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - return createPreparedStatement(sql, resultSetType); - } - - @Override - public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public Clob createClob() throws SQLException { - return null; - } - - @Override - public Blob createBlob() throws SQLException { - return null; - } - - @Override - public NClob createNClob() throws SQLException { - return null; - } - - @Override - public SQLXML createSQLXML() throws SQLException { - return null; - } - - @Override - public boolean isValid(int timeout) throws SQLException { - if (timeout < 0) { - throw new SQLException("Timeout value mustn't be less 0"); - } - - if (isClosed()) { - return false; - } - - boolean isAnotherHttpClient = false; - CloseableHttpClient closeableHttpClient = null; - try { - if (timeout == 0) { - closeableHttpClient = this.httpclient; - } else { - ClickHouseProperties properties = new ClickHouseProperties(this.properties); - int timeoutMs = (int) TimeUnit.SECONDS.toMillis(timeout); - properties.setConnectionTimeout(timeoutMs); - properties.setMaxExecutionTime(timeout); - properties.setSocketTimeout(timeoutMs); - closeableHttpClient = new ClickHouseHttpClientBuilder(properties).buildClient(); - isAnotherHttpClient = true; - } - - Statement statement = createClickHouseStatement(closeableHttpClient); - statement.execute("SELECT 1"); - statement.close(); - return true; - } catch (Exception e) { - boolean isFailOnConnectionTimeout = - e instanceof ConnectTimeoutException - || e.getCause() instanceof ConnectTimeoutException; - - if (!isFailOnConnectionTimeout) { - log.warn("Something had happened while validating a connection", e); - } - - return false; - } finally { - if (isAnotherHttpClient) { - try { - closeableHttpClient.close(); - } catch (IOException e) { - log.warn("Can't close a http client", e); - } - } - } - } - - @Override - public void setClientInfo(String name, String value) throws SQLClientInfoException { - - } - - @Override - public void setClientInfo(Properties properties) throws SQLClientInfoException { - - } - - @Override - public String getClientInfo(String name) throws SQLException { - return null; - } - - @Override - public Properties getClientInfo() throws SQLException { - return null; - } - - @Override - public Array createArrayOf(String typeName, Object[] elements) throws SQLException { - return new ClickHouseArray( - ClickHouseDataType.resolveDefaultArrayDataType(typeName), - elements); - } - - @Override - public Struct createStruct(String typeName, Object[] attributes) throws SQLException { - return null; - } - - @Override - public T unwrap(Class iface) throws SQLException { - if (iface.isAssignableFrom(getClass())) { - return iface.cast(this); - } - throw new SQLException("Cannot unwrap to " + iface.getName()); - } - - @Override - public boolean isWrapperFor(Class iface) throws SQLException { - return iface.isAssignableFrom(getClass()); - } - - @Override - public void setSchema(String schema) throws SQLException { - properties.setDatabase(schema); - } - - @Override - public String getSchema() throws SQLException { - return properties.getDatabase(); - } - - @Override - public void abort(Executor executor) throws SQLException { - this.close(); - } - - @Override - public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { - - } - - @Override - public int getNetworkTimeout() throws SQLException { - return 0; - } - - void cleanConnections() { - httpclient.getConnectionManager().closeExpiredConnections(); - httpclient.getConnectionManager().closeIdleConnections(2 * properties.getSocketTimeout(), TimeUnit.MILLISECONDS); - } - - String getUrl() { - return url; - } - - ClickHouseProperties getProperties() { - return properties; - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseDataSource.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseDataSource.java deleted file mode 100644 index 5fbb8a5d5..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseDataSource.java +++ /dev/null @@ -1,121 +0,0 @@ -package ru.yandex.clickhouse; - -import ru.yandex.clickhouse.settings.ClickHouseProperties; - -import javax.sql.DataSource; -import java.io.PrintWriter; -import java.net.URISyntaxException; -import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; -import java.util.Properties; -import java.util.concurrent.TimeUnit; -import java.util.logging.Logger; - - -public class ClickHouseDataSource implements DataSource { - protected final ClickHouseDriver driver = new ClickHouseDriver(); - protected final String url; - protected PrintWriter printWriter; - protected int loginTimeoutSeconds = 0; - private ClickHouseProperties properties; - - public ClickHouseDataSource(String url) { - this(url, new ClickHouseProperties()); - } - - public ClickHouseDataSource(String url, Properties info) { - this(url, new ClickHouseProperties(info)); - } - - public ClickHouseDataSource(String url, ClickHouseProperties properties) { - if (url == null) { - throw new IllegalArgumentException("Incorrect ClickHouse jdbc url. It must be not null"); - } - this.url = url; - try { - this.properties = ClickhouseJdbcUrlParser.parse(url, properties.asProperties()); - } catch (URISyntaxException e) { - throw new IllegalArgumentException(e); - } - } - - @Override - public ClickHouseConnection getConnection() throws SQLException { - return driver.connect(url, properties); - } - - @Override - public ClickHouseConnection getConnection(String username, String password) throws SQLException { - return driver.connect(url, properties.withCredentials(username, password)); - } - - public String getHost() { - return properties.getHost(); - } - - public int getPort() { - return properties.getPort(); - } - - public String getDatabase() { - return properties.getDatabase(); - } - - public String getUrl() { - return url; - } - - public ClickHouseProperties getProperties() { - return properties; - } - - @Override - public PrintWriter getLogWriter() throws SQLException { - return printWriter; - } - - @Override - public void setLogWriter(PrintWriter out) throws SQLException { - printWriter = out; - } - - @Override - public void setLoginTimeout(int seconds) throws SQLException { - loginTimeoutSeconds = seconds; - } - - @Override - public int getLoginTimeout() throws SQLException { - return loginTimeoutSeconds; - } - - public Logger getParentLogger() throws SQLFeatureNotSupportedException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public T unwrap(Class iface) throws SQLException { - if (iface.isAssignableFrom(getClass())) { - return iface.cast(this); - } - throw new SQLException("Cannot unwrap to " + iface.getName()); - } - - @Override - public boolean isWrapperFor(Class iface) throws SQLException { - return iface.isAssignableFrom(getClass()); - } - - /** - * Schedules connections cleaning at a rate. Turned off by default. - * See https://hc.apache.org/httpcomponents-client-4.5.x/tutorial/html/connmgmt.html#d5e418 - * - * @param rate period when checking would be performed - * @param timeUnit time unit of rate - * @return current modified object - */ - public ClickHouseDataSource withConnectionsCleaning(int rate, TimeUnit timeUnit){ - driver.scheduleConnectionsCleaning(rate, timeUnit); - return this; - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseDatabaseMetadata.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseDatabaseMetadata.java deleted file mode 100644 index e734d8484..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseDatabaseMetadata.java +++ /dev/null @@ -1,1337 +0,0 @@ -package ru.yandex.clickhouse; - -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.ResultSet; -import java.sql.RowIdLifetime; -import java.sql.SQLException; -import java.sql.Statement; -import java.sql.Types; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - -import com.clickhouse.client.ClickHouseVersion; -import com.clickhouse.client.logging.Logger; -import com.clickhouse.client.logging.LoggerFactory; - -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; -import ru.yandex.clickhouse.response.ClickHouseResultBuilder; - - -public class ClickHouseDatabaseMetadata implements DatabaseMetaData { - - static final String DEFAULT_CAT = "default"; - - private static final Logger log = LoggerFactory.getLogger(ClickHouseDatabaseMetadata.class); - - private final String url; - private final ClickHouseConnection connection; - - public ClickHouseDatabaseMetadata(String url, ClickHouseConnection connection) { - this.url = url; - this.connection = connection; - } - - @Override - public boolean allProceduresAreCallable() throws SQLException { - return true; - } - - @Override - public boolean allTablesAreSelectable() throws SQLException { - return true; - } - - @Override - public String getURL() throws SQLException { - return url; - } - - @Override - public String getUserName() throws SQLException { - return null; - } - - @Override - public boolean isReadOnly() throws SQLException { - return true; - } - - @Override - public boolean nullsAreSortedHigh() throws SQLException { - return true; - } - - @Override - public boolean nullsAreSortedLow() throws SQLException { - return false; - } - - @Override - public boolean nullsAreSortedAtStart() throws SQLException { - return true; - } - - @Override - public boolean nullsAreSortedAtEnd() throws SQLException { - return false; - } - - @Override - public String getDatabaseProductName() throws SQLException { - return "ClickHouse"; - } - - @Override - public String getDatabaseProductVersion() throws SQLException { - return connection.getServerVersion(); - } - - @Override - public String getDriverName() throws SQLException { - return "ru.yandex.clickhouse-jdbc"; - } - - @Override - public String getDriverVersion() throws SQLException { - String driverVersion = getClass().getPackage().getImplementationVersion(); - return driverVersion != null ? driverVersion : "0.1"; - } - - @Override - public int getDriverMajorVersion() { - String v; - try { - v = getDriverVersion(); - } catch (SQLException sqle) { - log.warn("Error determining driver major version", sqle); - return 0; - } - return ClickHouseVersion.of(v).getMajorVersion(); - } - - @Override - public int getDriverMinorVersion() { - String v; - try { - v = getDriverVersion(); - } catch (SQLException sqle) { - log.warn("Error determining driver minor version", sqle); - return 0; - } - return ClickHouseVersion.of(v).getMinorVersion(); - } - - @Override - public boolean usesLocalFiles() throws SQLException { - return false; - } - - @Override - public boolean usesLocalFilePerTable() throws SQLException { - return false; - } - - @Override - public boolean supportsMixedCaseIdentifiers() throws SQLException { - return true; - } - - @Override - public boolean storesUpperCaseIdentifiers() throws SQLException { - return false; - } - - @Override - public boolean storesLowerCaseIdentifiers() throws SQLException { - return false; - } - - @Override - public boolean storesMixedCaseIdentifiers() throws SQLException { - return true; - } - - @Override - public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException { - return true; - } - - @Override - public boolean storesUpperCaseQuotedIdentifiers() throws SQLException { - return false; - } - - @Override - public boolean storesLowerCaseQuotedIdentifiers() throws SQLException { - return false; - } - - @Override - public boolean storesMixedCaseQuotedIdentifiers() throws SQLException { - return true; - } - - @Override - public String getIdentifierQuoteString() throws SQLException { - return "`"; - } - - @Override - public String getSQLKeywords() throws SQLException { - return "GLOBAL,ARRAY"; - } - - @Override - public String getNumericFunctions() throws SQLException { - return ""; - } - - @Override - public String getStringFunctions() throws SQLException { - return ""; - } - - @Override - public String getSystemFunctions() throws SQLException { - return ""; - } - - @Override - public String getTimeDateFunctions() throws SQLException { - return ""; - } - - @Override - public String getSearchStringEscape() throws SQLException { - return "\\"; - } - - @Override - public String getExtraNameCharacters() throws SQLException { - return ""; - } - - @Override - public boolean supportsAlterTableWithAddColumn() throws SQLException { - return true; - } - - @Override - public boolean supportsAlterTableWithDropColumn() throws SQLException { - return true; - } - - @Override - public boolean supportsColumnAliasing() throws SQLException { - return true; - } - - @Override - public boolean nullPlusNonNullIsNull() throws SQLException { - return true; - } - - @Override - public boolean supportsConvert() throws SQLException { - return false; - } - - @Override - public boolean supportsConvert(int fromType, int toType) throws SQLException { - return false; - } - - @Override - public boolean supportsTableCorrelationNames() throws SQLException { - return false; - } - - @Override - public boolean supportsDifferentTableCorrelationNames() throws SQLException { - return false; - } - - @Override - public boolean supportsExpressionsInOrderBy() throws SQLException { - return true; - } - - @Override - public boolean supportsOrderByUnrelated() throws SQLException { - return true; - } - - @Override - public boolean supportsGroupBy() throws SQLException { - return true; - } - - @Override - public boolean supportsGroupByUnrelated() throws SQLException { - return true; - } - - @Override - public boolean supportsGroupByBeyondSelect() throws SQLException { - return true; - } - - @Override - public boolean supportsLikeEscapeClause() throws SQLException { - return true; - } - - @Override - public boolean supportsMultipleResultSets() throws SQLException { - return false; - } - - @Override - public boolean supportsMultipleTransactions() throws SQLException { - return false; - } - - @Override - public boolean supportsNonNullableColumns() throws SQLException { - return true; - } - - @Override - public boolean supportsMinimumSQLGrammar() throws SQLException { - return false; - } - - @Override - public boolean supportsCoreSQLGrammar() throws SQLException { - return false; - } - - @Override - public boolean supportsExtendedSQLGrammar() throws SQLException { - return false; - } - - @Override - public boolean supportsANSI92EntryLevelSQL() throws SQLException { - return false; - } - - @Override - public boolean supportsANSI92IntermediateSQL() throws SQLException { - return false; - } - - @Override - public boolean supportsANSI92FullSQL() throws SQLException { - return false; - } - - @Override - public boolean supportsIntegrityEnhancementFacility() throws SQLException { - return false; - } - - @Override - public boolean supportsOuterJoins() throws SQLException { - return true; - } - - @Override - public boolean supportsFullOuterJoins() throws SQLException { - return false; - } - - @Override - public boolean supportsLimitedOuterJoins() throws SQLException { - return true; - } - - @Override - public String getSchemaTerm() throws SQLException { - return "database"; - } - - @Override - public String getProcedureTerm() throws SQLException { - return "procedure"; - } - - @Override - public String getCatalogTerm() throws SQLException { - return "catalog"; - } - - @Override - public boolean isCatalogAtStart() throws SQLException { - return false; - } - - @Override - public String getCatalogSeparator() throws SQLException { - return "."; - } - - @Override - public boolean supportsSchemasInDataManipulation() throws SQLException { - return true; - } - - @Override - public boolean supportsSchemasInProcedureCalls() throws SQLException { - return true; - } - - @Override - public boolean supportsSchemasInTableDefinitions() throws SQLException { - return true; - } - - @Override - public boolean supportsSchemasInIndexDefinitions() throws SQLException { - return true; - } - - @Override - public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException { - return true; - } - - @Override - public boolean supportsCatalogsInDataManipulation() throws SQLException { - return false; - } - - @Override - public boolean supportsCatalogsInProcedureCalls() throws SQLException { - return false; - } - - @Override - public boolean supportsCatalogsInTableDefinitions() throws SQLException { - return false; - } - - @Override - public boolean supportsCatalogsInIndexDefinitions() throws SQLException { - return false; - } - - @Override - public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException { - return false; - } - - @Override - public boolean supportsPositionedDelete() throws SQLException { - return false; - } - - @Override - public boolean supportsPositionedUpdate() throws SQLException { - return false; - } - - @Override - public boolean supportsSelectForUpdate() throws SQLException { - return false; - } - - @Override - public boolean supportsStoredProcedures() throws SQLException { - return false; - } - - @Override - public boolean supportsSubqueriesInComparisons() throws SQLException { - return true; - } - - @Override - public boolean supportsSubqueriesInExists() throws SQLException { - return false; - } - - @Override - public boolean supportsSubqueriesInIns() throws SQLException { - return true; - } - - @Override - public boolean supportsSubqueriesInQuantifieds() throws SQLException { - return false; - } - - @Override - public boolean supportsCorrelatedSubqueries() throws SQLException { - return false; - } - - @Override - public boolean supportsUnion() throws SQLException { - return true; - } - - @Override - public boolean supportsUnionAll() throws SQLException { - return true; - } - - @Override - public boolean supportsOpenCursorsAcrossCommit() throws SQLException { - return false; - } - - @Override - public boolean supportsOpenCursorsAcrossRollback() throws SQLException { - return false; - } - - @Override - public boolean supportsOpenStatementsAcrossCommit() throws SQLException { - return false; - } - - @Override - public boolean supportsOpenStatementsAcrossRollback() throws SQLException { - return false; - } - - @Override - public int getMaxBinaryLiteralLength() throws SQLException { - return 0; - } - - @Override - public int getMaxCharLiteralLength() throws SQLException { - return 0; - } - - @Override - public int getMaxColumnNameLength() throws SQLException { - return 0; - } - - @Override - public int getMaxColumnsInGroupBy() throws SQLException { - return 0; - } - - @Override - public int getMaxColumnsInIndex() throws SQLException { - return 0; - } - - @Override - public int getMaxColumnsInOrderBy() throws SQLException { - return 0; - } - - @Override - public int getMaxColumnsInSelect() throws SQLException { - return 0; - } - - @Override - public int getMaxColumnsInTable() throws SQLException { - return 0; - } - - @Override - public int getMaxConnections() throws SQLException { - return 0; - } - - @Override - public int getMaxCursorNameLength() throws SQLException { - return 0; - } - - @Override - public int getMaxIndexLength() throws SQLException { - return 0; - } - - @Override - public int getMaxSchemaNameLength() throws SQLException { - return 0; - } - - @Override - public int getMaxProcedureNameLength() throws SQLException { - return 0; - } - - @Override - public int getMaxCatalogNameLength() throws SQLException { - return 0; - } - - @Override - public int getMaxRowSize() throws SQLException { - return 0; - } - - @Override - public boolean doesMaxRowSizeIncludeBlobs() throws SQLException { - return false; - } - - @Override - public int getMaxStatementLength() throws SQLException { - return 0; - } - - @Override - public int getMaxStatements() throws SQLException { - return 0; - } - - @Override - public int getMaxTableNameLength() throws SQLException { - return 0; - } - - @Override - public int getMaxTablesInSelect() throws SQLException { - return 0; - } - - @Override - public int getMaxUserNameLength() throws SQLException { - return 0; - } - - @Override - public int getDefaultTransactionIsolation() throws SQLException { - return Connection.TRANSACTION_NONE; - } - - @Override - public boolean supportsTransactions() throws SQLException { - return false; - } - - @Override - public boolean supportsTransactionIsolationLevel(int level) throws SQLException { - return level == Connection.TRANSACTION_NONE; - } - - @Override - public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException { - return false; - } - - @Override - public boolean supportsDataManipulationTransactionsOnly() throws SQLException { - return false; - } - - @Override - public boolean dataDefinitionCausesTransactionCommit() throws SQLException { - return false; - } - - @Override - public boolean dataDefinitionIgnoredInTransactions() throws SQLException { - return false; - } - - private ResultSet request(String sql) throws SQLException { - Statement statement = connection.createStatement(); - return statement.executeQuery(sql); - } - - @Override - public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException { - ClickHouseResultBuilder builder = ClickHouseResultBuilder.builder(9); - builder.names( - "PROCEDURE_CAT", - "PROCEDURE_SCHEM", - "PROCEDURE_NAME", - "RES_1", - "RES_2", - "RES_3", - "REMARKS", - "PROCEDURE_TYPE", - "SPECIFIC_NAME" - ); - - builder.types( - "String", - "String", - "String", - "String", - "String", - "String", - "String", - "UInt8", - "String" - ); - - return builder.build(); - } - - @Override - public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException { - ClickHouseResultBuilder builder = ClickHouseResultBuilder.builder(20); - builder.names("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"); - - builder.types("UInt32", "UInt32", "UInt32", "UInt32", "UInt32", "UInt32", "UInt32", "UInt32", "UInt32", "UInt32", "UInt32", "UInt32", "UInt32", "UInt32", "UInt32", "UInt32", "UInt32", "UInt32", "UInt32", "UInt32"); - - return builder.build(); - } - - @Override - public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) throws SQLException { - /* - TABLE_CAT String => table catalog (may be null) - TABLE_SCHEM String => table schema (may be null) - TABLE_NAME String => table name - TABLE_TYPE String => table type. Typical types are "TABLE", "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", "LOCAL TEMPORARY", "ALIAS", "SYNONYM". - REMARKS String => explanatory comment on the table - TYPE_CAT String => the types catalog (may be null) - TYPE_SCHEM String => the types schema (may be null) - TYPE_NAME String => type name (may be null) - SELF_REFERENCING_COL_NAME String => name of the designated "identifier" column of a typed table (may be null) - REF_GENERATION String => specifies how values in SELF_REFERENCING_COL_NAME are created. Values are "SYSTEM", "USER", "DERIVED". (may be null) - */ - String sql = "select " + - "database, name, engine " + - "from system.tables " + - "where 1 = 1"; - if (schemaPattern != null) { - sql += " and database like '" + schemaPattern + "'"; - } - if (tableNamePattern != null) { - sql += " and name like '" + tableNamePattern + "'"; - } - sql += " order by database, name"; - ResultSet result = request(sql); - - ClickHouseResultBuilder builder = ClickHouseResultBuilder.builder(10); - builder.names("TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "TABLE_TYPE", "REMARKS", "TYPE_CAT", "TYPE_SCHEM", "TYPE_NAME", "SELF_REFERENCING_COL_NAME", "REF_GENERATION"); - builder.types("String", "String", "String", "String", "String", "String", "String", "String", "String", "String"); - - List typeList = types != null ? Arrays.asList(types) : null; - while (result.next()) { - List row = new ArrayList<>(); - row.add(DEFAULT_CAT); - row.add(result.getString(1)); - row.add(result.getString(2)); - String type, e = result.getString(3).intern(); - if (e == "View" || e == "MaterializedView" || e == "Merge" || e == "Distributed" || e == "Null") { - type = "VIEW"; // some kind of view - } else if (e == "Set" || e == "Join" || e == "Buffer") { - type = "OTHER"; // not a real table - } else { - type = "TABLE"; - } - row.add(type); - for (int i = 3; i < 9; i++) { - row.add(null); - } - if (typeList == null || typeList.contains(type)) { - builder.addRow(row); - } - } - result.close(); - return builder.build(); - } - - @Override - public ResultSet getSchemas() throws SQLException { - return getSchemas(null, null); - } - - @Override - public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException { - String sql = "select name as TABLE_SCHEM, '" + - DEFAULT_CAT + "' as TABLE_CATALOG from system.databases"; - if (catalog != null) { - sql += " where TABLE_CATALOG = '" + catalog + '\''; - } - if (schemaPattern != null) { - if (catalog != null) { - sql += " and "; - } else { - sql += " where "; - } - sql += "name LIKE '" + schemaPattern + '\''; - } - return request(sql); - } - - @Override - public ResultSet getCatalogs() throws SQLException { - ClickHouseResultBuilder builder = ClickHouseResultBuilder.builder(1); - builder.names("TABLE_CAT"); - builder.types("String"); - - builder.addRow(DEFAULT_CAT); - return builder.build(); - } - - @Override - public ResultSet getTableTypes() throws SQLException { - ClickHouseResultBuilder builder = ClickHouseResultBuilder.builder(1); - builder.names("TABLE_TYPE"); - builder.types("String"); - - builder.addRow("TABLE"); - builder.addRow("VIEW"); - builder.addRow("OTHER"); - return builder.build(); - } - - private static void buildAndCondition(StringBuilder dest, List conditions) { - Iterator iter = conditions.iterator(); - if (iter.hasNext()) { - String entry = iter.next(); - dest.append(entry); - } - while (iter.hasNext()) { - String entry = iter.next(); - dest.append(" AND ").append(entry); - } - } - - @Override - public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { - StringBuilder query; - if (ClickHouseVersion.check(connection.getServerVersion(), "[18.16,)")) { - query = new StringBuilder( - "SELECT database, table, name, type, default_kind as default_type, default_expression, comment "); - } else { - query = new StringBuilder( - "SELECT database, table, name, type, default_kind as default_type, default_expression, NULL AS comment "); - } - query.append("FROM system.columns "); - List predicates = new ArrayList<>(); - if (schemaPattern != null) { - predicates.add("database LIKE '" + schemaPattern + "' "); - } - if (tableNamePattern != null) { - predicates.add("table LIKE '" + tableNamePattern + "' "); - } - if (columnNamePattern != null) { - predicates.add("name LIKE '" + columnNamePattern + "' "); - } - if (!predicates.isEmpty()) { - query.append(" WHERE "); - buildAndCondition(query, predicates); - } - ClickHouseResultBuilder builder = getClickHouseResultBuilderForGetColumns(); - ResultSet descTable = request(query.toString()); - int colNum = 1; - while (descTable.next()) { - List row = new ArrayList<>(); - //catalog name - row.add(DEFAULT_CAT); - //database name - row.add(descTable.getString("database")); - //table name - row.add(descTable.getString("table")); - //column name - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - descTable.getString("type"), - descTable.getString("name"), - connection.getServerTimeZone()); - row.add(columnInfo.getColumnName()); - //data type - row.add(String.valueOf(columnInfo.getClickHouseDataType().getSqlType())); - //type name - row.add(columnInfo.getCleanTypeName()); - // column size / precision - row.add(String.valueOf(columnInfo.getPrecision())); - //buffer length - row.add("0"); - // decimal digits - row.add(String.valueOf(columnInfo.getScale())); - // radix - row.add("10"); - // nullable - row.add(columnInfo.isNullable() - ? String.valueOf(columnNullable) - : String.valueOf(columnNoNulls)); - //remarks - String remarks = descTable.getString("comment"); - row.add("".equals(remarks) - ? null - : remarks); - - // COLUMN_DEF - if ("DEFAULT".equals(descTable.getString("default_type"))) { - row.add(descTable.getString("default_expression")); - } else { - row.add(null); - } - - //"SQL_DATA_TYPE", unused per JavaDoc - row.add(null); - //"SQL_DATETIME_SUB", unused per JavaDoc - row.add(null); - - // char octet length - row.add("0"); - // ordinal - row.add(String.valueOf(colNum)); - colNum += 1; - - //IS_NULLABLE - row.add(columnInfo.isNullable() - ? "YES" - : "NO"); - //"SCOPE_CATALOG", - row.add(null); - //"SCOPE_SCHEMA", - row.add(null); - //"SCOPE_TABLE", - row.add(null); - //"SOURCE_DATA_TYPE", - row.add(null); - //"IS_AUTOINCREMENT" - row.add("NO"); - //"IS_GENERATEDCOLUMN" - row.add("NO"); - - builder.addRow(row); - } - descTable.close(); - return builder.build(); - } - - private ClickHouseResultBuilder getClickHouseResultBuilderForGetColumns() { - ClickHouseResultBuilder builder = ClickHouseResultBuilder.builder(24); - builder.names( - "TABLE_CAT", - "TABLE_SCHEM", - "TABLE_NAME", - "COLUMN_NAME", - "DATA_TYPE", - "TYPE_NAME", - "COLUMN_SIZE", - "BUFFER_LENGTH", - "DECIMAL_DIGITS", - "NUM_PREC_RADIX", - "NULLABLE", - "REMARKS", - "COLUMN_DEF", - "SQL_DATA_TYPE", - "SQL_DATETIME_SUB", - "CHAR_OCTET_LENGTH", - "ORDINAL_POSITION", - "IS_NULLABLE", - "SCOPE_CATALOG", - "SCOPE_SCHEMA", - "SCOPE_TABLE", - "SOURCE_DATA_TYPE", - "IS_AUTOINCREMENT", - "IS_GENERATEDCOLUMN" - ); - builder.types( - "String", - "String", - "String", - "String", - "Int32", - "String", - "Int32", - "Int32", - "Int32", - "Int32", - "Int32", - "String", - "String", - "Int32", - "Int32", - "Int32", - "Int32", - "String", - "String", - "String", - "String", - "Int32", - "String", - "String" - ); - return builder; - } - - private ResultSet getEmptyResultSet() { - return ClickHouseResultBuilder.builder(1).names("some").types("String").build(); - } - - @Override - public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) throws SQLException { - return getEmptyResultSet(); - } - - @Override - public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { - return getEmptyResultSet(); - } - - @Override - public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) throws SQLException { - return getEmptyResultSet(); - } - - @Override - public ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException { - return getEmptyResultSet(); - } - - @Override - public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException { - return getEmptyResultSet(); - } - - @Override - public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException { - return getEmptyResultSet(); - } - - @Override - public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException { - return getEmptyResultSet(); - } - - @Override - public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException { - return getEmptyResultSet(); - } - - @Override - public ResultSet getTypeInfo() throws SQLException { - ClickHouseResultBuilder builder = ClickHouseResultBuilder.builder(18); - builder.names( - "TYPE_NAME", - "DATA_TYPE", - "PRECISION", - "LITERAL_PREFIX", - "LITERAL_SUFFIX", - "CREATE_PARAMS", - "NULLABLE", - "CASE_SENSITIVE", - "SEARCHABLE", - "UNSIGNED_ATTRIBUTE", - "FIXED_PREC_SCALE", - "AUTO_INCREMENT", - "LOCAL_TYPE_NAME", - "MINIMUM_SCALE", - "MAXIMUM_SCALE", - "SQL_DATA_TYPE", - "SQL_DATETIME_SUB", - "NUM_PREC_RADIX" - ); - builder.types( - "String", - "Int32", - "Int32", - "String", - "String", - "String", - "Int32", - "Int8", - "Int32", - "Int8", - "Int8", - "Int8", - "String", - "Int32", - "Int32", - "Int32", - "Int32", - "Int32" - ); - builder.addRow( - "String", Types.VARCHAR, - null, // precision - todo - '\'', '\'', null, - typeNoNulls, true, typeSearchable, - true, // unsigned - true, // fixed precision (money) - false, //auto-incr - null, - null, null, // scale - should be fixed - null, null, - 10 - ); - int[] sizes = { 8, 16, 32, 64 }; - boolean[] signed = { true, false }; - for (int size : sizes) { - for (boolean b: signed) { - String name = (b ? "" : "U") + "Int" + size; - builder.addRow( - name, (size <= 16 ? Types.INTEGER : Types.BIGINT), - null, // precision - todo - null, null, null, - typeNoNulls, true, typePredBasic, - !b, // unsigned - true, // fixed precision (money) - false, //auto-incr - null, - null, null, // scale - should be fixed - null, null, - 10 - ); - } - } - int[] floatSizes = { 32, 64 }; - for (int floatSize : floatSizes) { - String name = "Float" + floatSize; - builder.addRow( - name, Types.FLOAT, - null, // precision - todo - null, null, null, - typeNoNulls, true, typePredBasic, - false, // unsigned - true, // fixed precision (money) - false, //auto-incr - null, - null, null, // scale - should be fixed - null, null, - 10 - ); - } - builder.addRow( - "Date", Types.DATE, - null, // precision - todo - null, null, null, - typeNoNulls, true, typePredBasic, - false, // unsigned - true, // fixed precision (money) - false, //auto-incr - null, - null, null, // scale - should be fixed - null, null, - 10 - ); - builder.addRow( - "DateTime", Types.TIMESTAMP, - null, // precision - todo - null, null, null, - typeNoNulls, true, typePredBasic, - false, // unsigned - true, // fixed precision (money) - false, //auto-incr - null, - null, null, // scale - should be fixed - null, null, - 10 - ); - return builder.build(); - } - - @Override - public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) throws SQLException { - return getEmptyResultSet(); - } - - @Override - public boolean supportsResultSetType(int type) throws SQLException { - return ResultSet.TYPE_FORWARD_ONLY == type; - } - - @Override - public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException { - return false; - } - - @Override - public boolean ownUpdatesAreVisible(int type) throws SQLException { - return true; - } - - @Override - public boolean ownDeletesAreVisible(int type) throws SQLException { - return true; - } - - @Override - public boolean ownInsertsAreVisible(int type) throws SQLException { - return true; - } - - @Override - public boolean othersUpdatesAreVisible(int type) throws SQLException { - return true; - } - - @Override - public boolean othersDeletesAreVisible(int type) throws SQLException { - return true; - } - - @Override - public boolean othersInsertsAreVisible(int type) throws SQLException { - return true; - } - - @Override - public boolean updatesAreDetected(int type) throws SQLException { - return false; - } - - @Override - public boolean deletesAreDetected(int type) throws SQLException { - return false; - } - - @Override - public boolean insertsAreDetected(int type) throws SQLException { - return false; - } - - @Override - public boolean supportsBatchUpdates() throws SQLException { - return true; - } - - @Override - public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLException { - return getEmptyResultSet(); - } - - @Override - public Connection getConnection() throws SQLException { - return connection; - } - - @Override - public boolean supportsSavepoints() throws SQLException { - return false; - } - - @Override - public boolean supportsNamedParameters() throws SQLException { - return false; - } - - @Override - public boolean supportsMultipleOpenResults() throws SQLException { - return false; - } - - @Override - public boolean supportsGetGeneratedKeys() throws SQLException { - return false; - } - - @Override - public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException { - return getEmptyResultSet(); - } - - @Override - public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { - return getEmptyResultSet(); - } - - @Override - public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern) throws SQLException { - return getEmptyResultSet(); - } - - @Override - public boolean supportsResultSetHoldability(int holdability) throws SQLException { - return false; - } - - @Override - public int getResultSetHoldability() throws SQLException { - return 0; - } - - @Override - public int getDatabaseMajorVersion() throws SQLException { - return ClickHouseVersion.of(connection.getServerVersion()).getMajorVersion(); - } - - @Override - public int getDatabaseMinorVersion() throws SQLException { - return ClickHouseVersion.of(connection.getServerVersion()).getMinorVersion(); - } - - @Override - public int getJDBCMajorVersion() throws SQLException { - return 0; - } - - @Override - public int getJDBCMinorVersion() throws SQLException { - return 1; - } - - @Override - public int getSQLStateType() throws SQLException { - return sqlStateSQL; - } - - @Override - public boolean locatorsUpdateCopy() throws SQLException { - return false; - } - - @Override - public boolean supportsStatementPooling() throws SQLException { - return false; - } - - @Override - public RowIdLifetime getRowIdLifetime() throws SQLException { - return RowIdLifetime.ROWID_UNSUPPORTED; - } - - @Override - public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { - return false; - } - - @Override - public boolean autoCommitFailureClosesAllResultSets() throws SQLException { - return false; - } - - @Override - public ResultSet getClientInfoProperties() throws SQLException { - return getEmptyResultSet(); - } - - @Override - public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException { - return getEmptyResultSet(); - } - - @Override - public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) throws SQLException { - return getEmptyResultSet(); - } - - @Override - public T unwrap(Class iface) throws SQLException { - if (iface.isAssignableFrom(getClass())) { - return iface.cast(this); - } - throw new SQLException("Cannot unwrap to " + iface.getName()); - } - - @Override - public boolean isWrapperFor(Class iface) throws SQLException { - return iface.isAssignableFrom(getClass()); - } - - @Override - public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { - return null; - } - - @Override - public boolean generatedKeyAlwaysReturned() throws SQLException { - return false; - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseDriver.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseDriver.java deleted file mode 100644 index 129d10056..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseDriver.java +++ /dev/null @@ -1,157 +0,0 @@ -package ru.yandex.clickhouse; - -import ru.yandex.clickhouse.settings.ClickHouseConnectionSettings; -import ru.yandex.clickhouse.settings.ClickHouseProperties; -import ru.yandex.clickhouse.settings.ClickHouseQueryParam; -import ru.yandex.clickhouse.settings.DriverPropertyCreator; -import ru.yandex.clickhouse.util.LogProxy; - -import java.sql.Driver; -import java.sql.DriverManager; -import java.sql.DriverPropertyInfo; -import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.WeakHashMap; -import java.util.concurrent.*; - -import com.clickhouse.client.logging.Logger; -import com.clickhouse.client.logging.LoggerFactory; - -/** - * - * URL Format - * - * primitive for now - * - * jdbc:clickhouse://host:port - * - * for example, jdbc:clickhouse://localhost:8123 - * - */ -public class ClickHouseDriver implements Driver { - - private static final Logger log = LoggerFactory.getLogger(ClickHouseDriver.class); - - private static final Map connections = Collections.synchronizedMap(new WeakHashMap<>()); - - static { - ClickHouseDriver driver = new ClickHouseDriver(); - try { - DriverManager.registerDriver(driver); - } catch (SQLException e) { - throw new RuntimeException(e); - } - log.warn("******************************************************************************************"); - log.warn("* This driver is DEPRECATED. Please use [com.clickhouse.jdbc.ClickHouseDriver] instead. *"); - log.warn("* Also everything in package [ru.yandex.clickhouse] will be removed starting from 0.4.0. *"); - log.warn("******************************************************************************************"); - } - - @Override - public ClickHouseConnection connect(String url, Properties info) throws SQLException { - return connect(url, new ClickHouseProperties(info)); - } - - public ClickHouseConnection connect(String url, ClickHouseProperties properties) throws SQLException { - if (!acceptsURL(url)) { - return null; - } - log.debug("Creating connection"); - ClickHouseConnectionImpl connection = new ClickHouseConnectionImpl(url, properties); - registerConnection(connection); - return LogProxy.wrap(ClickHouseConnection.class, connection); - } - - private void registerConnection(ClickHouseConnectionImpl connection) { - connections.put(connection, Boolean.TRUE); - } - - @Override - public boolean acceptsURL(String url) throws SQLException { - return url.startsWith(ClickhouseJdbcUrlParser.JDBC_CLICKHOUSE_PREFIX); - } - - @Override - public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { - Properties copy = new Properties(info); - Properties properties; - try { - properties = ClickhouseJdbcUrlParser.parse(url, copy).asProperties(); - } catch (Exception ex) { - properties = copy; - log.error("could not parse url %s", url, ex); - } - List result = new ArrayList(ClickHouseQueryParam.values().length - + ClickHouseConnectionSettings.values().length); - result.addAll(dumpProperties(ClickHouseQueryParam.values(), properties)); - result.addAll(dumpProperties(ClickHouseConnectionSettings.values(), properties)); - return result.toArray(new DriverPropertyInfo[0]); - } - - private List dumpProperties(DriverPropertyCreator[] creators, Properties info) { - List result = new ArrayList(creators.length); - for (DriverPropertyCreator creator : creators) { - result.add(creator.createDriverPropertyInfo(info)); - } - return result; - } - - @Override - public int getMajorVersion() { - return 0; - } - - @Override - public int getMinorVersion() { - return 0; - } - - @Override - public boolean jdbcCompliant() { - return false; - } - - public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException { - throw new SQLFeatureNotSupportedException(); - } - - /** - * Schedules connections cleaning at a rate. Turned off by default. - * See https://hc.apache.org/httpcomponents-client-4.5.x/tutorial/html/connmgmt.html#d5e418 - * - * @param rate period when checking would be performed - * @param timeUnit time unit of rate - */ - public void scheduleConnectionsCleaning(int rate, TimeUnit timeUnit){ - ScheduledConnectionCleaner.INSTANCE.scheduleAtFixedRate(new Runnable() { - @Override - public void run() { - try { - for (ClickHouseConnectionImpl connection : connections.keySet()) { - connection.cleanConnections(); - } - } catch (Exception e){ - log.error("error evicting connections", e); - } - } - }, 0, rate, timeUnit); - } - - static class ScheduledConnectionCleaner { - static final ScheduledExecutorService INSTANCE = Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory()); - - static class DaemonThreadFactory implements ThreadFactory { - @Override - public Thread newThread(Runnable r) { - Thread thread = Executors.defaultThreadFactory().newThread(r); - thread.setDaemon(true); - return thread; - } - } - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseExternalData.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseExternalData.java deleted file mode 100644 index 5d4429414..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseExternalData.java +++ /dev/null @@ -1,89 +0,0 @@ -package ru.yandex.clickhouse; - -import java.io.InputStream; - -/** - * @author zgmnkv - */ -public class ClickHouseExternalData { - - private String name; - private InputStream content; - private String format; - private String types; - private String structure; - - public ClickHouseExternalData() { - } - - public ClickHouseExternalData(String name, InputStream content) { - this.name = name; - this.content = content; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public InputStream getContent() { - return content; - } - - public void setContent(InputStream content) { - this.content = content; - } - - public String getFormat() { - return format; - } - - public void setFormat(String format) { - this.format = format; - } - - public String getTypes() { - return types; - } - - public void setTypes(String types) { - this.types = types; - } - - public String getStructure() { - return structure; - } - - public void setStructure(String structure) { - this.structure = structure; - } - - public ClickHouseExternalData withName(String name) { - this.name = name; - return this; - } - - public ClickHouseExternalData withContent(InputStream content) { - this.content = content; - return this; - } - - public ClickHouseExternalData withFormat(String format) { - this.format = format; - return this; - } - - public ClickHouseExternalData withTypes(String types) { - this.types = types; - return this; - } - - public ClickHouseExternalData withStructure(String structure) { - this.structure = structure; - return this; - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHousePreparedStatement.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHousePreparedStatement.java deleted file mode 100644 index 03bdeb86e..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHousePreparedStatement.java +++ /dev/null @@ -1,30 +0,0 @@ -package ru.yandex.clickhouse; - -import ru.yandex.clickhouse.response.ClickHouseResponse; -import ru.yandex.clickhouse.settings.ClickHouseQueryParam; - -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Collection; -import java.util.List; -import java.util.Map; - - -public interface ClickHousePreparedStatement extends PreparedStatement, ClickHouseStatement { - ClickHouseResponse executeQueryClickhouseResponse() throws SQLException; - - ClickHouseResponse executeQueryClickhouseResponse(Map additionalDBParams) throws SQLException; - - void setArray(int parameterIndex, Collection collection) throws SQLException; - - void setArray(int parameterIndex, Object[] array) throws SQLException; - - ResultSet executeQuery(Map additionalDBParams) throws SQLException; - - ResultSet executeQuery(Map additionalDBParams, List externalData) throws SQLException; - - int[] executeBatch(Map additionalDBParams) throws SQLException; - - String asSql(); -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHousePreparedStatementImpl.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHousePreparedStatementImpl.java deleted file mode 100644 index 4aa7c3a6e..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHousePreparedStatementImpl.java +++ /dev/null @@ -1,648 +0,0 @@ -package ru.yandex.clickhouse; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Reader; -import java.math.BigDecimal; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.sql.Array; -import java.sql.Blob; -import java.sql.Clob; -import java.sql.Date; -import java.sql.NClob; -import java.sql.ParameterMetaData; -import java.sql.Ref; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.RowId; -import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; -import java.sql.SQLXML; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.TimeZone; - -import com.clickhouse.client.logging.Logger; -import com.clickhouse.client.logging.LoggerFactory; -import com.clickhouse.jdbc.parser.ClickHouseSqlStatement; -import com.clickhouse.jdbc.parser.StatementType; - -import org.apache.http.entity.AbstractHttpEntity; -import org.apache.http.impl.client.CloseableHttpClient; - -import ru.yandex.clickhouse.response.ClickHouseResponse; -import ru.yandex.clickhouse.settings.ClickHouseProperties; -import ru.yandex.clickhouse.settings.ClickHouseQueryParam; -import ru.yandex.clickhouse.util.ClickHouseArrayUtil; -import ru.yandex.clickhouse.util.ClickHouseValueFormatter; - -public class ClickHousePreparedStatementImpl extends ClickHouseStatementImpl implements ClickHousePreparedStatement { - private static final Logger log = LoggerFactory.getLogger(ClickHousePreparedStatementImpl.class); - - static final String PARAM_MARKER = "?"; - static final String NULL_MARKER = "\\N"; - - private final TimeZone dateTimeZone; - private final TimeZone dateTimeTimeZone; - private final ClickHouseSqlStatement parsedStmt; - private final List sqlParts; - private final ClickHousePreparedStatementParameter[] binds; - private final List> parameterList; - private final boolean insertBatchMode; - private List batchRows = new ArrayList<>(); - - public ClickHousePreparedStatementImpl(CloseableHttpClient client, - ClickHouseConnection connection, ClickHouseProperties properties, String sql, - TimeZone serverTimeZone, int resultSetType) throws SQLException - { - super(client, connection, properties, resultSetType); - parseSqlStatements(sql); - - if (parsedStmts.length != 1) { - throw new IllegalArgumentException("Only single statement is supported"); - } - - parsedStmt = parsedStmts[0]; - - PreparedStatementParser parser = PreparedStatementParser.parse(sql, - parsedStmt.getEndPosition(ClickHouseSqlStatement.KEYWORD_VALUES)); - this.parameterList = parser.getParameters(); - this.insertBatchMode = parser.isValuesMode(); - this.sqlParts = parser.getParts(); - int numParams = countNonConstantParams(); - this.binds = new ClickHousePreparedStatementParameter[numParams]; - dateTimeTimeZone = serverTimeZone; - if (properties.isUseServerTimeZoneForDates()) { - dateTimeZone = serverTimeZone; - } else { - dateTimeZone = TimeZone.getDefault(); - } - } - - @Override - public void clearParameters() { - Arrays.fill(binds, null); - } - - @Override - public ClickHouseResponse executeQueryClickhouseResponse() throws SQLException { - return executeQueryClickhouseResponse(buildSql(), null, null); - } - - @Override - public ClickHouseResponse executeQueryClickhouseResponse(Map additionalDBParams) throws SQLException { - return executeQueryClickhouseResponse(buildSql(), additionalDBParams, null); - } - - private ClickHouseSqlStatement buildSql() throws SQLException { - if (sqlParts.size() == 1) { - return new ClickHouseSqlStatement(sqlParts.get(0), parsedStmt.getStatementType()); - } - - checkBinded(); - StringBuilder sb = new StringBuilder(sqlParts.get(0)); - for (int i = 1, p = 0; i < sqlParts.size(); i++) { - String pValue = getParameter(i - 1); - if (PARAM_MARKER.equals(pValue)) { - sb.append(binds[p++].getRegularValue()); - } else if (NULL_MARKER.equals(pValue)) { - sb.append("NULL"); - } else { - sb.append(pValue); - } - sb.append(sqlParts.get(i)); - } - return new ClickHouseSqlStatement(sb.toString(), parsedStmt.getStatementType()); - } - - private void checkBinded() throws SQLException { - int i = 0; - for (Object b : binds) { - ++i; - if (b == null) { - throw new SQLException("Not all parameters binded (placeholder " + i + " is undefined)"); - } - } - } - - @Override - public boolean execute() throws SQLException { - return executeQueryStatement(buildSql(), null, null, null) != null; - } - - @Override - public ResultSet executeQuery() throws SQLException { - return executeQueryStatement(buildSql(), null, null, null); - } - - @Override - public void clearBatch() throws SQLException { - super.clearBatch(); - - batchRows = new ArrayList<>(); - } - - @Override - public ResultSet executeQuery(Map additionalDBParams) throws SQLException { - return executeQuery(additionalDBParams, null); - } - - @Override - public ResultSet executeQuery(Map additionalDBParams, List externalData) throws SQLException { - return executeQueryStatement(buildSql(), additionalDBParams, externalData, null); - } - - @Override - public int executeUpdate() throws SQLException { - return executeStatement(buildSql(), null, null, null); - } - - private void setBind(int parameterIndex, String bind, boolean quote) { - binds[parameterIndex - 1] = new ClickHousePreparedStatementParameter(bind, quote); - } - - private void setBind(int parameterIndex, ClickHousePreparedStatementParameter parameter) { - binds[parameterIndex -1] = parameter; - } - - private void setNull(int parameterIndex) { - setBind(parameterIndex, ClickHousePreparedStatementParameter.nullParameter()); - } - - @Override - public void setNull(int parameterIndex, int sqlType) throws SQLException { - setNull(parameterIndex); - } - - @Override - public void setBoolean(int parameterIndex, boolean x) throws SQLException { - setBind(parameterIndex, ClickHousePreparedStatementParameter.boolParameter(x)); - } - - @Override - public void setByte(int parameterIndex, byte x) throws SQLException { - setBind(parameterIndex, ClickHouseValueFormatter.formatByte(x), false); - } - - @Override - public void setShort(int parameterIndex, short x) throws SQLException { - setBind(parameterIndex, ClickHouseValueFormatter.formatShort(x), false); - } - - @Override - public void setInt(int parameterIndex, int x) throws SQLException { - setBind(parameterIndex, ClickHouseValueFormatter.formatInt(x), false); - } - - @Override - public void setLong(int parameterIndex, long x) throws SQLException { - setBind(parameterIndex, ClickHouseValueFormatter.formatLong(x), false); - } - - @Override - public void setFloat(int parameterIndex, float x) throws SQLException { - setBind(parameterIndex, ClickHouseValueFormatter.formatFloat(x), false); - } - - @Override - public void setDouble(int parameterIndex, double x) throws SQLException { - setBind(parameterIndex, ClickHouseValueFormatter.formatDouble(x), false); - } - - @Override - public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException { - setBind(parameterIndex, ClickHouseValueFormatter.formatBigDecimal(x), false); - } - - @Override - public void setString(int parameterIndex, String x) throws SQLException { - setBind(parameterIndex, ClickHouseValueFormatter.formatString(x), x != null); - } - - @Override - public void setBytes(int parameterIndex, byte[] x) throws SQLException { - setBind(parameterIndex, ClickHouseValueFormatter.formatBytes(x), true); - } - - @Override - public void setDate(int parameterIndex, Date x) throws SQLException { - if (x != null) { - setBind( - parameterIndex, - ClickHouseValueFormatter.formatDate(x, dateTimeZone), - true); - } else { - setNull(parameterIndex); - } - } - - @Override - public void setTime(int parameterIndex, Time x) throws SQLException { - if (x != null) { - setBind( - parameterIndex, - ClickHouseValueFormatter.formatTime(x, dateTimeTimeZone), - true); - } else { - setNull(parameterIndex); - } - } - - @Override - public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { - if (x != null) { - setBind( - parameterIndex, - ClickHouseValueFormatter.formatTimestamp(x, dateTimeTimeZone), - true); - } else { - setNull(parameterIndex); - } - } - - @Override - public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException(); - - } - - @Override - @Deprecated - public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException(); - - } - - @Override - public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { - setObject(parameterIndex, x); - } - - @Override - public void setArray(int parameterIndex, Collection collection) throws SQLException { - setBind(parameterIndex, ClickHouseArrayUtil.toString(collection, dateTimeZone, dateTimeTimeZone), - false); - } - - @Override - public void setArray(int parameterIndex, Object[] array) throws SQLException { - setBind(parameterIndex, ClickHouseArrayUtil.toString(array, dateTimeZone, dateTimeTimeZone), false); - } - - @Override - public void setArray(int parameterIndex, Array x) throws SQLException { - setBind(parameterIndex, ClickHouseArrayUtil.arrayToString(x.getArray(), dateTimeZone, dateTimeTimeZone), - false); - } - - @Override - public void setObject(int parameterIndex, Object x) throws SQLException { - if (x != null) { - setBind( - parameterIndex, - ClickHousePreparedStatementParameter.fromObject( - x, dateTimeZone, dateTimeTimeZone)); - } else { - setNull(parameterIndex); - } - } - - @Override - public void addBatch(String sql) throws SQLException { - throw new SQLException("addBatch(String) cannot be called in PreparedStatement or CallableStatement!"); - } - - @Override - public void addBatch() throws SQLException { - if (parsedStmt.getStatementType() == StatementType.INSERT && parsedStmt.hasValues()) { - batchRows.addAll(buildBatch()); - } else { - batchStmts.add(buildSql()); - } - } - - private List buildBatch() throws SQLException { - checkBinded(); - List newBatches = new ArrayList<>(parameterList.size()); - StringBuilder sb = new StringBuilder(); - for (int i = 0, p = 0; i < parameterList.size(); i++) { - List pList = parameterList.get(i); - for (int j = 0; j < pList.size(); j++) { - String pValue = pList.get(j); - if (PARAM_MARKER.equals(pValue)) { - if (insertBatchMode) { - sb.append(binds[p++].getBatchValue()); - } else { - sb.append(binds[p++].getRegularValue()); - } - } else { - sb.append(pValue); - } - sb.append(j < pList.size() - 1 ? "\t" : "\n"); - } - newBatches.add(sb.toString().getBytes(StandardCharsets.UTF_8)); - sb = new StringBuilder(); - } - return newBatches; - } - - @Override - public int[] executeBatch() throws SQLException { - return executeBatch(null); - } - - @Override - public int[] executeBatch(Map additionalDBParams) throws SQLException { - int valuePosition = -1; - String sql = parsedStmt.getSQL(); - StatementType type = parsedStmt.getStatementType(); - if (type == StatementType.INSERT && parsedStmt.hasValues()) { - valuePosition = parsedStmt.getStartPosition(ClickHouseSqlStatement.KEYWORD_VALUES); - } - - int[] result = new int[batchRows.size()]; - Arrays.fill(result, 1); - if (valuePosition > 0) { // insert - String insertSql = sql.substring(0, valuePosition); - BatchHttpEntity entity = new BatchHttpEntity(batchRows); - sendStream(entity, insertSql, additionalDBParams); - } else { // others - if (type == StatementType.ALTER_DELETE || type == StatementType.ALTER_UPDATE) { - log.warn("UPDATE and DELETE should be used with caution, as they are expensive operations and not supposed to be used frequently."); - } else { - log.warn("PreparedStatement will slow down non-INSERT queries, so please consider to use Statement instead."); - } - result = super.executeBatch(); - } - - clearBatch(); - return result; - } - - private static class BatchHttpEntity extends AbstractHttpEntity { - private final List rows; - - public BatchHttpEntity(List rows) { - this.rows = rows; - } - - @Override - public boolean isRepeatable() { - return true; - } - - @Override - public long getContentLength() { - return -1; - } - - @Override - public InputStream getContent() throws IOException, IllegalStateException { - throw new UnsupportedOperationException(); - } - - @Override - public void writeTo(OutputStream outputStream) throws IOException { - for (byte[] row : rows) { - outputStream.write(row); - } - } - - @Override - public boolean isStreaming() { - return false; - } - } - - @Override - public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException { - throw new SQLFeatureNotSupportedException(); - - } - - @Override - public void setRef(int parameterIndex, Ref x) throws SQLException { - throw new SQLFeatureNotSupportedException(); - - } - - @Override - public void setBlob(int parameterIndex, Blob x) throws SQLException { - throw new SQLFeatureNotSupportedException(); - - } - - @Override - public void setClob(int parameterIndex, Clob x) throws SQLException { - throw new SQLFeatureNotSupportedException(); - - } - - @Override - public ResultSetMetaData getMetaData() throws SQLException { - ResultSet currentResult = getResultSet(); - if (currentResult != null) { - return currentResult.getMetaData(); - } - - if (!parsedStmt.isQuery()) { - return null; - } - ResultSet myRs = executeQuery(Collections.singletonMap( - ClickHouseQueryParam.MAX_RESULT_ROWS, "0")); - return myRs != null ? myRs.getMetaData() : null; - } - - @Override - public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException { - if (x != null && cal != null && cal.getTimeZone() != null) { - setBind( - parameterIndex, - ClickHouseValueFormatter.formatDate(x, cal.getTimeZone()), - true); - } else { - setDate(parameterIndex, x); - } - } - - @Override - public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException { - if (x != null && cal != null && cal.getTimeZone() != null) { - setBind( - parameterIndex, - ClickHouseValueFormatter.formatTime(x, cal.getTimeZone()), - true); - } else { - setTime(parameterIndex, x); - } - } - - @Override - public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException { - if (x != null && cal != null && cal.getTimeZone() != null) { - setBind( - parameterIndex, - ClickHouseValueFormatter.formatTimestamp(x, cal.getTimeZone()), - true); - } else { - setTimestamp(parameterIndex, x); - } - } - - @Override - public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException { - setNull(parameterIndex, sqlType); - } - - @Override - public void setURL(int parameterIndex, URL x) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public ParameterMetaData getParameterMetaData() throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public void setRowId(int parameterIndex, RowId x) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public void setNString(int parameterIndex, String value) throws SQLException { - setString(parameterIndex, value); - } - - @Override - public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public void setNClob(int parameterIndex, NClob value) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException { - setObject(parameterIndex, x); - } - - @Override - public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public void setClob(int parameterIndex, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public void setNClob(int parameterIndex, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - private int countNonConstantParams() { - int count = 0; - for (int i = 0; i < parameterList.size(); i++) { - List pList = parameterList.get(i); - for (int j = 0; j < pList.size(); j++) { - if (PARAM_MARKER.equals(pList.get(j))) { - count += 1; - } - } - } - return count; - } - - private String getParameter(int paramIndex) { - for (int i = 0, count = paramIndex; i < parameterList.size(); i++) { - List pList = parameterList.get(i); - count -= pList.size(); - if (count < 0) { - return pList.get(pList.size() + count); - } - } - return null; - } - - @Override - public String asSql() { - try { - return buildSql().getSQL(); - } catch (SQLException e) { - return parsedStmt.getSQL(); - } - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHousePreparedStatementParameter.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHousePreparedStatementParameter.java deleted file mode 100644 index 7201f42fe..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHousePreparedStatementParameter.java +++ /dev/null @@ -1,67 +0,0 @@ -package ru.yandex.clickhouse; - -import ru.yandex.clickhouse.util.ClickHouseValueFormatter; - -import java.util.TimeZone; - -public final class ClickHousePreparedStatementParameter { - - private static final ClickHousePreparedStatementParameter NULL_PARAM = - new ClickHousePreparedStatementParameter(null, false); - - private static final ClickHousePreparedStatementParameter TRUE_PARAM = - new ClickHousePreparedStatementParameter("1", false); - - private static final ClickHousePreparedStatementParameter FALSE_PARAM = - new ClickHousePreparedStatementParameter("0", false); - - private final String stringValue; - private final boolean quoteNeeded; - - public static ClickHousePreparedStatementParameter fromObject(Object x, - TimeZone dateTimeZone, TimeZone dateTimeTimeZone) - { - if (x == null) { - return NULL_PARAM; - } - return new ClickHousePreparedStatementParameter( - ClickHouseValueFormatter.formatObject(x, dateTimeZone, dateTimeTimeZone), - ClickHouseValueFormatter.needsQuoting(x)); - } - - public static ClickHousePreparedStatementParameter nullParameter() { - return NULL_PARAM; - } - - public static ClickHousePreparedStatementParameter boolParameter(boolean value) { - return value ? TRUE_PARAM : FALSE_PARAM; - } - - public ClickHousePreparedStatementParameter(String stringValue, - boolean quoteNeeded) - { - this.stringValue = stringValue == null - ? ClickHouseValueFormatter.NULL_MARKER - : stringValue; - this.quoteNeeded = quoteNeeded; - } - - String getRegularValue() { - return !ClickHouseValueFormatter.NULL_MARKER.equals(stringValue) - ? quoteNeeded - ? "'" + stringValue + "'" - : stringValue - : "null"; - } - - String getBatchValue() { - return stringValue; - } - - - @Override - public String toString() { - return stringValue; - } - -} \ No newline at end of file diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseStatement.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseStatement.java deleted file mode 100644 index 695d9378c..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseStatement.java +++ /dev/null @@ -1,85 +0,0 @@ -package ru.yandex.clickhouse; - -import ru.yandex.clickhouse.response.ClickHouseResponse; -import ru.yandex.clickhouse.response.ClickHouseResponseSummary; -import ru.yandex.clickhouse.settings.ClickHouseQueryParam; -import ru.yandex.clickhouse.util.ClickHouseRowBinaryInputStream; -import ru.yandex.clickhouse.util.ClickHouseStreamCallback; - -import java.io.InputStream; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.List; -import java.util.Map; - - -public interface ClickHouseStatement extends Statement { - - ClickHouseResponse executeQueryClickhouseResponse(String sql) throws SQLException; - - ClickHouseResponse executeQueryClickhouseResponse(String sql, Map additionalDBParams) throws SQLException; - - ClickHouseResponse executeQueryClickhouseResponse(String sql, - Map additionalDBParams, - Map additionalRequestParams) throws SQLException; - - ClickHouseRowBinaryInputStream executeQueryClickhouseRowBinaryStream(String sql) throws SQLException; - - ClickHouseRowBinaryInputStream executeQueryClickhouseRowBinaryStream(String sql, - Map additionalDBParams) throws SQLException; - - ClickHouseRowBinaryInputStream executeQueryClickhouseRowBinaryStream(String sql, - Map additionalDBParams, - Map additionalRequestParams) throws SQLException; - - ResultSet executeQuery(String sql, Map additionalDBParams) throws SQLException; - - ResultSet executeQuery(String sql, Map additionalDBParams, List externalData) throws SQLException; - - ResultSet executeQuery(String sql, - Map additionalDBParams, - List externalData, - Map additionalRequestParams) throws SQLException; - - @Deprecated - void sendStream(InputStream content, String table, Map additionalDBParams) throws SQLException; - - @Deprecated - void sendStream(InputStream content, String table) throws SQLException; - - @Deprecated - void sendRowBinaryStream(String sql, Map additionalDBParams, ClickHouseStreamCallback callback) throws SQLException; - - @Deprecated - void sendRowBinaryStream(String sql, ClickHouseStreamCallback callback) throws SQLException; - - @Deprecated - void sendNativeStream(String sql, Map additionalDBParams, ClickHouseStreamCallback callback) throws SQLException; - - @Deprecated - void sendNativeStream(String sql, ClickHouseStreamCallback callback) throws SQLException; - - @Deprecated - void sendCSVStream(InputStream content, String table, Map additionalDBParams) throws SQLException; - - @Deprecated - void sendCSVStream(InputStream content, String table) throws SQLException; - - @Deprecated - void sendStreamSQL(InputStream content, String sql, Map additionalDBParams) throws SQLException; - - @Deprecated - void sendStreamSQL(InputStream content, String sql) throws SQLException; - - /** - * Returns extended write-API, which simplifies uploading larger files or - * data streams. - * - * @return a new {@link Writer} builder object which can be used to - * construct a request to the server - */ - Writer write(); - - ClickHouseResponseSummary getResponseSummary(); -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseStatementImpl.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseStatementImpl.java deleted file mode 100644 index 15211f31f..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseStatementImpl.java +++ /dev/null @@ -1,1149 +0,0 @@ -package ru.yandex.clickhouse; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.SQLWarning; -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.TimeZone; -import java.util.UUID; - -import com.clickhouse.client.data.JsonStreamUtils; -import com.clickhouse.client.logging.Logger; -import com.clickhouse.client.logging.LoggerFactory; -import com.clickhouse.jdbc.parser.ClickHouseSqlParser; -import com.clickhouse.jdbc.parser.ClickHouseSqlStatement; -import com.clickhouse.jdbc.parser.StatementType; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.NameValuePair; -import org.apache.http.StatusLine; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.entity.AbstractHttpEntity; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; -import org.apache.http.entity.mime.MultipartEntityBuilder; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.util.EntityUtils; - -import ru.yandex.clickhouse.domain.ClickHouseCompression; -import ru.yandex.clickhouse.domain.ClickHouseFormat; -import ru.yandex.clickhouse.except.ClickHouseException; -import ru.yandex.clickhouse.except.ClickHouseExceptionSpecifier; -import ru.yandex.clickhouse.response.ClickHouseLZ4Stream; -import ru.yandex.clickhouse.response.ClickHouseResponse; -import ru.yandex.clickhouse.response.ClickHouseResponseGsonDeserializer; -import ru.yandex.clickhouse.response.ClickHouseResponseSummary; -import ru.yandex.clickhouse.response.ClickHouseResultSet; -import ru.yandex.clickhouse.response.ClickHouseScrollableResultSet; -import ru.yandex.clickhouse.response.FastByteArrayOutputStream; -import ru.yandex.clickhouse.settings.ClickHouseProperties; -import ru.yandex.clickhouse.settings.ClickHouseQueryParam; -import ru.yandex.clickhouse.util.ClickHouseHttpClientBuilder; -import ru.yandex.clickhouse.util.ClickHouseRowBinaryInputStream; -import ru.yandex.clickhouse.util.ClickHouseStreamCallback; -import ru.yandex.clickhouse.util.Utils; - -public class ClickHouseStatementImpl extends ConfigurableApi implements ClickHouseStatement { - - private static final Logger log = LoggerFactory.getLogger(ClickHouseStatementImpl.class); - private static final Gson gson = new GsonBuilder().registerTypeAdapter(ClickHouseResponse.class, - new ClickHouseResponseGsonDeserializer()).create(); - - protected static class WrappedHttpEntity extends AbstractHttpEntity { - private final String sql; - private final HttpEntity entity; - - public WrappedHttpEntity(String sql, HttpEntity entity) { - this.sql = sql; - this.entity = Objects.requireNonNull(entity); - - this.chunked = entity.isChunked(); - this.contentEncoding = entity.getContentEncoding(); - this.contentType = entity.getContentType(); - } - - @Override - public boolean isRepeatable() { - return entity.isRepeatable(); - } - - @Override - public long getContentLength() { - return entity.getContentLength(); - } - - @Override - public InputStream getContent() throws IOException, IllegalStateException { - return entity.getContent(); - } - - @Override - public void writeTo(OutputStream outputStream) throws IOException { - if (sql != null && !sql.isEmpty()) { - outputStream.write(sql.getBytes(StandardCharsets.UTF_8)); - outputStream.write('\n'); - } - - entity.writeTo(outputStream); - } - - @Override - public boolean isStreaming() { - return entity.isStreaming(); - } - } - - private final CloseableHttpClient client; - - private final HttpClientContext httpContext; - - protected ClickHouseProperties properties; - - private ClickHouseConnection connection; - - private ClickHouseResultSet currentResult; - - private ClickHouseRowBinaryInputStream currentRowBinaryResult; - - private ClickHouseResponseSummary currentSummary; - - private int currentUpdateCount = -1; - - private int queryTimeout; - - private boolean isQueryTimeoutSet = false; - - private int maxRows; - - private boolean closeOnCompletion; - - private final boolean isResultSetScrollable; - - private volatile String queryId; - - protected ClickHouseSqlStatement[] parsedStmts; - - protected List batchStmts; - - /** - * Current database name may be changed by - * {@link java.sql.Connection#setCatalog(String)} between creation of this - * object and query execution, but javadoc does not allow {@code setCatalog} - * influence on already created statements. - */ - protected String currentDatabase; - - protected String getQueryId() { - return queryId; - } - - protected ClickHouseSqlStatement getLastStatement() { - ClickHouseSqlStatement stmt = null; - - if (parsedStmts != null && parsedStmts.length > 0) { - stmt = parsedStmts[parsedStmts.length - 1]; - } - - return Objects.requireNonNull(stmt); - } - - protected void setLastStatement(ClickHouseSqlStatement stmt) { - if (parsedStmts != null && parsedStmts.length > 0) { - parsedStmts[parsedStmts.length - 1] = Objects.requireNonNull(stmt); - } - } - - protected ClickHouseSqlStatement[] parseSqlStatements(String sql) throws SQLException { - parsedStmts = ClickHouseSqlParser.parse(sql, null); - - if (parsedStmts == null || parsedStmts.length == 0) { - // should never happen - throw new IllegalArgumentException("Failed to parse given SQL: " + sql); - } - - return parsedStmts; - } - - protected ClickHouseSqlStatement parseSqlStatements(String sql, ClickHouseFormat preferredFormat, - Map additionalDBParams) throws SQLException { - parseSqlStatements(sql); - - // enable session when we have more than one statement - if (additionalDBParams != null && parsedStmts.length > 1 && properties.getSessionId() == null) { - additionalDBParams.put(ClickHouseQueryParam.SESSION_ID, UUID.randomUUID().toString()); - } - - ClickHouseSqlStatement lastStmt = getLastStatement(); - ClickHouseSqlStatement formattedStmt = applyFormat(lastStmt, preferredFormat); - if (formattedStmt != lastStmt) { - setLastStatement(lastStmt = formattedStmt); - } - - return lastStmt; - } - - protected ClickHouseSqlStatement applyFormat(ClickHouseSqlStatement stmt, ClickHouseFormat preferredFormat) { - if (Objects.requireNonNull(stmt).isQuery() && !stmt.hasFormat()) { - String sql = stmt.getSQL(); - String format = Objects.requireNonNull(preferredFormat).name(); - - Map positions = new HashMap<>(); - positions.putAll(stmt.getPositions()); - positions.put(ClickHouseSqlStatement.KEYWORD_FORMAT, sql.length()); - - sql = new StringBuilder(sql).append("\nFORMAT ").append(format).toString(); - stmt = new ClickHouseSqlStatement(sql, stmt.getStatementType(), stmt.getCluster(), stmt.getDatabase(), - stmt.getTable(), stmt.getInput(), format, stmt.getOutfile(), stmt.getParameters(), positions, null, null); - } - - return stmt; - } - - protected Map importAdditionalDBParameters( - Map additionalDBParams) { - if (additionalDBParams == null || additionalDBParams.isEmpty()) { - additionalDBParams = new EnumMap<>(ClickHouseQueryParam.class); - } else { // in case the given additionalDBParams is immutable - additionalDBParams = new EnumMap<>(additionalDBParams); - } - - return additionalDBParams; - } - - protected T readJsonResponse(InputStream input, Class clazz) throws IOException { - return gson.fromJson(new InputStreamReader(input, StandardCharsets.UTF_8), clazz); - } - - protected ResultSet updateResult(ClickHouseSqlStatement stmt, InputStream is) - throws IOException, ClickHouseException { - ResultSet rs = null; - if (stmt.isQuery()) { - currentUpdateCount = -1; - currentResult = createResultSet(properties.isCompress() ? new ClickHouseLZ4Stream(is) : is, - properties.getBufferSize(), stmt.getDatabaseOrDefault(properties.getDatabase()), stmt.getTable(), - stmt.hasWithTotals(), this, getConnection().getTimeZone(), properties); - currentResult.setMaxRows(maxRows); - rs = currentResult; - } else { - currentUpdateCount = 0; - try { - is.close(); - } catch (IOException e) { - log.error("can not close stream: %s", e.getMessage()); - } - } - - return rs; - } - - protected int executeStatement(ClickHouseSqlStatement stmt, Map additionalDBParams, - List externalData, Map additionalRequestParams) - throws SQLException { - additionalDBParams = importAdditionalDBParameters(additionalDBParams); - stmt = applyFormat(stmt, ClickHouseFormat.TabSeparatedWithNamesAndTypes); - - try (InputStream is = getInputStream(stmt, additionalDBParams, externalData, additionalRequestParams)) { - // noinspection StatementWithEmptyBody - } catch (IOException e) { - log.error("can not close stream: %s", e.getMessage()); - } - - return currentSummary != null ? (int) currentSummary.getWrittenRows() : 1; - } - - protected ResultSet executeQueryStatement(ClickHouseSqlStatement stmt, - Map additionalDBParams, List externalData, - Map additionalRequestParams) throws SQLException { - additionalDBParams = importAdditionalDBParameters(additionalDBParams); - stmt = applyFormat(stmt, ClickHouseFormat.TabSeparatedWithNamesAndTypes); - - InputStream is = getInputStream(stmt, additionalDBParams, externalData, additionalRequestParams); - try { - return updateResult(stmt, is); - } catch (Exception e) { - try { - is.close(); - } catch (IOException ioe) { - log.error("can not close stream: %s", ioe.getMessage()); - } - throw ClickHouseExceptionSpecifier.specify(e, properties.getHost(), properties.getPort()); - } - } - - protected ClickHouseResponse executeQueryClickhouseResponse(ClickHouseSqlStatement stmt, - Map additionalDBParams, Map additionalRequestParams) - throws SQLException { - additionalDBParams = importAdditionalDBParameters(additionalDBParams); - stmt = applyFormat(stmt, ClickHouseFormat.JSONCompact); - - try (InputStream is = getInputStream(stmt, additionalDBParams, null, additionalRequestParams)) { - return readJsonResponse(properties.isCompress() ? new ClickHouseLZ4Stream(is) : is, - ClickHouseResponse.class); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - public ClickHouseStatementImpl(CloseableHttpClient client, ClickHouseConnection connection, - ClickHouseProperties properties, int resultSetType) { - super(null); - this.client = client; - this.httpContext = ClickHouseHttpClientBuilder.createClientContext(properties); - this.connection = connection; - this.properties = properties == null ? new ClickHouseProperties() : properties; - this.currentDatabase = this.properties.getDatabase(); - this.isResultSetScrollable = (resultSetType != ResultSet.TYPE_FORWARD_ONLY); - - this.batchStmts = new ArrayList<>(); - } - - @Override - public ResultSet executeQuery(String sql) throws SQLException { - return executeQuery(sql, null); - } - - @Override - public ResultSet executeQuery(String sql, Map additionalDBParams) - throws SQLException { - return executeQuery(sql, additionalDBParams, null); - } - - @Override - public ResultSet executeQuery(String sql, Map additionalDBParams, - List externalData) throws SQLException { - return executeQuery(sql, additionalDBParams, externalData, null); - } - - @Override - public ResultSet executeQuery(String sql, Map additionalDBParams, - List externalData, Map additionalRequestParams) - throws SQLException { - - // forcibly disable extremes for ResultSet queries - additionalDBParams = importAdditionalDBParameters(additionalDBParams); - // FIXME respect the value set in additionalDBParams? - additionalDBParams.put(ClickHouseQueryParam.EXTREMES, "0"); - - parseSqlStatements(sql, ClickHouseFormat.TabSeparatedWithNamesAndTypes, additionalDBParams); - - InputStream is = getLastInputStream(additionalDBParams, externalData, additionalRequestParams); - ClickHouseSqlStatement parsedStmt = getLastStatement(); - - try { - return updateResult(parsedStmt, is); - } catch (Exception e) { - try { - is.close(); - } catch (IOException ioe) { - log.error("can not close stream: %s", ioe.getMessage()); - } - throw ClickHouseExceptionSpecifier.specify(e, properties.getHost(), properties.getPort()); - } - } - - @Override - public ClickHouseResponse executeQueryClickhouseResponse(String sql) throws SQLException { - return executeQueryClickhouseResponse(sql, null); - } - - @Override - public ClickHouseResponse executeQueryClickhouseResponse(String sql, - Map additionalDBParams) throws SQLException { - return executeQueryClickhouseResponse(sql, additionalDBParams, null); - } - - @Override - public ClickHouseResponse executeQueryClickhouseResponse(String sql, - Map additionalDBParams, Map additionalRequestParams) - throws SQLException { - additionalDBParams = importAdditionalDBParameters(additionalDBParams); - parseSqlStatements(sql, ClickHouseFormat.JSONCompact, additionalDBParams); - - try (InputStream is = getLastInputStream(additionalDBParams, null, additionalRequestParams)) { - return readJsonResponse(properties.isCompress() ? new ClickHouseLZ4Stream(is) : is, - ClickHouseResponse.class); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public ClickHouseRowBinaryInputStream executeQueryClickhouseRowBinaryStream(String sql) throws SQLException { - return executeQueryClickhouseRowBinaryStream(sql, null); - } - - @Override - public ClickHouseRowBinaryInputStream executeQueryClickhouseRowBinaryStream(String sql, - Map additionalDBParams) throws SQLException { - return executeQueryClickhouseRowBinaryStream(sql, additionalDBParams, null); - } - - @Override - public ClickHouseRowBinaryInputStream executeQueryClickhouseRowBinaryStream(String sql, - Map additionalDBParams, Map additionalRequestParams) - throws SQLException { - additionalDBParams = importAdditionalDBParameters(additionalDBParams); - parseSqlStatements(sql, ClickHouseFormat.RowBinaryWithNamesAndTypes, additionalDBParams); - - InputStream is = getLastInputStream(additionalDBParams, null, additionalRequestParams); - ClickHouseSqlStatement parsedStmt = getLastStatement(); - - try { - if (parsedStmt.isQuery()) { - currentUpdateCount = -1; - // FIXME get server timezone? - currentRowBinaryResult = new ClickHouseRowBinaryInputStream( - properties.isCompress() ? new ClickHouseLZ4Stream(is) : is, getConnection().getTimeZone(), - properties, true); - return currentRowBinaryResult; - } else { - currentUpdateCount = 0; - try { - is.close(); - } catch (IOException e) { - log.error("can not close stream: %s", e.getMessage()); - } - return null; - } - } catch (Exception e) { - try { - is.close(); - } catch (IOException ioe) { - log.error("can not close stream: %s", ioe.getMessage()); - } - throw ClickHouseExceptionSpecifier.specify(e, properties.getHost(), properties.getPort()); - } - } - - @Override - public int executeUpdate(String sql) throws SQLException { - Map additionalDBParams = new EnumMap<>(ClickHouseQueryParam.class); - parseSqlStatements(sql, ClickHouseFormat.TabSeparatedWithNamesAndTypes, additionalDBParams); - - try (InputStream is = getLastInputStream(additionalDBParams, null, null)) { - // noinspection StatementWithEmptyBody - } catch (IOException e) { - log.error("can not close stream: %s", e.getMessage()); - } - - return currentSummary != null ? (int) currentSummary.getWrittenRows() : 1; - } - - @Override - public boolean execute(String sql) throws SQLException { - // currentResult is stored here. InputString and currentResult will be closed on - // this.close() - return executeQuery(sql) != null; - } - - @Override - public void close() throws SQLException { - if (currentResult != null) { - currentResult.close(); - } - - if (currentRowBinaryResult != null) { - try { - currentRowBinaryResult.close(); - } catch (IOException e) { - log.error("can not close stream: %s", e.getMessage()); - } - } - } - - @Override - public int getMaxFieldSize() throws SQLException { - return 0; - } - - @Override - public void setMaxFieldSize(int max) throws SQLException { - - } - - @Override - public int getMaxRows() throws SQLException { - return maxRows; - } - - @Override - public void setMaxRows(int max) throws SQLException { - if (max < 0) { - throw new SQLException(String.format("Illegal maxRows value: %d", max)); - } - maxRows = max; - } - - @Override - public void setEscapeProcessing(boolean enable) throws SQLException { - - } - - @Override - public int getQueryTimeout() throws SQLException { - return queryTimeout; - } - - @Override - public void setQueryTimeout(int seconds) throws SQLException { - queryTimeout = seconds; - isQueryTimeoutSet = true; - } - - @Override - public void cancel() throws SQLException { - if (this.queryId == null || isClosed()) { - return; - } - - executeQuery(String.format("KILL QUERY WHERE query_id='%s'", queryId)); - } - - @Override - public SQLWarning getWarnings() throws SQLException { - return null; - } - - @Override - public void clearWarnings() throws SQLException { - - } - - @Override - public void setCursorName(String name) throws SQLException { - - } - - @Override - public ResultSet getResultSet() throws SQLException { - return currentResult; - } - - @Override - public int getUpdateCount() throws SQLException { - return currentUpdateCount; - } - - @Override - public boolean getMoreResults() throws SQLException { - if (currentResult != null) { - currentResult.close(); - currentResult = null; - } - currentUpdateCount = -1; - return false; - } - - @Override - public void setFetchDirection(int direction) throws SQLException { - - } - - @Override - public int getFetchDirection() throws SQLException { - return 0; - } - - @Override - public void setFetchSize(int rows) throws SQLException { - - } - - @Override - public int getFetchSize() throws SQLException { - return 0; - } - - @Override - public int getResultSetConcurrency() throws SQLException { - return 0; - } - - @Override - public int getResultSetType() throws SQLException { - return 0; - } - - @Override - public void addBatch(String sql) throws SQLException { - for (ClickHouseSqlStatement s : ClickHouseSqlParser.parse(sql, null)) { - this.batchStmts.add(s); - } - } - - @Override - public void clearBatch() throws SQLException { - this.batchStmts = new ArrayList<>(); - } - - @Override - public int[] executeBatch() throws SQLException { - int len = batchStmts.size(); - int[] results = new int[len]; - for (int i = 0; i < len; i++) { - results[i] = executeStatement(batchStmts.get(i), null, null, null); - } - - clearBatch(); - - return results; - } - - @Override - public ClickHouseConnection getConnection() throws ClickHouseException { - return connection; - } - - @Override - public boolean getMoreResults(int current) throws SQLException { - return false; - } - - @Override - public ResultSet getGeneratedKeys() throws SQLException { - return null; - } - - @Override - public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { - return 0; - } - - @Override - public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { - return 0; - } - - @Override - public int executeUpdate(String sql, String[] columnNames) throws SQLException { - return 0; - } - - @Override - public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { - return false; - } - - @Override - public boolean execute(String sql, int[] columnIndexes) throws SQLException { - return false; - } - - @Override - public boolean execute(String sql, String[] columnNames) throws SQLException { - return false; - } - - @Override - public int getResultSetHoldability() throws SQLException { - return 0; - } - - @Override - public boolean isClosed() throws SQLException { - return false; - } - - @Override - public void setPoolable(boolean poolable) throws SQLException { - - } - - @Override - public boolean isPoolable() throws SQLException { - return false; - } - - @Override - public T unwrap(Class iface) throws SQLException { - if (iface.isAssignableFrom(getClass())) { - return iface.cast(this); - } - throw new SQLException("Cannot unwrap to " + iface.getName()); - } - - @Override - public boolean isWrapperFor(Class iface) throws SQLException { - return iface.isAssignableFrom(getClass()); - } - - @Override - public ClickHouseResponseSummary getResponseSummary() { - return currentSummary; - } - - private InputStream getLastInputStream(Map additionalDBParams, - List externalData, Map additionalRequestParams) - throws ClickHouseException { - InputStream is = null; - for (int i = 0, len = parsedStmts.length; i < len; i++) { - // TODO skip useless queries to reduce network calls and server load - is = getInputStream(parsedStmts[i], additionalDBParams, externalData, additionalRequestParams); - // TODO multi-resultset - if (i + 1 < len) { - try { - is.close(); - } catch (IOException ioe) { - log.warn("Failed to close stream: %s", ioe.getMessage()); - } - } - } - - return is; - } - - private InputStream getInputStream(ClickHouseSqlStatement parsedStmt, - Map additionalClickHouseDBParams, List externalData, - Map additionalRequestParams) throws ClickHouseException { - String sql = parsedStmt.getSQL(); - boolean ignoreDatabase = parsedStmt.isRecognized() && !parsedStmt.isDML() - && parsedStmt.containsKeyword("DATABASE"); - if (parsedStmt.getStatementType() == StatementType.USE) { - currentDatabase = parsedStmt.getDatabaseOrDefault(currentDatabase); - } - - log.debug("Executing SQL: %s", sql); - - additionalClickHouseDBParams = addQueryIdTo(additionalClickHouseDBParams == null - ? new EnumMap(ClickHouseQueryParam.class) - : additionalClickHouseDBParams); - - URI uri = buildRequestUri(null, externalData, additionalClickHouseDBParams, additionalRequestParams, - ignoreDatabase); - log.debug("Request url: %s", uri); - - HttpEntity requestEntity; - if (externalData == null || externalData.isEmpty()) { - requestEntity = new StringEntity(sql, StandardCharsets.UTF_8); - } else { - MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create(); - - ContentType queryContentType = ContentType.create(ContentType.TEXT_PLAIN.getMimeType(), - StandardCharsets.UTF_8); - entityBuilder.addTextBody("query", sql, queryContentType); - - try { - for (ClickHouseExternalData externalDataItem : externalData) { - // clickhouse may return 400 (bad request) when chunked encoding is used with - // multipart request - // so read content to byte array to avoid chunked encoding - // TODO do not read stream into memory when this issue is fixed in clickhouse - entityBuilder.addBinaryBody(externalDataItem.getName(), - Utils.toByteArray(externalDataItem.getContent()), ContentType.APPLICATION_OCTET_STREAM, - externalDataItem.getName()); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - - requestEntity = entityBuilder.build(); - } - - requestEntity = applyRequestBodyCompression(requestEntity); - - HttpEntity entity = null; - try { - uri = followRedirects(uri); - HttpPost post = new HttpPost(uri); - post.setEntity(requestEntity); - - if (parsedStmt.isIdemponent()) { - httpContext.setAttribute("is_idempotent", Boolean.TRUE); - } else { - httpContext.removeAttribute("is_idempotent"); - } - - HttpResponse response = client.execute(post, httpContext); - entity = response.getEntity(); - checkForErrorAndThrow(entity, response); - - InputStream is; - if (entity.isStreaming()) { - is = entity.getContent(); - } else { - FastByteArrayOutputStream baos = new FastByteArrayOutputStream(); - entity.writeTo(baos); - is = baos.convertToInputStream(); - } - - // retrieve response summary - if (isQueryParamSet(ClickHouseQueryParam.SEND_PROGRESS_IN_HTTP_HEADERS, additionalClickHouseDBParams, - additionalRequestParams)) { - Header summaryHeader = response.getFirstHeader("X-ClickHouse-Summary"); - currentSummary = summaryHeader != null - ? JsonStreamUtils.readObject(summaryHeader.getValue(), ClickHouseResponseSummary.class) - : null; - } - - return is; - } catch (ClickHouseException e) { - throw e; - } catch (Exception e) { - log.info("Error during connection to %s, reporting failure to data source, message: %s", properties, - e.getMessage()); - EntityUtils.consumeQuietly(entity); - log.info("Error sql: %s", sql); - throw ClickHouseExceptionSpecifier.specify(e, properties.getHost(), properties.getPort()); - } - } - - URI buildRequestUri(String sql, List externalData, - Map additionalClickHouseDBParams, Map additionalRequestParams, - boolean ignoreDatabase) { - try { - List queryParams = getUrlQueryParams(sql, externalData, additionalClickHouseDBParams, - additionalRequestParams, ignoreDatabase); - - // avoid to reuse query id - if (additionalClickHouseDBParams != null) { - additionalClickHouseDBParams.remove(ClickHouseQueryParam.QUERY_ID); - } - - return new URIBuilder().setScheme(properties.getSsl() ? "https" : "http").setHost(properties.getHost()) - .setPort(properties.getPort()) - .setPath((properties.getPath() == null || properties.getPath().isEmpty() ? "/" - : properties.getPath())) - .setParameters(queryParams).build(); - } catch (URISyntaxException e) { - log.error("Mailformed URL: %s", e.getMessage()); - throw new IllegalStateException("illegal configuration of db"); - } - } - - private List getUrlQueryParams(String sql, List externalData, - Map additionalClickHouseDBParams, Map additionalRequestParams, - boolean ignoreDatabase) { - List result = new ArrayList<>(); - - if (sql != null && !sql.isEmpty()) { - result.add(new BasicNameValuePair("query", sql)); - } - - if (externalData != null) { - for (ClickHouseExternalData externalDataItem : externalData) { - String name = externalDataItem.getName(); - String format = externalDataItem.getFormat(); - String types = externalDataItem.getTypes(); - String structure = externalDataItem.getStructure(); - - if (format != null && !format.isEmpty()) { - result.add(new BasicNameValuePair(name + "_format", format)); - } - if (types != null && !types.isEmpty()) { - result.add(new BasicNameValuePair(name + "_types", types)); - } - if (structure != null && !structure.isEmpty()) { - result.add(new BasicNameValuePair(name + "_structure", structure)); - } - } - } - - Map params = properties.buildQueryParams(true); - String db = params.getOrDefault(ClickHouseQueryParam.DATABASE, currentDatabase); - if (!ignoreDatabase && !Utils.isNullOrEmptyString(db)) { - params.put(ClickHouseQueryParam.DATABASE, currentDatabase); - } - - params.putAll(getAdditionalDBParams()); - - if (additionalClickHouseDBParams != null && !additionalClickHouseDBParams.isEmpty()) { - params.putAll(additionalClickHouseDBParams); - } - - setStatementPropertiesToParams(params); - - for (Map.Entry entry : params.entrySet()) { - if (!Utils.isNullOrEmptyString(entry.getValue())) { - result.add(new BasicNameValuePair(entry.getKey().toString(), entry.getValue())); - } - } - - for (Map.Entry entry : getRequestParams().entrySet()) { - if (!Utils.isNullOrEmptyString(entry.getValue())) { - result.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); - } - } - - if (additionalRequestParams != null) { - for (Map.Entry entry : additionalRequestParams.entrySet()) { - if (!Utils.isNullOrEmptyString(entry.getValue())) { - result.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); - } - } - } - - return result; - } - - private boolean isQueryParamSet(ClickHouseQueryParam param, - Map additionalClickHouseDBParams, - Map additionalRequestParams) { - String value = getQueryParamValue(param, additionalClickHouseDBParams, additionalRequestParams); - - return "true".equals(value) || "1".equals(value); - } - - private String getQueryParamValue(ClickHouseQueryParam param, - Map additionalClickHouseDBParams, - Map additionalRequestParams) { - if (additionalRequestParams != null && additionalRequestParams.containsKey(param.getKey()) - && !Utils.isNullOrEmptyString(additionalRequestParams.get(param.getKey()))) { - return additionalRequestParams.get(param.getKey()); - } - - if (getRequestParams().containsKey(param.getKey()) - && !Utils.isNullOrEmptyString(getRequestParams().get(param.getKey()))) { - return getRequestParams().get(param.getKey()); - } - - if (additionalClickHouseDBParams != null && additionalClickHouseDBParams.containsKey(param) - && !Utils.isNullOrEmptyString(additionalClickHouseDBParams.get(param))) { - return additionalClickHouseDBParams.get(param); - } - - if (getAdditionalDBParams().containsKey(param) - && !Utils.isNullOrEmptyString(getAdditionalDBParams().get(param))) { - return getAdditionalDBParams().get(param); - } - - return properties.asProperties().getProperty(param.getKey()); - } - - private URI followRedirects(URI uri) throws IOException, URISyntaxException { - if (properties.isCheckForRedirects()) { - int redirects = 0; - while (redirects < properties.getMaxRedirects()) { - HttpGet httpGet = new HttpGet(uri); - HttpResponse response = client.execute(httpGet, httpContext); - if (response.getStatusLine().getStatusCode() == 307) { - uri = new URI(response.getHeaders("Location")[0].getValue()); - redirects++; - log.info("Redirected to %s", uri.getHost()); - } else { - break; - } - } - } - return uri; - } - - private void setStatementPropertiesToParams(Map params) { - if (maxRows > 0) { - params.put(ClickHouseQueryParam.MAX_RESULT_ROWS, String.valueOf(maxRows)); - params.put(ClickHouseQueryParam.RESULT_OVERFLOW_MODE, "break"); - } - if (isQueryTimeoutSet) { - params.put(ClickHouseQueryParam.MAX_EXECUTION_TIME, String.valueOf(queryTimeout)); - } - } - - @Override - public void sendRowBinaryStream(String sql, ClickHouseStreamCallback callback) throws SQLException { - sendRowBinaryStream(sql, null, callback); - } - - @Override - public void sendRowBinaryStream(String sql, Map additionalDBParams, - ClickHouseStreamCallback callback) throws SQLException { - write().withDbParams(additionalDBParams).send(sql, callback, ClickHouseFormat.RowBinary); - } - - @Override - public void sendNativeStream(String sql, ClickHouseStreamCallback callback) throws SQLException { - sendNativeStream(sql, null, callback); - } - - @Override - public void sendNativeStream(String sql, Map additionalDBParams, - ClickHouseStreamCallback callback) throws SQLException { - write().withDbParams(additionalDBParams).send(sql, callback, ClickHouseFormat.Native); - } - - @Override - public void sendCSVStream(InputStream content, String table, Map additionalDBParams) - throws SQLException { - write().table(table).withDbParams(additionalDBParams).data(content).format(ClickHouseFormat.CSV).send(); - } - - @Override - public void sendCSVStream(InputStream content, String table) throws SQLException { - sendCSVStream(content, table, null); - } - - @Override - public void sendStream(InputStream content, String table) throws SQLException { - sendStream(content, table, null); - } - - @Override - public void sendStream(InputStream content, String table, Map additionalDBParams) - throws SQLException { - write().table(table).data(content).withDbParams(additionalDBParams).format(ClickHouseFormat.TabSeparated) - .send(); - } - - @Deprecated - public void sendStream(HttpEntity content, String sql) throws ClickHouseException { - sendStream(content, sql, ClickHouseFormat.TabSeparated, null); - } - - @Deprecated - public void sendStream(HttpEntity content, String sql, Map additionalDBParams) - throws ClickHouseException { - sendStream(content, sql, ClickHouseFormat.TabSeparated, additionalDBParams); - } - - private void sendStream(HttpEntity content, String sql, ClickHouseFormat format, - Map additionalDBParams) throws ClickHouseException { - - Writer writer = write().format(format).withDbParams(additionalDBParams).sql(sql); - sendStream(writer, content); - } - - @Override - public void sendStreamSQL(InputStream content, String sql, Map additionalDBParams) - throws SQLException { - write().data(content).sql(sql).withDbParams(additionalDBParams).send(); - } - - @Override - public void sendStreamSQL(InputStream content, String sql) throws SQLException { - write().sql(sql).data(content).send(); - } - - void sendStream(Writer writer, HttpEntity content) throws ClickHouseException { - HttpEntity entity = null; - // TODO no parser involved so user can execute arbitray statement here - try { - String sql = writer.getSql(); - boolean isContentCompressed = writer.getCompression() != ClickHouseCompression.none; - URI uri = buildRequestUri(isContentCompressed ? sql : null, null, writer.getAdditionalDBParams(), - writer.getRequestParams(), false); - uri = followRedirects(uri); - - content = applyRequestBodyCompression(new WrappedHttpEntity(isContentCompressed ? null : sql, content)); - - HttpPost httpPost = new HttpPost(uri); - - if (writer.getCompression() != ClickHouseCompression.none) { - httpPost.addHeader("Content-Encoding", writer.getCompression().name()); - } - httpPost.setEntity(content); - HttpResponse response = client.execute(httpPost, httpContext); - entity = response.getEntity(); - checkForErrorAndThrow(entity, response); - - // retrieve response summary - if (isQueryParamSet(ClickHouseQueryParam.SEND_PROGRESS_IN_HTTP_HEADERS, writer.getAdditionalDBParams(), - writer.getRequestParams())) { - Header summaryHeader = response.getFirstHeader("X-ClickHouse-Summary"); - currentSummary = summaryHeader != null - ? JsonStreamUtils.readObject(summaryHeader.getValue(), ClickHouseResponseSummary.class) - : null; - } - } catch (ClickHouseException e) { - throw e; - } catch (Exception e) { - throw ClickHouseExceptionSpecifier.specify(e, properties.getHost(), properties.getPort()); - } finally { - EntityUtils.consumeQuietly(entity); - } - } - - private void checkForErrorAndThrow(HttpEntity entity, HttpResponse response) - throws IOException, ClickHouseException { - StatusLine line = response.getStatusLine(); - if (line.getStatusCode() != HttpURLConnection.HTTP_OK) { - InputStream messageStream = entity.getContent(); - byte[] bytes = Utils.toByteArray(messageStream); - if (properties.isCompress()) { - try { - messageStream = new ClickHouseLZ4Stream(new ByteArrayInputStream(bytes)); - bytes = Utils.toByteArray(messageStream); - } catch (IOException e) { - log.warn("error while read compressed stream %s", e.getMessage()); - } - } - EntityUtils.consumeQuietly(entity); - if (bytes.length == 0) { - throw ClickHouseExceptionSpecifier.specify(new IllegalStateException(line.toString()), - properties.getHost(), properties.getPort()); - } else { - throw ClickHouseExceptionSpecifier.specify(new String(bytes, StandardCharsets.UTF_8), - properties.getHost(), properties.getPort()); - } - } - } - - @Override - public void closeOnCompletion() throws SQLException { - closeOnCompletion = true; - } - - @Override - public boolean isCloseOnCompletion() throws SQLException { - return closeOnCompletion; - } - - private HttpEntity applyRequestBodyCompression(final HttpEntity entity) { - if (properties.isDecompress()) { - return new LZ4EntityWrapper(entity, properties.getMaxCompressBufferSize()); - } - return entity; - } - - private ClickHouseResultSet createResultSet(InputStream is, int bufferSize, String db, String table, - boolean usesWithTotals, ClickHouseStatement statement, TimeZone timezone, ClickHouseProperties properties) - throws IOException { - if (isResultSetScrollable) { - return new ClickHouseScrollableResultSet(is, bufferSize, db, table, usesWithTotals, statement, timezone, - properties); - } else { - return new ClickHouseResultSet(is, bufferSize, db, table, usesWithTotals, statement, timezone, properties); - } - } - - private Map addQueryIdTo(Map parameters) { - if (this.queryId != null) { - return parameters; - } - - String queryId = parameters.get(ClickHouseQueryParam.QUERY_ID); - if (queryId == null) { - // TODO perhaps we should use TimeUUID so that it's easy to sort? - this.queryId = UUID.randomUUID().toString(); - parameters.put(ClickHouseQueryParam.QUERY_ID, this.queryId); - } else { - this.queryId = queryId; - } - - return parameters; - } - - @Override - public Writer write() { - return new Writer(this).withDbParams(getAdditionalDBParams()).options(getRequestParams()); - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseUtil.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseUtil.java deleted file mode 100644 index 020f989af..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseUtil.java +++ /dev/null @@ -1,55 +0,0 @@ -package ru.yandex.clickhouse; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -public class ClickHouseUtil { - private static final Map escapeMapping; - - static { - Map map = new HashMap<>(); - map.put('\\', "\\\\"); - map.put('\n', "\\n"); - map.put('\t', "\\t"); - map.put('\b', "\\b"); - map.put('\f', "\\f"); - map.put('\r', "\\r"); - map.put('\0', "\\0"); - map.put('\'', "\\'"); - map.put('`', "\\`"); - escapeMapping = Collections.unmodifiableMap(map); - } - - public static String escape(String s) { - if (s == null) { - return "\\N"; - } - - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < s.length(); i++) { - char ch = s.charAt(i); - - String escaped = escapeMapping.get(ch); - if (escaped != null) { - sb.append(escaped); - } else { - sb.append(ch); - } - } - - return sb.toString(); - } - - public static String quoteIdentifier(String s) { - if (s == null) { - throw new IllegalArgumentException("Can't quote null as identifier"); - } - StringBuilder sb = new StringBuilder(s.length() + 2); - sb.append('`'); - sb.append(escape(s)); - sb.append('`'); - return sb.toString(); - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickhouseJdbcUrlParser.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickhouseJdbcUrlParser.java deleted file mode 100644 index ec64254dd..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickhouseJdbcUrlParser.java +++ /dev/null @@ -1,118 +0,0 @@ -package ru.yandex.clickhouse; - -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URLDecoder; -import java.nio.charset.StandardCharsets; -import java.util.Properties; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import com.clickhouse.client.logging.Logger; -import com.clickhouse.client.logging.LoggerFactory; - -import ru.yandex.clickhouse.settings.ClickHouseProperties; -import ru.yandex.clickhouse.settings.ClickHouseQueryParam; - -public class ClickhouseJdbcUrlParser { - private static final Logger log = LoggerFactory.getLogger(ClickhouseJdbcUrlParser.class); - - protected static final String DEFAULT_DATABASE = "default"; - - public static final String JDBC_PREFIX = "jdbc:"; - public static final String JDBC_CLICKHOUSE_PREFIX = JDBC_PREFIX + "clickhouse:"; - public static final Pattern DB_PATH_PATTERN = Pattern.compile("/([a-zA-Z0-9_*\\-]+)"); - - private ClickhouseJdbcUrlParser() { - } - - private static String decode(String str) { - try { - return URLDecoder.decode(str, StandardCharsets.UTF_8.name()); - } catch (UnsupportedEncodingException e) { - // don't print the content here as it may contain password - log.warn("Failed to decode given string, fallback to the original string"); - return str; - } - } - - private static ClickHouseProperties parseClickhouseUrl(String uriString, Properties defaults) - throws URISyntaxException { - URI uri = new URI(uriString); - Properties urlProperties = parseUriQueryPart(uri.getQuery(), defaults); - ClickHouseProperties props = new ClickHouseProperties(urlProperties); - String host = uri.getHost(); - if (host == null || host.isEmpty()) { - throw new IllegalArgumentException("host is missed or wrong"); - } - props.setHost(uri.getHost()); - int port = uri.getPort(); - if (port == -1) { - port = props.getProtocol().getDefaultPort(); - } - props.setPort(port); - String credentials = uri.getRawUserInfo(); - if (credentials != null && !credentials.isEmpty()) { - int index = credentials.indexOf(':'); - String userName = index == 0 ? "" : decode(index > 0 ? credentials.substring(0, index) : credentials); - if (!userName.isEmpty()) { - props.setUser(userName); - } - String password = index < 0 ? "" : decode(credentials.substring(index + 1)); - if (!password.isEmpty()) { - props.setPassword(password); - } - } - String path = uri.getPath(); - String database; - if (props.isUsePathAsDb()) { - if (path == null || path.isEmpty() || path.equals("/")) { - String defaultsDb = defaults.getProperty(ClickHouseQueryParam.DATABASE.getKey()); - database = defaultsDb == null ? DEFAULT_DATABASE : defaultsDb; - } else { - Matcher m = DB_PATH_PATTERN.matcher(path); - if (m.matches()) { - database = m.group(1); - } else { - throw new URISyntaxException("wrong database name path: '" + path + "'", uriString); - } - } - props.setDatabase(database); - } else { - if (props.getDatabase() == null || props.getDatabase().isEmpty()) { - props.setDatabase(DEFAULT_DATABASE); - } - if (path == null || path.isEmpty()) { - props.setPath("/"); - } else { - props.setPath(path); - } - } - return props; - } - - static Properties parseUriQueryPart(String query, Properties defaults) { - if (query == null) { - return defaults; - } - Properties urlProps = new Properties(defaults); - String[] queryKeyValues = query.split("&"); - for (String keyValue : queryKeyValues) { - String[] keyValueTokens = keyValue.split("="); - if (keyValueTokens.length == 2) { - urlProps.put(keyValueTokens[0], keyValueTokens[1]); - } else { - log.warn("don't know how to handle parameter pair: %s", keyValue); - } - } - return urlProps; - } - - public static ClickHouseProperties parse(String jdbcUrl, Properties defaults) throws URISyntaxException { - if (!jdbcUrl.startsWith(JDBC_CLICKHOUSE_PREFIX)) { - throw new URISyntaxException(jdbcUrl, "'" + JDBC_CLICKHOUSE_PREFIX + "' prefix is mandatory"); - } - return parseClickhouseUrl(jdbcUrl.substring(JDBC_PREFIX.length()), defaults); - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ConfigurableApi.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ConfigurableApi.java deleted file mode 100644 index 942b9e881..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ConfigurableApi.java +++ /dev/null @@ -1,62 +0,0 @@ -package ru.yandex.clickhouse; - -import ru.yandex.clickhouse.settings.ClickHouseQueryParam; - -import java.util.*; - -@SuppressWarnings("unchecked") -class ConfigurableApi { - - protected final ClickHouseStatementImpl statement; - private Map additionalDBParams = new HashMap(); - private Map additionalRequestParams = new HashMap(); - - ConfigurableApi(ClickHouseStatementImpl statement) { - this.statement = statement; - } - - Map getRequestParams() { - return additionalRequestParams; - } - - Map getAdditionalDBParams() { - return additionalDBParams; - } - - public T addDbParam(ClickHouseQueryParam param, String value) { - additionalDBParams.put(param, value); - return (T) this; - } - - public T removeDbParam(ClickHouseQueryParam param) { - additionalDBParams.remove(param); - return (T) this; - } - - public T withDbParams(Map dbParams) { - this.additionalDBParams = new HashMap(); - if (null != dbParams) { - additionalDBParams.putAll(dbParams); - } - return (T) this; - } - - public T options(Map params) { - additionalRequestParams = new HashMap(); - if (null != params) { - additionalRequestParams.putAll(params); - } - return (T) this; - } - - public T option(String key, String value) { - additionalRequestParams.put(key, value); - return (T) this; - } - - public T removeOption(String key) { - additionalRequestParams.remove(key); - return (T) this; - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/LZ4EntityWrapper.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/LZ4EntityWrapper.java deleted file mode 100644 index b10646517..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/LZ4EntityWrapper.java +++ /dev/null @@ -1,52 +0,0 @@ -package ru.yandex.clickhouse; - -import org.apache.http.HttpEntity; -import org.apache.http.entity.AbstractHttpEntity; -import ru.yandex.clickhouse.util.ClickHouseLZ4OutputStream; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -public class LZ4EntityWrapper extends AbstractHttpEntity { - private final HttpEntity delegate; - private final int maxCompressBlockSize; - public LZ4EntityWrapper(AbstractHttpEntity content, int maxCompressBlockSize) { - this.delegate = content; - this.maxCompressBlockSize = maxCompressBlockSize; - } - - public LZ4EntityWrapper(HttpEntity content, int maxCompressBlockSize) { - delegate = content; - this.maxCompressBlockSize = maxCompressBlockSize; - } - - - @Override - public boolean isRepeatable() { - return delegate.isRepeatable(); - } - - @Override - public long getContentLength() { - return -1; - } - - @Override - public InputStream getContent() throws IOException, IllegalStateException { - throw new UnsupportedOperationException(); - } - - @Override - public void writeTo(OutputStream outputStream) throws IOException { - ClickHouseLZ4OutputStream stream = new ClickHouseLZ4OutputStream(outputStream, maxCompressBlockSize); - delegate.writeTo(stream); - stream.flush(); - } - - @Override - public boolean isStreaming() { - return delegate.isStreaming(); - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/PreparedStatementParser.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/PreparedStatementParser.java deleted file mode 100644 index ea837f125..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/PreparedStatementParser.java +++ /dev/null @@ -1,196 +0,0 @@ -package ru.yandex.clickhouse; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import com.clickhouse.client.ClickHouseChecker; - -/** - * Parser for JDBC SQL Strings. - * - *

Tries to extract query parameters in a way that is usable for (batched) - * prepared statements. - */ -final class PreparedStatementParser { - - private static final Pattern VALUES = Pattern.compile( - "(?i)INSERT\\s+INTO\\s+.+VALUES\\s*\\(", - Pattern.MULTILINE | Pattern.DOTALL); - - private List> parameters; - private List parts; - private boolean valuesMode; - - private PreparedStatementParser() { - parameters = new ArrayList>(); - parts = new ArrayList(); - valuesMode = false; - } - - @Deprecated - static PreparedStatementParser parse(String sql) { - return parse(sql, -1); - } - - @Deprecated - static PreparedStatementParser parse(String sql, int valuesEndPosition) { - if (ClickHouseChecker.isNullOrBlank(sql)) { - throw new IllegalArgumentException("SQL may not be blank"); - } - PreparedStatementParser parser = new PreparedStatementParser(); - parser.parseSQL(sql, valuesEndPosition); - return parser; - } - - List> getParameters() { - return Collections.unmodifiableList(parameters); - } - - List getParts() { - return Collections.unmodifiableList(parts); - } - - boolean isValuesMode() { - return valuesMode; - } - - private void reset() { - parameters.clear(); - parts.clear(); - valuesMode = false; - } - - private void parseSQL(String sql, int valuesEndPosition) { - reset(); - List currentParamList = new ArrayList(); - boolean afterBackSlash = false; - boolean inQuotes = false; - boolean inBackQuotes = false; - boolean inSingleLineComment = false; - boolean inMultiLineComment = false; - boolean whiteSpace = false; - int endPosition = 0; - if (valuesEndPosition > 0) { - valuesMode = true; - endPosition = valuesEndPosition; - } else { - Matcher matcher = VALUES.matcher(sql); - if (matcher.find()) { - valuesMode = true; - endPosition = matcher.end() - 1; - } - } - - int currentParensLevel = 0; - int quotedStart = 0; - int partStart = 0; - int sqlLength = sql.length(); - for (int i = valuesMode ? endPosition : 0, idxStart = i, idxEnd = i; i < sqlLength; i++) { - char c = sql.charAt(i); - if (inSingleLineComment) { - if (c == '\n') { - inSingleLineComment = false; - } - } else if (inMultiLineComment) { - if (c == '*' && sqlLength > i + 1 && sql.charAt(i + 1) == '/') { - inMultiLineComment = false; - i++; - } - } else if (afterBackSlash) { - afterBackSlash = false; - } else if (c == '\\') { - afterBackSlash = true; - } else if (c == '\'' && !inBackQuotes) { - inQuotes = !inQuotes; - if (inQuotes) { - quotedStart = i; - } else if (!afterBackSlash) { - idxStart = quotedStart; - idxEnd = i + 1; - } - } else if (c == '`' && !inQuotes) { - inBackQuotes = !inBackQuotes; - } else if (!inQuotes && !inBackQuotes) { - if (c == '?') { - if (currentParensLevel > 0) { - idxStart = i; - idxEnd = i + 1; - } - if (!valuesMode) { - parts.add(sql.substring(partStart, i)); - partStart = i + 1; - currentParamList.add(ClickHousePreparedStatementImpl.PARAM_MARKER); - } - } else if (c == '-' && sqlLength > i + 1 && sql.charAt(i + 1) == '-') { - inSingleLineComment = true; - i++; - } else if (c == '/' && sqlLength > i + 1 && sql.charAt(i + 1) == '*') { - inMultiLineComment = true; - i++; - } else if (c == ',') { - if (valuesMode && idxEnd > idxStart) { - currentParamList.add(typeTransformParameterValue(sql.substring(idxStart, idxEnd))); - parts.add(sql.substring(partStart, idxStart)); - partStart = idxEnd; - idxStart = idxEnd = i; - } - idxStart++; - idxEnd++; - } else if (c == '(') { - currentParensLevel++; - idxStart++; - idxEnd++; - } else if (c == ')') { - currentParensLevel--; - if (valuesMode && currentParensLevel == 0) { - if (idxEnd > idxStart) { - currentParamList.add(typeTransformParameterValue(sql.substring(idxStart, idxEnd))); - parts.add(sql.substring(partStart, idxStart)); - partStart = idxEnd; - idxStart = idxEnd = i; - } - if (!currentParamList.isEmpty()) { - parameters.add(currentParamList); - currentParamList = new ArrayList(currentParamList.size()); - } - } - } else if (Character.isWhitespace(c)) { - whiteSpace = true; - } else if (currentParensLevel > 0) { - if (whiteSpace) { - idxStart = i; - idxEnd = i + 1; - } else { - idxEnd++; - } - whiteSpace = false; - } - } - } - if (!valuesMode && !currentParamList.isEmpty()) { - parameters.add(currentParamList); - } - String lastPart = sql.substring(partStart, sqlLength); - parts.add(lastPart); - } - - private static String typeTransformParameterValue(String paramValue) { - if (paramValue == null) { - return null; - } - if (Boolean.TRUE.toString().equalsIgnoreCase(paramValue)) { - return "1"; - } - if (Boolean.FALSE.toString().equalsIgnoreCase(paramValue)) { - return "0"; - } - if ("NULL".equalsIgnoreCase(paramValue)) { - return ClickHousePreparedStatementImpl.NULL_MARKER; - } - return paramValue; - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ResponseFactory.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ResponseFactory.java deleted file mode 100644 index b28d6fe09..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ResponseFactory.java +++ /dev/null @@ -1,13 +0,0 @@ -package ru.yandex.clickhouse; - -import java.io.IOException; -import java.io.InputStream; - -/** - * Interface for consuming content from server response and - * @param type of response - */ -public interface ResponseFactory { - - public T create(InputStream response) throws IOException; -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/Writer.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/Writer.java deleted file mode 100644 index dd24fccec..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/Writer.java +++ /dev/null @@ -1,255 +0,0 @@ -package ru.yandex.clickhouse; - -import static ru.yandex.clickhouse.domain.ClickHouseFormat.Native; -import static ru.yandex.clickhouse.domain.ClickHouseFormat.RowBinary; -import static ru.yandex.clickhouse.domain.ClickHouseFormat.TabSeparated; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.sql.SQLException; -import java.util.Objects; - -import org.apache.http.HttpEntity; -import org.apache.http.entity.InputStreamEntity; -import ru.yandex.clickhouse.domain.ClickHouseCompression; -import ru.yandex.clickhouse.domain.ClickHouseFormat; -import ru.yandex.clickhouse.settings.ClickHouseQueryParam; -import ru.yandex.clickhouse.util.ClickHouseStreamCallback; -import ru.yandex.clickhouse.util.ClickHouseStreamHttpEntity; - -public class Writer extends ConfigurableApi { - - private ClickHouseFormat format = TabSeparated; - private ClickHouseCompression compression = null; - private String table = null; - private String sql = null; - private InputStreamProvider streamProvider = null; - - Writer(ClickHouseStatementImpl statement) { - super(statement); - - dataCompression(ClickHouseCompression.none); - } - - /** - * Specifies format for further insert of data via send(). - * - * @param format - * the format of the data to upload - * @return this writer instance - */ - public Writer format(ClickHouseFormat format) { - if (null == format) { - throw new NullPointerException("Format can not be null"); - } - this.format = format; - return this; - } - - /** - * Set table name for data insertion. - * - * @param table - * name of the table to upload the data to - * @return this writer instance - */ - public Writer table(String table) { - this.sql = null; - this.table = table; - return this; - } - - /** - * Set SQL for data insertion. - * - * @param sql - * in a form "INSERT INTO table_name [(X,Y,Z)] VALUES " - * @return this writer instance - */ - public Writer sql(String sql) { - this.sql = sql; - this.table = null; - return this; - } - - /** - * Specifies data input stream. - * - * @param stream - * a stream providing the data to upload - * @return this writer instance - */ - public Writer data(InputStream stream) { - streamProvider = new HoldingInputProvider(stream); - return this; - } - - /** - * Specifies data input stream, and the format to use. - * - * @param stream - * a stream providing the data to upload - * @param format - * the format of the data to upload - * @return this writer instance - */ - public Writer data(InputStream stream, ClickHouseFormat format) { - return format(format).data(stream); - } - - /** - * Shortcut method for specifying a file as an input. - * - * @param input - * the file to upload - * @return this writer instance - */ - public Writer data(File input) { - streamProvider = new FileInputProvider(input); - return this; - } - - public Writer data(InputStream stream, ClickHouseFormat format, ClickHouseCompression compression) { - return dataCompression(compression).format(format).data(stream); - } - - public Writer data(File input, ClickHouseFormat format, ClickHouseCompression compression) { - return dataCompression(compression).format(format).data(input); - } - - public Writer dataCompression(ClickHouseCompression compression) { - this.compression = Objects.requireNonNull(compression, "Compression can not be null"); - this.addDbParam(ClickHouseQueryParam.COMPRESS, String.valueOf(compression != ClickHouseCompression.none)); - - return this; - } - - public Writer data(File input, ClickHouseFormat format) { - return format(format).data(input); - } - - /** - * Method to call, when Writer is fully configured. - */ - public void send() throws SQLException { - HttpEntity entity; - try { - InputStream stream; - if (null == streamProvider || null == (stream = streamProvider.get())) { - throw new IOException("No input data specified"); - } - entity = new InputStreamEntity(stream); - } catch (IOException err) { - throw new SQLException(err); - } - send(entity); - } - - private void send(HttpEntity entity) throws SQLException { - statement.sendStream(this, entity); - } - - /** - * Allows to send stream of data to ClickHouse. - * - * @param sql - * in a form of "INSERT INTO table_name (X,Y,Z) VALUES " - * @param data - * where to read data from - * @param format - * format of data in InputStream - * @throws SQLException - * if the upload fails - */ - public void send(String sql, InputStream data, ClickHouseFormat format) throws SQLException { - sql(sql).data(data).format(format).send(); - } - - /** - * Convenient method for importing the data into table. - * - * @param table - * table name - * @param data - * source data - * @param format - * format of data in InputStream - * @throws SQLException - * if the upload fails - */ - public void sendToTable(String table, InputStream data, ClickHouseFormat format) throws SQLException { - table(table).data(data).format(format).send(); - } - - /** - * Sends the data in {@link ClickHouseFormat#RowBinary RowBinary} or in - * {@link ClickHouseFormat#Native Native} format. - * - * @param sql - * the SQL statement to execute - * @param callback - * data source for the upload - * @param format - * the format to use, either {@link ClickHouseFormat#RowBinary - * RowBinary} or {@link ClickHouseFormat#Native Native} - * @throws SQLException - * if the upload fails - */ - public void send(String sql, ClickHouseStreamCallback callback, ClickHouseFormat format) throws SQLException { - if (!(RowBinary.equals(format) || Native.equals(format))) { - throw new SQLException("Wrong binary format - only RowBinary and Native are supported"); - } - - format(format).sql(sql).send(new ClickHouseStreamHttpEntity(callback, statement.getConnection().getTimeZone(), statement.properties)); - } - - String getSql() { - if (null != table) { - return "INSERT INTO " + table + " FORMAT " + format; - } else if (null != sql) { - String result = sql; - if (!ClickHouseFormat.containsFormat(result)) { - result += " FORMAT " + format; - } - return result; - } else { - throw new IllegalArgumentException("Neither table nor SQL clause are specified"); - } - } - - private interface InputStreamProvider { - InputStream get() throws IOException; - } - - private static final class FileInputProvider implements InputStreamProvider { - private final File file; - - private FileInputProvider(File file) { - this.file = file; - } - - @Override - public InputStream get() throws IOException { - return new FileInputStream(file); - } - } - - private static final class HoldingInputProvider implements InputStreamProvider { - private final InputStream stream; - - private HoldingInputProvider(InputStream stream) { - this.stream = stream; - } - - @Override - public InputStream get() throws IOException { - return stream; - } - } - - public ClickHouseCompression getCompression() { - return compression; - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/domain/ClickHouseCompression.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/domain/ClickHouseCompression.java deleted file mode 100644 index d9269d631..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/domain/ClickHouseCompression.java +++ /dev/null @@ -1,9 +0,0 @@ -package ru.yandex.clickhouse.domain; - -public enum ClickHouseCompression { - none, - gzip, - brotli, - deflate, - zstd; -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/domain/ClickHouseDataType.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/domain/ClickHouseDataType.java deleted file mode 100644 index 2c3e4e41e..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/domain/ClickHouseDataType.java +++ /dev/null @@ -1,179 +0,0 @@ -package ru.yandex.clickhouse.domain; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Array; -import java.sql.Date; -import java.sql.JDBCType; -import java.sql.Timestamp; -import java.util.Collections; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.UUID; - -/** - * Basic ClickHouse data types. - *

- * This list is based on the list of data type families returned by - * {@code SELECT * FROM system.data_type_families} - *

- * {@code LowCardinality} and {@code Nullable} are technically data types in - * ClickHouse, but for the sake of this driver, we treat these data types as - * modifiers for the underlying base data types. - */ -public enum ClickHouseDataType { - // aliases: - // https://clickhouse.tech/docs/en/sql-reference/data-types/multiword-types/ - // https://github.com/ClickHouse/ClickHouse/blob/master/src/DataTypes/DataTypeCustomIPv4AndIPv6.cpp - // https://github.com/ClickHouse/ClickHouse/blob/master/src/DataTypes/registerDataTypeDateTime.cpp - // https://github.com/ClickHouse/ClickHouse/blob/master/src/DataTypes/DataTypesDecimal.cpp - // https://github.com/ClickHouse/ClickHouse/blob/master/src/DataTypes/DataTypeFixedString.cpp - // https://github.com/ClickHouse/ClickHouse/blob/master/src/DataTypes/DataTypesNumber.cpp - // https://github.com/ClickHouse/ClickHouse/blob/master/src/DataTypes/DataTypeString.cpp - IntervalYear(JDBCType.INTEGER, Integer.class, true, 19, 0), - IntervalQuarter(JDBCType.INTEGER, Integer.class, true, 19, 0), - IntervalMonth(JDBCType.INTEGER, Integer.class, true, 19, 0), - IntervalWeek(JDBCType.INTEGER, Integer.class, true, 19, 0), - IntervalDay(JDBCType.INTEGER, Integer.class, true, 19, 0), - IntervalHour(JDBCType.INTEGER, Integer.class, true, 19, 0), - IntervalMinute(JDBCType.INTEGER, Integer.class, true, 19, 0), - IntervalSecond(JDBCType.INTEGER, Integer.class, true, 19, 0), - UInt256(JDBCType.NUMERIC, BigInteger.class, true, 39, 0), - UInt128(JDBCType.NUMERIC, BigInteger.class, true, 20, 0), - UInt64(JDBCType.BIGINT, BigInteger.class, false, 19, 0, - "BIGINT UNSIGNED"), - UInt32(JDBCType.BIGINT, Long.class, false, 10, 0, - "INT UNSIGNED", "INTEGER UNSIGNED", "MEDIUMINT UNSIGNED"), - UInt16(JDBCType.SMALLINT, Integer.class, false, 5, 0, - "SMALLINT UNSIGNED"), - UInt8(JDBCType.TINYINT, Integer.class, false, 3, 0, - "TINYINT UNSIGNED", "INT1 UNSIGNED"), - Int256(JDBCType.NUMERIC, BigInteger.class, true, 40, 0), - Int128(JDBCType.NUMERIC, BigInteger.class, true, 20, 0), - Int64(JDBCType.BIGINT, Long.class, true, 20, 0, - "BIGINT", "BIGINT SIGNED"), - Int32(JDBCType.INTEGER, Integer.class, true, 11, 0, - "INT", "INTEGER", "MEDIUMINT", "INT SIGNED", "INTEGER SIGNED", "MEDIUMINT SIGNED"), - Int16(JDBCType.SMALLINT, Integer.class, true, 6, 0, - "SMALLINT", "SMALLINT SIGNED"), - Int8(JDBCType.TINYINT, Integer.class, true, 4, 0, - "TINYINT", "BOOL", "BOOLEAN", "INT1", "BYTE", "TINYINT SIGNED", "INT1 SIGNED"), - Date(JDBCType.DATE, Date.class, false, 10, 0), - DateTime(JDBCType.TIMESTAMP, Timestamp.class, false, 19, 0, - "TIMESTAMP"), - DateTime32(JDBCType.TIMESTAMP, Timestamp.class, false, 19, 0), - DateTime64(JDBCType.TIMESTAMP, Timestamp.class, false, 38, 3), // scale up to 18 - Enum8(JDBCType.VARCHAR, String.class, false, 0, 0, - "ENUM"), - Enum16(JDBCType.VARCHAR, String.class, false, 0, 0), - Float32(JDBCType.REAL, Float.class, true, 8, 8, - "SINGLE", "REAL"), - Float64(JDBCType.DOUBLE, Double.class, true, 17, 17, - "DOUBLE", "DOUBLE PRECISION"), - Decimal32(JDBCType.DECIMAL, BigDecimal.class, true, 9, 9), - Decimal64(JDBCType.DECIMAL, BigDecimal.class, true, 18, 18), - Decimal128(JDBCType.DECIMAL, BigDecimal.class, true, 38, 38), - Decimal256(JDBCType.DECIMAL, BigDecimal.class, true, 76, 20), - Decimal(JDBCType.DECIMAL, BigDecimal.class, true, 0, 0, - "DEC", "NUMERIC", "FIXED"), - UUID(JDBCType.OTHER, UUID.class, false, 36, 0), - IPv4(JDBCType.VARCHAR, String.class, false, 10, 0), - IPv6(JDBCType.VARCHAR, String.class, false, 0, 0), - String(JDBCType.VARCHAR, String.class, false, 0, 0, - "CHAR", "NCHAR", "CHARACTER", "VARCHAR", "NVARCHAR", "VARCHAR2", - "TEXT", "TINYTEXT", "MEDIUMTEXT", "LONGTEXT", - "BLOB", "CLOB", "TINYBLOB", "MEDIUMBLOB", "LONGBLOB", "BYTEA", - "CHARACTER LARGE OBJECT", "CHARACTER VARYING", "CHAR LARGE OBJECT", "CHAR VARYING", - "NATIONAL CHAR", "NATIONAL CHARACTER", "NATIONAL CHARACTER LARGE OBJECT", - "NATIONAL CHARACTER VARYING", "NATIONAL CHAR VARYING", - "NCHAR VARYING", "NCHAR LARGE OBJECT", "BINARY LARGE OBJECT", "BINARY VARYING"), - FixedString(JDBCType.CHAR, String.class, false, -1, 0, - "BINARY"), - Nothing(JDBCType.NULL, Object.class, false, 0, 0), - Nested(JDBCType.STRUCT, String.class, false, 0, 0), - // TODO use list/collection for Tuple - Tuple(JDBCType.OTHER, String.class, false, 0, 0), - Array(JDBCType.ARRAY, Array.class, false, 0, 0), - Map(JDBCType.OTHER, Map.class, false, 0, 0), - AggregateFunction(JDBCType.OTHER, String.class, false, 0, 0), - Unknown(JDBCType.OTHER, String.class, false, 0, 0); - - private static final Map name2type; - - static { - Map map = new HashMap<>(); - String errorMsg = "[%s] is used by type [%s]"; - ClickHouseDataType used = null; - for (ClickHouseDataType t : ClickHouseDataType.values()) { - used = map.put(t.name(), t); - if (used != null) { - throw new IllegalStateException(java.lang.String.format(errorMsg, t.name(), used.name())); - } - String nameInUpperCase = t.name().toUpperCase(Locale.ROOT); - if (!nameInUpperCase.equals(t.name())) { - used = map.put(nameInUpperCase, t); - if (used != null) { - throw new IllegalStateException(java.lang.String.format(errorMsg, nameInUpperCase, used.name())); - } - } - for (String alias : t.aliases) { - used = map.put(alias.toUpperCase(Locale.ROOT), t); - if (used != null) { - throw new IllegalStateException(java.lang.String.format(errorMsg, alias, used.name())); - } - } - } - name2type = Collections.unmodifiableMap(map); - } - - private final JDBCType jdbcType; - private final Class javaClass; - private final boolean signed; - private final int defaultPrecision; - private final int defaultScale; - private final String[] aliases; - - ClickHouseDataType(JDBCType jdbcType, Class javaClass, - boolean signed, int defaultPrecision, int defaultScale, - String... aliases) { - this.jdbcType = jdbcType; - this.javaClass = javaClass; - this.signed = signed; - this.defaultPrecision = defaultPrecision; - this.defaultScale = defaultScale; - this.aliases = aliases; - } - - public int getSqlType() { - return jdbcType.getVendorTypeNumber().intValue(); - } - - public JDBCType getJdbcType() { - return jdbcType; - } - - public Class getJavaClass() { - return javaClass; - } - - public boolean isSigned() { - return signed; - } - - public int getDefaultPrecision() { - return defaultPrecision; - } - - public int getDefaultScale() { - return defaultScale; - } - - public static ClickHouseDataType fromTypeString(String typeString) { - return name2type.getOrDefault(typeString.trim().toUpperCase(Locale.ROOT), ClickHouseDataType.Unknown); - } - - public static ClickHouseDataType resolveDefaultArrayDataType(String typeName) { - return name2type.getOrDefault(typeName, ClickHouseDataType.String); - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/domain/ClickHouseFormat.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/domain/ClickHouseFormat.java deleted file mode 100644 index bd5d081c1..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/domain/ClickHouseFormat.java +++ /dev/null @@ -1,129 +0,0 @@ -package ru.yandex.clickhouse.domain; - -/** - * Input / Output formats supported by ClickHouse - *

- * Note that the sole existence of a format in this enumeration does not mean - * that its use is supported for any operation with this JDBC driver. When in - * doubt, just omit any specific format and let the driver take care of it. - *

- * - * @see ClickHouse - * Reference Documentation - * - * @author Dmitry Andreev - */ -public enum ClickHouseFormat { - Arrow(true, true, true, true, false), // https://clickhouse.tech/docs/en/interfaces/formats/#arrow - ArrowStream(true, true, true, true, false), // https://clickhouse.tech/docs/en/interfaces/formats/#arrowstream - Avro(true, true, true, true, false), // https://clickhouse.tech/docs/en/interfaces/formats/#avro - AvroConfluent(true, false, true, false, false), // https://clickhouse.tech/docs/en/interfaces/formats/#avroconfluent - CapnProto(true, false, true, false, false), // https://clickhouse.tech/docs/en/interfaces/formats/#capnproto - CSV(true, true, false, false, true), // https://clickhouse.tech/docs/en/interfaces/formats/#csv - CSVWithNames(true, true, false, true, true), // https://clickhouse.tech/docs/en/interfaces/formats/#csvwithnames - CustomSeparated(true, true, false, false, true), // https://clickhouse.tech/docs/en/interfaces/formats/#customseparated - JSON(false, true, false, false, false), // https://clickhouse.tech/docs/en/interfaces/formats/#json - JSONAsString(true, false, false, false, false), // https://clickhouse.tech/docs/en/interfaces/formats/#jsonasstring - JSONCompact(false, true, false, false, false), // https://clickhouse.tech/docs/en/interfaces/formats/#jsoncompact - JSONCompactEachRow(true, true, false, false, true), // https://clickhouse.tech/docs/en/interfaces/formats/#jsoncompacteachrow - JSONCompactEachRowWithNamesAndTypes(true, true, false, true, true), // https://clickhouse.tech/docs/en/interfaces/formats/#jsoncompacteachrowwithnamesandtypes - JSONCompactString(false, true, false, false, false), // https://clickhouse.tech/docs/en/interfaces/formats/#jsoncompactstring - JSONCompactStringEachRow(true, true, false, false, true), // https://clickhouse.tech/docs/en/interfaces/formats/#jsoncompactstringeachrow - JSONCompactStringEachRowWithNamesAndTypes(true, true, false, true, true), // https://clickhouse.tech/docs/en/interfaces/formats/#jsoncompactstringeachrowwithnamesandtypes - JSONEachRow(true, true, false, false, true), // https://clickhouse.tech/docs/en/interfaces/formats/#jsoneachrow - JSONEachRowWithProgress(false, true, false, false, true), // https://clickhouse.tech/docs/en/interfaces/formats/#jsoneachrowwithprogress - JSONString(false, true, false, false, false), // https://clickhouse.tech/docs/en/interfaces/formats/#jsonstring - JSONStringsEachRow(true, true, false, false, true), // https://clickhouse.tech/docs/en/interfaces/formats/#jsonstringseachrow - JSONStringsEachRowWithProgress(false, true, false, false, true), // https://clickhouse.tech/docs/en/interfaces/formats/#jsonstringseachrowwithprogress - LineAsString(true, false, false, false, true), // https://clickhouse.tech/docs/en/interfaces/formats/#lineasstring - Native(true, true, true, true, false), // https://clickhouse.tech/docs/en/interfaces/formats/#native - Null(false, true, false, false, false), // https://clickhouse.tech/docs/en/interfaces/formats/#null - ORC(true, false, true, true, false), // https://clickhouse.tech/docs/en/interfaces/formats/#orc - Parquet(true, true, true, true, false), // https://clickhouse.tech/docs/en/interfaces/formats/#parquet - Pretty(false, true, false, false, false), // https://clickhouse.tech/docs/en/interfaces/formats/#pretty - PrettyCompact(false, true, false, false, false), // https://clickhouse.tech/docs/en/interfaces/formats/#prettycompact - PrettyCompactMonoBlock(false, true, false, false, false), // https://clickhouse.tech/docs/en/interfaces/formats/#prettycompactmonoblock - PrettyNoEscapes(false, true, false, false, false), // https://clickhouse.tech/docs/en/interfaces/formats/#prettynoescapes - PrettySpace(false, true, false, false, false), // https://clickhouse.tech/docs/en/interfaces/formats/#prettyspace - Protobuf(true, true, true, true, false), // https://clickhouse.tech/docs/en/interfaces/formats/#protobuf - ProtobufSingle(true, true, true, true, false), // https://clickhouse.tech/docs/en/interfaces/formats/#protobufsingle - RawBLOB(true, true, true, false, false), // https://clickhouse.tech/docs/en/interfaces/formats/#rawblob - Regexp(true, false, false, false, false), // https://clickhouse.tech/docs/en/interfaces/formats/#regexp - RowBinary(true, true, true, false, true), // https://clickhouse.tech/docs/en/interfaces/formats/#rowbinary - RowBinaryWithNamesAndTypes(true, true, true, true, true), // https://clickhouse.tech/docs/en/interfaces/formats/#rowbinarywithnamesandtypes - TabSeparated(true, true, false, false, true), // https://clickhouse.tech/docs/en/interfaces/formats/#tabseparated - TabSeparatedRaw(true, true, false, false, true), // https://clickhouse.tech/docs/en/interfaces/formats/#tabseparatedraw - TabSeparatedWithNames(true, true, false, true, true), // https://clickhouse.tech/docs/en/interfaces/formats/#tabseparatedwithnames - TabSeparatedWithNamesAndTypes(true, true, false, true, true), // https://clickhouse.tech/docs/en/interfaces/formats/#tabseparatedwithnamesandtypes - TSV(true, true, false, false, true), // alias of TabSeparated - TSVRaw(true, true, false, false, true), // alias of TabSeparatedRaw - TSVWithNames(true, true, false, true, true), // alias of TabSeparatedWithNames - TSVWithNamesAndTypes(true, true, false, true, true), // alias of TabSeparatedWithNamesAndTypes - Template(true, true, false, true, true), // https://clickhouse.tech/docs/en/interfaces/formats/#template - TemplateIgnoreSpaces(true, false, false, true, true), // https://clickhouse.tech/docs/en/interfaces/formats/#templateignorespaces - TSKV(true, true, false, false, false), // https://clickhouse.tech/docs/en/interfaces/formats/#tskv - Values(true, true, false, false, true), // https://clickhouse.tech/docs/en/interfaces/formats/#values - Vertical(false, true, false, false, false), // https://clickhouse.tech/docs/en/interfaces/formats/#vertical - VerticalRaw(false, true, false, false, false), // https://clickhouse.tech/docs/en/interfaces/formats/#verticalraw - XML(false, true, false, false, false); // https://clickhouse.tech/docs/en/interfaces/formats/#xml - - private boolean input; - private boolean output; - private boolean binary; - private boolean header; - private boolean rowBased; - - ClickHouseFormat(boolean input, boolean output, boolean binary, boolean header, boolean rowBased) { - this.input = input; - this.output = output; - this.binary = binary; - this.header = output && header; - this.rowBased = rowBased; - } - - public boolean supportsInput() { - return input; - } - - public boolean supportsOutput() { - return output; - } - - public boolean isBinary() { - return binary; - } - - public boolean isText() { - return !binary; - } - - public boolean hasHeader() { - return header; - } - - /** - * Check whether the format is row based(e.g. read/write by row), which is a - * very useful hint on how to process the data. - * - * @return true if the format is row based; false otherwise(e.g. column, - * document, or structured-object etc.) - */ - public boolean isRowBased() { - return rowBased; - } - - public static boolean containsFormat(String statement) { - if (statement == null || statement.isEmpty()) { - return false; - } - // TODO: Proper parsing of comments etc. - String s = statement.replaceAll("[;\\s]", ""); - for (ClickHouseFormat f : values()) { - if (s.endsWith(f.name())) { - return true; - } - } - return false; - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/except/ClickHouseErrorCode.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/except/ClickHouseErrorCode.java deleted file mode 100644 index 47e9e7e9f..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/except/ClickHouseErrorCode.java +++ /dev/null @@ -1,477 +0,0 @@ -package ru.yandex.clickhouse.except; - -import java.util.*; - -public enum ClickHouseErrorCode { - OK(0), - UNSUPPORTED_METHOD(1), - UNSUPPORTED_PARAMETER(2), - UNEXPECTED_END_OF_FILE(3), - EXPECTED_END_OF_FILE(4), - CANNOT_PARSE_TEXT(6), - INCORRECT_NUMBER_OF_COLUMNS(7), - THERE_IS_NO_COLUMN(8), - SIZES_OF_COLUMNS_DOESNT_MATCH(9), - NOT_FOUND_COLUMN_IN_BLOCK(10), - POSITION_OUT_OF_BOUND(11), - PARAMETER_OUT_OF_BOUND(12), - SIZES_OF_COLUMNS_IN_TUPLE_DOESNT_MATCH(13), - DUPLICATE_COLUMN(15), - NO_SUCH_COLUMN_IN_TABLE(16), - DELIMITER_IN_STRING_LITERAL_DOESNT_MATCH(17), - CANNOT_INSERT_ELEMENT_INTO_CONSTANT_COLUMN(18), - SIZE_OF_FIXED_STRING_DOESNT_MATCH(19), - NUMBER_OF_COLUMNS_DOESNT_MATCH(20), - CANNOT_READ_ALL_DATA_FROM_TAB_SEPARATED_INPUT(21), - CANNOT_PARSE_ALL_VALUE_FROM_TAB_SEPARATED_INPUT(22), - CANNOT_READ_FROM_ISTREAM(23), - CANNOT_WRITE_TO_OSTREAM(24), - CANNOT_PARSE_ESCAPE_SEQUENCE(25), - CANNOT_PARSE_QUOTED_STRING(26), - CANNOT_PARSE_INPUT_ASSERTION_FAILED(27), - CANNOT_PRINT_FLOAT_OR_DOUBLE_NUMBER(28), - CANNOT_PRINT_INTEGER(29), - CANNOT_READ_SIZE_OF_COMPRESSED_CHUNK(30), - CANNOT_READ_COMPRESSED_CHUNK(31), - ATTEMPT_TO_READ_AFTER_EOF(32), - CANNOT_READ_ALL_DATA(33), - TOO_MUCH_ARGUMENTS_FOR_FUNCTION(34), - TOO_LESS_ARGUMENTS_FOR_FUNCTION(35), - BAD_ARGUMENTS(36), - UNKNOWN_ELEMENT_IN_AST(37), - CANNOT_PARSE_DATE(38), - TOO_LARGE_SIZE_COMPRESSED(39), - CHECKSUM_DOESNT_MATCH(40), - CANNOT_PARSE_DATETIME(41), - NUMBER_OF_ARGUMENTS_DOESNT_MATCH(42), - ILLEGAL_TYPE_OF_ARGUMENT(43), - ILLEGAL_COLUMN(44), - ILLEGAL_NUMBER_OF_RESULT_COLUMNS(45), - UNKNOWN_FUNCTION(46), - UNKNOWN_IDENTIFIER(47), - NOT_IMPLEMENTED(48), - LOGICAL_ERROR(49), - UNKNOWN_TYPE(50), - EMPTY_LIST_OF_COLUMNS_QUERIED(51), - COLUMN_QUERIED_MORE_THAN_ONCE(52), - TYPE_MISMATCH(53), - STORAGE_DOESNT_ALLOW_PARAMETERS(54), - STORAGE_REQUIRES_PARAMETER(55), - UNKNOWN_STORAGE(56), - TABLE_ALREADY_EXISTS(57), - TABLE_METADATA_ALREADY_EXISTS(58), - ILLEGAL_TYPE_OF_COLUMN_FOR_FILTER(59), - UNKNOWN_TABLE(60), - ONLY_FILTER_COLUMN_IN_BLOCK(61), - SYNTAX_ERROR(62), - UNKNOWN_AGGREGATE_FUNCTION(63), - CANNOT_READ_AGGREGATE_FUNCTION_FROM_TEXT(64), - CANNOT_WRITE_AGGREGATE_FUNCTION_AS_TEXT(65), - NOT_A_COLUMN(66), - ILLEGAL_KEY_OF_AGGREGATION(67), - CANNOT_GET_SIZE_OF_FIELD(68), - ARGUMENT_OUT_OF_BOUND(69), - CANNOT_CONVERT_TYPE(70), - CANNOT_WRITE_AFTER_END_OF_BUFFER(71), - CANNOT_PARSE_NUMBER(72), - UNKNOWN_FORMAT(73), - CANNOT_READ_FROM_FILE_DESCRIPTOR(74), - CANNOT_WRITE_TO_FILE_DESCRIPTOR(75), - CANNOT_OPEN_FILE(76), - CANNOT_CLOSE_FILE(77), - UNKNOWN_TYPE_OF_QUERY(78), - INCORRECT_FILE_NAME(79), - INCORRECT_QUERY(80), - UNKNOWN_DATABASE(81), - DATABASE_ALREADY_EXISTS(82), - DIRECTORY_DOESNT_EXIST(83), - DIRECTORY_ALREADY_EXISTS(84), - FORMAT_IS_NOT_SUITABLE_FOR_INPUT(85), - RECEIVED_ERROR_FROM_REMOTE_IO_SERVER(86), - CANNOT_SEEK_THROUGH_FILE(87), - CANNOT_TRUNCATE_FILE(88), - UNKNOWN_COMPRESSION_METHOD(89), - EMPTY_LIST_OF_COLUMNS_PASSED(90), - SIZES_OF_MARKS_FILES_ARE_INCONSISTENT(91), - EMPTY_DATA_PASSED(92), - UNKNOWN_AGGREGATED_DATA_VARIANT(93), - CANNOT_MERGE_DIFFERENT_AGGREGATED_DATA_VARIANTS(94), - CANNOT_READ_FROM_SOCKET(95), - CANNOT_WRITE_TO_SOCKET(96), - CANNOT_READ_ALL_DATA_FROM_CHUNKED_INPUT(97), - CANNOT_WRITE_TO_EMPTY_BLOCK_OUTPUT_STREAM(98), - UNKNOWN_PACKET_FROM_CLIENT(99), - UNKNOWN_PACKET_FROM_SERVER(100), - UNEXPECTED_PACKET_FROM_CLIENT(101), - UNEXPECTED_PACKET_FROM_SERVER(102), - RECEIVED_DATA_FOR_WRONG_QUERY_ID(103), - TOO_SMALL_BUFFER_SIZE(104), - CANNOT_READ_HISTORY(105), - CANNOT_APPEND_HISTORY(106), - FILE_DOESNT_EXIST(107), - NO_DATA_TO_INSERT(108), - CANNOT_BLOCK_SIGNAL(109), - CANNOT_UNBLOCK_SIGNAL(110), - CANNOT_MANIPULATE_SIGSET(111), - CANNOT_WAIT_FOR_SIGNAL(112), - THERE_IS_NO_SESSION(113), - CANNOT_CLOCK_GETTIME(114), - UNKNOWN_SETTING(115), - THERE_IS_NO_DEFAULT_VALUE(116), - INCORRECT_DATA(117), - TABLE_METADATA_DOESNT_EXIST(118), - ENGINE_REQUIRED(119), - CANNOT_INSERT_VALUE_OF_DIFFERENT_SIZE_INTO_TUPLE(120), - UNKNOWN_SET_DATA_VARIANT(121), - INCOMPATIBLE_COLUMNS(122), - UNKNOWN_TYPE_OF_AST_NODE(123), - INCORRECT_ELEMENT_OF_SET(124), - INCORRECT_RESULT_OF_SCALAR_SUBQUERY(125), - CANNOT_GET_RETURN_TYPE(126), - ILLEGAL_INDEX(127), - TOO_LARGE_ARRAY_SIZE(128), - FUNCTION_IS_SPECIAL(129), - CANNOT_READ_ARRAY_FROM_TEXT(130), - TOO_LARGE_STRING_SIZE(131), - CANNOT_CREATE_TABLE_FROM_METADATA(132), - AGGREGATE_FUNCTION_DOESNT_ALLOW_PARAMETERS(133), - PARAMETERS_TO_AGGREGATE_FUNCTIONS_MUST_BE_LITERALS(134), - ZERO_ARRAY_OR_TUPLE_INDEX(135), - UNKNOWN_ELEMENT_IN_CONFIG(137), - EXCESSIVE_ELEMENT_IN_CONFIG(138), - NO_ELEMENTS_IN_CONFIG(139), - ALL_REQUESTED_COLUMNS_ARE_MISSING(140), - SAMPLING_NOT_SUPPORTED(141), - NOT_FOUND_NODE(142), - FOUND_MORE_THAN_ONE_NODE(143), - FIRST_DATE_IS_BIGGER_THAN_LAST_DATE(144), - UNKNOWN_OVERFLOW_MODE(145), - QUERY_SECTION_DOESNT_MAKE_SENSE(146), - NOT_FOUND_FUNCTION_ELEMENT_FOR_AGGREGATE(147), - NOT_FOUND_RELATION_ELEMENT_FOR_CONDITION(148), - NOT_FOUND_RHS_ELEMENT_FOR_CONDITION(149), - NO_ATTRIBUTES_LISTED(150), - INDEX_OF_COLUMN_IN_SORT_CLAUSE_IS_OUT_OF_RANGE(151), - UNKNOWN_DIRECTION_OF_SORTING(152), - ILLEGAL_DIVISION(153), - AGGREGATE_FUNCTION_NOT_APPLICABLE(154), - UNKNOWN_RELATION(155), - DICTIONARIES_WAS_NOT_LOADED(156), - ILLEGAL_OVERFLOW_MODE(157), - TOO_MUCH_ROWS(158), - TIMEOUT_EXCEEDED(159), - TOO_SLOW(160), - TOO_MUCH_COLUMNS(161), - TOO_DEEP_SUBQUERIES(162), - TOO_DEEP_PIPELINE(163), - READONLY(164), - TOO_MUCH_TEMPORARY_COLUMNS(165), - TOO_MUCH_TEMPORARY_NON_CONST_COLUMNS(166), - TOO_DEEP_AST(167), - TOO_BIG_AST(168), - BAD_TYPE_OF_FIELD(169), - BAD_GET(170), - BLOCKS_HAS_DIFFERENT_STRUCTURE(171), - CANNOT_CREATE_DIRECTORY(172), - CANNOT_ALLOCATE_MEMORY(173), - CYCLIC_ALIASES(174), - CHUNK_NOT_FOUND(176), - DUPLICATE_CHUNK_NAME(177), - MULTIPLE_ALIASES_FOR_EXPRESSION(178), - MULTIPLE_EXPRESSIONS_FOR_ALIAS(179), - THERE_IS_NO_PROFILE(180), - ILLEGAL_FINAL(181), - ILLEGAL_PREWHERE(182), - UNEXPECTED_EXPRESSION(183), - ILLEGAL_AGGREGATION(184), - UNSUPPORTED_MYISAM_BLOCK_TYPE(185), - UNSUPPORTED_COLLATION_LOCALE(186), - COLLATION_COMPARISON_FAILED(187), - UNKNOWN_ACTION(188), - TABLE_MUST_NOT_BE_CREATED_MANUALLY(189), - SIZES_OF_ARRAYS_DOESNT_MATCH(190), - SET_SIZE_LIMIT_EXCEEDED(191), - UNKNOWN_USER(192), - WRONG_PASSWORD(193), - REQUIRED_PASSWORD(194), - IP_ADDRESS_NOT_ALLOWED(195), - UNKNOWN_ADDRESS_PATTERN_TYPE(196), - SERVER_REVISION_IS_TOO_OLD(197), - DNS_ERROR(198), - UNKNOWN_QUOTA(199), - QUOTA_DOESNT_ALLOW_KEYS(200), - QUOTA_EXPIRED(201), - TOO_MUCH_SIMULTANEOUS_QUERIES(202), - NO_FREE_CONNECTION(203), - CANNOT_FSYNC(204), - NESTED_TYPE_TOO_DEEP(205), - ALIAS_REQUIRED(206), - AMBIGUOUS_IDENTIFIER(207), - EMPTY_NESTED_TABLE(208), - SOCKET_TIMEOUT(209), - NETWORK_ERROR(210), - EMPTY_QUERY(211), - UNKNOWN_LOAD_BALANCING(212), - UNKNOWN_TOTALS_MODE(213), - CANNOT_STATVFS(214), - NOT_AN_AGGREGATE(215), - QUERY_WITH_SAME_ID_IS_ALREADY_RUNNING(216), - CLIENT_HAS_CONNECTED_TO_WRONG_PORT(217), - TABLE_IS_DROPPED(218), - DATABASE_NOT_EMPTY(219), - DUPLICATE_INTERSERVER_IO_ENDPOINT(220), - NO_SUCH_INTERSERVER_IO_ENDPOINT(221), - ADDING_REPLICA_TO_NON_EMPTY_TABLE(222), - UNEXPECTED_AST_STRUCTURE(223), - REPLICA_IS_ALREADY_ACTIVE(224), - NO_ZOOKEEPER(225), - NO_FILE_IN_DATA_PART(226), - UNEXPECTED_FILE_IN_DATA_PART(227), - BAD_SIZE_OF_FILE_IN_DATA_PART(228), - QUERY_IS_TOO_LARGE(229), - NOT_FOUND_EXPECTED_DATA_PART(230), - TOO_MANY_UNEXPECTED_DATA_PARTS(231), - NO_SUCH_DATA_PART(232), - BAD_DATA_PART_NAME(233), - NO_REPLICA_HAS_PART(234), - DUPLICATE_DATA_PART(235), - ABORTED(236), - NO_REPLICA_NAME_GIVEN(237), - FORMAT_VERSION_TOO_OLD(238), - CANNOT_MUNMAP(239), - CANNOT_MREMAP(240), - MEMORY_LIMIT_EXCEEDED(241), - TABLE_IS_READ_ONLY(242), - NOT_ENOUGH_SPACE(243), - UNEXPECTED_ZOOKEEPER_ERROR(244), - INVALID_NESTED_NAME(245), - CORRUPTED_DATA(246), - INCORRECT_MARK(247), - INVALID_PARTITION_NAME(248), - NOT_ENOUGH_BLOCK_NUMBERS(250), - NO_SUCH_REPLICA(251), - TOO_MUCH_PARTS(252), - REPLICA_IS_ALREADY_EXIST(253), - NO_ACTIVE_REPLICAS(254), - TOO_MUCH_RETRIES_TO_FETCH_PARTS(255), - PARTITION_ALREADY_EXISTS(256), - PARTITION_DOESNT_EXIST(257), - UNION_ALL_RESULT_STRUCTURES_MISMATCH(258), - UNION_ALL_COLUMN_ALIAS_MISMATCH(259), - CLIENT_OUTPUT_FORMAT_SPECIFIED(260), - UNKNOWN_BLOCK_INFO_FIELD(261), - BAD_COLLATION(262), - CANNOT_COMPILE_CODE(263), - INCOMPATIBLE_TYPE_OF_JOIN(264), - NO_AVAILABLE_REPLICA(265), - MISMATCH_REPLICAS_DATA_SOURCES(266), - STORAGE_DOESNT_SUPPORT_PARALLEL_REPLICAS(267), - CPUID_ERROR(268), - INFINITE_LOOP(269), - CANNOT_COMPRESS(270), - CANNOT_DECOMPRESS(271), - AIO_SUBMIT_ERROR(272), - AIO_COMPLETION_ERROR(273), - AIO_READ_ERROR(274), - AIO_WRITE_ERROR(275), - INDEX_NOT_USED(277), - LEADERSHIP_LOST(278), - ALL_CONNECTION_TRIES_FAILED(279), - NO_AVAILABLE_DATA(280), - DICTIONARY_IS_EMPTY(281), - INCORRECT_INDEX(282), - UNKNOWN_DISTRIBUTED_PRODUCT_MODE(283), - UNKNOWN_GLOBAL_SUBQUERIES_METHOD(284), - TOO_LESS_LIVE_REPLICAS(285), - UNSATISFIED_QUORUM_FOR_PREVIOUS_WRITE(286), - UNKNOWN_FORMAT_VERSION(287), - DISTRIBUTED_IN_JOIN_SUBQUERY_DENIED(288), - REPLICA_IS_NOT_IN_QUORUM(289), - LIMIT_EXCEEDED(290), - DATABASE_ACCESS_DENIED(291), - LEADERSHIP_CHANGED(292), - MONGODB_INIT_FAILED(293), - INVALID_BLOCK_EXTRA_INFO(294), - RECEIVED_EMPTY_DATA(295), - NO_REMOTE_SHARD_FOUND(296), - SHARD_HAS_NO_CONNECTIONS(297), - CANNOT_PIPE(298), - CANNOT_FORK(299), - CANNOT_DLSYM(300), - CANNOT_CREATE_CHILD_PROCESS(301), - CHILD_WAS_NOT_EXITED_NORMALLY(302), - CANNOT_SELECT(303), - CANNOT_WAITPID(304), - TABLE_WAS_NOT_DROPPED(305), - TOO_DEEP_RECURSION(306), - TOO_MUCH_BYTES(307), - UNEXPECTED_NODE_IN_ZOOKEEPER(308), - FUNCTION_CANNOT_HAVE_PARAMETERS(309), - INCONSISTENT_TABLE_ACCROSS_SHARDS(310), - INSUFFICIENT_SPACE_FOR_RESHARDING(311), - PARTITION_COPY_FAILED(312), - PARTITION_ATTACH_FAILED(313), - RESHARDING_NO_WORKER(314), - INVALID_PARTITIONS_INTERVAL(315), - RESHARDING_INVALID_PARAMETERS(316), - INVALID_SHARD_WEIGHT(317), - INVALID_CONFIG_PARAMETER(318), - UNKNOWN_STATUS_OF_INSERT(319), - DUPLICATE_SHARD_PATHS(320), - VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE(321), - RESHARDING_BUSY_CLUSTER(322), - RESHARDING_BUSY_SHARD(323), - RESHARDING_NO_SUCH_COORDINATOR(324), - RESHARDING_NO_COORDINATOR_MEMBERSHIP(325), - RESHARDING_ALREADY_SUBSCRIBED(326), - RESHARDING_REMOTE_NODE_UNAVAILABLE(327), - RESHARDING_REMOTE_NODE_ERROR(328), - RESHARDING_COORDINATOR_DELETED(329), - RESHARDING_DISTRIBUTED_JOB_ON_HOLD(330), - RESHARDING_INVALID_QUERY(331), - RESHARDING_INITIATOR_CHECK_FAILED(332), - RWLOCK_ALREADY_HELD(333), - RWLOCK_NO_SUCH_LOCK(334), - BARRIER_TIMEOUT(335), - UNKNOWN_DATABASE_ENGINE(336), - DDL_GUARD_IS_ACTIVE(337), - UNFINISHED(341), - METADATA_MISMATCH(342), - SUPPORT_IS_DISABLED(344), - TABLE_DIFFERS_TOO_MUCH(345), - CANNOT_CONVERT_CHARSET(346), - CANNOT_LOAD_CONFIG(347), - CANNOT_INSERT_NULL_IN_ORDINARY_COLUMN(349), - INCOMPATIBLE_SOURCE_TABLES(350), - AMBIGUOUS_TABLE_NAME(351), - AMBIGUOUS_COLUMN_NAME(352), - INDEX_OF_POSITIONAL_ARGUMENT_IS_OUT_OF_RANGE(353), - ZLIB_INFLATE_FAILED(354), - ZLIB_DEFLATE_FAILED(355), - BAD_LAMBDA(356), - RESERVED_IDENTIFIER_NAME(357), - INTO_OUTFILE_NOT_ALLOWED(358), - TABLE_SIZE_EXCEEDS_MAX_DROP_SIZE_LIMIT(359), - CANNOT_CREATE_CHARSET_CONVERTER(360), - SEEK_POSITION_OUT_OF_BOUND(361), - CURRENT_WRITE_BUFFER_IS_EXHAUSTED(362), - CANNOT_CREATE_IO_BUFFER(363), - RECEIVED_ERROR_TOO_MANY_REQUESTS(364), - OUTPUT_IS_NOT_SORTED(365), - SIZES_OF_NESTED_COLUMNS_ARE_INCONSISTENT(366), - TOO_MANY_FETCHES(367), - BAD_CAST(368), - ALL_REPLICAS_ARE_STALE(369), - DATA_TYPE_CANNOT_BE_USED_IN_TABLES(370), - INCONSISTENT_CLUSTER_DEFINITION(371), - SESSION_NOT_FOUND(372), - SESSION_IS_LOCKED(373), - INVALID_SESSION_TIMEOUT(374), - CANNOT_DLOPEN(375), - CANNOT_PARSE_UUID(376), - ILLEGAL_SYNTAX_FOR_DATA_TYPE(377), - DATA_TYPE_CANNOT_HAVE_ARGUMENTS(378), - UNKNOWN_STATUS_OF_DISTRIBUTED_DDL_TASK(379), - CANNOT_KILL(380), - HTTP_LENGTH_REQUIRED(381), - CANNOT_LOAD_CATBOOST_MODEL(382), - CANNOT_APPLY_CATBOOST_MODEL(383), - PART_IS_TEMPORARILY_LOCKED(384), - MULTIPLE_STREAMS_REQUIRED(385), - NO_COMMON_TYPE(386), - EXTERNAL_LOADABLE_ALREADY_EXISTS(387), - CANNOT_ASSIGN_OPTIMIZE(388), - INSERT_WAS_DEDUPLICATED(389), - CANNOT_GET_CREATE_TABLE_QUERY(390), - EXTERNAL_LIBRARY_ERROR(391), - QUERY_IS_PROHIBITED(392), - THERE_IS_NO_QUERY(393), - QUERY_WAS_CANCELLED(394), - FUNCTION_THROW_IF_VALUE_IS_NON_ZERO(395), - TOO_MANY_ROWS_OR_BYTES(396), - QUERY_IS_NOT_SUPPORTED_IN_MATERIALIZED_VIEW(397), - UNKNOWN_MUTATION_COMMAND(398), - FORMAT_IS_NOT_SUITABLE_FOR_OUTPUT(399), - CANNOT_STAT(400), - FEATURE_IS_NOT_ENABLED_AT_BUILD_TIME(401), - CANNOT_IOSETUP(402), - INVALID_JOIN_ON_EXPRESSION(403), - BAD_ODBC_CONNECTION_STRING(404), - PARTITION_SIZE_EXCEEDS_MAX_DROP_SIZE_LIMIT(405), - TOP_AND_LIMIT_TOGETHER(406), - DECIMAL_OVERFLOW(407), - BAD_REQUEST_PARAMETER(408), - EXTERNAL_EXECUTABLE_NOT_FOUND(409), - EXTERNAL_SERVER_IS_NOT_RESPONDING(410), - PTHREAD_ERROR(411), - NETLINK_ERROR(412), - CANNOT_SET_SIGNAL_HANDLER(413), - CANNOT_READLINE(414), - ALL_REPLICAS_LOST(415), - REPLICA_STATUS_CHANGED(416), - EXPECTED_ALL_OR_ANY(417), - UNKNOWN_JOIN_STRICTNESS(418), - MULTIPLE_ASSIGNMENTS_TO_COLUMN(419), - CANNOT_UPDATE_COLUMN(420), - CANNOT_ADD_DIFFERENT_AGGREGATE_STATES(421), - UNSUPPORTED_URI_SCHEME(422), - CANNOT_GETTIMEOFDAY(423), - CANNOT_LINK(424), - SYSTEM_ERROR(425), - NULL_POINTER_DEREFERENCE(426), - CANNOT_COMPILE_REGEXP(427), - UNKNOWN_LOG_LEVEL(428), - FAILED_TO_GETPWUID(429), - MISMATCHING_USERS_FOR_PROCESS_AND_DATA(430), - ILLEGAL_SYNTAX_FOR_CODEC_TYPE(431), - UNKNOWN_CODEC(432), - ILLEGAL_CODEC_PARAMETER(433), - CANNOT_PARSE_PROTOBUF_SCHEMA(434), - NO_DATA_FOR_REQUIRED_PROTOBUF_FIELD(435), - PROTOBUF_BAD_CAST(436), - PROTOBUF_FIELD_NOT_REPEATED(437), - DATA_TYPE_CANNOT_BE_PROMOTED(438), - CANNOT_SCHEDULE_TASK(439), - INVALID_LIMIT_EXPRESSION(440), - CANNOT_PARSE_DOMAIN_VALUE_FROM_STRING(441), - BAD_DATABASE_FOR_TEMPORARY_TABLE(442), - NO_COMMON_COLUMNS_WITH_PROTOBUF_SCHEMA(443), - UNKNOWN_PROTOBUF_FORMAT(444), - CANNOT_MPROTECT(445), - FUNCTION_NOT_ALLOWED(446), - HYPERSCAN_CANNOT_SCAN_TEXT(447), - BROTLI_READ_FAILED(448), - BROTLI_WRITE_FAILED(449), - BAD_TTL_EXPRESSION(450), - BAD_TTL_FILE(451), - SETTING_CONSTRAINT_VIOLATION(452), - - KEEPER_EXCEPTION(999), - POCO_EXCEPTION(1000), - STD_EXCEPTION(1001), - UNKNOWN_EXCEPTION(1002); - - public final Integer code; - - private static final Map byCodes; - static { - Map map = new HashMap(); - for (ClickHouseErrorCode errorCode : values()) - map.put(errorCode.code, errorCode); - byCodes = Collections.unmodifiableMap(map); - } - - ClickHouseErrorCode(Integer code) { - this.code = code; - } - - - public static ClickHouseErrorCode fromCode(Integer code) { - return byCodes.get(code); - } - - @Override - public String toString() { - return name() + " (code " + code + ')'; - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/except/ClickHouseException.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/except/ClickHouseException.java deleted file mode 100644 index 570da79cb..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/except/ClickHouseException.java +++ /dev/null @@ -1,22 +0,0 @@ -package ru.yandex.clickhouse.except; - -import java.sql.SQLException; - -public class ClickHouseException extends SQLException { - - public ClickHouseException(int code, Throwable cause, String host, int port) { - super("ClickHouse exception, code: " + code + ", host: " + host + ", port: " + port + "; " - + (cause == null ? "" : cause.getMessage()), null, code, cause); - } - - public ClickHouseException(int code, String message, Throwable cause, String host, int port) { - super("ClickHouse exception, message: " + message + ", host: " + host + ", port: " + port + "; " - + (cause == null ? "" : cause.getMessage()), null, code, cause); - } - - public ClickHouseException(int code, String message, Throwable cause) { - super("ClickHouse exception, message: " + message + "; " - + (cause == null ? "" : cause.getMessage()), null, code, cause); - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/except/ClickHouseExceptionSpecifier.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/except/ClickHouseExceptionSpecifier.java deleted file mode 100644 index d43184d9e..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/except/ClickHouseExceptionSpecifier.java +++ /dev/null @@ -1,104 +0,0 @@ -package ru.yandex.clickhouse.except; - -import org.apache.http.conn.ConnectTimeoutException; - -import ru.yandex.clickhouse.util.Utils; - -import java.net.ConnectException; -import java.net.SocketTimeoutException; - -import com.clickhouse.client.logging.Logger; -import com.clickhouse.client.logging.LoggerFactory; - -/** - * Specify ClickHouse exception to ClickHouseException and fill it with a vendor - * code. - */ - -public final class ClickHouseExceptionSpecifier { - - private static final Logger log = LoggerFactory.getLogger(ClickHouseExceptionSpecifier.class); - - private ClickHouseExceptionSpecifier() { - } - - public static ClickHouseException specify(Throwable cause, String host, int port) { - return specify(cause != null ? cause.getMessage() : null, cause, host, port); - } - - public static ClickHouseException specify(String clickHouseMessage, String host, int port) { - return specify(clickHouseMessage, null, host, port); - } - - public static ClickHouseException specify(String clickHouseMessage) { - return specify(clickHouseMessage, "unknown", -1); - } - - /** - * Here we expect the ClickHouse error message to be of the following format: - * "Code: 10, e.displayText() = DB::Exception: ...". - */ - private static ClickHouseException specify(String clickHouseMessage, Throwable cause, String host, int port) { - if (Utils.isNullOrEmptyString(clickHouseMessage) && cause != null) { - return getException(cause, host, port); - } - - try { - int code; - if (clickHouseMessage.startsWith("Poco::Exception. Code: 1000, ")) { - code = 1000; - } else { - // Code: 175, e.displayText() = DB::Exception: - code = getErrorCode(clickHouseMessage); - } - // ошибку в изначальном виде все-таки укажем - Throwable messageHolder = cause != null ? cause : new Throwable(clickHouseMessage); - if (code == -1) { - return getException(messageHolder, host, port); - } - - return new ClickHouseException(code, messageHolder, host, port); - } catch (Exception e) { - log.error( - "Unsupported ClickHouse error format, please fix ClickHouseExceptionSpecifier, message: %s, error: %s", - clickHouseMessage, e.getMessage()); - return new ClickHouseUnknownException(clickHouseMessage, cause, host, port); - } - } - - private static int getErrorCode(String errorMessage) { - int startIndex = errorMessage.indexOf(' '); - if (startIndex >= 0) { - for (int i = ++startIndex, len = errorMessage.length(); i < len; i++) { - char ch = errorMessage.charAt(i); - if (ch == '.' || ch == ',' || Character.isWhitespace(ch)) { - try { - return Integer.parseInt(errorMessage.substring(startIndex, i)); - } catch (NumberFormatException e) { - // ignore - } - break; - } - } - } - - return -1; - } - - private static ClickHouseException getException(Throwable cause, String host, int port) { - if (cause instanceof SocketTimeoutException) - // if we've got SocketTimeoutException, we'll say that the query is not good. - // This is not the same as SOCKET_TIMEOUT of clickhouse - // but it actually could be a failing ClickHouse - { - return new ClickHouseException(ClickHouseErrorCode.TIMEOUT_EXCEEDED.code, cause, host, port); - } else if (cause instanceof ConnectTimeoutException || cause instanceof ConnectException) - // couldn't connect to ClickHouse during connectTimeout - { - return new ClickHouseException(ClickHouseErrorCode.NETWORK_ERROR.code, cause, host, port); - } else { - return new ClickHouseUnknownException(cause, host, port); - } - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/except/ClickHouseUnknownException.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/except/ClickHouseUnknownException.java deleted file mode 100644 index e1bd79708..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/except/ClickHouseUnknownException.java +++ /dev/null @@ -1,22 +0,0 @@ -package ru.yandex.clickhouse.except; - -public class ClickHouseUnknownException extends ClickHouseException { - - public ClickHouseUnknownException(Throwable cause, String host, int port) { - super(ClickHouseErrorCode.UNKNOWN_EXCEPTION.code, cause, host, port); - } - - - public ClickHouseUnknownException(String message, Throwable cause, String host, int port) { - super(ClickHouseErrorCode.UNKNOWN_EXCEPTION.code, message, cause, host, port); - } - - public ClickHouseUnknownException(String message, Throwable cause) { - super(ClickHouseErrorCode.UNKNOWN_EXCEPTION.code, message, cause); - } - - public ClickHouseUnknownException(Integer code, Throwable cause, String host, int port) { - super(code, cause, host, port); - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/AbstractResultSet.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/AbstractResultSet.java deleted file mode 100644 index 9c44e6f6a..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/AbstractResultSet.java +++ /dev/null @@ -1,986 +0,0 @@ -package ru.yandex.clickhouse.response; - -import java.io.InputStream; -import java.io.Reader; -import java.math.BigDecimal; -import java.net.URL; -import java.sql.Array; -import java.sql.Blob; -import java.sql.Clob; -import java.sql.Date; -import java.sql.NClob; -import java.sql.Ref; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.RowId; -import java.sql.SQLException; -import java.sql.SQLWarning; -import java.sql.SQLXML; -import java.sql.Statement; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.Calendar; -import java.util.Map; - - -public abstract class AbstractResultSet implements ResultSet { - - @Override - public boolean next() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void close() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean wasNull() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public String getString(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean getBoolean(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public byte getByte(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public short getShort(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public int getInt(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public long getLong(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public float getFloat(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public double getDouble(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public byte[] getBytes(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Date getDate(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Time getTime(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Timestamp getTimestamp(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public InputStream getAsciiStream(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - @Deprecated - public InputStream getUnicodeStream(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public InputStream getBinaryStream(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public String getString(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean getBoolean(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public byte getByte(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public short getShort(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public int getInt(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public long getLong(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public float getFloat(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public double getDouble(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public byte[] getBytes(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Date getDate(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Time getTime(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Timestamp getTimestamp(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public InputStream getAsciiStream(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - @Deprecated - public InputStream getUnicodeStream(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public InputStream getBinaryStream(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public SQLWarning getWarnings() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void clearWarnings() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public String getCursorName() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public ResultSetMetaData getMetaData() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Object getObject(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Object getObject(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public int findColumn(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Reader getCharacterStream(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Reader getCharacterStream(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public BigDecimal getBigDecimal(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public BigDecimal getBigDecimal(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isBeforeFirst() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isAfterLast() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isFirst() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isLast() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void beforeFirst() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void afterLast() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean first() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean last() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean absolute(int row) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean relative(int rows) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean previous() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void setFetchDirection(int direction) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public int getFetchDirection() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void setFetchSize(int rows) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public int getFetchSize() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public int getType() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public int getConcurrency() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean rowUpdated() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean rowInserted() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean rowDeleted() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateNull(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateBoolean(int columnIndex, boolean x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateByte(int columnIndex, byte x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateShort(int columnIndex, short x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateInt(int columnIndex, int x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateLong(int columnIndex, long x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateFloat(int columnIndex, float x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateDouble(int columnIndex, double x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateString(int columnIndex, String x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateBytes(int columnIndex, byte[] x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateDate(int columnIndex, Date x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateTime(int columnIndex, Time x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateObject(int columnIndex, Object x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateNull(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateBoolean(String columnLabel, boolean x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateByte(String columnLabel, byte x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateShort(String columnLabel, short x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateInt(String columnLabel, int x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateLong(String columnLabel, long x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateFloat(String columnLabel, float x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateDouble(String columnLabel, double x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateString(String columnLabel, String x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateBytes(String columnLabel, byte[] x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateDate(String columnLabel, Date x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateTime(String columnLabel, Time x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateTimestamp(String columnLabel, Timestamp x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateBinaryStream(String columnLabel, InputStream x, int length) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateCharacterStream(String columnLabel, Reader reader, int length) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateObject(String columnLabel, Object x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void insertRow() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateRow() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void deleteRow() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void refreshRow() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void cancelRowUpdates() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void moveToInsertRow() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void moveToCurrentRow() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Statement getStatement() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Object getObject(int columnIndex, Map> map) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Ref getRef(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Blob getBlob(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Clob getClob(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Array getArray(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Object getObject(String columnLabel, Map> map) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Ref getRef(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Blob getBlob(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Clob getClob(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Array getArray(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Date getDate(int columnIndex, Calendar cal) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Date getDate(String columnLabel, Calendar cal) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Time getTime(int columnIndex, Calendar cal) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Time getTime(String columnLabel, Calendar cal) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public URL getURL(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public URL getURL(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateRef(int columnIndex, Ref x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateRef(String columnLabel, Ref x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateBlob(int columnIndex, Blob x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateBlob(String columnLabel, Blob x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateClob(int columnIndex, Clob x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateClob(String columnLabel, Clob x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateArray(int columnIndex, Array x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateArray(String columnLabel, Array x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public RowId getRowId(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public RowId getRowId(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateRowId(int columnIndex, RowId x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateRowId(String columnLabel, RowId x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public int getHoldability() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isClosed() throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateNString(int columnIndex, String nString) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateNString(String columnLabel, String nString) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateNClob(int columnIndex, NClob nClob) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateNClob(String columnLabel, NClob nClob) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public NClob getNClob(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public NClob getNClob(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public SQLXML getSQLXML(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public SQLXML getSQLXML(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public String getNString(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public String getNString(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Reader getNCharacterStream(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public Reader getNCharacterStream(String columnLabel) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateClob(int columnIndex, Reader reader, long length) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateClob(String columnLabel, Reader reader, long length) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateCharacterStream(int columnIndex, Reader x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateClob(int columnIndex, Reader reader) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateClob(String columnLabel, Reader reader) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateNClob(int columnIndex, Reader reader) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public void updateNClob(String columnLabel, Reader reader) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public T unwrap(Class iface) throws SQLException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isWrapperFor(Class iface) throws SQLException { - throw new UnsupportedOperationException(); - } - - /** - * Parse the value in current row at column with label {@code column} as an array - * of long - * - * @param column - * the label, name, alias of the column - * @return an array of longs - * @throws SQLException - * if the value cannot be interpreted as {@code long[]} - * @deprecated prefer to use regular JDBC API, e.g. via - * {@link #getArray(int)} or simply - * {@link #getObject(int, Class)} - */ - @Deprecated - public abstract long[] getLongArray(String column) throws SQLException; - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ArrayByteFragment.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ArrayByteFragment.java deleted file mode 100644 index 602ec42f5..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ArrayByteFragment.java +++ /dev/null @@ -1,20 +0,0 @@ -package ru.yandex.clickhouse.response; - -public final class ArrayByteFragment extends ByteFragment { - - private ArrayByteFragment(byte[] buf, int start, int len) { - super(buf, start, len); - } - - public static ArrayByteFragment wrap(ByteFragment fragment) { - return new ArrayByteFragment(fragment.buf, fragment.start, fragment.len); - } - - @Override - public boolean isNull() { - // NULL - return len == 4 && buf[start] == 'N' && buf[start + 1] == 'U' && buf[start + 2] == 'L' && buf[start + 3] == 'L'; - } - - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ByteFragment.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ByteFragment.java deleted file mode 100644 index 4ffcb2c6e..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ByteFragment.java +++ /dev/null @@ -1,233 +0,0 @@ -package ru.yandex.clickhouse.response; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.nio.charset.StandardCharsets; - -public class ByteFragment { - - protected final byte[] buf; - protected final int start; - protected final int len; - private static final ByteFragment EMPTY = new ByteFragment(new byte[0], 0, 0); - - public ByteFragment(byte[] buf, int start, int len) { - this.buf = buf; - this.start = start; - this.len = len; - } - - public static ByteFragment fromString(String str) { - // https://bugs.openjdk.java.net/browse/JDK-6219899 - byte[] bytes = str.getBytes(StandardCharsets.UTF_8); - return new ByteFragment(bytes, 0, bytes.length); - } - - public String asString() { - return new String(buf, start, len, StandardCharsets.UTF_8); - } - - public String asString(boolean unescape) { - if(unescape) { - if (isNull()) { - return null; - } - return new String(unescape(), StandardCharsets.UTF_8); - } else { - return asString(); - } - } - - public boolean isNull() { - // \N - return len == 2 && buf[start] == '\\' && buf[start + 1] == 'N'; - } - - public boolean isEmpty() { - return len == 0; - } - - public boolean isNaN() { - // nan - return len == 3 && buf[start] == 'n' && buf[start + 1] == 'a' && buf[start + 2] == 'n'; - } - - @Override - public String toString() { - StringBuilder b = new StringBuilder(); - b.append("ByteFragment{["); - for (byte b1 : buf) { - if (b1 == '\t') { - b.append(""); - } else { - b.append((char) b1); - } - } - b.append(']'); - b.append(", start=" + start + - ", len=" + len + - '}'); - return b.toString(); - } - - public ByteFragment[] split(byte sep) { - StreamSplitter ss = new StreamSplitter(this, sep); - int c = count(sep)+1; - ByteFragment[] res = new ByteFragment[c]; - try { - int i = 0; - ByteFragment next = null; - while((next = ss.next())!=null) { - res[i++] = next; - } - } catch (IOException ignore) { - } - if(res[c-1] == null) { - res[c-1] = ByteFragment.EMPTY; - } - return res; - } - // [45, 49, 57, 52, 49, 51, 56, 48, 57, 49, 52, 9, 9, 50, 48, 49, 50, 45, 48, 55, 45, 49, 55, 32, 49, 51, 58, 49, 50, 58, 50, 49, 9, 49, 50, 49, 50, 55, 53, 53, 9, 50, 57, 57, 57, 55, 55, 57, 57, 55, 56, 9, 48, 9, 52, 48, 57, 49, 57, 55, 52, 49, 49, 51, 50, 56, 53, 53, 50, 54, 57, 51, 9, 51, 9, 54, 9, 50, 48, 9, 48, 92, 48, 9, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 97, 118, 105, 116, 111, 46, 114, 117, 47, 99, 97, 116, 97, 108, 111, 103, 47, 103, 97, 114, 97, 122, 104, 105, 95, 105, 95, 109, 97, 115, 104, 105, 110, 111, 109, 101, 115, 116, 97, 45, 56, 53, 47, 116, 97, 116, 97, 114, 115, 116, 97, 110, 45, 54, 53, 48, 49, 51, 48, 47, 112, 97, 103, 101, 56, 9, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 97, 118, 105, 116, 111, 46, 114, 117, 47, 99, 97, 116, 97, 108, 111, 103, 47, 103, 97, 114, 97, 122, 104, 105, 95, 105, 95, 109, 97, 115, 104, 105, 110, 111, 109, 101, 115, 116, 97, 45, 56, 53, 47, 116, 97, 116, 97, 114, 115, 116, 97, 110, 45, 54, 53, 48, 49, 51, 48, 47, 112, 97, 103, 101, 55, 9, 48, 9, 48, 9, 50, 56, 53, 55, 48, 56, 48, 9, 45, 49, 9, 48, 9, 9, 48, 9, 48, 9, 48, 9, 45, 49, 9, 48, 48, 48, 48, 45, 48, 48, 45, 48, 48, 32, 48, 48, 58, 48, 48, 58, 48, 48, 9, 9, 48, 9, 48, 9, 103, 9, 45, 49, 9, 45, 49, 9, 45, 49, 9] - public ByteArrayInputStream asStream() { - return new ByteArrayInputStream(buf, start, len); - } - - private int count(byte sep) { - int res = 0; - for (int i = start; i < start+len; i++) { - if (buf[i] == sep) { - res++; - } - } - return res; - } - - public int getLen() { - return len; - } - - // "\0" => 0 - // "\r" => 13 - // "\n" => 10 - // "\\" => 92 - // "\'" => 39 - // "\b" => 8 - // "\f" => 12 - // "\t" => 9 - //null - // "\N" => 0 - private static final byte[] convert = { - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 0.. 9 - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, //10..19 - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, //20..29 - -1,-1,-1,-1,-1,-1,-1,-1,-1,39, //30..39 - -1,-1,-1,-1,-1,-1,-1,-1, 0,-1, //40..49 - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, //50..59 - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, //60..69 - -1,-1,-1,-1,-1,-1,-1,-1, 0,-1, //70..79 - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, //80..89 - -1,-1,92,-1,-1,-1,-1,-1, 8,-1, //90..99 - -1,-1,12,-1,-1,-1,-1,-1,-1,-1, //100..109 - 10,-1,-1,-1,13,-1, 9,-1,-1,-1, //110..119 - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, //120..129 - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - }; - // [0xb6][0xfe][0x7][0x1][0xd8][0xd6][0x94][0x80][0x5]\0 html. - // [-74,-2,7,1,-40,-42,-108,-128,5,0] real value - // [-74,-2,7,1,-40,-42,-108,-128,5,92,48] parsed value - - public byte[] unescape() { - int resLen = 0; - { - boolean prevSlash = false; - for(int i = start; i < start + len; i++){ - if(prevSlash) { - resLen++; - prevSlash = false; - } else { - if(buf[i] == 92) { // slash character - prevSlash = true; - } else { - resLen++; - } - } - } - } - if (resLen == len) { - return getBytesCopy(); - } - byte[] res = new byte[resLen]; - int index = 0; - { - boolean prevSlash = false; - for(int i = start; i < start + len; i++){ - if(prevSlash) { - prevSlash = false; - res[index++] = convert[buf[i]]; - - } else { - if(buf[i] == 92) { // slash character - prevSlash = true; - } else { - res[index++] = buf[i]; - } - } - - } - } - return res; - } - - final static byte[] reverse; - static { - reverse = new byte[convert.length]; - for (int i = 0; i < convert.length; i++) { - reverse[i] = -1; - byte c = convert[i]; - if (c != -1) { - reverse[c] = (byte) i; - } - } - } - - public static void escape(byte[] bytes, OutputStream stream) throws IOException { - for (byte b : bytes) { - if(b < 0 || b >= reverse.length) { - stream.write(b); - } else { - byte converted = reverse[b]; - if (converted != -1) { - stream.write(92); - stream.write(converted); - } else { - stream.write(b); - } - } - } - } - - private byte[] getBytesCopy() { - byte[] bytes = new byte[len]; - System.arraycopy(buf, start, bytes, 0, len); - return bytes; - } - - public int length() { - return len; - } - - public int charAt(int i) { - return buf[start+i]; - } - - - public ByteFragment subseq(int start, int len) { - if(start < 0 || start + len > this.len) { - throw new IllegalArgumentException("arg start,len="+(start+","+len)+" while this start,len="+(this.start+","+this.len)); - } - return new ByteFragment(buf, this.start+start, len); - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseColumnInfo.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseColumnInfo.java deleted file mode 100644 index 240dd0d9a..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseColumnInfo.java +++ /dev/null @@ -1,251 +0,0 @@ -package ru.yandex.clickhouse.response; - -import java.util.TimeZone; -import ru.yandex.clickhouse.domain.ClickHouseDataType; - -/** - * This class represents a column defined in database. - */ -public final class ClickHouseColumnInfo { - - private static final String KEYWORD_NULLABLE = "Nullable"; - private static final String KEYWORD_LOW_CARDINALITY = "LowCardinality"; - private static final String KEYWORD_ARRAY = "Array"; - - private ClickHouseDataType clickHouseDataType; - private final String originalTypeName; - private final String columnName; - private boolean nullable; - private boolean lowCardinality; - private int arrayLevel; - private ClickHouseDataType arrayBaseType; - private TimeZone timeZone; - private int precision; - private int scale; - private ClickHouseColumnInfo keyInfo; - private ClickHouseColumnInfo valueInfo; - private String functionName; - - @Deprecated - public static ClickHouseColumnInfo parse(String typeInfo, String columnName) { - return parse(typeInfo, columnName, null); - } - - /** - * Parse given type string. - * - * @param typeInfo type defined in database - * @param columnName column name - * @param serverTimeZone server time zone - * @return parsed type - */ - public static ClickHouseColumnInfo parse(String typeInfo, String columnName, TimeZone serverTimeZone) { - ClickHouseColumnInfo column = new ClickHouseColumnInfo(typeInfo, columnName); - int currIdx = 0; - while (typeInfo.startsWith(KEYWORD_ARRAY, currIdx)) { - column.arrayLevel++; - column.clickHouseDataType = ClickHouseDataType.Array; - currIdx += KEYWORD_ARRAY.length() + 1; // opening parenthesis - } - if (typeInfo.startsWith(KEYWORD_LOW_CARDINALITY, currIdx)) { - column.lowCardinality = true; - currIdx += KEYWORD_LOW_CARDINALITY.length() + 1; - } - if (typeInfo.startsWith(KEYWORD_NULLABLE, currIdx)) { - column.nullable = true; - currIdx += KEYWORD_NULLABLE.length() + 1; - } - int endIdx = typeInfo.indexOf("(", currIdx) < 0 - ? typeInfo.indexOf(")", currIdx) - : typeInfo.indexOf("(", currIdx); - if (endIdx < 0) { - endIdx = typeInfo.length(); - } - ClickHouseDataType dataType = ClickHouseDataType.fromTypeString( - typeInfo.substring(currIdx, endIdx)); - if (column.arrayLevel > 0) { - column.arrayBaseType = dataType; - } else { - column.clickHouseDataType = dataType; - } - column.precision = dataType.getDefaultPrecision(); - column.scale = dataType.getDefaultScale(); - column.timeZone = serverTimeZone; - currIdx = endIdx; - if (endIdx == typeInfo.length() || !typeInfo.startsWith("(", currIdx)) { - return column; - } - - switch (dataType) { - case AggregateFunction : - String[] argsAf = splitArgs(typeInfo, currIdx); - column.functionName = argsAf[0]; - column.arrayBaseType = ClickHouseDataType.Unknown; - if (argsAf.length == 2) { - column.arrayBaseType = ClickHouseDataType.fromTypeString(argsAf[1]); - } - break; - case DateTime : - String[] argsDt = splitArgs(typeInfo, currIdx); - if (argsDt.length == 2) { // same as DateTime64 - column.scale = Integer.parseInt(argsDt[0]); - column.timeZone = TimeZone.getTimeZone(argsDt[1].replace("'", "")); - } else if (argsDt.length == 1) { // same as DateTime32 - // unfortunately this will fall back to GMT if the time zone - // cannot be resolved - TimeZone tz = TimeZone.getTimeZone(argsDt[0].replace("'", "")); - column.timeZone = tz; - } - break; - case DateTime32: - String[] argsD32 = splitArgs(typeInfo, currIdx); - if (argsD32.length == 1) { - // unfortunately this will fall back to GMT if the time zone - // cannot be resolved - TimeZone tz = TimeZone.getTimeZone(argsD32[0].replace("'", "")); - column.timeZone = tz; - } - break; - case DateTime64: - String[] argsD64 = splitArgs(typeInfo, currIdx); - if (argsD64.length == 2) { - column.scale = Integer.parseInt(argsD64[0]); - column.timeZone = TimeZone.getTimeZone(argsD64[1].replace("'", "")); - } - break; - case Decimal : - String[] argsDecimal = splitArgs(typeInfo, currIdx); - if (argsDecimal.length == 2) { - column.precision = Integer.parseInt(argsDecimal[0]); - column.scale = Integer.parseInt(argsDecimal[1]); - } - break; - case Decimal32 : - case Decimal64 : - case Decimal128 : - case Decimal256 : - String[] argsScale = splitArgs(typeInfo, currIdx); - column.scale = Integer.parseInt(argsScale[0]); - break; - case FixedString : - String[] argsPrecision = splitArgs(typeInfo, currIdx); - column.precision = Integer.parseInt(argsPrecision[0]); - break; - case Map: - String[] argsMap = splitArgs(typeInfo, currIdx); - if (argsMap.length == 2) { - column.keyInfo = ClickHouseColumnInfo.parse(argsMap[0], columnName + "Key", serverTimeZone); - column.valueInfo = ClickHouseColumnInfo.parse(argsMap[1], columnName + "Value", serverTimeZone); - } - break; - default: - break; - } - - return column; - } - - private static String[] splitArgs(String args, int currIdx) { - // There can be arguments containing a closing parentheses - // e.g. Enum8(\'f(o)o\' = 42), but we currently do not try - // to parse any of those - return args - .substring( - args.indexOf("(", currIdx) + 1, - args.indexOf(")", currIdx)) - .split("\\s*,\\s*"); - } - - private ClickHouseColumnInfo(String originalTypeName, String columnName) { - this.originalTypeName = originalTypeName; - this.columnName = columnName; - } - - public ClickHouseDataType getClickHouseDataType() { - return clickHouseDataType; - } - - public String getOriginalTypeName() { - return originalTypeName; - } - - /** - * Get the type name returned from the database, without modifiers, i.e. Nullable or LowCardinality. - * - * @return the type name returned from the database - */ - public String getCleanTypeName() { - if (!nullable && !lowCardinality) { - return originalTypeName; - } - StringBuilder sb = new StringBuilder(); - int idx = 0; - int numParens = 0; - if (lowCardinality) { - int start = originalTypeName.indexOf(KEYWORD_LOW_CARDINALITY); - sb.append(originalTypeName.substring(idx, start)); - numParens++; - idx = start + KEYWORD_LOW_CARDINALITY.length() + 1; - } - if (nullable) { - int start = originalTypeName.indexOf(KEYWORD_NULLABLE, idx); - sb.append(originalTypeName.substring(idx, start)); - numParens++; - idx = start + KEYWORD_NULLABLE.length() + 1; - } - sb.append(originalTypeName.substring(idx, originalTypeName.length() - numParens)); - return sb.toString(); - } - - public String getColumnName() { - return columnName; - } - - public boolean isNullable() { - return nullable; - } - - boolean isLowCardinality() { - return lowCardinality; - } - - public int getArrayLevel() { - return arrayLevel; - } - - public boolean isArray() { - return arrayLevel > 0; - } - - public ClickHouseDataType getArrayBaseType() { - return arrayBaseType; - } - - public ClickHouseDataType getEffectiveClickHouseDataType() { - return arrayLevel > 0 ? arrayBaseType : clickHouseDataType; - } - - public TimeZone getTimeZone() { - return timeZone; - } - - public int getPrecision() { - return precision; - } - - public int getScale() { - return scale; - } - - public ClickHouseColumnInfo getKeyInfo() { - return this.keyInfo; - } - - public ClickHouseColumnInfo getValueInfo() { - return this.valueInfo; - } - - public String getFunctionName() { - return this.functionName; - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseLZ4Stream.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseLZ4Stream.java deleted file mode 100644 index a1ebf2d45..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseLZ4Stream.java +++ /dev/null @@ -1,116 +0,0 @@ -package ru.yandex.clickhouse.response; - -import net.jpountz.lz4.LZ4Factory; -import net.jpountz.lz4.LZ4FastDecompressor; -import ru.yandex.clickhouse.util.ClickHouseBlockChecksum; -import ru.yandex.clickhouse.util.Utils; - -import java.io.DataInputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * Reader from clickhouse in lz4 - */ - -public class ClickHouseLZ4Stream extends InputStream { - - private static final LZ4Factory factory = LZ4Factory.fastestInstance(); - - public static final int MAGIC = 0x82; - - private final InputStream stream; - private final DataInputStream dataWrapper; - - private byte[] currentBlock; - private int pointer; - - public ClickHouseLZ4Stream(InputStream stream) { - this.stream = stream; - dataWrapper = new DataInputStream(stream); - } - - @Override - public int read() throws IOException { - if (!checkNext()) return -1; - byte b = currentBlock[pointer]; - pointer += 1; - return b & 0xFF; - } - - @Override - public int read(byte[] b, int off, int len) throws IOException { - if (b == null) { - throw new NullPointerException(); - } else if (off < 0 || len < 0 || len > b.length - off) { - throw new IndexOutOfBoundsException(); - } else if (len == 0) { - return 0; - } - - if (!checkNext()) return -1; - - int copied = 0; - int targetPointer = off; - while(copied != len) { - int toCopy = Math.min(currentBlock.length - pointer, len - copied); - System.arraycopy(currentBlock, pointer, b, targetPointer, toCopy); - targetPointer += toCopy; - pointer += toCopy; - copied += toCopy; - if (!checkNext()) { //finished - return copied; - } - } - return copied; - } - - @Override - public void close() throws IOException { - stream.close(); - } - - private boolean checkNext() throws IOException { - if (currentBlock == null || pointer == currentBlock.length) { - currentBlock = readNextBlock(); - pointer = 0; - } - return currentBlock != null; - } - - // every block is: - private byte[] readNextBlock() throws IOException { - int read = stream.read(); - if (read < 0) return null; - - byte[] checksum = new byte[16]; - checksum[0] = (byte)read; - // checksum - 16 bytes. - Utils.readFully(dataWrapper, checksum, 1, 15); - ClickHouseBlockChecksum expected = ClickHouseBlockChecksum.fromBytes(checksum); - // header: - // 1 byte - 0x82 (shows this is LZ4) - int magic = dataWrapper.readUnsignedByte(); - if (magic != MAGIC) throw new IOException("Magic is not correct: " + magic); - // 4 bytes - size of the compressed data including 9 bytes of the header - int compressedSizeWithHeader = Utils.readInt(dataWrapper); - // 4 bytes - size of uncompressed data - int uncompressedSize = Utils.readInt(dataWrapper); - int compressedSize = compressedSizeWithHeader - 9; //header - byte[] block = new byte[compressedSize]; - // compressed data: compressed_size - 9 байт. - Utils.readFully(dataWrapper, block); - - ClickHouseBlockChecksum real = ClickHouseBlockChecksum.calculateForBlock((byte)magic, compressedSizeWithHeader, uncompressedSize, block, compressedSize); - if (!real.equals(expected)) { - throw new IllegalArgumentException("Checksum doesn't match: corrupted data."); - } - - byte[] decompressed = new byte[uncompressedSize]; - LZ4FastDecompressor decompressor = factory.fastDecompressor(); - decompressor.decompress(block, 0, decompressed, 0, uncompressedSize); - return decompressed; - } - - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseResponse.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseResponse.java deleted file mode 100644 index 3381d6b30..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseResponse.java +++ /dev/null @@ -1,124 +0,0 @@ -package ru.yandex.clickhouse.response; - -import java.util.List; - -/** - * Object for jackson for ClickHouse response - */ -public class ClickHouseResponse { - private List meta; - private List> data; - private List totals; - private Extremes extremes; - private int rows; - private int rows_before_limit_at_least; - - - public static class Extremes { - private List min; - private List max; - - public List getMin() { - return min; - } - - public void setMin(List min) { - this.min = min; - } - - public List getMax() { - return max; - } - - public void setMax(List max) { - this.max = max; - } - } - - public static class Meta { - private String name; - private String type; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - @Override - public String toString() { - return "Meta{" + - "name='" + name + '\'' + - ", type='" + type + '\'' + - '}'; - } - } - - public Extremes getExtremes() { - return extremes; - } - - public void setExtremes(Extremes extremes) { - this.extremes = extremes; - } - - public List getMeta() { - return meta; - } - - public void setMeta(List meta) { - this.meta = meta; - } - - public List> getData() { - return data; - } - - public void setData(List> data) { - this.data = data; - } - - public int getRows() { - return rows; - } - - public void setRows(int rows) { - this.rows = rows; - } - - public int getRows_before_limit_at_least() { - return rows_before_limit_at_least; - } - - public void setRows_before_limit_at_least(int rows_before_limit_at_least) { - this.rows_before_limit_at_least = rows_before_limit_at_least; - } - - public List getTotals() { - return totals; - } - - public void setTotals(List totals) { - this.totals = totals; - } - - @Override - public String toString() { - return "ClickHouseResponse{" + - "meta=" + meta + - ", data=" + data + - ", rows=" + rows + - ", rows_before_limit_at_least=" + rows_before_limit_at_least + - '}'; - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseResponseFactory.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseResponseFactory.java deleted file mode 100644 index 89b617a36..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseResponseFactory.java +++ /dev/null @@ -1,15 +0,0 @@ -package ru.yandex.clickhouse.response; - -import ru.yandex.clickhouse.ResponseFactory; - -import java.io.IOException; -import java.io.InputStream; - -import com.clickhouse.client.data.JsonStreamUtils; - -public class ClickHouseResponseFactory implements ResponseFactory { - @Override - public ClickHouseResponse create(InputStream response) throws IOException { - return JsonStreamUtils.readObject(response, ClickHouseResponse.class); - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseResponseGsonDeserializer.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseResponseGsonDeserializer.java deleted file mode 100644 index 32c8fbe23..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseResponseGsonDeserializer.java +++ /dev/null @@ -1,100 +0,0 @@ -package ru.yandex.clickhouse.response; - -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.List; - -import com.google.gson.JsonArray; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; - -public class ClickHouseResponseGsonDeserializer implements JsonDeserializer { - - @Override - public ClickHouseResponse deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - ClickHouseResponse result = new ClickHouseResponse(); - JsonObject jsonObject = json.getAsJsonObject(); - - JsonArray metaNode = jsonObject.getAsJsonArray("meta"); - if (metaNode != null) { - List meta = new ArrayList<>(); - metaNode.forEach(e -> meta.add(parseMeta(e))); - result.setMeta(meta); - } - - JsonArray dataNode = jsonObject.getAsJsonArray("data"); - if (dataNode != null) { - List> data = new ArrayList<>(); - dataNode.forEach(row -> { - List rowList = getAsStringArray(row); - data.add(rowList); - }); - result.setData(data); - } - - JsonArray totalsNode = jsonObject.getAsJsonArray("totals"); - if (totalsNode != null) { - List totals = getAsStringArray(totalsNode); - result.setTotals(totals); - } - - JsonObject extremesNode = jsonObject.getAsJsonObject("extremes"); - if (extremesNode != null) { - ClickHouseResponse.Extremes extremes = new ClickHouseResponse.Extremes(); - extremes.setMax(getAsStringArray(extremesNode.get("max"))); - extremes.setMin(getAsStringArray(extremesNode.get("min"))); - result.setExtremes(extremes); - } - - JsonElement rowsNode = jsonObject.get("rows"); - if (rowsNode != null) { - result.setRows(rowsNode.getAsInt()); - } - - JsonElement rows_before_limit_at_leastNode = jsonObject.get("rows_before_limit_at_least"); - if (rows_before_limit_at_leastNode != null) { - result.setRows_before_limit_at_least(rows_before_limit_at_leastNode.getAsInt()); - } - - return result; - } - - private List getAsStringArray(JsonElement row) { - JsonArray rowArray = row.getAsJsonArray(); - List rowList = new ArrayList<>(); - rowArray.forEach(value -> { - String valueStr = getAsString(value); - rowList.add(valueStr); - }); - return rowList; - } - - private String getAsString(JsonElement value) { - String valueStr; - if (value.isJsonPrimitive()) { - valueStr = value.getAsString(); - } else if (value.isJsonArray()) { - valueStr = arrayToString(value); - } else if (value.isJsonNull()){ - valueStr = null; - } else { - valueStr = value.toString(); - } - return valueStr; - } - - private ClickHouseResponse.Meta parseMeta(JsonElement e) { - JsonObject metaObject = e.getAsJsonObject(); - ClickHouseResponse.Meta meta = new ClickHouseResponse.Meta(); - meta.setName(metaObject.get("name").getAsString()); - meta.setType(metaObject.get("type").getAsString()); - return meta; - } - - private String arrayToString(JsonElement value) { - return value.getAsJsonArray().toString(); - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseResponseSummary.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseResponseSummary.java deleted file mode 100644 index af1d0e38b..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseResponseSummary.java +++ /dev/null @@ -1,38 +0,0 @@ -package ru.yandex.clickhouse.response; - -public class ClickHouseResponseSummary { - private final long read_rows; // number of read rows for selects (may be more than rows in result set) - private final long written_rows; // number of written rows for inserts - private final long read_bytes; - private final long written_bytes; - private final long total_rows_to_read; - - public ClickHouseResponseSummary(long read_rows, long written_rows, long read_bytes, long written_bytes, - long total_rows_to_read) { - this.read_rows = read_rows; - this.written_rows = written_rows; - this.read_bytes = read_bytes; - this.written_bytes = written_bytes; - this.total_rows_to_read = total_rows_to_read; - } - - public long getReadRows() { - return read_rows; - } - - public long getWrittenRows() { - return written_rows; - } - - public long getReadBytes() { - return read_bytes; - } - - public long getWrittenBytes() { - return written_bytes; - } - - public long getTotalRowsToRead() { - return total_rows_to_read; - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseResultBuilder.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseResultBuilder.java deleted file mode 100644 index d8173c088..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseResultBuilder.java +++ /dev/null @@ -1,127 +0,0 @@ -package ru.yandex.clickhouse.response; - -import ru.yandex.clickhouse.settings.ClickHouseProperties; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.TimeZone; - -/** - * For building ClickHouseResultSet by hands - */ -public class ClickHouseResultBuilder { - - private final int columnsNum; - private List names; - private List types; - private List> rows = new ArrayList>(); - private TimeZone timezone = TimeZone.getTimeZone("UTC"); - private boolean usesWithTotals; - private ClickHouseProperties properties = new ClickHouseProperties(); - - public static ClickHouseResultBuilder builder(int columnsNum) { - return new ClickHouseResultBuilder(columnsNum); - } - - private ClickHouseResultBuilder(int columnsNum) { - this.columnsNum = columnsNum; - } - - public ClickHouseResultBuilder names(String... names) { - return names(Arrays.asList(names)); - } - - public ClickHouseResultBuilder types(String... types) { - return types(Arrays.asList(types)); - } - - public ClickHouseResultBuilder addRow(Object... row) { - return addRow(Arrays.asList(row)); - } - - public ClickHouseResultBuilder withTotals(boolean usesWithTotals) { - this.usesWithTotals = usesWithTotals; - return this; - } - - public ClickHouseResultBuilder names(List names) { - if (names.size() != columnsNum) throw new IllegalArgumentException("size mismatch, req: " + columnsNum + " got: " + names.size()); - this.names = names; - return this; - } - - public ClickHouseResultBuilder types(List types) { - if (types.size() != columnsNum) throw new IllegalArgumentException("size mismatch, req: " + columnsNum + " got: " + types.size()); - this.types = types; - return this; - } - - public ClickHouseResultBuilder addRow(List row) { - if (row.size() != columnsNum) throw new IllegalArgumentException("size mismatch, req: " + columnsNum + " got: " + row.size()); - rows.add(row); - return this; - } - - public ClickHouseResultBuilder timeZone(TimeZone timezone) { - this.timezone = timezone; - return this; - } - - public ClickHouseResultBuilder properties(ClickHouseProperties properties) { - this.properties = properties; - return this; - } - - public ClickHouseResultSet build() { - try { - if (names == null) throw new IllegalStateException("names == null"); - if (types == null) throw new IllegalStateException("types == null"); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - appendRow(names, baos); - appendRow(types, baos); - for (List row : rows) { - appendRow(row, baos); - } - - byte[] bytes = baos.toByteArray(); - ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes); - - return new ClickHouseResultSet(inputStream, 1024, "system", "unknown", usesWithTotals, null, timezone, properties); - } catch (IOException e) { - throw new RuntimeException("Never happens", e); - } - } - - private void appendRow(List row, ByteArrayOutputStream baos) throws IOException { - for (int i = 0; i < row.size(); i++) { - if (i != 0) baos.write('\t'); - appendObject(row.get(i), baos); - } - baos.write('\n'); - } - - private void appendObject(Object o, ByteArrayOutputStream baos) throws IOException { - if (o == null) { - baos.write('\\'); - baos.write('N'); - } else { - String value; - if (o instanceof Boolean) { - if ((Boolean) o) { - value = "1"; - } else { - value = "0"; - } - } else { - value = o.toString(); - } - ByteFragment.escape(value.getBytes(StandardCharsets.UTF_8), baos); - } - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseResultSet.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseResultSet.java deleted file mode 100644 index 07cac08de..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseResultSet.java +++ /dev/null @@ -1,847 +0,0 @@ -package ru.yandex.clickhouse.response; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.math.RoundingMode; -import java.sql.Array; -import java.sql.Date; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.sql.Statement; -import java.sql.Time; -import java.sql.Timestamp; -import java.sql.Types; -import java.time.Instant; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collections; -import java.util.List; -import java.util.TimeZone; -import ru.yandex.clickhouse.ClickHouseArray; -import ru.yandex.clickhouse.ClickHouseConnection; -import ru.yandex.clickhouse.ClickHouseStatement; -import ru.yandex.clickhouse.domain.ClickHouseDataType; -import ru.yandex.clickhouse.except.ClickHouseExceptionSpecifier; -import ru.yandex.clickhouse.except.ClickHouseUnknownException; -import ru.yandex.clickhouse.response.parser.ClickHouseValueParser; -import ru.yandex.clickhouse.settings.ClickHouseProperties; -import ru.yandex.clickhouse.util.ClickHouseArrayUtil; -import ru.yandex.clickhouse.util.ClickHouseBitmap; -import ru.yandex.clickhouse.util.ClickHouseValueFormatter; -import ru.yandex.clickhouse.util.Utils; - - -public class ClickHouseResultSet extends AbstractResultSet { - - private static final long[] EMPTY_LONG_ARRAY = new long[0]; - - private final TimeZone dateTimeTimeZone; - private final TimeZone dateTimeZone; - - private final StreamSplitter bis; - - private final String db; - private final String table; - - private List columns; - - private int maxRows; - - // current line - protected ByteFragment[] values; - // 1-based - private int lastReadColumn; - - // next line - protected ByteFragment nextLine; - - // total lines - private ByteFragment totalLine; - - // row counter - protected int rowNumber; - - // statement result set belongs to - private final ClickHouseStatement statement; - - private final ClickHouseProperties properties; - - private boolean usesWithTotals; - - // NOTE this can't be used for `isLast` impl because - // it does not do prefetch. It is effectively a witness - // to the fact that rs.next() returned false. - private boolean lastReached = false; - - private boolean isAfterLastReached = false; - - public ClickHouseResultSet(InputStream is, int bufferSize, String db, String table, - boolean usesWithTotals, ClickHouseStatement statement, TimeZone timeZone, - ClickHouseProperties properties) throws IOException - { - this.db = db; - this.table = table; - this.statement = statement; - this.properties = properties; - this.usesWithTotals = usesWithTotals; - this.dateTimeTimeZone = timeZone; - this.dateTimeZone = properties.isUseServerTimeZoneForDates() - ? timeZone - : TimeZone.getDefault(); // FIXME should be the timezone defined in useTimeZone? - bis = new StreamSplitter(is, (byte) 0x0A, bufferSize); /// \n - ByteFragment headerFragment = bis.next(); - if (headerFragment == null) { - throw new IllegalArgumentException("ClickHouse response without column names"); - } - String header = headerFragment.asString(true); - if (header.startsWith("Code: ") && !header.contains("\t")) { - is.close(); - throw new IOException("ClickHouse error: " + header); - } - String[] cols = toStringArray(headerFragment); - ByteFragment typesFragment = bis.next(); - if (typesFragment == null) { - throw new IllegalArgumentException("ClickHouse response without column types"); - } - String[] types = toStringArray(typesFragment); - columns = new ArrayList<>(cols.length); - TimeZone tz = null; - try { - if (statement != null && statement.getConnection() instanceof ClickHouseConnection) { - tz = ((ClickHouseConnection)statement.getConnection()).getServerTimeZone(); - } - } catch (SQLException e) { - // ignore the error - } - - if (tz == null) { - tz = timeZone; - } - - for (int i = 0; i < cols.length; i++) { - columns.add(ClickHouseColumnInfo.parse(types[i], cols[i], tz)); - } - } - - private static String[] toStringArray(ByteFragment headerFragment) { - ByteFragment[] split = headerFragment.split((byte) 0x09); - String[] c = new String[split.length]; - for (int i = 0; i < split.length; i++) { - String name = split[i].asString(true); - c[i] = name; - } - return c; - } - - /** - * Check if there is another row. - * - * @return {@code true} if this result set has another row after the current - * cursor position, {@code false} else - * @throws SQLException if something goes wrong - */ - protected boolean hasNext() throws SQLException { - if (nextLine == null && !lastReached) { - try { - nextLine = bis.next(); - - if (nextLine == null - || (maxRows != 0 && rowNumber >= maxRows) - || (usesWithTotals && nextLine.length() == 0)) { - if (usesWithTotals) { - if (onTheSeparatorRow()) { - totalLine = bis.next(); - endOfStream(); - } // otherwise do not close the stream, it is single column or invalid result set case - } else { - endOfStream(); - } - } - } catch (IOException e) { - throw new SQLException(e); - } - } - return nextLine != null; - } - - @Override - public boolean isBeforeFirst() throws SQLException { - return rowNumber == 0 && hasNext(); - } - - @Override - public boolean isAfterLast() throws SQLException { - return isAfterLastReached; - } - - @Override - public boolean isFirst() throws SQLException { - return rowNumber == 1; - } - - @Override - public boolean isLast() throws SQLException { - return !hasNext(); - // && !isAfterLastReached should be probably added, - // but it may brake compatibility with the previous implementation - } - - private void endOfStream() throws IOException { - bis.close(); - lastReached = true; - nextLine = null; - } - - @Override - public boolean next() throws SQLException { - if (hasNext()) { - values = nextLine.split((byte) 0x09); - checkValues(columns, values, nextLine); - nextLine = null; - rowNumber += 1; - return true; - } - isAfterLastReached = true; - return false; - } - - private boolean onTheSeparatorRow() throws IOException { - // test bis vs "\n???\nEOF" pattern if not then rest to current position - bis.mark(); - boolean onSeparatorRow = bis.next() !=null && bis.next() == null; - bis.reset(); - - return onSeparatorRow; - } - - private static void checkValues(List columns, ByteFragment[] values, - ByteFragment fragment) throws SQLException - { - if (columns.size() != values.length) { - throw ClickHouseExceptionSpecifier.specify(fragment.asString()); - } - } - - @Override - public void close() throws SQLException { - try { - bis.close(); - } catch (IOException e) { - throw new SQLException(e); - } - } - - @Override - public boolean isClosed() throws SQLException { - try { - return bis.isClosed(); - } catch (IOException e) { - throw new SQLException(e); - } - } - - public void getTotals() throws SQLException { - if (!usesWithTotals) { - throw new IllegalStateException("Cannot get totals when totals are not being used."); - } - - nextLine = totalLine; - - this.next(); - } - - // this method is mocked in a test, do not make it final :-) - List getColumns() { - return Collections.unmodifiableList(columns); - } - - @Override - public ResultSetMetaData getMetaData() throws SQLException { - return new ClickHouseResultSetMetaData(this); - } - - @Override - public boolean wasNull() throws SQLException { - if (lastReadColumn == 0) { - throw new IllegalStateException("You should get something before check nullability"); - } - return getValue(lastReadColumn).isNull(); - } - - @Override - public int getInt(String column) throws SQLException { - return getInt(findColumn(column)); - } - - @Override - public boolean getBoolean(String column) throws SQLException { - return getBoolean(findColumn(column)); - } - - @Override - public long getLong(String column) throws SQLException { - return getLong(findColumn(column)); - } - - @Override - public String getString(String column) throws SQLException { - return getString(findColumn(column)); - } - - @Override - public byte[] getBytes(String column) throws SQLException { - return getBytes(findColumn(column)); - } - - @Override - public Timestamp getTimestamp(String column) throws SQLException { - return getTimestamp(findColumn(column)); - } - - @Override - public Timestamp getTimestamp(int columnIndex) throws SQLException { - ClickHouseColumnInfo columnInfo = getColumnInfo(columnIndex); - TimeZone tz = getEffectiveTimeZone(columnInfo); - - return ClickHouseValueParser.getParser(Timestamp.class).parse( - getValue(columnIndex), columnInfo, tz); - } - - private TimeZone getEffectiveTimeZone(ClickHouseColumnInfo columnInfo) { - TimeZone tz = null; - - if (columnInfo.getClickHouseDataType() == ClickHouseDataType.Date) { - tz = dateTimeZone; - } else { - tz = properties.isUseServerTimeZone() ? null : dateTimeTimeZone; - } - - return tz; - } - - @Override - public Timestamp getTimestamp(String column, Calendar cal) throws SQLException { - return getTimestamp(findColumn(column), cal); - } - - @Override - public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { - return getTimestamp(columnIndex); - } - - @Override - public short getShort(String column) throws SQLException { - return getShort(findColumn(column)); - } - - @Override - public byte getByte(String column) throws SQLException { - return getByte(findColumn(column)); - } - - @Override - public long[] getLongArray(String column) throws SQLException { - return getLongArray(findColumn(column)); - } - - @Override - public Array getArray(int columnIndex) throws SQLException { - ClickHouseColumnInfo colInfo = getColumnInfo(columnIndex); - if (colInfo.getClickHouseDataType() != ClickHouseDataType.Array) { - throw new SQLException("Column not an array"); - } - - final Object array; - switch (colInfo.getArrayBaseType()) { - case Date : - array = ClickHouseArrayUtil.parseArray( - getValue(columnIndex), - properties.isUseObjectsInArrays(), - dateTimeZone, - colInfo - ); - break; - default : - TimeZone timeZone = colInfo.getTimeZone() != null - ? colInfo.getTimeZone() - : dateTimeTimeZone; - array = ClickHouseArrayUtil.parseArray( - getValue(columnIndex), - properties.isUseObjectsInArrays(), - timeZone, - colInfo - ); - break; - } - return new ClickHouseArray(colInfo.getArrayBaseType(), array); - } - - @Override - public Array getArray(String column) throws SQLException { - return getArray(findColumn(column)); - } - - @Override - public double getDouble(String columnLabel) throws SQLException { - return getDouble(findColumn(columnLabel)); - } - - @Override - public float getFloat(String columnLabel) throws SQLException { - return getFloat(findColumn(columnLabel)); - } - - @Override - public Date getDate(String columnLabel) throws SQLException { - return getDate(findColumn(columnLabel)); - } - - @Override - public Time getTime(String columnLabel) throws SQLException { - return getTime(findColumn(columnLabel)); - } - - @Override - public Object getObject(String columnLabel) throws SQLException { - return getObject(findColumn(columnLabel)); - } - - @Override - public String getString(int colNum) throws SQLException { - // FIXME this won't help when datetime string is in a nested structure - ClickHouseColumnInfo columnInfo = getColumnInfo(colNum); - ByteFragment value = getValue(colNum); - ClickHouseDataType dataType = columnInfo.getClickHouseDataType(); - - // Date is time-zone netural so let's skip that. - // DateTime string returned from Server however is always formatted using server/column - // timezone. The behaviour may change when - // https://github.com/ClickHouse/ClickHouse/issues/4548 is addressed - if (!properties.isUseServerTimeZone() && ( - dataType == ClickHouseDataType.DateTime - || dataType == ClickHouseDataType.DateTime32 - || dataType == ClickHouseDataType.DateTime64)) { - TimeZone serverTimeZone = columnInfo.getTimeZone(); - if (serverTimeZone == null) { - serverTimeZone = ((ClickHouseConnection) getStatement().getConnection()).getServerTimeZone(); - } - TimeZone clientTimeZone = Utils.isNullOrEmptyString(properties.getUseTimeZone()) - ? TimeZone.getDefault() - : TimeZone.getTimeZone(properties.getUseTimeZone()); - - if (!clientTimeZone.equals(serverTimeZone)) { - Timestamp newTs = ClickHouseValueParser.getParser(Timestamp.class) - .parse(value, columnInfo, serverTimeZone); - value = ByteFragment.fromString(ClickHouseValueFormatter.formatTimestamp(newTs, clientTimeZone)); - } - } - - return ClickHouseValueParser.getParser(String.class).parse(value, columnInfo, null); - } - - @Override - public int getInt(int colNum) throws SQLException { - return ClickHouseValueParser.parseInt( - getValue(colNum), getColumnInfo(colNum)); - } - - @Override - public boolean getBoolean(int colNum) throws SQLException { - return ClickHouseValueParser.parseBoolean( - getValue(colNum), getColumnInfo(colNum)); - } - - @Override - public long getLong(int colNum) throws SQLException { - return ClickHouseValueParser.parseLong( - getValue(colNum), getColumnInfo(colNum)); - } - - @Override - public byte[] getBytes(int colNum) { - return toBytes(getValue(colNum)); - } - - /** - * Tries to parse the value as a timestamp using the connection time zone if - * applicable and return its representation as milliseconds since epoch. - * - * @param colNum - * column number - * @return timestamp value as milliseconds since epoch - * @deprecated prefer to use regular JDBC API methods, e.g. - * {@link #getTimestamp(int)} or {@link #getObject(int, Class)} - * using {@link Instant} - */ - @Deprecated - public Long getTimestampAsLong(int colNum) { - ClickHouseColumnInfo columnInfo = getColumnInfo(colNum); - TimeZone tz = getEffectiveTimeZone(columnInfo); - return getTimestampAsLong(colNum, tz); - } - - /** - * Tries to parse the value as a timestamp and return its representation as - * milliseconds since epoch - * - * @param colNum - * the column number - * @param timeZone - * time zone to use when parsing date / date time values - * @return value interpreted as timestamp as milliseconds since epoch - * @deprecated prefer to use regular JDBC API method - */ - @Deprecated - public Long getTimestampAsLong(int colNum, TimeZone timeZone) { - ByteFragment value = getValue(colNum); - if (value.isNull() || value.asString().equals("0000-00-00 00:00:00")) { - return null; - } - try { - Instant instant = ClickHouseValueParser.getParser(Instant.class) - .parse(value, getColumnInfo(colNum), timeZone); - return Long.valueOf(instant.toEpochMilli()); - } catch (SQLException sqle) { - throw new RuntimeException(sqle); - } - } - - @Override - public short getShort(int colNum) throws SQLException { - return ClickHouseValueParser.parseShort( - getValue(colNum), getColumnInfo(colNum)); - } - - @Override - public byte getByte(int colNum) { - return toByte(getValue(colNum)); - } - - /** - * Parse the value in current row at column index {@code colNum} as an array - * of long - * - * @param colNum - * column number - * @return an array of longs - * @throws SQLException - * if the value cannot be interpreted as {@code long[]} - * @deprecated prefer to use regular JDBC API - */ - @Deprecated - public long[] getLongArray(int colNum) throws SQLException { - return toLongArray(getValue(colNum), getColumnInfo(colNum)); - } - - @Override - public float getFloat(int columnIndex) throws SQLException { - return ClickHouseValueParser.parseFloat( - getValue(columnIndex), getColumnInfo(columnIndex)); - } - - @Override - public double getDouble(int columnIndex) throws SQLException { - return ClickHouseValueParser.parseDouble( - getValue(columnIndex), getColumnInfo(columnIndex)); - } - - @Override - public Statement getStatement() { - return statement; - } - - @Override - public Date getDate(int columnIndex) throws SQLException { - ClickHouseColumnInfo columnInfo = getColumnInfo(columnIndex); - TimeZone tz = getEffectiveTimeZone(columnInfo); - return ClickHouseValueParser.getParser(Date.class).parse( - getValue(columnIndex), columnInfo, tz); - } - - @Override - public Date getDate(int columnIndex, Calendar calendar) throws SQLException { - return getDate(columnIndex); - } - - @Override - public Time getTime(int columnIndex) throws SQLException { - ClickHouseColumnInfo columnInfo = getColumnInfo(columnIndex); - TimeZone tz = getEffectiveTimeZone(columnInfo); - return ClickHouseValueParser.getParser(Time.class).parse( - getValue(columnIndex), columnInfo, tz); - } - - @Override - public Time getTime(int columnIndex, Calendar calendar) throws SQLException { - return getTime(columnIndex); - } - - @Override - public Object getObject(int columnIndex) throws SQLException { - try { - if (getValue(columnIndex).isNull()) { - return null; - } - ClickHouseColumnInfo columnInfo = getColumnInfo(columnIndex); - ClickHouseDataType chType = columnInfo.getClickHouseDataType(); - switch (chType.getSqlType()) { - case Types.BIGINT: - if (chType == ClickHouseDataType.UInt64) { - return getObject(columnIndex, BigInteger.class); - } - return getObject(columnIndex, Long.class); - case Types.INTEGER: - if (!chType.isSigned()){ - return getObject(columnIndex, Long.class); - } - return getObject(columnIndex, Integer.class); - case Types.TINYINT: - case Types.SMALLINT: - return getObject(columnIndex, Integer.class); - case Types.VARCHAR: return getString(columnIndex); - case Types.REAL: return getObject(columnIndex, Float.class); - case Types.FLOAT: - case Types.DOUBLE: return getObject(columnIndex, Double.class); - case Types.DATE: return getDate(columnIndex); - case Types.TIMESTAMP: return getTimestamp(columnIndex); - case Types.BLOB: return getString(columnIndex); - case Types.ARRAY: return getArray(columnIndex); - case Types.DECIMAL: return getBigDecimal(columnIndex); - case Types.NUMERIC: return getBigInteger(columnIndex); - default: - // do not return - } - switch (chType) { - // case Array: - // case Tuple: - case AggregateFunction: - // TODO support more functions - if ("groupBitmap".equals(columnInfo.getFunctionName())) { - ClickHouseDataType innerType = columnInfo.getArrayBaseType(); - switch (innerType) { - // seems signed integers are not supported in ClickHouse - case Int8: - case Int16: - case Int32: - case Int64: - case UInt8: - case UInt16: - case UInt32: - case UInt64: - return getObject(columnIndex, ClickHouseBitmap.class); - default: - break; - } - } - return getString(columnIndex); - case Map: - case UUID : - return getObject(columnIndex, chType.getJavaClass()); - default : - return getString(columnIndex); - } - } catch (Exception e) { - throw new ClickHouseUnknownException( - "Parse exception: " + values[columnIndex - 1].toString(), - e); - } - } - - ///////////////////////////////////////////////////////// - - private static byte toByte(ByteFragment value) { - if (value.isNull()) { - return 0; - } - return Byte.parseByte(value.asString()); - } - - private static byte[] toBytes(ByteFragment value) { - if (value.isNull()) { - return null; - } - return value.unescape(); - } - - static long[] toLongArray(ByteFragment value, ClickHouseColumnInfo columnInfo) throws SQLException { - if (value.isNull()) { - return null; - } - if (value.charAt(0) != '[' || value.charAt(value.length() - 1) != ']') { - throw new IllegalArgumentException("not an array: " + value); - } - if (value.length() == 2) { - return EMPTY_LONG_ARRAY; - } - ByteFragment trim = value.subseq(1, value.length() - 2); - ByteFragment[] values = trim.split((byte) ','); - long[] result = new long[values.length]; - for (int i = 0; i < values.length; i++) { - result[i] = ClickHouseValueParser.parseLong(values[i], columnInfo); - } - return result; - } - - ////// - - @Override - public int getType() throws SQLException { - return TYPE_FORWARD_ONLY; - } - - @Override - public int getRow() throws SQLException { - return rowNumber; - } - - public String getDb() { - return db; - } - - public String getTable() { - return table; - } - - public void setMaxRows(int maxRows) { - this.maxRows = maxRows; - } - - ///// - - // 1-based index in column list - @Override - public int findColumn(String column) throws SQLException { - if (column == null || column.isEmpty()) { - throw new ClickHouseUnknownException( - "column name required", null); - } - for (int i = 0; i < columns.size(); i++) { - if (column.equalsIgnoreCase(columns.get(i).getColumnName())) { - return i+1; - } - } - throw new SQLException("no column " + column + " in columns list " + getColumnNamesString()); - } - - private ByteFragment getValue(int colNum) { - lastReadColumn = colNum; - return values[colNum - 1]; - } - - private ClickHouseColumnInfo getColumnInfo(int colNum) { - return columns.get(colNum - 1); - } - - @SuppressWarnings("unchecked") - @Override - public T getObject(int columnIndex, Class type) throws SQLException { - if (String.class.equals(type)) { - return (T) getString(columnIndex); - } - - ClickHouseColumnInfo columnInfo = getColumnInfo(columnIndex); - TimeZone tz = getEffectiveTimeZone(columnInfo); - return columnInfo.isArray() - ? (Array.class.isAssignableFrom(type) ? (T) getArray(columnIndex) : (T) getArray(columnIndex).getArray()) - : ClickHouseValueParser.getParser(type).parse(getValue(columnIndex), columnInfo, tz); - } - - @Override - public T getObject(String columnLabel, Class type) throws SQLException { - return getObject(findColumn(columnLabel), type); - } - - /** - * Retrieve the results in "raw" form. - * - * @return the results as an array of {@link ByteFragment}s - * @deprecated prefer to use regular JDBC API to retrieve the results - */ - @Deprecated - public ByteFragment[] getValues() { - return values; - } - - @Override - public BigDecimal getBigDecimal(String columnLabel) throws SQLException { - return getBigDecimal(findColumn(columnLabel)); - } - - @Override - public BigDecimal getBigDecimal(int columnIndex) throws SQLException { - return ClickHouseValueParser.getParser(BigDecimal.class) - .parse(getValue(columnIndex), getColumnInfo(columnIndex), null); - } - - @Override - public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException { - return getBigDecimal(findColumn(columnLabel), scale); - } - - @Override - public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { - BigDecimal result = ClickHouseValueParser.getParser(BigDecimal.class) - .parse(getValue(columnIndex), getColumnInfo(columnIndex), null); - return result != null - ? result.setScale(scale, RoundingMode.HALF_UP) - : null; - } - - public BigInteger getBigInteger(String columnLabel) throws SQLException { - return getBigInteger(findColumn(columnLabel)); - } - - public BigInteger getBigInteger(int columnIndex) throws SQLException { - BigDecimal dec = getBigDecimal(columnIndex); - return dec == null ? null : dec.toBigInteger(); - } - - public String[] getColumnNames() { - String[] columnNames = new String[columns.size()]; - for (int i = 0; i < columns.size(); ++i) { - columnNames[i] = columns.get(i).getColumnName(); - } - return columnNames; - } - - @Override - public void setFetchDirection(int direction) throws SQLException { - // ignore perfomance hint - } - - @Override - public void setFetchSize(int rows) throws SQLException { - // ignore perfomance hint - } - - - @Override - public String toString() { - return "ClickHouseResultSet{" + - "dateTimeTimeZone=" + dateTimeTimeZone.toString() + - ", dateTimeZone=" + dateTimeZone.toString() + - ", bis=" + bis + - ", db='" + db + '\'' + - ", table='" + table + '\'' + - ", columns=" + getColumnNamesString() + - ", maxRows=" + maxRows + - ", values=" + Arrays.toString(values) + - ", lastReadColumn=" + lastReadColumn + - ", nextLine=" + nextLine + - ", rowNumber=" + rowNumber + - ", statement=" + statement + - '}'; - } - - private String getColumnNamesString() { - StringBuilder sb = new StringBuilder(); - for (ClickHouseColumnInfo info : columns) { - sb.append(info.getColumnName()).append(' '); - } - return sb.substring(0, sb.length() - 1); - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseResultSetMetaData.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseResultSetMetaData.java deleted file mode 100644 index 970c3d507..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseResultSetMetaData.java +++ /dev/null @@ -1,139 +0,0 @@ -package ru.yandex.clickhouse.response; - -import java.sql.ResultSetMetaData; -import java.sql.SQLException; - -public class ClickHouseResultSetMetaData implements ResultSetMetaData { - - private final ClickHouseResultSet resultSet; - - ClickHouseResultSetMetaData(ClickHouseResultSet resultSet) { - this.resultSet = resultSet; - } - - @Override - public int getColumnCount() throws SQLException { - return resultSet.getColumns().size(); - } - - @Override - public boolean isAutoIncrement(int column) throws SQLException { - return false; - } - - @Override - public boolean isCaseSensitive(int column) throws SQLException { - return true; - } - - @Override - public boolean isSearchable(int column) throws SQLException { - return true; - } - - @Override - public boolean isCurrency(int column) throws SQLException { - return false; - } - - @Override - public int isNullable(int column) throws SQLException { - return getCol(column).isNullable() - ? columnNullable - : columnNoNulls; - } - - @Override - public boolean isSigned(int column) throws SQLException { - return getCol(column).getClickHouseDataType().isSigned(); - } - - @Override - public int getColumnDisplaySize(int column) throws SQLException { - return 80; - } - - @Override - public String getColumnLabel(int column) throws SQLException { - return getColumnName(column); - } - - @Override - public String getColumnName(int column) throws SQLException { - return getCol(column).getColumnName(); - } - - @Override - public String getSchemaName(int column) throws SQLException { - return ""; - } - - @Override - public int getPrecision(int column) throws SQLException { - return getCol(column).getPrecision(); - } - - @Override - public int getScale(int column) throws SQLException { - return getCol(column).getScale(); - } - - @Override - public String getTableName(int column) throws SQLException { - return resultSet.getTable(); - } - - @Override - public String getCatalogName(int column) throws SQLException { - return resultSet.getDb(); - } - - @Override - public int getColumnType(int column) throws SQLException { - return getCol(column).getClickHouseDataType().getSqlType(); - } - - @Override - public String getColumnTypeName(int column) throws SQLException { - return getCol(column).getCleanTypeName(); - } - - @Override - public boolean isReadOnly(int column) throws SQLException { - return true; - } - - @Override - public boolean isWritable(int column) throws SQLException { - return false; - } - - @Override - public boolean isDefinitelyWritable(int column) throws SQLException { - return false; - } - - @Override - public String getColumnClassName(int column) throws SQLException { - return getCol(column).getClickHouseDataType().getJavaClass().getCanonicalName(); - } - - @Override - @SuppressWarnings("unchecked") - public T unwrap(Class iface) throws SQLException { - if (isWrapperFor(iface)) { - return (T) this; - } - throw new SQLException("Unable to unwrap to " + iface.toString()); - } - - @Override - public boolean isWrapperFor(Class iface) throws SQLException { - return iface != null && iface.isAssignableFrom(getClass()); - } - - private ClickHouseColumnInfo getCol(int column) { - return resultSet.getColumns().get(column - 1); - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseScrollableResultSet.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseScrollableResultSet.java deleted file mode 100644 index 4a334c1b5..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/ClickHouseScrollableResultSet.java +++ /dev/null @@ -1,146 +0,0 @@ -package ru.yandex.clickhouse.response; - -import ru.yandex.clickhouse.ClickHouseStatement; -import ru.yandex.clickhouse.settings.ClickHouseProperties; - -import java.io.IOException; -import java.io.InputStream; -import java.sql.*; -import java.util.*; - - -public class ClickHouseScrollableResultSet extends ClickHouseResultSet { - - private List lines; - - public ClickHouseScrollableResultSet(InputStream is, int bufferSize, String db, String table, boolean usesWithTotals, ClickHouseStatement statement, TimeZone timezone, ClickHouseProperties properties) throws IOException { - super(is, bufferSize, db, table, usesWithTotals, statement, timezone, properties); - lines = new ArrayList(); - } - - public boolean hasNext() throws SQLException { - if(rowNumber < lines.size()) { - return true; - } - return super.hasNext(); - } - - @Override - public boolean next() throws SQLException { - if(rowNumber < lines.size()) { - values = lines.get(rowNumber); - nextLine = null; - rowNumber += 1; - return true; - } - if (hasNext()) { - super.next(); - lines.add(values); - return true; - } else { - rowNumber += 1; - values = null; - nextLine = null; - return false; - } - } - - ////// - - @Override - public int getType() throws SQLException { - return TYPE_SCROLL_INSENSITIVE; - } - - @Override - public int getRow() throws SQLException { - return rowNumber; - } - - @Override - public boolean isBeforeFirst() throws SQLException { - return getRow() == 0; - } - - @Override - public boolean isAfterLast() throws SQLException { - return getRow() > lines.size(); - } - - @Override - public boolean isFirst() throws SQLException { - return getRow() == 1; - } - - @Override - public void beforeFirst() throws SQLException { - absolute(0); - } - - @Override - public void afterLast() throws SQLException { - absolute(-1); - next(); - } - - @Override - public boolean first() throws SQLException { - return absolute(1); - } - - - @Override - public boolean last() throws SQLException { - return absolute(-1); - } - - @Override - public boolean absolute(int row) throws SQLException { - if(row == 0) { - rowNumber = 0; - values = null; - return false; - } else if(row > 0) { - if(row <= lines.size()) { - rowNumber = row; - values = lines.get(row-1); - return true; - } - absolute(lines.size()); - while(getRow() < row && hasNext()) { - next(); - } - if(row == getRow()) { - return true; - } else { - next(); - return false; - } - } else { - // We have to check the number of total rows - while(hasNext()) { - next(); - } - if(-row > lines.size()) { - // there is not so many rows - // Put the cursor before the first row - return absolute(0); - } - return absolute(lines.size()+1+row); - } - } - - @Override - public boolean relative(int rows) throws SQLException { - int r = getRow()+rows; - if(r < 0) { - r = 0; - } - return absolute(r); - } - - @Override - public boolean previous() throws SQLException { - return relative(-1); - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/FastByteArrayInputStream.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/FastByteArrayInputStream.java deleted file mode 100644 index e2671a724..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/FastByteArrayInputStream.java +++ /dev/null @@ -1,118 +0,0 @@ -package ru.yandex.clickhouse.response; - -import java.io.IOException; -import java.io.InputStream; - -/** - * Not synchronized quick version of {@link java.io.ByteArrayInputStream} - */ -public final class FastByteArrayInputStream extends InputStream { - private final byte[] buf; - - private int pos; - - private final int count; - - public FastByteArrayInputStream(byte[] buf) { - this.buf = buf; - pos = 0; - count = buf.length; - } - - /** - * Special constructor fo creating InputStream over not fully filled array - * @param buf byte array - * @param count number of filled elements - */ - public FastByteArrayInputStream(byte[] buf, int count) { - this.buf = buf; - pos = 0; - this.count = count; - } - - - @Override - public int read() { - return pos < count ? buf[pos++] & 0xff : -1; - } - - - @Override - public int read(byte[] b, int off, int len) { - if (off < 0 || len < 0 || len > b.length - off) { - throw new IndexOutOfBoundsException(); - } - if (pos >= count) { - return -1; - } - if (pos + len > count) { - //noinspection AssignmentToMethodParameter - len = count - pos; - } - if (len <= 0) { - return 0; - } - System.arraycopy(buf, pos, b, off, len); - pos += len; - return len; - } - - - @Override - public long skip(long n) { - if (pos + n > count) { - //noinspection AssignmentToMethodParameter - n = count - pos; - } - if (n < 0) { - return 0; - } - pos += (int) n; - return n; - } - - - @Override - public int available() { - return count - pos; - } - - @Override - public boolean markSupported() { - return false; - } - - - @Override - public void close() throws IOException { - } - - public int getPos() { - return pos; - } - - public int getCount() { - return count; - } - - public byte[] getBuf() { - return buf; - } - - public byte[] getData() { - if (buf.length > count) { - byte[] data = new byte[count]; - System.arraycopy(buf, 0, data, 0, count); - return data; - } else { - return buf; - } - } - - @Override - public void reset() { - pos = 0; - } - - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/FastByteArrayOutputStream.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/FastByteArrayOutputStream.java deleted file mode 100644 index b8e7321f8..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/FastByteArrayOutputStream.java +++ /dev/null @@ -1,175 +0,0 @@ -package ru.yandex.clickhouse.response; - - -import java.io.DataOutput; -import java.io.IOException; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.util.Arrays; - -/** - * Not synchronized quick version of {@link java.io.ByteArrayOutputStream} - */ - -public final class FastByteArrayOutputStream extends OutputStream { - - /** - * The buffer where data is stored. - */ - private byte[] buf; - - /** - * The number of valid bytes in the buffer. - */ - private int count; - - /** - * Creates a new byte array output stream. The buffer capacity is - * initially 32 bytes, though its size increases if necessary. - */ - public FastByteArrayOutputStream() { - this(1024); - } - - /** - * Creates a new byte array output stream, with a buffer capacity of - * the specified size, in bytes. - * - * @param size the initial size. - * @exception IllegalArgumentException if size is negative. - */ - public FastByteArrayOutputStream(int size) { - super(); - if (size < 0) { - throw new IllegalArgumentException("Negative initial size: " - + size); - } - buf = new byte[size]; - } - - private int ensureCapacity(int datalen) { - int newcount = count + datalen; - if (newcount > buf.length) { - buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount)); - } - return newcount; - } - - - /** - * Writes the specified byte to this byte array output stream. - * - * @param b the byte to be written. - */ - @Override - public void write(int b) { - int newcount = ensureCapacity(1); - buf[count] = (byte)b; - count = newcount; - } - - /** - * Writes len bytes from the specified byte array - * starting at offset off to this byte array output stream. - * - * @param b the data. - * @param off the start offset in the data. - * @param len the number of bytes to write. - */ - @Override - public void write(byte[] b, int off, int len) { - if (off < 0 || off > b.length || len < 0 || off + len > b.length || off + len < 0) { - throw new IndexOutOfBoundsException(); - } else if (len == 0) { - return; - } - int newcount = ensureCapacity(len); - System.arraycopy(b, off, buf, count, len); - count = newcount; - } - - - - /** - * returns inner array - * - * @return the current contents of this output stream, as a byte array. - */ - public byte[] toByteArray() { - byte[] result = new byte[count]; - System.arraycopy(buf, 0, result, 0, count); - return result; - } - - public void writeTo(OutputStream output) throws IOException { - output.write(buf, 0, count); - } - - /** - * Returns the current size of the buffer. - * - * @return the value of the count field, which is the number - * of valid bytes in this output stream. - */ - public int size() { - return count; - } - - - /** - * Closing a {@code ByteArrayOutputStream} has no effect. The methods in - * this class can be called after the stream has been closed without - * generating an {@code IOException}. - */ - @Override - public void close() throws IOException { - } - - /** - * Copies data from input stream - * @param source source stream - * @param offset offset in the source - * @param count number of bytes to copy - */ - public void copyFrom(FastByteArrayInputStream source, int offset, int count) { - if (offset + count > source.getCount()) { - throw new IndexOutOfBoundsException( - "Trying to copy data past the end of source" - + ", source.size=" + source.getCount() - + ", offset=" + offset + ", count=" + count - ); - } - byte[] srcBuf = source.getBuf(); - write(srcBuf, offset, count); - } - - public void copyTo(OutputStream dest) throws IOException { - dest.write(buf, 0, count); - } - - public void copyTo(DataOutput dest) throws IOException { - dest.write(buf, 0, count); - } - - /** - * Creates InputStream using the same data that is written into this stream with no copying in memory - * @return a input stream contained all bytes recorded in a current stream - */ - public FastByteArrayInputStream convertToInputStream() { - return new FastByteArrayInputStream(buf, count); - } - - public ByteBuffer toByteBuffer() { - return ByteBuffer.wrap(buf, 0, count); - } - - public byte[] getBuffer() { - return buf; - } - - - public void reset() { - count = 0; - } -} - diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/StreamSplitter.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/StreamSplitter.java deleted file mode 100644 index b6d857f49..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/StreamSplitter.java +++ /dev/null @@ -1,163 +0,0 @@ -package ru.yandex.clickhouse.response; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; - -/** - * We have a stream of bytes and a separator as an input. - * We split the stream by the separator and pass the byte arrays to output. - */ -public class StreamSplitter { - private static final int MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8; - private static final int buflen = 65536; - - // initial parameters - private final InputStream delegate; - private final byte sep; - - private byte[] buf; - // position until which the buf is filled with values read from delegate - private int posRead; - // position until which the values from buf already passed out through next() - private int posNext; - - private int markedRead; - private int markedNext; - - private boolean readOnce; - - private boolean closed; - - public StreamSplitter(ByteFragment bf, byte sep) { - this.delegate = bf.asStream(); - this.sep = sep; - buf = new byte[bf.getLen()]; - readOnce = true; - } - - public StreamSplitter(InputStream delegate, byte sep, int buflen) { - this.delegate = delegate; - this.sep = sep; - buf = new byte[buflen]; - } - - public StreamSplitter(InputStream delegate, byte sep) { - this(delegate, sep, buflen); - } - - public ByteFragment next() throws IOException { - // if sent out all that have read - if (posNext >= posRead) { - // need to read more from the stream - int readBytes = readFromStream(); - if (readBytes <= 0) { - // if everything was sent out and there is nothing left in the stream - return null; - } - } - // looking for the separator - int positionSep; - while ((positionSep = indexOf(buf, sep, posNext, posRead)) < posNext) { - // read from stream till we find the separator - int readBytes = readFromStream(); - if (readBytes <= 0) { - // if there is nothing to read, return everything left as a result - positionSep = posRead; - break; - } - } - // if the separator is found, return the fragment - int fragmentStart = posNext; - posNext = positionSep + 1; - return new ByteFragment(buf, fragmentStart, positionSep - fragmentStart); - } - - // if there is no separator in read but not sent fragment - read more data - protected int readFromStream() throws IOException { - if (readOnce) { - if (posRead >= buf.length) { - return -1; - } else { - int read = delegate.read(buf, posRead, buf.length - posRead); - if (read > 0) { - posRead += read; - } - return read; - } - } else { - if (posRead >= buf.length) { // buffer is filled - shiftOrResize(); - } - int read = delegate.read(buf, posRead, buf.length - posRead); - if (read > 0) { - posRead += read; - } - return read; - } - } - - - // if we have read till the end of buffer, we have to create a new buffer - // and move data by posNext (already send data position) - // if there is no sent data and buffer is still full - expand the buffer - private void shiftOrResize() { - if (posNext > 0) { - byte[] oldBuf = buf; - buf = new byte[buf.length]; - System.arraycopy(oldBuf, posNext, buf, 0, oldBuf.length - posNext); - posRead -= posNext; - posNext = 0; - } else { - byte[] oldBuf = buf; - int len = buf.length * 2; - if (len > MAX_ARRAY_LENGTH) { - len = MAX_ARRAY_LENGTH; - } - buf = new byte[len]; - System.arraycopy(oldBuf, 0, buf, 0, oldBuf.length); - } - } - - private static int indexOf(byte[] array, byte target, int start, int end) { - for (int i = start; i < end; i++) { - if (array[i] == target) { - return i; - } - } - return -1; - } - - public void close() throws IOException { - closed = true; - delegate.close(); - } - - public boolean isClosed() throws IOException { - return closed; - } - - @Override - public String toString() { - String bufStr = new String(buf, StandardCharsets.UTF_8).trim(); - - return "StreamSplitter{" - + "delegate=" + delegate - + ", sep=" + sep - + ", buf=" + bufStr - + ", posRead=" + posRead - + ", posNext=" + posNext - + ", readOnce=" + readOnce - + '}'; - } - - public void mark() { - markedRead = posRead; - markedNext = posNext; - } - - public void reset() { - posRead = markedRead; - posNext = markedNext; - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseArrayParser.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseArrayParser.java deleted file mode 100644 index 20b3afed4..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseArrayParser.java +++ /dev/null @@ -1,59 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.sql.Array; -import java.sql.SQLException; -import java.util.TimeZone; - -import ru.yandex.clickhouse.ClickHouseArray; -import ru.yandex.clickhouse.domain.ClickHouseDataType; -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; -import ru.yandex.clickhouse.util.ClickHouseArrayUtil; - -final class ClickHouseArrayParser extends ClickHouseValueParser { - - private static ClickHouseArrayParser instance; - - static ClickHouseArrayParser getInstance() { - if (instance == null) { - instance = new ClickHouseArrayParser(); - } - return instance; - } - - private ClickHouseArrayParser() { - // prevent instantiation - } - - @Override - public Array parse(ByteFragment value, ClickHouseColumnInfo columnInfo, TimeZone resultTimeZone) - throws SQLException { - if (columnInfo.getClickHouseDataType() != ClickHouseDataType.Array) { - throw new SQLException("Column not an array"); - } - - if (value.isNull()) { - return null; - } - - final Object array; - switch (columnInfo.getArrayBaseType()) { - case Date: - // FIXME: properties.isUseObjectsInArrays() - array = ClickHouseArrayUtil.parseArray(value, false, resultTimeZone, columnInfo); - break; - default: - // properties.isUseObjectsInArrays() - TimeZone timeZone = columnInfo.getTimeZone() != null ? columnInfo.getTimeZone() : resultTimeZone; - array = ClickHouseArrayUtil.parseArray(value, false, timeZone, columnInfo); - break; - } - - return new ClickHouseArray(columnInfo.getArrayBaseType(), array); - } - - @Override - protected Array getDefaultValue() { - return null; - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseBitmapParser.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseBitmapParser.java deleted file mode 100644 index a58f40ed3..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseBitmapParser.java +++ /dev/null @@ -1,53 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.io.IOException; -import java.sql.SQLException; -import java.util.TimeZone; -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; -import ru.yandex.clickhouse.util.ClickHouseBitmap; - -final class ClickHouseBitmapParser extends ClickHouseValueParser { - private static ClickHouseBitmapParser instance; - - static ClickHouseBitmapParser getInstance() { - if (instance == null) { - instance = new ClickHouseBitmapParser(); - } - return instance; - } - - private ClickHouseBitmapParser() { - // prevent instantiation - } - - @Override - public ClickHouseBitmap parse(ByteFragment value, ClickHouseColumnInfo columnInfo, TimeZone resultTimeZone) - throws SQLException { - if (value.isNull()) { - return null; - } - - // https://github.com/ClickHouse/ClickHouse/blob/master/src/AggregateFunctions/AggregateFunctionGroupBitmapData.h#L100 - ClickHouseBitmap rb = ClickHouseBitmap.wrap(); - - // FIXME use DataInput/DataOutput for stream after switching to RowBinary - byte[] bytes = value.unescape(); - if (bytes.length == 0) { - return rb; - } - - try { - rb = ClickHouseBitmap.deserialize(bytes, columnInfo.getArrayBaseType()); - } catch (IOException e) { - throw new SQLException("Failed to deserialize ClickHouseBitmap", e); - } - - return rb; - } - - @Override - protected ClickHouseBitmap getDefaultValue() { - return ClickHouseBitmap.wrap(); - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseDateValueParser.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseDateValueParser.java deleted file mode 100644 index 6f46b39b1..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseDateValueParser.java +++ /dev/null @@ -1,240 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.math.BigInteger; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetDateTime; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; -import java.time.format.ResolverStyle; -import java.util.Objects; -import java.util.TimeZone; -import java.util.regex.Pattern; -import ru.yandex.clickhouse.except.ClickHouseException; -import ru.yandex.clickhouse.except.ClickHouseUnknownException; -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -abstract class ClickHouseDateValueParser extends ClickHouseValueParser { - private static final Pattern PATTERN_EMPTY_DATE = - Pattern.compile("^(0000-00-00|0000-00-00 00:00:00|0)$"); - - private static final DateTimeFormatter DATE_FORMATTER = - DateTimeFormatter.ofPattern("yyyy[-]MM[-]dd"); - private static final DateTimeFormatter DATE_TIME_FORMATTER = - DateTimeFormatter.ofPattern("yyyy-MM-dd['T'][ ]HH:mm:ss"); - private static final DateTimeFormatter TIME_FORMATTER_NUMBERS = - DateTimeFormatter.ofPattern("HH[mm][ss]") - .withResolverStyle(ResolverStyle.STRICT); - - private final Class clazz; - - protected ClickHouseDateValueParser(Class clazz) { - this.clazz = Objects.requireNonNull(clazz); - } - - protected LocalDateTime dateToLocalDate(String value, ClickHouseColumnInfo columnInfo, TimeZone timeZone) { - return parseAsLocalDate(value).atStartOfDay(); - } - - protected LocalDateTime dateTimeToLocalDateTime(String value, ClickHouseColumnInfo columnInfo, TimeZone timeZone) { - TimeZone serverTimeZone = columnInfo.getTimeZone(); - LocalDateTime localDateTime = parseAsLocalDateTime(value); - if (serverTimeZone != null - && (serverTimeZone.useDaylightTime() || serverTimeZone.getRawOffset() > 0)) { // non-UTC - localDateTime = localDateTime.atZone(columnInfo.getTimeZone().toZoneId()) - .withZoneSameInstant(java.time.ZoneId.of("UTC")).toLocalDateTime(); - } - - return localDateTime; - } - - protected ZonedDateTime dateToZonedDateTime(String value, ClickHouseColumnInfo columnInfo, TimeZone timeZone) { - LocalDate localDate = parseAsLocalDate(value); - return localDate.atStartOfDay(timeZone != null ? timeZone.toZoneId() : ZoneId.systemDefault()); - } - - protected ZonedDateTime dateTimeToZonedDateTime(String value, ClickHouseColumnInfo columnInfo, TimeZone timeZone) { - LocalDateTime localDateTime = parseAsLocalDateTime(value); - return timeZone != null && !timeZone.equals(columnInfo.getTimeZone()) - ? localDateTime.atZone(columnInfo.getTimeZone().toZoneId()).withZoneSameInstant(timeZone.toZoneId()) - : localDateTime.atZone(columnInfo.getTimeZone().toZoneId()); - } - - @Override - public T parse(ByteFragment value, ClickHouseColumnInfo columnInfo, TimeZone timeZone) throws ClickHouseException { - - if (value.isNull()) { - return null; - } - - String s = value.asString(); - - /* - * filter default values for relevant data types, - * even if the column has nullable flag set. - */ - if (PATTERN_EMPTY_DATE.matcher(s).matches()) { - return null; - } - - switch (columnInfo.getEffectiveClickHouseDataType()) { - case Date: - try { - return parseDate(s, columnInfo, timeZone); - } catch (Exception e) { - throw new ClickHouseUnknownException( - "Error parsing '" + s + "' of data type '" - + columnInfo.getOriginalTypeName() - + "' as " + clazz.getName(), - e); - } - case DateTime: - case DateTime32: - case DateTime64: - try { - return parseDateTime(s, columnInfo, timeZone); - } catch (Exception e) { - throw new ClickHouseUnknownException( - "Error parsing '" + s + "' of data type '" - + columnInfo.getOriginalTypeName() - + "' as " + clazz.getName(), - e); - } - case Int8: - case Int16: - case Int32: - case Int64: - case UInt8: - case UInt16: - case UInt32: - try { - long l = Long.parseLong(s); - return parseNumber(l, columnInfo, timeZone); - } catch (Exception e) { - throw new ClickHouseUnknownException( - "Error parsing '" + s + "' of data type '" - + columnInfo.getOriginalTypeName() - + "' as " + clazz.getName(), - e); - } - case UInt64: - // If we have a large nanos value, we trim to millis - try { - BigInteger bi = new BigInteger(s); - if (bi.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) { - return parseNumber( - bi.divide(BigInteger.valueOf(1000_000L)).longValue(), - columnInfo, - timeZone); - } - return parseNumber(bi.longValue(), columnInfo, timeZone); - } catch (Exception e) { - throw new ClickHouseUnknownException( - "Error parsing '" + s + "' of data type '" - + columnInfo.getOriginalTypeName() - + "' as " + clazz.getName(), - e); - } - case String: - case Unknown: - try { - return parseOther(s, columnInfo, timeZone); - } catch (Exception e) { - throw new ClickHouseUnknownException( - "Error parsing '" + s + "' as " + clazz.getName(), e); - } - default: - throw new ClickHouseUnknownException( - "Error parsing '" + s + "' of data type '" - + columnInfo.getOriginalTypeName() - + "' as " + clazz.getName(), - null); - } - - } - - abstract T parseDate(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone); - - abstract T parseDateTime(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone); - - abstract T parseNumber(long value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone); - - abstract T parseOther(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone); - - protected final ZoneId effectiveTimeZone(ClickHouseColumnInfo columnInfo, - TimeZone timeZone) { - return timeZone != null - ? timeZone.toZoneId() - : columnInfo.getTimeZone() != null - ? columnInfo.getTimeZone().toZoneId() - : ZoneId.systemDefault(); - } - - protected final LocalDate parseAsLocalDate(String value) { - return LocalDate.parse(value, DATE_FORMATTER); - } - - protected final LocalDateTime parseAsLocalDateTime(String value) { - int index = Objects.requireNonNull(value).indexOf('.'); - if (index > 0) { - int endIndex = -1; - for (int i = index + 1, len = value.length(); i < len; i++) { - char ch = value.charAt(i); - if (!Character.isDigit(ch)) { - endIndex = i; - break; - } - } - String part1 = value.substring(0, index); - if (endIndex > index) { - part1 += value.substring(endIndex); - } - String part2 = endIndex > index ? value.substring(index, endIndex) : value.substring(index); - - LocalDateTime ts = LocalDateTime.parse(part1, DATE_TIME_FORMATTER); - int nanoSeconds = (int) Math.round(Double.parseDouble(part2) * 1000000000); - return LocalDateTime.of(ts.getYear(), ts.getMonth(), ts.getDayOfMonth(), - ts.getHour(), ts.getMinute(), ts.getSecond(), nanoSeconds); - } - - return LocalDateTime.parse(value, DATE_TIME_FORMATTER); - } - - protected final OffsetDateTime parseAsOffsetDateTime(String value) { - return OffsetDateTime.parse(value, DateTimeFormatter.ISO_DATE_TIME); - } - - protected final Instant parseAsInstant(String value) { - try { - long l = Long.parseLong(value); - return parseAsInstant(l); - } catch (NumberFormatException nfe) { - throw new DateTimeParseException("unparsable as long", value, -1, nfe); - } - } - - protected final Instant parseAsInstant(long value) { - return value > Integer.MAX_VALUE - ? Instant.ofEpochMilli(value) - : Instant.ofEpochSecond(value); - } - - protected final LocalTime parseAsLocalTime(String value) { - return LocalTime.parse( - value.length() % 2 == 0 ? value : "0" + value, - TIME_FORMATTER_NUMBERS); - } - - protected final LocalTime parseAsLocalTime(long value) { - return parseAsLocalTime(String.valueOf(value)); - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseDoubleParser.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseDoubleParser.java deleted file mode 100644 index 86c691b5c..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseDoubleParser.java +++ /dev/null @@ -1,58 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.sql.SQLException; -import java.util.TimeZone; - -import ru.yandex.clickhouse.except.ClickHouseUnknownException; -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -final class ClickHouseDoubleParser extends ClickHouseValueParser { - - private static ClickHouseDoubleParser instance; - - static ClickHouseDoubleParser getInstance() { - if (instance == null) { - instance = new ClickHouseDoubleParser(); - } - return instance; - } - - private ClickHouseDoubleParser() { - // prevent instantiation - } - - @Override - public Double parse(ByteFragment value, ClickHouseColumnInfo columnInfo, - TimeZone resultTimeZone) throws SQLException - { - if (value.isNull()) { - return null; - } - if (value.isNaN()) { - return Double.valueOf(Double.NaN); - } - String s = value.asString(); - switch (s) { - case "+inf": - case "inf": - return Double.valueOf(Double.POSITIVE_INFINITY); - case "-inf": - return Double.valueOf(Double.NEGATIVE_INFINITY); - default: - try { - return Double.valueOf(s); - } catch (NumberFormatException nfe) { - throw new ClickHouseUnknownException( - "Error parsing '" + s + "' as Double", - nfe); - } - } - } - - @Override - protected Double getDefaultValue() { - return Double.valueOf(0); - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseFloatParser.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseFloatParser.java deleted file mode 100644 index d8a623f49..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseFloatParser.java +++ /dev/null @@ -1,58 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.sql.SQLException; -import java.util.TimeZone; - -import ru.yandex.clickhouse.except.ClickHouseUnknownException; -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -final class ClickHouseFloatParser extends ClickHouseValueParser { - - private static ClickHouseFloatParser instance; - - static ClickHouseFloatParser getInstance() { - if (instance == null) { - instance = new ClickHouseFloatParser(); - } - return instance; - } - - private ClickHouseFloatParser() { - // prevent instantiation - } - - @Override - public Float parse(ByteFragment value, ClickHouseColumnInfo columnInfo, - TimeZone resultTimeZone) throws SQLException - { - if (value.isNull()) { - return null; - } - if (value.isNaN()) { - return Float.valueOf(Float.NaN); - } - String s = value.asString(); - switch (s) { - case "+inf": - case "inf": - return Float.valueOf(Float.POSITIVE_INFINITY); - case "-inf": - return Float.valueOf(Float.NEGATIVE_INFINITY); - default: - try { - return Float.valueOf(s); - } catch (NumberFormatException nfe) { - throw new ClickHouseUnknownException( - "Error parsing '" + s + "' as Float", - nfe); - } - } - } - - @Override - protected Float getDefaultValue() { - return Float.valueOf(0); - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseInstantParser.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseInstantParser.java deleted file mode 100644 index a770a0c5e..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseInstantParser.java +++ /dev/null @@ -1,74 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.format.DateTimeParseException; -import java.util.TimeZone; - -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -final class ClickHouseInstantParser extends ClickHouseDateValueParser { - - private static ClickHouseInstantParser instance; - - static ClickHouseInstantParser getInstance() { - if (instance == null) { - instance = new ClickHouseInstantParser(); - } - return instance; - } - - private ClickHouseInstantParser() { - super(Instant.class); - } - - @Override - Instant parseDate(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return parseAsLocalDate(value).atStartOfDay().toInstant(ZoneOffset.UTC); - } - - @Override - Instant parseDateTime(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return dateTimeToZonedDateTime(value, columnInfo, timeZone).toInstant(); - } - - @Override - Instant parseNumber(long value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return value > Integer.MAX_VALUE - ? Instant.ofEpochMilli(value) - : Instant.ofEpochSecond(value); - } - - @Override - Instant parseOther(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - try { - return parseAsLocalDate(value) - .atStartOfDay(effectiveTimeZone(columnInfo, timeZone)) - .toInstant(); - } catch (DateTimeParseException dtpe) { - // better luck next time - } - try { - return parseAsLocalDateTime(value) - .atZone(effectiveTimeZone(columnInfo, timeZone)) - .toInstant(); - } catch (DateTimeParseException dtpe) { - // better luck next time - } - try { - return parseAsOffsetDateTime(value) - .toInstant(); - } catch (DateTimeParseException dtpe) { - // better luck next time - } - return parseAsInstant(value); - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseLocalDateParser.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseLocalDateParser.java deleted file mode 100644 index 34d3ad3b3..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseLocalDateParser.java +++ /dev/null @@ -1,64 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.time.Instant; -import java.time.LocalDate; -import java.time.format.DateTimeParseException; -import java.util.TimeZone; - -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -final class ClickHouseLocalDateParser extends ClickHouseDateValueParser { - - private static ClickHouseLocalDateParser instance; - - static ClickHouseLocalDateParser getInstance() { - if (instance == null) { - instance = new ClickHouseLocalDateParser(); - } - return instance; - } - - private ClickHouseLocalDateParser() { - super(LocalDate.class); - } - - @Override - LocalDate parseDate(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return dateToLocalDate(value, columnInfo, timeZone).toLocalDate(); - } - - @Override - LocalDate parseDateTime(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return dateTimeToLocalDateTime(value, columnInfo, timeZone).toLocalDate(); - } - - @Override - LocalDate parseNumber(long value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return parseAsInstant(value).atZone(timeZone.toZoneId()).toLocalDate(); - } - - @Override - LocalDate parseOther(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - try { - return parseAsLocalDate(value); - } catch (DateTimeParseException dtpe) { - // not parseable as date - } - try { - return parseAsLocalDateTime(value).toLocalDate(); - } catch (DateTimeParseException dtpe) { - // not parseable as datetime - } - Instant i = parseAsInstant(value); - return i.atZone(timeZone.toZoneId()).toLocalDate(); - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseLocalDateTimeParser.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseLocalDateTimeParser.java deleted file mode 100644 index 34080f73f..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseLocalDateTimeParser.java +++ /dev/null @@ -1,66 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.format.DateTimeParseException; -import java.util.TimeZone; - -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -final class ClickHouseLocalDateTimeParser extends ClickHouseDateValueParser { - - private static ClickHouseLocalDateTimeParser instance; - - static ClickHouseLocalDateTimeParser getInstance() { - if (instance == null) { - instance = new ClickHouseLocalDateTimeParser(); - } - return instance; - } - - private ClickHouseLocalDateTimeParser() { - super(LocalDateTime.class); - } - - @Override - LocalDateTime parseDate(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return parseAsLocalDate(value).atStartOfDay(); - } - - @Override - LocalDateTime parseDateTime(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return dateTimeToLocalDateTime(value, columnInfo, timeZone); - } - - @Override - LocalDateTime parseNumber(long value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return parseAsInstant(value) - .atZone(timeZone.toZoneId()) - .toLocalDateTime(); - } - - @Override - LocalDateTime parseOther(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - try { - return parseAsLocalDate(value).atStartOfDay(); - } catch (DateTimeParseException dtpe) { - // not parseable as date - } - try { - return parseAsLocalDateTime(value); - } catch (DateTimeParseException dtpe) { - // not parseable as datetime - } - Instant i = parseAsInstant(value); - return i.atZone(timeZone.toZoneId()).toLocalDateTime(); - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseLocalTimeParser.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseLocalTimeParser.java deleted file mode 100644 index 3e9381919..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseLocalTimeParser.java +++ /dev/null @@ -1,63 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.time.LocalTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; -import java.util.TimeZone; - -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -final class ClickHouseLocalTimeParser extends ClickHouseDateValueParser { - - private static ClickHouseLocalTimeParser instance; - - static ClickHouseLocalTimeParser getInstance() { - if (instance == null) { - instance = new ClickHouseLocalTimeParser(); - } - return instance; - } - - private ClickHouseLocalTimeParser() { - super(LocalTime.class); - } - - @Override - LocalTime parseDate(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return LocalTime.MIDNIGHT; - } - - @Override - LocalTime parseDateTime(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return dateTimeToLocalDateTime(value, columnInfo, timeZone).toLocalTime(); - } - - @Override - LocalTime parseNumber(long value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return parseAsLocalTime(value); - } - - @Override - LocalTime parseOther(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - try { - return LocalTime.parse(value, DateTimeFormatter.ISO_LOCAL_TIME); - } catch (DateTimeParseException dtpe) { - // try different pattern - } - try { - return LocalTime.parse(value, DateTimeFormatter.ISO_OFFSET_TIME); - } catch (DateTimeParseException dtpe) { - // try different pattern - } - return parseAsLocalTime(value); - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseMapParser.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseMapParser.java deleted file mode 100644 index c0b7d44e3..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseMapParser.java +++ /dev/null @@ -1,183 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.sql.Array; -import java.sql.SQLException; -import java.util.ArrayDeque; -import java.util.Collections; -import java.util.Deque; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Objects; -import java.util.TimeZone; - -import ru.yandex.clickhouse.domain.ClickHouseDataType; -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -@SuppressWarnings("rawtypes") -final class ClickHouseMapParser extends ClickHouseValueParser { - - private static ClickHouseMapParser instance; - - static ClickHouseMapParser getInstance() { - if (instance == null) { - instance = new ClickHouseMapParser(); - } - return instance; - } - - private ClickHouseMapParser() { - // prevent instantiation - } - - int readPart(ClickHouseDataType type, String str, int startPosition, int len, StringBuilder sb, char stopChar) { - Deque stack = new ArrayDeque<>(); - stack.push('\0'); - char lastChar = '\0'; - for (int i = startPosition; i < len; i++) { - char ch = str.charAt(startPosition = i); - - if (lastChar == '\0') { - if (Character.isWhitespace(ch)) { - continue; - } - - if (ch == stopChar) { - break; - } - - switch (ch) { - case '\'': - if (lastChar != '\0') { - stack.push(lastChar); - } - lastChar = ch; - if (type != ClickHouseDataType.String) { - sb.append(ch); - } - break; - case '{': - if (lastChar != '\0') { - stack.push(lastChar); - } - lastChar = '}'; - sb.append(ch); - break; - case '(': - if (lastChar != '\0') { - stack.push(lastChar); - } - lastChar = ')'; - sb.append(ch); - break; - case '[': - if (lastChar != '\0') { - stack.push(lastChar); - } - lastChar = ']'; - sb.append(ch); - break; - case '}': - return i + 1; - default: - sb.append(ch); - break; - } - } else if (lastChar == '\'') { // quoted - if (ch != '\'' || type != ClickHouseDataType.String) { - sb.append(ch); - } - if (i + 1 < len) { - char nextChar = str.charAt(i + 1); - if (ch == '\\') { - sb.append(nextChar); - i++; - } else if (ch == '\'' && nextChar == ch) { - sb.append(ch).append(nextChar); - i++; - } else if (ch == '\'') { - lastChar = stack.pop(); - } - } - } else if (lastChar == '}' || lastChar == ')' || lastChar == ']') { - if (ch == lastChar) { - lastChar = stack.pop(); - } - sb.append(ch); - } - } - - return startPosition; - } - - @Override - public Map parse(ByteFragment value, ClickHouseColumnInfo columnInfo, TimeZone resultTimeZone) throws SQLException { - if (value.isNull()) { - return null; - } - - ClickHouseColumnInfo keyInfo = Objects.requireNonNull(columnInfo.getKeyInfo()); - ClickHouseColumnInfo valueInfo = Objects.requireNonNull(columnInfo.getValueInfo()); - - ClickHouseValueParser keyParser = ClickHouseValueParser - .getParser(keyInfo.getClickHouseDataType().getJavaClass()); - ClickHouseValueParser valueParser = ClickHouseValueParser - .getParser(valueInfo.getClickHouseDataType().getJavaClass()); - - String str = value.asString(); - int len = str == null ? 0 : str.length(); - if (len < 2) { - return Collections.emptyMap(); - } - - Map map = new LinkedHashMap<>(); - - int part = -1; // -1 - uncertain, 0 - key, 1 - value - StringBuilder sb = new StringBuilder(); - Object k = null; - Object v = null; - for (int i = 0; i < len; i++) { - char ch = str.charAt(i); - - if (Character.isWhitespace(ch)) { // skip whitespaces - continue; - } - - if (part == -1) { - if (ch == '{') { - part = 0; - continue; - } else { - throw new IllegalArgumentException("Invalid map. Expect '{' but we got '" + ch + "' at " + i); - } - } - - if (ch == '}') { - // TODO check if there's any pending characters - break; - } - - if (part == 0) { // reading key(String or Integer) - i = readPart(keyInfo.getClickHouseDataType(), str, i, len, sb, ':'); - k = keyParser.parse(ByteFragment.fromString(sb.toString()), keyInfo, resultTimeZone); - - part = 1; - sb.setLength(0); - } else { // reading value(String, Integer or Array) - i = readPart(valueInfo.getClickHouseDataType(), str, i, len, sb, ','); - v = valueParser.parse(ByteFragment.fromString(sb.toString()), valueInfo, resultTimeZone); - map.put(k, valueInfo.isArray() && v != null ? ((Array) v).getArray() : v); - - part = 0; - sb.setLength(0); - } - } - - return Collections.unmodifiableMap(map); - } - - @Override - protected Map getDefaultValue() { - return Collections.emptyMap(); - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseOffsetDateTimeParser.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseOffsetDateTimeParser.java deleted file mode 100644 index a74b45866..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseOffsetDateTimeParser.java +++ /dev/null @@ -1,69 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.time.OffsetDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; -import java.util.TimeZone; - -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -final class ClickHouseOffsetDateTimeParser extends ClickHouseDateValueParser { - - private static ClickHouseOffsetDateTimeParser instance; - - static ClickHouseOffsetDateTimeParser getInstance() { - if (instance == null) { - instance = new ClickHouseOffsetDateTimeParser(); - } - return instance; - } - - private ClickHouseOffsetDateTimeParser() { - super(OffsetDateTime.class); - } - - @Override - OffsetDateTime parseDate(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return dateToZonedDateTime(value, columnInfo, timeZone).toOffsetDateTime(); - } - - @Override - OffsetDateTime parseDateTime(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return dateTimeToZonedDateTime(value, columnInfo, timeZone).toOffsetDateTime(); - } - - @Override - OffsetDateTime parseNumber(long value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return parseAsInstant(value) - .atZone(effectiveTimeZone(columnInfo, timeZone)) - .toOffsetDateTime(); - } - - @Override - OffsetDateTime parseOther(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - try { - return parseAsLocalDateTime(value) - .atZone(effectiveTimeZone(columnInfo, timeZone)) - .toOffsetDateTime(); - } catch (DateTimeParseException dtpe) { - // try another way - } - try { - return OffsetDateTime.parse(value, DateTimeFormatter.ISO_OFFSET_DATE_TIME); - } catch (DateTimeParseException dtpe) { - // try another way - } - return parseAsInstant(value) - .atZone(effectiveTimeZone(columnInfo, timeZone)) - .toOffsetDateTime(); - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseOffsetTimeParser.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseOffsetTimeParser.java deleted file mode 100644 index 5feb348c1..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseOffsetTimeParser.java +++ /dev/null @@ -1,72 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; -import java.util.TimeZone; - -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -final class ClickHouseOffsetTimeParser extends ClickHouseDateValueParser { - - private static ClickHouseOffsetTimeParser instance; - - static ClickHouseOffsetTimeParser getInstance() { - if (instance == null) { - instance = new ClickHouseOffsetTimeParser(); - } - return instance; - } - - private ClickHouseOffsetTimeParser() { - super(OffsetTime.class); - } - - @Override - OffsetTime parseDate(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return dateToZonedDateTime(value, columnInfo, timeZone).toOffsetDateTime().toOffsetTime(); - } - - @Override - OffsetTime parseDateTime(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return dateTimeToZonedDateTime(value, columnInfo, timeZone).toOffsetDateTime().toOffsetTime(); - } - - @Override - OffsetTime parseNumber(long value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return OffsetTime.of( - parseAsLocalTime(value), - effectiveTimeZone(columnInfo, timeZone).getRules().getOffset(Instant.now())); - } - - @Override - OffsetTime parseOther(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - try { - return OffsetTime.parse(value, DateTimeFormatter.ISO_OFFSET_TIME); - } catch (DateTimeParseException dtpe) { - // try next pattern - } - try { - return OffsetTime.of( - LocalTime.parse(value, DateTimeFormatter.ISO_LOCAL_TIME), - effectiveTimeZone(columnInfo, timeZone).getRules().getOffset(Instant.now())); - } catch (DateTimeParseException dtpe) { - // try next pattern - } - return OffsetTime.of( - parseAsLocalTime(value), - effectiveTimeZone(columnInfo, timeZone).getRules().getOffset(Instant.now())); - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseSQLDateParser.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseSQLDateParser.java deleted file mode 100644 index 77c9732a3..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseSQLDateParser.java +++ /dev/null @@ -1,117 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.sql.Date; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.ZoneId; -import java.time.format.DateTimeParseException; -import java.time.temporal.ChronoUnit; -import java.util.TimeZone; - -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -final class ClickHouseSQLDateParser extends ClickHouseDateValueParser { - - private static ClickHouseSQLDateParser instance; - - static ClickHouseSQLDateParser getInstance() { - if (instance == null) { - instance = new ClickHouseSQLDateParser(); - } - return instance; - } - - private ClickHouseSQLDateParser() { - super(Date.class); - } - - @Override - Date parseDate(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return new Date(dateToZonedDateTime(value, columnInfo, timeZone).truncatedTo(ChronoUnit.DAYS).toInstant().toEpochMilli()); - } - - @Override - Date parseDateTime(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - if (timeZone == null) { - timeZone = TimeZone.getDefault(); - } - return new Date(dateTimeToZonedDateTime(value, columnInfo, timeZone).truncatedTo(ChronoUnit.DAYS).toInstant().toEpochMilli()); - } - - @Override - Date parseNumber(long value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return new Date(parseAsInstant(value) - .atZone(getResultTimeZone(timeZone)) - .truncatedTo(ChronoUnit.DAYS) - .toInstant() - .toEpochMilli()); - } - - @Override - Date parseOther(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - try { - return new Date(parseAsInstant(value) - .atZone(getResultTimeZone(timeZone)) - .truncatedTo(ChronoUnit.DAYS) - .toInstant() - .toEpochMilli()); - } catch (DateTimeParseException dtpe) { - // try next candidate - } - - try { - return new Date(parseAsOffsetDateTime(value) - .toInstant() - .atZone(getResultTimeZone(timeZone)) - .truncatedTo(ChronoUnit.DAYS) - .toInstant() - .toEpochMilli()); - } catch (DateTimeParseException dtpe) { - // try next candidate - } - - try { - return new Date(parseAsLocalDateTime(value) - .atZone(getParsingTimeZone(columnInfo, timeZone)) - .withZoneSameInstant(getResultTimeZone(timeZone)) - .truncatedTo(ChronoUnit.DAYS) - .toInstant() - .toEpochMilli()); - } catch (DateTimeParseException dtpe) { - // try next candidate - } - - return new Date(LocalDateTime - .of( - parseAsLocalDate(value), - LocalTime.MIDNIGHT) - .atZone(getResultTimeZone(timeZone)) - .toInstant() - .toEpochMilli()); - } - - private static ZoneId getParsingTimeZone(ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return columnInfo.getTimeZone() != null - ? columnInfo.getTimeZone().toZoneId() - : timeZone != null - ? timeZone.toZoneId() - : ZoneId.systemDefault(); - } - - private static ZoneId getResultTimeZone(TimeZone timeZone) { - return timeZone != null - ? timeZone.toZoneId() - : ZoneId.systemDefault(); - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseSQLTimeParser.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseSQLTimeParser.java deleted file mode 100644 index 357729fec..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseSQLTimeParser.java +++ /dev/null @@ -1,79 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.sql.Time; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; -import java.util.TimeZone; - -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -final class ClickHouseSQLTimeParser extends ClickHouseDateValueParser

- * If the result would be null, this method will check if there is a default - * value in place which should be returned instead. The default value - * depends on the class. This method is intended to be used when parsing - * numeric values which later need to be converted to primitive, e.g. int or - * float. - * - * @param value - * value as returned from the server or a default value - * @param columnInfo - * meta data of the column - * @param resultTimeZone - * time zone to be used when parsing dates or times - * @return the result of parsing {@code value} as an object of type - * {@code T} - * @throws SQLException - * if the value cannot be parsed under the given circumstances - */ - public T parseWithDefault(ByteFragment value, ClickHouseColumnInfo columnInfo, - TimeZone resultTimeZone) throws SQLException - { - T t = parse(value, columnInfo, resultTimeZone); - return t == null ? getDefaultValue() : t; - } - - protected T getDefaultValue() { - return null; - } - - private static final class ClickHouseValueParserFunctionWrapper - extends ClickHouseValueParser - { - - private final Function f; - private final T nanValue; - private final T defaultValue; - private final Class clazz; - - private ClickHouseValueParserFunctionWrapper(Function f, - T defaultValue, T nanValue, Class clazz) - { - this.f = Objects.requireNonNull(f); - this.nanValue = nanValue; - this.defaultValue = defaultValue; - this.clazz = Objects.requireNonNull(clazz); - } - - @Override - public T parse(ByteFragment value, ClickHouseColumnInfo columnInfo, - TimeZone resultTimeZone) throws SQLException - { - if (value.isNull() || value.isEmpty()) { - return null; - } - if (nanValue != null && value.isNaN()) { - return nanValue; - } - try { - return f.apply(value.asString()); - } catch (Exception e) { - throw new ClickHouseUnknownException( - "Error parsing '" + value.asString() + "' as " + clazz.getName(), - e); - } - } - - @Override - protected T getDefaultValue() { - return defaultValue; - } - - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseZonedDateTimeParser.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseZonedDateTimeParser.java deleted file mode 100644 index 2283427a5..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/response/parser/ClickHouseZonedDateTimeParser.java +++ /dev/null @@ -1,70 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.time.OffsetDateTime; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; -import java.util.TimeZone; - -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -final class ClickHouseZonedDateTimeParser extends ClickHouseDateValueParser { - - private static ClickHouseZonedDateTimeParser instance; - - static ClickHouseZonedDateTimeParser getInstance() { - if (instance == null) { - instance = new ClickHouseZonedDateTimeParser(); - } - return instance; - } - - private ClickHouseZonedDateTimeParser() { - super(ZonedDateTime.class); - } - - @Override - ZonedDateTime parseDate(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return dateToZonedDateTime(value, columnInfo, timeZone); - } - - @Override - ZonedDateTime parseDateTime(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return dateTimeToZonedDateTime(value, columnInfo, timeZone); - } - - @Override - ZonedDateTime parseNumber(long value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - return parseAsInstant(value) - .atZone(effectiveTimeZone(columnInfo, timeZone)); - } - - @Override - ZonedDateTime parseOther(String value, ClickHouseColumnInfo columnInfo, - TimeZone timeZone) - { - try { - return parseAsLocalDateTime(value) - .atZone(effectiveTimeZone(columnInfo, timeZone)); - } catch(DateTimeParseException dtpe) { - // try next candidate - } - - try { - return OffsetDateTime.parse(value, DateTimeFormatter.ISO_OFFSET_DATE_TIME) - .toZonedDateTime(); - } catch (DateTimeParseException dtpe) { - // try another way - } - - return parseAsInstant(value) - .atZone(effectiveTimeZone(columnInfo, timeZone)); - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/settings/ClickHouseConnectionSettings.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/settings/ClickHouseConnectionSettings.java deleted file mode 100644 index 1ecdbd1fb..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/settings/ClickHouseConnectionSettings.java +++ /dev/null @@ -1,103 +0,0 @@ -package ru.yandex.clickhouse.settings; - - -import java.sql.DriverPropertyInfo; -import java.util.Properties; - -public enum ClickHouseConnectionSettings implements DriverPropertyCreator { - - ASYNC("async", false, ""), - BUFFER_SIZE("buffer_size", 65536, ""), - APACHE_BUFFER_SIZE("apache_buffer_size", 65536, ""), - SOCKET_TIMEOUT("socket_timeout", 30000, ""), - CONNECTION_TIMEOUT("connection_timeout", 10 * 1000, "connection timeout in milliseconds"), - SSL("ssl", false, "enable SSL/TLS for the connection"), - SSL_ROOT_CERTIFICATE("sslrootcert", "", "SSL/TLS root certificate"), - SSL_MODE("sslmode", "strict", "verify or not certificate: none (don't verify), strict (verify)"), - USE_PATH_AS_DB("use_path_as_db", true, "whether URL path should be treated as database name"), - PATH("path", "/", "URL path"), - PROTOCOL("protocol", "http", "protocol used to connect to server, http or grpc"), - CHECK_FOR_REDIRECTS("check_for_redirects", false, "whether we should check for 307 redirect using GET before sending POST to given URL"), - MAX_REDIRECTS("max_redirects", 5, "number of redirect checks before using last URL"), - - /* - * - * */ - DATA_TRANSFER_TIMEOUT( "dataTransferTimeout", 10000, "Timeout for data transfer. " - + " socketTimeout + dataTransferTimeout is sent to ClickHouse as max_execution_time. " - + " ClickHouse rejects request execution if its time exceeds max_execution_time"), - - - /** - * for ConnectionManager - */ - VALIDATE_AFTER_INACTIVITY_MILLIS("validateAfterInactivityMillis", 3 * 1000, "period of inactivity in milliseconds after which persistent connections must be re-validated, this check helps detect connections that have become stale (half-closed) while kept inactive in the pool. "), - TIME_TO_LIVE_MILLIS("timeToLiveMillis", 60 * 1000, ""), - DEFAULT_MAX_PER_ROUTE("defaultMaxPerRoute", 500, ""), - MAX_TOTAL("maxTotal", 10000, ""), - MAX_RETRIES("maxRetries", 3, "Maximum retries(default to 3) for idempotent operation. Set 0 to disable retry."), - - /** - * additional - */ - USE_OBJECTS_IN_ARRAYS("use_objects_in_arrays", false, "Whether Object[] should be used instead primitive arrays."), - USE_SHARED_COOKIE_STORE("useSharedCookieStore", false, "Whether to use shared cookie to store among all http clients of db are not"), - MAX_COMPRESS_BUFFER_SIZE("maxCompressBufferSize", 1024*1024, ""), - - USE_SERVER_TIME_ZONE("use_server_time_zone", true, "Whether to use timezone from server. On connection init select timezone() will be executed"), - USE_TIME_ZONE("use_time_zone", "", "Which time zone to use"), - USE_SERVER_TIME_ZONE_FOR_DATES("use_server_time_zone_for_dates", false, - "Whether to use timezone from server on Date parsing in getDate(). " + - "If false, Date returned is a wrapper of a timestamp at start of the day in client timezone. " + - "If true - at start of the day in server or use_timezone timezone."), - CLIENT_NAME("client_name", "", "client_name or http_user_agent show up in system.query_log table, depending on the protocol you're using."), - ; - - private final String key; - private final Object defaultValue; - private final String description; - private final Class clazz; - - ClickHouseConnectionSettings(String key, Object defaultValue, String description) { - this.key = key; - this.defaultValue = defaultValue; - this.clazz = defaultValue.getClass(); - this.description = description; - } - - public String getKey() { - return key; - } - - public Object getDefaultValue() { - return defaultValue; - } - - public Class getClazz() { - return clazz; - } - - public String getDescription() { - return description; - } - - public DriverPropertyInfo createDriverPropertyInfo(Properties properties) { - DriverPropertyInfo propertyInfo = new DriverPropertyInfo(key, driverPropertyValue(properties)); - propertyInfo.required = false; - propertyInfo.description = description; - propertyInfo.choices = driverPropertyInfoChoices(); - return propertyInfo; - } - - private String[] driverPropertyInfoChoices() { - return clazz == Boolean.class || clazz == Boolean.TYPE ? new String[]{"true", "false"} : null; - } - - private String driverPropertyValue(Properties properties) { - String value = properties.getProperty(key); - if (value == null) { - value = defaultValue == null ? null : defaultValue.toString(); - } - return value; - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/settings/ClickHouseProperties.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/settings/ClickHouseProperties.java deleted file mode 100644 index bfdde7672..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/settings/ClickHouseProperties.java +++ /dev/null @@ -1,1065 +0,0 @@ -package ru.yandex.clickhouse.settings; - -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - -import com.clickhouse.client.ClickHouseChecker; -import com.clickhouse.client.ClickHouseProtocol; - -public class ClickHouseProperties { - - // connection settings - private boolean async; - private int bufferSize; - private int apacheBufferSize; - private int socketTimeout; - private int connectionTimeout; - private int dataTransferTimeout; - private int timeToLiveMillis; - private int validateAfterInactivityMillis; - private int defaultMaxPerRoute; - private int maxTotal; - private int maxRetries; - private String host; - private int port; - private ClickHouseProtocol protocol; - private boolean usePathAsDb; - private String path; - private boolean ssl; - private String sslRootCertificate; - private String sslMode; - - /** - * Maximum number of allowed redirects. Active only when {@link ClickHouseProperties#checkForRedirects} - * is true - */ - private int maxRedirects; - - /** - * If set to true, driver will first try to connect to the server using GET request. If the response is 307, - * it will use URI given in the response's Location header instead of the original one. - *

- * Those queries will be repeated until response is anything other than 307, or until - * {@link ClickHouseProperties#maxRedirects maxRedirects} is hit. - *

- * This is a workaround to issues with properly following HTTP POST redirects. - * Namely, Apache HTTP client's inability to process early responses, and difficulties with resending non-repeatable - * {@link org.apache.http.entity.InputStreamEntity InputStreamEntity} - */ - private boolean checkForRedirects; - //additional - private int maxCompressBufferSize; - - private boolean useServerTimeZone; - private String useTimeZone; - private boolean useServerTimeZoneForDates; - private boolean useObjectsInArrays; - // the shared cookie store is scoped to a database - private boolean useSharedCookieStore; - - // queries settings - private Integer maxParallelReplicas; - private Integer maxPartitionsPerInsertBlock; - private String totalsMode; - private String quotaKey; - private Integer priority; - private String database; - private boolean compress; - private boolean decompress; - private boolean extremes; - private Integer maxThreads; - private Integer maxExecutionTime; - private Integer maxBlockSize; - private Integer maxRowsToGroupBy; - private String profile; - private String user; - private String password; - private String httpAuthorization; - private boolean distributedAggregationMemoryEfficient; - private Long maxBytesBeforeExternalGroupBy; - private Long maxBytesBeforeExternalSort; - private Long maxMemoryUsage; - private Long maxMemoryUsageForUser; - private Long maxMemoryUsageForAllQueries; - private Long preferredBlockSizeBytes; - private Long maxQuerySize; - private Long maxAstElements; - private boolean sessionCheck; - private String sessionId; - private Long sessionTimeout; - private Long insertQuorum; - private Long insertQuorumTimeout; - private Long selectSequentialConsistency; - private Boolean enableOptimizePredicateExpression; - private Long maxInsertBlockSize; - private Boolean insertDeduplicate; - private Boolean insertDistributedSync; - private Boolean anyJoinDistinctRightTableKeys; - private Boolean sendProgressInHttpHeaders; - private Boolean waitEndOfQuery; - private String clientName; - - public ClickHouseProperties() { - this(new Properties()); - } - - public ClickHouseProperties(Properties info) { - // need casts for java 6 - this.async = (Boolean)getSetting(info, ClickHouseConnectionSettings.ASYNC); - this.bufferSize = (Integer)getSetting(info, ClickHouseConnectionSettings.BUFFER_SIZE); - this.apacheBufferSize = (Integer)getSetting(info, ClickHouseConnectionSettings.APACHE_BUFFER_SIZE); - this.socketTimeout = (Integer)getSetting(info, ClickHouseConnectionSettings.SOCKET_TIMEOUT); - this.connectionTimeout = (Integer)getSetting(info, ClickHouseConnectionSettings.CONNECTION_TIMEOUT); - this.dataTransferTimeout = (Integer)getSetting(info, ClickHouseConnectionSettings.DATA_TRANSFER_TIMEOUT); - this.timeToLiveMillis = (Integer)getSetting(info, ClickHouseConnectionSettings.TIME_TO_LIVE_MILLIS); - this.validateAfterInactivityMillis = (Integer)getSetting(info, ClickHouseConnectionSettings.VALIDATE_AFTER_INACTIVITY_MILLIS); - this.defaultMaxPerRoute = (Integer)getSetting(info, ClickHouseConnectionSettings.DEFAULT_MAX_PER_ROUTE); - this.maxTotal = (Integer)getSetting(info, ClickHouseConnectionSettings.MAX_TOTAL); - this.maxRetries = (Integer)getSetting(info, ClickHouseConnectionSettings.MAX_RETRIES); - this.maxCompressBufferSize = (Integer) getSetting(info, ClickHouseConnectionSettings.MAX_COMPRESS_BUFFER_SIZE); - this.ssl = (Boolean) getSetting(info, ClickHouseConnectionSettings.SSL); - this.sslRootCertificate = (String) getSetting(info, ClickHouseConnectionSettings.SSL_ROOT_CERTIFICATE); - this.sslMode = (String) getSetting(info, ClickHouseConnectionSettings.SSL_MODE); - this.usePathAsDb = (Boolean) getSetting(info, ClickHouseConnectionSettings.USE_PATH_AS_DB); - this.path = (String) getSetting(info, ClickHouseConnectionSettings.PATH); - this.protocol = ClickHouseProtocol.valueOf(((String) getSetting(info, ClickHouseConnectionSettings.PROTOCOL)).toUpperCase()); - this.maxRedirects = (Integer) getSetting(info, ClickHouseConnectionSettings.MAX_REDIRECTS); - this.checkForRedirects = (Boolean) getSetting(info, ClickHouseConnectionSettings.CHECK_FOR_REDIRECTS); - this.useServerTimeZone = (Boolean)getSetting(info, ClickHouseConnectionSettings.USE_SERVER_TIME_ZONE); - this.useTimeZone = (String)getSetting(info, ClickHouseConnectionSettings.USE_TIME_ZONE); - this.useServerTimeZoneForDates = (Boolean)getSetting(info, ClickHouseConnectionSettings.USE_SERVER_TIME_ZONE_FOR_DATES); - this.useObjectsInArrays = (Boolean)getSetting(info, ClickHouseConnectionSettings.USE_OBJECTS_IN_ARRAYS); - this.useSharedCookieStore = (Boolean)getSetting(info, ClickHouseConnectionSettings.USE_SHARED_COOKIE_STORE); - this.clientName = (String)getSetting(info, ClickHouseConnectionSettings.CLIENT_NAME); - - this.maxParallelReplicas = getSetting(info, ClickHouseQueryParam.MAX_PARALLEL_REPLICAS); - this.maxPartitionsPerInsertBlock = getSetting(info, ClickHouseQueryParam.MAX_PARTITIONS_PER_INSERT_BLOCK); - this.totalsMode = getSetting(info, ClickHouseQueryParam.TOTALS_MODE); - this.quotaKey = getSetting(info, ClickHouseQueryParam.QUOTA_KEY); - this.priority = getSetting(info, ClickHouseQueryParam.PRIORITY); - this.database = getSetting(info, ClickHouseQueryParam.DATABASE); - this.protocol = ClickHouseProtocol.valueOf(((String)getSetting(info, ClickHouseConnectionSettings.PROTOCOL)).toUpperCase()); - this.compress = (Boolean)getSetting(info, ClickHouseQueryParam.COMPRESS); - this.decompress = (Boolean)getSetting(info, ClickHouseQueryParam.DECOMPRESS); - this.extremes = (Boolean)getSetting(info, ClickHouseQueryParam.EXTREMES); - this.maxThreads = getSetting(info, ClickHouseQueryParam.MAX_THREADS); - this.maxExecutionTime = getSetting(info, ClickHouseQueryParam.MAX_EXECUTION_TIME); - this.maxBlockSize = getSetting(info, ClickHouseQueryParam.MAX_BLOCK_SIZE); - this.maxRowsToGroupBy = getSetting(info, ClickHouseQueryParam.MAX_ROWS_TO_GROUP_BY); - this.profile = getSetting(info, ClickHouseQueryParam.PROFILE); - this.user = getSetting(info, ClickHouseQueryParam.USER); - this.password = getSetting(info, ClickHouseQueryParam.PASSWORD); - this.httpAuthorization = getSetting(info, ClickHouseQueryParam.AUTHORIZATION); - this.distributedAggregationMemoryEfficient = (Boolean)getSetting(info, ClickHouseQueryParam.DISTRIBUTED_AGGREGATION_MEMORY_EFFICIENT); - this.maxBytesBeforeExternalGroupBy = (Long)getSetting(info, ClickHouseQueryParam.MAX_BYTES_BEFORE_EXTERNAL_GROUP_BY); - this.maxBytesBeforeExternalSort = (Long)getSetting(info, ClickHouseQueryParam.MAX_BYTES_BEFORE_EXTERNAL_SORT); - this.maxMemoryUsage = getSetting(info, ClickHouseQueryParam.MAX_MEMORY_USAGE); - this.maxMemoryUsageForUser = getSetting(info, ClickHouseQueryParam.MAX_MEMORY_USAGE_FOR_USER); - this.maxMemoryUsageForAllQueries = getSetting(info, ClickHouseQueryParam.MAX_MEMORY_USAGE_FOR_ALL_QUERIES); - this.preferredBlockSizeBytes = getSetting(info, ClickHouseQueryParam.PREFERRED_BLOCK_SIZE_BYTES); - this.maxQuerySize = getSetting(info, ClickHouseQueryParam.MAX_QUERY_SIZE); - this.maxAstElements = getSetting(info, ClickHouseQueryParam.MAX_AST_ELEMENTS); - this.sessionCheck = (Boolean) getSetting(info, ClickHouseQueryParam.SESSION_CHECK); - this.sessionId = getSetting(info, ClickHouseQueryParam.SESSION_ID); - this.sessionTimeout = getSetting(info, ClickHouseQueryParam.SESSION_TIMEOUT); - this.insertQuorum = (Long)getSetting(info, ClickHouseQueryParam.INSERT_QUORUM); - this.insertQuorumTimeout = (Long)getSetting(info, ClickHouseQueryParam.INSERT_QUORUM_TIMEOUT); - this.selectSequentialConsistency = (Long)getSetting(info, ClickHouseQueryParam.SELECT_SEQUENTIAL_CONSISTENCY); - this.enableOptimizePredicateExpression = getSetting(info, ClickHouseQueryParam.ENABLE_OPTIMIZE_PREDICATE_EXPRESSION); - this.maxInsertBlockSize = getSetting(info, ClickHouseQueryParam.MAX_INSERT_BLOCK_SIZE); - this.insertDeduplicate = getSetting(info, ClickHouseQueryParam.INSERT_DEDUPLICATE); - this.insertDistributedSync = getSetting(info, ClickHouseQueryParam.INSERT_DISTRIBUTED_SYNC); - this.anyJoinDistinctRightTableKeys = getSetting(info, ClickHouseQueryParam.ANY_JOIN_DISTINCT_RIGHT_TABLE_KEYS); - this.sendProgressInHttpHeaders = (Boolean)getSetting(info, ClickHouseQueryParam.SEND_PROGRESS_IN_HTTP_HEADERS); - this.waitEndOfQuery = (Boolean)getSetting(info, ClickHouseQueryParam.WAIT_END_OF_QUERY); - } - - public Properties asProperties() { - PropertiesBuilder ret = new PropertiesBuilder(); - ret.put(ClickHouseConnectionSettings.ASYNC.getKey(), String.valueOf(async)); - ret.put(ClickHouseConnectionSettings.BUFFER_SIZE.getKey(), String.valueOf(bufferSize)); - ret.put(ClickHouseConnectionSettings.APACHE_BUFFER_SIZE.getKey(), String.valueOf(apacheBufferSize)); - ret.put(ClickHouseConnectionSettings.SOCKET_TIMEOUT.getKey(), String.valueOf(socketTimeout)); - ret.put(ClickHouseConnectionSettings.CONNECTION_TIMEOUT.getKey(), String.valueOf(connectionTimeout)); - ret.put(ClickHouseConnectionSettings.DATA_TRANSFER_TIMEOUT.getKey(), String.valueOf(dataTransferTimeout)); - ret.put(ClickHouseConnectionSettings.TIME_TO_LIVE_MILLIS.getKey(), String.valueOf(timeToLiveMillis)); - ret.put(ClickHouseConnectionSettings.VALIDATE_AFTER_INACTIVITY_MILLIS.getKey(), String.valueOf(validateAfterInactivityMillis)); - ret.put(ClickHouseConnectionSettings.DEFAULT_MAX_PER_ROUTE.getKey(), String.valueOf(defaultMaxPerRoute)); - ret.put(ClickHouseConnectionSettings.MAX_TOTAL.getKey(), String.valueOf(maxTotal)); - ret.put(ClickHouseConnectionSettings.MAX_RETRIES.getKey(), String.valueOf(maxRetries)); - ret.put(ClickHouseConnectionSettings.MAX_COMPRESS_BUFFER_SIZE.getKey(), String.valueOf(maxCompressBufferSize)); - ret.put(ClickHouseConnectionSettings.SSL.getKey(), String.valueOf(ssl)); - ret.put(ClickHouseConnectionSettings.SSL_ROOT_CERTIFICATE.getKey(), String.valueOf(sslRootCertificate)); - ret.put(ClickHouseConnectionSettings.SSL_MODE.getKey(), String.valueOf(sslMode)); - ret.put(ClickHouseConnectionSettings.USE_PATH_AS_DB.getKey(), String.valueOf(usePathAsDb)); - ret.put(ClickHouseConnectionSettings.PATH.getKey(), String.valueOf(path)); - ret.put(ClickHouseConnectionSettings.PROTOCOL.getKey(), String.valueOf(protocol.name().toLowerCase())); - ret.put(ClickHouseConnectionSettings.MAX_REDIRECTS.getKey(), String.valueOf(maxRedirects)); - ret.put(ClickHouseConnectionSettings.CHECK_FOR_REDIRECTS.getKey(), String.valueOf(checkForRedirects)); - ret.put(ClickHouseConnectionSettings.USE_SERVER_TIME_ZONE.getKey(), String.valueOf(useServerTimeZone)); - ret.put(ClickHouseConnectionSettings.USE_TIME_ZONE.getKey(), String.valueOf(useTimeZone)); - ret.put(ClickHouseConnectionSettings.USE_SERVER_TIME_ZONE_FOR_DATES.getKey(), String.valueOf(useServerTimeZoneForDates)); - ret.put(ClickHouseConnectionSettings.USE_OBJECTS_IN_ARRAYS.getKey(), String.valueOf(useObjectsInArrays)); - ret.put(ClickHouseConnectionSettings.USE_SHARED_COOKIE_STORE.getKey(), String.valueOf(useSharedCookieStore)); - ret.put(ClickHouseConnectionSettings.CLIENT_NAME.getKey(), String.valueOf(clientName)); - - ret.put(ClickHouseQueryParam.MAX_PARALLEL_REPLICAS.getKey(), maxParallelReplicas); - ret.put(ClickHouseQueryParam.MAX_PARTITIONS_PER_INSERT_BLOCK.getKey(), maxPartitionsPerInsertBlock); - ret.put(ClickHouseQueryParam.TOTALS_MODE.getKey(), totalsMode); - ret.put(ClickHouseQueryParam.QUOTA_KEY.getKey(), quotaKey); - ret.put(ClickHouseQueryParam.PRIORITY.getKey(), priority); - ret.put(ClickHouseQueryParam.DATABASE.getKey(), database); - ret.put(ClickHouseQueryParam.COMPRESS.getKey(), String.valueOf(compress)); - ret.put(ClickHouseQueryParam.DECOMPRESS.getKey(), String.valueOf(decompress)); - ret.put(ClickHouseQueryParam.EXTREMES.getKey(), String.valueOf(extremes)); - ret.put(ClickHouseQueryParam.MAX_THREADS.getKey(), maxThreads); - ret.put(ClickHouseQueryParam.MAX_EXECUTION_TIME.getKey(), maxExecutionTime); - ret.put(ClickHouseQueryParam.MAX_BLOCK_SIZE.getKey(), maxBlockSize); - ret.put(ClickHouseQueryParam.MAX_ROWS_TO_GROUP_BY.getKey(), maxRowsToGroupBy); - ret.put(ClickHouseQueryParam.PROFILE.getKey(), profile); - ret.put(ClickHouseQueryParam.USER.getKey(), user); - ret.put(ClickHouseQueryParam.PASSWORD.getKey(), password); - ret.put(ClickHouseQueryParam.AUTHORIZATION.getKey(), httpAuthorization); - ret.put(ClickHouseQueryParam.DISTRIBUTED_AGGREGATION_MEMORY_EFFICIENT.getKey(), String.valueOf(distributedAggregationMemoryEfficient)); - ret.put(ClickHouseQueryParam.MAX_BYTES_BEFORE_EXTERNAL_GROUP_BY.getKey(), maxBytesBeforeExternalGroupBy); - ret.put(ClickHouseQueryParam.MAX_BYTES_BEFORE_EXTERNAL_SORT.getKey(), maxBytesBeforeExternalSort); - ret.put(ClickHouseQueryParam.MAX_MEMORY_USAGE.getKey(), maxMemoryUsage); - ret.put(ClickHouseQueryParam.MAX_MEMORY_USAGE_FOR_USER.getKey(), maxMemoryUsageForUser); - ret.put(ClickHouseQueryParam.MAX_MEMORY_USAGE_FOR_ALL_QUERIES.getKey(), maxMemoryUsageForAllQueries); - ret.put(ClickHouseQueryParam.PREFERRED_BLOCK_SIZE_BYTES.getKey(), preferredBlockSizeBytes); - ret.put(ClickHouseQueryParam.MAX_QUERY_SIZE.getKey(), maxQuerySize); - ret.put(ClickHouseQueryParam.MAX_AST_ELEMENTS.getKey(), maxAstElements); - ret.put(ClickHouseQueryParam.SESSION_CHECK.getKey(), String.valueOf(sessionCheck)); - ret.put(ClickHouseQueryParam.SESSION_ID.getKey(), sessionId); - ret.put(ClickHouseQueryParam.SESSION_TIMEOUT.getKey(), sessionTimeout); - ret.put(ClickHouseQueryParam.INSERT_QUORUM.getKey(), insertQuorum); - ret.put(ClickHouseQueryParam.INSERT_QUORUM_TIMEOUT.getKey(), insertQuorumTimeout); - ret.put(ClickHouseQueryParam.SELECT_SEQUENTIAL_CONSISTENCY.getKey(), selectSequentialConsistency); - ret.put(ClickHouseQueryParam.ENABLE_OPTIMIZE_PREDICATE_EXPRESSION.getKey(), enableOptimizePredicateExpression); - ret.put(ClickHouseQueryParam.MAX_INSERT_BLOCK_SIZE.getKey(), maxInsertBlockSize); - ret.put(ClickHouseQueryParam.INSERT_DEDUPLICATE.getKey(), insertDeduplicate); - ret.put(ClickHouseQueryParam.INSERT_DISTRIBUTED_SYNC.getKey(), insertDistributedSync); - ret.put(ClickHouseQueryParam.ANY_JOIN_DISTINCT_RIGHT_TABLE_KEYS.getKey(), anyJoinDistinctRightTableKeys); - ret.put(ClickHouseQueryParam.SEND_PROGRESS_IN_HTTP_HEADERS.getKey(), sendProgressInHttpHeaders); - ret.put(ClickHouseQueryParam.WAIT_END_OF_QUERY.getKey(), waitEndOfQuery); - - return ret.getProperties(); - } - - public ClickHouseProperties(ClickHouseProperties properties) { - setHost(properties.host); - setPort(properties.port); - setAsync(properties.async); - setBufferSize(properties.bufferSize); - setApacheBufferSize(properties.apacheBufferSize); - setSocketTimeout(properties.socketTimeout); - setConnectionTimeout(properties.connectionTimeout); - setDataTransferTimeout(properties.dataTransferTimeout); - setTimeToLiveMillis(properties.timeToLiveMillis); - setValidateAfterInactivityMillis(properties.validateAfterInactivityMillis); - setDefaultMaxPerRoute(properties.defaultMaxPerRoute); - setMaxTotal(properties.maxTotal); - setMaxRetries(properties.maxRetries); - setMaxCompressBufferSize(properties.maxCompressBufferSize); - setSsl(properties.ssl); - setSslRootCertificate(properties.sslRootCertificate); - setSslMode(properties.sslMode); - setUsePathAsDb(properties.usePathAsDb); - setPath(properties.path); - setProtocol(properties.protocol); - setMaxRedirects(properties.maxRedirects); - setCheckForRedirects(properties.checkForRedirects); - setUseServerTimeZone(properties.useServerTimeZone); - setUseTimeZone(properties.useTimeZone); - setUseServerTimeZoneForDates(properties.useServerTimeZoneForDates); - setUseObjectsInArrays(properties.useObjectsInArrays); - setUseSharedCookieStore(properties.useSharedCookieStore); - setClientName(properties.clientName); - setMaxParallelReplicas(properties.maxParallelReplicas); - setMaxPartitionsPerInsertBlock(properties.maxPartitionsPerInsertBlock); - setTotalsMode(properties.totalsMode); - setQuotaKey(properties.quotaKey); - setPriority(properties.priority); - setDatabase(properties.database); - setCompress(properties.compress); - setDecompress(properties.decompress); - setExtremes(properties.extremes); - setMaxThreads(properties.maxThreads); - setMaxExecutionTime(properties.maxExecutionTime); - setMaxBlockSize(properties.maxBlockSize); - setMaxRowsToGroupBy(properties.maxRowsToGroupBy); - setProfile(properties.profile); - setUser(properties.user); - setPassword(properties.password); - setHttpAuthorization(properties.httpAuthorization); - setDistributedAggregationMemoryEfficient(properties.distributedAggregationMemoryEfficient); - setMaxBytesBeforeExternalGroupBy(properties.maxBytesBeforeExternalGroupBy); - setMaxBytesBeforeExternalSort(properties.maxBytesBeforeExternalSort); - setMaxMemoryUsage(properties.maxMemoryUsage); - setMaxMemoryUsageForUser(properties.maxMemoryUsageForUser); - setMaxMemoryUsageForAllQueries(properties.maxMemoryUsageForAllQueries); - setSessionCheck(properties.sessionCheck); - setSessionId(properties.sessionId); - setSessionTimeout(properties.sessionTimeout); - setInsertQuorum(properties.insertQuorum); - setInsertQuorumTimeout(properties.insertQuorumTimeout); - setSelectSequentialConsistency(properties.selectSequentialConsistency); - setPreferredBlockSizeBytes(properties.preferredBlockSizeBytes); - setMaxQuerySize(properties.maxQuerySize); - setMaxAstElements(properties.maxAstElements); - setEnableOptimizePredicateExpression(properties.enableOptimizePredicateExpression); - setMaxInsertBlockSize(properties.maxInsertBlockSize); - setInsertDeduplicate(properties.insertDeduplicate); - setInsertDistributedSync(properties.insertDistributedSync); - setAnyJoinDistinctRightTableKeys(properties.anyJoinDistinctRightTableKeys); - setSendProgressInHttpHeaders(properties.sendProgressInHttpHeaders); - setWaitEndOfQuery(properties.waitEndOfQuery); - } - - public Map buildQueryParams(boolean ignoreDatabase){ - Map params = new HashMap<>(); - - if (maxParallelReplicas != null) { - params.put(ClickHouseQueryParam.MAX_PARALLEL_REPLICAS, String.valueOf(maxParallelReplicas)); - } - if (maxPartitionsPerInsertBlock != null) { - params.put(ClickHouseQueryParam.MAX_PARTITIONS_PER_INSERT_BLOCK, String.valueOf(maxPartitionsPerInsertBlock)); - } - if (maxRowsToGroupBy != null) { - params.put(ClickHouseQueryParam.MAX_ROWS_TO_GROUP_BY, String.valueOf(maxRowsToGroupBy)); - } - if (totalsMode != null) { - params.put(ClickHouseQueryParam.TOTALS_MODE, totalsMode); - } - if (quotaKey != null) { - params.put(ClickHouseQueryParam.QUOTA_KEY, quotaKey); - } - if (priority != null) { - params.put(ClickHouseQueryParam.PRIORITY, String.valueOf(priority)); - } - - if (!ClickHouseChecker.isNullOrBlank(database) && !ignoreDatabase) { - params.put(ClickHouseQueryParam.DATABASE, getDatabase()); - } - - if (compress) { - params.put(ClickHouseQueryParam.COMPRESS, "1"); - } - if (decompress) { - params.put(ClickHouseQueryParam.DECOMPRESS, "1"); - } - - - if (extremes) { - params.put(ClickHouseQueryParam.EXTREMES, "1"); - } - - if (ClickHouseChecker.isNullOrBlank(profile)) { - if (getMaxThreads() != null) { - params.put(ClickHouseQueryParam.MAX_THREADS, String.valueOf(maxThreads)); - } - - // in seconds there - if (getMaxExecutionTime() != null) { - params.put(ClickHouseQueryParam.MAX_EXECUTION_TIME, String.valueOf((maxExecutionTime))); - } - - if (getMaxBlockSize() != null) { - params.put(ClickHouseQueryParam.MAX_BLOCK_SIZE, String.valueOf(getMaxBlockSize())); - } - } else { - params.put(ClickHouseQueryParam.PROFILE, profile); - } - - if (distributedAggregationMemoryEfficient) { - params.put(ClickHouseQueryParam.DISTRIBUTED_AGGREGATION_MEMORY_EFFICIENT, "1"); - } - - if (maxBytesBeforeExternalGroupBy != null) { - params.put(ClickHouseQueryParam.MAX_BYTES_BEFORE_EXTERNAL_GROUP_BY, String.valueOf(maxBytesBeforeExternalGroupBy)); - } - if (maxBytesBeforeExternalSort != null) { - params.put(ClickHouseQueryParam.MAX_BYTES_BEFORE_EXTERNAL_SORT, String.valueOf(maxBytesBeforeExternalSort)); - } - if (maxMemoryUsage != null) { - params.put(ClickHouseQueryParam.MAX_MEMORY_USAGE, String.valueOf(maxMemoryUsage)); - } - if (maxMemoryUsageForUser != null) { - params.put(ClickHouseQueryParam.MAX_MEMORY_USAGE_FOR_USER, String.valueOf(maxMemoryUsageForUser)); - } - if (maxMemoryUsageForAllQueries != null) { - params.put(ClickHouseQueryParam.MAX_MEMORY_USAGE_FOR_ALL_QUERIES, String.valueOf(maxMemoryUsageForAllQueries)); - } - if (preferredBlockSizeBytes != null) { - params.put(ClickHouseQueryParam.PREFERRED_BLOCK_SIZE_BYTES, String.valueOf(preferredBlockSizeBytes)); - } - if (maxQuerySize != null) { - params.put(ClickHouseQueryParam.MAX_QUERY_SIZE, String.valueOf(maxQuerySize)); - } - if (maxAstElements != null) { - params.put(ClickHouseQueryParam.MAX_AST_ELEMENTS, String.valueOf(maxAstElements)); - } - - if (sessionCheck) { - params.put(ClickHouseQueryParam.SESSION_CHECK, "1"); - } - - if (sessionId != null) { - params.put(ClickHouseQueryParam.SESSION_ID, String.valueOf(sessionId)); - } - - if (sessionTimeout != null) { - params.put(ClickHouseQueryParam.SESSION_TIMEOUT, String.valueOf(sessionTimeout)); - } - - addQueryParam(insertQuorum, ClickHouseQueryParam.INSERT_QUORUM, params); - addQueryParam(insertQuorumTimeout, ClickHouseQueryParam.INSERT_QUORUM_TIMEOUT, params); - addQueryParam(selectSequentialConsistency, ClickHouseQueryParam.SELECT_SEQUENTIAL_CONSISTENCY, params); - addQueryParam(maxInsertBlockSize, ClickHouseQueryParam.MAX_INSERT_BLOCK_SIZE, params); - addQueryParam(insertDeduplicate, ClickHouseQueryParam.INSERT_DEDUPLICATE, params); - addQueryParam(insertDistributedSync, ClickHouseQueryParam.INSERT_DISTRIBUTED_SYNC, params); - addQueryParam(anyJoinDistinctRightTableKeys, ClickHouseQueryParam.ANY_JOIN_DISTINCT_RIGHT_TABLE_KEYS, params); - - if (enableOptimizePredicateExpression != null) { - params.put(ClickHouseQueryParam.ENABLE_OPTIMIZE_PREDICATE_EXPRESSION, enableOptimizePredicateExpression ? "1" : "0"); - } - - addQueryParam(sendProgressInHttpHeaders, ClickHouseQueryParam.SEND_PROGRESS_IN_HTTP_HEADERS, params); - addQueryParam(waitEndOfQuery, ClickHouseQueryParam.WAIT_END_OF_QUERY, params); - - return params; - } - - private void addQueryParam(Object param, ClickHouseQueryParam definition, Map params) { - if (param != null) { - if (definition.getClazz() == Boolean.class || definition.getClazz() == boolean.class) { - params.put(definition, ((Boolean) param) ? "1" : "0"); - } else { - params.put(definition, String.valueOf(param)); - } - } - } - - public ClickHouseProperties withCredentials(String user, String password){ - ClickHouseProperties copy = new ClickHouseProperties(this); - copy.setUser(user); - copy.setPassword(password); - return copy; - } - - - private T getSetting(Properties info, ClickHouseQueryParam param){ - return getSetting(info, param.getKey(), param.getDefaultValue(), param.getClazz()); - } - - private T getSetting(Properties info, ClickHouseConnectionSettings settings){ - return getSetting(info, settings.getKey(), settings.getDefaultValue(), settings.getClazz()); - } - - @SuppressWarnings("unchecked") - private T getSetting(Properties info, String key, Object defaultValue, Class clazz){ - String val = info.getProperty(key); - if (val == null) { - return (T)defaultValue; - } - if (clazz == int.class || clazz == Integer.class) { - return (T) clazz.cast(Integer.valueOf(val)); - } - if (clazz == long.class || clazz == Long.class) { - return (T) clazz.cast(Long.valueOf(val)); - } - if (clazz == boolean.class || clazz == Boolean.class) { - final Boolean boolValue; - if ("1".equals(val) || "0".equals(val)) { - boolValue = "1".equals(val); - } else { - boolValue = Boolean.valueOf(val); - } - return (T) clazz.cast(boolValue); - } - return (T) clazz.cast(val); - } - - - public String getProfile() { - return profile; - } - - public void setProfile(String profile) { - this.profile = profile; - } - - public boolean isCompress() { - return compress; - } - - public void setCompress(boolean compress) { - this.compress = compress; - } - - public boolean isDecompress() { - return decompress; - } - - public void setDecompress(boolean decompress) { - this.decompress = decompress; - } - - public boolean isAsync() { - return async; - } - - public void setAsync(boolean async) { - this.async = async; - } - - public Integer getMaxThreads() { - return maxThreads; - } - - public void setMaxThreads(Integer maxThreads) { - this.maxThreads = maxThreads; - } - - public Integer getMaxBlockSize() { - return maxBlockSize; - } - - public void setMaxBlockSize(Integer maxBlockSize) { - this.maxBlockSize = maxBlockSize; - } - - public int getBufferSize() { - return bufferSize; - } - - public void setBufferSize(int bufferSize) { - this.bufferSize = bufferSize; - } - - public int getApacheBufferSize() { - return apacheBufferSize; - } - - public void setApacheBufferSize(int apacheBufferSize) { - this.apacheBufferSize = apacheBufferSize; - } - - public int getSocketTimeout() { - return socketTimeout; - } - - public void setSocketTimeout(int socketTimeout) { - this.socketTimeout = socketTimeout; - } - - public int getConnectionTimeout() { - return connectionTimeout; - } - - public void setConnectionTimeout(int connectionTimeout) { - this.connectionTimeout = connectionTimeout; - } - - public int getDataTransferTimeout() { - return dataTransferTimeout; - } - - public void setDataTransferTimeout(int dataTransferTimeout) { - this.dataTransferTimeout = dataTransferTimeout; - } - - public String getUser() { - return user; - } - - public void setUser(String user) { - this.user = user; - } - - public int getTimeToLiveMillis() { - return timeToLiveMillis; - } - - public void setTimeToLiveMillis(int timeToLiveMillis) { - this.timeToLiveMillis = timeToLiveMillis; - } - - public int getValidateAfterInactivityMillis() { - return validateAfterInactivityMillis; - } - - public void setValidateAfterInactivityMillis(int validateAfterInactivityMillis) { - this.validateAfterInactivityMillis = validateAfterInactivityMillis; - } - - public int getDefaultMaxPerRoute() { - return defaultMaxPerRoute; - } - - public void setDefaultMaxPerRoute(int defaultMaxPerRoute) { - this.defaultMaxPerRoute = defaultMaxPerRoute; - } - - public int getMaxTotal() { - return maxTotal; - } - - public void setMaxTotal(int maxTotal) { - this.maxTotal = maxTotal; - } - - public int getMaxRetries() { - return maxRetries; - } - - public void setMaxRetries(int maxRetries) { - this.maxRetries = maxRetries; - } - - public int getMaxCompressBufferSize() { - return maxCompressBufferSize; - } - - public void setMaxCompressBufferSize(int maxCompressBufferSize) { - this.maxCompressBufferSize = maxCompressBufferSize; - } - - public boolean getSsl() { - return ssl; - } - - public void setSsl(boolean ssl) { - this.ssl = ssl; - } - - public String getSslRootCertificate() { - return sslRootCertificate; - } - - public void setSslRootCertificate(String sslRootCertificate) { - this.sslRootCertificate = sslRootCertificate; - } - - public String getSslMode() { - return sslMode; - } - - public void setSslMode(String sslMode) { - this.sslMode = sslMode; - } - - public int getMaxRedirects() { - return maxRedirects; - } - - public void setMaxRedirects(int maxRedirects) { - this.maxRedirects = maxRedirects; - } - - public boolean isCheckForRedirects() { - return checkForRedirects; - } - - public void setCheckForRedirects(boolean checkForRedirects) { - this.checkForRedirects = checkForRedirects; - } - public boolean isUseServerTimeZone() { - return useServerTimeZone; - } - - public void setUseServerTimeZone(boolean useServerTimeZone) { - this.useServerTimeZone = useServerTimeZone; - } - - public String getUseTimeZone() { - return useTimeZone; - } - - public void setUseTimeZone(String useTimeZone) { - this.useTimeZone = useTimeZone; - } - - public boolean isUseObjectsInArrays() { - return useObjectsInArrays; - } - - public void setUseObjectsInArrays(boolean useObjectsInArrays) { - this.useObjectsInArrays = useObjectsInArrays; - } - - public boolean isUseSharedCookieStore() { - return useSharedCookieStore; - } - - public void setUseSharedCookieStore(boolean useSharedCookieStore) { - this.useSharedCookieStore = useSharedCookieStore; - } - - public String getClientName() { - return this.clientName; - } - - public void setClientName(String clientName) { - this.clientName = clientName; - } - - public boolean isUseServerTimeZoneForDates() { - return useServerTimeZoneForDates; - } - - public void setUseServerTimeZoneForDates(boolean useServerTimeZoneForDates) { - this.useServerTimeZoneForDates = useServerTimeZoneForDates; - } - - public Integer getMaxParallelReplicas() { - return maxParallelReplicas; - } - - public void setMaxParallelReplicas(Integer maxParallelReplicas) { - this.maxParallelReplicas = maxParallelReplicas; - } - - public Integer getMaxPartitionsPerInsertBlock() { - return maxPartitionsPerInsertBlock; - } - - public void setMaxPartitionsPerInsertBlock(Integer maxPartitionsPerInsertBlock) { - this.maxPartitionsPerInsertBlock = maxPartitionsPerInsertBlock; - } - - public String getTotalsMode() { - return totalsMode; - } - - public void setTotalsMode(String totalsMode) { - this.totalsMode = totalsMode; - } - - public String getQuotaKey() { - return quotaKey; - } - - public void setQuotaKey(String quotaKey) { - this.quotaKey = quotaKey; - } - - public Integer getPriority() { - return priority; - } - - public void setPriority(Integer priority) { - this.priority = priority; - } - - public String getDatabase() { - return database; - } - - public void setDatabase(String database) { - this.database = database; - } - - public boolean isExtremes() { - return extremes; - } - - public void setExtremes(boolean extremes) { - this.extremes = extremes; - } - - public Integer getMaxExecutionTime() { - return maxExecutionTime; - } - - public void setMaxExecutionTime(Integer maxExecutionTime) { - this.maxExecutionTime = maxExecutionTime; - } - - public Integer getMaxRowsToGroupBy() { - return maxRowsToGroupBy; - } - - public void setMaxRowsToGroupBy(Integer maxRowsToGroupBy) { - this.maxRowsToGroupBy = maxRowsToGroupBy; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getHttpAuthorization() { - return httpAuthorization; - } - - public void setHttpAuthorization(String httpAuthorization) { - this.httpAuthorization = httpAuthorization; - } - - public String getHost() { - return host; - } - - public void setHost(String host) { - this.host = host; - } - - public int getPort() { - return port; - } - - public void setPort(int port) { - this.port = port; - } - - public ClickHouseProtocol getProtocol() { - return this.protocol; - } - - public void setProtocol(ClickHouseProtocol protocol) { - this.protocol = protocol; - } - - public boolean isUsePathAsDb() { - return usePathAsDb; - } - - public void setUsePathAsDb(boolean usePathAsDb) { - this.usePathAsDb = usePathAsDb; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public boolean isDistributedAggregationMemoryEfficient() { - return distributedAggregationMemoryEfficient; - } - - public void setDistributedAggregationMemoryEfficient(boolean distributedAggregationMemoryEfficient) { - this.distributedAggregationMemoryEfficient = distributedAggregationMemoryEfficient; - } - - public Long getMaxBytesBeforeExternalGroupBy() { - return maxBytesBeforeExternalGroupBy; - } - - public void setMaxBytesBeforeExternalGroupBy(Long maxBytesBeforeExternalGroupBy) { - this.maxBytesBeforeExternalGroupBy = maxBytesBeforeExternalGroupBy; - } - - public Long getMaxBytesBeforeExternalSort() { - return maxBytesBeforeExternalSort; - } - - public void setMaxBytesBeforeExternalSort(Long maxBytesBeforeExternalSort) { - this.maxBytesBeforeExternalSort = maxBytesBeforeExternalSort; - } - - public Long getMaxMemoryUsage() { - return maxMemoryUsage; - } - - public void setMaxMemoryUsage(Long maxMemoryUsage) { - this.maxMemoryUsage = maxMemoryUsage; - } - - public Long getMaxMemoryUsageForUser() { - return maxMemoryUsageForUser; - } - - public void setMaxMemoryUsageForUser(Long maxMemoryUsageForUser) { - this.maxMemoryUsageForUser = maxMemoryUsageForUser; - } - - public Long getMaxMemoryUsageForAllQueries() { - return maxMemoryUsageForAllQueries; - } - - public void setMaxMemoryUsageForAllQueries(Long maxMemoryUsageForAllQueries) { - this.maxMemoryUsageForAllQueries = maxMemoryUsageForAllQueries; - } - - public Long getPreferredBlockSizeBytes() { - return preferredBlockSizeBytes; - } - - public void setPreferredBlockSizeBytes(Long preferredBlockSizeBytes) { - this.preferredBlockSizeBytes = preferredBlockSizeBytes; - } - - public Long getMaxQuerySize() { - return maxQuerySize; - } - - public void setMaxQuerySize(Long maxQuerySize) { - this.maxQuerySize = maxQuerySize; - } - - public void setMaxAstElements(Long maxAstElements) { - this.maxAstElements = maxAstElements; - } - - public Long getMaxAstElements() { - return this.maxAstElements; - } - - public boolean isSessionCheck() { return sessionCheck; } - - public void setSessionCheck(boolean sessionCheck) { this.sessionCheck = sessionCheck; } - - public String getSessionId() { return sessionId; } - - public void setSessionId(String sessionId) { this.sessionId = sessionId; } - - public Long getSessionTimeout() { return sessionTimeout; } - - public void setSessionTimeout(Long sessionTimeout) { this.sessionTimeout = sessionTimeout; } - - public Long getInsertQuorum() { - return insertQuorum; - } - - public void setInsertQuorum(Long insertQuorum) { - this.insertQuorum = insertQuorum; - } - - public Long getInsertQuorumTimeout() { - return insertQuorumTimeout; - } - - public void setInsertQuorumTimeout(Long insertQuorumTimeout) { - this.insertQuorumTimeout = insertQuorumTimeout; - } - - public Long getSelectSequentialConsistency() { - return selectSequentialConsistency; - } - - public void setSelectSequentialConsistency(Long selectSequentialConsistency) { - this.selectSequentialConsistency = selectSequentialConsistency; - } - - public Boolean getEnableOptimizePredicateExpression() { - return enableOptimizePredicateExpression; - } - - public void setEnableOptimizePredicateExpression(Boolean enableOptimizePredicateExpression) { - this.enableOptimizePredicateExpression = enableOptimizePredicateExpression; - } - - public Long getMaxInsertBlockSize() { - return maxInsertBlockSize; - } - - public void setMaxInsertBlockSize(Long maxInsertBlockSize) { - this.maxInsertBlockSize = maxInsertBlockSize; - } - - public Boolean getInsertDeduplicate() { - return insertDeduplicate; - } - - public void setInsertDeduplicate(Boolean insertDeduplicate) { - this.insertDeduplicate = insertDeduplicate; - } - - public Boolean getInsertDistributedSync() { - return insertDistributedSync; - } - - public void setInsertDistributedSync(Boolean insertDistributedSync) { - this.insertDistributedSync = insertDistributedSync; - } - - public void setAnyJoinDistinctRightTableKeys(Boolean anyJoinDistinctRightTableKeys) { - this.anyJoinDistinctRightTableKeys = anyJoinDistinctRightTableKeys; - } - - public Boolean getAnyJoinDistinctRightTableKeys() { - return anyJoinDistinctRightTableKeys; - } - - public Boolean getSendProgressInHttpHeaders() { - return sendProgressInHttpHeaders; - } - - public void setSendProgressInHttpHeaders(Boolean sendProgressInHttpHeaders) { - this.sendProgressInHttpHeaders = sendProgressInHttpHeaders; - } - - public Boolean getWaitEndOfQuery() { - return waitEndOfQuery; - } - - public void setWaitEndOfQuery(Boolean waitEndOfQuery) { - this.waitEndOfQuery = waitEndOfQuery; - } - - private static class PropertiesBuilder { - private final Properties properties; - public PropertiesBuilder() { - properties = new Properties(); - } - - public void put(String key, int value) { - properties.put(key, value); - } - - public void put(String key, Integer value) { - if (value != null) { - properties.put(key, value.toString()); - } - } - - public void put(String key, Long value) { - if (value != null) { - properties.put(key, value.toString()); - } - } - - public void put(String key, Boolean value) { - if (value != null) { - properties.put(key, value.toString()); - } - } - - public void put(String key, String value) { - if (value != null) { - properties.put(key, value); - } - } - - public Properties getProperties() { - return properties; - } - } - - public ClickHouseProperties merge(ClickHouseProperties second){ - Properties properties = this.asProperties(); - for (Map.Entry entry : second.asProperties().entrySet()) { - properties.put(entry.getKey(), entry.getValue()); - } - - return new ClickHouseProperties(properties); - } - - public ClickHouseProperties merge(Properties other){ - Properties properties = this.asProperties(); - for (Map.Entry entry : other.entrySet()) { - properties.put(entry.getKey(), entry.getValue()); - } - - return new ClickHouseProperties(properties); - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/settings/ClickHouseQueryParam.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/settings/ClickHouseQueryParam.java deleted file mode 100644 index 96cc71c40..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/settings/ClickHouseQueryParam.java +++ /dev/null @@ -1,325 +0,0 @@ -package ru.yandex.clickhouse.settings; - - -import java.sql.DriverPropertyInfo; -import java.util.Locale; -import java.util.Properties; - -public enum ClickHouseQueryParam implements DriverPropertyCreator { - - ADD_HTTP_CORS_HEADER("add_http_cors_header", false, Boolean.class, "Write add http CORS header"), - - AGGREGATION_MEMORY_EFFICIENT_MERGE_THREADS("aggregation_memory_efficient_merge_threads", null, Long.class, ""), - - ALLOW_EXPERIMENTAL_BIGINT_TYPES("allow_experimental_bigint_types", null, Integer.class, "Enables or disables integer values exceeding the range that is supported by the int data type."), - - ALLOW_EXPERIMENTAL_MAP_TYPE("allow_experimental_map_type", null, Integer.class, "Enables or disables Map data type."), - - BACKGROUND_POOL_SIZE("background_pool_size", null, Long.class, ""), - - AUTHORIZATION("authorization", null, String.class, "Authorization header content for HTTP transport"), - - COMPILE("compile", false, Boolean.class, ""), - - COMPRESS("compress", true, Boolean.class, "whether to compress transferred data or not"), - - CONNECT_TIMEOUT("connect_timeout", null, Integer.class, ""), - - CONNECT_TIMEOUT_WITH_FAILOVER_MS("connect_timeout_with_failover_ms", null, Integer.class, ""), - - CONNECTIONS_WITH_FAILOVER_MAX_TRIES("connections_with_failover_max_tries", null, Long.class, ""), - - COUNT_DISTINCT_IMPLEMENTATION("count_distinct_implementation", null, String.class, "What aggregate function to use for implementation of count(DISTINCT ...)"), - - DATABASE("database", null, String.class, "database name used by default"), - - DECOMPRESS("decompress", false, Boolean.class, "whether to decompress transferred data or not"), - - DISTRIBUTED_AGGREGATION_MEMORY_EFFICIENT("distributed_aggregation_memory_efficient", false, Boolean.class, "Whether to optimize memory consumption for external aggregation"), - - DISTRIBUTED_CONNECTIONS_POOL_SIZE("distributed_connections_pool_size", null, Long.class, ""), - - DISTRIBUTED_DIRECTORY_MONITOR_SLEEP_TIME_MS("distributed_directory_monitor_sleep_time_ms", null, Long.class, ""), - - DISTRIBUTED_GROUP_BY_NO_MERGE("distributed_group_by_no_merge", false, Boolean.class, ""), - - DISTRIBUTED_PRODUCT_MODE("distributed_product_mode", null, String.class, ""), - - ENABLE_HTTP_COMPRESSION("enable_http_compression", false, Boolean.class, ""), - /** - * https://clickhouse.yandex/reference_en.html#Extreme values - */ - EXTREMES("extremes", false, Boolean.class, "Whether to include extreme values."), - - FORCE_INDEX_BY_DATE("force_index_by_date", false, Boolean.class, ""), - - FORCE_OPTIMIZE_SKIP_UNUSED_SHARDS("force_optimize_skip_unused_shards", 0, Integer.class, "Enables or disables query execution if optimize_skip_unused_shards is enabled and skipping of unused shards is not possible. If the skipping is not possible and the setting is enabled, an exception will be thrown."), - - FORCE_PRIMARY_KEY("force_primary_key", false, Boolean.class, ""), - - GLOBAL_SUBQUERIES_METHOD("global_subqueries_method", null, String.class, ""), - - GROUP_BY_TWO_LEVEL_THRESHOLD("group_by_two_level_threshold", null, Long.class, ""), - - GROUP_BY_TWO_LEVEL_THRESHOLD_BYTES("group_by_two_level_threshold_bytes", null, Long.class, ""), - - HTTP_NATIVE_COMPRESSION_DISABLE_CHECKSUMMING_ON_DECOMPRESS("http_native_compression_disable_checksumming_on_decompress", null, Boolean.class, "Whether to disable checksum check on decompress"), - - HTTP_ZLIB_COMPRESSION_LEVEL("http_zlib_compression_level", null, Long.class, ""), - - INPUT_FORMAT_SKIP_UNKNOWN_FIELDS("input_format_skip_unknown_fields", false, Boolean.class, "Skip columns with unknown names from input data (it works for JSONEachRow and TSKV formats)."), - - INPUT_FORMAT_VALUES_INTERPRET_EXPRESSIONS("input_format_values_interpret_expressions", true, Boolean.class, - "For Values format: if field could not be parsed by streaming parser, run SQL parser and try to interpret it as SQL expression."), - - INSERT_DEDUPLICATE("insert_deduplicate", null, Boolean.class, "For INSERT queries in the replicated table, specifies that deduplication of insertings blocks should be preformed"), - - INSERT_DISTRIBUTED_SYNC("insert_distributed_sync", null, Boolean.class, "If setting is enabled, insert query into distributed waits until data will be sent to all nodes in cluster."), - - ANY_JOIN_DISTINCT_RIGHT_TABLE_KEYS("any_join_distinct_right_table_keys", null, Boolean.class, "Setting enables old behaviour of ANY INNER|RIGHT|FULL JOIN which are disabled by default from version 19.14.3.3"), - - INSERT_QUORUM("insert_quorum", null, Long.class, ""), - - INSERT_QUORUM_TIMEOUT("insert_quorum_timeout", null, Long.class, ""), - - INTERACTIVE_DELAY("interactive_delay", null, Long.class, ""), - - JOIN_ALGORITHM("join_algorithm", null, String.class, ""), - - LOAD_BALANCING("load_balancing", null, String.class, ""), - - LOG_QUERIES("log_queries", false, Boolean.class, ""), - - LOG_QUERIES_CUT_TO_LENGTH("log_queries_cut_to_length", null, Long.class, ""), - - MARK_CACHE_MIN_LIFETIME("mark_cache_min_lifetime", null, Long.class, ""), - /** - * https://clickhouse.yandex/reference_en.html#max_block_size - */ - MAX_BLOCK_SIZE("max_block_size", null, Integer.class, "Recommendation for what size of block (in number of rows) to load from tables"), - - MAX_BYTES_BEFORE_EXTERNAL_GROUP_BY("max_bytes_before_external_group_by", null, Long.class, "Threshold to use external group by"), - - MAX_BYTES_BEFORE_EXTERNAL_SORT("max_bytes_before_external_sort", null, Long.class, "Threshold to use external sort"), - - MAX_COMPRESS_BLOCK_SIZE("max_compress_block_size", null, Long.class, ""), - - MAX_CONCURRENT_QUERIES_FOR_USER("max_concurrent_queries_for_user", null, Long.class, ""), - - MAX_DISTRIBUTED_CONNECTIONS("max_distributed_connections", null, Long.class, ""), - - MAX_DISTRIBUTED_PROCESSING_THREADS("max_distributed_processing_threads", null, Long.class, ""), - /** - * https://clickhouse.yandex/reference_en.html#max_execution_time - */ - MAX_EXECUTION_TIME("max_execution_time", null, Integer.class, "Maximum query execution time in seconds."), - - MAX_INSERT_BLOCK_SIZE("max_insert_block_size", null, Long.class, ""), - - /** - * @see max_memory_usage - */ - MAX_MEMORY_USAGE("max_memory_usage", null, Long.class, "The maximum amount of memory consumption when running a query on a single server."), - - /** - * @see max_memory_usage_for_user - */ - MAX_MEMORY_USAGE_FOR_USER("max_memory_usage_for_user", null, Long.class, "The maximum amount of RAM to use for running a user's queries on a single server."), - - /** - * @see max_memory_usage_for_all_queries - */ - MAX_MEMORY_USAGE_FOR_ALL_QUERIES("max_memory_usage_for_all_queries", null, Long.class, "The maximum amount of RAM to use for running all queries on a single server."), - - //dbms/include/DB/Interpreters/Settings.h - MAX_PARALLEL_REPLICAS("max_parallel_replicas", null, Integer.class, "Max shard replica count."), - - MAX_PARTITIONS_PER_INSERT_BLOCK("max_partitions_per_insert_block", null, Integer.class, "If inserted block contains larger number of partitions, an exception is thrown. Set it to 0 if you want to remove the limit (not recommended)."), - - MAX_READ_BUFFER_SIZE("max_read_buffer_size", null, Long.class, ""), - - MAX_RESULT_ROWS("max_result_rows", null, Integer.class, "Limit on the number of rows in the result. Also checked for subqueries, and on remote servers when running parts of a distributed query."), - /** - * https://clickhouse.yandex/reference_en.html#max_rows_to_group_by - */ - MAX_ROWS_TO_GROUP_BY("max_rows_to_group_by", null, Integer.class, - "Maximum number of unique keys received from aggregation. This setting lets you limit memory consumption when aggregating."), - - MAX_STREAMS_TO_MAX_THREADS_RATIO("max_streams_to_max_threads_ratio", null, Double.class, ""), - /** - * https://clickhouse.yandex/reference_en.html#max_threads - */ - MAX_THREADS("max_threads", null, Integer.class, "The maximum number of query processing threads"), - - MAX_QUERY_SIZE("max_query_size", null, Long.class, "Maximum size of query"), - - MAX_AST_ELEMENTS("max_ast_elements", null, Long.class, "Maximum number of elements in a query syntactic tree"), - - MEMORY_TRACKER_FAULT_PROBABILITY("memory_tracker_fault_probability", null, Double.class, ""), - - MERGE_TREE_COARSE_INDEX_GRANULARITY("merge_tree_coarse_index_granularity", null, Long.class, ""), - - MERGE_TREE_MAX_ROWS_TO_USE_CACHE("merge_tree_max_rows_to_use_cache", null, Long.class, ""), - - MERGE_TREE_MIN_ROWS_FOR_CONCURRENT_READ("merge_tree_min_rows_for_concurrent_read", null, Long.class, ""), - - MERGE_TREE_MIN_ROWS_FOR_SEEK("merge_tree_min_rows_for_seek", null, Long.class, ""), - - MERGE_TREE_UNIFORM_READ_DISTRIBUTION("merge_tree_uniform_read_distribution", true, Boolean.class, ""), - - MIN_BYTES_TO_USE_DIRECT_IO("min_bytes_to_use_direct_io", null, Long.class, ""), - - MIN_COMPRESS_BLOCK_SIZE("min_compress_block_size", null, Long.class, ""), - - MIN_COUNT_TO_COMPILE("min_count_to_compile", null, Long.class, ""), - - MIN_INSERT_BLOCK_SIZE_BYTES("min_insert_block_size_bytes", null, Long.class, "Squash blocks passed to INSERT query to specified size in bytes, if blocks are not big enoug"), - - MIN_INSERT_BLOCK_SIZE_ROWS("min_insert_block_size_rows", null, Long.class, "Squash blocks passed to INSERT query to specified size in rows, if blocks are not big enough."), - - NETWORK_COMPRESSION_METHOD("network_compression_method", null, String.class, ""), - - OPTIMIZE_MIN_EQUALITY_DISJUNCTION_CHAIN_LENGTH("optimize_min_equality_disjunction_chain_length", null, Long.class, ""), - - OPTIMIZE_MOVE_TO_PREWHERE("optimize_move_to_prewhere", true, Boolean.class, ""), - - OPTIMIZE_SKIP_UNUSED_SHARDS("optimize_skip_unused_shards", 0, Integer.class, "Enables or disables skipping of unused shards for SELECT queries that have sharding key condition in WHERE/PREWHERE (assuming that the data is distributed by sharding key, otherwise does nothing)."), - - OUTPUT_FORMAT_JSON_QUOTE_64BIT_INTEGERS("output_format_json_quote_64bit_integers", true, Boolean.class, "Controls quoting of 64-bit integers in JSON output format."), - - OUTPUT_FORMAT_PRETTY_MAX_ROWS("output_format_pretty_max_rows", null, Long.class, "Rows limit for Pretty formats."), - - OUTPUT_FORMAT_WRITE_STATISTICS("output_format_write_statistics", true, Boolean.class, "Write statistics about read rows, bytes, time elapsed in suitable output formats"), - - PARALLEL_REPLICAS_COUNT("parallel_replicas_count", null, Long.class, ""), - - PARALLEL_REPLICA_OFFSET("parallel_replica_offset", null, Long.class, ""), - - PASSWORD("password", null, String.class, "user password, by default null"), - - POLL_INTERVAL("poll_interval", null, Long.class, ""), - - PRIORITY("priority", null, Integer.class, "The lower the value the bigger the priority."), - /** - * https://clickhouse.yandex/reference_en.html#Settings profiles - */ - PROFILE("profile", null, String.class, "Settings profile: a collection of settings grouped under the same name"), - - RECEIVE_TIMEOUT("receive_timeout", null, Integer.class, ""), - - READ_BACKOFF_MAX_THROUGHPUT("read_backoff_max_throughput", null, Long.class, ""), - - READ_BACKOFF_MIN_EVENTS("read_backoff_min_events", null, Long.class, ""), - - READ_BACKOFF_MIN_INTERVAL_BETWEEN_EVENTS_MS("read_backoff_min_interval_between_events_ms", null, Long.class, ""), - - READ_BACKOFF_MIN_LATENCY_MS("read_backoff_min_latency_ms", null, Long.class, ""), - - REPLACE_RUNNING_QUERY("replace_running_query", false, Boolean.class, ""), - - REPLICATION_ALTER_COLUMNS_TIMEOUT("replication_alter_columns_timeout", null, Long.class, ""), - - REPLICATION_ALTER_PARTITIONS_SYNC("replication_alter_partitions_sync", null, Long.class, ""), - - RESHARDING_BARRIER_TIMEOUT("resharding_barrier_timeout", null, Long.class, ""), - - RESULT_OVERFLOW_MODE("result_overflow_mode", null, String.class, "What to do if the volume of the result exceeds one of the limits: 'throw' or 'break'. By default, throw. Using 'break' is similar to using LIMIT."), - - SELECT_SEQUENTIAL_CONSISTENCY("select_sequential_consistency", null, Long.class, ""), - - SEND_PROGRESS_IN_HTTP_HEADERS("send_progress_in_http_headers", null, Boolean.class, "Allow to populate summary in ClickHouseStatement with read/written rows/bytes"), - - SEND_TIMEOUT("send_timeout", null, Integer.class, ""), - - SESSION_CHECK("session_check", false, Boolean.class, ""), - - SESSION_ID("session_id", null, String.class, ""), - - SESSION_TIMEOUT("session_timeout", null, Long.class, ""), - - SKIP_UNAVAILABLE_SHARDS("skip_unavailable_shards", false, Boolean.class, ""), - - STRICT_INSERT_DEFAULTS("strict_insert_defaults", false, Boolean.class, ""), - - TABLE_FUNCTION_REMOTE_MAX_ADDRESSES("table_function_remote_max_addresses", null, Long.class, ""), - - TOTALS_AUTO_THRESHOLD("totals_auto_threshold", null, Double.class, ""), - /** - * https://clickhouse.yandex/reference_en.html#WITH TOTALS modifier - */ - TOTALS_MODE("totals_mode", null, String.class, "How to calculate TOTALS when HAVING is present, as well as when max_rows_to_group_by and group_by_overflow_mode = 'any' are present."), - - QUERY_ID("query_id", null, String.class, ""), - - QUEUE_MAX_WAIT_MS("queue_max_wait_ms", null, Integer.class, ""), - - QUOTA_KEY("quota_key", null, String.class, "quota is calculated for each quota_key value. For example here may be some user name."), - - @Deprecated - use_client_time_zone("use_client_time_zone", false, Boolean.class, ""), - - USE_UNCOMPRESSED_CACHE("use_uncompressed_cache", true, Boolean.class, "Whether to use the cache of uncompressed blocks."), - - USER("user", null, String.class, "user name, by default - default"), - - PREFERRED_BLOCK_SIZE_BYTES("preferred_block_size_bytes", null, Long.class, "Adaptively estimates number of required rows in a block."), - - ENABLE_OPTIMIZE_PREDICATE_EXPRESSION("enable_optimize_predicate_expression", null, Boolean.class, "See Clickhouse server description for this parameter. Default value is null so that server setting is taken."), - - WAIT_END_OF_QUERY("wait_end_of_query", null, Boolean.class, "Buffer the response server-side before sending to client. Useful when using SEND_PROGRESS_IN_HTTP_HEADERS to get accurate stats."), - ; - - private final String key; - private final Object defaultValue; - private final Class clazz; - private final String description; - - ClickHouseQueryParam(String key, T defaultValue, Class clazz, String description) { - this.key = key; - this.defaultValue = defaultValue; - this.clazz = clazz; - this.description = description; - } - - public String getKey() { - return key; - } - - public Object getDefaultValue() { - return defaultValue; - } - - public Class getClazz() { - return clazz; - } - - public String getDescription() { - return description; - } - - @Override - public String toString() { - return name().toLowerCase(Locale.ROOT); - } - - @Override - public DriverPropertyInfo createDriverPropertyInfo(Properties properties) { - DriverPropertyInfo propertyInfo = new DriverPropertyInfo(key, driverPropertyValue(properties)); - propertyInfo.required = false; - propertyInfo.description = description; - propertyInfo.choices = driverPropertyInfoChoices(); - return propertyInfo; - } - - private String[] driverPropertyInfoChoices() { - return clazz == Boolean.class || clazz == Boolean.TYPE ? new String[]{"true", "false"} : null; - } - - private String driverPropertyValue(Properties properties) { - String value = properties.getProperty(key); - if (value == null) { - value = defaultValue == null ? null : defaultValue.toString(); - } - return value; - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/settings/DriverPropertyCreator.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/settings/DriverPropertyCreator.java deleted file mode 100644 index 1a957ae8e..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/settings/DriverPropertyCreator.java +++ /dev/null @@ -1,8 +0,0 @@ -package ru.yandex.clickhouse.settings; - -import java.sql.DriverPropertyInfo; -import java.util.Properties; - -public interface DriverPropertyCreator { - DriverPropertyInfo createDriverPropertyInfo(Properties properties); -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseArrayUtil.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseArrayUtil.java deleted file mode 100644 index 4b7a2d92c..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseArrayUtil.java +++ /dev/null @@ -1,371 +0,0 @@ -package ru.yandex.clickhouse.util; - -import java.sql.Date; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.util.Collection; -import java.util.TimeZone; - -import ru.yandex.clickhouse.ClickHouseUtil; -import ru.yandex.clickhouse.response.ArrayByteFragment; -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; -import ru.yandex.clickhouse.response.parser.ClickHouseValueParser; - -/** - * @author Dmitry Andreev - */ -public class ClickHouseArrayUtil { - - private static final char ARRAY_ELEMENTS_SEPARATOR = ','; - private static final char STRING_QUOTATION = '\''; - private static final int MAX_ARRAY_DEPTH = 32; - - private ClickHouseArrayUtil() { - // NOP - } - - /** - * @param object - * the object to convert to ClickHouse-string representation - * @param dateTimeZone - * TimeZone to use when formatting date values - * @param dateTimeTimeZone - * TimeZone to use when formatting datetime values - * @return string representation of an object - */ - public static String arrayToString(Object object, TimeZone dateTimeZone, - TimeZone dateTimeTimeZone) - { - if (!object.getClass().isArray()) { - throw new IllegalArgumentException("Object must be array"); - } - if (object.getClass().getComponentType().isPrimitive()) { - return primitiveArrayToString(object); - } - return toString((Object[]) object, dateTimeZone, dateTimeTimeZone); - } - - - public static String toString(Object[] values, TimeZone dateTimeZone, TimeZone dateTimeTimeZone) { - if (values.length > 0 && values[0] != null && (values[0].getClass().isArray() || values[0] instanceof Collection)) { - // quote is false to avoid escaping inner '[' - ArrayBuilder builder = new ArrayBuilder(false, dateTimeZone, dateTimeTimeZone); - for (Object value : values) { - if (value instanceof Collection) { - Object[] objects = ((Collection) value).toArray(); - builder.append(toString(objects, dateTimeZone, dateTimeTimeZone)); - } else { - builder.append(arrayToString(value, dateTimeZone, dateTimeTimeZone)); - } - } - return builder.build(); - } - ArrayBuilder builder = new ArrayBuilder(needQuote(values), dateTimeZone, dateTimeTimeZone); - for (Object value : values) { - builder.append(value); - } - return builder.build(); - } - - public static String toString(Collection collection, TimeZone dateTimeZone, - TimeZone dateTimeTimeZone) - { - return toString(collection.toArray(), dateTimeZone, dateTimeTimeZone); - } - - public static Object parseArray(ByteFragment value, boolean useObjects, - TimeZone timeZone, int arrayLevel, Class elementClass, ClickHouseColumnInfo columnInfo) throws SQLException - { - if (arrayLevel > ClickHouseArrayUtil.MAX_ARRAY_DEPTH) { - throw new IllegalArgumentException("Maximum parse depth exceeded"); - } - - if (value.isNull()) { - return null; - } - - if (value.charAt(0) != '[' || value.charAt(value.length() - 1) != ']') { - throw new IllegalArgumentException("not an array: " + value); - } - - if ((elementClass == Date.class || elementClass == Timestamp.class) && timeZone == null) { - throw new IllegalArgumentException("Time zone must be provided for date/dateTime array"); - } - - ByteFragment trim = value.subseq(1, value.length() - 2); - - int index = 0; - Object array; - if (arrayLevel > 1) { - int[] dimensions = new int[arrayLevel]; - dimensions[0] = ClickHouseArrayUtil.getArrayLength(trim); - array = java.lang.reflect.Array.newInstance( - useObjects ? elementClass : Utils.unwrap(elementClass), - dimensions - ); - } else { - array = java.lang.reflect.Array.newInstance( - useObjects ? elementClass : Utils.unwrap(elementClass), - ClickHouseArrayUtil.getArrayLength(trim) - ); - } - int fieldStart = 0; - int currentLevel = 0; - boolean inQuotation = false; - for (int chIdx = 0; chIdx < trim.length(); chIdx++) { - int ch = trim.charAt(chIdx); - - if (ch == '\\') { - chIdx++; - } - inQuotation = ch == STRING_QUOTATION ^ inQuotation; - if (!inQuotation) { - if (ch == '[') { - currentLevel++; - } else if (ch == ']') { - currentLevel--; - } - } - - if (!inQuotation && ch == ARRAY_ELEMENTS_SEPARATOR && currentLevel == 0 || chIdx == trim.length() - 1) { - int fieldEnd = chIdx == trim.length() - 1 ? chIdx + 1 : chIdx; - if (trim.charAt(fieldStart) == '\'') { - fieldStart++; - fieldEnd--; - } - ArrayByteFragment fragment = ArrayByteFragment.wrap(trim.subseq(fieldStart, fieldEnd - fieldStart)); - if (arrayLevel > 1) { - Object arrayValue = parseArray( - fragment, useObjects, timeZone, arrayLevel - 1, elementClass, columnInfo); - java.lang.reflect.Array.set(array, index++, arrayValue); - } else { - Object o = useObjects - ? ClickHouseValueParser.getParser(elementClass).parse( - fragment, columnInfo, timeZone) - : ClickHouseValueParser.getParser(elementClass).parseWithDefault( - fragment, columnInfo, timeZone); - java.lang.reflect.Array.set(array, index++, o); - } - fieldStart = chIdx + 1; - } - } - - return array; - } - - public static int getArrayLength(ByteFragment value) { - if (value.length() == 0) { - return 0; - } - - int length = 1; - boolean inQuotation = false; - int arrayLevel = 0; - for (int i = 0; i < value.length(); i++) { - int ch = value.charAt(i); - - if (ch == '\\') { - i++; - } - - inQuotation = ch == ClickHouseArrayUtil.STRING_QUOTATION ^ inQuotation; - if (!inQuotation) { - if (ch == '[') { - ++arrayLevel; - } else if (ch == ']') { - --arrayLevel; - } else if (ch == ClickHouseArrayUtil.ARRAY_ELEMENTS_SEPARATOR && arrayLevel == 0) { - ++length; - } - } - } - return length; - } - - public static Object parseArray(ByteFragment value, - boolean useObjects, TimeZone timeZone, ClickHouseColumnInfo columnInfo) - throws SQLException - { - return parseArray(value, useObjects, timeZone, columnInfo.getArrayLevel(), - columnInfo.getEffectiveClickHouseDataType().getJavaClass(), columnInfo); - } - - static Object parseArray(ByteFragment value, Class clazz, - boolean useObjects, ClickHouseColumnInfo columnInfo) - throws SQLException - { - return parseArray(value, useObjects, null, columnInfo.getArrayLevel(), - clazz, columnInfo); - } - - /** - * @deprecated convenience for unit tests - */ - @Deprecated - static String toString(Collection collection) { - TimeZone tz = TimeZone.getDefault(); - return toString(collection, tz, tz); - } - - /** - * @deprecated convenience for unit tests - */ - @Deprecated - static String toString(Object[] values) { - TimeZone tz = TimeZone.getDefault(); - return toString(values, tz, tz); - } - - /** - * @deprecated convenience for unit tests - */ - @Deprecated - static String arrayToString(Object object) { - TimeZone tz = TimeZone.getDefault(); - return arrayToString(object, tz, tz); - } - - private static String primitiveArrayToString(Object array) { - if (array instanceof int[]) { - return toString((int[]) array); - } else if (array instanceof long[]) { - return toString((long[]) array); - } else if (array instanceof float[]) { - return toString((float[]) array); - } else if (array instanceof double[]) { - return toString((double[]) array); - } else if (array instanceof char[]) { - return toString((char[]) array); - } else if (array instanceof byte[]) { - return toString((byte[]) array); - } else if (array instanceof short[]) { - return toString((short[]) array); - } else { - throw new IllegalArgumentException("Wrong primitive type: " + array.getClass().getComponentType()); - } - } - - private static String toString(int[] values) { - ArrayBuilder builder = new ArrayBuilder(false); - for (int value : values) { - builder.append(value); - } - return builder.build(); - } - - private static String toString(long[] values) { - ArrayBuilder builder = new ArrayBuilder(false); - for (long value : values) { - builder.append(value); - } - return builder.build(); - } - - private static String toString(float[] values) { - ArrayBuilder builder = new ArrayBuilder(false); - for (float value : values) { - builder.append(value); - } - return builder.build(); - } - - private static String toString(double[] values) { - ArrayBuilder builder = new ArrayBuilder(false); - for (double value : values) { - builder.append(value); - } - return builder.build(); - } - - private static String toString(byte[] values) { - return "'" + ClickHouseValueFormatter.formatBytes(values) + "'"; - } - - private static String toString(short[] values) { - ArrayBuilder builder = new ArrayBuilder(false); - for (short value : values) { - builder.append(value); - } - return builder.build(); - } - - private static String toString(char[] values) { - ArrayBuilder builder = new ArrayBuilder(true); - for (char value : values) { - builder.append(value); - } - return builder.build(); - } - - private static boolean needQuote(Object[] objects) { - Object o = null; - for (Object u : objects) { - if (u != null) { - o = u; - break; - } - } - return objects.length == 0 || ClickHouseValueFormatter.needsQuoting(o); - } - - private static class ArrayBuilder { - - private final StringBuilder builder; - private final boolean quote; - private final TimeZone dateTimeZone; - private final TimeZone dateTimeTimeZone; - private int size = 0; - private boolean built = false; - - private ArrayBuilder(boolean quote) { - this(quote, TimeZone.getDefault(), TimeZone.getDefault()); - } - - private ArrayBuilder(boolean quote, TimeZone dateTimeZone, - TimeZone dateTimeTimeZone) - { - this.quote = quote; - this.builder = new StringBuilder("["); - this.dateTimeZone = dateTimeZone; - this.dateTimeTimeZone = dateTimeTimeZone; - } - - private ArrayBuilder append(Object value) { - if (built) { - throw new IllegalStateException("Already built"); - } - if (size > 0) { - builder.append(','); - } - if (value != null) { - if (quote) { - builder.append('\''); - } - if (value instanceof String) { - builder.append(quote ? ClickHouseUtil.escape((String) value) : value); - } else { - builder.append(ClickHouseValueFormatter.formatObject( - value, dateTimeZone, dateTimeTimeZone)); - } - if (quote) { - builder.append('\''); - } - } else { - builder.append("NULL"); - } - size++; - return this; - } - - private String build() { - if (!built) { - builder.append(']'); - built = true; - } - return builder.toString(); - } - } - - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseBitmap.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseBitmap.java deleted file mode 100644 index b135054cb..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseBitmap.java +++ /dev/null @@ -1,571 +0,0 @@ -package ru.yandex.clickhouse.util; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutput; -import java.io.DataOutputStream; -import java.io.IOException; -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Objects; -import org.roaringbitmap.RoaringBitmap; -import org.roaringbitmap.buffer.ImmutableRoaringBitmap; -import org.roaringbitmap.buffer.MutableRoaringBitmap; -import org.roaringbitmap.longlong.Roaring64Bitmap; -import org.roaringbitmap.longlong.Roaring64NavigableMap; -import ru.yandex.clickhouse.domain.ClickHouseDataType; - -public abstract class ClickHouseBitmap { - static class ClickHouseRoaringBitmap extends ClickHouseBitmap { - private final RoaringBitmap rb; - - protected ClickHouseRoaringBitmap(RoaringBitmap bitmap, ClickHouseDataType innerType) { - super(bitmap, innerType); - - this.rb = Objects.requireNonNull(bitmap); - } - - @Override - public int getCardinality() { - return rb.getCardinality(); - } - - @Override - public void serialize(ByteBuffer buffer) { - rb.serialize(buffer); - } - - @Override - public int serializedSizeInBytes() { - return rb.serializedSizeInBytes(); - } - - @Override - public int[] toIntArray() { - return rb.toArray(); - } - } - - static class ClickHouseImmutableRoaringBitmap extends ClickHouseBitmap { - private final ImmutableRoaringBitmap rb; - - protected ClickHouseImmutableRoaringBitmap(ImmutableRoaringBitmap rb, ClickHouseDataType innerType) { - super(rb, innerType); - - this.rb = Objects.requireNonNull(rb); - } - - @Override - public int getCardinality() { - return rb.getCardinality(); - } - - @Override - public void serialize(ByteBuffer buffer) { - rb.serialize(buffer); - } - - @Override - public int serializedSizeInBytes() { - return rb.serializedSizeInBytes(); - } - - @Override - public int[] toIntArray() { - return rb.toArray(); - } - } - - static class ClickHouseMutableRoaringBitmap extends ClickHouseBitmap { - private final MutableRoaringBitmap rb; - - protected ClickHouseMutableRoaringBitmap(MutableRoaringBitmap bitmap, ClickHouseDataType innerType) { - super(bitmap, innerType); - - this.rb = Objects.requireNonNull(bitmap); - } - - @Override - public int getCardinality() { - return rb.getCardinality(); - } - - @Override - public void serialize(ByteBuffer buffer) { - rb.serialize(buffer); - } - - @Override - public int serializedSizeInBytes() { - return rb.serializedSizeInBytes(); - } - - @Override - public int[] toIntArray() { - return rb.toArray(); - } - } - - static class ClickHouseRoaring64NavigableMap extends ClickHouseBitmap { - private final Roaring64NavigableMap rb; - - protected ClickHouseRoaring64NavigableMap(Roaring64NavigableMap bitmap, ClickHouseDataType innerType) { - super(bitmap, innerType); - - this.rb = Objects.requireNonNull(bitmap); - } - - @Override - public int getCardinality() { - return rb.getIntCardinality(); - } - - @Override - public long getLongCardinality() { - return rb.getLongCardinality(); - } - - @Override - public void serialize(ByteBuffer buffer) { - int size = serializedSizeInBytes(); - // TODO use custom data output so that we can handle large byte array - try (ByteArrayOutputStream bas = new ByteArrayOutputStream(size)) { - DataOutput out = new DataOutputStream(bas); - try { - // https://github.com/RoaringBitmap/RoaringBitmap/blob/0.9.9/RoaringBitmap/src/main/java/org/roaringbitmap/longlong/Roaring64NavigableMap.java#L1105 - rb.serialize(out); - } catch (IOException e) { - throw new IllegalArgumentException("Failed to serialize given bitmap", e); - } - - byte[] bytes = bas.toByteArray(); - for (int i = 4; i > 0; i--) { - buffer.put(bytes[i]); - } - buffer.putInt(0); - buffer.put(bytes, 5, size - 5); - } catch (IOException e) { - throw new IllegalStateException("Failed to serialize given bitmap", e); - } - } - - @Override - public int serializedSizeInBytes() { - return (int) rb.serializedSizeInBytes(); - } - - @Override - public long serializedSizeInBytesAsLong() { - return rb.serializedSizeInBytes(); - } - - @Override - public int[] toIntArray() { - long[] longs = toLongArray(); - int len = longs.length; - int[] ints = new int[len]; - for (int i = 0; i < len; i++) { - ints[i] = (int) longs[i]; - } - return ints; - } - - @Override - public long[] toLongArray() { - return rb.toArray(); - } - } - - public static ClickHouseBitmap wrap(byte... values) { - boolean isUnsigned = true; - int len = values.length; - int[] ints = new int[len]; - for (int i = 0; i < len; i++) { - byte v = values[i]; - ints[i] = v; - if (isUnsigned && v < 0) { - isUnsigned = false; - } - } - - return wrap(RoaringBitmap.bitmapOf(ints), isUnsigned ? ClickHouseDataType.UInt8 : ClickHouseDataType.Int8); - } - - public static ClickHouseBitmap wrap(short... values) { - boolean isUnsigned = true; - int len = values.length; - int[] ints = new int[len]; - for (int i = 0; i < len; i++) { - short v = values[i]; - ints[i] = v; - if (isUnsigned && v < 0) { - isUnsigned = false; - } - } - - return wrap(RoaringBitmap.bitmapOf(ints), isUnsigned ? ClickHouseDataType.UInt16 : ClickHouseDataType.Int16); - } - - public static ClickHouseBitmap wrap(int... values) { - boolean isUnsigned = true; - int len = values.length; - int[] ints = new int[len]; - for (int i = 0; i < len; i++) { - int v = values[i]; - ints[i] = v; - if (isUnsigned && v < 0) { - isUnsigned = false; - } - } - - return wrap(RoaringBitmap.bitmapOf(ints), isUnsigned ? ClickHouseDataType.UInt32 : ClickHouseDataType.Int32); - } - - public static ClickHouseBitmap wrap(long... values) { - boolean isUnsigned = true; - int len = values.length; - long[] longs = new long[len]; - for (int i = 0; i < len; i++) { - long v = values[i]; - longs[i] = v; - if (isUnsigned && v < 0) { - isUnsigned = false; - } - } - - return wrap(Roaring64NavigableMap.bitmapOf(longs), - isUnsigned ? ClickHouseDataType.UInt64 : ClickHouseDataType.Int64); - } - - public static ClickHouseBitmap wrap(Object bitmap, ClickHouseDataType innerType) { - final ClickHouseBitmap b; - if (bitmap instanceof RoaringBitmap) { - b = new ClickHouseRoaringBitmap((RoaringBitmap) bitmap, innerType); - } else if (bitmap instanceof MutableRoaringBitmap) { - b = new ClickHouseMutableRoaringBitmap((MutableRoaringBitmap) bitmap, innerType); - } else if (bitmap instanceof ImmutableRoaringBitmap) { - b = new ClickHouseImmutableRoaringBitmap((ImmutableRoaringBitmap) bitmap, innerType); - } else if (bitmap instanceof Roaring64Bitmap) { - b = new ClickHouseRoaring64NavigableMap( - Roaring64NavigableMap.bitmapOf(((Roaring64Bitmap) bitmap).toArray()), innerType); - } else if (bitmap instanceof Roaring64NavigableMap) { - b = new ClickHouseRoaring64NavigableMap((Roaring64NavigableMap) bitmap, innerType); - } else { - throw new IllegalArgumentException("Only RoaringBitmap is supported but got: " + bitmap); - } - - return b; - } - - public static ClickHouseBitmap deserialize(DataInputStream in, ClickHouseDataType innerType) throws IOException { - final ClickHouseBitmap rb; - - int byteLen = byteLength(innerType); - int flag = in.readUnsignedByte(); - if (flag == 0) { - byte cardinality = (byte) in.readUnsignedByte(); - byte[] bytes = new byte[2 + byteLen * cardinality]; - bytes[0] = (byte) flag; - bytes[1] = cardinality; - in.read(bytes, 2, bytes.length - 2); - - rb = ClickHouseBitmap.deserialize(bytes, innerType); - } else { - int len = Utils.readVarInt(in); - byte[] bytes = new byte[len]; - - if (byteLen <= 4) { - Utils.readFully(in, bytes); - RoaringBitmap b = new RoaringBitmap(); - b.deserialize(flip(newBuffer(len).put(bytes))); - rb = ClickHouseBitmap.wrap(b, innerType); - } else { - // TODO implement a wrapper of DataInput to get rid of byte array here - bytes[0] = (byte) 0; // always unsigned - // read map size in big-endian byte order - for (int i = 4; i > 0; i--) { - bytes[i] = in.readByte(); - } - if (in.readByte() != 0 || in.readByte() != 0 || in.readByte() != 0 || in.readByte() != 0) { - throw new IllegalStateException( - "Not able to deserialize ClickHouseBitmap for too many bitmaps(>" + 0xFFFFFFFFL + ")!"); - } - // read the rest - Utils.readFully(in, bytes, 5, len - 8); - Roaring64NavigableMap b = new Roaring64NavigableMap(); - b.deserialize(new DataInputStream(new ByteArrayInputStream(bytes))); - rb = ClickHouseBitmap.wrap(b, innerType); - } - } - - return rb; - } - - public static ClickHouseBitmap deserialize(byte[] bytes, ClickHouseDataType innerType) throws IOException { - // https://github.com/ClickHouse/ClickHouse/blob/master/src/AggregateFunctions/AggregateFunctionGroupBitmapData.h#L100 - ClickHouseBitmap rb = ClickHouseBitmap.wrap(); - - if (bytes == null || bytes.length == 0) { - return rb; - } - - int byteLen = byteLength(innerType); - ByteBuffer buffer = newBuffer(bytes.length); - buffer = (ByteBuffer) ((Buffer) buffer.put(bytes)).flip(); - - if (buffer.get() == (byte) 0) { // small set - int cardinality = buffer.get(); - if (byteLen == 1) { - byte[] values = new byte[cardinality]; - for (int i = 0; i < cardinality; i++) { - values[i] = buffer.get(); - } - rb = ClickHouseBitmap.wrap(values); - } else if (byteLen == 2) { - short[] values = new short[cardinality]; - for (int i = 0; i < cardinality; i++) { - values[i] = buffer.getShort(); - } - rb = ClickHouseBitmap.wrap(values); - } else if (byteLen == 4) { - int[] values = new int[cardinality]; - for (int i = 0; i < cardinality; i++) { - values[i] = buffer.getInt(); - } - rb = ClickHouseBitmap.wrap(values); - } else { - long[] values = new long[cardinality]; - for (int i = 0; i < cardinality; i++) { - values[i] = buffer.getLong(); - } - rb = ClickHouseBitmap.wrap(values); - } - } else { // serialized bitmap - int len = Utils.readVarInt(buffer); - if (buffer.remaining() < len) { - throw new IllegalStateException( - "Need " + len + " bytes to deserialize ClickHouseBitmap but only got " + buffer.remaining()); - } - if (byteLen <= 4) { - RoaringBitmap b = new RoaringBitmap(); - b.deserialize(buffer); - rb = ClickHouseBitmap.wrap(b, innerType); - } else { - // consume map size(long in little-endian byte order) - byte[] bitmaps = new byte[4]; - buffer.get(bitmaps); - - if (buffer.get() != 0 || buffer.get() != 0 || buffer.get() != 0 || buffer.get() != 0) { - throw new IllegalStateException( - "Not able to deserialize ClickHouseBitmap for too many bitmaps(>" + 0xFFFFFFFFL + ")!"); - } - // replace the last 5 bytes to flag(boolean for signed/unsigned) and map - // size(integer) - ((Buffer) buffer).position(buffer.position() - 5); - // always unsigned due to limit of CRoaring - buffer.put((byte) 0); - // big-endian -> little-endian - for (int i = 3; i >= 0; i--) { - buffer.put(bitmaps[i]); - } - - ((Buffer) buffer).position(buffer.position() - 5); - bitmaps = new byte[buffer.remaining()]; - buffer.get(bitmaps); - Roaring64NavigableMap b = new Roaring64NavigableMap(); - b.deserialize(new DataInputStream(new ByteArrayInputStream(bitmaps))); - rb = ClickHouseBitmap.wrap(b, innerType); - } - } - - return rb; - } - - private static ByteBuffer newBuffer(int capacity) { - ByteBuffer buffer = ByteBuffer.allocate(capacity); - if (buffer.order() != ByteOrder.LITTLE_ENDIAN) { - buffer = buffer.slice().order(ByteOrder.LITTLE_ENDIAN); - } - - return buffer; - } - - private static ByteBuffer flip(ByteBuffer buffer) { - return (ByteBuffer) ((Buffer) buffer).flip(); - } - - private static int byteLength(ClickHouseDataType type) { - int byteLen = 0; - switch (Objects.requireNonNull(type)) { - case Int8: - case UInt8: - byteLen = 1; - break; - case Int16: - case UInt16: - byteLen = 2; - break; - case Int32: - case UInt32: - byteLen = 4; - break; - case Int64: - case UInt64: - byteLen = 8; - break; - default: - throw new IllegalArgumentException( - "Only native integer types are supported but we got: " + type.name()); - } - - return byteLen; - } - - protected final ClickHouseDataType innerType; - protected final int byteLen; - protected final Object reference; - - protected ClickHouseBitmap(Object bitmap, ClickHouseDataType innerType) { - this.innerType = innerType; - this.byteLen = byteLength(innerType); - this.reference = Objects.requireNonNull(bitmap); - } - - public abstract int getCardinality(); - - public long getLongCardinality() { - return getCardinality(); - } - - public abstract void serialize(ByteBuffer buffer); - - public abstract int serializedSizeInBytes(); - - public long serializedSizeInBytesAsLong() { - return serializedSizeInBytes(); - } - - public abstract int[] toIntArray(); - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj == null || getClass() != obj.getClass()) { - return false; - } - - ClickHouseBitmap b = (ClickHouseBitmap) obj; - return Objects.equals(innerType, b.innerType) && Objects.equals(byteLen, b.byteLen) - && Objects.equals(reference, b.reference); - } - - @Override - public int hashCode() { - return Objects.hash(innerType, byteLen, reference); - } - - public long[] toLongArray() { - int[] ints = toIntArray(); - int len = ints.length; - long[] longs = new long[len]; - for (int i = 0; i < len; i++) { - longs[i] = ints[i]; - } - return longs; - } - - /** - * Serialize the bitmap into a flipped ByteBuffer. - * - * @return flipped byte buffer - */ - public ByteBuffer toByteBuffer() { - ByteBuffer buf; - - int cardinality = getCardinality(); - if (cardinality <= 32) { - buf = newBuffer(2 + byteLen * cardinality); - buf.put((byte) 0); - buf.put((byte) cardinality); - if (byteLen == 1) { - for (int v : toIntArray()) { - buf.put((byte) v); - } - } else if (byteLen == 2) { - for (int v : toIntArray()) { - buf.putShort((short) v); - } - } else if (byteLen == 4) { - for (int v : toIntArray()) { - buf.putInt(v); - } - } else { // 64 - for (long v : toLongArray()) { - buf.putLong(v); - } - } - } else if (byteLen <= 4) { - int size = serializedSizeInBytes(); - int varIntSize = Utils.getVarIntSize(size); - - buf = newBuffer(1 + varIntSize + size); - buf.put((byte) 1); - Utils.writeVarInt(size, buf); - serialize(buf); - } else { // 64 - // 1) deduct one to exclude the leading byte - boolean flag, see below: - // https://github.com/RoaringBitmap/RoaringBitmap/blob/0.9.9/RoaringBitmap/src/main/java/org/roaringbitmap/longlong/Roaring64NavigableMap.java#L1107 - // 2) add 4 bytes because CRoaring uses long to store count of 32-bit bitmaps, - // while Java uses int - see - // https://github.com/RoaringBitmap/CRoaring/blob/v0.2.66/cpp/roaring64map.hh#L597 - long size = serializedSizeInBytesAsLong() - 1 + 4; - int varIntSize = Utils.getVarLongSize(size); - // TODO add serialize(DataOutput) to handle more - int intSize = (int) size; - buf = newBuffer(1 + varIntSize + intSize); - buf.put((byte) 1); - Utils.writeVarInt(intSize, buf); - serialize(buf); - } - - return (ByteBuffer) ((Buffer) buf).flip(); - } - - public byte[] toBytes() { - ByteBuffer buffer = toByteBuffer(); - byte[] bytes = new byte[buffer.remaining()]; - buffer.get(bytes); - return bytes; - } - - public String toBitmapBuildExpression() { - StringBuilder sb = new StringBuilder(); - - if (byteLen <= 4) { - for (int v : toIntArray()) { - sb.append(',').append("to").append(innerType.name()).append('(').append(v).append(')'); - } - } else { - for (long v : toLongArray()) { - sb.append(',').append("to").append(innerType.name()).append('(').append(v).append(')'); - } - } - - if (sb.length() > 0) { - sb.deleteCharAt(0).insert(0, '[').append(']'); - } else { - sb.append("cast([] as Array(").append(innerType.name()).append(')').append(')'); - } - - return sb.insert(0, "bitmapBuild(").append(')').toString(); - } - - public Object unwrap() { - return this.reference; - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseBlockChecksum.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseBlockChecksum.java deleted file mode 100644 index 06ec67c28..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseBlockChecksum.java +++ /dev/null @@ -1,62 +0,0 @@ -package ru.yandex.clickhouse.util; - -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -public class ClickHouseBlockChecksum { - private final long first; - private final long second; - - public ClickHouseBlockChecksum(long first, long second) { - this.first = first; - this.second = second; - } - - public static ClickHouseBlockChecksum fromBytes(byte[] checksum) { - ByteBuffer buffer = ByteBuffer.allocate(16).order(ByteOrder.LITTLE_ENDIAN).put(checksum); - ((Buffer) buffer).flip(); - return new ClickHouseBlockChecksum(buffer.getLong(), buffer.getLong()); - } - - public static ClickHouseBlockChecksum calculateForBlock(byte magic, int compressedSizeWithHeader, int uncompressedSize, byte[] data, int length) { - ByteBuffer buffer = ByteBuffer.allocate(compressedSizeWithHeader).order(ByteOrder.LITTLE_ENDIAN).put((byte)magic).putInt(compressedSizeWithHeader) - .putInt(uncompressedSize).put(data, 0, length); - ((Buffer) buffer).flip(); - return calculate(buffer.array()); - } - - public byte[] asBytes(){ - ByteBuffer buffer = ByteBuffer.allocate(16).order(ByteOrder.LITTLE_ENDIAN).putLong(first).putLong(second); - ((Buffer) buffer).flip(); - return buffer.array(); - } - - private static ClickHouseBlockChecksum calculate(byte[] data) { - long[] sum = ClickHouseCityHash.cityHash128(data, 0, data.length); - return new ClickHouseBlockChecksum(sum[0], sum[1]); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - ClickHouseBlockChecksum that = (ClickHouseBlockChecksum) o; - - if (first != that.first) return false; - return second == that.second; - } - - @Override - public int hashCode() { - int result = (int) (first ^ (first >>> 32)); - result = 31 * result + (int) (second ^ (second >>> 32)); - return result; - } - - @Override - public String toString() { - return "{" + first + ", " + second + '}'; - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseCityHash.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseCityHash.java deleted file mode 100644 index 35c18fbea..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseCityHash.java +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright 2017 YANDEX LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Copyright (C) 2012 tamtam180 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package ru.yandex.clickhouse.util; - -/** - * @author tamtam180 - kirscheless at gmail.com - * @see http://google-opensource.blogspot.jp/2011/04/introducing-cityhash.html - * @see http://code.google.com/p/cityhash/ - * - */ - -/** - * NOTE: The code is modified to be compatible with CityHash128 used in ClickHouse - */ -public class ClickHouseCityHash { - - private static final long k0 = 0xc3a5c85c97cb3127L; - private static final long k1 = 0xb492b66fbe98f273L; - private static final long k2 = 0x9ae16a3b2f90404fL; - private static final long k3 = 0xc949d7c7509e6557L; - - private static long toLongLE(byte[] b, int i) { - return (((long)b[i+7] << 56) + - ((long)(b[i+6] & 255) << 48) + - ((long)(b[i+5] & 255) << 40) + - ((long)(b[i+4] & 255) << 32) + - ((long)(b[i+3] & 255) << 24) + - ((b[i+2] & 255) << 16) + - ((b[i+1] & 255) << 8) + - ((b[i+0] & 255) << 0)); - } - private static long toIntLE(byte[] b, int i) { - return (((b[i+3] & 255L) << 24) + ((b[i+2] & 255L) << 16) + ((b[i+1] & 255L) << 8) + ((b[i+0] & 255L) << 0)); - } - - private static long fetch64(byte[] s, int pos) { - return toLongLE(s, pos); - } - - private static long fetch32(byte[] s, int pos) { - return toIntLE(s, pos); - } - - private static int staticCastToInt(byte b) { - return b & 0xFF; - } - - private static long rotate(long val, int shift) { - return shift == 0 ? val : (val >>> shift) | (val << (64 - shift)); - } - - private static long rotateByAtLeast1(long val, int shift) { - return (val >>> shift) | (val << (64 - shift)); - } - - private static long shiftMix(long val) { - return val ^ (val >>> 47); - } - - private static final long kMul = 0x9ddfea08eb382d69L; - private static long hash128to64(long u, long v) { - long a = (u ^ v) * kMul; - a ^= (a >>> 47); - long b = (v ^ a) * kMul; - b ^= (b >>> 47); - b *= kMul; - return b; - } - - private static long hashLen16(long u, long v) { - return hash128to64(u, v); - } - - private static long hashLen0to16(byte[] s, int pos, int len) { - if (len > 8) { - long a = fetch64(s, pos + 0); - long b = fetch64(s, pos + len - 8); - return hashLen16(a, rotateByAtLeast1(b + len, len)) ^ b; - } - if (len >= 4) { - long a = fetch32(s, pos + 0); - return hashLen16((a << 3) + len, fetch32(s, pos + len - 4)); - } - if (len > 0) { - byte a = s[pos + 0]; - byte b = s[pos + (len >>> 1)]; - byte c = s[pos + len - 1]; - int y = staticCastToInt(a) + (staticCastToInt(b) << 8); - int z = len + (staticCastToInt(c) << 2); - return shiftMix(y * k2 ^ z * k3) * k2; - } - return k2; - } - - - private static long[] weakHashLen32WithSeeds( - long w, long x, long y, long z, - long a, long b) { - - a += w; - b = rotate(b + a + z, 21); - long c = a; - a += x; - a += y; - b += rotate(a, 44); - return new long[]{ a + z, b + c }; - } - - private static long[] weakHashLen32WithSeeds(byte[] s, int pos, long a, long b) { - return weakHashLen32WithSeeds( - fetch64(s, pos + 0), - fetch64(s, pos + 8), - fetch64(s, pos + 16), - fetch64(s, pos + 24), - a, - b - ); - } - - private static long[] cityMurmur(byte[] s, int pos, int len, long seed0, long seed1) { - - long a = seed0; - long b = seed1; - long c = 0; - long d = 0; - - int l = len - 16; - if (l <= 0) { - a = shiftMix(a * k1) * k1; - c = b * k1 + hashLen0to16(s, pos, len); - d = shiftMix(a + (len >= 8 ? fetch64(s, pos + 0) : c)); - } else { - - c = hashLen16(fetch64(s, pos + len - 8) + k1, a); - d = hashLen16(b + len, c + fetch64(s, pos + len - 16)); - a += d; - - do { - a ^= shiftMix(fetch64(s, pos + 0) * k1) * k1; - a *= k1; - b ^= a; - c ^= shiftMix(fetch64(s, pos + 8) * k1) * k1; - c *= k1; - d ^= c; - pos += 16; - l -= 16; - } while (l > 0); - } - - a = hashLen16(a, c); - b = hashLen16(d, b); - - return new long[]{ a ^ b, hashLen16(b, a) }; - } - - private static long[] cityHash128WithSeed(byte[] s, int pos, int len, long seed0, long seed1) { - if (len < 128) { - return cityMurmur(s, pos, len, seed0, seed1); - } - - long[] v = new long[2], w = new long[2]; - long x = seed0; - long y = seed1; - long z = k1 * len; - v[0] = rotate(y ^ k1, 49) * k1 + fetch64(s, pos); - v[1] = rotate(v[0], 42) * k1 + fetch64(s, pos + 8); - w[0] = rotate(y + z, 35) * k1 + x; - w[1] = rotate(x + fetch64(s, pos + 88), 53) * k1; - - // This is the same inner loop as CityHash64(), manually unrolled. - do { - x = rotate(x + y + v[0] + fetch64(s, pos + 16), 37) * k1; - y = rotate(y + v[1] + fetch64(s, pos + 48), 42) * k1; - - x ^= w[1]; - y ^= v[0] ; - - z = rotate(z ^ w[0], 33); - v = weakHashLen32WithSeeds(s, pos, v[1] * k1, x + w[0]); - w = weakHashLen32WithSeeds(s, pos + 32, z + w[1], y); - - { long swap = z; z = x; x = swap; } - pos += 64; - x = rotate(x + y + v[0] + fetch64(s, pos + 16), 37) * k1; - y = rotate(y + v[1] + fetch64(s, pos + 48), 42) * k1; - x ^= w[1]; - y ^= v[0]; - z = rotate(z ^ w[0], 33); - v = weakHashLen32WithSeeds(s, pos, v[1] * k1, x + w[0]); - w = weakHashLen32WithSeeds(s, pos + 32, z + w[1], y); - { long swap = z; z = x; x = swap; } - pos += 64; - len -= 128; - } while (len >= 128); - - y += rotate(w[0], 37) * k0 + z; - x += rotate(v[0] + z, 49) * k0; - - // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s. - for (int tail_done = 0; tail_done < len; ) { - tail_done += 32; - y = rotate(y - x, 42) * k0 + v[1]; - w[0] += fetch64(s, pos + len - tail_done + 16); - x = rotate(x, 49) * k0 + w[0]; - w[0] += v[0]; - v = weakHashLen32WithSeeds(s, pos + len - tail_done, v[0], v[1]); - } - - // At this point our 48 bytes of state should contain more than - // enough information for a strong 128-bit hash. We use two - // different 48-byte-to-8-byte hashes to get a 16-byte final result. - - x = hashLen16(x, v[0]); - y = hashLen16(y, w[0]); - - return new long[]{ - hashLen16(x + v[1], w[1]) + y, - hashLen16(x + w[1], y + v[1]) - }; - } - - static long[] cityHash128(byte[] s, int pos, int len) { - - if (len >= 16) { - return cityHash128WithSeed( - s, pos + 16, - len - 16, - fetch64(s, pos) ^ k3, - fetch64(s, pos + 8) - ); - } else if (len >= 8) { - return cityHash128WithSeed( - new byte[0], 0, 0, - fetch64(s, pos ) ^ (len * k0), - fetch64(s, pos + len -8) ^ k1 - ); - } else { - return cityHash128WithSeed(s, pos, len, k0, k1); - } - } - -} \ No newline at end of file diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseCookieStoreProvider.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseCookieStoreProvider.java deleted file mode 100644 index 921226f66..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseCookieStoreProvider.java +++ /dev/null @@ -1,29 +0,0 @@ -package ru.yandex.clickhouse.util; - -import org.apache.http.client.CookieStore; -import org.apache.http.impl.client.BasicCookieStore; -import ru.yandex.clickhouse.settings.ClickHouseProperties; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -public class ClickHouseCookieStoreProvider { - private static final Map cookieStoreMap = new ConcurrentHashMap<>(); - - public CookieStore getCookieStore(ClickHouseProperties properties) { - return hasValidProperties(properties) && properties.isUseSharedCookieStore() ? - cookieStoreMap.computeIfAbsent(getCookieStoreKey(properties), k -> new BasicCookieStore()) : - null; - } - - private boolean hasValidProperties(ClickHouseProperties properties) { - return properties != null - && !Utils.isNullOrEmptyString(properties.getHost()) - && properties.getPort() > 0 - && !Utils.isNullOrEmptyString(properties.getDatabase()); - } - - private String getCookieStoreKey(ClickHouseProperties properties) { - return String.format("%s:%s/%s", properties.getHost(), properties.getPort(), properties.getDatabase()); - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseHttpClientBuilder.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseHttpClientBuilder.java deleted file mode 100644 index 782d07896..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseHttpClientBuilder.java +++ /dev/null @@ -1,274 +0,0 @@ -package ru.yandex.clickhouse.util; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.security.KeyManagementException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.KeyManager; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; - -import org.apache.http.ConnectionReuseStrategy; -import org.apache.http.Header; -import org.apache.http.HttpHeaders; -import org.apache.http.HttpHost; -import org.apache.http.HttpResponse; -import org.apache.http.NoHttpResponseException; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.AuthCache; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.client.HttpRequestRetryHandler; -import org.apache.http.client.config.CookieSpecs; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.config.ConnectionConfig; -import org.apache.http.config.RegistryBuilder; -import org.apache.http.conn.socket.ConnectionSocketFactory; -import org.apache.http.conn.socket.PlainConnectionSocketFactory; -import org.apache.http.conn.ssl.NoopHostnameVerifier; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.impl.DefaultConnectionReuseStrategy; -import org.apache.http.impl.auth.BasicScheme; -import org.apache.http.impl.client.BasicAuthCache; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; -import org.apache.http.message.BasicHeader; -import org.apache.http.protocol.HttpContext; - -import ru.yandex.clickhouse.settings.ClickHouseProperties; -import ru.yandex.clickhouse.util.ssl.NonValidatingTrustManager; - -public class ClickHouseHttpClientBuilder { - - private static final ClickHouseCookieStoreProvider cookieStoreProvider = new ClickHouseCookieStoreProvider(); - private final ClickHouseProperties properties; - - public ClickHouseHttpClientBuilder(ClickHouseProperties properties) { - this.properties = properties; - } - - public CloseableHttpClient buildClient() throws Exception { - HttpClientBuilder builder = HttpClientBuilder.create() - .setConnectionManager(getConnectionManager()) - .setRetryHandler(getRequestRetryHandler()) - .setConnectionReuseStrategy(getConnectionReuseStrategy()) - .setDefaultConnectionConfig(getConnectionConfig()) - .setDefaultRequestConfig(getRequestConfig()) - .setDefaultHeaders(getDefaultHeaders()) - .setDefaultCredentialsProvider(getDefaultCredentialsProvider()) - .disableContentCompression() // gzip is not needed. Use lz4 when compress=1 - .setDefaultCookieStore(cookieStoreProvider.getCookieStore(properties)) - .disableRedirectHandling(); - - String clientName = properties != null ? properties.getClientName() : null; - if (!Utils.isNullOrEmptyString(clientName)) { - builder.setUserAgent(clientName); - } - - return builder.build(); - } - - private HttpRequestRetryHandler getRequestRetryHandler() { - final int maxRetries = properties.getMaxRetries(); - return new DefaultHttpRequestRetryHandler(maxRetries, false) { - @Override - public boolean retryRequest(IOException exception, int executionCount, HttpContext context) { - if (executionCount > maxRetries || context == null - || !Boolean.TRUE.equals(context.getAttribute("is_idempotent"))) { - return false; - } - - return (exception instanceof NoHttpResponseException) || super.retryRequest(exception, executionCount, context); - } - }; - } - - public static HttpClientContext createClientContext(ClickHouseProperties props) { - if (props == null - || !isConfigurationValidForAuth(props)) - { - return HttpClientContext.create(); - } - AuthCache authCache = new BasicAuthCache(); - BasicScheme basicAuth = new BasicScheme(); - authCache.put(getTargetHost(props), basicAuth); - HttpClientContext ctx = HttpClientContext.create(); - ctx.setAuthCache(authCache); - ctx.setCookieStore(cookieStoreProvider.getCookieStore(props)); - return ctx; - } - - private ConnectionReuseStrategy getConnectionReuseStrategy() { - return new DefaultConnectionReuseStrategy() { - @Override - public boolean keepAlive(HttpResponse httpResponse, HttpContext httpContext) { - if (httpResponse.getStatusLine().getStatusCode() != HttpURLConnection.HTTP_OK) { - return false; - } - return super.keepAlive(httpResponse, httpContext); - } - }; - } - - private PoolingHttpClientConnectionManager getConnectionManager() - throws CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException, IOException { - RegistryBuilder registry = RegistryBuilder.create() - .register("http", PlainConnectionSocketFactory.getSocketFactory()); - - if (properties.getSsl()) { - HostnameVerifier verifier = "strict".equals(properties.getSslMode()) ? SSLConnectionSocketFactory.getDefaultHostnameVerifier() : NoopHostnameVerifier.INSTANCE; - registry.register("https", new SSLConnectionSocketFactory(getSSLContext(), verifier)); - } - - //noinspection resource - PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager( - registry.build(), - null, - null, - new IpVersionPriorityResolver(), - properties.getTimeToLiveMillis(), - TimeUnit.MILLISECONDS - ); - - connectionManager.setValidateAfterInactivity(properties.getValidateAfterInactivityMillis()); - connectionManager.setDefaultMaxPerRoute(properties.getDefaultMaxPerRoute()); - connectionManager.setMaxTotal(properties.getMaxTotal()); - connectionManager.setDefaultConnectionConfig(getConnectionConfig()); - return connectionManager; - } - - private ConnectionConfig getConnectionConfig() { - return ConnectionConfig.custom() - .setBufferSize(properties.getApacheBufferSize()) - .build(); - } - - private RequestConfig getRequestConfig() { - return RequestConfig.custom() - .setSocketTimeout(properties.getSocketTimeout()) - .setConnectTimeout(properties.getConnectionTimeout()) - .setConnectionRequestTimeout(properties.getConnectionTimeout()) - .setCookieSpec(CookieSpecs.STANDARD) - .build(); - } - - private Collection

getDefaultHeaders() { - List
headers = new ArrayList<>(); - if (properties.getHttpAuthorization() != null) { - headers.add(new BasicHeader(HttpHeaders.AUTHORIZATION, properties.getHttpAuthorization())); - } - return headers; - } - - private SSLContext getSSLContext() - throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, KeyManagementException { - SSLContext ctx = SSLContext.getInstance("TLS"); - TrustManager[] tms = null; - KeyManager[] kms = null; - SecureRandom sr = null; - - if(properties.getSslMode().equals("none")) { - tms = new TrustManager[]{new NonValidatingTrustManager()}; - kms = new KeyManager[]{}; - sr = new SecureRandom(); - } else if (properties.getSslMode().equals("strict")) { - if (!properties.getSslRootCertificate().isEmpty()) { - TrustManagerFactory tmf = TrustManagerFactory - .getInstance(TrustManagerFactory.getDefaultAlgorithm()); - - tmf.init(getKeyStore()); - tms = tmf.getTrustManagers(); - kms = new KeyManager[]{}; - sr = new SecureRandom(); - } - } else { - throw new IllegalArgumentException("unknown ssl mode '"+ properties.getSslMode() +"'"); - } - - ctx.init(kms, tms, sr); - return ctx; - } - - private KeyStore getKeyStore() - throws NoSuchAlgorithmException, IOException, CertificateException, KeyStoreException { - KeyStore ks; - try { - ks = KeyStore.getInstance("jks"); - ks.load(null, null); // needed to initialize the key store - } catch (KeyStoreException e) { - throw new NoSuchAlgorithmException("jks KeyStore not available"); - } - - InputStream caInputStream; - try { - caInputStream = new FileInputStream(properties.getSslRootCertificate()); - } catch (FileNotFoundException ex) { - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - caInputStream = cl.getResourceAsStream(properties.getSslRootCertificate()); - if(caInputStream == null) { - throw new IOException( - "Could not open SSL/TLS root certificate file '" + properties - .getSslRootCertificate() + "'", ex); - } - } - - try { - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - Iterator caIt = cf.generateCertificates(caInputStream).iterator(); - for (int i = 0; caIt.hasNext(); i++) { - ks.setCertificateEntry("cert" + i, caIt.next()); - } - return ks; - } finally { - caInputStream.close(); - } - } - - private CredentialsProvider getDefaultCredentialsProvider() { - if (!isConfigurationValidForAuth(properties)) { - return null; - } - HttpHost targetHost = getTargetHost(properties); - CredentialsProvider credsProvider = new BasicCredentialsProvider(); - credsProvider.setCredentials( - new AuthScope(targetHost.getHostName(), targetHost.getPort()), - new UsernamePasswordCredentials( - properties.getUser() != null ? properties.getUser() : "default", - properties.getPassword() != null ? properties.getPassword() : "")); - return credsProvider; - } - - private static HttpHost getTargetHost(ClickHouseProperties props) { - return new HttpHost( - props.getHost(), - props.getPort(), - props.getSsl() ? "https" : "http"); - } - - private static boolean isConfigurationValidForAuth(ClickHouseProperties props) { - return props.getHost() != null - && props.getHttpAuthorization() == null - && (props.getUser() != null || props.getPassword() != null); - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseLZ4OutputStream.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseLZ4OutputStream.java deleted file mode 100644 index 2ccd3ec62..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseLZ4OutputStream.java +++ /dev/null @@ -1,91 +0,0 @@ -package ru.yandex.clickhouse.util; - -import net.jpountz.lz4.LZ4Compressor; -import net.jpountz.lz4.LZ4Factory; -import ru.yandex.clickhouse.response.ClickHouseLZ4Stream; - -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -public class ClickHouseLZ4OutputStream extends OutputStream { - private static final LZ4Factory factory = LZ4Factory.fastestInstance(); - private final DataOutputStream dataWrapper; - - private final LZ4Compressor compressor; - private final byte[] currentBlock; - private final byte[] compressedBlock; - - private int pointer; - - public ClickHouseLZ4OutputStream(OutputStream stream, int maxCompressBlockSize) { - dataWrapper = new DataOutputStream(stream); - compressor = factory.fastCompressor(); - currentBlock = new byte[maxCompressBlockSize]; - compressedBlock = new byte[compressor.maxCompressedLength(maxCompressBlockSize)]; - } - - /** - * @return Location of pointer in the byte buffer (bytes not yet flushed) - */ - public int position() { - return pointer; - } - - @Override - public void write(int b) throws IOException { - currentBlock[pointer] = (byte) b; - pointer++; - - if (pointer == currentBlock.length) { - writeBlock(); - } - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - if (b == null) { - throw new NullPointerException(); - } else if (off < 0 || len < 0 || len > b.length - off) { - throw new IndexOutOfBoundsException(); - } else if (len == 0) { - return; - } - - int blockSize = currentBlock.length; - int rest = blockSize - pointer; - while (len >= rest) { - System.arraycopy(b, off, currentBlock, pointer, rest); - pointer += rest; - writeBlock(); - off += rest; - len -= rest; - rest = blockSize; - } - - if (len > 0) { - System.arraycopy(b, off, currentBlock, pointer, len); - pointer += len; - } - } - - @Override - public void flush() throws IOException { - if (pointer != 0) { - writeBlock(); - } - dataWrapper.flush(); - } - - private void writeBlock() throws IOException { - int compressed = compressor.compress(currentBlock, 0, pointer, compressedBlock, 0); - ClickHouseBlockChecksum checksum = ClickHouseBlockChecksum.calculateForBlock((byte) ClickHouseLZ4Stream.MAGIC, - compressed + 9, pointer, compressedBlock, compressed); - dataWrapper.write(checksum.asBytes()); - dataWrapper.writeByte(ClickHouseLZ4Stream.MAGIC); - Utils.writeInt(dataWrapper, compressed + 9); // compressed size with header - Utils.writeInt(dataWrapper, pointer); // uncompressed size - dataWrapper.write(compressedBlock, 0, compressed); - pointer = 0; - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseRowBinaryInputStream.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseRowBinaryInputStream.java deleted file mode 100644 index 6bebec710..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseRowBinaryInputStream.java +++ /dev/null @@ -1,460 +0,0 @@ -package ru.yandex.clickhouse.util; - -import static ru.yandex.clickhouse.util.ClickHouseRowBinaryStream.MILLIS_IN_DAY; - -import java.io.Closeable; -import java.io.DataInputStream; -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.charset.StandardCharsets; -import java.sql.Date; -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.TimeZone; -import java.util.UUID; -import java.util.concurrent.TimeUnit; -import ru.yandex.clickhouse.domain.ClickHouseDataType; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; -import ru.yandex.clickhouse.settings.ClickHouseProperties; - -public class ClickHouseRowBinaryInputStream implements Closeable { - private final DataInputStream in; - private final TimeZone timeZone; - - private final List columns; - - public ClickHouseRowBinaryInputStream(InputStream is, TimeZone timeZone, ClickHouseProperties properties) - throws IOException { - this(is, timeZone, properties, false); - } - - public ClickHouseRowBinaryInputStream(InputStream is, TimeZone timeZone, ClickHouseProperties properties, - boolean hasColumnInfo) throws IOException { - this.in = new DataInputStream(is); - if (properties.isUseServerTimeZoneForDates()) { - this.timeZone = timeZone; - } else { - this.timeZone = TimeZone.getDefault(); - } - - if (hasColumnInfo) { - // read names and types - int count = Utils.readVarInt(in); - String[][] columns = new String[count][2]; - for (int i = 0; i < 2; i++) { - for (int j = 0; j < count; j++) { - columns[j][i] = readString(); - } - } - - List list = new ArrayList<>(count); - for (int i = 0; i < count; i++) { - String[] column = columns[i]; - list.add(ClickHouseColumnInfo.parse(column[1], column[0], timeZone)); - } - this.columns = Collections.unmodifiableList(list); - } else { - this.columns = Collections.emptyList(); - } - } - - public List getColumns() { - return this.columns; - } - - public int readUnsignedLeb128() throws IOException { - return Utils.readUnsignedLeb128(in); - } - - public void readBytes(byte[] bytes) throws IOException { - readBytes(bytes, 0, bytes.length); - } - - public void readBytes(byte[] bytes, int offset, int length) throws IOException { - while (length > 0) { - int read = in.read(bytes, offset, length); - if (read == -1) { - throw new EOFException(); - } - offset += read; - length -= read; - } - } - - public int readByte() throws IOException { - return in.readUnsignedByte(); - } - - public boolean readIsNull() throws IOException { - int value = readByte(); - - Utils.checkArgument(value, 0, 1); - - return value != 0; - } - - public String readString() throws IOException { - int length = Utils.readUnsignedLeb128(in); - byte[] bytes = new byte[length]; - readBytes(bytes); - - return new String(bytes, StandardCharsets.UTF_8); - } - - public String readFixedString(int length) throws IOException { - byte[] bytes = new byte[length]; - readBytes(bytes); - - return new String(bytes, StandardCharsets.UTF_8); - } - - public boolean readBoolean() throws IOException { - int value = readUInt8(); - Utils.checkArgument(value, 0, 1); - return value != 0; - } - - public short readUInt8() throws IOException { - return (short) in.readUnsignedByte(); - } - - /** - * Warning: the result is negative in Java if UInt8 > 0x7f - * - * @return next UInt8 value as a byte - * @throws IOException in case if an I/O error occurs - */ - public byte readUInt8AsByte() throws IOException { - return in.readByte(); - } - - public byte readInt8() throws IOException { - return in.readByte(); - } - - public int readUInt16() throws IOException { - return Utils.readUnsignedShort(in); - } - - /** - * Warning: the result is negative in Java if UInt16 > 0x7fff - * - * @return next UInt16 value as a short - * @throws IOException in case if an I/O error occurs - */ - public short readUInt16AsShort() throws IOException { - return (short) Utils.readUnsignedShort(in); - } - - public short readInt16() throws IOException { - return (short) Utils.readUnsignedShort(in); - } - - public long readUInt32() throws IOException { - return ((long) Utils.readInt(in)) & 0xffffffffL; - } - - /** - * Warning: the result is negative in Java if UInt32 > 0x7fffffff - * - * @return next UInt32 value as an int - * @throws IOException in case if an I/O error occurs - */ - public int readUInt32AsInt() throws IOException { - return Utils.readInt(in); - } - - public int readInt32() throws IOException { - return Utils.readInt(in); - } - - /** - * Warning: the result is negative in Java if UInt64 > 0x7fffffffffffffff - * - * @return next UInt64 value as a long - * @throws IOException in case if an I/O error occurs - */ - public long readUInt64AsLong() throws IOException { - return Utils.readLong(in); - } - - public BigInteger readUInt64() throws IOException { - return Utils.readLongAsBigInteger(in); - } - - public long readInt64() throws IOException { - return Utils.readLong(in); - } - - public BigInteger readInt128() throws IOException { - return Utils.readBigInteger(in, 16); - } - - public BigInteger writeUInt128() throws IOException { - return Utils.readBigInteger(in, 16); - } - - public BigInteger writeInt256() throws IOException { - return Utils.readBigInteger(in, 32); - } - - public BigInteger writeUInt256() throws IOException { - return Utils.readBigInteger(in, 32); - } - - public Timestamp readDateTime() throws IOException { - long value = readUInt32(); - return new Timestamp(TimeUnit.SECONDS.toMillis(value)); - } - - public Date readDate() throws IOException { - int daysSinceEpoch = readUInt16(); - long utcMillis = daysSinceEpoch * MILLIS_IN_DAY; - long localMillis = utcMillis - timeZone.getOffset(utcMillis); - return new Date(localMillis); - } - - public float readFloat32() throws IOException { - return Float.intBitsToFloat(Utils.readInt(in)); - } - - public double readFloat64() throws IOException { - return Double.longBitsToDouble(Utils.readLong(in)); - } - - public Date[] readDateArray() throws IOException { - int length = Utils.readUnsignedLeb128(in); - Date[] dates = new Date[length]; - for (int i = 0; i < length; i++) { - dates[i] = readDate(); - } - - return dates; - } - - public Timestamp[] readDateTimeArray() throws IOException { - int length = Utils.readUnsignedLeb128(in); - Timestamp[] dates = new Timestamp[length]; - for (int i = 0; i < length; i++) { - dates[i] = readDateTime(); - } - - return dates; - } - - public String[] readStringArray() throws IOException { - int length = Utils.readUnsignedLeb128(in); - String[] strings = new String[length]; - for (int i = 0; i < length; i++) { - strings[i] = readString(); - } - - return strings; - } - - public byte[] readInt8Array() throws IOException { - int length = Utils.readUnsignedLeb128(in); - byte[] bytes = new byte[length]; - for (int i = 0; i < length; i++) { - bytes[i] = readInt8(); - } - - return bytes; - } - - public byte[] readUInt8ArrayAsByte() throws IOException { - int length = Utils.readUnsignedLeb128(in); - byte[] bytes = new byte[length]; - for (int i = 0; i < length; i++) { - bytes[i] = readUInt8AsByte(); - } - - return bytes; - } - - public short[] readUInt8Array() throws IOException { - int length = Utils.readUnsignedLeb128(in); - short[] shorts = new short[length]; - for (int i = 0; i < length; i++) { - shorts[i] = readUInt8(); - } - - return shorts; - } - - public short[] readInt16Array() throws IOException { - int length = Utils.readUnsignedLeb128(in); - short[] shorts = new short[length]; - for (int i = 0; i < length; i++) { - shorts[i] = readInt16(); - } - - return shorts; - } - - public short[] readUInt16ArrayAsShort() throws IOException { - int length = Utils.readUnsignedLeb128(in); - short[] shorts = new short[length]; - for (int i = 0; i < length; i++) { - shorts[i] = readUInt16AsShort(); - } - - return shorts; - } - - public int[] readUInt16Array() throws IOException { - int length = Utils.readUnsignedLeb128(in); - int[] ints = new int[length]; - for (int i = 0; i < length; i++) { - ints[i] = readUInt16(); - } - - return ints; - } - - public int[] readInt32Array() throws IOException { - int length = Utils.readUnsignedLeb128(in); - int[] ints = new int[length]; - for (int i = 0; i < length; i++) { - ints[i] = readInt32(); - } - - return ints; - } - - public int[] readUInt32ArrayAsInt() throws IOException { - int length = Utils.readUnsignedLeb128(in); - int[] ints = new int[length]; - for (int i = 0; i < length; i++) { - ints[i] = readUInt32AsInt(); - } - - return ints; - } - - public long[] readUInt32Array() throws IOException { - int length = Utils.readUnsignedLeb128(in); - long[] longs = new long[length]; - for (int i = 0; i < length; i++) { - longs[i] = readUInt32(); - } - - return longs; - } - - public long[] readInt64Array() throws IOException { - int length = Utils.readUnsignedLeb128(in); - long[] longs = new long[length]; - for (int i = 0; i < length; i++) { - longs[i] = readInt64(); - } - - return longs; - } - - public long[] readUInt64ArrayAsLong() throws IOException { - int length = Utils.readUnsignedLeb128(in); - long[] longs = new long[length]; - for (int i = 0; i < length; i++) { - longs[i] = readUInt64AsLong(); - } - - return longs; - } - - public BigInteger[] readUInt64Array() throws IOException { - int length = Utils.readUnsignedLeb128(in); - BigInteger[] bigs = new BigInteger[length]; - for (int i = 0; i < length; i++) { - bigs[i] = readUInt64(); - } - - return bigs; - } - - public float[] readFloat32Array() throws IOException { - int length = Utils.readUnsignedLeb128(in); - float[] floats = new float[length]; - for (int i = 0; i < length; i++) { - floats[i] = readFloat32(); - } - - return floats; - } - - public double[] readFloat64Array() throws IOException { - int length = Utils.readUnsignedLeb128(in); - double[] doubles = new double[length]; - for (int i = 0; i < length; i++) { - doubles[i] = readFloat64(); - } - - return doubles; - } - - public UUID readUUID() throws IOException { - byte[] array = new byte[16]; - readBytes(array); - - ByteBuffer bb = ByteBuffer.wrap(array).order(ByteOrder.LITTLE_ENDIAN); - return new UUID(bb.getLong(), bb.getLong()); - } - - public UUID[] readUUIDArray() throws IOException { - int length = Utils.readUnsignedLeb128(in); - UUID[] uuids = new UUID[length]; - for (int i = 0; i < length; i++) { - uuids[i] = readUUID(); - } - - return uuids; - } - - public BigDecimal readDecimal32(int scale) throws IOException { - int i = Utils.readInt(in); - BigDecimal ten = BigDecimal.valueOf(10); - BigDecimal s = ten.pow(scale); - return new BigDecimal(i).divide(s); - } - - public BigDecimal readDecimal64(int scale) throws IOException { - long i = Utils.readLong(in); - BigDecimal ten = BigDecimal.valueOf(10); - BigDecimal s = ten.pow(scale); - return new BigDecimal(i).divide(s); - } - - public BigDecimal readDecimal128(int scale) throws IOException { - byte[] r = new byte[16]; - for (int i = r.length; i > 0; i--) { - r[i - 1] = (byte) in.readUnsignedByte(); - } - BigDecimal res = new BigDecimal(new BigInteger(r), scale); - return res; - } - - public BigDecimal readDecimal256(int scale) throws IOException { - byte[] r = new byte[32]; - for (int i = r.length; i > 0; i--) { - r[i - 1] = (byte) in.readUnsignedByte(); - } - BigDecimal res = new BigDecimal(new BigInteger(r), scale); - return res; - } - - public ClickHouseBitmap readBitmap(ClickHouseDataType innerType) throws IOException { - return ClickHouseBitmap.deserialize(in, innerType); - } - - @Override - public void close() throws IOException { - in.close(); - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseRowBinaryStream.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseRowBinaryStream.java deleted file mode 100644 index f5afcc0a0..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseRowBinaryStream.java +++ /dev/null @@ -1,393 +0,0 @@ -package ru.yandex.clickhouse.util; - -import ru.yandex.clickhouse.settings.ClickHouseProperties; - -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.Channels; -import java.nio.charset.StandardCharsets; -import java.util.Date; -import java.util.Objects; -import java.util.TimeZone; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -/** - * @author Dmitry Andreev - */ -public class ClickHouseRowBinaryStream { - - private static final int U_INT8_MAX = (1 << 8) - 1; - private static final int U_INT16_MAX = (1 << 16) - 1; - private static final long U_INT32_MAX = (1L << 32) - 1; - protected static final long MILLIS_IN_DAY = TimeUnit.DAYS.toMillis(1); - - private final DataOutputStream out; - private final TimeZone timeZone; - - public ClickHouseRowBinaryStream(OutputStream outputStream, TimeZone timeZone, ClickHouseProperties properties) { - this.out = new DataOutputStream(outputStream); - if (properties.isUseServerTimeZoneForDates()) { - this.timeZone = timeZone; - } else { - this.timeZone = TimeZone.getDefault(); - } - } - - public void writeUnsignedLeb128(int value) throws IOException { - Utils.checkArgument(value, 0); - - int remaining = value >>> 7; - while (remaining != 0) { - out.write((byte) ((value & 0x7f) | 0x80)); - value = remaining; - remaining >>>= 7; - } - out.write((byte) (value & 0x7f)); - } - - /** - * Dangerous. Can only be used for rare optimizations, for example when the string is written in parts - * without prior concatenation. The size of the string in bytes must be passed through writeUnsignedLeb128. - * - * @param bytes byte array will be written into stream - * @throws IOException in case if an I/O error occurs - */ - public void writeBytes(byte[] bytes) throws IOException { - out.write(bytes); - } - - public void writeByteBuffer(ByteBuffer buffer) throws IOException { - Channels.newChannel(out).write(buffer); - } - - /** - * @param bytes byte array will be written into stream - * @param offset the starting offset in {@code bytes} to start writing at - * @param len the length of the {@code bytes}, starting from {@code offset} - * @throws IOException in case if an I/O error occurs - */ - public void writeBytes(byte[] bytes, int offset, int len) throws IOException { - out.write(bytes, offset, len); - } - - /** - * Dangerous. Can only be used for rare optimizations, for example when the string is written in parts - * without prior concatenation. The size of the string in bytes must be passed through writeUnsignedLeb128. - * - * @param b byte value - * @throws IOException in case if an I/O error occurs - */ - public void writeByte(byte b) throws IOException { - out.write(b); - } - - public void writeString(String string) throws IOException { - byte[] bytes = Objects.requireNonNull(string).getBytes(StandardCharsets.UTF_8); - writeUnsignedLeb128(bytes.length); - out.write(bytes); - } - - /** - * Write string with predefined proper length. - * - * @param string Input string - * @throws IOException in case if an I/O error occurs - */ - public void writeFixedString(String string) throws IOException { - byte[] bytes = Objects.requireNonNull(string).getBytes(StandardCharsets.UTF_8); - out.write(bytes); - } - - /** - * Write string with any length, but it will be corrected, cut or extended to len - * - * @param string Input string - * @param len Length of FixedString - * @throws IOException in case if an I/O error occurs - */ - public void writeFixedString(String string, Integer len) throws IOException { - byte[] bytes = Objects.requireNonNull(string).getBytes(StandardCharsets.UTF_8); - Integer bl = bytes.length; - out.write(bytes, 0, Math.min(len, bl)); - for (int i = 0; i < len - bl; i++) { - out.write(0); - } - } - - public void writeUInt8(boolean value) throws IOException { - out.writeByte(value ? 1 : 0); - } - - public void writeUInt8(int value) throws IOException { - Utils.checkArgument(value, 0, U_INT8_MAX); - byte unsigned = (byte) (value & 0xffL); - out.writeByte(unsigned); - } - - public void writeInt8(int value) throws IOException { - Utils.checkArgument(value, Byte.MIN_VALUE, Byte.MAX_VALUE); - out.writeByte(value); - } - - public void writeInt8(byte value) throws IOException { - out.writeByte(value); - } - - public void writeInt16(int value) throws IOException { - Utils.checkArgument(value, Short.MIN_VALUE, Short.MAX_VALUE); - Utils.writeShort(out, value); - } - - public void writeInt16(short value) throws IOException { - Utils.writeShort(out, value); - } - - public void writeUInt16(int value) throws IOException { - Utils.checkArgument(value, 0, U_INT16_MAX); - short unsigned = (short) (value & 0xffffL); - Utils.writeShort(out, unsigned); - } - - public void writeInt32(int value) throws IOException { - Utils.writeInt(out, value); - } - - public void writeUInt32(long value) throws IOException { - Utils.checkArgument(value, 0, U_INT32_MAX); - int unsigned = (int) (value & 0xffffffffL); - Utils.writeInt(out, unsigned); - } - - public void writeInt64(long value) throws IOException { - Utils.writeLong(out, value); - } - - public void writeUInt64(long value) throws IOException { - Utils.writeLong(out, value); - } - - public void writeUInt64(BigInteger value) throws IOException { - Utils.checkArgument(value, BigInteger.ZERO); - Utils.writeLong(out, value.longValue()); - } - - public void writeInt128(BigInteger value) throws IOException { - Utils.writeBigInteger(out, value, 16); - } - - public void writeUInt128(BigInteger value) throws IOException { - Utils.checkArgument(value, BigInteger.ZERO); - Utils.writeBigInteger(out, value, 16); - } - - public void writeInt256(BigInteger value) throws IOException { - Utils.writeBigInteger(out, value, 32); - } - - public void writeUInt256(BigInteger value) throws IOException { - Utils.checkArgument(value, BigInteger.ZERO); - Utils.writeBigInteger(out, value, 32); - } - - public void writeDateTime(Date date) throws IOException { - Objects.requireNonNull(date); - writeUInt32(TimeUnit.MILLISECONDS.toSeconds(date.getTime())); - } - - public void writeDate(Date date) throws IOException { - Objects.requireNonNull(date); - long localMillis = date.getTime() + timeZone.getOffset(date.getTime()); - int daysSinceEpoch = (int) (localMillis / MILLIS_IN_DAY); - writeUInt16(daysSinceEpoch); - } - - public void writeFloat32(float value) throws IOException { - Utils.writeInt(out, Float.floatToIntBits(value)); - } - - public void writeFloat64(double value) throws IOException { - Utils.writeLong(out, Double.doubleToLongBits(value)); - } - - public void writeBigInteger(BigInteger value, int byteLength) throws IOException { - byte empty = value.signum() == -1 ? (byte) 0xFF : 0x00; - byte[] bytes = value.toByteArray(); - for (int i = bytes.length - 1; i >= 0; i--) { - out.write(bytes[i]); - } - - for (int i = byteLength - bytes.length; i > 0; i--) { - out.write(empty); - } - } - - public void writeDecimal128(BigDecimal num, int scale) throws IOException { - writeBigInteger(Utils.toBigInteger(num, scale), 16); - } - - public void writeDecimal256(BigDecimal num, int scale) throws IOException { - writeBigInteger(Utils.toBigInteger(num, scale), 32); - } - - public void writeDecimal64(BigDecimal num, int scale) throws IOException { - Utils.writeLong(out, Utils.toBigInteger(num, scale).longValue()); - } - - public void writeDecimal32(BigDecimal num, int scale) throws IOException { - Utils.writeInt(out, Utils.toBigInteger(num, scale).intValue()); - } - - public void writeDateArray(Date[] dates) throws IOException { - writeUnsignedLeb128(Objects.requireNonNull(dates).length); - for (Date date : dates) { - writeDate(date); - } - } - - public void writeDateTimeArray(Date[] dates) throws IOException { - writeUnsignedLeb128(Objects.requireNonNull(dates).length); - for (Date date : dates) { - writeDateTime(date); - } - } - - public void writeStringArray(String[] strings) throws IOException { - writeUnsignedLeb128(Objects.requireNonNull(strings).length); - for (String el : strings) { - writeString(el); - } - } - - public void writeInt8Array(byte[] bytes) throws IOException { - writeUnsignedLeb128(Objects.requireNonNull(bytes).length); - for (byte b : bytes) { - writeInt8(b); - } - } - - public void writeInt8Array(int[] ints) throws IOException { - writeUnsignedLeb128(Objects.requireNonNull(ints).length); - for (int i : ints) { - writeInt8(i); - } - } - - public void writeUInt8Array(int[] ints) throws IOException { - writeUnsignedLeb128(Objects.requireNonNull(ints).length); - for (int i : ints) { - writeUInt8(i); - } - } - - public void writeInt16Array(short[] shorts) throws IOException { - writeUnsignedLeb128(Objects.requireNonNull(shorts).length); - for (short s : shorts) { - writeInt16(s); - } - } - - public void writeUInt16Array(int[] ints) throws IOException { - writeUnsignedLeb128(Objects.requireNonNull(ints).length); - for (int i : ints) { - writeUInt16(i); - } - } - - public void writeInt32Array(int[] ints) throws IOException { - writeUnsignedLeb128(Objects.requireNonNull(ints).length); - for (int i : ints) { - writeInt32(i); - } - } - - public void writeUInt32Array(long[] longs) throws IOException { - writeUnsignedLeb128(Objects.requireNonNull(longs).length); - for (long l : longs) { - writeUInt32(l); - } - } - - public void writeInt64Array(long[] longs) throws IOException { - writeUnsignedLeb128(Objects.requireNonNull(longs).length); - for (long l : longs) { - writeInt64(l); - } - } - - public void writeUInt64Array(long[] longs) throws IOException { - writeUnsignedLeb128(Objects.requireNonNull(longs).length); - for (long l : longs) { - writeUInt64(l); - } - } - - public void writeUInt64Array(BigInteger[] longs) throws IOException { - writeUnsignedLeb128(Objects.requireNonNull(longs).length); - for (BigInteger l : longs) { - writeUInt64(l); - } - } - - public void writeFloat32Array(float[] floats) throws IOException { - writeUnsignedLeb128(Objects.requireNonNull(floats).length); - for (float f : floats) { - writeFloat32(f); - } - } - - public void writeFloat64Array(double[] doubles) throws IOException { - writeUnsignedLeb128(Objects.requireNonNull(doubles).length); - for (double d : doubles) { - writeFloat64(d); - } - } - - /** - * Write a marker indicating if value is nullable or not. - *

- * E.g., to write Nullable(Int32): - * - *

-     *     void writeNullableInt32(Integer value) {
-     *         if (value == null) {
-     *             markNextNullable(true);
-     *         } else {
-     *             markNextNullable(false);
-     *             writeInt32(value);
-     *         }
-     *     }
-     * 
- * - * @param isNullable if it's true, 1 will be written otherwise 0 - * @throws IOException in case if an I/O error occurs - */ - public void markNextNullable(boolean isNullable) throws IOException { - writeByte(isNullable ? (byte) 1 : (byte) 0); - } - - public void writeUUID(UUID uuid) throws IOException { - Objects.requireNonNull(uuid); - ByteBuffer bb = ByteBuffer.wrap(new byte[16]).order(ByteOrder.LITTLE_ENDIAN); - bb.putLong(uuid.getMostSignificantBits()); - bb.putLong(uuid.getLeastSignificantBits()); - byte[] array = bb.array(); - this.writeBytes(array); - } - - public void writeUUIDArray(UUID[] uuids) throws IOException { - writeUnsignedLeb128(Objects.requireNonNull(uuids).length); - for (UUID uuid : uuids) { - writeUUID(uuid); - } - } - - public void writeBitmap(ClickHouseBitmap rb) throws IOException { - this.writeByteBuffer(Objects.requireNonNull(rb).toByteBuffer()); - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseStreamCallback.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseStreamCallback.java deleted file mode 100644 index cbe3b1149..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseStreamCallback.java +++ /dev/null @@ -1,10 +0,0 @@ -package ru.yandex.clickhouse.util; - -import java.io.IOException; - -/** - * @author Dmitry Andreev - */ -public interface ClickHouseStreamCallback { - void writeTo(ClickHouseRowBinaryStream stream) throws IOException; -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseStreamHttpEntity.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseStreamHttpEntity.java deleted file mode 100644 index fc6607458..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseStreamHttpEntity.java +++ /dev/null @@ -1,52 +0,0 @@ -package ru.yandex.clickhouse.util; - -import org.apache.http.entity.AbstractHttpEntity; -import ru.yandex.clickhouse.settings.ClickHouseProperties; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Objects; -import java.util.TimeZone; - -/** - * @author Dmitry Andreev - */ -public class ClickHouseStreamHttpEntity extends AbstractHttpEntity { - - private final ClickHouseStreamCallback callback; - private final TimeZone timeZone; - private final ClickHouseProperties properties; - - public ClickHouseStreamHttpEntity(ClickHouseStreamCallback callback, TimeZone timeZone, ClickHouseProperties properties) { - this.timeZone = timeZone; - this.callback = Objects.requireNonNull(callback); - this.properties = properties; - } - - @Override - public boolean isRepeatable() { - return true; - } - - @Override - public long getContentLength() { - return -1; - } - - @Override - public InputStream getContent() throws IOException, UnsupportedOperationException { - return null; - } - - @Override - public void writeTo(OutputStream out) throws IOException { - ClickHouseRowBinaryStream stream = new ClickHouseRowBinaryStream(out, timeZone, properties); - callback.writeTo(stream); - } - - @Override - public boolean isStreaming() { - return false; - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseValueFormatter.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseValueFormatter.java deleted file mode 100644 index a6bac9928..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseValueFormatter.java +++ /dev/null @@ -1,309 +0,0 @@ -package ru.yandex.clickhouse.util; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Array; -import java.sql.Date; -import java.sql.Time; -import java.sql.Timestamp; -import java.text.SimpleDateFormat; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetDateTime; -import java.time.OffsetTime; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.util.Collection; -import java.util.Map; -import java.util.TimeZone; -import java.util.UUID; - -import ru.yandex.clickhouse.ClickHouseUtil; -import ru.yandex.clickhouse.domain.ClickHouseDataType; - -public final class ClickHouseValueFormatter { - - public static final String NULL_MARKER = "\\N"; - - private static final DateTimeFormatter DATE_FORMATTER = - DateTimeFormatter.ofPattern("yyyy-MM-dd"); - private static final DateTimeFormatter DATE_TIME_FORMATTER = - DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - private static final DateTimeFormatter TIME_FORMATTER = - DateTimeFormatter.ofPattern("HH:mm:ss"); - - private static ThreadLocal dateFormat = new ThreadLocal() { - @Override - protected SimpleDateFormat initialValue() { - return new SimpleDateFormat("yyyy-MM-dd"); - } - }; - - private static ThreadLocal dateTimeFormat = new ThreadLocal() { - @Override - protected SimpleDateFormat initialValue() { - return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - } - }; - - public static String formatBytes(byte[] bytes) { - if (bytes == null) { - return null; - } - char[] hexArray = - {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; - char[] hexChars = new char[bytes.length * 4]; - int v; - for ( int j = 0; j < bytes.length; j++ ) { - v = bytes[j] & 0xFF; - hexChars[j * 4] = '\\'; - hexChars[j * 4 + 1] = 'x'; - hexChars[j * 4 + 2] = hexArray[v/16]; - hexChars[j * 4 + 3] = hexArray[v%16]; - } - return new String(hexChars); - } - - public static String formatInt(int myInt) { - return Integer.toString(myInt); - } - - public static String formatDouble(double myDouble) { - return Double.toString(myDouble); - } - - public static String formatChar(char myChar) { - return Character.toString(myChar); - } - - public static String formatLong(long myLong) { - return Long.toString(myLong); - } - - public static String formatFloat(float myFloat) { - return Float.toString(myFloat); - } - - public static String formatBigDecimal(BigDecimal myBigDecimal) { - return myBigDecimal != null ? myBigDecimal.toPlainString() : NULL_MARKER; - } - - public static String formatShort(short myShort) { - return Short.toString(myShort); - } - - public static String formatString(String myString) { - return ClickHouseUtil.escape(myString); - } - - public static String formatNull() { - return NULL_MARKER; - } - - public static String formatByte(byte myByte) { - return Byte.toString(myByte); - } - - public static String formatBoolean(boolean myBoolean) { - return myBoolean ? "1" : "0"; - } - - public static String formatDate(Date date, TimeZone timeZone) { - SimpleDateFormat formatter = getDateFormat(); - formatter.setTimeZone(timeZone); - return formatter.format(date); - } - - public static String formatTime(Time time, TimeZone timeZone) { - return TIME_FORMATTER.format( - Instant.ofEpochMilli(time.getTime()) - .atZone(timeZone.toZoneId()) - .toLocalTime()); - // getDateTimeFormat().setTimeZone(timeZone); - // return getDateTimeFormat().format(time); - } - - public static String formatTimestamp(Timestamp time, TimeZone timeZone) { - SimpleDateFormat formatter = getDateTimeFormat(); - formatter.setTimeZone(timeZone); - StringBuilder formatted = new StringBuilder(formatter.format(time)); - // TODO implement a true prepared statement to format according to parameter type - if (time != null && time.getNanos() % 1000000 > 0) { - formatted.append('.').append(time.getNanos()); - } - return formatted.toString(); - } - - public static String formatUUID(UUID x) { - return x.toString(); - } - - public static String formatBigInteger(BigInteger x) { - return x.toString(); - } - - public static String formatLocalDate(LocalDate x) { - return DATE_FORMATTER.format(x); - } - - public static String formatLocalDateTime(LocalDateTime x) { - return DATE_TIME_FORMATTER.format(x); - } - - /** - * Formats a {@link LocalTime} as "HH:mm:ss". There isn't any - * dedicated ClickHouse data type for times, so this is the most - * straightforward thing to do. It would be wrong for the JDBC driver to - * construct an artificial {@link ClickHouseDataType#DateTime DateTime} - * representation using a dummy date, e.g. 1970-01-01. - * - * @param x - * a {@link LocalTime} parameter - * @return {@code x} formatted as "HH:mm:ss" - */ - public static String formatLocalTime(LocalTime x) { - return TIME_FORMATTER.format(x); - } - - public static String formatOffsetTime(OffsetTime x) { - return DateTimeFormatter.ISO_OFFSET_TIME.format(x); - } - - public static String formatOffsetDateTime(OffsetDateTime x, TimeZone timeZone) { - return DATE_TIME_FORMATTER - .withZone(timeZone.toZoneId()) - .format(x); - } - - public static String formatZonedDateTime(ZonedDateTime x, TimeZone timeZone) { - return DATE_TIME_FORMATTER - .withZone(timeZone.toZoneId()) - .format(x); - } - - public static String formatInstant(Instant x, TimeZone timeZone) { - return DATE_TIME_FORMATTER - .withZone(timeZone.toZoneId()) - .format(x); - } - - public static String formatBitmap(ClickHouseBitmap bitmap) { - return bitmap.toBitmapBuildExpression(); - } - - public static String formatMap(Map map, TimeZone dateTimeZone, TimeZone dateTimeTimeZone) { - StringBuilder sb = new StringBuilder(); - for (Map.Entry e : map.entrySet()) { - Object key = e.getKey(); - Object value = e.getValue(); - sb.append(','); - - if (key instanceof String) { - sb.append('\'').append(formatString((String) key)).append('\''); - } else { - sb.append(formatObject(key, dateTimeZone, dateTimeTimeZone)); - } - - sb.append(':'); - - if (value instanceof String) { - sb.append('\'').append(formatString((String) value)).append('\''); - } else { - sb.append(formatObject(value, dateTimeZone, dateTimeTimeZone)); - } - } - if (sb.length() > 0) { - sb.deleteCharAt(0); - } - return sb.insert(0, '{').append('}').toString(); - } - - public static String formatObject(Object x, TimeZone dateTimeZone, - TimeZone dateTimeTimeZone) - { - if (x == null) { - return null; - } - if (x instanceof Byte) { - return formatInt(((Byte) x).intValue()); - } else if (x instanceof String) { - return formatString((String) x); - } else if (x instanceof BigDecimal) { - return formatBigDecimal((BigDecimal) x); - } else if (x instanceof Short) { - return formatShort(((Short) x).shortValue()); - } else if (x instanceof Integer) { - return formatInt(((Integer) x).intValue()); - } else if (x instanceof Long) { - return formatLong(((Long) x).longValue()); - } else if (x instanceof Float) { - return formatFloat(((Float) x).floatValue()); - } else if (x instanceof Double) { - return formatDouble(((Double) x).doubleValue()); - } else if (x instanceof byte[]) { - return formatBytes((byte[]) x); - } else if (x instanceof Date) { - return formatDate((Date) x, dateTimeZone); - } else if (x instanceof LocalDate) { - return formatLocalDate((LocalDate) x); - } else if (x instanceof Time) { - return formatTime((Time) x, dateTimeTimeZone); - } else if (x instanceof LocalTime) { - return formatLocalTime((LocalTime) x); - } else if (x instanceof OffsetTime) { - return formatOffsetTime((OffsetTime) x); - } else if (x instanceof Timestamp) { - return formatTimestamp((Timestamp) x, dateTimeTimeZone); - } else if (x instanceof LocalDateTime) { - return formatLocalDateTime((LocalDateTime) x); - } else if (x instanceof OffsetDateTime) { - return formatOffsetDateTime((OffsetDateTime) x, dateTimeTimeZone); - } else if (x instanceof ZonedDateTime) { - return formatZonedDateTime((ZonedDateTime) x, dateTimeTimeZone); - } else if (x instanceof Boolean) { - return formatBoolean(((Boolean) x).booleanValue()); - } else if (x instanceof UUID) { - return formatUUID((UUID) x); - } else if (x instanceof BigInteger) { - return formatBigInteger((BigInteger) x); - } else if (x instanceof Collection) { - return ClickHouseArrayUtil.toString((Collection) x, dateTimeZone, dateTimeTimeZone); - } else if (x instanceof ClickHouseBitmap) { - return formatBitmap((ClickHouseBitmap) x); - } else if (x instanceof Map) { - return formatMap((Map) x, dateTimeZone, dateTimeTimeZone); - } else if (x.getClass().isArray()) { - return ClickHouseArrayUtil.arrayToString(x, dateTimeZone, dateTimeTimeZone); - } else { - return String.valueOf(x); - } - } - - public static boolean needsQuoting(Object o) { - if (o == null - || o instanceof Array - || o instanceof Boolean - || o instanceof Collection - // || o instanceof Iterable - || o instanceof Map - || o instanceof Number - || o.getClass().isArray() - || o instanceof ClickHouseBitmap) { - return false; - } - - return true; - } - - private static SimpleDateFormat getDateFormat() { - return dateFormat.get(); - } - - private static SimpleDateFormat getDateTimeFormat() { - return dateTimeFormat.get(); - } - - private ClickHouseValueFormatter() { /* NOP */ } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseVersionNumberUtil.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseVersionNumberUtil.java deleted file mode 100644 index f1d24c5a6..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseVersionNumberUtil.java +++ /dev/null @@ -1,62 +0,0 @@ -package ru.yandex.clickhouse.util; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Very simple version number parser. It is only needed for ClickHouse driver - * and database version numbers - * - * @deprecated As of release 0.3.2, replaced by - * {@link com.clickhouse.client.ClickHouseVersion} and it will be - * removed in 0.3.3 - */ -@Deprecated -public final class ClickHouseVersionNumberUtil { - - private static final Pattern VERSION_NUMBER_PATTERN = Pattern.compile("^\\s*(\\d+)\\.(\\d+).*"); - private static final Pattern NON_NUMBERIC_PATTERN = Pattern.compile("[^0-9.]"); - - public static int getMajorVersion(String versionNumber) { - Matcher m = VERSION_NUMBER_PATTERN.matcher(versionNumber); - return m.matches() ? Integer.parseInt(m.group(1)) : 0; - } - - public static int getMinorVersion(String versionNumber) { - Matcher m = VERSION_NUMBER_PATTERN.matcher(versionNumber); - return m.matches() ? Integer.parseInt(m.group(2)) : 0; - } - - public static int compare(String currentVersion, String targetVersion) { - if (currentVersion == null || targetVersion == null || currentVersion.isEmpty() || targetVersion.isEmpty()) { - throw new IllegalArgumentException("Both version cannot be null or empty"); - } - - currentVersion = NON_NUMBERIC_PATTERN.matcher(currentVersion).replaceAll(""); - targetVersion = NON_NUMBERIC_PATTERN.matcher(targetVersion).replaceAll(""); - if (currentVersion.equals(targetVersion)) { - return 0; - } - - String[] v1 = currentVersion.split("\\."); - String[] v2 = targetVersion.split("\\."); - - int result = 0; - for (int i = 0, len = Math.min(v1.length, v2.length); i < len; i++) { - int n1 = Integer.parseInt(v1[i]); - int n2 = Integer.parseInt(v2[i]); - - if (n1 == n2) { - continue; - } else { - result = n1 > n2 ? 1 : -1; - break; - } - } - - return result; - } - - private ClickHouseVersionNumberUtil() { - /* do not instantiate util */ } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/IpVersionPriorityResolver.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/IpVersionPriorityResolver.java deleted file mode 100644 index 8567e36c5..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/IpVersionPriorityResolver.java +++ /dev/null @@ -1,49 +0,0 @@ -package ru.yandex.clickhouse.util; - -import org.apache.http.conn.DnsResolver; -import org.apache.http.impl.conn.SystemDefaultDnsResolver; - -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; - - -public class IpVersionPriorityResolver implements DnsResolver { - - private DnsResolver defaultResolver = new SystemDefaultDnsResolver(); - - private boolean preferV6 = true; - - public IpVersionPriorityResolver() { - } - - public IpVersionPriorityResolver(boolean preferV6) { - this.preferV6 = preferV6; - } - - @Override - public InetAddress[] resolve(String host) throws UnknownHostException { - InetAddress[] resolve = defaultResolver.resolve(host); - Comparator comparator = new Comparator() { - @Override - public int compare(InetAddress o1, InetAddress o2) { - boolean o16 = o1 instanceof Inet6Address; - boolean o26 = o2 instanceof Inet6Address; - if (o16 == o26) return 0; - if (o16) return -1; - if (o26) return 1; - return 0; - } - }; - if (!preferV6) comparator = Collections.reverseOrder(comparator); - Arrays.sort(resolve, comparator); - return resolve; - } - - public void setPreferV6(boolean preferV6) { - this.preferV6 = preferV6; - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/LogProxy.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/LogProxy.java deleted file mode 100644 index 057c3ce5a..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/LogProxy.java +++ /dev/null @@ -1,68 +0,0 @@ -package ru.yandex.clickhouse.util; - -import java.lang.reflect.Array; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.Arrays; - -import com.clickhouse.client.logging.Logger; -import com.clickhouse.client.logging.LoggerFactory; - - -public class LogProxy implements InvocationHandler { - - private static final Logger log = LoggerFactory.getLogger(LogProxy.class); - - private final T object; - private final Class clazz; - - public static T wrap(Class interfaceClass, T object) { - T[] wrapper = (T[]) Array.newInstance(interfaceClass, 1); - wrapper[0] = object; - log.trace(() -> { - LogProxy proxy = new LogProxy(interfaceClass, object); - wrapper[0] = proxy.getProxy(); - return "Proxy enabled for class: " + interfaceClass.getName(); - }); - - return wrapper[0]; - } - - private LogProxy(Class interfaceClass, T object) { - if (!interfaceClass.isInterface()) { - throw new IllegalStateException("Class " + interfaceClass.getName() + " is not an interface"); - } - clazz = interfaceClass; - this.object = object; - } - - @SuppressWarnings("unchecked") - public T getProxy() { - //xnoinspection x - // unchecked - return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, this); - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - String msg = - "Call class: " + object.getClass().getName() + - "\nMethod: " + method.getName() + - "\nObject: " + object + - "\nArgs: " + Arrays.toString(args) + - "\nInvoke result: "; - try { - final Object invokeResult = method.invoke(object, args); - msg += invokeResult; - return invokeResult; - } catch (InvocationTargetException e) { - msg += e.getMessage(); - throw e.getTargetException(); - } finally { - msg = "==== ClickHouse JDBC trace begin ====\n" + msg + "\n==== ClickHouse JDBC trace end ===="; - log.trace(msg); - } - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/Logger.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/Logger.java deleted file mode 100644 index 29de5a9bf..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/Logger.java +++ /dev/null @@ -1,59 +0,0 @@ -package ru.yandex.clickhouse.util; - -import java.sql.DriverManager; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.logging.Level; - -/** - * Simple logger. - */ -public class Logger { - - private static Level currentLevel = Level.FINE; // todo configuration - - private final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - - private final String key; - - private Logger(String key) { - this.key = key; - } - - public static Logger logger(String key) { - return new Logger(key); - } - - public static Logger of(Class clazz) { - return new Logger(clazz.getSimpleName()); - } - - public static Logger of(Object object) { - return new Logger(object.getClass().getSimpleName()); - } - - public void info(String message) { - log(message, Level.INFO); - } - - public void debug(String message) { - log(message, Level.FINE); - } - - public void warn(String message) { - log(message, Level.WARNING); - } - - public void error(String message) { - log(message, Level.SEVERE); - } - - public synchronized void log(String message, Level level) { - if (level.intValue() >= currentLevel.intValue()) { - String str = String.format("%s <%s> %s: %s", DATE_FORMAT.format(new Date()), level.getName(), key, message); - DriverManager.println(str); - } - } - -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/Utils.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/Utils.java deleted file mode 100644 index f05cc974e..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/Utils.java +++ /dev/null @@ -1,409 +0,0 @@ -package ru.yandex.clickhouse.util; - -import java.io.ByteArrayOutputStream; -import java.io.DataInput; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -public class Utils { - private static final int BUF_SIZE = 0x1000; // 4K - private static final Map, Class> classToPrimitive; - - static { - Map, Class> map = new HashMap<>(); - map.put(Boolean.class, boolean.class); - map.put(Byte.class, byte.class); - map.put(Character.class, char.class); - map.put(Double.class, double.class); - map.put(Float.class, float.class); - map.put(Integer.class, int.class); - map.put(Long.class, long.class); - map.put(Short.class, short.class); - map.put(Void.class, void.class); - - classToPrimitive = Collections.unmodifiableMap(map); - } - - public static Class unwrap(Class type) { - @SuppressWarnings("unchecked") - Class unwrapped = (Class) classToPrimitive.get(Objects.requireNonNull(type)); - return (unwrapped == null) ? type : unwrapped; - } - - public static Map mapOf(Object... kvps) { - Map map = new LinkedHashMap<>(); - - for (int i = 0, len = kvps.length; i < len; i += 2) { - map.put(kvps[i], kvps[i + 1]); - } - - return Collections.unmodifiableMap(map); - } - - public static List listOf(Object... values) { - List list = new LinkedList<>(); - - for (int i = 0, len = values.length; i < len; i++) { - list.add(values[i]); - } - - return Collections.unmodifiableList(list); - } - - public static String toString(InputStream in) throws IOException { - return new String(toByteArray(in), StandardCharsets.UTF_8); - } - - public static byte[] toByteArray(InputStream in) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - copy(in, out); - return out.toByteArray(); - } - - public static long copy(InputStream from, OutputStream to) throws IOException { - byte[] buf = new byte[BUF_SIZE]; - long total = 0; - while (true) { - int r = from.read(buf); - if (r == -1) { - break; - } - to.write(buf, 0, r); - total += r; - } - return total; - } - - public static boolean isNullOrEmptyString(String str) { - return str == null || str.isEmpty(); - } - - public static void checkArgument(byte[] value, int length) { - if (value.length > length) { - throw new IllegalArgumentException( - new StringBuilder().append("Given byte array should NOT greater than ").append(length).toString()); - } - } - - public static void checkArgument(int value, int minValue) { - if (value < minValue) { - throw new IllegalArgumentException(new StringBuilder().append("Given value(").append(value) - .append(") should NOT less than ").append(minValue).toString()); - } - } - - public static void checkArgument(long value, long minValue) { - if (value < minValue) { - throw new IllegalArgumentException(new StringBuilder().append("Given value(").append(value) - .append(") should NOT less than ").append(minValue).toString()); - } - } - - public static void checkArgument(int value, int minValue, int maxValue) { - if (value < minValue || value > maxValue) { - throw new IllegalArgumentException(new StringBuilder().append("Given value(").append(value) - .append(") should between ").append(minValue).append(" and ").append(maxValue).toString()); - } - } - - public static void checkArgument(long value, long minValue, long maxValue) { - if (value < minValue || value > maxValue) { - throw new IllegalArgumentException(new StringBuilder().append("Given value(").append(value) - .append(") should between ").append(minValue).append(" and ").append(maxValue).toString()); - } - } - - public static void checkArgument(BigInteger value, BigInteger minValue) { - if (value.compareTo(minValue) < 0) { - throw new IllegalArgumentException(new StringBuilder().append("Given value(").append(value) - .append(") should greater than ").append(minValue).toString()); - } - } - - public static void checkArgument(BigInteger value, BigInteger minValue, BigInteger maxValue) { - if (value.compareTo(minValue) < 0 || value.compareTo(maxValue) > 0) { - throw new IllegalArgumentException(new StringBuilder().append("Given value(").append(value) - .append(") should between ").append(minValue).append(" and ").append(maxValue).toString()); - } - } - - public static void readFully(DataInputStream in, byte[] b) throws IOException { - readFully(in, b, 0, b.length); - } - - public static void readFully(DataInputStream in, byte[] b, int off, int len) throws IOException { - Objects.requireNonNull(in); - Objects.requireNonNull(b); - if (len < 0 || off < 0) { - throw new IndexOutOfBoundsException(String.format("length (%s) and offset (%s) cannot be negative", len, off)); - } - int end = off + len; - if (end < off || end > b.length) { - throw new IndexOutOfBoundsException(String.format("offset (%s) should less than length (%s) and buffer length (%s)", off, len, b.length)); - } - - int total = 0; - while (total < len) { - int result = in.read(b, off + total, len - total); - if (result == -1) { - break; - } - total += result; - } - - if (total != len) { - throw new EOFException( - "reached end of stream after reading " + total + " bytes; " + len + " bytes expected"); - } - } - - public static int readUnsignedShort(DataInputStream inputStream) throws IOException { - byte b1 = (byte) inputStream.readUnsignedByte(); - byte b2 = (byte) inputStream.readUnsignedByte(); - - return (b2 & 0xFF) << 8 | (b1 & 0xFF); - } - - public static int readInt(DataInputStream inputStream) throws IOException { - byte b1 = (byte) inputStream.readUnsignedByte(); - byte b2 = (byte) inputStream.readUnsignedByte(); - byte b3 = (byte) inputStream.readUnsignedByte(); - byte b4 = (byte) inputStream.readUnsignedByte(); - - return b4 << 24 | (b3 & 0xFF) << 16 | (b2 & 0xFF) << 8 | (b1 & 0xFF); - } - - public static long readLong(DataInputStream inputStream) throws IOException { - byte b1 = (byte) inputStream.readUnsignedByte(); - byte b2 = (byte) inputStream.readUnsignedByte(); - byte b3 = (byte) inputStream.readUnsignedByte(); - byte b4 = (byte) inputStream.readUnsignedByte(); - byte b5 = (byte) inputStream.readUnsignedByte(); - byte b6 = (byte) inputStream.readUnsignedByte(); - byte b7 = (byte) inputStream.readUnsignedByte(); - byte b8 = (byte) inputStream.readUnsignedByte(); - - return (b8 & 0xFFL) << 56 - | (b7 & 0xFFL) << 48 - | (b6 & 0xFFL) << 40 - | (b5 & 0xFFL) << 32 - | (b4 & 0xFFL) << 24 - | (b3 & 0xFFL) << 16 - | (b2 & 0xFFL) << 8 - | (b1 & 0xFFL); - } - - public static BigInteger readLongAsBigInteger(DataInputStream inputStream) throws IOException { - byte b1 = (byte) inputStream.readUnsignedByte(); - byte b2 = (byte) inputStream.readUnsignedByte(); - byte b3 = (byte) inputStream.readUnsignedByte(); - byte b4 = (byte) inputStream.readUnsignedByte(); - byte b5 = (byte) inputStream.readUnsignedByte(); - byte b6 = (byte) inputStream.readUnsignedByte(); - byte b7 = (byte) inputStream.readUnsignedByte(); - byte b8 = (byte) inputStream.readUnsignedByte(); - - return new BigInteger(new byte[] { 0, b8, b7, b6, b5, b4, b3, b2, b1 }); - } - - public static int readUnsignedLeb128(DataInputStream inputStream) throws IOException { - int value = 0; - int read; - int count = 0; - do { - read = inputStream.readUnsignedByte() & 0xff; - value |= (read & 0x7f) << (count * 7); - count++; - } while (((read & 0x80) == 0x80) && count < 5); - - if ((read & 0x80) == 0x80) { - throw new IOException("invalid LEB128 sequence"); - } - return value; - } - - public static BigInteger readBigInteger(DataInputStream inputStream, int byteLength) throws IOException { - byte[] r = new byte[byteLength]; - for (int i = r.length; i > 0; i--) { - r[i - 1] = inputStream.readByte(); - } - - return new BigInteger(r); - } - - public static void writeShort(DataOutputStream outputStream, int value) throws IOException { - outputStream.write(0xFF & value); - outputStream.write(0xFF & (value >> 8)); - } - - public static void writeInt(DataOutputStream outputStream, int value) throws IOException { - outputStream.write(0xFF & value); - outputStream.write(0xFF & (value >> 8)); - outputStream.write(0xFF & (value >> 16)); - outputStream.write(0xFF & (value >> 24)); - } - - public static void writeLong(DataOutputStream outputStream, long value) throws IOException { - outputStream.write((int) (0xFF & value)); - outputStream.write((int) (0xFF & (value >> 8))); - outputStream.write((int) (0xFF & (value >> 16))); - outputStream.write((int) (0xFF & (value >> 24))); - outputStream.write((int) (0xFF & (value >> 32))); - outputStream.write((int) (0xFF & (value >> 40))); - outputStream.write((int) (0xFF & (value >> 48))); - outputStream.write((int) (0xFF & (value >> 56))); - } - - public static void writeBigInteger(DataOutputStream outputStream, BigInteger value, int byteLength) throws IOException { - byte empty = value.signum() == -1 ? (byte) 0xFF : 0x00; - byte[] bytes = value.toByteArray(); - for (int i = bytes.length - 1; i >= 0; i--) { - outputStream.writeByte(bytes[i]); - } - - // FIXME when the given (byte)length is less than bytes.length... - for (int i = byteLength - bytes.length; i > 0; i--) { - outputStream.writeByte(empty); - } - } - - public static int getVarIntSize(int value) { - int result = 0; - do { - result++; - value >>>= 7; - } while (value != 0); - - return result; - } - - public static int getVarLongSize(long value) { - int result = 0; - do { - result++; - value >>>= 7; - } while (value != 0); - - return result; - } - - public static void writeVarInt(int value, ByteBuffer buffer) { - while ((value & 0xFFFFFF80) != 0L) { - buffer.put((byte) ((value & 0x7F) | 0x80)); - value >>>= 7; - } - buffer.put((byte) (value & 0x7F)); - } - - public static int readVarInt(DataInput in) throws IOException { - int result = 0; - int shift = 0; - int b; - do { - if (shift >= 32) { - // Out of range - throw new IndexOutOfBoundsException("varint too long"); - } - // Get 7 bits from next byte - b = in.readUnsignedByte(); - result |= (b & 0x7F) << shift; - shift += 7; - } while ((b & 0x80) != 0); - - return result; - } - - public static int readVarInt(ByteBuffer buffer) { - int result = 0; - int shift = 0; - int b; - do { - if (shift >= 32) { - // Out of range - throw new IndexOutOfBoundsException("varint too long"); - } - // Get 7 bits from next byte - b = buffer.get(); - result |= (b & 0x7F) << shift; - shift += 7; - } while ((b & 0x80) != 0); - - return result; - } - - public static BigInteger toBigInteger(BigDecimal num, int scale) { - BigDecimal ten = BigDecimal.valueOf(10); - BigDecimal s = ten.pow(scale); - return num.multiply(s).toBigInteger(); - } - - public static boolean startsWithIgnoreCase(String haystack, String pattern) { - return haystack.substring(0, pattern.length()).equalsIgnoreCase(pattern); - } - - public static String retainUnquoted(String haystack, char quoteChar) { - StringBuilder sb = new StringBuilder(); - String[] split = splitWithoutEscaped(haystack, quoteChar, true); - for (int i = 0; i < split.length; i++) { - String s = split[i]; - if ((i & 1) == 0) { - sb.append(s); - } - } - return sb.toString(); - } - - /** - * Does not take into account escaped separators - * - * @param str the String to parse, may be null - * @param separatorChar the character used as the delimiter - * @param retainEmpty if it is true, result can contain empty strings - * @return string array - */ - private static String[] splitWithoutEscaped(String str, char separatorChar, boolean retainEmpty) { - int len = str.length(); - if (len == 0) { - return new String[0]; - } - List list = new ArrayList(); - int i = 0; - int start = 0; - boolean match = false; - while (i < len) { - if (str.charAt(i) == '\\') { - match = true; - i += 2; - } else if (str.charAt(i) == separatorChar) { - if (retainEmpty || match) { - list.add(str.substring(start, i)); - match = false; - } - start = ++i; - } else { - match = true; - i++; - } - } - if (retainEmpty || match) { - list.add(str.substring(start, i)); - } - return list.toArray(new String[0]); - } -} diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ssl/NonValidatingTrustManager.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ssl/NonValidatingTrustManager.java deleted file mode 100644 index 595d9eecc..000000000 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ssl/NonValidatingTrustManager.java +++ /dev/null @@ -1,20 +0,0 @@ -package ru.yandex.clickhouse.util.ssl; - -import java.security.cert.X509Certificate; -import javax.net.ssl.X509TrustManager; - -/** - * An insecure {@link javax.net.ssl.TrustManager}, that don't validate the certificate. - */ -public class NonValidatingTrustManager implements X509TrustManager { - - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } - - public void checkClientTrusted(X509Certificate[] certs, String authType) { - } - - public void checkServerTrusted(X509Certificate[] certs, String authType) { - } -} diff --git a/clickhouse-jdbc/src/main/java9/module-info.java b/clickhouse-jdbc/src/main/java9/module-info.java index cc20b289d..fbe968b51 100644 --- a/clickhouse-jdbc/src/main/java9/module-info.java +++ b/clickhouse-jdbc/src/main/java9/module-info.java @@ -1,22 +1,13 @@ /** - * Declares ru.yandex.clickhouse module. + * Declares com.clickhouse module. */ module com.clickhouse.jdbc { exports com.clickhouse.jdbc; - exports ru.yandex.clickhouse; - exports ru.yandex.clickhouse.domain; - exports ru.yandex.clickhouse.except; - exports ru.yandex.clickhouse.response; - exports ru.yandex.clickhouse.settings; - exports ru.yandex.clickhouse.util; - requires java.sql; requires transitive com.clickhouse.client; requires transitive com.google.gson; - requires transitive org.apache.httpcomponents.httpclient; - requires transitive org.apache.httpcomponents.httpmime; requires transitive org.lz4.java; requires static java.logging; diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/BalancedClickhouseDataSourceTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/BalancedClickhouseDataSourceTest.java deleted file mode 100644 index d6cac407f..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/BalancedClickhouseDataSourceTest.java +++ /dev/null @@ -1,331 +0,0 @@ -package ru.yandex.clickhouse; - -import java.net.SocketException; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Arrays; - -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.except.ClickHouseException; -import ru.yandex.clickhouse.settings.ClickHouseProperties; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; - -public class BalancedClickhouseDataSourceTest extends JdbcIntegrationTest { - - private BalancedClickhouseDataSource dataSource; - private BalancedClickhouseDataSource doubleDataSource; - - @Test(groups = "unit") - public void testUrlSplit() throws Exception { - assertEquals(Arrays.asList("jdbc:clickhouse://localhost:1234/ppc"), - BalancedClickhouseDataSource.splitUrl("jdbc:clickhouse://localhost:1234/ppc")); - - assertEquals(Arrays.asList("jdbc:clickhouse://localhost:1234/ppc", - "jdbc:clickhouse://another.host.com:4321/ppc"), - BalancedClickhouseDataSource.splitUrl("jdbc:clickhouse://localhost:1234,another.host.com:4321/ppc")); - - assertEquals(Arrays.asList("jdbc:clickhouse://localhost:1234", "jdbc:clickhouse://another.host.com:4321"), - BalancedClickhouseDataSource.splitUrl("jdbc:clickhouse://localhost:1234,another.host.com:4321")); - - } - - - @Test(groups = "unit") - public void testUrlSplitValidHostName() throws Exception { - assertEquals(Arrays.asList("jdbc:clickhouse://localhost:1234", "jdbc:clickhouse://_0another-host.com:4321"), - BalancedClickhouseDataSource.splitUrl("jdbc:clickhouse://localhost:1234,_0another-host.com:4321")); - - } - - - @Test(groups = "unit", expectedExceptions = IllegalArgumentException.class) - public void testUrlSplitInvalidHostName() throws Exception { - BalancedClickhouseDataSource.splitUrl("jdbc:clickhouse://localhost:1234,_0ano^ther-host.com:4321"); - - } - - @BeforeClass(groups = "integration") - public void setUp() throws Exception { - dataSource = newBalancedDataSource(); - String address = getClickHouseHttpAddress(); - doubleDataSource = newBalancedDataSource(address, address); - } - - @Test(groups = "integration") - public void testSingleDatabaseConnection() throws Exception { - Connection connection = dataSource.getConnection(); - connection.createStatement().execute("CREATE DATABASE IF NOT EXISTS test"); - - connection.createStatement().execute("DROP TABLE IF EXISTS test.insert_test"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS test.insert_test (i Int32, s String) ENGINE = TinyLog" - ); - PreparedStatement statement = connection.prepareStatement("INSERT INTO test.insert_test (s, i) VALUES (?, ?)"); - statement.setString(1, "asd"); - statement.setInt(2, 42); - statement.execute(); - - - ResultSet rs = connection.createStatement().executeQuery("SELECT * from test.insert_test"); - rs.next(); - - assertEquals("asd", rs.getString("s")); - assertEquals(42, rs.getInt("i")); - } - - @Test(groups = "integration") - public void testDoubleDatabaseConnection() throws Exception { - Connection connection = doubleDataSource.getConnection(); - connection.createStatement().execute("CREATE DATABASE IF NOT EXISTS test"); - connection = doubleDataSource.getConnection(); - connection.createStatement().execute("DROP TABLE IF EXISTS test.insert_test"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS test.insert_test (i Int32, s String) ENGINE = TinyLog" - ); - - connection = doubleDataSource.getConnection(); - - PreparedStatement statement = connection.prepareStatement("INSERT INTO test.insert_test (s, i) VALUES (?, ?)"); - statement.setString(1, "asd"); - statement.setInt(2, 42); - statement.execute(); - - ResultSet rs = connection.createStatement().executeQuery("SELECT * from test.insert_test"); - rs.next(); - - assertEquals("asd", rs.getString("s")); - assertEquals(42, rs.getInt("i")); - - connection = doubleDataSource.getConnection(); - - statement = connection.prepareStatement("INSERT INTO test.insert_test (s, i) VALUES (?, ?)"); - statement.setString(1, "asd"); - statement.setInt(2, 42); - statement.execute(); - - rs = connection.createStatement().executeQuery("SELECT * from test.insert_test"); - rs.next(); - - assertEquals("asd", rs.getString("s")); - assertEquals(42, rs.getInt("i")); - - } - - @Test(groups = "integration") - public void testCorrectActualizationDatabaseConnection() throws Exception { - dataSource.actualize(); - Connection connection = dataSource.getConnection(); - } - - - @Test(groups = "integration") - public void testDisableConnection() throws Exception { - BalancedClickhouseDataSource badDatasource = newBalancedDataSource("not.existed.url:8123"); - badDatasource.actualize(); - try { - Connection connection = badDatasource.getConnection(); - fail(); - } catch (Exception e) { - // There is no enabled connections - } - } - - - @Test(groups = "integration") - public void testWorkWithEnabledUrl() throws Exception { - BalancedClickhouseDataSource halfDatasource = newBalancedDataSource("not.existed.url:8123", getClickHouseHttpAddress()); - - halfDatasource.actualize(); - Connection connection = halfDatasource.getConnection(); - - connection.createStatement().execute("CREATE DATABASE IF NOT EXISTS test"); - connection = halfDatasource.getConnection(); - connection.createStatement().execute("DROP TABLE IF EXISTS test.insert_test"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS test.insert_test (i Int32, s String) ENGINE = TinyLog" - ); - - connection = halfDatasource.getConnection(); - - PreparedStatement statement = connection.prepareStatement("INSERT INTO test.insert_test (s, i) VALUES (?, ?)"); - statement.setString(1, "asd"); - statement.setInt(2, 42); - statement.execute(); - - ResultSet rs = connection.createStatement().executeQuery("SELECT * from test.insert_test"); - rs.next(); - - assertEquals("asd", rs.getString("s")); - assertEquals(42, rs.getInt("i")); - - connection = halfDatasource.getConnection(); - - statement = connection.prepareStatement("INSERT INTO test.insert_test (s, i) VALUES (?, ?)"); - statement.setString(1, "asd"); - statement.setInt(2, 42); - statement.execute(); - - rs = connection.createStatement().executeQuery("SELECT * from test.insert_test"); - rs.next(); - - assertEquals("asd", rs.getString("s")); - assertEquals(42, rs.getInt("i")); - } - - @Test(groups = "integration") - public void testConstructWithClickHouseProperties() { - final ClickHouseProperties properties = new ClickHouseProperties(); - properties.setMaxThreads(3); - properties.setSocketTimeout(67890); - properties.setPassword("888888"); - //without connection parameters - String hostAddr = getClickHouseHttpAddress(); - String ipAddr = getClickHouseHttpAddress(true); - BalancedClickhouseDataSource dataSource = newBalancedDataSourceWithSuffix( - "click", properties, hostAddr, ipAddr); - ClickHouseProperties dataSourceProperties = dataSource.getProperties(); - assertEquals(dataSourceProperties.getMaxThreads().intValue(), 3); - assertEquals(dataSourceProperties.getSocketTimeout(), 67890); - assertEquals(dataSourceProperties.getPassword(), "888888"); - assertEquals(dataSourceProperties.getDatabase(), "click"); - assertEquals(2, dataSource.getAllClickhouseUrls().size()); - assertEquals(dataSource.getAllClickhouseUrls().get(0), "jdbc:clickhouse://" + hostAddr + "/click"); - assertEquals(dataSource.getAllClickhouseUrls().get(1), "jdbc:clickhouse://" + ipAddr + "/click"); - // with connection parameters - dataSource = newBalancedDataSourceWithSuffix( - "click?socket_timeout=12345&user=readonly", properties, hostAddr, ipAddr); - dataSourceProperties = dataSource.getProperties(); - assertEquals(dataSourceProperties.getMaxThreads().intValue(), 3); - assertEquals(dataSourceProperties.getSocketTimeout(), 12345); - assertEquals(dataSourceProperties.getUser(), "readonly"); - assertEquals(dataSourceProperties.getPassword(), "888888"); - assertEquals(dataSourceProperties.getDatabase(), "click"); - assertEquals(2, dataSource.getAllClickhouseUrls().size()); - assertEquals(dataSource.getAllClickhouseUrls().get(0), "jdbc:clickhouse://" + hostAddr + "/click?socket_timeout" + - "=12345&user=readonly"); - assertEquals(dataSource.getAllClickhouseUrls().get(1), "jdbc:clickhouse://" + ipAddr + "/click?socket_timeout=12345&user=readonly"); - } - - @Test(groups = "integration") - public void testConnectionWithAuth() throws SQLException { - final ClickHouseProperties properties = new ClickHouseProperties(); - final String hostAddr = getClickHouseHttpAddress(); - final String ipAddr = getClickHouseHttpAddress(true); - - final BalancedClickhouseDataSource dataSource0 = newBalancedDataSourceWithSuffix( - "default?user=foo&password=bar", - properties, - hostAddr, - ipAddr); - assertTrue(dataSource0.getConnection().createStatement().execute("SELECT 1")); - - final BalancedClickhouseDataSource dataSource1 = newBalancedDataSourceWithSuffix( - "default?user=foo", - properties, - hostAddr, - ipAddr); - // assertThrows(RuntimeException.class, - // () -> dataSource1.getConnection().createStatement().execute("SELECT 1")); - - - final BalancedClickhouseDataSource dataSource2 = newBalancedDataSourceWithSuffix( - "default?user=oof", - properties, - hostAddr, - ipAddr); - assertTrue(dataSource2.getConnection().createStatement().execute("SELECT 1")); - - properties.setUser("foo"); - properties.setPassword("bar"); - final BalancedClickhouseDataSource dataSource3 = newBalancedDataSourceWithSuffix( - "default", - properties, - hostAddr, - ipAddr); - assertTrue(dataSource3.getConnection().createStatement().execute("SELECT 1")); - - properties.setPassword("bar"); - final BalancedClickhouseDataSource dataSource4 = newBalancedDataSourceWithSuffix( - "default?user=oof", - properties, - hostAddr, - ipAddr); - // JDK 1.8 - // assertThrows(RuntimeException.class, - // () -> dataSource4.getConnection().createStatement().execute("SELECT 1")); - try { - dataSource4.getConnection().createStatement().execute("SELECT 1"); - fail(); - } catch (ClickHouseException e) { - // expected - } - - // it is not allowed to have query parameters per host - try { - newBalancedDataSourceWithSuffix( - "default?user=oof", - properties, - hostAddr + "/default?user=foo&password=bar", - ipAddr); - fail(); - } catch (IllegalArgumentException iae) { - // expected - } - - // the following behavior is quite unexpected, honestly - // but query params always have precedence over properties - final BalancedClickhouseDataSource dataSource5 = newBalancedDataSourceWithSuffix( - "default?user=foo&password=bar", - properties, - hostAddr, - ipAddr); - assertTrue( - dataSource5.getConnection("broken", "hacker").createStatement().execute("SELECT 1")); - - // now the other way round, also strange - final BalancedClickhouseDataSource dataSource6 = newBalancedDataSourceWithSuffix( - "default?user=broken&password=hacker", - properties, - hostAddr, - ipAddr); - // JDK 1.8 - // assertThrows(RuntimeException.class, - // () -> dataSource6.getConnection("foo", "bar").createStatement().execute("SELECT 1")); - try { - dataSource6.getConnection("foo", "bar").createStatement().execute("SELECT 1"); - fail(); - } catch (ClickHouseException e) { - // expected - } - } - - @Test(groups = "integration") - public void testIPv6() throws Exception { - // dedup is not supported at all :< - assertEquals(Arrays.asList("jdbc:clickhouse://[::1]:12345", "jdbc:clickhouse://[0:0:0:0:0:0:0:1]:12345"), - BalancedClickhouseDataSource.splitUrl("jdbc:clickhouse://[::1]:12345,[0:0:0:0:0:0:0:1]:12345")); - assertEquals(Arrays.asList("jdbc:clickhouse://[192:168:0:0:0:0:0:1]:12345", "jdbc:clickhouse://[192:168:0:0:0:0:0:2]:12345"), - BalancedClickhouseDataSource.splitUrl("jdbc:clickhouse://[192:168:0:0:0:0:0:1]:12345,[192:168:0:0:0:0:0:2]:12345")); - - ClickHouseProperties properties = new ClickHouseProperties(); - String hostAddr = getClickHouseHttpAddress(); - String ipAddr = getClickHouseHttpAddress("[::1]"); - - try { - assertEquals(newBalancedDataSource(properties, ipAddr).getConnection().getServerVersion(), - newBalancedDataSource(properties, hostAddr).getConnection().getServerVersion()); - } catch (SQLException e) { - // acceptable if IPv6 is not enabled - Throwable cause = e.getCause(); - assertTrue(cause instanceof SocketException); - assertTrue("Protocol family unavailable".equals(cause.getMessage()) || cause.getMessage().contains("Connection refused")); - } - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHouseConnectionTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHouseConnectionTest.java deleted file mode 100644 index 7fad97fd0..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHouseConnectionTest.java +++ /dev/null @@ -1,158 +0,0 @@ -package ru.yandex.clickhouse; - -import java.sql.Array; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.domain.ClickHouseDataType; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; - -public class ClickHouseConnectionTest extends JdbcIntegrationTest { - @Test(groups = "integration") - public void testGetSetCatalog() throws SQLException { - String address = getClickHouseHttpAddress(); - String url = "jdbc:clickhouse://" + address + "/default?option1=one%20two&option2=y"; - ClickHouseDataSource dataSource = newDataSource(url); - String[] dbNames = new String[]{"get_set_catalog_test1", "get_set_catalog_test2"}; - try { - ClickHouseConnectionImpl connection = (ClickHouseConnectionImpl) dataSource.getConnection(); - assertEquals(connection.getUrl(), url); - assertEquals(connection.getCatalog(), "default"); - assertEquals(connection.getProperties().getDatabase(), "default"); - - for (String db : dbNames) { - connection.createStatement().executeUpdate("CREATE DATABASE " + db); - connection.createStatement().executeUpdate( - "CREATE TABLE " + db + ".some_table ENGINE = TinyLog()" - + " AS SELECT 'value_" + db + "' AS field"); - - connection.setCatalog(db); - assertEquals(connection.getCatalog(), db); - assertEquals(connection.getProperties().getDatabase(), db); - assertEquals(connection.getUrl(), - "jdbc:clickhouse://" + address + "/" + db + "?option1=one%20two&option2=y"); - - ResultSet resultSet = connection.createStatement().executeQuery("SELECT field FROM some_table"); - assertTrue(resultSet.next()); - assertEquals(resultSet.getString(1), "value_" + db); - } - } finally { - Connection connection = dataSource.getConnection(); - for (String db : dbNames) { - connection.createStatement().executeUpdate("DROP DATABASE IF EXISTS " + db); - } - } - } - - @Test(groups = "integration") - public void testSetCatalogAndStatements() throws SQLException { - ClickHouseDataSource dataSource = newDataSource("default?option1=one%20two&option2=y"); - ClickHouseConnectionImpl connection = (ClickHouseConnectionImpl) dataSource.getConnection(); - final String sql = "SELECT currentDatabase()"; - - connection.setCatalog("system"); - Statement statement = connection.createStatement(); - connection.setCatalog("default"); - ResultSet resultSet = statement.executeQuery(sql); - resultSet.next(); - assertEquals(resultSet.getString(1), "system"); - - statement = connection.createStatement(); - resultSet = statement.executeQuery(sql); - resultSet.next(); - assertEquals(resultSet.getString(1), "default"); - } - - @Test(groups = "integration") - public void testSetCatalogAndPreparedStatements() throws SQLException { - ClickHouseDataSource dataSource = newDataSource("default?option1=one%20two&option2=y"); - ClickHouseConnectionImpl connection = (ClickHouseConnectionImpl) dataSource.getConnection(); - final String sql = "SELECT currentDatabase() FROM system.tables WHERE name = ? LIMIT 1"; - - connection.setCatalog("system"); - PreparedStatement statement = connection.prepareStatement(sql); - statement.setString(1, "tables"); - connection.setCatalog("default"); - ResultSet resultSet = statement.executeQuery(); - resultSet.next(); - assertEquals(resultSet.getString(1), "system"); - - statement = connection.prepareStatement(sql); - statement.setString(1, "tables"); - resultSet = statement.executeQuery(); - resultSet.next(); - assertEquals(resultSet.getString(1), "default"); - } - - @Test(groups = "integration") - public void testScrollableResultSetOnPreparedStatements() throws SQLException { - ClickHouseDataSource dataSource = newDataSource("default?option1=one%20two&option2=y"); - ClickHouseConnectionImpl connection = (ClickHouseConnectionImpl) dataSource.getConnection(); - final String sql = "SELECT currentDatabase() FROM system.tables WHERE name = ? LIMIT 1"; - - connection.setCatalog("system"); - PreparedStatement statement = connection.prepareStatement(sql,ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - statement.setString(1, "tables"); - connection.setCatalog("default"); - ResultSet resultSet = statement.executeQuery(); - resultSet.next(); - assertEquals(resultSet.getString(1), "system"); - assertEquals(resultSet.getType(), ResultSet.TYPE_FORWARD_ONLY); - - statement = connection.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); - statement.setString(1, "tables"); - resultSet = statement.executeQuery(); - resultSet.next(); - assertEquals(resultSet.getString(1), "default"); - assertEquals(resultSet.getType(), ResultSet.TYPE_SCROLL_INSENSITIVE); - resultSet.beforeFirst(); - resultSet.next(); - assertEquals(resultSet.getString(1), "default"); - } - - @Test(groups = "integration") - public void testScrollableResultSetOnStatements() throws SQLException { - ClickHouseDataSource dataSource = newDataSource("default?option1=one%20two&option2=y"); - ClickHouseConnectionImpl connection = (ClickHouseConnectionImpl) dataSource.getConnection(); - final String sql = "SELECT currentDatabase()"; - - connection.setCatalog("system"); - Statement statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - connection.setCatalog("default"); - ResultSet resultSet = statement.executeQuery(sql); - resultSet.next(); - assertEquals(resultSet.getString(1), "system"); - assertEquals(resultSet.getType(), ResultSet.TYPE_FORWARD_ONLY); - - statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); - resultSet = statement.executeQuery(sql); - resultSet.next(); - assertEquals(resultSet.getString(1), "default"); - assertEquals(resultSet.getType(), ResultSet.TYPE_SCROLL_INSENSITIVE); - resultSet.beforeFirst(); - resultSet.next(); - assertEquals(resultSet.getString(1), "default"); - } - - @Test(groups = "integration") - public void testCreateArrayOf() throws Exception { - // TODO: more - ClickHouseDataSource dataSource = newDataSource("default"); - ClickHouseConnectionImpl connection = (ClickHouseConnectionImpl) dataSource.getConnection(); - for (ClickHouseDataType dataType : ClickHouseDataType.values()) { - if (dataType == ClickHouseDataType.Array) { - continue; - } - Array a = connection.createArrayOf(dataType.name(), new Object[0]); - assertEquals(a.getBaseType(), dataType.getSqlType()); - assertEquals(a.getBaseTypeName(), dataType.name()); - } - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHouseDataSourceTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHouseDataSourceTest.java deleted file mode 100644 index ea0fa671b..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHouseDataSourceTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package ru.yandex.clickhouse; - -import org.testng.annotations.Test; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.fail; - -public class ClickHouseDataSourceTest { - @Test(groups = "unit") - public void testConstructor() throws Exception { - ClickHouseDataSource ds = new ClickHouseDataSource("jdbc:clickhouse://localhost:1234/ppc"); - assertEquals("localhost", ds.getHost()); - assertEquals(1234, ds.getPort()); - assertEquals("ppc", ds.getDatabase()); - - ClickHouseDataSource ds2 = new ClickHouseDataSource("jdbc:clickhouse://clh.company.com:5324"); - assertEquals("clh.company.com", ds2.getHost()); - assertEquals(5324, ds2.getPort()); - assertEquals("default", ds2.getDatabase()); - - try { - new ClickHouseDataSource(null); - fail("ClickHouseDataSource with null argument must fail"); - } catch (IllegalArgumentException ex) { - // pass, it's ok - } - - try { - new ClickHouseDataSource("jdbc:mysql://localhost:2342"); - fail("ClickHouseDataSource with incorrect args must fail"); - } catch (IllegalArgumentException ex) { - // pass, it's ok - } - - try { - new ClickHouseDataSource("jdbc:clickhouse://localhost:wer"); - fail("ClickHouseDataSource with incorrect args must fail"); - } catch (IllegalArgumentException ex) { - // pass, it's ok - } - } - - @Test(groups = "unit") - public void testIPv6Constructor() throws Exception { - ClickHouseDataSource ds = new ClickHouseDataSource("jdbc:clickhouse://[::1]:5324"); - assertEquals(ds.getHost(), "[::1]"); - assertEquals(ds.getPort(), 5324); - assertEquals(ds.getDatabase(), "default"); - - ClickHouseDataSource ds2 = new ClickHouseDataSource("jdbc:clickhouse://[::FFFF:129.144.52.38]:5324"); - assertEquals(ds2.getHost(), "[::FFFF:129.144.52.38]"); - assertEquals(ds2.getPort(), 5324); - assertEquals(ds2.getDatabase(), "default"); - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHousePreparedStatementParameterTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHousePreparedStatementParameterTest.java deleted file mode 100644 index aba79e44e..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHousePreparedStatementParameterTest.java +++ /dev/null @@ -1,57 +0,0 @@ -package ru.yandex.clickhouse; - -import org.testng.annotations.Test; - -import java.util.Arrays; -import java.util.TimeZone; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertSame; - -public class ClickHousePreparedStatementParameterTest { - - @Test(groups = "unit") - public void testNullParam() { - ClickHousePreparedStatementParameter p0 = - ClickHousePreparedStatementParameter.nullParameter(); - assertEquals(p0.getRegularValue(), "null"); - assertEquals(p0.getBatchValue(), "\\N"); - - ClickHousePreparedStatementParameter p1 = - ClickHousePreparedStatementParameter.nullParameter(); - assertEquals(p1, p0); - assertSame(p1, p0); - } - - @Test(groups = "unit") - public void testArrayAndCollectionParam() { - ClickHousePreparedStatementParameter p0 = - ClickHousePreparedStatementParameter.fromObject(Arrays.asList("A", "B", "C"), TimeZone.getDefault(), TimeZone.getDefault()); - ClickHousePreparedStatementParameter p1 = - ClickHousePreparedStatementParameter.fromObject(new String[]{"A", "B", "C"}, TimeZone.getDefault(), TimeZone.getDefault()); - assertEquals(p0.getRegularValue(), p1.getRegularValue()); - assertEquals(p0.getBatchValue(), p1.getBatchValue()); - } - - @Test(groups = "unit") - public void testBooleanParam() { - assertEquals(ClickHousePreparedStatementParameter.fromObject(Boolean.TRUE, - TimeZone.getDefault(), TimeZone.getDefault()).getRegularValue(), "1"); - assertEquals(ClickHousePreparedStatementParameter.fromObject(Boolean.FALSE, - TimeZone.getDefault(), TimeZone.getDefault()).getRegularValue(), "0"); - } - - @Test(groups = "unit") - public void testNumberParam() { - assertEquals(ClickHousePreparedStatementParameter.fromObject(10, - TimeZone.getDefault(), TimeZone.getDefault()).getRegularValue(), "10"); - assertEquals(ClickHousePreparedStatementParameter.fromObject(10.5, - TimeZone.getDefault(), TimeZone.getDefault()).getRegularValue(), "10.5"); - } - - @Test(groups = "unit") - public void testStringParam() { - assertEquals(ClickHousePreparedStatementParameter.fromObject("someString", - TimeZone.getDefault(), TimeZone.getDefault()).getRegularValue(), "'someString'"); - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHousePreparedStatementTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHousePreparedStatementTest.java deleted file mode 100644 index 7098f94b4..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHousePreparedStatementTest.java +++ /dev/null @@ -1,353 +0,0 @@ -package ru.yandex.clickhouse; - -import java.math.BigDecimal; -import java.sql.Date; -import java.sql.ResultSet; -import java.sql.Time; -import java.sql.Timestamp; -import java.sql.Types; -import java.util.Calendar; -import java.util.GregorianCalendar; -import java.util.TimeZone; - -import org.apache.http.impl.client.CloseableHttpClient; -import org.mockito.Mockito; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.settings.ClickHouseProperties; - -import static org.testng.Assert.assertEquals; - -public class ClickHousePreparedStatementTest { - - private static final String SQL_STATEMENT= "INSERT INTO foo (bar) VALUES ("; - - @Test(groups = "unit") - public void testSetBytesNull() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setBytes(1, null); - assertParamMatches(s, "null"); - } - - @Test(groups = "unit") - public void testSetBytesNormal() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setBytes(1, "foo".getBytes("UTF-8")); - assertParamMatches(s, "'\\x66\\x6F\\x6F'"); - } - - @Test(groups = "unit") - public void testSetBytesEmpty() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setBytes(1, "".getBytes("UTF-8")); - assertParamMatches(s, "''"); - } - - @Test(groups = "unit") - public void testSetNull() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setNull(1, Types.ARRAY); - assertParamMatches(s, "null"); - s.setNull(1, Types.CHAR); - assertParamMatches(s, "null"); - } - - @Test(groups = "unit") - public void testSetBooleanTrue() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setBoolean(1, true); - assertParamMatches(s, "1"); - } - - @Test(groups = "unit") - public void testSetBooleanFalse() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setBoolean(1, false); - assertParamMatches(s, "0"); - } - - @Test(groups = "unit") - public void testSetByte() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setByte(1, (byte) -127); - assertParamMatches(s, "-127"); - } - - @Test(groups = "unit") - public void testSetShort() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setShort(1, (short) 42); - assertParamMatches(s, "42"); - } - - @Test(groups = "unit") - public void testSetInt() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setInt(1, 0); - assertParamMatches(s, "0"); - } - - @Test(groups = "unit") - public void testSetLong() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setLong(1, 1337L); - assertParamMatches(s, "1337"); - } - - @Test(groups = "unit") - public void testSetFloat() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setFloat(1, -23.42f); - assertParamMatches(s, "-23.42"); - } - - @Test(groups = "unit") - public void testSetDouble() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setDouble(1, Double.MIN_VALUE); - assertParamMatches(s, "4.9E-324"); // will result in 0 in Float64 - // but parsing is OK - } - - @Test(groups = "unit") - public void testSetBigDecimalNull() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setBigDecimal(1, null); - assertParamMatches(s, "null"); - } - - @Test(groups = "unit") - public void testSetBigDecimalNormal() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setBigDecimal(1, BigDecimal.valueOf(-0.2342)); - assertParamMatches(s, "-0.2342"); - } - - @Test(groups = "unit") - public void testSetStringNull() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setString(1, null); - assertParamMatches(s, "null"); - } - - @Test(groups = "unit") - public void testSetStringSimple() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setString(1, "foo"); - assertParamMatches(s, "'foo'"); - } - - @Test(groups = "unit") - public void testSetStringEvil() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setString(1, "\"'\\x32"); - assertParamMatches(s, "'\"\\'\\\\x32'"); - } - - @Test(groups = "unit") - public void testSetDateNull() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setDate(1, null); - assertParamMatches(s, "null"); - } - - @Test(groups = "unit") - public void testSetDateNormal() throws Exception { - ClickHousePreparedStatement s = createStatement(); - Date d = new Date(1557168043000L); - s.setDate(1, d); - assertParamMatches(s, "'" + d.toLocalDate().toString() + "'"); - } - - @Test(groups = "unit") - public void testSetDateOtherTimeZone() throws Exception { - ClickHouseProperties p = new ClickHouseProperties(); - ClickHousePreparedStatement s = createStatement( - TimeZone.getTimeZone("Asia/Tokyo"), p); - Date d = new Date(1557168043000L); - s.setDate(1, d); - assertParamMatches(s, "'" + d.toLocalDate().toString() + "'"); - - /* - TimeZone t = TimeZone.getTimeZone("American/Los_Angels"); - p.setUseServerTimeZoneForDates(true); - s = createStatement(t, p); - s.setDate(1, d); - assertParamMatches(s, "'" + LocalDate.ofInstant( - Instant.ofEpochMilli(d.getTime()), t.toZoneId()).toString() + "'"); - */ - } - - @Test(groups = "unit") - public void testSetDateOtherTimeZoneServerTime() throws Exception { - ClickHouseProperties props = new ClickHouseProperties(); - props.setUseServerTimeZoneForDates(true); - ClickHousePreparedStatement s = createStatement( - TimeZone.getTimeZone("Asia/Tokyo"), - props); - s.setDate(1, new Date(1557168043000L)); - assertParamMatches(s, "'2019-05-07'"); - } - - @Test(groups = "unit") - public void testSetDateCalendar() throws Exception { - ClickHouseProperties props = new ClickHouseProperties(); - props.setUseServerTimeZoneForDates(true); - ClickHousePreparedStatement s = createStatement( - TimeZone.getTimeZone("Asia/Tokyo"), - props); - Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("Europe/Berlin")); - s.setDate(1, new Date(1557168043000L), cal); - assertParamMatches(s, "'2019-05-06'"); - } - - @Test(groups = "unit") - public void testSetDateCalendarSameTimeZone() throws Exception { - ClickHouseProperties props = new ClickHouseProperties(); - props.setUseServerTimeZoneForDates(true); - ClickHousePreparedStatement s = createStatement( - TimeZone.getTimeZone("Asia/Tokyo"), - props); - Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("Asia/Tokyo")); - s.setDate(1, new Date(1557168043000L), cal); - assertParamMatches(s, "'2019-05-07'"); - } - - @Test(groups = "unit") - public void testSetDateCalendarNull() throws Exception { - ClickHouseProperties props = new ClickHouseProperties(); - props.setUseServerTimeZoneForDates(true); - ClickHousePreparedStatement s = createStatement( - TimeZone.getTimeZone("Asia/Tokyo"), - props); - s.setDate(1, new Date(1557168043000L), null); - assertParamMatches(s, "'2019-05-07'"); - } - - @Test(groups = "unit") - public void testSetTimeNull() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setTime(1, null); - assertParamMatches(s, "null"); - } - - @Test(groups = "unit") - public void testSetTimeNormal() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setTime(1, new Time(1557168043000L)); - assertParamMatches(s, "'21:40:43'"); - } - - @Test(groups = "unit") - public void testSetTimeNormalOtherTimeZone() throws Exception { - ClickHousePreparedStatement s = createStatement( - TimeZone.getTimeZone("America/Los_Angeles"), - new ClickHouseProperties()); - s.setTime(1, new Time(1557168043000L)); - assertParamMatches(s, "'11:40:43'"); - } - - @Test(groups = "unit") - public void testSetTimeCalendar() throws Exception { - ClickHousePreparedStatement s = createStatement( - TimeZone.getTimeZone("America/Los_Angeles"), - new ClickHouseProperties()); - Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("Asia/Kuala_Lumpur")); - s.setTime(1, new Time(1557168043000L), cal); - assertParamMatches(s, "'02:40:43'"); - } - - @Test(groups = "unit") - public void testSetTimeCalendarNull() throws Exception { - ClickHousePreparedStatement s = createStatement( - TimeZone.getTimeZone("America/Los_Angeles"), - new ClickHouseProperties()); - s.setTime(1, new Time(1557168043000L), null); - assertParamMatches(s, "'11:40:43'"); - } - - @Test(groups = "unit") - public void testSetTimeCalendarSameTimeZone() throws Exception { - ClickHousePreparedStatement s = createStatement( - TimeZone.getTimeZone("America/Los_Angeles"), - new ClickHouseProperties()); - Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("America/Los_Angeles")); - s.setTime(1, new Time(1557168043000L), cal); - assertParamMatches(s, "'11:40:43'"); - } - - @Test(groups = "unit") - public void testSetTimestampNull() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setTimestamp(1, null); - assertParamMatches(s, "null"); - } - - @Test(groups = "unit") - public void testSetTimestampNormal() throws Exception { - ClickHousePreparedStatement s = createStatement(); - s.setTimestamp(1, new Timestamp(1557168043000L)); - assertParamMatches(s, "'2019-05-06 21:40:43'"); - } - - @Test(groups = "unit") - public void testSetTimestampNormalOtherTimeZone() throws Exception { - ClickHousePreparedStatement s = createStatement( - TimeZone.getTimeZone("America/Los_Angeles"), - new ClickHouseProperties()); - s.setTimestamp(1, new Timestamp(1557168043000L)); - assertParamMatches(s, "'2019-05-06 11:40:43'"); - } - - @Test(groups = "unit") - public void testSetTimestampCalendar() throws Exception { - ClickHousePreparedStatement s = createStatement( - TimeZone.getTimeZone("America/Los_Angeles"), - new ClickHouseProperties()); - Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("Asia/Manila")); - s.setTimestamp(1, new Timestamp(1557168043000L), cal); - assertParamMatches(s, "'2019-05-07 02:40:43'"); - } - - @Test(groups = "unit") - public void testSetTimestampCalendarSameTimeZone() throws Exception { - ClickHousePreparedStatement s = createStatement( - TimeZone.getTimeZone("America/Los_Angeles"), - new ClickHouseProperties()); - Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("America/Los_Angeles")); - s.setTimestamp(1, new Timestamp(1557168043000L), cal); - assertParamMatches(s, "'2019-05-06 11:40:43'"); - } - - @Test(groups = "unit") - public void testSetTimestampCalendarNull() throws Exception { - ClickHousePreparedStatement s = createStatement( - TimeZone.getTimeZone("America/Los_Angeles"), - new ClickHouseProperties()); - s.setTimestamp(1, new Timestamp(1557168043000L), null); - assertParamMatches(s, "'2019-05-06 11:40:43'"); - } - - private static void assertParamMatches(ClickHousePreparedStatement stmt, String expected) { - assertEquals(stmt.asSql(), SQL_STATEMENT + expected + ")"); - } - - private static ClickHousePreparedStatement createStatement() throws Exception { - return createStatement( - TimeZone.getTimeZone("Europe/Moscow"), - new ClickHouseProperties()); - } - - private static ClickHousePreparedStatement createStatement(TimeZone timezone, - ClickHouseProperties props) throws Exception - { - return new ClickHousePreparedStatementImpl( - Mockito.mock(CloseableHttpClient.class), - Mockito.mock(ClickHouseConnection.class), - props, - "INSERT INTO foo (bar) VALUES (?)", - timezone, - ResultSet.TYPE_FORWARD_ONLY); - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHouseStatementImplTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHouseStatementImplTest.java deleted file mode 100644 index 9bb493d2f..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHouseStatementImplTest.java +++ /dev/null @@ -1,596 +0,0 @@ -package ru.yandex.clickhouse; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.math.BigInteger; -import java.nio.charset.Charset; -import java.sql.Array; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.sql.Types; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -import com.clickhouse.client.ClickHouseVersion; - -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.response.ClickHouseResponse; -import ru.yandex.clickhouse.settings.ClickHouseProperties; -import ru.yandex.clickhouse.settings.ClickHouseQueryParam; - -public class ClickHouseStatementImplTest extends JdbcIntegrationTest { - private ClickHouseConnection connection; - - @BeforeClass(groups = "integration") - public void setUp() throws Exception { - connection = newConnection(); - } - - @AfterClass(groups = "integration") - public void tearDown() throws Exception { - closeConnection(connection); - } - - @Test(groups = "integration") - public void testUpdateCountForSelect() throws Exception { - Statement stmt = connection.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT dummy FROM system.one"); - Assert.assertEquals(stmt.getUpdateCount(), -1); - rs.next(); - Assert.assertEquals(stmt.getUpdateCount(), -1); - rs.close(); - stmt.close(); - } - - @Test(groups = "integration") - public void testSingleColumnResultSet() throws SQLException { - ResultSet rs = connection.createStatement().executeQuery("select c from (\n" + - " select 'a' as c, 1 as rn\n" + - " UNION ALL select 'b' as c, 2 as rn\n" + - " UNION ALL select '' as c, 3 as rn\n" + - " UNION ALL select 'd' as c, 4 as rn\n" + - " ) order by rn"); - StringBuffer sb = new StringBuffer(); - while (rs.next()) { - sb.append(rs.getString("c")).append("\n"); - } - Assert.assertEquals(sb.toString(), "a\nb\n\nd\n"); - } - - @Test(groups = "integration") - public void readsPastLastAreSafe() throws SQLException { - ResultSet rs = connection.createStatement().executeQuery("select c from (\n" + - " select 'a' as c, 1 as rn\n" + - " UNION ALL select 'b' as c, 2 as rn\n" + - " UNION ALL select '' as c, 3 as rn\n" + - " UNION ALL select 'd' as c, 4 as rn\n" + - " ) order by rn"); - StringBuffer sb = new StringBuffer(); - while (rs.next()) { - sb.append(rs.getString("c")).append("\n"); - } - Assert.assertFalse(rs.next()); - Assert.assertFalse(rs.next()); - Assert.assertFalse(rs.next()); - Assert.assertEquals(sb.toString(), "a\nb\n\nd\n"); - } - - @Test(groups = "integration") - public void testSelectUInt32() throws SQLException { - Statement stmt = connection.createStatement(); - ResultSet rs = stmt.executeQuery("select toUInt32(10), toUInt32(-10)"); - rs.next(); - Object smallUInt32 = rs.getObject(1); - Assert.assertTrue(smallUInt32 instanceof Long); - Assert.assertEquals(((Long)smallUInt32).longValue(), 10); - Object bigUInt32 = rs.getObject(2); - Assert.assertTrue(bigUInt32 instanceof Long); - Assert.assertEquals(((Long)bigUInt32).longValue(), 4294967286L); - } - - @Test(groups = "integration") - public void testSelectUInt64() throws SQLException { - Statement stmt = connection.createStatement(); - ResultSet rs = stmt.executeQuery("select toUInt64(10), toUInt64(-10)"); - rs.next(); - Object smallUInt64 = rs.getObject(1); - Assert.assertTrue(smallUInt64 instanceof BigInteger); - Assert.assertEquals(((BigInteger)smallUInt64).intValue(), 10); - Object bigUInt64 = rs.getObject(2); - Assert.assertTrue(bigUInt64 instanceof BigInteger); - Assert.assertEquals(bigUInt64, new BigInteger("18446744073709551606")); - } - - @Test(groups = "integration") - public void testExternalData() throws SQLException, UnsupportedEncodingException { - ClickHouseStatement stmt = connection.createStatement(); - String[] rows = ClickHouseVersion.check(connection.getServerVersion(), "[21.3,)") - ? new String[] { "1\tGroup\n" } - : new String[] { "1\tGroup", "1\tGroup\n" }; - - for (String row : rows) { - try (ResultSet rs = stmt.executeQuery( - "select UserName, GroupName " + - "from (select 'User' as UserName, 1 as GroupId) as g" + - "any left join groups using GroupId", null, - Collections.singletonList(new ClickHouseExternalData( - "groups", - new ByteArrayInputStream(row.getBytes()) - ).withStructure("GroupId UInt8, GroupName String")))) { - Assert.assertTrue(rs.next()); - String userName = rs.getString("UserName"); - String groupName = rs.getString("GroupName"); - - Assert.assertEquals(userName, "User"); - Assert.assertEquals(groupName, "Group"); - } - } - } - - // reproduce issue #634 - @Test(groups = "integration") - public void testLargeQueryWithExternalData() throws Exception { - String[] rows = ClickHouseVersion.check(connection.getServerVersion(), "[21.3,)") - ? new String[] { "1\tGroup\n" } - : new String[] { "1\tGroup", "1\tGroup\n" }; - - int length = 160000; - StringBuilder builder = new StringBuilder(length); - for (int i = 0; i < length; i++) { - builder.append('u'); - } - String user = builder.toString(); - for (String row : rows) { - try (ClickHouseStatement stmt = connection.createStatement(); - ResultSet rs = stmt.executeQuery( - "select UserName, GroupName from (select '" - + user - + "' as UserName, 1 as GroupId) as g" - + "any left join groups using GroupId", null, - Collections.singletonList(new ClickHouseExternalData( - "groups", new ByteArrayInputStream(row.getBytes()) - ).withStructure("GroupId UInt8, GroupName String")))) { - Assert.assertTrue(rs.next()); - String userName = rs.getString("UserName"); - String groupName = rs.getString("GroupName"); - - Assert.assertEquals(userName, user); - Assert.assertEquals(groupName, "Group"); - } - } - } - - - private InputStream getTSVStream(final int rowsCount) { - return new InputStream() { - private int si = 0; - private String s = ""; - private int i = 0; - - private boolean genNextString() { - if (i >= rowsCount) { - return false; - } - si = 0; - s = String.format("%d\t%d\n", i, i); - i++; - return true; - } - - @Override - public int read() { - if (si >= s.length()) { - if (!genNextString()) { - return -1; - } - } - return s.charAt(si++); - } - }; - } - - - @Test(groups = "integration") - public void testExternalDataStream() throws SQLException, UnsupportedEncodingException { - if ("21.3.3.14".equals(connection.getServerVersion())) { - return; - } - - final ClickHouseStatement statement = connection.createStatement(); - statement.execute("DROP TABLE IF EXISTS testExternalData"); - statement.execute( - "CREATE TABLE testExternalData (id UInt64, s String) ENGINE = Memory"); - statement.execute( - "insert into testExternalData select number, toString(number) from numbers(500,100000)"); - - InputStream inputStream = getTSVStream(100000); - - ClickHouseExternalData extData = new ClickHouseExternalData("ext_data", inputStream); - extData.setStructure("id UInt64, s String"); - - ResultSet rs = statement.executeQuery( - "select count() cnt from testExternalData where (id,s) in ext_data", - null, - Collections.singletonList(extData) - ); - - rs.next(); - - int cnt = rs.getInt("cnt"); - - Assert.assertEquals(cnt, 99500); - } - - @Test(groups = "integration") - public void testQueryWithMultipleExternalTables() throws SQLException { - int tables = 30; - int rows = 10; - - String ddl = "drop table if exists test_ext_data_query;\n" - + "create table test_ext_data_query (\n" - + " Cb String,\n" - + " CREATETIME DateTime64(3),\n" - + " TIMESTAMP UInt64,\n" - + " Cc String,\n" - + " Ca1 UInt64,\n" - + " Ca2 UInt64,\n" - + " Ca3 UInt64\n" - + ") engine = MergeTree()\n" - + "PARTITION BY toYYYYMMDD(CREATETIME)\n" - + "ORDER BY (Cb, CREATETIME, Cc);"; - - String template = "avgIf(Ca1, Cb in L%1$d) as avgCa1%2$d, sumIf(Ca1, Cb in L%1$d) as sumCa1%2$d, minIf(Ca1, Cb in L%1$d) as minCa1%2$d, maxIf(Ca1, Cb in L%1$d) as maxCa1%2$d, anyIf(Ca1, Cb in L%1$d) as anyCa1%2$d, avgIf(Ca2, Cb in L%1$d) as avgCa2%2$d, sumIf(Ca2, Cb in L%1$d) as sumCa2%2$d, minIf(Ca2, Cb in L%1$d) as minCa2%2$d, maxIf(Ca2, Cb in L%1$d) as maxCa2%2$d, anyIf(Ca2, Cb in L%1$d) as anyCa2%2$d, avgIf(Ca3, Cb in L%1$d) as avgCa3%2$d, sumIf(Ca3, Cb in L%1$d) as sumCa3%2$d, minIf(Ca3, Cb in L%1$d) as minCa3%2$d, maxIf(Ca3, Cb in L%1$d) as maxCa3%2$d, anyIf(Ca3, Cb in L%1$d) as anyCa3%2$d"; - ClickHouseProperties properties = new ClickHouseProperties(); - properties.setDatabase(dbName); - properties.setSocketTimeout(300000); - properties.setMaxAstElements(Long.MAX_VALUE); - properties.setMaxTotal(20); - properties.setMaxQuerySize(104857600L); - - Map paramMap = new HashMap<>(); - paramMap.put(ClickHouseQueryParam.PRIORITY,"2"); - - StringBuilder sql = new StringBuilder().append("select "); - List extDataList = new ArrayList<>(tables); - for (int i = 0; i < tables; i++) { - sql.append(String.format(template, i, i + 1)).append(','); - List valueList = new ArrayList<>(rows); - for (int j = i, size = i + rows; j < size; j++) { - valueList.add(String.valueOf(j)); - } - String dnExtString = String.join("\n", valueList); - InputStream inputStream = new ByteArrayInputStream(dnExtString.getBytes(Charset.forName("UTF-8"))); - ClickHouseExternalData extData = new ClickHouseExternalData("L" + i, inputStream); - extData.setStructure("Cb String"); - extDataList.add(extData); - } - - if (tables > 0) { - sql.deleteCharAt(sql.length() - 1); - } else { - sql.append('*'); - } - sql.append(" from test_ext_data_query where TIMESTAMP >= 1625796480 and TIMESTAMP < 1625796540 and Cc = 'eth0'"); - - try (ClickHouseConnection c = newDataSource(properties).getConnection(); - ClickHouseStatement s = c.createStatement();) { - s.execute(ddl); - ResultSet rs = s.executeQuery(sql.toString(), paramMap, extDataList); - assertTrue(tables <= 0 || rs.next()); - } - } - - @Test(groups = "integration") - public void testResultSetWithExtremes() throws SQLException { - ClickHouseProperties properties = new ClickHouseProperties(); - properties.setExtremes(true); - ClickHouseDataSource dataSource = newDataSource(properties); - Connection connection = dataSource.getConnection(); - - try { - Statement stmt = connection.createStatement(); - ResultSet rs = stmt.executeQuery("select 1"); - StringBuilder sb = new StringBuilder(); - while (rs.next()) { - sb.append(rs.getString(1)).append("\n"); - } - - Assert.assertEquals(sb.toString(), "1\n"); - } finally { - connection.close(); - } - } - - @Test(groups = "integration") - public void testSelectOne() throws SQLException { - try (Statement stmt = connection.createStatement()) { - ResultSet rs = stmt.executeQuery("select\n1"); - Assert.assertTrue(rs.next()); - Assert.assertEquals(rs.getInt(1), 1); - Assert.assertFalse(rs.next()); - } - } - - @Test(groups = "integration") - public void testSelectManyRows() throws SQLException { - Statement stmt = connection.createStatement(); - int limit = 10000; - ResultSet rs = stmt.executeQuery( - "select concat('test', toString(number)) as str from system.numbers limit " + limit); - int i = 0; - while (rs.next()) { - String s = rs.getString("str"); - Assert.assertEquals(s, "test" + i); - i++; - } - Assert.assertEquals(i, limit); - } - - @Test(groups = "integration") - public void testMoreResultsWithResultSet() throws SQLException { - Statement stmt = connection.createStatement(); - - Assert.assertTrue(stmt.execute("select 1")); - Assert.assertNotNull(stmt.getResultSet()); - Assert.assertEquals(stmt.getUpdateCount(), -1); - - Assert.assertFalse(stmt.getMoreResults()); - Assert.assertNull(stmt.getResultSet()); - Assert.assertEquals(stmt.getUpdateCount(), -1); - } - - @Test(groups = "integration") - public void testMoreResultsWithUpdateCount() throws SQLException { - Statement stmt = connection.createStatement(); - - Assert.assertFalse(stmt.execute("create database if not exists default")); - Assert.assertNull(stmt.getResultSet()); - Assert.assertEquals(stmt.getUpdateCount(), 0); - - Assert.assertFalse(stmt.getMoreResults()); - Assert.assertNull(stmt.getResultSet()); - Assert.assertEquals(stmt.getUpdateCount(), -1); - } - - @Test(groups = "integration") - public void testSelectQueryStartingWithWith() throws SQLException { - Statement stmt = connection.createStatement(); - ResultSet rs = stmt.executeQuery("WITH 2 AS two SELECT two * two;"); - - Assert.assertNotNull(rs); - Assert.assertTrue(rs.next()); - Assert.assertEquals(rs.getInt(1), 4); - - rs.close(); - stmt.close(); - } - - @Test(groups = "integration") - public void cancelTest_queryId_is_not_set() throws Exception { - final ClickHouseStatement firstStatement = newConnection().createStatement(); - - final AtomicReference exceptionAtomicReference = new AtomicReference<>(); - Thread thread = new Thread() { - @Override - public void run() { - try { - Map params = new EnumMap<>(ClickHouseQueryParam.class); - params.put(ClickHouseQueryParam.CONNECT_TIMEOUT, Long.toString(TimeUnit.MINUTES.toMillis(1))); - firstStatement.executeQuery("SELECT count() FROM system.numbers", params); - } catch (Exception e) { - exceptionAtomicReference.set(e); - } - } - }; - thread.setDaemon(true); - thread.start(); - - - final long timeout = 10; - assertTrue(firstStatement instanceof ClickHouseStatementImpl); - String queryId = readQueryId((ClickHouseStatementImpl) firstStatement, timeout); - assertNotNull( - String.format("it's actually very strange. It seems the query hasn't been executed in %s seconds", timeout), - queryId); - assertNull(exceptionAtomicReference.get(), "An exception happened while the query was being executed"); - - - assertTrue(checkQuery(queryId, true, 10), "The query isn't being executed. It seems very strange"); - firstStatement.cancel(); - assertTrue(checkQuery(queryId, false, 10), "The query is still being executed"); - - firstStatement.close(); - thread.interrupt(); - } - - - @Test(groups = "integration") - public void cancelTest_queryId_is_set() throws Exception { - final String queryId = UUID.randomUUID().toString(); - final ClickHouseStatement firstStatement = newConnection().createStatement(); - - final CountDownLatch countDownLatch = new CountDownLatch(1); - final AtomicReference exceptionAtomicReference = new AtomicReference<>(); - Thread thread = new Thread() { - @Override - public void run() { - try { - Map params = new EnumMap<>(ClickHouseQueryParam.class); - params.put(ClickHouseQueryParam.CONNECT_TIMEOUT, Long.toString(TimeUnit.MINUTES.toMillis(1))); - params.put(ClickHouseQueryParam.QUERY_ID, queryId); - countDownLatch.countDown(); - firstStatement.executeQuery("SELECT count() FROM system.numbers", params); - } catch (Exception e) { - exceptionAtomicReference.set(e); - } - } - }; - thread.setDaemon(true); - thread.start(); - final long timeout = 10; - assertTrue(countDownLatch.await(timeout, TimeUnit.SECONDS), - String.format( - "it's actually very strange. It seems the query hasn't been executed in %s seconds", timeout)); - assertNull(exceptionAtomicReference.get(), "An exception happened while the query was being executed"); - - assertTrue(checkQuery(queryId, true, 10), "The query isn't being executed. It seems very strange"); - firstStatement.cancel(); - assertTrue(checkQuery(queryId, false, 10), "The query is still being executed"); - - firstStatement.close(); - thread.interrupt(); - } - - @Test(groups = "integration") - public void testArrayMetaActualExecutiom() throws SQLException { - Statement stmt = connection.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT array(42, 23)"); - rs.next(); - Assert.assertEquals(rs.getMetaData().getColumnType(1), Types.ARRAY); - Assert.assertEquals(rs.getMetaData().getColumnTypeName(1), "Array(UInt8)"); - Assert.assertEquals(rs.getMetaData().getColumnClassName(1), - Array.class.getCanonicalName()); - Array arr = (Array) rs.getObject(1); - Assert.assertEquals(((int[]) arr.getArray())[0], 42); - Assert.assertEquals(((int[]) arr.getArray())[1], 23); - - } - - @Test(groups = "integration") - public void testInsertQueryUUIDArray() throws SQLException { - // issue #569 - connection.createStatement().execute( - "DROP TABLE IF EXISTS uuidArray"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS uuidArray" - + "(id UInt8, arr Array(UUID)) " - + "ENGINE = TinyLog"); - connection.createStatement().execute( - "INSERT INTO uuidArray VALUES(1, ['5ff22319-793d-4e6c-bdc1-916095a5a496'])"); - ResultSet rs = connection.createStatement().executeQuery( - "SELECT * FROM uuidArray"); - rs.next(); - assertEquals( - rs.getArray(2).getArray(), - new UUID[] {UUID.fromString("5ff22319-793d-4e6c-bdc1-916095a5a496")}); - } - - @Test(groups = "integration") - public void testMultiStatements() throws SQLException { - try (Statement s = connection.createStatement()) { - String sql = "select 1; select 2"; - try (ResultSet rs = s.executeQuery(sql)) { - assertTrue(rs.next()); - assertEquals(rs.getString(1), "2"); - assertFalse(rs.next()); - } - - assertTrue(s.execute(sql)); - try (ResultSet rs = s.getResultSet()) { - assertNotNull(rs); - assertTrue(rs.next()); - assertEquals(rs.getString(1), "2"); - assertFalse(rs.next()); - } - - assertEquals(s.executeUpdate(sql), 1); - } - } - - @Test(groups = "integration") - public void testBatchProcessing() throws SQLException { - try (Statement s = connection.createStatement()) { - int[] results = s.executeBatch(); - assertNotNull(results); - assertEquals(results.length, 0); - - s.addBatch("select 1; select 2"); - s.addBatch("select 3"); - results = s.executeBatch(); - assertNotNull(results); - assertEquals(results.length, 3); - - s.clearBatch(); - results = s.executeBatch(); - assertNotNull(results); - assertEquals(results.length, 0); - } - } - - @Test(groups = "integration") - public void testJsonResponse() throws SQLException { - try (ClickHouseStatement s = connection.createStatement()) { - ClickHouseResponse response = s.executeQueryClickhouseResponse( - "SELECT 1 AS one, tuple(1,'hello', 'world') AS two"); - assertNotNull(response); - assertEquals(response.getData(), Collections.singletonList(Arrays.asList("1", "[1,\"hello\",\"world\"]"))); - } - } - - @Test(groups = "integration") - public void testJsonResponseWithNull() throws SQLException { - try (ClickHouseStatement s = connection.createStatement()) { - ClickHouseResponse response = s.executeQueryClickhouseResponse( - "SELECT 1 AS one, 0/0 AS n"); - assertNotNull(response); - assertEquals(response.getData(), Collections.singletonList(Arrays.asList("1", null))); - } - } - - private static String readQueryId(ClickHouseStatementImpl stmt, long timeoutSecs) { - long start = System.currentTimeMillis(); - String value; - do { - value = stmt.getQueryId(); - } while (value == null && TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - start) < timeoutSecs); - - return value; - } - - private boolean checkQuery(String queryId, boolean isRunning, long timeoutSecs) throws Exception { - long start = System.currentTimeMillis(); - - do { - ClickHouseStatement statement = null; - try { - statement = connection.createStatement(); - statement.execute(String.format("SELECT * FROM system.processes where query_id='%s'", queryId)); - ResultSet resultSet = statement.getResultSet(); - if (resultSet.next() == isRunning) { - return true; - } - } finally { - if (statement != null) { - statement.close(); - } - } - - } while (TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - start) < timeoutSecs); - - return false; - } - - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHouseStatementTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHouseStatementTest.java deleted file mode 100644 index aa9784ade..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHouseStatementTest.java +++ /dev/null @@ -1,220 +0,0 @@ -package ru.yandex.clickhouse; - - -import java.net.URI; -import java.net.URISyntaxException; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Collections; -import java.util.Properties; - -import org.apache.http.impl.client.HttpClientBuilder; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.domain.ClickHouseFormat; -import ru.yandex.clickhouse.settings.ClickHouseProperties; -import ru.yandex.clickhouse.settings.ClickHouseQueryParam; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; - -public class ClickHouseStatementTest { - @Test(groups = "unit") - public void testClickhousify() throws Exception { - ClickHouseStatementImpl s = new ClickHouseStatementImpl(null, null, null, ResultSet.TYPE_FORWARD_ONLY); - String sql = "SELECT ololo FROM ololoed;"; - assertEquals(s.parseSqlStatements(sql, ClickHouseFormat.TabSeparatedWithNamesAndTypes, null).getSQL(), - "SELECT ololo FROM ololoed\nFORMAT TabSeparatedWithNamesAndTypes"); - - sql = "SELECT ololo FROM ololoed"; - assertEquals(s.parseSqlStatements(sql, ClickHouseFormat.TabSeparatedWithNamesAndTypes, null).getSQL(), - "SELECT ololo FROM ololoed\nFORMAT TabSeparatedWithNamesAndTypes"); - - sql = "SELECT ololo FROM ololoed FORMAT TabSeparatedWithNamesAndTypes"; - assertEquals(s.parseSqlStatements(sql, ClickHouseFormat.TabSeparatedWithNamesAndTypes, null).getSQL(), - "SELECT ololo FROM ololoed FORMAT TabSeparatedWithNamesAndTypes"); - - sql = "SELECT ololo FROM ololoed FORMAT TabSeparatedWithNamesAndTypes;"; - assertEquals(s.parseSqlStatements(sql, ClickHouseFormat.TabSeparatedWithNamesAndTypes, null).getSQL(), - "SELECT ololo FROM ololoed FORMAT TabSeparatedWithNamesAndTypes"); - - sql = "SHOW ololo FROM ololoed;"; - assertEquals(s.parseSqlStatements(sql, ClickHouseFormat.TabSeparatedWithNamesAndTypes, null).getSQL(), - "SHOW ololo FROM ololoed\nFORMAT TabSeparatedWithNamesAndTypes"); - - sql = " show ololo FROM ololoed;"; - assertEquals(s.parseSqlStatements(sql, ClickHouseFormat.TabSeparatedWithNamesAndTypes, null).getSQL(), - " show ololo FROM ololoed\nFORMAT TabSeparatedWithNamesAndTypes"); - - sql = "SELECT ololo FROM ololoed \nFORMAT TabSeparatedWithNamesAndTypes"; - assertEquals(s.parseSqlStatements(sql, ClickHouseFormat.TabSeparatedWithNamesAndTypes, null).getSQL(), - "SELECT ololo FROM ololoed \nFORMAT TabSeparatedWithNamesAndTypes"); - - sql = "SELECT ololo FROM ololoed \n\n FORMAT TabSeparatedWithNamesAndTypes"; - assertEquals(s.parseSqlStatements(sql, ClickHouseFormat.TabSeparatedWithNamesAndTypes, null).getSQL(), - "SELECT ololo FROM ololoed \n\n FORMAT TabSeparatedWithNamesAndTypes"); - - sql = "SELECT ololo FROM ololoed\n-- some comments one line"; - assertEquals(s.parseSqlStatements(sql, ClickHouseFormat.TabSeparatedWithNamesAndTypes, null).getSQL(), - "SELECT ololo FROM ololoed\n-- some comments one line\nFORMAT TabSeparatedWithNamesAndTypes"); - - sql = "SELECT ololo FROM ololoed\n-- some comments\ntwo line"; - assertEquals(s.parseSqlStatements(sql, ClickHouseFormat.TabSeparatedWithNamesAndTypes, null).getSQL(), - "SELECT ololo FROM ololoed\n-- some comments\ntwo line\nFORMAT TabSeparatedWithNamesAndTypes"); - - sql = "SELECT ololo FROM ololoed/*\nsome comments\ntwo line*/"; - assertEquals(s.parseSqlStatements(sql, ClickHouseFormat.TabSeparatedWithNamesAndTypes, null).getSQL(), - "SELECT ololo FROM ololoed/*\nsome comments\ntwo line*/\nFORMAT TabSeparatedWithNamesAndTypes"); - - sql = "SELECT ololo FROM ololoed\n// c style some comments one line"; - assertEquals(s.parseSqlStatements(sql, ClickHouseFormat.TabSeparatedWithNamesAndTypes, null).getSQL(), - "SELECT ololo FROM ololoed\n// c style some comments one line\nFORMAT TabSeparatedWithNamesAndTypes"); - - } - - @Test(groups = "unit") - public void testCredentials() throws SQLException, URISyntaxException { - ClickHouseProperties properties = new ClickHouseProperties(new Properties()); - ClickHouseProperties withCredentials = properties.withCredentials("test_user", "test_password"); - assertTrue(withCredentials != properties); - assertNull(properties.getUser()); - assertNull(properties.getPassword()); - assertEquals(withCredentials.getUser(), "test_user"); - assertEquals(withCredentials.getPassword(), "test_password"); - - ClickHouseStatementImpl statement = new ClickHouseStatementImpl( - HttpClientBuilder.create().build(), - null, withCredentials, ResultSet.TYPE_FORWARD_ONLY); - - URI uri = statement.buildRequestUri(null, null, null, null, false); - String query = uri.getQuery(); - // we use Basic AUTH nowadays - assertFalse(query.contains("password=test_password")); - assertFalse(query.contains("user=test_user")); - } - - @Test(groups = "unit") - public void testMaxExecutionTime() throws Exception { - ClickHouseProperties properties = new ClickHouseProperties(); - properties.setMaxExecutionTime(20); - ClickHouseStatementImpl statement = new ClickHouseStatementImpl(HttpClientBuilder.create().build(), - null, properties, ResultSet.TYPE_FORWARD_ONLY); - URI uri = statement.buildRequestUri(null, null, null, null, false); - String query = uri.getQuery(); - assertTrue(query.contains("max_execution_time=20"), "max_execution_time param is missing in URL"); - - statement.setQueryTimeout(10); - uri = statement.buildRequestUri(null, null, null, null, false); - query = uri.getQuery(); - assertTrue(query.contains("max_execution_time=10"), "max_execution_time param is missing in URL"); - } - - @Test(groups = "unit") - public void testMaxMemoryUsage() throws Exception { - ClickHouseProperties properties = new ClickHouseProperties(); - properties.setMaxMemoryUsage(41L); - ClickHouseStatementImpl statement = new ClickHouseStatementImpl(HttpClientBuilder.create().build(), - null, properties, ResultSet.TYPE_FORWARD_ONLY); - - URI uri = statement.buildRequestUri(null, null, null, null, false); - String query = uri.getQuery(); - assertTrue(query.contains("max_memory_usage=41"), "max_memory_usage param is missing in URL"); - } - - @Test(groups = "unit") - public void testAdditionalRequestParams() { - ClickHouseProperties properties = new ClickHouseProperties(); - ClickHouseStatementImpl statement = new ClickHouseStatementImpl( - HttpClientBuilder.create().build(), - null, - properties, - ResultSet.TYPE_FORWARD_ONLY - ); - - statement.option("cache_namespace", "aaaa"); - URI uri = statement.buildRequestUri( - null, - null, - null, - null, - false - ); - String query = uri.getQuery(); - assertTrue(query.contains("cache_namespace=aaaa"), "cache_namespace param is missing in URL"); - - uri = statement.buildRequestUri( - null, - null, - null, - Collections.singletonMap("cache_namespace", "bbbb"), - false - ); - query = uri.getQuery(); - assertTrue(query.contains("cache_namespace=bbbb"), "cache_namespace param is missing in URL"); - - // check that statement level params are given to Writer - assertEquals(statement.write().getRequestParams().get("cache_namespace"), "aaaa"); - } - - @Test(groups = "unit") - public void testAdditionalDBParams() { - ClickHouseProperties properties = new ClickHouseProperties(); - properties.setMaxThreads(1); - - ClickHouseStatementImpl statement = new ClickHouseStatementImpl( - HttpClientBuilder.create().build(), - null, - properties, - ResultSet.TYPE_FORWARD_ONLY - ); - - URI uri = statement.buildRequestUri(null, null, null, null, false); - assertTrue(uri.getQuery().contains("max_threads=1")); - - // override on statement level - statement.addDbParam(ClickHouseQueryParam.MAX_THREADS, "2"); - - uri = statement.buildRequestUri(null, null, null, null, false); - assertTrue(uri.getQuery().contains("max_threads=2")); - - // override on method level - uri = statement.buildRequestUri(null, null, Collections.singletonMap(ClickHouseQueryParam.MAX_THREADS, "3"), null, false); - assertTrue(uri.getQuery().contains("max_threads=3")); - - // check that statement level params are given to Writer - assertEquals(statement.write().getAdditionalDBParams().get(ClickHouseQueryParam.MAX_THREADS), "2"); - } - - @Test(groups = "unit") - public void testIsSelect() throws SQLException { - ClickHouseStatementImpl s = new ClickHouseStatementImpl(null, null, null, ResultSet.TYPE_FORWARD_ONLY); - assertTrue(s.parseSqlStatements("SELECT 42")[0].isQuery()); - assertTrue(s.parseSqlStatements("select 42")[0].isQuery()); - assertFalse(s.parseSqlStatements("selectfoo")[0].isQuery()); - assertTrue(s.parseSqlStatements(" SELECT foo")[0].isQuery()); - assertFalse(s.parseSqlStatements("WITH foo")[0].isQuery()); - assertTrue(s.parseSqlStatements("DESC foo")[0].isQuery()); - assertTrue(s.parseSqlStatements("EXISTS foo")[0].isQuery()); - assertTrue(s.parseSqlStatements("SHOW foo")[0].isQuery()); - assertTrue(s.parseSqlStatements("-- foo\n SELECT 42")[0].isQuery()); - assertTrue(s.parseSqlStatements("--foo\n SELECT 42")[0].isQuery()); - assertFalse(s.parseSqlStatements("- foo\n SELECT 42")[0].isQuery()); - assertTrue(s.parseSqlStatements("/* foo */ SELECT 42")[0].isQuery()); - assertTrue(s.parseSqlStatements("/*\n * foo\n*/\n SELECT 42")[0].isQuery()); - assertFalse(s.parseSqlStatements("/ foo */ SELECT 42")[0].isQuery()); - assertFalse(s.parseSqlStatements("-- SELECT baz\n UPDATE foo")[0].isQuery()); - assertFalse(s.parseSqlStatements("/* SELECT baz */\n UPDATE foo")[0].isQuery()); - assertFalse(s.parseSqlStatements("/*\n UPDATE foo")[0].isQuery()); - assertFalse(s.parseSqlStatements("/*")[0].isQuery()); - assertFalse(s.parseSqlStatements("/**/")[0].isQuery()); - assertFalse(s.parseSqlStatements(" --")[0].isQuery()); - assertTrue(s.parseSqlStatements("explain select 42")[0].isQuery()); - assertTrue(s.parseSqlStatements("EXPLAIN select 42")[0].isQuery()); - assertFalse(s.parseSqlStatements("--EXPLAIN select 42\n alter")[0].isQuery()); - assertTrue(s.parseSqlStatements("--\nEXPLAIN select 42")[0].isQuery()); - assertTrue(s.parseSqlStatements("/*test*/ EXPLAIN select 42")[0].isQuery()); - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHouseUtilTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHouseUtilTest.java deleted file mode 100644 index 1c3a0b817..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHouseUtilTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package ru.yandex.clickhouse; - - -import org.testng.annotations.Test; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.fail; - - -public class ClickHouseUtilTest { - - @Test(groups = "unit") - public void testQuote() throws Exception { - assertEquals("\\N", ClickHouseUtil.escape(null)); - assertEquals("test", ClickHouseUtil.escape("test")); - assertEquals("t\\n\\0\\r\\test\\'", ClickHouseUtil.escape("t\n\0\r\test'")); - } - - @Test(groups = "unit") - public void testQuoteIdentifier() throws Exception { - assertEquals("`z`", ClickHouseUtil.quoteIdentifier("z")); - assertEquals("`a\\`\\' `", ClickHouseUtil.quoteIdentifier("a`' ")); - - try { - ClickHouseUtil.quoteIdentifier(null); - fail("quiteIdentifier with null argument must fail"); - } catch (IllegalArgumentException ex) { - // pass, it's ok - } - } -} \ No newline at end of file diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickhouseJdbcUrlParserTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickhouseJdbcUrlParserTest.java deleted file mode 100644 index d650c38a4..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickhouseJdbcUrlParserTest.java +++ /dev/null @@ -1,119 +0,0 @@ -package ru.yandex.clickhouse; - -import java.util.Properties; - -import com.clickhouse.client.ClickHouseProtocol; - -import org.testng.Assert; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.settings.ClickHouseProperties; - -public class ClickhouseJdbcUrlParserTest { - - @Test(groups = "unit") - public void testParseDashes() throws Exception { - Properties props = new Properties(); - ClickHouseProperties chProps = ClickhouseJdbcUrlParser - .parse("jdbc:clickhouse://foo.yandex:1337/db-name-with-dash", new Properties()); - Assert.assertEquals(chProps.getDatabase(), "db-name-with-dash"); - } - - @Test(groups = "unit") - public void testParseTrailingSlash() throws Exception { - Properties props = new Properties(); - ClickHouseProperties chProps = ClickhouseJdbcUrlParser.parse("jdbc:clickhouse://foo.yandex:1337/", - new Properties()); - Assert.assertEquals(chProps.getDatabase(), "default"); - } - - @Test(groups = "unit") - public void testParseDbInPathAndProps() throws Exception { - ClickHouseProperties props = new ClickHouseProperties(); - props.setDatabase("database-name"); - ClickHouseProperties chProps = ClickhouseJdbcUrlParser.parse("jdbc:clickhouse://foo.yandex:1337/database-name", - props.asProperties()); - Assert.assertEquals(chProps.getDatabase(), "database-name"); - Assert.assertEquals(chProps.getPath(), "/"); - } - - @Test(groups = "unit") - public void testParseDbInPathAndProps2() throws Exception { - ClickHouseProperties props = new ClickHouseProperties(); - props.setDatabase("database-name"); - props.setUsePathAsDb(false); - ClickHouseProperties chProps = ClickhouseJdbcUrlParser.parse("jdbc:clickhouse://foo.yandex:1337/database-name", - props.asProperties()); - Assert.assertEquals(chProps.getDatabase(), "database-name"); - Assert.assertEquals(chProps.getPath(), "/database-name"); - } - - @Test(groups = "unit") - public void testParsePathDefaultDb() throws Exception { - ClickHouseProperties props = new ClickHouseProperties(); - props.setPath("/path"); - ClickHouseProperties chProps = ClickhouseJdbcUrlParser.parse("jdbc:clickhouse://foo.yandex:1337/", - props.asProperties()); - Assert.assertEquals(chProps.getDatabase(), "default"); - Assert.assertEquals(chProps.getPath(), "/path"); - } - - @Test(groups = "unit") - public void testParsePathDefaultDb2() throws Exception { - ClickHouseProperties props = new ClickHouseProperties(); - props.setPath("/path"); - props.setUsePathAsDb(false); - ClickHouseProperties chProps = ClickhouseJdbcUrlParser.parse("jdbc:clickhouse://foo.yandex:1337", - props.asProperties()); - Assert.assertEquals(chProps.getDatabase(), "default"); - Assert.assertEquals(chProps.getPath(), "/"); // uri takes priority - } - - @Test(groups = "unit") - public void testParsePathAndDb() throws Exception { - ClickHouseProperties props = new ClickHouseProperties(); - ClickHouseProperties chProps = ClickhouseJdbcUrlParser - .parse("jdbc:clickhouse://foo.yandex:1337/db?database=dbname", props.asProperties()); - Assert.assertEquals(chProps.getDatabase(), "db"); - Assert.assertEquals(chProps.getPath(), "/"); - } - - @Test(groups = "unit") - public void testParsePathAndDb2() throws Exception { - ClickHouseProperties props = new ClickHouseProperties(); - props.setUsePathAsDb(false); - ClickHouseProperties chProps = ClickhouseJdbcUrlParser - .parse("jdbc:clickhouse://foo.yandex:1337/db?database=dbname", props.asProperties()); - Assert.assertEquals(chProps.getDatabase(), "dbname"); - Assert.assertEquals(chProps.getPath(), "/db"); - } - - @Test(groups = "unit") - public void testParseCredentials() throws Exception { - ClickHouseProperties props = new ClickHouseProperties(); - props.setUser("default1"); - props.setPassword("password1"); - ClickHouseProperties chProps = ClickhouseJdbcUrlParser.parse("jdbc:clickhouse://user:a:passwd@foo.ch/test", - props.asProperties()); - Assert.assertEquals(chProps.getUser(), "user"); - Assert.assertEquals(chProps.getPassword(), "a:passwd"); - - chProps = ClickhouseJdbcUrlParser.parse("jdbc:clickhouse://let%40me%3Ain:let%40me%3Ain@foo.ch", - props.asProperties()); - Assert.assertEquals(chProps.getUser(), "let@me:in"); - Assert.assertEquals(chProps.getPassword(), "let@me:in"); - } - - @Test(groups = "unit") - public void testParseProtocol() throws Exception { - ClickHouseProperties props = new ClickHouseProperties(); - ClickHouseProperties chProps = ClickhouseJdbcUrlParser.parse("jdbc:clickhouse://foo.ch/test", - props.asProperties()); - Assert.assertEquals(chProps.getProtocol(), ClickHouseProtocol.HTTP); - Assert.assertEquals(chProps.getPort(), ClickHouseProtocol.HTTP.getDefaultPort()); - - chProps = ClickhouseJdbcUrlParser.parse("jdbc:clickhouse://foo.ch/test?protocol=grpc", props.asProperties()); - Assert.assertEquals(chProps.getProtocol(), ClickHouseProtocol.GRPC); - Assert.assertEquals(chProps.getPort(), ClickHouseProtocol.GRPC.getDefaultPort()); - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickhouseLZ4StreamTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickhouseLZ4StreamTest.java deleted file mode 100644 index 8b39ec224..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickhouseLZ4StreamTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package ru.yandex.clickhouse; - -import org.testng.Assert; -import org.testng.annotations.Test; -import ru.yandex.clickhouse.response.ClickHouseLZ4Stream; -import ru.yandex.clickhouse.util.ClickHouseLZ4OutputStream; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -public class ClickhouseLZ4StreamTest { - @Test(groups = "unit") - public void testLZ4Stream() throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ClickHouseLZ4OutputStream outputStream = new ClickHouseLZ4OutputStream(baos, 1024*1024); - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < 100000; i++) { - outputStream.write(("test"+i).getBytes()); - sb.append("test").append(i); - } - outputStream.flush(); - byte[] result = baos.toByteArray(); - // System.out.println(result.length); - Assert.assertTrue(result.length < sb.length()/2); - ByteArrayInputStream bais = new ByteArrayInputStream(result); - ClickHouseLZ4Stream is = new ClickHouseLZ4Stream(bais); - byte[] buf = new byte[20000000]; - int read = is.read(buf); - // System.out.println(read); - Assert.assertEquals(new String(buf, 0, read), sb.toString()); - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/JdbcIntegrationTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/JdbcIntegrationTest.java deleted file mode 100644 index 9a3408836..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/JdbcIntegrationTest.java +++ /dev/null @@ -1,132 +0,0 @@ -package ru.yandex.clickhouse; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.sql.Connection; -import java.sql.SQLException; -import java.sql.Statement; - -import ru.yandex.clickhouse.settings.ClickHouseProperties; -import com.clickhouse.client.BaseIntegrationTest; -import com.clickhouse.client.ClickHouseNode; -import com.clickhouse.client.ClickHouseProtocol; - -public abstract class JdbcIntegrationTest extends BaseIntegrationTest { - private static final String CLASS_PREFIX = "ClickHouse"; - private static final String CLASS_SUFFIX = "Test"; - - protected final String dbName; - - public JdbcIntegrationTest() { - String className = getClass().getSimpleName(); - if (className.startsWith(CLASS_PREFIX)) { - className = className.substring(CLASS_PREFIX.length()); - } - if (className.endsWith(CLASS_SUFFIX)) { - className = className.substring(0, className.length() - CLASS_SUFFIX.length()); - } - - this.dbName = "test_" + className.toLowerCase(); - } - - public String getClickHouseHttpAddress() { - return getClickHouseHttpAddress(false); - } - - public String getClickHouseHttpAddress(boolean useIPaddress) { - ClickHouseNode server = getServer(ClickHouseProtocol.HTTP); - - String ipAddress = server.getHost(); - try { - ipAddress = InetAddress.getByName(ipAddress).getHostAddress(); - } catch (UnknownHostException e) { - throw new IllegalArgumentException( - String.format("Not able to resolve %s to get its IP address", server.getHost()), e); - } - return new StringBuilder().append(useIPaddress ? ipAddress : server.getHost()).append(':') - .append(server.getPort()).toString(); - } - - public String getClickHouseHttpAddress(String customHostOrIp) { - ClickHouseNode server = getServer(ClickHouseProtocol.HTTP); - return new StringBuilder() - .append(customHostOrIp == null || customHostOrIp.isEmpty() ? server.getHost() : customHostOrIp) - .append(':').append(server.getPort()).toString(); - } - - public ClickHouseDataSource newDataSource() { - return newDataSource(new ClickHouseProperties()); - } - - public ClickHouseDataSource newDataSource(ClickHouseProperties properties) { - return newDataSource("jdbc:clickhouse://" + getClickHouseHttpAddress(), properties); - } - - public ClickHouseDataSource newDataSource(String url) { - return newDataSource(url, new ClickHouseProperties()); - } - - public ClickHouseDataSource newDataSource(String url, ClickHouseProperties properties) { - String baseUrl = "jdbc:clickhouse://" + getClickHouseHttpAddress(); - if (url == null) { - url = baseUrl; - } else if (!url.startsWith("jdbc:")) { - url = baseUrl + "/" + url; - } - - return new ClickHouseDataSource(url, properties); - } - - public BalancedClickhouseDataSource newBalancedDataSource(String... addresses) { - return newBalancedDataSource(new ClickHouseProperties(), addresses); - } - - public BalancedClickhouseDataSource newBalancedDataSource(ClickHouseProperties properties, String... addresses) { - return newBalancedDataSourceWithSuffix(null, properties, addresses); - } - - public BalancedClickhouseDataSource newBalancedDataSourceWithSuffix(String urlSuffix, - ClickHouseProperties properties, String... addresses) { - StringBuilder url = new StringBuilder().append("jdbc:clickhouse://"); - if (addresses == null || addresses.length == 0) { - url.append(getClickHouseHttpAddress()); - } else { - int position = url.length(); - for (int i = 0; i < addresses.length; i++) { - url.append(',').append(addresses[i]); - } - url.deleteCharAt(position); - } - - if (urlSuffix != null) { - url.append('/').append(urlSuffix); - } - - return new BalancedClickhouseDataSource(url.toString(), properties); - } - - public ClickHouseConnection newConnection() throws SQLException { - return newConnection(null); - } - - public ClickHouseConnection newConnection(ClickHouseProperties properties) throws SQLException { - try (ClickHouseConnection conn = newDataSource().getConnection(); - ClickHouseStatement stmt = conn.createStatement();) { - stmt.execute("CREATE DATABASE IF NOT EXISTS " + dbName); - } - - return newDataSource(dbName, properties == null ? new ClickHouseProperties() : properties).getConnection(); - } - - public void closeConnection(Connection conn) throws SQLException { - if (conn == null) { - return; - } - - try (Statement stmt = conn.createStatement()) { - stmt.execute("DROP DATABASE IF EXISTS " + dbName); - } finally { - conn.close(); - } - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/PreparedStatementParserTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/PreparedStatementParserTest.java deleted file mode 100644 index cc489da27..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/PreparedStatementParserTest.java +++ /dev/null @@ -1,496 +0,0 @@ -package ru.yandex.clickhouse; - -import java.util.List; - -import org.testng.Assert; -import org.testng.annotations.Test; - - -/** - * Unit tests for {@link PreparedStatementParser} - */ -public class PreparedStatementParserTest { - - @Test(groups = "unit") - public void testNullSafety() { - try { - PreparedStatementParser.parse(null); - Assert.fail(); - } catch (IllegalArgumentException iae) { /* expected */ } - } - - @Test(groups = "unit") - public void testParseSimple() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (a, b) VALUES (?, ?)"); - assertMatchParams(new String[][] {{"?", "?"}}, s); - } - - @Test(groups = "unit") - public void testParseConstantSimple() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (a, b) VALUES (?, 'foo')"); - assertMatchParams(new String[][] {{"?", "'foo'"}}, s); - } - - @Test(groups = "unit") - public void testParseSimpleWhitespaceValueMode() { - PreparedStatementParser s = PreparedStatementParser.parse( - " INSERT\t INTO t(a, b) VALUES(?, ?)"); - assertMatchParams(new String[][] {{"?", "?"}}, s); - } - - @Test(groups = "unit") - public void testParseConstantSimpleInt() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (a, b) VALUES (?, 42)"); - assertMatchParams(new String[][] {{"?", "42"}}, s); - } - - @Test(groups = "unit") - public void testParseConstantSimpleIntTrailingWhitespace() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (a, b) VALUES (?,42 )"); - assertMatchParams(new String[][] {{"?", "42"}}, s); - } - - @Test(groups = "unit") - public void testParseConstantSimpleIntTrailingLeadingWhitespace() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (a, b) VALUES (?, 42 )"); - assertMatchParams(new String[][] {{"?", "42"}}, s); - } - - @Test(groups = "unit") - public void testParseParentheses() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (a, b) VALUES ((?), ('foo'))"); - assertMatchParams(new String[][] {{"?", "'foo'"}}, s); - } - - @Test(groups = "unit") - public void testParseParenthesesInQuotes() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (a, b) VALUES ((?), ('foo)))'))"); - assertMatchParams(new String[][] {{"?", "'foo)))'"}}, s); - } - - @Test(groups = "unit") - public void testParseEscapedQuote() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (a, b) VALUES (?, 'foo\\'bar')"); - assertMatchParams(new String[][] {{"?", "'foo\\'bar'"}}, s); - } - - @Test(groups = "unit") - public void testParseEscapedQuoteBroken() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (a, b) VALUES (?, 'foo\'bar')"); - Assert.assertTrue(s.getParameters().isEmpty()); // Is this expected? - } - - @Test(groups = "unit") - public void testParseQuestionMarkInQuotes() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (a, b) VALUES ('?', 'foo')"); - assertMatchParams(new String[][] {{"'?'", "'foo'"}}, s); - } - - @Test(groups = "unit") - public void testParseQuestionMarkAndMoreInQuotes() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (a, b) VALUES ('? foo ?', 'bar')"); - assertMatchParams(new String[][] {{"'? foo ?'", "'bar'"}}, s); - } - - @Test(groups = "unit") - public void testParseEscapedQuestionMark() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (a, b) VALUES (\\?, 'foo')"); - assertMatchParams(new String[][] {{"'foo'"}}, s); - } - - @Test(groups = "unit") - public void testNoCommasQuestionMarks() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (a, b) VALUES (foo ? bar ?)"); - List> matrix = s.getParameters(); - Assert.assertEquals(matrix.size(), 1); - Assert.assertEquals(matrix.get(0).size(), 1); - } - - @Test(groups = "unit") - public void testParseIgnoreInsert() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (foo, ?) VALUES (?, 'bar')"); - assertMatchParams(new String[][] {{"?", "'bar'"}}, s); - } - - @Test(groups = "unit") - public void testDoubleComma() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (a, b) VALUES (?, 'bar',, ?, , ?)"); - assertMatchParams(new String[][] {{"?", "'bar'", "?", "?"}}, s); - } - - @Test(groups = "unit") - public void testDoubleSingleQuote() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (a) VALUES ('')"); - assertMatchParams(new String[][] {{"''"}}, s); - } - - @Test(groups = "unit") - public void testInsertNumbers() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (foo, bar, baz) VALUES (42, 23, '42')"); - assertMatchParams(new String[][] {{"42", "23", "'42'"}}, s); - } - - @Test(groups = "unit") - public void testInsertBoolean() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (foo, bar) VALUES (TRUE, false)"); - assertMatchParams(new String[][] {{"1", "0"}}, s); - } - - @Test(groups = "unit") - public void testMultiParams() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (a, b) VALUES (?, ?), (?, ?)"); - assertMatchParams( - new String[][] { - {"?", "?" }, - {"?", "?" } - }, - s); - } - - @Test(groups = "unit") - public void testMultiParamsWithConstants() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (a, b) VALUES (?, 'foo'), ('bar', ?)"); - assertMatchParams( - new String[][] { - {"?", "'foo'" }, - {"'bar'", "?" } - }, - s); - } - - @Test(groups = "unit") - public void testValuesModeDoubleQuotes() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (\"foo.bar\") VALUES (?)"); - assertMatchParams(new String[][] {{"?"}}, s); - Assert.assertEquals(s.getParts().get(0), "INSERT INTO t (\"foo.bar\") VALUES ("); - } - - @Test(groups = "unit") - public void testValuesModeDoubleQuotesValues() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (\"foo.bar\") VALUES (\"baz\")"); - assertMatchParams(new String[][] {{"\"baz\""}}, s); - Assert.assertEquals(s.getParts().get(0), "INSERT INTO t (\"foo.bar\") VALUES ("); - } - - @Test(groups = "unit") - public void testValuesModeSingleQuotes() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t ('foo.bar') VALUES (?)"); - assertMatchParams(new String[][] {{"?"}}, s); - Assert.assertEquals(s.getParts().get(0), "INSERT INTO t ('foo.bar') VALUES ("); - } - - @Test(groups = "unit") - public void testValuesModeSingleQuotesValues() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t ('foo.bar') VALUES ('baz')"); - assertMatchParams(new String[][] {{"'baz'"}}, s); - Assert.assertEquals(s.getParts().get(0), "INSERT INTO t ('foo.bar') VALUES ("); - } - - @Test(groups = "unit") - public void testParseInsertSelect() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (a, b) SELECT x, y"); - Assert.assertEquals(s.getParts().get(0), "INSERT INTO t (a, b) SELECT x, y"); - Assert.assertTrue(s.getParameters().isEmpty()); - } - - @Test(groups = "unit") - public void testParseInsertSelectParams() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO t (a, b) SELECT x FROM u WHERE y = ? AND z = ?"); - Assert.assertEquals(s.getParts().get(0), - "INSERT INTO t (a, b) SELECT x FROM u WHERE y = "); - Assert.assertEquals(" AND z = ", s.getParts().get(1)); - assertMatchParams(new String[][] {{"?", "?"}}, s); - } - - @Test(groups = "unit") - public void testParseSelectGroupBy() { - PreparedStatementParser s = PreparedStatementParser.parse( - "SELECT SUM(x) FROM t WHERE y = ? GROUP BY ? HAVING COUNT(z) > ? ORDER BY z DESC"); - Assert.assertEquals("SELECT SUM(x) FROM t WHERE y = ", - s.getParts().get(0)); - Assert.assertEquals(s.getParts().get(1), " GROUP BY "); - Assert.assertEquals(s.getParts().get(2), " HAVING COUNT(z) > "); - Assert.assertEquals(s.getParts().get(3), " ORDER BY z DESC"); - assertMatchParams(new String[][] {{"?", "?", "?"}}, s); - } - - @Test(groups = "unit") - public void testParseWithComment1() { - PreparedStatementParser s = PreparedStatementParser.parse( - "select a --what is it?\nfrom t where a = ? and b = 1"); - Assert.assertEquals( s.getParts().get(0), "select a --what is it?\nfrom t where a = "); - Assert.assertEquals(s.getParts().get(1), " and b = 1"); - assertMatchParams(new String[][] {{"?"}}, s); - } - - @Test(groups = "unit") - public void testParseWithComment2() { - PreparedStatementParser s = PreparedStatementParser.parse( - "select a /*what is it?*/ from t where a = ? and b = 1"); - assertMatchParts(new String[] { - "select a /*what is it?*/ from t where a = ", - " and b = 1"}, - s); - assertMatchParams(new String[][] {{"?"}}, s); - } - - @Test(groups = "unit") - public void testParseSelectStar() { - PreparedStatementParser s = PreparedStatementParser.parse( - "SELECT * FROM tbl"); - assertMatchParts(new String[] {"SELECT * FROM tbl"}, s); - Assert.assertTrue(s.getParameters().isEmpty()); - } - - @Test(groups = "unit") - public void testParseSelectStarParam() { - PreparedStatementParser s = PreparedStatementParser.parse( - "SELECT * FROM tbl WHERE t = ?"); - assertMatchParts(new String[] {"SELECT * FROM tbl WHERE t = ", ""}, s); - assertMatchParams(new String[][] {{"?"}}, s); - } - - @Test(groups = "unit") - public void testParseSelectEscapedGarbage() { - PreparedStatementParser s = PreparedStatementParser.parse( - "SELECT 'a\\'\\\\sdfasdf?adsf\\\\' as `sadf\\`?` FROM tbl WHERE t = ? AND r = ? ORDER BY 1"); - assertMatchParts(new String[] { - "SELECT 'a\\'\\\\sdfasdf?adsf\\\\' as `sadf\\`?` FROM tbl WHERE t = ", - " AND r = ", - " ORDER BY 1"}, - s); - assertMatchParams(new String[][] {{"?", "?"}}, s); - } - - @Test(groups = "unit") - public void testRegularParam() throws Exception { - // Test inspired by MetaBase test cases - PreparedStatementParser s = PreparedStatementParser.parse( - "SELECT count(*) AS `count` FROM `foo`.`bar` " - + "WHERE (`foo`.`bar`.`id` <= 32 " - + "AND (`foo`.`bar`.`name` like ?))"); - assertMatchParams(new String[][] {{"?"}}, s); - Assert.assertEquals( - s.getParts().get(0), - "SELECT count(*) AS `count` FROM `foo`.`bar` " - + "WHERE (`foo`.`bar`.`id` <= 32 " - + "AND (`foo`.`bar`.`name` like "); - Assert.assertEquals( - s.getParts().get(1), - "))"); - } - - @Test(groups = "unit") - public void testRegularParamWhitespace() throws Exception { - PreparedStatementParser s = PreparedStatementParser.parse( - "SELECT count(*) AS `count` FROM `foo`.`bar` " - + "WHERE (`foo`.`bar`.`id` <= 32 " - + "AND (`foo`.`bar`.`name` like ? ))"); - assertMatchParams(new String[][] {{"?"}}, s); - Assert.assertEquals( - s.getParts().get(0), - "SELECT count(*) AS `count` FROM `foo`.`bar` " - + "WHERE (`foo`.`bar`.`id` <= 32 " - + "AND (`foo`.`bar`.`name` like "); - Assert.assertEquals( - s.getParts().get(1), - " ))"); - } - - @Test(groups = "unit") - public void testRegularParamInFunction() throws Exception { - PreparedStatementParser s = PreparedStatementParser.parse( - "SELECT count(*) AS `count` FROM `foo`.`bar` " - + "WHERE toMonday(`foo`.`bar`.`date`) = toMonday(?)"); - assertMatchParams(new String[][] {{"?"}}, s); - Assert.assertEquals( - s.getParts().get(0), - "SELECT count(*) AS `count` FROM `foo`.`bar` " - + "WHERE toMonday(`foo`.`bar`.`date`) = toMonday("); - Assert.assertEquals( - s.getParts().get(1), - ")"); - } - - @Test(groups = "unit") - public void testNullValuesSelect() throws Exception { - PreparedStatementParser s = PreparedStatementParser.parse( - "SELECT 1 FROM foo WHERE bar IN (?, NULL)"); - List> params = s.getParameters(); - Assert.assertEquals(params.size(), 1); - Assert.assertEquals(params.get(0).size(), 1); - Assert.assertEquals(params.get(0).get(0), "?"); - } - - @Test(groups = "unit") - public void testNullValuesInsert() throws Exception { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO test.prep_nullable_value (s, i, f) VALUES " - + "(?, NULL, ?), (NULL, null , ?)"); - assertMatchParams(new String[][] { - {"?", "\\N", "?"}, - {"\\N", "\\N", "?"}}, - s); - } - - @Test(groups = "unit") - public void testParamLastCharacter() throws Exception { - PreparedStatementParser s = PreparedStatementParser.parse( - "SELECT * FROM decisions " - + "PREWHERE userID = ? " - + "AND eventDate >= toDate(?) " - + "AND eventDate <= toDate(?) " - + "ORDER BY time DESC LIMIT ?, ?"); - assertMatchParams(new String[][] {{"?", "?", "?", "?", "?"}}, s); - Assert.assertEquals(s.getParts().size(), 6); - Assert.assertEquals(s.getParts().get(0), "SELECT * FROM decisions PREWHERE userID = "); - Assert.assertEquals(s.getParts().get(1), " AND eventDate >= toDate("); - Assert.assertEquals(s.getParts().get(2), ") AND eventDate <= toDate("); - Assert.assertEquals(s.getParts().get(3), ") ORDER BY time DESC LIMIT "); - Assert.assertEquals(s.getParts().get(4), ", "); - Assert.assertEquals(s.getParts().get(5), ""); - } - - @Test(groups = "unit") - public void testSingleAndBackMixedQuotes() { - PreparedStatementParser s = PreparedStatementParser.parse( - "SELECT '`' as `'` WHERE 0 = ?"); - assertMatchParams(new String[][] {{"?"}}, s); - Assert.assertEquals(s.getParts().get(0), "SELECT '`' as `'` WHERE 0 = "); - } - - - @Test(groups = "unit") - public void testInsertValuesFunctions() throws Exception { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO foo(id, src, dst) " - + "VALUES (?, IPv4ToIPv6(toIPv4(?)), IPv4ToIPv6(toIPv4(?)))"); - assertMatchParams(new String[][] {{ "?", "?", "?" }}, s); - assertMatchParts(new String[] { - "INSERT INTO foo(id, src, dst) VALUES (", - ", IPv4ToIPv6(toIPv4(", - ")), IPv4ToIPv6(toIPv4(", - ")))"}, s); - } - - @Test(groups = "unit") - public void testMultiLineValues() { - PreparedStatementParser s = PreparedStatementParser.parse( - "INSERT INTO table1\n" - + "\t(foo, bar)\r\n" - + "\t\tVALUES\n" - + "(?, ?) , \r\n" - + "\t(?,?),(?,?)\n"); - Assert.assertTrue(s.isValuesMode()); - assertMatchParams(new String[][] {{"?", "?"}, {"?", "?"}, {"?", "?"}}, s); - Assert.assertEquals(s.getParts().get(0), - "INSERT INTO table1\n" - + "\t(foo, bar)\r\n" - + "\t\tVALUES\n" - + "("); - Assert.assertEquals(7, s.getParts().size()); - Assert.assertEquals(s.getParts().get(0), - "INSERT INTO table1\n" - + "\t(foo, bar)\r\n" - + "\t\tVALUES\n" - + "("); - Assert.assertEquals(s.getParts().get(1), ", "); - Assert.assertEquals(s.getParts().get(2), - ") , \r\n" - + "\t("); - Assert.assertEquals(s.getParts().get(3), ","); - Assert.assertEquals(s.getParts().get(4), "),("); - Assert.assertEquals(s.getParts().get(5), ","); - Assert.assertEquals(s.getParts().get(6), ")\n"); - } - - private static void assertMatchParts(String[] expected, PreparedStatementParser stmt) { - List parts = stmt.getParts(); - Assert.assertEquals( parts.size(), expected.length); - for (int i = 0; i < expected.length; i++) { - Assert.assertEquals(parts.get(i), expected[i]); - } - } - - private static void assertMatchParams(String[][] expected, PreparedStatementParser stmt) { - List> actual = stmt.getParameters(); - if (expected.length != actual.size()) { - Assert.assertEquals(formatParamsList(actual), formatParams(expected)); - } - if (expected.length == 0 && actual.isEmpty()) { - return; - } - for (int i = 0; i < expected.length; i++) { - String[] expRow = expected[i]; - String[] actRow = actual.get(i).toArray(new String[actual.get(i).size()]); - Assert.assertEquals(actRow.length, expRow.length); - for (int j = 0; j < expRow.length; j++) { - Assert.assertEquals(actRow[j], expRow[j]); - } - } - } - - private static String formatParamsList(List> params) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < params.size(); i++) { - sb.append("row ") - .append(i) - .append(": ") - .append(formatRow(params.get(i).toArray(new String[params.get(i).size()]))) - .append("\n"); - } - return sb.length() > 1 ? - sb.substring(0, sb.length() - 1) - : null; - } - - private static String formatParams(String[][] params) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < params.length; i++) { - sb.append("row ") - .append(i) - .append(": ") - .append(formatRow(params[i])) - .append("\n"); - } - return sb.substring(0, sb.length() - 1); - } - - private static String formatRow(String[] paramGroup) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < paramGroup.length; i++) { - sb.append(i) - .append(": ") - .append(paramGroup[i]) - .append(", "); - } - return sb.substring(0, sb.length() - 2); - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/WriterTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/WriterTest.java deleted file mode 100644 index 834f4de97..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/WriterTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package ru.yandex.clickhouse; - -import org.mockito.Mockito; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import ru.yandex.clickhouse.domain.ClickHouseFormat; -import ru.yandex.clickhouse.util.ClickHouseStreamCallback; - -import java.io.ByteArrayInputStream; -import java.sql.SQLException; - -public class WriterTest { - - private ClickHouseStatementImpl statement; - - @BeforeClass(groups = "unit") - public void setUp() throws SQLException { - statement = Mockito.mock(ClickHouseStatementImpl.class); - Mockito.when(statement.write()).thenReturn(new Writer(statement)); - } - - @Test(groups = "unit", expectedExceptions = SQLException.class, expectedExceptionsMessageRegExp = ".*No input data.*") - public void testNonConfigured() throws SQLException { - statement.write().send(); - } - - @Test(groups = "unit", expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "Format can not be null") - public void testNullFormatGiven() { - statement.write().format(null); - } - - @Test(groups = "unit", expectedExceptions = SQLException.class, expectedExceptionsMessageRegExp = "Wrong binary format.*") - public void testWrongBinaryFormat() throws SQLException { - statement.write().send("INSERT", (ClickHouseStreamCallback)null, ClickHouseFormat.CSV); - } - - @Test(groups = "unit") - public void testWhitePath() throws SQLException { - statement - .write() - .format(ClickHouseFormat.CSV) - .table("my_table") - .data(new ByteArrayInputStream(new byte[1])) - .send(); - } - - @Test(groups = "unit") - public void testSendToTable() throws SQLException { - statement.write().sendToTable("table", new ByteArrayInputStream(new byte[1]), ClickHouseFormat.CSV); - } -} \ No newline at end of file diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/domain/ClickHouseDataTypeTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/domain/ClickHouseDataTypeTest.java deleted file mode 100644 index a9dce3dca..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/domain/ClickHouseDataTypeTest.java +++ /dev/null @@ -1,16 +0,0 @@ -package ru.yandex.clickhouse.domain; - -import java.util.Locale; - -import org.testng.annotations.Test; - -import static org.testng.Assert.assertEquals; - -public class ClickHouseDataTypeTest { - @Test(groups = "unit", dataProvider = "clickHouseDataTypeStringsProvider", dataProviderClass = ClickHouseDataTypeTestDataProvider.class) - public void testFromDataTypeStringSimpleTypes(String typeName, ClickHouseDataType result) { - assertEquals(ClickHouseDataType.fromTypeString(typeName), result, typeName); - assertEquals(ClickHouseDataType.fromTypeString(typeName.toUpperCase(Locale.ROOT)), result); - assertEquals(ClickHouseDataType.fromTypeString(typeName.toLowerCase(Locale.ROOT)), result); - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/domain/ClickHouseDataTypeTestDataProvider.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/domain/ClickHouseDataTypeTestDataProvider.java deleted file mode 100644 index 776ff1752..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/domain/ClickHouseDataTypeTestDataProvider.java +++ /dev/null @@ -1,160 +0,0 @@ -package ru.yandex.clickhouse.domain; - -import java.util.ArrayList; -import java.util.List; - -import org.testng.annotations.DataProvider; - -public class ClickHouseDataTypeTestDataProvider { - - private static ClickHouseDataTypeTestData[] testData; - - @DataProvider(name = "clickHouseDataTypeStringsProvider") - public static Object[][] provideSimpleDataTypes() { - Object[][] myData = new Object[getTestData().length][2]; - for (int i = 0; i < getTestData().length; i++) { - myData[i][0] = getTestData()[i].simpleTypeName; - myData[i][1] = getTestData()[i].clickHouseDataType; - } - return myData; - } - - public static List provideDataTypes() { - List filtered = new ArrayList<>(); - for (int i = 0; i < getTestData().length; i++) { - ClickHouseDataTypeTestData d = getTestData()[i]; - if (d.isCheckValue()) { - filtered.add(d); - } - } - return filtered; - } - - private static ClickHouseDataTypeTestData[] getTestData() { - if (testData == null) { - testData = initTestData(); - } - return testData; - } - - private static ClickHouseDataTypeTestData[] initTestData() { - return new ClickHouseDataTypeTestData[] { - create("IntervalYear", ClickHouseDataType.IntervalYear, "IntervalYear", "42", true, true), - create("IntervalQuarter", ClickHouseDataType.IntervalQuarter, "IntervalQuarter", "42", true, true), - create("IntervalDay", ClickHouseDataType.IntervalDay, "IntervalDay", "42", true, true), - create("IntervalWeek", ClickHouseDataType.IntervalWeek, "IntervalWeek", "42", true, true), - create("IntervalHour", ClickHouseDataType.IntervalHour, "IntervalHour", "42", true, true), - create("IntervalMinute", ClickHouseDataType.IntervalMinute, "IntervalMinute", "42", true, true), - create("Nested", ClickHouseDataType.Nested), - create("IntervalMonth", ClickHouseDataType.IntervalMonth, "IntervalMonth", "42", true, true), - create("Tuple", ClickHouseDataType.Tuple, "Tuple(String, UInt32)", "('foo', 42)", true, true), - create("AggregateFunction", ClickHouseDataType.AggregateFunction), - create("FixedString", ClickHouseDataType.FixedString, "FixedString(6)", "FOOBAR", true, true), - create("IntervalSecond", ClickHouseDataType.IntervalSecond, "IntervalSecond", "42", true, true), - create("UInt64", ClickHouseDataType.UInt64, "UInt64", "42", true, true), - create("Enum8", ClickHouseDataType.Enum8, "Enum8(1 = 'foo', 2 = 'bar')", "foo", true, true), - create("Int32", ClickHouseDataType.Int32, "Int32", "-23", true, true), - create("Int16", ClickHouseDataType.Int16, "Int16", "-23", true, true), - create("Int8", ClickHouseDataType.Int8, "Int8", "-42", true, true), - create("Date", ClickHouseDataType.Date, "Date", "2019-05-02", true, true), - create("UInt32", ClickHouseDataType.UInt32, "UInt32", "42", true, true), - create("UInt8", ClickHouseDataType.UInt8, "UInt8", "23", true, true), - create("Enum16", ClickHouseDataType.Enum16, "Enum16(1 = 'foo', 2 = 'bar')", "foo", true, false), - create("DateTime", ClickHouseDataType.DateTime, "DateTime", "2019-05-02 13:37:00", true, true), - create("UInt16", ClickHouseDataType.UInt16, "UInt16", "42", true, true), - create("Nothing", ClickHouseDataType.Nothing), - create("Array", ClickHouseDataType.Array), - create("Int64", ClickHouseDataType.Int64, "Int64", "-42", true, true), - create("Float32", ClickHouseDataType.Float32, "Float32", "0.42", true, false), - create("Float64", ClickHouseDataType.Float64, "Float64", "-0.23", true, false), - create("Decimal32", ClickHouseDataType.Decimal32, "Decimal32(4)", "0.4242", true, false), - create("Decimal64", ClickHouseDataType.Decimal64, "Decimal64(4)", "1337.23", true, false), - create("Decimal128", ClickHouseDataType.Decimal128, "Decimal128(4)", "1337.23", true, false), - create("UUID", ClickHouseDataType.UUID, "UUID", "61f0c404-5cb3-11e7-907b-a6006ad3dba0", true, false), - create("String", ClickHouseDataType.String, "String", "foo", true, true), - create("Decimal", ClickHouseDataType.Decimal, "Decimal(12,3)", "23.420", true, true), - create("LONGBLOB", ClickHouseDataType.String), - create("MEDIUMBLOB", ClickHouseDataType.String), - create("TINYBLOB", ClickHouseDataType.String), - create("BIGINT", ClickHouseDataType.Int64), - create("SMALLINT", ClickHouseDataType.Int16), - create("TIMESTAMP", ClickHouseDataType.DateTime), - create("INTEGER", ClickHouseDataType.Int32), - create("INT", ClickHouseDataType.Int32), - create("DOUBLE", ClickHouseDataType.Float64), - create("MEDIUMTEXT", ClickHouseDataType.String), - create("TINYINT", ClickHouseDataType.Int8), - create("DEC", ClickHouseDataType.Decimal), - create("BINARY", ClickHouseDataType.FixedString), - create("REAL", ClickHouseDataType.Float32), - create("CHAR", ClickHouseDataType.String), - create("VARCHAR", ClickHouseDataType.String), - create("TEXT", ClickHouseDataType.String), - create("TINYTEXT", ClickHouseDataType.String), - create("LONGTEXT", ClickHouseDataType.String), - create("BLOB", ClickHouseDataType.String), - create("FANTASY", ClickHouseDataType.Unknown, "Fantasy", "[42, 23]", true, true) - }; - } - - private static ClickHouseDataTypeTestData create(String simpleTypeName, - ClickHouseDataType clickHouseDataType, String typeName, - String testValue, boolean nullableCandidate, - boolean lowCardinalityCandidate) - { - return new ClickHouseDataTypeTestData(simpleTypeName, clickHouseDataType, - typeName, testValue, nullableCandidate, lowCardinalityCandidate); - } - - private static ClickHouseDataTypeTestData create(String simpleTypeName, - ClickHouseDataType clickHouseDataType) - { - return new ClickHouseDataTypeTestData(simpleTypeName, clickHouseDataType, - null, null, false, false); - } - - public static final class ClickHouseDataTypeTestData { - - private final String simpleTypeName; - private final ClickHouseDataType clickHouseDataType; - private final String typeName; - private final String testValue; - private final boolean nullableCandidate; - private final boolean lowCardinalityCandidate; - - ClickHouseDataTypeTestData(String simpleTypeName, - ClickHouseDataType clickHouseDataType, String typeName, - String testValue, boolean nullableCandidate, - boolean lowCardinalityCandidate) - { - this.simpleTypeName = simpleTypeName; - this.clickHouseDataType = clickHouseDataType; - this.typeName = typeName; - this.testValue = testValue; - this.nullableCandidate = nullableCandidate; - this.lowCardinalityCandidate = lowCardinalityCandidate; - } - - private boolean isCheckValue() { - return typeName != null; - } - - public String getTypeName() { - return typeName; - } - - public boolean isNullableCandidate() { - return nullableCandidate; - } - - public boolean isLowCardinalityCandidate() { - return lowCardinalityCandidate; - } - - public String getTestValue() { - return testValue; - } - - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/domain/ClickHouseFormatTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/domain/ClickHouseFormatTest.java deleted file mode 100644 index febba8fd0..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/domain/ClickHouseFormatTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package ru.yandex.clickhouse.domain; - -import org.testng.annotations.Test; - -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; - -public class ClickHouseFormatTest { - - @Test(groups = "unit") - public void testNull() { - assertFalse(ClickHouseFormat.containsFormat(null)); - } - - @Test(groups = "unit") - public void testEmpty() { - assertFalse(ClickHouseFormat.containsFormat(" \t \r\n")); - } - - @Test(groups = "unit") - public void testTrailingWhitespace() { - assertFalse(ClickHouseFormat.containsFormat("Phantasy ")); - assertTrue(ClickHouseFormat.containsFormat("TabSeparatedWithNamesAndTypes ")); - assertTrue(ClickHouseFormat.containsFormat("TabSeparatedWithNamesAndTypes \t \n")); - } - - @Test(groups = "unit") - public void testTrailingSemicolon() { - assertFalse(ClickHouseFormat.containsFormat("Phantasy ;")); - assertTrue(ClickHouseFormat.containsFormat("TabSeparatedWithNamesAndTypes ; ")); - assertTrue(ClickHouseFormat.containsFormat("TabSeparatedWithNamesAndTypes ;")); - assertTrue(ClickHouseFormat.containsFormat("TabSeparatedWithNamesAndTypes \t ; \n")); - } - - @Test(groups = "unit") - public void testAllFormats() { - for (ClickHouseFormat format : ClickHouseFormat.values()) { - assertTrue(ClickHouseFormat.containsFormat(format.name())); - } - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ArrayTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ArrayTest.java deleted file mode 100644 index 4a607c429..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ArrayTest.java +++ /dev/null @@ -1,235 +0,0 @@ -package ru.yandex.clickhouse.integration; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Array; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.sql.Types; -import java.util.ArrayList; -import java.util.Arrays; - -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.ClickHouseArray; -import ru.yandex.clickhouse.ClickHouseDataSource; -import ru.yandex.clickhouse.ClickHousePreparedStatement; -import ru.yandex.clickhouse.JdbcIntegrationTest; -import ru.yandex.clickhouse.domain.ClickHouseDataType; - -/** - * Here it is assumed the connection to a ClickHouse instance with flights example data it available at localhost:8123 - * For ClickHouse quickstart and example dataset see https://clickhouse.yandex/tutorial.html - */ -public class ArrayTest extends JdbcIntegrationTest { - private Connection connection; - - @BeforeClass(groups = "integration") - public void setUp() throws Exception { - connection = newConnection(); - } - - @AfterClass(groups = "integration") - public void tearDown() throws Exception { - closeConnection(connection); - } - - @Test(groups = "integration") - public void testStringArray() throws SQLException { - String[] array = {"a'','sadf',aa", "", ",", "юникод,'юникод'", ",2134,saldfk"}; - - StringBuilder sb = new StringBuilder(); - for (String s : array) { - sb.append("','").append(s.replace("'", "\\'")); - } - - if (sb.length() > 0) { - sb.deleteCharAt(0).deleteCharAt(0).append('\''); - } - - String arrayString = sb.toString(); - - Statement statement = connection.createStatement(); - ResultSet rs = statement.executeQuery("select array(" + arrayString + ")"); - while (rs.next()) { - Assert.assertEquals(rs.getArray(1).getBaseType(), Types.VARCHAR); - String[] stringArray = (String[]) rs.getArray(1).getArray(); - Assert.assertEquals(stringArray.length, array.length); - for (int i = 0; i < stringArray.length; i++) { - Assert.assertEquals(stringArray[i], array[i]); - } - } - statement.close(); - } - - @Test(groups = "integration") - public void testLongArray() throws SQLException { - Long[] array = {-12345678987654321L, 23325235235L, -12321342L}; - StringBuilder sb = new StringBuilder(); - for (long l : array) { - sb.append("),toInt64(").append(l); - } - if (sb.length() > 0) { - sb.deleteCharAt(0).deleteCharAt(0).append(')'); - } - String arrayString = sb.toString(); - - Statement statement = connection.createStatement(); - ResultSet rs = statement.executeQuery("select array(" + arrayString + ")"); - while (rs.next()) { - Assert.assertEquals(rs.getArray(1).getBaseType(), Types.BIGINT); - long[] longArray = (long[]) rs.getArray(1).getArray(); - Assert.assertEquals(longArray.length, array.length); - for (int i = 0; i < longArray.length; i++) { - Assert.assertEquals(longArray[i], array[i].longValue()); - } - } - statement.close(); - } - - @Test(groups = "integration") - public void testDecimalArray() throws SQLException { - BigDecimal[] array = {BigDecimal.valueOf(-12.345678987654321), BigDecimal.valueOf(23.325235235), BigDecimal.valueOf(-12.321342)}; - StringBuilder sb = new StringBuilder(); - for (BigDecimal d : array) { - sb.append(", 15),toDecimal64(").append(d); - } - if (sb.length() > 0) { - sb.deleteCharAt(0).delete(0, sb.indexOf(",") + 1).append(", 15)"); - } - String arrayString = sb.toString(); - - Statement statement = connection.createStatement(); - ResultSet rs = statement.executeQuery("select array(" + arrayString + ")"); - while (rs.next()) { - Assert.assertEquals(rs.getArray(1).getBaseType(), Types.DECIMAL); - BigDecimal[] deciamlArray = (BigDecimal[]) rs.getArray(1).getArray(); - Assert.assertEquals(deciamlArray.length, array.length); - for (int i = 0; i < deciamlArray.length; i++) { - Assert.assertEquals(0, deciamlArray[i].compareTo(array[i])); - } - } - statement.close(); - } - - @Test(groups = "integration") - public void testInsertUIntArray() throws SQLException { - connection.createStatement().execute("DROP TABLE IF EXISTS unsigned_array"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS unsigned_array" - + " (ua32 Array(UInt32), ua64 Array(UInt64), f64 Array(Float64), a32 Array(Int32)) ENGINE = TinyLog" - ); - - String insertSql = "INSERT INTO unsigned_array (ua32, ua64, f64, a32) VALUES (?, ?, ?, ?)"; - - PreparedStatement statement = connection.prepareStatement(insertSql); - - statement.setArray(1, new ClickHouseArray(ClickHouseDataType.UInt64, new long[]{4294967286L, 4294967287L})); - statement.setArray(2, new ClickHouseArray(ClickHouseDataType.UInt64, new BigInteger[]{new BigInteger("18446744073709551606"), new BigInteger("18446744073709551607")})); - statement.setArray(3, new ClickHouseArray(ClickHouseDataType.Float64, new double[]{1.23, 4.56})); - statement.setArray(4, new ClickHouseArray(ClickHouseDataType.Int32, new int[]{-2147483648, 2147483647})); - statement.execute(); - - statement = connection.prepareStatement(insertSql); - - statement.setObject(1, new ArrayList(Arrays.asList(4294967286L, 4294967287L))); - statement.setObject(2, new ArrayList(Arrays.asList( - new BigInteger("18446744073709551606"), - new BigInteger("18446744073709551607")))); - statement.setObject(3, new ArrayList(Arrays.asList(1.23, 4.56))); - statement.setObject(4, Arrays.asList(-2147483648, 2147483647)); - statement.execute(); - - Statement select = connection.createStatement(); - ResultSet rs = select.executeQuery("select ua32, ua64, f64, a32 from unsigned_array"); - for (int i = 0; i < 2; ++i) { - rs.next(); - Array bigUInt32 = rs.getArray(1); - Assert.assertEquals(bigUInt32.getBaseType(), Types.BIGINT); // - Assert.assertEquals(bigUInt32.getArray().getClass(), long[].class); - Assert.assertEquals(((long[]) bigUInt32.getArray())[0], 4294967286L); - Assert.assertEquals(((long[]) bigUInt32.getArray())[1], 4294967287L); - Array bigUInt64 = rs.getArray(2); - Assert.assertEquals(bigUInt64.getBaseType(), Types.BIGINT); - Assert.assertEquals(bigUInt64.getArray().getClass(), BigInteger[].class); - Assert.assertEquals(((BigInteger[]) bigUInt64.getArray())[0], new BigInteger("18446744073709551606")); - Assert.assertEquals(((BigInteger[]) bigUInt64.getArray())[1], new BigInteger("18446744073709551607")); - Array float64 = rs.getArray(3); - Assert.assertEquals(float64.getBaseType(), Types.DOUBLE); - Assert.assertEquals(float64.getArray().getClass(), double[].class); - Assert.assertEquals(((double[]) float64.getArray())[0], 1.23, 0.0000001); - Assert.assertEquals(((double[]) float64.getArray())[1], 4.56, 0.0000001); - Array int32 = rs.getArray(4); - Assert.assertEquals(int32.getBaseType(), Types.INTEGER); // - Assert.assertEquals(int32.getArray().getClass(), int[].class); - Assert.assertEquals(((int[]) int32.getArray())[0], -2147483648); - Assert.assertEquals(((int[]) int32.getArray())[1], 2147483647); - } - } - - @Test(groups = "integration") - public void testInsertStringArray() throws Exception { - connection.createStatement().execute("DROP TABLE IF EXISTS string_array"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS string_array (foo Array(String)) ENGINE = TinyLog"); - - String insertSQL = "INSERT INTO string_array (foo) VALUES (?)"; - PreparedStatement statement = connection.prepareStatement(insertSQL); - statement.setArray(1, connection.createArrayOf( - String.class.getCanonicalName(), - new String[]{"23", "42"})); - statement.executeUpdate(); - - ResultSet r = connection.createStatement().executeQuery( - "SELECT foo FROM string_array"); - r.next(); - String[] s = (String[]) r.getArray(1).getArray(); - Assert.assertEquals(s[0], "23"); - Assert.assertEquals(s[1], "42"); - } - - @Test(groups = "integration") - public void testInsertStringArrayViaUnwrap() throws Exception { - connection.createStatement().execute("DROP TABLE IF EXISTS string_array"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS string_array (foo Array(String)) ENGINE = TinyLog"); - - String insertSQL = "INSERT INTO string_array (foo) VALUES (?)"; - ClickHousePreparedStatement statement = connection.prepareStatement(insertSQL) - .unwrap(ClickHousePreparedStatement.class); - statement.setArray(1, new String[] {"23", "42"}); - statement.executeUpdate(); - - ResultSet r = connection.createStatement().executeQuery( - "SELECT foo FROM string_array"); - r.next(); - String[] s = (String[]) r.getArray(1).getArray(); - Assert.assertEquals(s[0], "23"); - Assert.assertEquals(s[1], "42"); - } - - // @Test(groups = "integration") - public void testInsertByteArray() throws Exception { - connection.createStatement().execute("DROP TABLE IF EXISTS int8_array"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS int8_array (foo Array(Int8)) ENGINE = Memory"); - - String insertSQL = "INSERT INTO int8_array (foo) VALUES (?)"; - PreparedStatement statement = connection.prepareStatement(insertSQL); - statement.setArray(1, new ClickHouseArray(ClickHouseDataType.Int8, new byte[]{12,34})); - statement.executeUpdate(); - - ResultSet r = connection.createStatement().executeQuery( - "SELECT foo FROM int8_array"); - r.next(); - int[] bytes = (int[]) r.getArray(1).getArray(); - Assert.assertEquals(bytes[0], 12); - Assert.assertEquals(bytes[1], 34); - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/BatchInsertsTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/BatchInsertsTest.java deleted file mode 100644 index f402c12c7..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/BatchInsertsTest.java +++ /dev/null @@ -1,317 +0,0 @@ -package ru.yandex.clickhouse.integration; - -import java.sql.Connection; -import java.sql.Date; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.sql.Timestamp; -import java.sql.Types; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Collections; -import java.util.TimeZone; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.ClickHouseDataSource; -import ru.yandex.clickhouse.ClickHousePreparedStatement; -import ru.yandex.clickhouse.ClickHousePreparedStatementImpl; -import ru.yandex.clickhouse.JdbcIntegrationTest; -import ru.yandex.clickhouse.settings.ClickHouseQueryParam; - -public class BatchInsertsTest extends JdbcIntegrationTest { - - private Connection connection; - private DateFormat dateFormat; - - @BeforeClass(groups = "integration") - public void setUp() throws Exception { - connection = newConnection(); - dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - dateFormat.setTimeZone(TimeZone.getDefault()); - } - - @AfterClass(groups = "integration") - public void tearDown() throws Exception { - closeConnection(connection); - } - - @Test(groups = "integration") - public void batchInsert() throws Exception { - - connection.createStatement().execute("DROP TABLE IF EXISTS batch_insert"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS batch_insert (i Int32, s String) ENGINE = TinyLog" - ); - - PreparedStatement statement = connection.prepareStatement("INSERT INTO batch_insert (s, i) VALUES (?, ?)"); - - statement.setString(1, "string1"); - statement.setInt(2, 21); - statement.addBatch(); - - statement.setString(1, "string2"); - statement.setInt(2, 32); - statement.addBatch(); - - statement.executeBatch(); - - ResultSet rs = connection.createStatement().executeQuery("SELECT count() as cnt from batch_insert"); - rs.next(); - - Assert.assertEquals(rs.getInt("cnt"), 2); - - Assert.assertFalse(rs.next()); - - } - - @Test(groups = "integration") - public void testBatchInsert2() throws Exception { - connection.createStatement().execute("DROP TABLE IF EXISTS batch_insert2"); - connection.createStatement().execute( - "CREATE TABLE batch_insert2 (" + - "date Date," + - "date_time DateTime," + - "string String," + - "int32 Int32," + - "float64 Float64" + - ") ENGINE = MergeTree order by date" - ); - - Date date = new Date(dateFormat.parse("1989-01-30").getTime()); - Timestamp dateTime = new Timestamp(1471008092000L); //2016-08-12 16:21:32 - String string = "testString"; - int int32 = Integer.MAX_VALUE; - double float64 = 42.21; - - PreparedStatement statement = connection.prepareStatement( - "INSERT INTO batch_insert2 (date, date_time, string, int32, float64) VALUES (?, ?, ?, ?, ?)" - ); - - statement.setDate(1, date); - statement.setTimestamp(2, dateTime); - statement.setString(3, string); - statement.setInt(4, int32); - statement.setDouble(5, float64); - statement.addBatch(); - statement.executeBatch(); - - ResultSet rs = connection.createStatement().executeQuery("SELECT * from batch_insert2"); - Assert.assertTrue(rs.next()); - - Assert.assertEquals(rs.getDate("date"), date); - Assert.assertEquals(rs.getTimestamp("date_time"), dateTime); - Assert.assertEquals(rs.getString("string"), string); - Assert.assertEquals(rs.getInt("int32"), int32); - Assert.assertEquals(rs.getDouble("float64"), float64); - - Assert.assertFalse(rs.next()); - } - - @Test(groups = "integration") - public void testBatchInsert3() throws Exception { - connection.createStatement().execute("DROP TABLE IF EXISTS batch_insert3"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS batch_insert3 (i Int32, s String) ENGINE = TinyLog" - ); - - ClickHousePreparedStatementImpl statement = (ClickHousePreparedStatementImpl) connection.prepareStatement("INSERT INTO batch_insert3 (s, i) VALUES (?, ?), (?, ?)"); - statement.setString(1, "firstParam"); - statement.setInt(2, 1); - statement.setString(3, "thirdParam"); - statement.setInt(4, 2); - statement.addBatch(); - int[] result = statement.executeBatch(); - Assert.assertEquals(result, new int[]{1, 1}); - - ResultSet rs = connection.createStatement().executeQuery("SELECT count() as cnt from batch_insert3"); - rs.next(); - - Assert.assertEquals(rs.getInt("cnt"), 2); - Assert.assertFalse(rs.next()); - } - - @Test(groups = "integration") - public void batchInsert4() throws Exception { - connection.createStatement().execute("DROP TABLE IF EXISTS batch_insert4"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS batch_insert4 (i Int32, s String) ENGINE = TinyLog" - ); - - PreparedStatement statement = connection.prepareStatement("INSERT INTO batch_insert4 (i, s) VALUES (?, 'hello'), (?, ?)"); - statement.setInt(1, 42); - statement.setInt(2, 43); - statement.setString(3, "first_param"); - statement.execute(); - - ResultSet rs = connection.createStatement().executeQuery("SELECT count() as cnt from batch_insert4"); - rs.next(); - - Assert.assertEquals(rs.getInt("cnt"), 2); - Assert.assertFalse(rs.next()); - } - - @Test(groups = "integration") - public void testBatchInsert5() throws Exception { - - connection.createStatement().execute("DROP TABLE IF EXISTS batch_insert5"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS batch_insert5 (i Int32, s String) ENGINE = TinyLog" - ); - - PreparedStatement statement = connection.prepareStatement("INSERT INTO batch_insert5 (i, s) VALUES (?, 'hello'), (?, ?)"); - statement.setInt(1, 42); - statement.setInt(2, 43); - statement.setString(3, "first_param"); - statement.addBatch(); - statement.setInt(1, 44); - statement.setInt(2, 45); - statement.setString(3, "second_param"); - statement.addBatch(); - statement.executeBatch(); - - ResultSet rs = connection.createStatement().executeQuery("SELECT count() as cnt from batch_insert5"); - rs.next(); - - Assert.assertEquals(rs.getInt("cnt"), 4); - Assert.assertFalse(rs.next()); - } - - @Test(groups = "integration") - public void testSimpleInsert() throws Exception { - connection.createStatement().execute("DROP TABLE IF EXISTS insert"); - connection.createStatement().execute( - "CREATE TABLE insert (" + - "date Date," + - "date_time DateTime," + - "string String," + - "int32 Int32," + - "float64 Float64" + - ") ENGINE = MergeTree order by date" - ); - - Date date = new Date(dateFormat.parse("1989-01-30").getTime()); - Timestamp dateTime = new Timestamp(1471008092000L); //2016-08-12 16:21:32 - String string = "testString"; - int int32 = Integer.MAX_VALUE; - double float64 = 42.21; - - PreparedStatement statement = connection.prepareStatement( - "INSERT INTO insert (date, date_time, string, int32, float64) VALUES (?, ?, ?, ?, ?)" - ); - - statement.setDate(1, date); - statement.setTimestamp(2, dateTime); - statement.setString(3, string); - statement.setInt(4, int32); - statement.setDouble(5, float64); - - statement.execute(); - - ResultSet rs = connection.createStatement().executeQuery("SELECT * from insert"); - Assert.assertTrue(rs.next()); - - Assert.assertEquals(rs.getDate("date").getTime(), date.getTime()); - Assert.assertEquals(rs.getTimestamp("date_time"), dateTime); - Assert.assertEquals(rs.getString("string"), string); - Assert.assertEquals(rs.getInt("int32"), int32); - Assert.assertEquals(rs.getDouble("float64"), float64); - - Assert.assertFalse(rs.next()); - } - - @Test(groups = "integration") - public void batchInsertNulls() throws Exception { - connection.createStatement().execute("DROP TABLE IF EXISTS batch_insert_nulls"); - connection.createStatement().execute( - "CREATE TABLE batch_insert_nulls (" + - "date Date," + - "date_time Nullable(DateTime)," + - "string Nullable(String)," + - "int32 Nullable(Int32)," + - "float64 Nullable(Float64)" + - ") ENGINE = MergeTree order by date" - ); - - ClickHousePreparedStatement statement = (ClickHousePreparedStatement) connection.prepareStatement( - "INSERT INTO batch_insert_nulls (date, date_time, string, int32, float64) VALUES (?, ?, ?, ?, ?)" - ); - - Date date = new Date(dateFormat.parse("1989-01-30").getTime()); - statement.setDate(1, date); - statement.setObject(2, null, Types.TIMESTAMP); - statement.setObject(3, null, Types.VARCHAR); - statement.setObject(4, null, Types.INTEGER); - statement.setObject(5, null, Types.DOUBLE); - statement.addBatch(); - statement.executeBatch(Collections.singletonMap(ClickHouseQueryParam.CONNECT_TIMEOUT, "1000")); - - ResultSet rs = connection.createStatement().executeQuery("SELECT date, date_time, string, int32, float64 from batch_insert_nulls"); - Assert.assertTrue(rs.next()); - - Assert.assertEquals(rs.getDate("date"), date); - Assert.assertNull(rs.getTimestamp("date_time")); - Assert.assertNull(rs.getString("string")); - Assert.assertEquals(rs.getInt("int32"), 0); - Assert.assertNull(rs.getObject("int32")); - Assert.assertEquals(rs.getDouble("float64"), 0.0); - Assert.assertNull(rs.getObject("float64")); - - Assert.assertFalse(rs.next()); - connection.createStatement().execute("DROP TABLE batch_insert_nulls"); - } - - @Test(groups = "integration") - public void testBatchValuesColumn() throws SQLException { - connection.createStatement().execute("DROP TABLE IF EXISTS batch_single_test"); - connection.createStatement().execute( - "CREATE TABLE batch_single_test(date Date, values String) ENGINE = StripeLog" - ); - - PreparedStatement st = connection.prepareStatement("INSERT INTO batch_single_test (date, values) VALUES (?, ?)"); - st.setDate(1, new Date(System.currentTimeMillis())); - st.setString(2, "test"); - - st.addBatch(); - st.executeBatch(); - } - - @Test(groups = "integration", expectedExceptions = SQLException.class) - public void testNullParameters() throws SQLException { - PreparedStatement st = connection.prepareStatement("INSERT INTO batch_single_test (date, values) VALUES (?, ?)"); - st.setString(2, "test"); - st.addBatch(); - } - - @Test(groups = "integration") - public void testBatchInsertWithLongQuery() throws SQLException { - int columnCount = 200; - try (Statement s = connection.createStatement()) { - String createColumns = IntStream.range(0, columnCount).mapToObj( - i -> "`looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongnaaaaameeeeeeee" + i + "` String " - ).collect(Collectors.joining(",")); - s.execute("DROP TABLE IF EXISTS batch_insert_with_long_query"); - s.execute("CREATE TABLE batch_insert_with_long_query (" + createColumns + ") ENGINE = Memory"); - } - - String values = IntStream.range(0, columnCount).mapToObj(i -> "?").collect(Collectors.joining(",")); - String columns = IntStream.range(0, columnCount).mapToObj( - i -> "looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongnaaaaameeeeeeee" + i - ).collect(Collectors.joining(",")); - int index = 1; - try (PreparedStatement s = connection.prepareStatement("INSERT INTO batch_insert_with_long_query (" + columns + ") VALUES (" + values + ")")) { - for (int i = 0; i < columnCount; i++) { - s.setString(index++, "12345"); - } - s.addBatch(); - s.executeBatch(); - } - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/CSVStreamTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/CSVStreamTest.java deleted file mode 100644 index df6fff62f..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/CSVStreamTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package ru.yandex.clickhouse.integration; - -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import ru.yandex.clickhouse.ClickHouseConnection; -import ru.yandex.clickhouse.JdbcIntegrationTest; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.nio.charset.Charset; -import java.sql.ResultSet; -import java.sql.SQLException; - -public class CSVStreamTest extends JdbcIntegrationTest { - private ClickHouseConnection connection; - - @BeforeClass(groups = "integration") - public void setUp() throws Exception { - connection = newConnection(); - } - - @AfterClass(groups = "integration") - public void tearDown() throws Exception { - closeConnection(connection); - } - - @Test(groups = "integration") - public void simpleInsert() throws SQLException { - connection.createStatement().execute("DROP TABLE IF EXISTS csv_stream"); - connection.createStatement().execute( - "CREATE TABLE csv_stream (value Int32, string_value String) ENGINE = Log()" - ); - - String string = "5,6\n1,6"; - InputStream inputStream = new ByteArrayInputStream(string.getBytes(Charset.forName("UTF-8"))); - - connection.createStatement().sendCSVStream(inputStream, dbName + ".csv_stream"); - - ResultSet rs = connection.createStatement().executeQuery( - "SELECT count() AS cnt, sum(value) AS sum, uniqExact(string_value) uniq FROM csv_stream"); - Assert.assertTrue(rs.next()); - Assert.assertEquals(rs.getInt("cnt"), 2); - Assert.assertEquals(rs.getLong("sum"), 6); - Assert.assertEquals(rs.getLong("uniq"), 1); - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseBitmapTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseBitmapTest.java deleted file mode 100644 index 4a714b904..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseBitmapTest.java +++ /dev/null @@ -1,203 +0,0 @@ -package ru.yandex.clickhouse.integration; - -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; - -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - -import com.clickhouse.client.ClickHouseVersion; - -import org.junit.Assert; -import org.roaringbitmap.RoaringBitmap; -import org.roaringbitmap.buffer.ImmutableRoaringBitmap; -import org.roaringbitmap.buffer.MutableRoaringBitmap; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.ClickHouseConnection; -import ru.yandex.clickhouse.ClickHouseDataSource; -import ru.yandex.clickhouse.JdbcIntegrationTest; -import ru.yandex.clickhouse.domain.ClickHouseDataType; -import ru.yandex.clickhouse.util.ClickHouseBitmap; - -public class ClickHouseBitmapTest extends JdbcIntegrationTest { - private ClickHouseConnection conn; - - @BeforeClass(groups = "integration") - public void setUp() throws Exception { - ClickHouseDataSource dataSource = newDataSource(); - conn = dataSource.getConnection(); - } - - @AfterClass(groups = "integration") - public void tearDown() throws Exception { - if (conn != null) { - conn.close(); - } - } - - private void checkBitmaps(ResultSet rs, ClickHouseBitmap empty, ClickHouseBitmap small, ClickHouseBitmap large) - throws SQLException { - // Charset charset = Charset.forName("ISO-8859-15"); - Charset charset = StandardCharsets.UTF_8; - - assertTrue(rs.next()); - assertEquals(rs.getObject(1), 0L); - assertEquals(rs.getString(2), new String(empty.toBytes(), charset)); - assertEquals(rs.getObject(2), rs.getObject(2, ClickHouseBitmap.class)); - assertEquals(rs.getObject(2, ClickHouseBitmap.class), empty); - - assertTrue(rs.next()); - assertEquals(rs.getObject(1), 1L); - assertEquals(rs.getString(2), new String(small.toBytes(), charset)); - assertEquals(rs.getObject(2), rs.getObject(2, ClickHouseBitmap.class)); - assertEquals(rs.getObject(2, ClickHouseBitmap.class), small); - - assertTrue(rs.next()); - assertEquals(rs.getObject(1), 2L); - assertEquals(rs.getString(2), new String(large.toBytes(), charset)); - assertEquals(rs.getObject(2), rs.getObject(2, ClickHouseBitmap.class)); - assertEquals(rs.getObject(2, ClickHouseBitmap.class), large); - - assertFalse(rs.next()); - } - - @Test(groups = "integration") - public void testRoaringBitmap() throws Exception { - if (conn == null) { - return; - } - - int[] smallSet = new int[32]; - for (int i = 0, len = smallSet.length; i < len; i++) { - int value = i + 100; - smallSet[i] = value; - } - - int[] largeSet = new int[33]; - for (int i = 0, len = largeSet.length; i < len; i++) { - int value = i + 60000; - largeSet[i] = value; - } - - String testQuery = "select *, base64Encode(toString(rb)) as x from test_roaring_bitmap order by i"; - ClickHouseBitmap empty = ClickHouseBitmap.wrap(RoaringBitmap.bitmapOf(), ClickHouseDataType.UInt32); - ClickHouseBitmap small = ClickHouseBitmap.wrap(smallSet); - ClickHouseBitmap large = ClickHouseBitmap.wrap(largeSet); - try (Statement s = conn.createStatement()) { - s.execute("DROP TABLE IF EXISTS test_roaring_bitmap"); - // AggregateFunction(groupBitmap, UInt32) cannot be used inside Nullable type - // AggregateFunction(groupBitmap, Nullable(UInt32)) can be created but not - // usable - s.execute( - "CREATE TABLE IF NOT EXISTS test_roaring_bitmap(i UInt32, rb AggregateFunction(groupBitmap, UInt32)) ENGINE = Memory"); - s.execute("insert into test_roaring_bitmap values(0, " + empty.toBitmapBuildExpression() + ")"); - s.execute("insert into test_roaring_bitmap values(1, " + small.toBitmapBuildExpression() + ")"); - s.execute("insert into test_roaring_bitmap values(2, " + large.toBitmapBuildExpression() + ")"); - - try (ResultSet rs = s.executeQuery(testQuery)) { - checkBitmaps(rs, empty, small, large); - } - - s.execute("truncate table test_roaring_bitmap"); - } - - // FIXME too bad batching is not supported - try (PreparedStatement s = conn.prepareStatement("insert into test_roaring_bitmap values(?,?)")) { - s.setObject(1, 0L); - s.setObject(2, empty); - s.execute(); - s.setObject(1, 1L); - s.setObject(2, small); - s.execute(); - s.setObject(1, 2L); - s.setObject(2, large); - s.execute(); - } - - try (Statement s = conn.createStatement()) { - try (ResultSet rs = s.executeQuery(testQuery)) { - checkBitmaps(rs, empty, small, large); - } - - s.execute("truncate table test_roaring_bitmap"); - } - - try (PreparedStatement s = conn.prepareStatement("insert into test_roaring_bitmap values(?,?)")) { - s.setObject(1, 0L); - s.setObject(2, ClickHouseBitmap.wrap(MutableRoaringBitmap.bitmapOf(), ClickHouseDataType.UInt32)); - s.execute(); - s.setObject(1, 1L); - s.setObject(2, ClickHouseBitmap.wrap(MutableRoaringBitmap.bitmapOf(smallSet), ClickHouseDataType.UInt32)); - s.execute(); - s.setObject(1, 2L); - s.setObject(2, ClickHouseBitmap.wrap(MutableRoaringBitmap.bitmapOf(largeSet), ClickHouseDataType.UInt32)); - s.execute(); - } - - try (Statement s = conn.createStatement()) { - try (ResultSet rs = s.executeQuery(testQuery)) { - checkBitmaps(rs, empty, small, large); - } - - s.execute("truncate table test_roaring_bitmap"); - } - - try (PreparedStatement s = conn.prepareStatement("insert into test_roaring_bitmap values(?,?)")) { - s.setObject(1, 0L); - s.setObject(2, ClickHouseBitmap.wrap(ImmutableRoaringBitmap.bitmapOf(), ClickHouseDataType.UInt32)); - s.execute(); - s.setObject(1, 1L); - s.setObject(2, ClickHouseBitmap.wrap(ImmutableRoaringBitmap.bitmapOf(smallSet), ClickHouseDataType.UInt32)); - s.execute(); - s.setObject(1, 2L); - s.setObject(2, ClickHouseBitmap.wrap(ImmutableRoaringBitmap.bitmapOf(largeSet), ClickHouseDataType.UInt32)); - s.execute(); - } - - try (Statement s = conn.createStatement()) { - try (ResultSet rs = s.executeQuery(testQuery)) { - checkBitmaps(rs, empty, small, large); - } - - s.execute("truncate table test_roaring_bitmap"); - } - } - - @Test(groups = "integration") - public void testRoaringBitmap64() throws Exception { - if (conn == null || ClickHouseVersion.check(conn.getServerVersion(), "(,20.8]")) { - return; - } - - try (Statement s = conn.createStatement()) { - s.execute( - "drop table if exists string_labels; create table string_labels (label String, value String, uv AggregateFunction(groupBitmap, UInt64)) ENGINE = AggregatingMergeTree() partition by label order by (label, value);"); - s.execute( - "drop table if exists user_string_properties; create table user_string_properties (uid UInt64, label String, value String) ENGINE=MergeTree() order by uid"); - s.execute( - "drop table if exists string_labels_mv; create materialized view string_labels_mv to string_labels as select label, value, groupBitmapState(uid) as uv from user_string_properties group by (label, value)"); - s.execute( - "insert into user_string_properties select number as uid, 'gender' as label, multiIf((number % 3) = 0, 'f', 'm') as value from numbers(20000000)"); - - try (ResultSet rs = s.executeQuery( - "select groupBitmapMergeState(uv) as uv from string_labels where label = 'gender' and value = 'f'")) { - Assert.assertTrue(rs.next()); - - ClickHouseBitmap bitmap = rs.getObject(1, ClickHouseBitmap.class); - Assert.assertNotNull(bitmap); - - Assert.assertFalse(rs.next()); - } - - // s.execute("truncate table test_roaring_bitmap"); - } - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseConnectionImplTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseConnectionImplTest.java deleted file mode 100644 index febcf3413..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseConnectionImplTest.java +++ /dev/null @@ -1,180 +0,0 @@ -package ru.yandex.clickhouse.integration; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.Statement; -import java.util.UUID; - -import javax.sql.DataSource; - -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.ClickHouseConnection; -import ru.yandex.clickhouse.ClickHouseDataSource; -import ru.yandex.clickhouse.JdbcIntegrationTest; -import ru.yandex.clickhouse.except.ClickHouseException; -import ru.yandex.clickhouse.settings.ClickHouseProperties; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; - -public class ClickHouseConnectionImplTest extends JdbcIntegrationTest { - - @Test(groups = "integration") - public void testDefaultEmpty() throws Exception { - assertSuccess(createDataSource(null, null)); - } - - @Test(groups = "integration") - public void testDefaultUserOnly() throws Exception { - assertSuccess(createDataSource("default", null)); - } - - @Test(groups = "integration") - public void testDefaultUserEmptyPassword() throws Exception { - assertSuccess(createDataSource("default", "")); - } - - @Test(groups = "integration") - public void testDefaultUserPass() throws Exception { - assertFailure(createDataSource("default", "bar")); - } - - @Test(groups = "integration") - public void testDefaultPass() throws Exception { - assertFailure(createDataSource(null, "bar")); - } - - @Test(groups = "integration") - public void testFooEmpty() throws Exception { - assertFailure(createDataSource("foo", null)); - } - - @Test(groups = "integration") - public void testFooWrongPass() throws Exception { - assertFailure(createDataSource("foo", "baz")); - } - - @Test(groups = "integration") - public void testFooPass() throws Exception { - assertSuccess(createDataSource("foo", "bar")); - } - - @Test(groups = "integration") - public void testFooWrongUser() throws Exception { - assertFailure(createDataSource("baz", "bar")); - } - - @Test(groups = "integration") - public void testOofNoPassword() throws Exception { - assertSuccess(createDataSource("oof", null)); - } - - @Test(groups = "integration") - public void testOofWrongPassword() throws Exception { - assertFailure(createDataSource("oof", "baz")); - } - - @Test(groups = "integration") - public void testDefaultDatabase() throws Exception { - ClickHouseDataSource ds = newDataSource(); - String currentDbQuery = "select currentDatabase()"; - try (Connection conn = ds.getConnection(); Statement s = conn.createStatement()) { - try (ResultSet rs = s.executeQuery(currentDbQuery)) { - assertTrue(rs.next()); - assertEquals(rs.getString(1), "default"); - assertFalse(rs.next()); - } - - PreparedStatement p = conn.prepareStatement(currentDbQuery); - try (ResultSet rs = p.executeQuery()) { - assertTrue(rs.next()); - assertEquals(rs.getString(1), "default"); - assertFalse(rs.next()); - } - s.execute("drop database if exists tdb1; drop database if exists tdb2; create database tdb1; create database tdb2"); - } - - ds = newDataSource("tdb2"); - try (Connection conn = ds.getConnection(); Statement s = conn.createStatement()) { - try (ResultSet rs = s.executeQuery(currentDbQuery)) { - assertTrue(rs.next()); - assertEquals(rs.getString(1), "tdb2"); - assertFalse(rs.next()); - } - - s.execute("create table tdb2_aaa(a String) engine=Memory; insert into tdb2_aaa values('3')"); - - try (ResultSet rs = s.executeQuery("select currentDatabase(), a from tdb2_aaa")) { - assertTrue(rs.next()); - assertEquals(rs.getString(1), "tdb2"); - assertEquals(rs.getString(2), "3"); - assertFalse(rs.next()); - } - - s.execute("use tdb1; create table tdb1_aaa(a String) engine=Memory; insert into tdb1_aaa values('1')"); - - try (ResultSet rs = s.executeQuery("select currentDatabase(), a from tdb1_aaa")) { - assertTrue(rs.next()); - assertEquals(rs.getString(1), "tdb1"); - assertEquals(rs.getString(2), "1"); - assertFalse(rs.next()); - } - - try (ResultSet rs = s.executeQuery("use `tdb2`; select currentDatabase(), a from tdb2_aaa")) { - assertTrue(rs.next()); - assertEquals(rs.getString(1), "tdb2"); - assertEquals(rs.getString(2), "3"); - assertFalse(rs.next()); - } - - String sql = "select currentDatabase(), a from tdb2_aaa"; - try (PreparedStatement p = conn.prepareStatement(sql); ResultSet rs = p.executeQuery()) { - assertTrue(rs.next()); - assertEquals(rs.getString(1), "tdb2"); - assertEquals(rs.getString(2), "3"); - assertFalse(rs.next()); - } - } - } - - @Test(groups = "integration") - public void testNonExistDatabase() throws Exception { - String database = UUID.randomUUID().toString(); - ClickHouseProperties props = new ClickHouseProperties(); - props.setUser("default"); - props.setPassword(""); - props.setDatabase(database); - ClickHouseDataSource ds = newDataSource(props); - try (ClickHouseConnection conn = ds.getConnection()) { - conn.createStatement().execute("create database `" + database + "`; " - + "drop database `" + database + "`"); - } - } - - private static void assertSuccess(DataSource dataSource) throws Exception { - Connection connection = dataSource.getConnection(); - assertTrue(connection.createStatement().execute("SELECT 1")); - } - - private static void assertFailure(DataSource dataSource) throws Exception { - // grrr, no JDK 1.8 - // assertThrows(SQLException.class, () -> dataSource.getConnection()); - try { - dataSource.getConnection(); - fail(); - } catch (ClickHouseException e) { - // expected - } - } - - private DataSource createDataSource(String user, String password) { - ClickHouseProperties props = new ClickHouseProperties(); - props.setUser(user); - props.setPassword(password); - return newDataSource(props); - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseDataTypeTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseDataTypeTest.java deleted file mode 100644 index a2b66be8a..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseDataTypeTest.java +++ /dev/null @@ -1,1095 +0,0 @@ -package ru.yandex.clickhouse.integration; - -import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; - -import java.sql.Date; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.Statement; -import java.sql.Time; -import java.sql.Timestamp; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetDateTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.temporal.ChronoUnit; -import java.time.zone.ZoneRules; -import java.util.Calendar; -import java.util.Objects; -import java.util.TimeZone; -import java.util.UUID; - -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.ClickHouseArray; -import ru.yandex.clickhouse.ClickHouseConnection; -import ru.yandex.clickhouse.ClickHouseDataSource; -import ru.yandex.clickhouse.JdbcIntegrationTest; -import ru.yandex.clickhouse.except.ClickHouseException; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; -import ru.yandex.clickhouse.response.parser.ClickHouseValueParser; -import ru.yandex.clickhouse.settings.ClickHouseProperties; - -public class ClickHouseDataTypeTest extends JdbcIntegrationTest { - private ClickHouseConnection conn; - - private LocalDate instantToLocalDate(Instant instant, ZoneId zone) { - Objects.requireNonNull(instant, "instant"); - Objects.requireNonNull(zone, "zone"); - ZoneRules rules = zone.getRules(); - ZoneOffset offset = rules.getOffset(instant); - long localSecond = instant.getEpochSecond() + offset.getTotalSeconds(); - long localEpochDay = Math.floorDiv(localSecond, 24 * 3600L); - return LocalDate.ofEpochDay(localEpochDay); - } - - private LocalTime instantToLocalTime(Instant instant, ZoneId zone) { - Objects.requireNonNull(instant, "instant"); - Objects.requireNonNull(zone, "zone"); - ZoneOffset offset = zone.getRules().getOffset(instant); - long localSecond = instant.getEpochSecond() + offset.getTotalSeconds(); - long secondsADay = 24 * 3600L; - int secsOfDay = (int) (localSecond - Math.floorDiv(localSecond, secondsADay) * secondsADay); - return LocalTime.ofNanoOfDay(secsOfDay * 1000_000_000L + instant.getNano()); - } - - @BeforeClass(groups = "integration") - public void setUp() throws Exception { - ClickHouseDataSource dataSource = newDataSource(); - conn = (ClickHouseConnection) dataSource.getConnection(); - } - - @AfterClass(groups = "integration") - public void tearDown() throws Exception { - conn.close(); - } - - @DataProvider(name = "uniqTimeZones") - public static Object[][] provideUniqTimeZones() { - return new Object[][] { new String[] { "Asia/Chongqing" }, new String[] { "America/Los_Angeles" }, - new String[] { "Europe/Moscow" }, new String[] { "Etc/UTC" }, new String[] { "Europe/Berlin" } }; - } - - @DataProvider(name = "testTimeZones") - public static Object[][] provieTestTimeZones() { - return new Object[][] { new String[] { "Asia/Chongqing", "America/Los_Angeles", "Europe/Moscow" }, - new String[] { "America/Los_Angeles", "Asia/Chongqing", "Europe/Moscow" }, - new String[] { "Europe/Moscow", "Asia/Chongqing", "America/Los_Angeles" }, - new String[] { "Asia/Chongqing", "Europe/Moscow", "America/Los_Angeles" }, - new String[] { "Europe/Moscow", "America/Los_Angeles", "Asia/Chongqing" }, - new String[] { "America/Los_Angeles", "Europe/Moscow", "Asia/Chongqing" }, - new String[] { "Asia/Chongqing", "Asia/Chongqing", "Asia/Chongqing" } }; - } - - @Test(groups = { "integration", "timezone" }, dataProvider = "testTimeZones") - public void testDateTimeWithTimeZone(String d1TimeZone, String d2TimeZone, String testTimeZone) throws Exception { - try (Statement s = conn.createStatement()) { - s.execute("DROP TABLE IF EXISTS test_datetime_with_timezone"); - s.execute("CREATE TABLE IF NOT EXISTS test_datetime_with_timezone(d0 DateTime, d1 DateTime('" + d1TimeZone - + "'), d2 DateTime('" + d2TimeZone + "')) ENGINE = Memory"); - } catch (ClickHouseException e) { - return; - } - - ClickHouseProperties props1 = new ClickHouseProperties(); - props1.setUseServerTimeZone(false); - props1.setUseServerTimeZoneForDates(false); - props1.setUseTimeZone(TimeZone.getDefault().getID()); - - ClickHouseProperties props2 = new ClickHouseProperties(); - props2.setUseServerTimeZone(true); - props2.setUseServerTimeZoneForDates(true); - - ClickHouseProperties props3 = new ClickHouseProperties(); - props3.setUseServerTimeZone(false); - props3.setUseServerTimeZoneForDates(true); - props3.setUseTimeZone(testTimeZone); - - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - long timestamp = 1546300800L; // '2019-01-01 00:00:00' in GMT - try (ClickHouseConnection connDefaultTz = (ClickHouseConnection) newDataSource(props1).getConnection(); - ClickHouseConnection connServerTz = (ClickHouseConnection) newDataSource(props2).getConnection(); - ClickHouseConnection connCustomTz = (ClickHouseConnection) newDataSource(props3).getConnection(); - Statement stmt = conn.createStatement()) { - stmt.execute("insert into test_datetime_with_timezone values (" + timestamp + ", " + timestamp + ", " - + timestamp + ")"); - - // time is saved as unix timestamp, while timezone is stored in column metadata - // which only affects display and parsing - String query = "select d0, d1, d2, toUInt32(d0) i0, toUInt32(d1) i1, toUInt32(d2) i2 from test_datetime_with_timezone"; - try (ResultSet rs = stmt.executeQuery(query)) { - // datetime as long - assertTrue(rs.next()); - assertEquals(rs.getLong("i0"), timestamp); // server/client timezone - assertEquals(rs.getObject("i0", Long.class), Long.valueOf(timestamp)); - assertEquals(rs.getLong("i1"), timestamp); // d1TimeZone - assertEquals(rs.getObject("i1", Long.class), Long.valueOf(timestamp)); - assertEquals(rs.getLong("i2"), timestamp); // d2TimeZone - assertEquals(rs.getObject("i2", Long.class), Long.valueOf(timestamp)); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getLong("i0"), timestamp); - assertEquals(r.getObject("i0", Long.class), Long.valueOf(timestamp)); - assertEquals(r.getLong("i1"), timestamp); - assertEquals(r.getObject("i1", Long.class), Long.valueOf(timestamp)); - assertEquals(r.getLong("i2"), timestamp); - assertEquals(r.getObject("i2", Long.class), Long.valueOf(timestamp)); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getLong("i0"), timestamp); - assertEquals(r.getObject("i0", Long.class), Long.valueOf(timestamp)); - assertEquals(r.getLong("i1"), timestamp); - assertEquals(r.getObject("i1", Long.class), Long.valueOf(timestamp)); - assertEquals(r.getLong("i2"), timestamp); - assertEquals(r.getObject("i2", Long.class), Long.valueOf(timestamp)); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getLong("i0"), timestamp); - assertEquals(r.getObject("i0", Long.class), Long.valueOf(timestamp)); - assertEquals(r.getLong("i1"), timestamp); - assertEquals(r.getObject("i1", Long.class), Long.valueOf(timestamp)); - assertEquals(r.getLong("i2"), timestamp); - assertEquals(r.getObject("i2", Long.class), Long.valueOf(timestamp)); - } - - // datetime as string - final long epochMilli = timestamp * 1000L; - Instant testInstant = Instant.ofEpochMilli(epochMilli); - assertEquals(rs.getString("d0"), - testInstant.atZone(conn.getServerTimeZone().toZoneId()).toLocalDateTime().format(formatter)); - assertEquals(rs.getObject("d0", String.class), - testInstant.atZone(conn.getServerTimeZone().toZoneId()).toLocalDateTime().format(formatter)); - assertEquals(rs.getString("d1"), - testInstant.atZone(ZoneId.of(d1TimeZone)).toLocalDateTime().format(formatter)); - assertEquals(rs.getObject("d1", String.class), - testInstant.atZone(ZoneId.of(d1TimeZone)).toLocalDateTime().format(formatter)); - assertEquals(rs.getString("d2"), - testInstant.atZone(ZoneId.of(d2TimeZone)).toLocalDateTime().format(formatter)); - assertEquals(rs.getObject("d2", String.class), - testInstant.atZone(ZoneId.of(d2TimeZone)).toLocalDateTime().format(formatter)); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - - String expectedDateTime = testInstant.atZone(ZoneId.systemDefault()).toLocalDateTime() - .format(formatter); - assertEquals(r.getString("d0"), expectedDateTime); - assertEquals(r.getObject("d0", String.class), expectedDateTime); - assertEquals(r.getString("d1"), expectedDateTime); - assertEquals(r.getObject("d1", String.class), expectedDateTime); - assertEquals(r.getString("d2"), expectedDateTime); - assertEquals(r.getObject("d2", String.class), expectedDateTime); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - - assertEquals(r.getString("d0"), testInstant.atZone(connServerTz.getServerTimeZone().toZoneId()) - .toLocalDateTime().format(formatter)); - assertEquals(r.getObject("d0", String.class), testInstant - .atZone(connServerTz.getServerTimeZone().toZoneId()).toLocalDateTime().format(formatter)); - assertEquals(r.getString("d1"), - testInstant.atZone(ZoneId.of(d1TimeZone)).toLocalDateTime().format(formatter)); - assertEquals(r.getObject("d1", String.class), - testInstant.atZone(ZoneId.of(d1TimeZone)).toLocalDateTime().format(formatter)); - assertEquals(r.getString("d2"), - testInstant.atZone(ZoneId.of(d2TimeZone)).toLocalDateTime().format(formatter)); - assertEquals(r.getObject("d2", String.class), - testInstant.atZone(ZoneId.of(d2TimeZone)).toLocalDateTime().format(formatter)); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - - String expectedDateTime = testInstant.atZone(ZoneId.of(testTimeZone)).toLocalDateTime() - .format(formatter); - assertEquals(r.getString("d0"), expectedDateTime); - assertEquals(r.getObject("d0", String.class), expectedDateTime); - assertEquals(r.getString("d1"), expectedDateTime); - assertEquals(r.getObject("d1", String.class), expectedDateTime); - assertEquals(r.getString("d2"), expectedDateTime); - assertEquals(r.getObject("d2", String.class), expectedDateTime); - } - - // datetime as timestamp - Timestamp expectedTimestamp = new Timestamp(epochMilli); - assertEquals(rs.getTimestamp("d0"), expectedTimestamp); - assertEquals(rs.getObject("d0"), expectedTimestamp); - assertEquals(rs.getObject("d0", Timestamp.class), expectedTimestamp); - assertEquals(rs.getTimestamp("d1"), expectedTimestamp); - assertEquals(rs.getObject("d1"), expectedTimestamp); - assertEquals(rs.getObject("d1", Timestamp.class), expectedTimestamp); - assertEquals(rs.getTimestamp("d2"), expectedTimestamp); - assertEquals(rs.getObject("d2"), expectedTimestamp); - assertEquals(rs.getObject("d2", Timestamp.class), expectedTimestamp); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getTimestamp("d0"), expectedTimestamp); - assertEquals(r.getObject("d0"), expectedTimestamp); - assertEquals(r.getObject("d0", Timestamp.class), expectedTimestamp); - assertEquals(r.getTimestamp("d1"), expectedTimestamp); - assertEquals(r.getObject("d1"), expectedTimestamp); - assertEquals(r.getObject("d1", Timestamp.class), expectedTimestamp); - assertEquals(r.getTimestamp("d2"), expectedTimestamp); - assertEquals(r.getObject("d2"), expectedTimestamp); - assertEquals(r.getObject("d2", Timestamp.class), expectedTimestamp); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getTimestamp("d0"), expectedTimestamp); - assertEquals(r.getObject("d0"), expectedTimestamp); - assertEquals(r.getObject("d0", Timestamp.class), expectedTimestamp); - assertEquals(r.getTimestamp("d1"), expectedTimestamp); - assertEquals(r.getObject("d1"), expectedTimestamp); - assertEquals(r.getObject("d1", Timestamp.class), expectedTimestamp); - assertEquals(r.getTimestamp("d2"), expectedTimestamp); - assertEquals(r.getObject("d2"), expectedTimestamp); - assertEquals(r.getObject("d2", Timestamp.class), expectedTimestamp); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getTimestamp("d0"), expectedTimestamp); - assertEquals(r.getObject("d0"), expectedTimestamp); - assertEquals(r.getObject("d0", Timestamp.class), expectedTimestamp); - assertEquals(r.getTimestamp("d1"), expectedTimestamp); - assertEquals(r.getObject("d1"), expectedTimestamp); - assertEquals(r.getObject("d1", Timestamp.class), expectedTimestamp); - assertEquals(r.getTimestamp("d2"), expectedTimestamp); - assertEquals(r.getObject("d2"), expectedTimestamp); - assertEquals(r.getObject("d2", Timestamp.class), expectedTimestamp); - } - - // datetime as timestamp, with calendar - assertEquals(rs.getTimestamp("d0"), - rs.getTimestamp("d0", Calendar.getInstance(TimeZone.getTimeZone(testTimeZone)))); - assertEquals(rs.getTimestamp("d1"), - rs.getTimestamp("d1", Calendar.getInstance(TimeZone.getTimeZone(testTimeZone)))); - assertEquals(rs.getTimestamp("d2"), - rs.getTimestamp("d2", Calendar.getInstance(TimeZone.getTimeZone(testTimeZone)))); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getTimestamp("d0"), - r.getTimestamp("d0", Calendar.getInstance(TimeZone.getTimeZone(testTimeZone)))); - assertEquals(r.getTimestamp("d1"), - r.getTimestamp("d1", Calendar.getInstance(TimeZone.getTimeZone(testTimeZone)))); - assertEquals(r.getTimestamp("d2"), - r.getTimestamp("d2", Calendar.getInstance(TimeZone.getTimeZone(testTimeZone)))); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getTimestamp("d0"), - r.getTimestamp("d0", Calendar.getInstance(TimeZone.getTimeZone(testTimeZone)))); - assertEquals(r.getTimestamp("d1"), - r.getTimestamp("d1", Calendar.getInstance(TimeZone.getTimeZone(testTimeZone)))); - assertEquals(r.getTimestamp("d2"), - r.getTimestamp("d2", Calendar.getInstance(TimeZone.getTimeZone(testTimeZone)))); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getTimestamp("d0"), - r.getTimestamp("d0", Calendar.getInstance(TimeZone.getTimeZone(testTimeZone)))); - assertEquals(r.getTimestamp("d1"), - r.getTimestamp("d1", Calendar.getInstance(TimeZone.getTimeZone(testTimeZone)))); - assertEquals(r.getTimestamp("d2"), - r.getTimestamp("d2", Calendar.getInstance(TimeZone.getTimeZone(testTimeZone)))); - } - - // datetime as date - Date expectedDate = new Date(testInstant.atZone(ZoneId.systemDefault()).truncatedTo(ChronoUnit.DAYS) - .toInstant().toEpochMilli()); - assertEquals(rs.getDate("d0"), expectedDate); - assertEquals(rs.getObject("d0", Date.class), expectedDate); - assertEquals(rs.getDate("d1"), expectedDate); - assertEquals(rs.getObject("d1", Date.class), expectedDate); - assertEquals(rs.getDate("d2"), expectedDate); - assertEquals(rs.getObject("d2", Date.class), expectedDate); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getDate("d0"), expectedDate); - assertEquals(r.getObject("d0", Date.class), expectedDate); - assertEquals(r.getDate("d1"), expectedDate); - assertEquals(r.getObject("d1", Date.class), expectedDate); - assertEquals(r.getDate("d2"), expectedDate); - assertEquals(r.getObject("d2", Date.class), expectedDate); - } - // expectedDate = new - // Date(testInstant.atZone(connServerTz.getServerTimeZone().toZoneId()) - // .truncatedTo(ChronoUnit.DAYS).toInstant().toEpochMilli()); - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getDate("d0"), expectedDate); - assertEquals(r.getObject("d0", Date.class), expectedDate); - assertEquals(r.getDate("d1"), expectedDate); - assertEquals(r.getObject("d1", Date.class), expectedDate); - assertEquals(r.getDate("d2"), expectedDate); - assertEquals(r.getObject("d2", Date.class), expectedDate); - } - expectedDate = new Date(testInstant.atZone(ZoneId.of(testTimeZone)).truncatedTo(ChronoUnit.DAYS) - .toInstant().toEpochMilli()); - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getDate("d0"), expectedDate); - assertEquals(r.getObject("d0", Date.class), expectedDate); - assertEquals(r.getDate("d1"), expectedDate); - assertEquals(r.getObject("d1", Date.class), expectedDate); - assertEquals(r.getDate("d2"), expectedDate); - assertEquals(r.getObject("d2", Date.class), expectedDate); - } - - // datetime as time - Time expectedTime = new Time(ClickHouseValueParser.normalizeTime(null, epochMilli)); - assertEquals(rs.getTime("d0"), expectedTime); - assertEquals(rs.getObject("d0", Time.class), expectedTime); - assertEquals(rs.getTime("d1"), expectedTime); - assertEquals(rs.getObject("d1", Time.class), expectedTime); - assertEquals(rs.getTime("d2"), expectedTime); - assertEquals(rs.getObject("d2", Time.class), expectedTime); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getTime("d0"), expectedTime); - assertEquals(r.getObject("d0", Time.class), expectedTime); - assertEquals(r.getTime("d1"), expectedTime); - assertEquals(r.getObject("d1", Time.class), expectedTime); - assertEquals(r.getTime("d2"), expectedTime); - assertEquals(r.getObject("d2", Time.class), expectedTime); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getTime("d0"), expectedTime); - assertEquals(r.getObject("d0", Time.class), expectedTime); - assertEquals(r.getTime("d1"), expectedTime); - assertEquals(r.getObject("d1", Time.class), expectedTime); - assertEquals(r.getTime("d2"), expectedTime); - assertEquals(r.getObject("d2", Time.class), expectedTime); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getTime("d0"), expectedTime); - assertEquals(r.getObject("d0", Time.class), expectedTime); - assertEquals(r.getTime("d1"), expectedTime); - assertEquals(r.getObject("d1", Time.class), expectedTime); - assertEquals(r.getTime("d2"), expectedTime); - assertEquals(r.getObject("d2", Time.class), expectedTime); - } - - // datetime as Instant - assertEquals(rs.getObject("d0", Instant.class), testInstant); - assertEquals(rs.getObject("d1", Instant.class), testInstant); - assertEquals(rs.getObject("d2", Instant.class), testInstant); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d0", Instant.class), testInstant); - assertEquals(r.getObject("d1", Instant.class), testInstant); - assertEquals(r.getObject("d2", Instant.class), testInstant); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d0", Instant.class), testInstant); - assertEquals(r.getObject("d1", Instant.class), testInstant); - assertEquals(r.getObject("d2", Instant.class), testInstant); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d0", Instant.class), testInstant); - assertEquals(r.getObject("d1", Instant.class), testInstant); - assertEquals(r.getObject("d2", Instant.class), testInstant); - } - - // datetime as OffsetDateTime - assertEquals(rs.getObject("d0", OffsetDateTime.class), - testInstant.atOffset(conn.getServerTimeZone().toZoneId().getRules().getOffset(testInstant))); - assertEquals(rs.getObject("d1", OffsetDateTime.class), - testInstant.atOffset(ZoneId.of(d1TimeZone).getRules().getOffset(testInstant))); - assertEquals(rs.getObject("d2", OffsetDateTime.class), - testInstant.atOffset(ZoneId.of(d2TimeZone).getRules().getOffset(testInstant))); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d0", OffsetDateTime.class), - testInstant.atOffset(ZoneId.systemDefault().getRules().getOffset(testInstant))); - assertEquals(r.getObject("d1", OffsetDateTime.class), - testInstant.atOffset(ZoneId.systemDefault().getRules().getOffset(testInstant))); - assertEquals(r.getObject("d2", OffsetDateTime.class), - testInstant.atOffset(ZoneId.systemDefault().getRules().getOffset(testInstant))); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d0", OffsetDateTime.class), testInstant - .atOffset(connServerTz.getServerTimeZone().toZoneId().getRules().getOffset(testInstant))); - assertEquals(r.getObject("d1", OffsetDateTime.class), - testInstant.atOffset(ZoneId.of(d1TimeZone).getRules().getOffset(testInstant))); - assertEquals(r.getObject("d2", OffsetDateTime.class), - testInstant.atOffset(ZoneId.of(d2TimeZone).getRules().getOffset(testInstant))); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d0", OffsetDateTime.class), - testInstant.atOffset(ZoneId.of(testTimeZone).getRules().getOffset(testInstant))); - assertEquals(r.getObject("d1", OffsetDateTime.class), - testInstant.atOffset(ZoneId.of(testTimeZone).getRules().getOffset(testInstant))); - assertEquals(r.getObject("d2", OffsetDateTime.class), - testInstant.atOffset(ZoneId.of(testTimeZone).getRules().getOffset(testInstant))); - } - - // datetime as OffsetTime - assertEquals(rs.getObject("d0", OffsetTime.class), - testInstant.atOffset(conn.getServerTimeZone().toZoneId().getRules().getOffset(testInstant)) - .toOffsetTime()); - assertEquals(rs.getObject("d1", OffsetTime.class), - testInstant.atOffset(ZoneId.of(d1TimeZone).getRules().getOffset(testInstant)).toOffsetTime()); - assertEquals(rs.getObject("d2", OffsetTime.class), - testInstant.atOffset(ZoneId.of(d2TimeZone).getRules().getOffset(testInstant)).toOffsetTime()); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d0", OffsetTime.class), testInstant - .atOffset(ZoneId.systemDefault().getRules().getOffset(testInstant)).toOffsetTime()); - assertEquals(r.getObject("d1", OffsetTime.class), testInstant - .atOffset(ZoneId.systemDefault().getRules().getOffset(testInstant)).toOffsetTime()); - assertEquals(r.getObject("d2", OffsetTime.class), testInstant - .atOffset(ZoneId.systemDefault().getRules().getOffset(testInstant)).toOffsetTime()); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d0", OffsetTime.class), - testInstant.atOffset( - connServerTz.getServerTimeZone().toZoneId().getRules().getOffset(testInstant)) - .toOffsetTime()); - assertEquals(r.getObject("d1", OffsetTime.class), testInstant - .atOffset(ZoneId.of(d1TimeZone).getRules().getOffset(testInstant)).toOffsetTime()); - assertEquals(r.getObject("d2", OffsetTime.class), testInstant - .atOffset(ZoneId.of(d2TimeZone).getRules().getOffset(testInstant)).toOffsetTime()); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d0", OffsetTime.class), testInstant - .atOffset(ZoneId.of(testTimeZone).getRules().getOffset(testInstant)).toOffsetTime()); - assertEquals(r.getObject("d1", OffsetTime.class), testInstant - .atOffset(ZoneId.of(testTimeZone).getRules().getOffset(testInstant)).toOffsetTime()); - assertEquals(r.getObject("d2", OffsetTime.class), testInstant - .atOffset(ZoneId.of(testTimeZone).getRules().getOffset(testInstant)).toOffsetTime()); - } - - // datetime as ZonedDateTime - assertEquals(rs.getObject("d0", ZonedDateTime.class), - testInstant.atZone(conn.getServerTimeZone().toZoneId())); - assertEquals(rs.getObject("d1", ZonedDateTime.class), testInstant.atZone(ZoneId.of(d1TimeZone))); - assertEquals(rs.getObject("d2", ZonedDateTime.class), testInstant.atZone(ZoneId.of(d2TimeZone))); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d0", ZonedDateTime.class), testInstant.atZone(ZoneId.systemDefault())); - assertEquals(r.getObject("d1", ZonedDateTime.class), testInstant.atZone(ZoneId.systemDefault())); - assertEquals(r.getObject("d2", ZonedDateTime.class), testInstant.atZone(ZoneId.systemDefault())); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d0", ZonedDateTime.class), - testInstant.atZone(connServerTz.getServerTimeZone().toZoneId())); - assertEquals(r.getObject("d1", ZonedDateTime.class), testInstant.atZone(ZoneId.of(d1TimeZone))); - assertEquals(r.getObject("d2", ZonedDateTime.class), testInstant.atZone(ZoneId.of(d2TimeZone))); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d0", ZonedDateTime.class), testInstant.atZone(ZoneId.of(testTimeZone))); - assertEquals(r.getObject("d1", ZonedDateTime.class), testInstant.atZone(ZoneId.of(testTimeZone))); - assertEquals(r.getObject("d2", ZonedDateTime.class), testInstant.atZone(ZoneId.of(testTimeZone))); - } - - // datetime as LocalDateTime - LocalDateTime expectedLocalDateTime = LocalDateTime.ofInstant(testInstant, ZoneOffset.UTC); - assertEquals(rs.getObject("d0", LocalDateTime.class), expectedLocalDateTime); - assertEquals(rs.getObject("d1", LocalDateTime.class), expectedLocalDateTime); - assertEquals(rs.getObject("d2", LocalDateTime.class), expectedLocalDateTime); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d0", LocalDateTime.class), expectedLocalDateTime); - assertEquals(r.getObject("d1", LocalDateTime.class), expectedLocalDateTime); - assertEquals(r.getObject("d2", LocalDateTime.class), expectedLocalDateTime); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d0", LocalDateTime.class), expectedLocalDateTime); - assertEquals(r.getObject("d1", LocalDateTime.class), expectedLocalDateTime); - assertEquals(r.getObject("d2", LocalDateTime.class), expectedLocalDateTime); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d0", LocalDateTime.class), expectedLocalDateTime); - assertEquals(r.getObject("d1", LocalDateTime.class), expectedLocalDateTime); - assertEquals(r.getObject("d2", LocalDateTime.class), expectedLocalDateTime); - } - - // datetime as LocalDate - LocalDate expectedLocalDate = instantToLocalDate(testInstant, ZoneOffset.UTC); - assertEquals(rs.getObject("d0", LocalDate.class), expectedLocalDate); - assertEquals(rs.getObject("d1", LocalDate.class), expectedLocalDate); - assertEquals(rs.getObject("d2", LocalDate.class), expectedLocalDate); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d0", LocalDate.class), expectedLocalDate); - assertEquals(r.getObject("d1", LocalDate.class), expectedLocalDate); - assertEquals(r.getObject("d2", LocalDate.class), expectedLocalDate); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d0", LocalDate.class), expectedLocalDate); - assertEquals(r.getObject("d1", LocalDate.class), expectedLocalDate); - assertEquals(r.getObject("d2", LocalDate.class), expectedLocalDate); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d0", LocalDate.class), expectedLocalDate); - assertEquals(r.getObject("d1", LocalDate.class), expectedLocalDate); - assertEquals(r.getObject("d2", LocalDate.class), expectedLocalDate); - } - - // datetime as LocalTime - LocalTime expectedLocalTime = instantToLocalTime(testInstant, ZoneOffset.UTC); - assertEquals(rs.getObject("d0", LocalTime.class), expectedLocalTime); - assertEquals(rs.getObject("d1", LocalTime.class), expectedLocalTime); - assertEquals(rs.getObject("d2", LocalTime.class), expectedLocalTime); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d0", LocalTime.class), expectedLocalTime); - assertEquals(r.getObject("d1", LocalTime.class), expectedLocalTime); - assertEquals(r.getObject("d2", LocalTime.class), expectedLocalTime); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d0", LocalTime.class), expectedLocalTime); - assertEquals(r.getObject("d1", LocalTime.class), expectedLocalTime); - assertEquals(r.getObject("d2", LocalTime.class), expectedLocalTime); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d0", LocalTime.class), expectedLocalTime); - assertEquals(r.getObject("d1", LocalTime.class), expectedLocalTime); - assertEquals(r.getObject("d2", LocalTime.class), expectedLocalTime); - } - } - - stmt.execute("truncate table test_datetime_with_timezone"); - } - } - - @Test(groups = { "integration", "timezone" }, dataProvider = "uniqTimeZones") - public void testDateWithTimeZone(String testTimeZone) throws Exception { - try (Statement s = conn.createStatement()) { - s.execute("DROP TABLE IF EXISTS test_date_with_timezone"); - s.execute("CREATE TABLE IF NOT EXISTS test_date_with_timezone(d Date) ENGINE = Memory"); - } catch (ClickHouseException e) { - return; - } - - ClickHouseProperties props1 = new ClickHouseProperties(); - props1.setUseServerTimeZone(false); - props1.setUseServerTimeZoneForDates(false); - props1.setUseTimeZone(TimeZone.getDefault().getID()); - - ClickHouseProperties props2 = new ClickHouseProperties(); - props2.setUseServerTimeZone(true); - props2.setUseServerTimeZoneForDates(true); - - ClickHouseProperties props3 = new ClickHouseProperties(); - props3.setUseServerTimeZone(false); - props3.setUseServerTimeZoneForDates(true); - props3.setUseTimeZone(testTimeZone); - - long timestamp = 1546300800L; // '2019-01-01 00:00:00' in GMT - int date = (int) timestamp / 24 / 3600; // '2019-01-01' in GMT - try (ClickHouseConnection connDefaultTz = (ClickHouseConnection) newDataSource(props1).getConnection(); - ClickHouseConnection connServerTz = (ClickHouseConnection) newDataSource(props2).getConnection(); - ClickHouseConnection connCustomTz = (ClickHouseConnection) newDataSource(props3).getConnection(); - Statement stmt = conn.createStatement()) { - stmt.execute("insert into test_date_with_timezone values (" + date + ")"); - - String query = "select d, toUInt16(d) i from test_date_with_timezone"; - try (ResultSet rs = stmt.executeQuery(query)) { - // date as integer - assertTrue(rs.next()); - assertEquals(rs.getInt("i"), date); - assertEquals(rs.getObject("i", Integer.class), Integer.valueOf(date)); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getInt("i"), date); - assertEquals(r.getObject("i", Integer.class), Integer.valueOf(date)); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getInt("i"), date); - assertEquals(r.getObject("i", Integer.class), Integer.valueOf(date)); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getInt("i"), date); - assertEquals(r.getObject("i", Integer.class), Integer.valueOf(date)); - } - - // date as string - final long epochMilli = timestamp * 1000L; - LocalDate testLocalDate = LocalDate.ofEpochDay(date); - Instant testInstant = Instant.ofEpochMilli(epochMilli); - String d = "2019-01-01"; - assertEquals(rs.getString("d"), d); - assertEquals(rs.getObject("d", String.class), d); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getString("d"), d); - assertEquals(r.getObject("d", String.class), d); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getString("d"), d); - assertEquals(r.getObject("d", String.class), d); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getString("d"), d); - assertEquals(r.getObject("d", String.class), d); - } - - // date as timestamp - Timestamp expectedTimestamp = Timestamp - .from(testLocalDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); - Timestamp serverTimestamp = Timestamp - .from(testLocalDate.atStartOfDay(connServerTz.getServerTimeZone().toZoneId()).toInstant()); - Timestamp customTimestamp = Timestamp - .from(testLocalDate.atStartOfDay(ZoneId.of(testTimeZone)).toInstant()); - assertEquals(rs.getTimestamp("d"), expectedTimestamp); - assertEquals(rs.getObject("d", Timestamp.class), expectedTimestamp); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getTimestamp("d"), expectedTimestamp); - assertEquals(r.getObject("d", Timestamp.class), expectedTimestamp); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getTimestamp("d"), serverTimestamp); - assertEquals(r.getObject("d", Timestamp.class), serverTimestamp); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getTimestamp("d"), customTimestamp); - assertEquals(r.getObject("d", Timestamp.class), customTimestamp); - } - - // date as timestamp, with calendar - assertEquals(rs.getTimestamp("d"), - rs.getTimestamp("d", Calendar.getInstance(TimeZone.getTimeZone(testTimeZone)))); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getTimestamp("d"), - r.getTimestamp("d", Calendar.getInstance(TimeZone.getTimeZone(testTimeZone)))); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getTimestamp("d"), - r.getTimestamp("d", Calendar.getInstance(TimeZone.getTimeZone(testTimeZone)))); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getTimestamp("d"), - r.getTimestamp("d", Calendar.getInstance(TimeZone.getTimeZone(testTimeZone)))); - } - - // date as date - Date expectedDate = new Date(expectedTimestamp.getTime()); - Date serverDate = new Date(serverTimestamp.getTime()); - Date customDate = new Date(customTimestamp.getTime()); - assertEquals(rs.getDate("d"), expectedDate); - assertEquals(rs.getObject("d"), expectedDate); - assertEquals(rs.getObject("d", Date.class), expectedDate); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getDate("d"), expectedDate); - assertEquals(r.getObject("d"), expectedDate); - assertEquals(r.getObject("d", Date.class), expectedDate); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getDate("d"), serverDate); - assertEquals(r.getObject("d"), serverDate); - assertEquals(r.getObject("d", Date.class), serverDate); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getDate("d"), customDate); - assertEquals(r.getObject("d"), customDate); - assertEquals(r.getObject("d", Date.class), customDate); - } - - // date as time - Time expectedTime = new Time(ClickHouseValueParser.normalizeTime(null, expectedTimestamp.getTime())); - Time serverTime = new Time(ClickHouseValueParser.normalizeTime(null, serverTimestamp.getTime())); - Time customTime = new Time(ClickHouseValueParser.normalizeTime(null, customTimestamp.getTime())); - assertEquals(rs.getTime("d"), expectedTime); - assertEquals(rs.getObject("d", Time.class), expectedTime); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getTime("d"), expectedTime); - assertEquals(r.getObject("d", Time.class), expectedTime); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getTime("d"), serverTime); - assertEquals(r.getObject("d", Time.class), serverTime); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getTime("d"), customTime); - assertEquals(r.getObject("d", Time.class), customTime); - } - - // date as Instant - assertEquals(rs.getObject("d", Instant.class), testInstant); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d", Instant.class), testInstant); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d", Instant.class), testInstant); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d", Instant.class), testInstant); - } - - // date as OffsetDateTime - ZoneOffset expectedOffset = ZoneId.systemDefault().getRules().getOffset(testInstant); - ZoneOffset serverOffset = connServerTz.getServerTimeZone().toZoneId().getRules().getOffset(testInstant); - ZoneOffset customOffset = ZoneId.of(testTimeZone).getRules().getOffset(testInstant); - OffsetDateTime expectedOffsetDateTime = testLocalDate.atStartOfDay(ZoneId.systemDefault()) - .toOffsetDateTime(); - OffsetDateTime serverOffsetDateTime = testLocalDate - .atStartOfDay(connServerTz.getServerTimeZone().toZoneId()).toOffsetDateTime(); - OffsetDateTime customOffsetDateTime = testLocalDate.atStartOfDay(ZoneId.of(testTimeZone)) - .toOffsetDateTime(); - assertEquals(rs.getObject("d", OffsetDateTime.class), expectedOffsetDateTime); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d", OffsetDateTime.class), expectedOffsetDateTime); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d", OffsetDateTime.class), serverOffsetDateTime); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d", OffsetDateTime.class), customOffsetDateTime); - } - - // date as OffsetTime - assertEquals(rs.getObject("d", OffsetTime.class), LocalTime.MIDNIGHT.atOffset(expectedOffset)); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d", OffsetTime.class), LocalTime.MIDNIGHT.atOffset(expectedOffset)); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d", OffsetTime.class), LocalTime.MIDNIGHT.atOffset(serverOffset)); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d", OffsetTime.class), LocalTime.MIDNIGHT.atOffset(customOffset)); - } - - // date as ZonedDateTime - assertEquals(rs.getObject("d", ZonedDateTime.class), - testLocalDate.atStartOfDay(ZoneId.systemDefault())); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d", ZonedDateTime.class), - testLocalDate.atStartOfDay(ZoneId.systemDefault())); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d", ZonedDateTime.class), - testLocalDate.atStartOfDay(connServerTz.getServerTimeZone().toZoneId())); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d", ZonedDateTime.class), - testLocalDate.atStartOfDay(ZoneId.of(testTimeZone))); - } - - // date as LocalDateTime - LocalDateTime expectedLocalDateTime = testLocalDate.atStartOfDay(ZoneId.systemDefault()) - .toLocalDateTime(); - assertEquals(rs.getObject("d", LocalDateTime.class), expectedLocalDateTime); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d", LocalDateTime.class), expectedLocalDateTime); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d", LocalDateTime.class), - testLocalDate.atStartOfDay(connServerTz.getServerTimeZone().toZoneId()).toLocalDateTime()); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d", LocalDateTime.class), - testLocalDate.atStartOfDay(ZoneId.of(testTimeZone)).toLocalDateTime()); - } - - // date as LocalDate - assertEquals(rs.getObject("d", LocalDate.class), testLocalDate); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d", LocalDate.class), testLocalDate); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d", LocalDate.class), testLocalDate); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d", LocalDate.class), testLocalDate); - } - - // date as LocalTime - assertEquals(rs.getObject("d", LocalTime.class), LocalTime.MIDNIGHT); - try (Statement s = connDefaultTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d", LocalTime.class), LocalTime.MIDNIGHT); - } - try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d", LocalTime.class), LocalTime.MIDNIGHT); - } - try (Statement s = connCustomTz.createStatement(); ResultSet r = s.executeQuery(query);) { - assertTrue(r.next()); - assertEquals(r.getObject("d", LocalTime.class), LocalTime.MIDNIGHT); - } - } - - stmt.execute("truncate table test_date_with_timezone"); - } - } - - @Test(groups = "integration") - public void testUUID() throws Exception { - try (Statement s = conn.createStatement()) { - s.execute("DROP TABLE IF EXISTS test_uuid"); - s.execute( - "CREATE TABLE IF NOT EXISTS test_uuid(u0 UUID, u1 Nullable(UUID), u2 Array(UUID), u3 Array(Nullable(UUID))) ENGINE = Memory"); - } catch (ClickHouseException e) { - return; - } - - try (Statement s = conn.createStatement()) { - UUID uuid = UUID.randomUUID(); - String str = uuid.toString(); - s.execute("insert into test_uuid values ('" + str + "', null, ['" + str + "'], [null])"); - - try (ResultSet rs = s.executeQuery("select * from test_uuid")) { - assertTrue(rs.next()); - - assertEquals(rs.getString(1), str); - assertEquals(rs.getObject(1), uuid); - assertEquals(rs.getObject(1, UUID.class), uuid); - - assertNull(rs.getString(2)); - assertNull(rs.getObject(2)); - assertNull(rs.getObject(2, UUID.class)); - - assertEquals(rs.getString(3), "['" + str + "']"); - assertEquals(rs.getArray(3).getArray(), new UUID[] { uuid }); - assertEquals(rs.getObject(3, ClickHouseArray.class).getArray(), new UUID[] { uuid }); - assertEquals(rs.getObject(3, UUID[].class), new UUID[] { uuid }); - - assertEquals(rs.getString(4), "[NULL]"); - assertEquals(rs.getArray(4).getArray(), new UUID[] { null }); - assertEquals(rs.getObject(4, ClickHouseArray.class).getArray(), new UUID[] { null }); - assertEquals(rs.getObject(4, UUID[].class), new UUID[] { null }); - } - - s.execute("truncate table test_uuid"); - } - } - - @Test(groups = "integration") - public void testDateTime64() throws Exception { - try (Statement s = conn.createStatement()) { - s.execute("DROP TABLE IF EXISTS test_datetime64"); - s.execute( - "CREATE TABLE IF NOT EXISTS test_datetime64(d0 DateTime64(3, 'UTC'), d1 Nullable(DateTime64)) ENGINE = Memory"); - } catch (ClickHouseException e) { - return; - } - - try (Statement s = conn.createStatement()) { - s.execute("insert into test_datetime64 values (1, null)"); - - try (ResultSet rs = s.executeQuery("select * from test_datetime64")) { - assertTrue(rs.next()); - assertEquals(rs.getObject(1), new Timestamp(1L)); - assertEquals(rs.getObject(1, Instant.class), Instant.ofEpochMilli(1L)); - assertEquals(rs.getObject(1, LocalDate.class), LocalDate.ofEpochDay(0)); - assertEquals(rs.getObject(1, LocalDateTime.class), - Instant.ofEpochMilli(1L).atZone(ZoneId.of("UTC")).toLocalDateTime()); - assertNull(rs.getObject(2)); - assertNull(rs.getObject(2, Instant.class)); - assertNull(rs.getObject(2, LocalDate.class)); - assertNull(rs.getObject(2, LocalDateTime.class)); - } - - s.execute("truncate table test_datetime64"); - } - } - - @Test(groups = "integration") - public void testDateTimes() throws Exception { - try (Statement s = conn.createStatement()) { - s.execute("DROP TABLE IF EXISTS test_datetimes"); - s.execute( - "CREATE TABLE IF NOT EXISTS test_datetimes(d DateTime, d32 DateTime32, d64 DateTime64(9)) ENGINE = Memory"); - } catch (ClickHouseException e) { - return; - } - - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - long timestamp = 1614881594000L; - Timestamp expected = new Timestamp(timestamp); - expected.setNanos(123456789); - String str = Instant.ofEpochMilli(timestamp).atZone(conn.getServerTimeZone().toZoneId()).format(formatter); - String before = Instant.ofEpochMilli(timestamp - 3 * 24 * 3600000).atZone(conn.getServerTimeZone().toZoneId()) - .format(formatter); - - try (Statement s = conn.createStatement()) { - s.execute("insert into test_datetimes values ('" + str + "', '" + str + "', '" + str + ".123456789')"); - - try (ResultSet rs = s.executeQuery("select * from test_datetimes")) { - assertTrue(rs.next()); - assertEquals(rs.getObject("d"), new Timestamp(timestamp)); - assertEquals(rs.getObject("d32"), new Timestamp(timestamp)); - assertEquals(rs.getObject("d64"), expected); - } - - s.execute("truncate table test_datetimes"); - } - - try (PreparedStatement s = conn.prepareStatement("insert into test_datetimes values(?,?,?)")) { - s.setString(1, str); - s.setString(2, str); - s.setString(3, str + ".123456789"); - s.execute(); - } - try (Statement s = conn.createStatement(); ResultSet rs = s.executeQuery("select * from test_datetimes")) { - assertTrue(rs.next()); - assertEquals(rs.getObject("d"), new Timestamp(timestamp)); - assertEquals(rs.getObject("d32"), new Timestamp(timestamp)); - assertEquals(rs.getObject("d64"), expected); - s.execute("truncate table test_datetimes"); - } - - try (PreparedStatement s = conn.prepareStatement("insert into test_datetimes values(?,?,?)")) { - s.setObject(1, new Timestamp(timestamp)); - s.setObject(2, new Timestamp(timestamp)); - s.setObject(3, expected); - s.execute(); - } - try (Statement s = conn.createStatement(); ResultSet rs = s.executeQuery("select * from test_datetimes")) { - assertTrue(rs.next()); - assertEquals(rs.getObject("d"), new Timestamp(timestamp)); - assertEquals(rs.getObject("d32"), new Timestamp(timestamp)); - assertEquals(rs.getObject("d64"), expected); - s.execute("truncate table test_datetimes"); - } - - try (Statement s = conn.createStatement()) { - s.execute("insert into test_datetimes values ('" + str + "', '" + str + "', '" + str + ".123456789')"); - - try (ResultSet rs = s.executeQuery("select * from test_datetimes")) { - assertTrue(rs.next()); - assertEquals(rs.getObject("d"), new Timestamp(timestamp)); - assertEquals(rs.getObject("d32"), new Timestamp(timestamp)); - assertEquals(rs.getObject("d64"), expected); - } - - s.execute("truncate table test_datetimes"); - } - - try (PreparedStatement s = conn.prepareStatement("insert into test_datetimes values(?,?,?)")) { - s.setString(1, before); - s.setString(2, before); - s.setString(3, before + ".123456789"); - s.execute(); - - s.setObject(1, new Timestamp(expected.getTime())); - s.setObject(2, new Timestamp(expected.getTime())); - s.setObject(3, expected); - s.execute(); - } - - try (Statement s = conn.createStatement()) { - try (ResultSet rs = s.executeQuery("select * from test_datetimes order by d")) { - assertTrue(rs.next()); - Timestamp ts = new Timestamp(expected.getTime() - 3 * 24 * 3600000); - ts.setNanos(expected.getNanos()); - assertEquals(rs.getObject("d"), new Timestamp(ts.getTime() - ts.getNanos() / 1000000)); - assertEquals(rs.getObject("d32"), new Timestamp(ts.getTime() - ts.getNanos() / 1000000)); - assertEquals(rs.getObject("d64"), ts); - - assertTrue(rs.next()); - assertEquals(rs.getObject("d"), new Timestamp(expected.getTime() - expected.getNanos() / 1000000)); - assertEquals(rs.getObject("d32"), new Timestamp(expected.getTime() - expected.getNanos() / 1000000)); - assertEquals(rs.getObject("d64"), expected); - - assertEquals(rs.getTime("d"), new Time( - ClickHouseValueParser.normalizeTime(null, expected.getTime() - expected.getTime() % 1000))); - assertEquals(rs.getTime("d32"), new Time( - ClickHouseValueParser.normalizeTime(null, expected.getTime() - expected.getTime() % 1000))); - assertEquals(rs.getTime("d64"), new Time(ClickHouseValueParser - .normalizeTime(ClickHouseColumnInfo.parse("DateTime64(9)", "d64", null), expected.getTime()))); - } - } - } - - @Test(groups = "integration") - public void testIPs() throws Exception { - try (Statement s = conn.createStatement()) { - s.execute("DROP TABLE IF EXISTS test_ips"); - s.execute("CREATE TABLE IF NOT EXISTS test_ips(ip4 IPv4, ip6 IPv6) ENGINE = Memory"); - s.execute("insert into test_ips values ('0.0.0.0', '::')"); - - try (ResultSet rs = s.executeQuery("select * from test_ips")) { - assertTrue(rs.next()); - assertEquals(rs.getObject("ip4"), "0.0.0.0"); - assertEquals(rs.getObject("ip6"), "::"); - } - - s.execute("truncate table test_ips"); - } - - try (PreparedStatement s = conn.prepareStatement("insert into test_ips values(?,?)")) { - s.setString(1, "0.0.0.0"); - s.setString(2, "::"); - s.execute(); - - s.setObject(1, 16909060); - s.setObject(2, "2607:f8b0:4005:805::2004"); - s.execute(); - } - - try (Statement s = conn.createStatement()) { - try (ResultSet rs = s.executeQuery("select * from test_ips order by ip4")) { - assertTrue(rs.next()); - assertEquals(rs.getObject("ip4"), "0.0.0.0"); - assertEquals(rs.getObject("ip6"), "::"); - - assertTrue(rs.next()); - assertEquals(rs.getObject("ip4"), "1.2.3.4"); - assertEquals(rs.getObject("ip6"), "2607:f8b0:4005:805::2004"); - } - } - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseDatabaseMetadataTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseDatabaseMetadataTest.java deleted file mode 100644 index 013834c91..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseDatabaseMetadataTest.java +++ /dev/null @@ -1,182 +0,0 @@ -package ru.yandex.clickhouse.integration; - -import java.sql.DatabaseMetaData; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.Timestamp; -import java.sql.Types; -import java.util.TimeZone; - -import com.clickhouse.client.ClickHouseVersion; - -import org.mockito.Mockito; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.ClickHouseConnection; -import ru.yandex.clickhouse.ClickHouseDatabaseMetadata; -import ru.yandex.clickhouse.JdbcIntegrationTest; - -public class ClickHouseDatabaseMetadataTest extends JdbcIntegrationTest { - private ClickHouseConnection connection; - - @BeforeClass(groups = "integration") - public void setUp() throws Exception { - connection = newConnection(); - } - - @AfterClass(groups = "integration") - public void tearDown() throws Exception { - closeConnection(connection); - } - - @Test(groups = "integration") - public void testMetadata() throws Exception { - connection.createStatement().executeQuery( - "DROP TABLE IF EXISTS testMetadata"); - connection.createStatement().executeQuery( - "CREATE TABLE testMetadata(" - + "foo Nullable(UInt32), bar UInt64) ENGINE = TinyLog"); - ResultSet columns = connection.getMetaData().getColumns( - null, dbName, "testMetaData", null); - while (columns.next()) { - String colName = columns.getString("COLUMN_NAME"); - if ("foo".equals(colName)) { - Assert.assertEquals(columns.getString("TYPE_NAME"), "UInt32"); - } else if ("bar".equals(columns.getString("COLUMN_NAME"))) { - Assert.assertEquals(columns.getString("TYPE_NAME"), "UInt64"); - } else { - throw new IllegalStateException( - "Unexpected column name " + colName); - } - } - } - - @Test(groups = "integration") - public void testMetadataColumns() throws Exception { - boolean supportComment = ClickHouseVersion.check(connection.getServerVersion(), "[18.16,)"); - connection.createStatement().executeQuery( - "DROP TABLE IF EXISTS testMetadata"); - connection.createStatement().executeQuery( - "CREATE TABLE testMetadata(" - + "foo Float32, bar UInt8" - + (supportComment ? " DEFAULT 42 COMMENT 'baz'" : "") - + ") ENGINE = TinyLog"); - ResultSet columns = connection.getMetaData().getColumns( - null, dbName, "testMetadata", null); - columns.next(); - Assert.assertEquals(columns.getString("TABLE_CAT"), "default"); - Assert.assertEquals(columns.getString("TABLE_SCHEM"), dbName); - Assert.assertEquals(columns.getString("TABLE_NAME"), "testMetadata"); - Assert.assertEquals(columns.getString("COLUMN_NAME"), "foo"); - Assert.assertEquals(columns.getInt("DATA_TYPE"), Types.REAL); - Assert.assertEquals(columns.getString("TYPE_NAME"), "Float32"); - Assert.assertEquals(columns.getInt("COLUMN_SIZE"), 8); - Assert.assertEquals(columns.getInt("BUFFER_LENGTH"), 0); - Assert.assertEquals(columns.getInt("DECIMAL_DIGITS"), 8); - Assert.assertEquals(columns.getInt("NUM_PREC_RADIX"), 10); - Assert.assertEquals(columns.getInt("NULLABLE"), DatabaseMetaData.columnNoNulls); - Assert.assertNull(columns.getObject("REMARKS")); - Assert.assertNull(columns.getObject("COLUMN_DEF")); - Assert.assertNull(columns.getObject("SQL_DATA_TYPE")); - Assert.assertNull(columns.getObject("SQL_DATETIME_SUB")); - Assert.assertEquals(columns.getInt("CHAR_OCTET_LENGTH"), 0); - Assert.assertEquals(columns.getInt("ORDINAL_POSITION"), 1); - Assert.assertEquals(columns.getString("IS_NULLABLE"), "NO"); - Assert.assertNull(columns.getObject("SCOPE_CATALOG")); - Assert.assertNull(columns.getObject("SCOPE_SCHEMA")); - Assert.assertNull(columns.getObject("SCOPE_TABLE")); - Assert.assertNull(columns.getObject("SOURCE_DATA_TYPE")); - Assert.assertEquals(columns.getString("IS_AUTOINCREMENT"), "NO"); - Assert.assertEquals(columns.getString("IS_GENERATEDCOLUMN"), "NO"); - columns.next(); - if (supportComment) { - Assert.assertEquals(columns.getInt("COLUMN_DEF"), 42); - Assert.assertEquals(columns.getObject("REMARKS"), "baz"); - } - } - - @Test(groups = "integration") - public void testDriverVersion() throws Exception { - DatabaseMetaData metaData = new ClickHouseDatabaseMetadata( - "url", Mockito.mock(ClickHouseConnection.class)); - Assert.assertEquals(metaData.getDriverVersion(), "0.1"); - Assert.assertEquals(metaData.getDriverMajorVersion(), 0); - Assert.assertEquals(metaData.getDriverMinorVersion(), 1); - } - - @Test(groups = "integration") - public void testDatabaseVersion() throws Exception { - String dbVersion = connection.getMetaData().getDatabaseProductVersion(); - Assert.assertFalse(dbVersion == null || dbVersion.isEmpty()); - int dbMajor = Integer.parseInt(dbVersion.substring(0, dbVersion.indexOf("."))); - Assert.assertTrue(dbMajor > 0); - Assert.assertEquals(connection.getMetaData().getDatabaseMajorVersion(), dbMajor); - int majorIdx = dbVersion.indexOf(".") + 1; - int dbMinor = Integer.parseInt(dbVersion.substring(majorIdx, dbVersion.indexOf(".", majorIdx))); - Assert.assertEquals(connection.getMetaData().getDatabaseMinorVersion(), dbMinor); - } - - @Test(groups = "integration", dataProvider = "tableEngines") - public void testGetTablesEngines(String engine) throws Exception { - connection.createStatement().executeQuery( - "DROP TABLE IF EXISTS testMetadata"); - connection.createStatement().executeQuery( - "CREATE TABLE testMetadata(" - + "foo Date) ENGINE = " - + engine); - ResultSet tableMeta = connection.getMetaData().getTables(null, dbName, "testMetadata", null); - tableMeta.next(); - Assert.assertEquals("TABLE", tableMeta.getString("TABLE_TYPE")); - } - - @Test(groups = "integration") - public void testGetTablesViews() throws Exception { - connection.createStatement().executeQuery( - "DROP TABLE IF EXISTS testMetadataView"); - connection.createStatement().executeQuery( - "CREATE VIEW testMetadataView AS SELECT 1 FROM system.tables"); - ResultSet tableMeta = connection.getMetaData().getTables( - null, dbName, "testMetadataView", null); - tableMeta.next(); - Assert.assertEquals("VIEW", tableMeta.getString("TABLE_TYPE")); - } - - @Test(groups = "integration") - public void testToDateTimeTZ() throws Exception { - connection.createStatement().executeQuery( - "DROP TABLE IF EXISTS testDateTimeTZ"); - connection.createStatement().executeQuery( - "CREATE TABLE testDateTimeTZ (foo DateTime) Engine = Memory"); - connection.createStatement().execute( - "INSERT INTO testDateTimeTZ (foo) VALUES('2019-04-12 13:37:00')"); - ResultSet rs = connection.createStatement().executeQuery( - "SELECT toDateTime(foo) FROM testDateTimeTZ"); - ResultSetMetaData meta = rs.getMetaData(); - Assert.assertEquals(meta.getColumnClassName(1), Timestamp.class.getCanonicalName()); - TimeZone timezone = ((ClickHouseConnection) connection).getTimeZone(); - if (ClickHouseVersion.check(connection.getServerVersion(), "[21.6,)")) { - Assert.assertEquals(meta.getColumnTypeName(1), "DateTime"); - } else { - Assert.assertEquals(meta.getColumnTypeName(1), "DateTime('" + timezone.getID() + "')"); - } - - Assert.assertEquals(meta.getColumnType(1), Types.TIMESTAMP); - } - - @DataProvider(name = "tableEngines") - private Object[][] getTableEngines() { - return new Object[][] { - new String[] {"TinyLog"}, - new String[] {"Log"}, - new String[] {"Memory"}, - new String[] {"MergeTree order by foo"} - }; - // unfortunately this is hard to test - // new String[] {"Dictionary(myDict)"}, - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseLargeNumberTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseLargeNumberTest.java deleted file mode 100644 index f5c4e2465..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseLargeNumberTest.java +++ /dev/null @@ -1,184 +0,0 @@ -package ru.yandex.clickhouse.integration; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.EnumMap; -import java.util.Map; -import java.util.UUID; - -import com.clickhouse.client.ClickHouseVersion; - -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.ClickHouseConnection; -import ru.yandex.clickhouse.ClickHouseDataSource; -import ru.yandex.clickhouse.ClickHouseStatement; -import ru.yandex.clickhouse.JdbcIntegrationTest; -import ru.yandex.clickhouse.except.ClickHouseException; -import ru.yandex.clickhouse.settings.ClickHouseProperties; -import ru.yandex.clickhouse.settings.ClickHouseQueryParam; - -public class ClickHouseLargeNumberTest extends JdbcIntegrationTest { - private ClickHouseConnection conn; - - @BeforeClass(groups = "integration") - public void setUp() throws Exception { - ClickHouseProperties props = new ClickHouseProperties(); - props.setSessionId(UUID.randomUUID().toString()); - ClickHouseDataSource dataSource = newDataSource(props); - conn = dataSource.getConnection(); - try (Statement s = conn.createStatement()) { - s.execute("SET allow_experimental_bigint_types=1"); - } catch (ClickHouseException e) { - conn = null; - } - } - - @AfterClass(groups = "integration") - public void tearDown() throws Exception { - if (conn == null) { - return; - } - - try (Statement s = conn.createStatement()) { - s.execute("SET allow_experimental_bigint_types=0"); - } - } - - @Test(groups = "integration") - public void testBigIntSupport() throws SQLException { - if (conn == null || ClickHouseVersion.check(conn.getServerVersion(), "[21.7,)")) { - return; - } - - String testSql = "create table if not exists system.test_bigint_support(i Int256) engine=Memory;" - + "drop table if exists system.test_bigint_support;"; - try (Connection conn = newDataSource().getConnection(); Statement s = conn.createStatement()) { - s.execute("set allow_experimental_bigint_types=0;" + testSql); - fail("Should fail without enabling bigint support"); - } catch (SQLException e) { - assertEquals(e.getErrorCode(), 44); - } - - try (Connection conn = newDataSource().getConnection(); Statement s = conn.createStatement()) { - assertFalse(s.execute("set allow_experimental_bigint_types=1;" + testSql)); - } - - try (ClickHouseConnection conn = newDataSource().getConnection(); - ClickHouseStatement s = conn.createStatement()) { - Map params = new EnumMap<>(ClickHouseQueryParam.class); - params.put(ClickHouseQueryParam.ALLOW_EXPERIMENTAL_BIGINT_TYPES, "1"); - assertNull(s.executeQuery(testSql, params)); - - params.put(ClickHouseQueryParam.ALLOW_EXPERIMENTAL_BIGINT_TYPES, "0"); - s.executeQuery(testSql, params); - fail("Should fail without enabling bigint support"); - } catch (SQLException e) { - assertEquals(e.getErrorCode(), 44); - } - } - - @Test(groups = "integration") - public void testSignedIntegers() throws Exception { - if (conn == null) { - return; - } - - try (Statement s = conn.createStatement()) { - s.execute("DROP TABLE IF EXISTS test_signed_integers"); - s.execute("CREATE TABLE IF NOT EXISTS test_signed_integers(i128 Int128, i256 Int256) ENGINE = TinyLog"); - s.execute( - "insert into test_signed_integers values(0, 0), (-170141183460469231731687303715884105728,-57896044618658097711785492504343953926634992332820282019728792003956564819968), (170141183460469231731687303715884105727,57896044618658097711785492504343953926634992332820282019728792003956564819967)"); - // check Int128 - try (ResultSet rs = s.executeQuery("select min(i128) as a, max(i128) as b from test_signed_integers")) { - assertTrue(rs.next()); - assertEquals(new BigInteger("-170141183460469231731687303715884105728"), rs.getObject("a")); - assertEquals(new BigInteger("170141183460469231731687303715884105727"), rs.getObject("b")); - } - - // check Int256 - try (ResultSet rs = s.executeQuery("select min(i256) as a, max(i256) as b from test_signed_integers")) { - assertTrue(rs.next()); - assertEquals( - new BigInteger( - "-57896044618658097711785492504343953926634992332820282019728792003956564819968"), - rs.getObject("a")); - assertEquals( - new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564819967"), - rs.getObject("b")); - } - } - } - - @Test(groups = "integration") - public void testUnsignedIntegers() throws Exception { - if (conn == null) { - return; - } - - try (Statement s = conn.createStatement()) { - s.execute("DROP TABLE IF EXISTS test_unsigned_integers"); - s.execute("CREATE TABLE IF NOT EXISTS test_unsigned_integers(i256 UInt256) ENGINE = TinyLog"); - s.execute( - "insert into test_unsigned_integers values (1), (0), (115792089237316195423570985008687907853269984665640564039457584007913129639935)"); - // TODO: add check for UInt128 once it's supported - - // check UInt256 - try (ResultSet rs = s.executeQuery("select min(i256) as a, max(i256) as b from test_unsigned_integers")) { - assertTrue(rs.next()); - assertEquals(BigInteger.ZERO, rs.getObject("a")); - assertEquals( - new BigInteger( - "115792089237316195423570985008687907853269984665640564039457584007913129639935"), - rs.getObject("b")); - } - } - } - - @Test(groups = "integration") - public void testDecimal256() throws Exception { - if (conn == null) { - return; - } - - try (Statement s = conn.createStatement()) { - s.execute("DROP TABLE IF EXISTS test_decimal256"); - s.execute( - "CREATE TABLE IF NOT EXISTS test_decimal256(d256 Decimal256(0), d Decimal256(20)) ENGINE = Memory"); - s.execute( - "insert into test_decimal256 values (-123456789.123456789, -123456789.123456789), (0, 0), (123456789.123456789, 123456789.123456789)"); - - // check min scale - try (ResultSet rs = s.executeQuery("select min(d256) as a, max(d256) as b from test_decimal256")) { - assertTrue(rs.next()); - assertEquals(new BigDecimal("-123456789"), rs.getObject("a")); - assertEquals(new BigDecimal("123456789"), rs.getObject("b")); - } - - // check max scale - if (ClickHouseVersion.check(conn.getServerVersion(), "[21.9,)")) { - s.execute("set output_format_decimal_trailing_zeros=1"); - } - try (ResultSet rs = s.executeQuery("select d from test_decimal256 order by d")) { - assertTrue(rs.next()); - assertEquals(rs.getObject("d"), new BigDecimal("-123456789.123456789").setScale(20)); - - assertTrue(rs.next()); - assertTrue(rs.next()); - assertEquals(rs.getObject("d"), new BigDecimal("123456789.123456789").setScale(20)); - } - } - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseMapTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseMapTest.java deleted file mode 100644 index cd88a9a98..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseMapTest.java +++ /dev/null @@ -1,170 +0,0 @@ -package ru.yandex.clickhouse.integration; - -import static org.junit.Assert.assertArrayEquals; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.EnumMap; -import java.util.Map; -import java.util.UUID; - -import com.clickhouse.client.ClickHouseVersion; - -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.ClickHouseConnection; -import ru.yandex.clickhouse.ClickHouseDataSource; -import ru.yandex.clickhouse.ClickHouseStatement; -import ru.yandex.clickhouse.JdbcIntegrationTest; -import ru.yandex.clickhouse.except.ClickHouseException; -import ru.yandex.clickhouse.settings.ClickHouseProperties; -import ru.yandex.clickhouse.settings.ClickHouseQueryParam; -import ru.yandex.clickhouse.util.Utils; - -public class ClickHouseMapTest extends JdbcIntegrationTest { - private ClickHouseConnection conn; - - @BeforeClass(groups = "integration") - public void setUp() throws Exception { - ClickHouseProperties props = new ClickHouseProperties(); - props.setSessionId(UUID.randomUUID().toString()); - ClickHouseDataSource dataSource = newDataSource(props); - conn = dataSource.getConnection(); - try (Statement s = conn.createStatement()) { - s.execute("SET allow_experimental_map_type=1"); - } catch (ClickHouseException e) { - conn = null; - } - } - - @AfterClass(groups = "integration") - public void tearDown() throws Exception { - if (conn == null) { - return; - } - - try (Statement s = conn.createStatement()) { - s.execute("SET allow_experimental_map_type=0"); - } - } - - private void assertMap(Object actual, Object expected) { - Map m1 = (Map) actual; - Map m2 = (Map) expected; - assertEquals(m1.size(), m2.size()); - for (Map.Entry e : m1.entrySet()) { - if (e.getValue().getClass().isArray()) { - assertArrayEquals((Object[]) e.getValue(), (Object[]) m2.get(e.getKey())); - } else { - assertEquals(e.getValue(), m2.get(e.getKey())); - } - } - } - - @Test(groups = "integration") - public void testMapSupport() throws SQLException { - if (conn == null) { - return; - } - - String testSql = "create table if not exists system.test_map_support(m Map(UInt8, String)) engine=Memory;" - + "drop table if exists system.test_map_support;"; - try (ClickHouseConnection conn = newDataSource().getConnection(); Statement s = conn.createStatement()) { - s.execute("set allow_experimental_map_type=0;" + testSql); - if (ClickHouseVersion.check(conn.getServerVersion(), "(,21.8)")) { - fail("Should fail without enabling map support"); - } - } catch (SQLException e) { - assertEquals(e.getErrorCode(), 44); - } - - try (Connection conn = newDataSource().getConnection(); Statement s = conn.createStatement()) { - assertFalse(s.execute("set allow_experimental_map_type=1;" + testSql)); - } - - try (ClickHouseConnection conn = newDataSource().getConnection(); - ClickHouseStatement s = conn.createStatement()) { - Map params = new EnumMap<>(ClickHouseQueryParam.class); - params.put(ClickHouseQueryParam.ALLOW_EXPERIMENTAL_MAP_TYPE, "1"); - assertNull(s.executeQuery(testSql, params)); - - params.put(ClickHouseQueryParam.ALLOW_EXPERIMENTAL_MAP_TYPE, "0"); - s.executeQuery(testSql, params); - if (ClickHouseVersion.check(conn.getServerVersion(), "(,21.8)")) { - fail("Should fail without enabling map support"); - } - } catch (SQLException e) { - assertEquals(e.getErrorCode(), 44); - } - } - - @Test(groups = "integration") - public void testMaps() throws Exception { - if (conn == null) { - return; - } - - ClickHouseVersion version = ClickHouseVersion.of(conn.getServerVersion()); - if (version.check("(,21.3]")) { - // https://github.com/ClickHouse/ClickHouse/issues/25026 - return; - } - String columns = ", ma Map(Integer, Array(String)), mi Map(Integer, Integer)"; - String values = ",{1:['11','12'],2:['22','23']},{1:11,2:22}"; - String params = ",?,?"; - if (version.check("[21.4,21.9)")) { - columns = ""; - values = ""; - params = ""; - } - - try (Statement s = conn.createStatement()) { - s.execute("DROP TABLE IF EXISTS test_maps"); - s.execute("CREATE TABLE IF NOT EXISTS test_maps(ms Map(String, String)" + columns + ") ENGINE = Memory"); - s.execute("insert into test_maps values ({'k1':'v1','k2':'v2'}" + values + ")"); - - try (ResultSet rs = s.executeQuery("select * from test_maps")) { - assertTrue(rs.next()); - assertMap(rs.getObject("ms"), Utils.mapOf("k1", "v1", "k2", "v2")); - if (!columns.isEmpty()) { - assertMap(rs.getObject("ma"), - Utils.mapOf(1, new String[] { "11", "12" }, 2, new String[] { "22", "23" })); - assertMap(rs.getObject("mi"), Utils.mapOf(1, 11, 2, 22)); - } - } - - s.execute("truncate table test_maps"); - } - - try (PreparedStatement s = conn.prepareStatement("insert into test_maps values(?" + params + ")")) { - s.setObject(1, Utils.mapOf("k1", "v1", "k2", "v2")); - if (!columns.isEmpty()) { - s.setObject(2, Utils.mapOf(1, new String[] { "11", "12" }, 2, new String[] { "22", "23" })); - s.setObject(3, Utils.mapOf(1, 11, 2, 22)); - } - s.execute(); - } - - try (Statement s = conn.createStatement()) { - try (ResultSet rs = s.executeQuery("select * from test_maps")) { - assertTrue(rs.next()); - assertMap(rs.getObject("ms"), Utils.mapOf("k1", "v1", "k2", "v2")); - if (!columns.isEmpty()) { - assertMap(rs.getObject("ma"), - Utils.mapOf(1, new String[] { "11", "12" }, 2, new String[] { "22", "23" })); - assertMap(rs.getObject("mi"), Utils.mapOf(1, 11, 2, 22)); - } - } - } - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHousePreparedStatementTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHousePreparedStatementTest.java deleted file mode 100644 index f950f82b2..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHousePreparedStatementTest.java +++ /dev/null @@ -1,769 +0,0 @@ -package ru.yandex.clickhouse.integration; - -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.sql.Statement; -import java.sql.Time; -import java.sql.Timestamp; -import java.sql.Types; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.ClickHouseArray; -import ru.yandex.clickhouse.ClickHouseConnection; -import ru.yandex.clickhouse.ClickHousePreparedStatement; -import ru.yandex.clickhouse.ClickHousePreparedStatementImpl; -import ru.yandex.clickhouse.JdbcIntegrationTest; -import ru.yandex.clickhouse.domain.ClickHouseDataType; -import ru.yandex.clickhouse.response.ClickHouseResponse; -import ru.yandex.clickhouse.settings.ClickHouseProperties; - -import static java.util.Collections.singletonList; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertTrue; - -public class ClickHousePreparedStatementTest extends JdbcIntegrationTest { - private Connection connection; - - @BeforeClass(groups = "integration") - public void setUp() throws Exception { - connection = newConnection(); - } - - @AfterClass(groups = "integration") - public void tearDown() throws Exception { - closeConnection(connection); - } - - @Test(groups = "integration") - public void testArrayTest() throws Exception { - - connection.createStatement().execute("DROP TABLE IF EXISTS array_test"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS array_test (i Int32, a Array(Int32)) ENGINE = TinyLog" - ); - - PreparedStatement statement = connection.prepareStatement("INSERT INTO array_test (i, a) VALUES (?, ?)"); - - statement.setInt(1, 1); - statement.setArray(2, new ClickHouseArray(ClickHouseDataType.Int32, new int[]{1, 2, 3})); - statement.addBatch(); - - statement.setInt(1, 2); - statement.setArray(2, new ClickHouseArray(ClickHouseDataType.Int32, new int[]{2, 3, 4, 5})); - statement.addBatch(); - statement.executeBatch(); - - ResultSet rs = connection.createStatement().executeQuery("SELECT count() as cnt from array_test"); - rs.next(); - - Assert.assertEquals(rs.getInt("cnt"), 2); - Assert.assertFalse(rs.next()); - } - - @Test(groups = "integration") - public void testArrayOfNullable() throws Exception { - connection.createStatement().execute("DROP TABLE IF EXISTS array_of_nullable"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS array_of_nullable (" + - "str Nullable(String), " + - "int Nullable(Int32), " + - "strs Array(Nullable(String)), " + - "ints Array(Nullable(Int32))) ENGINE = TinyLog" - ); - - PreparedStatement statement = connection.prepareStatement( - "INSERT INTO array_of_nullable (str, int, strs, ints) VALUES (?, ?, ?, ?)" - ); - - statement.setObject(1, null); - statement.setObject(2, null); - statement.setObject(3, new String[]{"a", null, "c"}); - statement.setArray(4, new ClickHouseArray(ClickHouseDataType.Int32, new Integer[]{1, null, 3})); - statement.addBatch(); - statement.executeBatch(); - - ResultSet rs = connection.createStatement().executeQuery("SELECT * FROM array_of_nullable"); - - Assert.assertTrue(rs.next()); - Assert.assertNull(rs.getObject("str")); - Assert.assertNull(rs.getObject("int")); - Assert.assertEquals(rs.getArray("strs").getArray(), new String[]{"a", null, "c"}); - Assert.assertEquals(rs.getArray("ints").getArray(), new int[]{1, 0, 3}); - Assert.assertFalse(rs.next()); - - ClickHouseProperties properties = new ClickHouseProperties(); - properties.setUseObjectsInArrays(true); - ClickHouseConnection configuredConnection = newConnection(properties); - - try { - rs = configuredConnection.createStatement().executeQuery("SELECT * FROM array_of_nullable"); - rs.next(); - - Assert.assertEquals(rs.getArray("ints").getArray(), new Integer[]{1, null, 3}); - } finally { - configuredConnection.close(); - } - } - - @Test(groups = "integration") - public void testArrayFixedStringTest() throws Exception { - connection.createStatement().execute("DROP TABLE IF EXISTS array_fixed_string_test"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS array_fixed_string_test (i Int32, a Array(FixedString(16))) ENGINE = TinyLog" - ); - - PreparedStatement statement = connection.prepareStatement("INSERT INTO array_fixed_string_test (i, a) VALUES (?, ?)"); - - statement.setInt(1, 1); - statement.setArray(2, new ClickHouseArray(ClickHouseDataType.FixedString, new byte[][]{randomEncodedUUID(), randomEncodedUUID()})); - statement.addBatch(); - - statement.setInt(1, 2); - statement.setArray(2, new ClickHouseArray(ClickHouseDataType.FixedString, new byte[][]{randomEncodedUUID(), randomEncodedUUID()})); - statement.addBatch(); - statement.executeBatch(); - - ResultSet rs = connection.createStatement().executeQuery("SELECT count() as cnt from array_fixed_string_test"); - rs.next(); - - Assert.assertEquals(rs.getInt("cnt"), 2); - Assert.assertFalse(rs.next()); - } - - @Test(groups = "integration") - public void testInsertUInt() throws SQLException { - connection.createStatement().execute("DROP TABLE IF EXISTS unsigned_insert"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS unsigned_insert (ui32 UInt32, ui64 UInt64) ENGINE = TinyLog" - ); - PreparedStatement stmt = connection.prepareStatement("insert into unsigned_insert (ui32, ui64) values (?, ?)"); - stmt.setObject(1, 4294967286L); - stmt.setObject(2, new BigInteger("18446744073709551606")); - stmt.execute(); - Statement select = connection.createStatement(); - ResultSet rs = select.executeQuery("select ui32, ui64 from unsigned_insert"); - rs.next(); - Object bigUInt32 = rs.getObject(1); - Assert.assertTrue(bigUInt32 instanceof Long); - Assert.assertEquals(((Long)bigUInt32).longValue(), 4294967286L); - Object bigUInt64 = rs.getObject(2); - Assert.assertTrue(bigUInt64 instanceof BigInteger); - Assert.assertEquals(bigUInt64, new BigInteger("18446744073709551606")); - } - - @Test(groups = "integration") - public void testInsertUUID() throws SQLException { - connection.createStatement().execute("DROP TABLE IF EXISTS uuid_insert"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS uuid_insert (ui32 UInt32, uuid UUID) ENGINE = TinyLog" - ); - PreparedStatement stmt = connection.prepareStatement("insert into uuid_insert (ui32, uuid) values (?, ?)"); - stmt.setObject(1, Long.valueOf(4294967286L)); - stmt.setObject(2, UUID.fromString("bef35f40-3b03-45b0-b1bd-8ec6593dcaaa")); - stmt.execute(); - Statement select = connection.createStatement(); - ResultSet rs = select.executeQuery("select ui32, uuid from uuid_insert"); - rs.next(); - Object bigUInt32 = rs.getObject(1); - Assert.assertTrue(bigUInt32 instanceof Long); - Assert.assertEquals(((Long)bigUInt32).longValue(), 4294967286L); - Object uuid = rs.getObject(2); - Assert.assertTrue(uuid instanceof UUID); - Assert.assertEquals(uuid, UUID.fromString("bef35f40-3b03-45b0-b1bd-8ec6593dcaaa")); - } - - @Test(groups = "integration") - public void testInsertUUIDBatch() throws SQLException { - connection.createStatement().execute("DROP TABLE IF EXISTS uuid_insert"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS uuid_insert (ui32 UInt32, uuid UUID) ENGINE = TinyLog" - ); - PreparedStatement stmt = connection.prepareStatement("insert into uuid_insert (ui32, uuid) values (?, ?)"); - stmt.setObject(1, 4294967286L); - stmt.setObject(2, UUID.fromString("bef35f40-3b03-45b0-b1bd-8ec6593dcaaa")); - stmt.addBatch(); - stmt.executeBatch(); - Statement select = connection.createStatement(); - ResultSet rs = select.executeQuery("select ui32, uuid from uuid_insert"); - rs.next(); - Object bigUInt32 = rs.getObject(1); - Assert.assertTrue(bigUInt32 instanceof Long); - Assert.assertEquals(((Long)bigUInt32).longValue(), 4294967286L); - Object uuid = rs.getObject(2); - Assert.assertTrue(uuid instanceof UUID); - Assert.assertEquals(uuid, UUID.fromString("bef35f40-3b03-45b0-b1bd-8ec6593dcaaa")); - } - - @Test(groups = "integration") - public void testInsertStringContainsKeyword() throws SQLException { - connection.createStatement().execute("DROP TABLE IF EXISTS keyword_insert"); - connection.createStatement().execute( - "CREATE TABLE keyword_insert(a String,b String)ENGINE = MergeTree() ORDER BY a SETTINGS index_granularity = 8192" - ); - - PreparedStatement stmt = connection.prepareStatement("insert into keyword_insert(a,b) values('values(',',')"); - stmt.execute(); - - Statement select = connection.createStatement(); - ResultSet rs = select.executeQuery("select * from keyword_insert"); - Assert.assertTrue(rs.next()); - Assert.assertEquals(rs.getString(1), "values("); - Assert.assertEquals(rs.getString(2), ","); - Assert.assertFalse(rs.next()); - } - - @Test(groups = "integration") - public void testInsertNullString() throws SQLException { - connection.createStatement().execute("DROP TABLE IF EXISTS null_insert"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS null_insert (val Nullable(String)) ENGINE = TinyLog" - ); - - PreparedStatement stmt = connection.prepareStatement("insert into null_insert (val) values (?)"); - stmt.setNull(1, Types.VARCHAR); - stmt.execute(); - stmt.setNull(1, Types.VARCHAR); - stmt.addBatch(); - stmt.executeBatch(); - - stmt.setString(1, null); - stmt.execute(); - stmt.setString(1, null); - stmt.addBatch(); - stmt.executeBatch(); - - stmt.setObject(1, null); - stmt.execute(); - stmt.setObject(1, null); - stmt.addBatch(); - stmt.executeBatch(); - - Statement select = connection.createStatement(); - ResultSet rs = select.executeQuery("select count(*), val from null_insert group by val"); - rs.next(); - Assert.assertEquals(rs.getInt(1), 6); - Assert.assertNull(rs.getString(2)); - Assert.assertFalse(rs.next()); - } - - @Test(groups = "integration") - public void testSelectNullableTypes() throws SQLException { - connection.createStatement().execute("DROP TABLE IF EXISTS select_nullable"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS select_nullable (idx Int32, i Nullable(Int32), ui Nullable(UInt64), f Nullable(Float32), s Nullable(String)) ENGINE = TinyLog" - ); - - PreparedStatement stmt = connection.prepareStatement("insert into select_nullable (idx, i, ui, f, s) values (?, ?, ?, ?, ?)"); - stmt.setInt(1, 1); - stmt.setObject(2, null); - stmt.setObject(3, null); - stmt.setObject(4, null); - stmt.setString(5, null); - stmt.addBatch(); - stmt.setInt(1, 2); - stmt.setInt(2, 1); - stmt.setInt(3, 1); - stmt.setFloat(4, 1.0f); - stmt.setString(5, "aaa"); - stmt.addBatch(); - stmt.executeBatch(); - - Statement select = connection.createStatement(); - ResultSet rs = select.executeQuery("select i, ui, f, s from select_nullable order by idx"); - rs.next(); - Assert.assertEquals(rs.getMetaData().getColumnType(1), Types.INTEGER); - Assert.assertEquals(rs.getMetaData().getColumnType(2), Types.BIGINT); - Assert.assertEquals(rs.getMetaData().getColumnType(3), Types.REAL); - Assert.assertEquals(rs.getMetaData().getColumnType(4), Types.VARCHAR); - - Assert.assertNull(rs.getObject(1)); - Assert.assertNull(rs.getObject(2)); - Assert.assertNull(rs.getObject(3)); - Assert.assertNull(rs.getObject(4)); - - Assert.assertEquals(rs.getInt(1), 0); - Assert.assertEquals(rs.getInt(1), 0); - Assert.assertEquals(rs.getFloat(1), 0.0f); - Assert.assertEquals(rs.getString(1), null); - - rs.next(); - Assert.assertEquals(rs.getObject(1).getClass(), Integer.class); - Assert.assertEquals(rs.getObject(2).getClass(), BigInteger.class); - Assert.assertEquals(rs.getObject(3).getClass(), Float.class); - Assert.assertEquals(rs.getObject(4).getClass(), String.class); - - Assert.assertEquals(rs.getObject(1), 1); - Assert.assertEquals(rs.getObject(2), BigInteger.ONE); - Assert.assertEquals(rs.getObject(3), 1.0f); - Assert.assertEquals(rs.getObject(4), "aaa"); - - } - - @Test(groups = "integration") - public void testInsertBatchNullValues() throws Exception { - connection.createStatement().execute( - "DROP TABLE IF EXISTS prep_nullable_value"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS prep_nullable_value " - + "(idx Int32, s Nullable(String), i Nullable(Int32), f Nullable(Float32)) " - + "ENGINE = TinyLog" - ); - PreparedStatement stmt = connection.prepareStatement( - "INSERT INTO prep_nullable_value (idx, s, i, f) VALUES " - + "(1, ?, ?, NULL), (2, NULL, NULL, ?)"); - stmt.setString(1, "foo"); - stmt.setInt(2, 42); - stmt.setFloat(3, 42.0F); - stmt.addBatch(); - int[] updateCount = stmt.executeBatch(); - Assert.assertEquals(updateCount.length, 2); - - ResultSet rs = connection.createStatement().executeQuery( - "SELECT s, i, f FROM prep_nullable_value " - + "ORDER BY idx ASC"); - rs.next(); - Assert.assertEquals(rs.getString(1), "foo"); - Assert.assertEquals(rs.getInt(2), 42); - Assert.assertNull(rs.getObject(3)); - rs.next(); - Assert.assertNull(rs.getObject(1)); - Assert.assertNull(rs.getObject(2)); - Assert.assertEquals(rs.getFloat(3), 42.0f); - } - - @Test(groups = "integration") - public void testSelectDouble() throws SQLException { - Statement select = connection.createStatement(); - ResultSet rs = select.executeQuery("select toFloat64(0.1) "); - rs.next(); - Assert.assertEquals(rs.getMetaData().getColumnType(1), Types.DOUBLE); - Assert.assertEquals(rs.getObject(1).getClass(), Double.class); - Assert.assertEquals(rs.getDouble(1), 0.1); - } - - @Test(groups = "integration") - public void testExecuteQueryClickhouseResponse() throws SQLException { - ClickHousePreparedStatement sth = (ClickHousePreparedStatement) connection.prepareStatement("select ? limit 5"); - sth.setObject(1, 314); - ClickHouseResponse resp = sth.executeQueryClickhouseResponse(); - Assert.assertEquals(resp.getData(), singletonList(singletonList("314"))); - } - - @Test(groups = "integration") - public void clickhouseJdbcFailsBecauseOfCommentInStart() throws Exception { - String sqlStatement = "/*comment*/ select * from system.numbers limit 3"; - Statement stmt = connection.createStatement(); - ResultSet rs = stmt.executeQuery(sqlStatement); - Assert.assertNotNull(rs); - for (int i = 0; i < 3; i++) { - rs.next(); - Assert.assertEquals(rs.getInt(1), i); - } - } - - @Test(groups = "integration") - public void testTrailingParameterOrderBy() throws Exception { - String sqlStatement = - "SELECT 42 AS foo, 23 AS bar from numbers(100) " - + "ORDER BY foo DESC LIMIT ?, ?"; - PreparedStatement stmt = connection.prepareStatement(sqlStatement); - stmt.setInt(1, 23); - stmt.setInt(2, 42); - ResultSet rs = stmt.executeQuery(); - Assert.assertTrue(rs.next()); - } - - @Test(groups = "integration") - public void testSetTime() throws Exception { - ClickHousePreparedStatement stmt = (ClickHousePreparedStatement) - connection.prepareStatement("SELECT ?"); - stmt.setTime(1, Time.valueOf("13:37:42")); - ResultSet rs = stmt.executeQuery(); - rs.next(); - Assert.assertEquals(rs.getTime(1), Time.valueOf("13:37:42")); - } - - @Test(groups = "integration") - public void testAsSql() throws Exception { - String unbindedStatement = "SELECT example WHERE id IN (?, ?)"; - ClickHousePreparedStatement statement = (ClickHousePreparedStatement) - connection.prepareStatement(unbindedStatement); - Assert.assertEquals(statement.asSql(), unbindedStatement); - - statement.setInt(1, 123); - Assert.assertEquals(statement.asSql(), unbindedStatement); - - statement.setInt(2, 456); - Assert.assertEquals(statement.asSql(), "SELECT example WHERE id IN (123, 456)"); - } - - @Test(groups = "integration") - public void testMetadataOnlySelect() throws Exception { - connection.createStatement().execute( - "DROP TABLE IF EXISTS mymetadata"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS mymetadata " - + "(idx Int32, s String) " - + "ENGINE = TinyLog" - ); - PreparedStatement insertStmt = connection.prepareStatement( - "INSERT INTO mymetadata (idx, s) VALUES (?, ?)"); - insertStmt.setInt(1, 42); - insertStmt.setString(2, "foo"); - insertStmt.executeUpdate(); - PreparedStatement metaStmt = connection.prepareStatement( - "SELECT idx, s FROM mymetadata WHERE idx = ?"); - metaStmt.setInt(1, 42); - ResultSetMetaData metadata = metaStmt.getMetaData(); - Assert.assertEquals(metadata.getColumnCount(), 2); - Assert.assertEquals(metadata.getColumnName(1), "idx"); - Assert.assertEquals(metadata.getColumnName(2), "s"); - } - - @Test(groups = "integration") - public void testMetadataOnlySelectAfterExecution() throws Exception { - connection.createStatement().execute( - "DROP TABLE IF EXISTS mymetadata"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS mymetadata " - + "(idx Int32, s String) " - + "ENGINE = TinyLog" - ); - PreparedStatement insertStmt = connection.prepareStatement( - "INSERT INTO mymetadata (idx, s) VALUES (?, ?)"); - insertStmt.setInt(1, 42); - insertStmt.setString(2, "foo"); - insertStmt.executeUpdate(); - PreparedStatement metaStmt = connection.prepareStatement( - "SELECT idx, s FROM mymetadata WHERE idx = ?"); - metaStmt.setInt(1, 42); - metaStmt.executeQuery(); - ResultSetMetaData metadata = metaStmt.getMetaData(); - Assert.assertEquals(metadata.getColumnCount(), 2); - Assert.assertEquals(metadata.getColumnName(1), "idx"); - Assert.assertEquals(metadata.getColumnName(2), "s"); - } - - @Test(groups = "integration") - public void testMetadataExecutionAfterMeta() throws Exception { - connection.createStatement().execute( - "DROP TABLE IF EXISTS mymetadata"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS mymetadata " - + "(idx Int32, s String) " - + "ENGINE = TinyLog" - ); - PreparedStatement insertStmt = connection.prepareStatement( - "INSERT INTO mymetadata (idx, s) VALUES (?, ?)"); - insertStmt.setInt(1, 42); - insertStmt.setString(2, "foo"); - insertStmt.executeUpdate(); - PreparedStatement metaStmt = connection.prepareStatement( - "SELECT idx, s FROM mymetadata WHERE idx = ?"); - metaStmt.setInt(1, 42); - ResultSetMetaData metadata = metaStmt.getMetaData(); - Assert.assertEquals(metadata.getColumnCount(), 2); - Assert.assertEquals(metadata.getColumnName(1), "idx"); - Assert.assertEquals(metadata.getColumnName(2), "s"); - - ResultSet rs = metaStmt.executeQuery(); - Assert.assertTrue(rs.next()); - Assert.assertEquals(rs.getInt(1), 42); - Assert.assertEquals(rs.getString(2), "foo"); - metadata = metaStmt.getMetaData(); - Assert.assertEquals(metadata.getColumnCount(), 2); - Assert.assertEquals(metadata.getColumnName(1), "idx"); - Assert.assertEquals(metadata.getColumnName(2), "s"); - } - - @Test(groups = "integration") - public void testMetadataOnlyUpdate() throws Exception { - connection.createStatement().execute( - "DROP TABLE IF EXISTS mymetadata"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS mymetadata " - + "(idx Int32, s String) " - + "ENGINE = TinyLog" - ); - PreparedStatement insertStmt = connection.prepareStatement( - "INSERT INTO mymetadata (idx, s) VALUES (?, ?)"); - insertStmt.setInt(1, 42); - insertStmt.setString(2, "foo"); - insertStmt.executeUpdate(); - PreparedStatement metaStmt = connection.prepareStatement( - "UPDATE mymetadata SET s = ? WHERE idx = ?"); - metaStmt.setString(1, "foo"); - metaStmt.setInt(2, 42); - ResultSetMetaData metadata = metaStmt.getMetaData(); - Assert.assertNull(metadata); - metaStmt.close(); - } - - @Test(groups = "integration") - public void testInsertWithFunctions() throws Exception { - connection.createStatement().execute( - "DROP TABLE IF EXISTS insertfunctions"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS insertfunctions " - + "(id UInt32, foo String, bar String) " - + "ENGINE = TinyLog"); - PreparedStatement stmt = connection.prepareStatement( - "INSERT INTO insertfunctions(id, foo, bar) VALUES " - + "(?, lower(reverse(?)), upper(reverse(?)))"); - stmt.setInt(1, 42); - stmt.setString(2, "Foo"); - stmt.setString(3, "Bar"); - String sql = stmt.unwrap(ClickHousePreparedStatementImpl.class).asSql(); - Assert.assertEquals( - sql, - "INSERT INTO insertfunctions(id, foo, bar) VALUES " - + "(42, lower(reverse('Foo')), upper(reverse('Bar')))"); - // make sure that there is no exception - stmt.execute(); - ResultSet rs = connection.createStatement().executeQuery( - "SELECT id, foo, bar FROM insertfunctions"); - rs.next(); - Assert.assertEquals(rs.getInt(1), 42); - Assert.assertEquals(rs.getString(2), "oof"); - Assert.assertEquals(rs.getString(3), "RAB"); - rs.close(); - } - - public void testBytes() throws Exception { - connection.createStatement().execute( - "DROP TABLE IF EXISTS strings_versus_bytes"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS strings_versus_bytes" - + "(s String, fs FixedString(8)) " - + "ENGINE = TinyLog" - ); - PreparedStatement insertStmt = connection.prepareStatement( - "INSERT INTO strings_versus_bytes (s, fs) VALUES (?, ?)"); - insertStmt.setBytes(1, "foo".getBytes(Charset.forName("UTF-8"))); - insertStmt.setBytes(2, "bar".getBytes(Charset.forName("UTF-8"))); - insertStmt.executeUpdate(); - ResultSet rs = connection.createStatement().executeQuery( - "SELECT s, fs FROM strings_versus_bytes"); - rs.next(); - Assert.assertEquals(rs.getString(1), "foo"); - // TODO: The actual String returned by our ResultSet is rather strange - // ['b' 'a' 'r' 0 0 0 0 0] - Assert.assertEquals(rs.getString(2).trim(), "bar"); - } - - @Test(groups = "integration") - public void testInsertWithFunctionsAddBatch() throws Exception { - connection.createStatement().execute( - "DROP TABLE IF EXISTS insertfunctions"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS insertfunctions " - + "(id UInt32, foo String, bar String) " - + "ENGINE = TinyLog"); - PreparedStatement stmt = connection.prepareStatement( - "INSERT INTO insertfunctions(id, foo, bar) VALUES " - + "(?, lower(reverse(?)), upper(reverse(?)))"); - stmt.setInt(1, 42); - stmt.setString(2, "Foo"); - stmt.setString(3, "Bar"); - stmt.addBatch(); - stmt.executeBatch(); - // this will _not_ perform the functions, but instead send the parameters - // as is to the clickhouse server - } - - @SuppressWarnings("boxing") - @Test(groups = "integration") - public void testMultiLineValues() throws Exception { - connection.createStatement().execute( - "DROP TABLE IF EXISTS multiline"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS multiline" - + "(foo Int32, bar String) " - + "ENGINE = TinyLog" - ); - PreparedStatement insertStmt = connection.prepareStatement( - "INSERT INTO multiline\n" - + "\t(foo, bar)\r\n" - + "\t\tVALUES\n" - + "(?, ?) , \n\r" - + "\t(?,?),(?,?)\n"); - Map testData = new HashMap<>(); - testData.put(23, "baz"); - testData.put(42, "bar"); - testData.put(1337, "oof"); - int i = 0; - for (Integer k : testData.keySet()) { - insertStmt.setInt(++i, k.intValue()); - insertStmt.setString(++i, testData.get(k)); - } - insertStmt.executeUpdate(); - - ResultSet rs = connection.createStatement().executeQuery( - "SELECT * FROM multiline ORDER BY foo"); - rs.next(); - Assert.assertEquals(rs.getInt(1), 23); - Assert.assertEquals(rs.getString(2), "baz"); - rs.next(); - Assert.assertEquals(rs.getInt(1), 42); - Assert.assertEquals(rs.getString(2), "bar"); - rs.next(); - Assert.assertEquals(rs.getInt(1), 1337); - Assert.assertEquals(rs.getString(2), "oof"); - Assert.assertFalse(rs.next()); - } - - // Issue 153 - public void testArrayDateTime() throws Exception { - connection.createStatement().execute( - "DROP TABLE IF EXISTS date_time_array"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS date_time_array" - + "(foo Array(DateTime)) " - + "ENGINE = TinyLog" - ); - PreparedStatement stmt = connection.prepareStatement( - "INSERT INTO date_time_array (foo) VALUES (?)"); - stmt.setArray(1, connection.createArrayOf("DateTime", - new Timestamp[] { - new Timestamp(1557136800000L), - new Timestamp(1560698526598L) - })); - stmt.execute(); - - ResultSet rs = connection.createStatement().executeQuery( - "SELECT foo FROM date_time_array"); - rs.next(); - Timestamp[] result = (Timestamp[]) rs.getArray(1).getArray(); - Assert.assertEquals(result[0].getTime(), 1557136800000L); - Assert.assertEquals(result[1].getTime(), 1560698526598L); - } - - @Test(groups = "integration") - public void testStaticNullValue() throws Exception { - connection.createStatement().execute( - "DROP TABLE IF EXISTS static_null_value"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS static_null_value" - + "(foo Nullable(String), bar Nullable(String)) " - + "ENGINE = TinyLog" - ); - PreparedStatement ps0 = connection.prepareStatement( - "INSERT INTO static_null_value(foo) VALUES (null)"); - ps0.executeUpdate(); - - ps0 = connection.prepareStatement( - "INSERT INTO static_null_value(foo, bar) VALUES (null, ?)"); - ps0.setNull(1, Types.VARCHAR); - ps0.executeUpdate(); - } - - // known issue - public void testTernaryOperator() throws Exception { - String sql = "select x > 2 ? 'a' : 'b' from (select number as x from system.numbers limit ?)"; - try (PreparedStatement s = connection.prepareStatement(sql)) { - int len = 5; - s.setInt(1, len); - ResultSet rs = s.executeQuery(); - for (int i = 0; i < len; i++) { - assertTrue(rs.next()); - assertEquals(rs.getString(1), i > 2 ? "a" : "b"); - } - assertFalse(rs.next()); - rs.close(); - } - } - - @Test(groups = "integration") - public void testBatchProcess() throws Exception { - try (PreparedStatement s = connection.prepareStatement( - "create table if not exists batch_update(k UInt8, v String) engine=MergeTree order by k")) { - s.execute(); - } - - Object[][] data = new Object[][] { - new Object[] {1, "a"}, - new Object[] {1, "b"}, - new Object[] {3, "c"} - }; - - // insert - try (PreparedStatement s = connection.prepareStatement("insert into table batch_update values(?,?)")) { - for (int i = 0; i < data.length; i++) { - Object[] row = data[i]; - s.setInt(1, (int) row[0]); - s.setString(2, (String) row[1]); - s.addBatch(); - } - int[] results = s.executeBatch(); - assertNotNull(results); - assertEquals(results.length, 3); - } - - // select - try (PreparedStatement s = connection.prepareStatement( - "select * from batch_update where k in (?, ?) order by k, v")) { - s.setInt(1, 1); - s.setInt(2, 3); - ResultSet rs = s.executeQuery(); - int index = 0; - while (rs.next()) { - Object[] row = data[index++]; - assertEquals(rs.getInt(1), (int) row[0]); - assertEquals(rs.getString(2), (String) row[1]); - } - assertEquals(index, data.length); - } - - // update - try (PreparedStatement s = connection.prepareStatement( - "alter table batch_update update v = ? where k = ?")) { - s.setString(1, "x"); - s.setInt(2, 1); - s.addBatch(); - s.setString(1, "y"); - s.setInt(2, 3); - s.addBatch(); - int[] results = s.executeBatch(); - assertNotNull(results); - assertEquals(results.length, 2); - } - - // delete - try (PreparedStatement s = connection.prepareStatement("alter table batch_update delete where k = ?")) { - s.setInt(1, 1); - s.addBatch(); - s.setInt(1, 3); - s.addBatch(); - int[] results = s.executeBatch(); - assertNotNull(results); - assertEquals(results.length, 2); - } - - try (PreparedStatement s = connection.prepareStatement("drop table if exists batch_update")) { - s.execute(); - } - } - - private static byte[] randomEncodedUUID() { - UUID uuid = UUID.randomUUID(); - return ByteBuffer.allocate(16) - .putLong(uuid.getMostSignificantBits()) - .putLong(uuid.getLeastSignificantBits()) - .array(); - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickhouseLZ4StreamTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickhouseLZ4StreamTest.java deleted file mode 100644 index 6ddf3c21b..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickhouseLZ4StreamTest.java +++ /dev/null @@ -1,57 +0,0 @@ -package ru.yandex.clickhouse.integration; - -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import ru.yandex.clickhouse.ClickHouseConnection; -import ru.yandex.clickhouse.JdbcIntegrationTest; -import ru.yandex.clickhouse.settings.ClickHouseProperties; - -public class ClickhouseLZ4StreamTest extends JdbcIntegrationTest { - private ClickHouseConnection connection; - - @BeforeClass(groups = "integration") - public void setUp() throws Exception { - ClickHouseProperties properties = new ClickHouseProperties(); - properties.setDecompress(true); - - connection = newConnection(properties); - } - - @AfterClass(groups = "integration") - public void tearDown() throws Exception { - closeConnection(connection); - } - - @Test(groups = "integration") - public void testBigBatchCompressedInsert() throws SQLException { - if ("21.3.3.14".equals(connection.getServerVersion())) { - return; - } - - connection.createStatement().execute("DROP TABLE IF EXISTS big_batch_insert"); - connection.createStatement().execute( - "CREATE TABLE IF NOT EXISTS big_batch_insert (i Int32, s String) ENGINE = TinyLog" - ); - - PreparedStatement statement = connection.prepareStatement("INSERT INTO big_batch_insert (s, i) VALUES (?, ?)"); - - int cnt = 1000000; - for (int i = 0; i < cnt; i++) { - statement.setString(1, "string" + i); - statement.setInt(2, i); - statement.addBatch(); - } - - statement.executeBatch(); - - ResultSet rs = connection.createStatement().executeQuery("SELECT count() as cnt from big_batch_insert"); - rs.next(); - Assert.assertEquals(rs.getInt("cnt"), cnt); - Assert.assertFalse(rs.next()); - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ErrorsTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ErrorsTest.java deleted file mode 100644 index 672bad8e2..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ErrorsTest.java +++ /dev/null @@ -1,120 +0,0 @@ -package ru.yandex.clickhouse.integration; - -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.ClickHouseConnection; -import ru.yandex.clickhouse.JdbcIntegrationTest; -import ru.yandex.clickhouse.except.ClickHouseException; -import ru.yandex.clickhouse.settings.ClickHouseProperties; -import com.clickhouse.client.ClickHouseServerForTest; -import com.clickhouse.client.ClickHouseVersion; - -import java.sql.Connection; -import java.sql.Date; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.List; - -public class ErrorsTest extends JdbcIntegrationTest { - private ClickHouseConnection connection; - - @BeforeClass(groups = "integration") - public void setUp() throws Exception { - connection = newConnection(); - } - - @AfterClass(groups = "integration") - public void tearDown() throws Exception { - closeConnection(connection); - } - - @Test(groups = "integration") - public void testWrongUser() { - ClickHouseProperties properties = new ClickHouseProperties(); - properties.setUser("not_existing"); - try (Connection connection = newConnection(properties)) { - } catch (Exception e) { - String version = ClickHouseServerForTest.getClickHouseVersion(); - if (!version.isEmpty() && ClickHouseVersion.check(version, "(,19]")) { - Assert.assertEquals((getClickhouseException(e)).getErrorCode(), 192); - } else { - Assert.assertEquals((getClickhouseException(e)).getErrorCode(), 516); - } - return; - } - Assert.assertTrue(false, "didn' find correct error"); - } - - @Test(groups = "integration", expectedExceptions = ClickHouseException.class) - public void testTableNotExists() throws SQLException { - try (Statement statement = connection.createStatement()) { - statement.execute("select * from table_not_exists"); - } - } - - @Test(groups = "integration") - public void testErrorDecompression() throws Exception { - ClickHouseProperties properties = new ClickHouseProperties(); - properties.setCompress(true); - String[] address = getClickHouseHttpAddress().split(":"); - - try (Connection connection = newConnection(properties)) { - connection.createStatement().execute("DROP TABLE IF EXISTS table_not_exists"); - - PreparedStatement statement = connection - .prepareStatement("INSERT INTO table_not_exists (d, s) VALUES (?, ?)"); - - statement.setDate(1, new Date(System.currentTimeMillis())); - statement.setInt(2, 1); - try { - statement.executeBatch(); - } catch (Exception e) { - String exceptionMsg = getClickhouseException(e).getMessage(); - Assert.assertTrue( - exceptionMsg - .startsWith("ClickHouse exception, code: 60, host: " + address[0] + ", port: " - + address[1] + "; Code: 60") - && exceptionMsg.contains( - " DB::Exception: Table " + dbName + ".table_not_exists doesn't exist"), - exceptionMsg); - return; - } - Assert.assertTrue(false, "didn' find correct error"); - } - } - - private static ClickHouseException getClickhouseException(Throwable t) { - List causes = new ArrayList<>(4); - causes.add(t); - - Throwable slowPointer = t; - boolean advanceSlowPointer = false; - - Throwable cause; - while ((cause = t.getCause()) != null) { - t = cause; - causes.add(t); - - if (t == slowPointer) { - throw new IllegalArgumentException("Loop in causal chain detected.", t); - } - if (advanceSlowPointer) { - slowPointer = slowPointer.getCause(); - } - advanceSlowPointer = !advanceSlowPointer; // only advance every other iteration - } - - for (Throwable throwable : causes) { - if (throwable instanceof ClickHouseException) { - return (ClickHouseException) throwable; - } - } - - throw new IllegalArgumentException("no ClickHouseException found"); - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/NativeStreamTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/NativeStreamTest.java deleted file mode 100644 index 0f6d460c6..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/NativeStreamTest.java +++ /dev/null @@ -1,91 +0,0 @@ -package ru.yandex.clickhouse.integration; - -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import ru.yandex.clickhouse.ClickHouseConnection; -import ru.yandex.clickhouse.ClickHouseStatement; -import ru.yandex.clickhouse.JdbcIntegrationTest; -import ru.yandex.clickhouse.util.ClickHouseRowBinaryStream; -import ru.yandex.clickhouse.util.ClickHouseStreamCallback; - -import java.io.IOException; -import java.sql.Date; -import java.sql.ResultSet; - -import static org.testng.Assert.assertEquals; - -public class NativeStreamTest extends JdbcIntegrationTest { - private ClickHouseConnection connection; - - @BeforeClass(groups = "integration") - public void setUp() throws Exception { - connection = newConnection(); - } - - @AfterClass(groups = "integration") - public void tearDown() throws Exception { - closeConnection(connection); - } - - @Test(groups = "integration") - public void testLowCardinality() throws Exception{ - final ClickHouseStatement statement = connection.createStatement(); - connection.createStatement().execute("DROP TABLE IF EXISTS low_cardinality"); - connection.createStatement().execute( - "CREATE TABLE low_cardinality (date Date, " + - "lowCardinality LowCardinality(String), " + - "string String," + - "fixedString FixedString(3)," + - "fixedStringLC LowCardinality(FixedString(6))" + - ") ENGINE = MergeTree partition by toYYYYMM(date) order by date" - ); - - // Code: 368, e.displayText() = DB::Exception: Bad cast from type DB::ColumnString to DB::ColumnLowCardinality - if (connection.getMetaData().getDatabaseMajorVersion() <= 19) { - return; - } - - final Date date1 = new Date(1497474018000L); - - statement.sendNativeStream( - "INSERT INTO low_cardinality (date, lowCardinality, string, fixedString, fixedStringLC)", - new ClickHouseStreamCallback() { - @Override - public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { - stream.writeUnsignedLeb128(5); // Columns number - stream.writeUnsignedLeb128(1); // Rows number - - stream.writeString("date"); // Column name - stream.writeString("Date"); // Column type - stream.writeDate(date1); // value - - stream.writeString("lowCardinality"); // Column name - stream.writeString("String"); // Column type - stream.writeString("string"); // value - - stream.writeString("string"); // Column name - stream.writeString("String"); // Column type - stream.writeString("string"); // value - - stream.writeString("fixedString"); // Column name - stream.writeString("FixedString(3)"); // Column type - stream.writeFixedString("str"); // value - - stream.writeString("fixedStringLC"); // Column name - stream.writeString("FixedString(6)"); // Column type - stream.writeFixedString("str1", 6); // value - } - } - ); - - ResultSet rs = connection.createStatement().executeQuery("SELECT * FROM low_cardinality"); - - Assert.assertTrue(rs.next()); - assertEquals(rs.getString("lowCardinality"), "string"); - assertEquals(rs.getString("string"), "string"); - assertEquals(rs.getString("fixedString"), "str"); - assertEquals(rs.getString("fixedStringLC"), "str1\0\0"); - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/OnTime.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/OnTime.java deleted file mode 100644 index c8cd658fa..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/OnTime.java +++ /dev/null @@ -1,62 +0,0 @@ -package ru.yandex.clickhouse.integration; - -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.ClickHouseDataSource; -import ru.yandex.clickhouse.JdbcIntegrationTest; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - -/** - * Here it is assumed the connection to a ClickHouse instance with flights example data it available at localhost:8123 - * For ClickHouse quickstart and example dataset see https://clickhouse.yandex/tutorial.html - */ -public class OnTime extends JdbcIntegrationTest { - - private ClickHouseDataSource dataSource; - private Connection connection; - - @BeforeClass(groups = "integration") - public void setUp() throws Exception { - dataSource = newDataSource(); - connection = dataSource.getConnection(); - connection.createStatement().execute("CREATE DATABASE IF NOT EXISTS test"); - } - - @Test(groups = "integration", enabled = false) - public void simpleSelect() throws SQLException { - Statement statement = connection.createStatement(); - ResultSet rs = statement.executeQuery("select FlightDate, AirlineID, FlightNum from ontime limit 10"); - while (rs.next()) { - System.out.println(rs.getDate("FlightDate") + ";" + rs.getInt("AirlineID") + ";" + rs.getString("FlightNum")); - } - statement.close(); - } - - @Test(groups = "integration", enabled = false) - public void mostTrendingDestinationTest() throws SQLException { - String query = - "SELECT \n" + - " DestCityName, \n" + - " sum(Year = 2014) AS c2014, \n" + - " sum(Year = 2015) AS c2015, \n" + - " c2015 / c2014 AS diff\n" + - "FROM ontime\n" + - "WHERE Year IN (2014, 2015)\n" + - "GROUP BY DestCityName\n" + - "HAVING (c2014 > 10000) AND (c2015 > 1000) AND (diff > 1)\n" + - "ORDER BY diff DESC"; - - Statement statement = connection.createStatement(); - ResultSet rs = statement.executeQuery(query); - while (rs.next()) { - System.out.println(rs.getString("DestCityName") + ";" + rs.getBigDecimal("c2014") + ";" + rs.getBigDecimal("c2015") + ";" + rs.getFloat("diff")); - } - statement.close(); - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ResultSummaryTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ResultSummaryTest.java deleted file mode 100644 index 0b8066228..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ResultSummaryTest.java +++ /dev/null @@ -1,135 +0,0 @@ -package ru.yandex.clickhouse.integration; - -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import ru.yandex.clickhouse.*; -import ru.yandex.clickhouse.settings.ClickHouseQueryParam; - -import java.sql.SQLException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNull; -import static org.testng.AssertJUnit.assertTrue; - -public class ResultSummaryTest extends JdbcIntegrationTest { - private ClickHouseConnection connection; - - @BeforeClass(groups = "integration") - public void setUp() throws Exception { - connection = newConnection(); - } - - @AfterClass(groups = "integration") - public void tearDown() throws Exception { - closeConnection(connection); - } - - @Test(groups = "integration") - public void select() throws Exception { - ClickHouseStatement st = connection.createStatement(); - st.executeQuery("SELECT * FROM numbers(10)", Collections.singletonMap(ClickHouseQueryParam.SEND_PROGRESS_IN_HTTP_HEADERS, "true")); - - assertTrue(st.getResponseSummary().getReadRows() >= 10); - assertTrue(st.getResponseSummary().getReadBytes() > 0); - } - - @Test(groups = "integration") - public void largeSelect() throws Exception { - ClickHouseStatement st = connection.createStatement(); - st.executeQuery("SELECT * FROM numbers(10000000)", Collections.singletonMap(ClickHouseQueryParam.SEND_PROGRESS_IN_HTTP_HEADERS, "true")); - - assertTrue(st.getResponseSummary().getReadRows() < 10000000); - assertTrue(st.getResponseSummary().getReadBytes() > 0); - } - - @Test(groups = "integration") - public void largeSelectWaitEndOfQuery() throws Exception { - ClickHouseStatement st = connection.createStatement(); - st.executeQuery("SELECT * FROM numbers(10000000)", largeSelectWaitEndOfQueryParams()); - - assertTrue(st.getResponseSummary().getReadRows() >= 10000000); - assertTrue(st.getResponseSummary().getReadBytes() > 0); - } - - private Map largeSelectWaitEndOfQueryParams() { - Map res = new HashMap<>(); - res.put(ClickHouseQueryParam.SEND_PROGRESS_IN_HTTP_HEADERS, "true"); - res.put(ClickHouseQueryParam.WAIT_END_OF_QUERY, "true"); - return res; - } - - @Test(groups = "integration") - public void selectWithoutParam() throws Exception { - ClickHouseStatement st = connection.createStatement(); - st.executeQuery("SELECT * FROM numbers(10)", Collections.singletonMap(ClickHouseQueryParam.SEND_PROGRESS_IN_HTTP_HEADERS, "true")); - - assertTrue(st.getResponseSummary().getReadRows() >= 10); - assertTrue(st.getResponseSummary().getReadBytes() > 0); - } - - @Test(groups = "integration") - public void insertSingle() throws Exception { - createInsertTestTable(); - - ClickHousePreparedStatement ps = (ClickHousePreparedStatement) connection.prepareStatement("INSERT INTO insert_test VALUES(?)"); - ps.setLong(1, 1); - ps.executeQuery(Collections.singletonMap(ClickHouseQueryParam.SEND_PROGRESS_IN_HTTP_HEADERS, "true")); - - assertEquals(ps.getResponseSummary().getWrittenRows(), 1); - assertTrue(ps.getResponseSummary().getWrittenBytes() > 0); - } - - @Test(groups = "integration") - public void insertBatch() throws Exception { - createInsertTestTable(); - - ClickHousePreparedStatement ps = (ClickHousePreparedStatement) connection.prepareStatement("INSERT INTO insert_test VALUES(?)"); - for (long i = 0; i < 10; i++) { - ps.setLong(1, i); - ps.addBatch(); - } - ps.executeBatch(Collections.singletonMap(ClickHouseQueryParam.SEND_PROGRESS_IN_HTTP_HEADERS, "true")); - - assertEquals(ps.getResponseSummary().getWrittenRows(), 10); - assertTrue(ps.getResponseSummary().getWrittenBytes() > 0); - } - - @Test(groups = "integration") - public void insertSelect() throws Exception { - createInsertTestTable(); - - ClickHousePreparedStatement ps = (ClickHousePreparedStatement) connection.prepareStatement("INSERT INTO insert_test SELECT number FROM numbers(10)"); - ps.executeQuery(Collections.singletonMap(ClickHouseQueryParam.SEND_PROGRESS_IN_HTTP_HEADERS, "true")); - - assertEquals(ps.getResponseSummary().getWrittenRows(), 10); - assertTrue(ps.getResponseSummary().getWrittenBytes() > 0); - } - - @Test(groups = "integration") - public void insertLargeSelect() throws Exception { - createInsertTestTable(); - - ClickHousePreparedStatement ps = (ClickHousePreparedStatement) connection.prepareStatement("INSERT INTO insert_test SELECT number FROM numbers(10000000)"); - ps.executeQuery(Collections.singletonMap(ClickHouseQueryParam.SEND_PROGRESS_IN_HTTP_HEADERS, "true")); - - assertEquals(ps.getResponseSummary().getWrittenRows(), 10000000); - assertTrue(ps.getResponseSummary().getWrittenBytes() > 0); - } - - @Test(groups = "integration") - public void noSummary() throws Exception { - ClickHouseStatement st = connection.createStatement(); - st.executeQuery("SELECT * FROM numbers(10)"); - - assertNull(st.getResponseSummary()); - } - - private void createInsertTestTable() throws SQLException { - connection.createStatement().execute("DROP TABLE IF EXISTS insert_test"); - connection.createStatement().execute("CREATE TABLE IF NOT EXISTS insert_test (value UInt32) ENGINE = TinyLog"); - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/RowBinaryStreamTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/RowBinaryStreamTest.java deleted file mode 100644 index 54e881675..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/RowBinaryStreamTest.java +++ /dev/null @@ -1,643 +0,0 @@ -package ru.yandex.clickhouse.integration; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; - -import java.io.EOFException; -import java.io.IOException; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Date; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.time.Instant; -import java.time.LocalTime; -import java.time.ZoneId; -import java.util.Calendar; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicLong; - -import com.clickhouse.client.ClickHouseVersion; - -import org.roaringbitmap.RoaringBitmap; -import org.roaringbitmap.buffer.ImmutableRoaringBitmap; -import org.roaringbitmap.buffer.MutableRoaringBitmap; -import org.roaringbitmap.longlong.Roaring64Bitmap; -import org.roaringbitmap.longlong.Roaring64NavigableMap; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import ru.yandex.clickhouse.ClickHouseConnection; -import ru.yandex.clickhouse.ClickHouseStatement; -import ru.yandex.clickhouse.JdbcIntegrationTest; -import ru.yandex.clickhouse.domain.ClickHouseDataType; -import ru.yandex.clickhouse.util.ClickHouseBitmap; -import ru.yandex.clickhouse.util.ClickHouseRowBinaryInputStream; -import ru.yandex.clickhouse.util.ClickHouseRowBinaryStream; -import ru.yandex.clickhouse.util.ClickHouseStreamCallback; - -/** - * @author Dmitry Andreev - */ -public class RowBinaryStreamTest extends JdbcIntegrationTest { - private ClickHouseConnection connection; - - @BeforeClass(groups = "integration") - public void setUp() throws Exception { - connection = newConnection(); - } - - @AfterClass(groups = "integration") - public void tearDown() throws Exception { - closeConnection(connection); - } - - private void createTable(String table) throws SQLException { - connection.createStatement().execute("DROP TABLE IF EXISTS " + table); - connection.createStatement() - .execute("CREATE TABLE " + table + " (" + "date Date, " + "dateTime DateTime, " + "string String, " - + "int8 Int8, " + "uInt8 UInt8, " + "int16 Int16, " + "uInt16 UInt16, " + "int32 Int32, " - + "uInt32 UInt32, " + "int64 Int64, " + "uInt64 UInt64, " + "float32 Float32, " - + "float64 Float64, " + "dateArray Array(Date), " + "dateTimeArray Array(DateTime), " - + "stringArray Array(String), " + "int8Array Array(Int8), " + "uInt8Array Array(UInt8), " - + "int16Array Array(Int16), " + "uInt16Array Array(UInt16), " + "int32Array Array(Int32), " - + "uInt32Array Array(UInt32), " + "int64Array Array(Int64), " + "uInt64Array Array(UInt64), " - + "float32Array Array(Float32), " + "float64Array Array(Float64), " + "uuid UUID," - + "lowCardinality LowCardinality(String)," + "fixedString FixedString(15)" - + ") ENGINE = MergeTree partition by toYYYYMM(date) order by date"); - } - - @Test(groups = "integration") - public void multiRowTest() throws SQLException { - connection.createStatement().execute("DROP TABLE IF EXISTS big_data"); - connection.createStatement().execute("CREATE TABLE big_data (value Int32) ENGINE = TinyLog()"); - - final int count = 1000000; - final AtomicLong sum = new AtomicLong(); - - connection.createStatement().sendRowBinaryStream("INSERT INTO big_data (value)", - new ClickHouseStreamCallback() { - @Override - public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { - for (int i = 0; i < count; i++) { - stream.writeInt32(i); - sum.addAndGet(i); - } - } - }); - - ResultSet rs = connection.createStatement() - .executeQuery("SELECT count() AS cnt, sum(value) AS sum FROM big_data"); - - Assert.assertTrue(rs.next()); - assertEquals(rs.getInt("cnt"), count); - assertEquals(rs.getLong("sum"), sum.get()); - } - - @Test(groups = "integration") - public void testRowBinaryStream() throws Exception { - testRowBinaryStream(false); - } - - @Test(groups = "integration") - public void testRowBinaryInputStream() throws Exception { - testRowBinaryStream(true); - } - - private String createtestBitmapTable(ClickHouseDataType innerType) throws Exception { - String tableName = "test_binary_rb_" + innerType.name(); - String arrType = "Array(" + innerType.name() + ")"; - String rbTypeName = "AggregateFunction(groupBitmap, " + innerType.name() + ")"; - try (ClickHouseStatement statement = connection.createStatement()) { - statement.execute("DROP TABLE IF EXISTS " + tableName); - statement.execute("CREATE TABLE IF NOT EXISTS " + tableName + "(i UInt8, a " + arrType + ", b " + rbTypeName - + ") engine=Memory"); - } - - return tableName; - } - - private int[] genRoaringBitmapValues(int length, ClickHouseDataType innerType) { - int[] values = new int[length]; - - for (int i = 0; i < length; i++) { - values[i] = i; - } - - return values; - } - - private long[] gen64BitmapValues(int length, long base, long step) { - long[] values = new long[length]; - - for (int i = 0; i < length; i++) { - values[i] = base + i * step; - } - - return values; - } - - private void writeValues(ClickHouseRowBinaryStream stream, int[] values, ClickHouseDataType innerType) - throws IOException { - switch (innerType) { - case Int8: - case UInt8: - stream.writeUInt8Array(values); - break; - case Int16: - case UInt16: - stream.writeUInt16Array(values); - break; - case Int32: - case UInt32: - stream.writeInt32Array(values); - break; - default: - throw new IllegalArgumentException(innerType.name() + " is not supported!"); - } - } - - private void testBitmap(ClickHouseDataType innerType, int valueLength) throws Exception { - try (ClickHouseStatement statement = connection.createStatement()) { - String tableName = createtestBitmapTable(innerType); - int[] values = genRoaringBitmapValues(valueLength, innerType); - statement.sendRowBinaryStream("insert into table " + tableName, new ClickHouseStreamCallback() { - @Override - public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { - stream.writeByte((byte) 1); - writeValues(stream, values, innerType); - stream.writeBitmap(ClickHouseBitmap.wrap(RoaringBitmap.bitmapOf(values), innerType)); - stream.writeByte((byte) 2); - writeValues(stream, values, innerType); - stream.writeBitmap(ClickHouseBitmap.wrap(ImmutableRoaringBitmap.bitmapOf(values), innerType)); - stream.writeByte((byte) 3); - writeValues(stream, values, innerType); - stream.writeBitmap(ClickHouseBitmap.wrap(MutableRoaringBitmap.bitmapOf(values), innerType)); - } - }); - - for (int i = 0; i < 3; i++) { - String sql = "select b = bitmapBuild(a) ? 1 : 0 from " + tableName + " where i = " + (i + 1); - try (ResultSet rs = statement.executeQuery(sql)) { - assertTrue(rs.next()); - assertEquals(rs.getInt(1), 1); - assertFalse(rs.next()); - } - - sql = "select b from " + tableName + " where i = " + (i + 1); - try (ClickHouseRowBinaryInputStream in = statement.executeQueryClickhouseRowBinaryStream(sql)) { - assertEquals(in.readBitmap(innerType), - ClickHouseBitmap.wrap(RoaringBitmap.bitmapOf(values), innerType)); - } - } - - statement.execute("drop table if exists " + tableName); - } - } - - private void testBitmap64(int valueLength, long base, long step) throws Exception { - ClickHouseDataType innerType = ClickHouseDataType.UInt64; - try (ClickHouseStatement statement = connection.createStatement()) { - String tableName = createtestBitmapTable(innerType); - long[] values = gen64BitmapValues(valueLength, base, step); - statement.sendRowBinaryStream("insert into table " + tableName, new ClickHouseStreamCallback() { - @Override - public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { - stream.writeByte((byte) 1); - stream.writeUInt64Array(values); - stream.writeBitmap( - ClickHouseBitmap.wrap(Roaring64NavigableMap.bitmapOf(values), ClickHouseDataType.UInt64)); - stream.writeByte((byte) 2); - stream.writeUInt64Array(values); - stream.writeBitmap( - ClickHouseBitmap.wrap(Roaring64Bitmap.bitmapOf(values), ClickHouseDataType.UInt64)); - } - }); - - String sql = "select bitmapBuild(a) = b ? 1 : 0 from " + tableName + " order by i"; - try (ResultSet rs = statement.executeQuery(sql)) { - assertTrue(rs.next()); - assertEquals(rs.getInt(1), 1); - assertTrue(rs.next()); - assertEquals(rs.getInt(1), 1); - assertFalse(rs.next()); - } - - sql = "select b from " + tableName + " order by i"; - try (ClickHouseRowBinaryInputStream in = statement.executeQueryClickhouseRowBinaryStream(sql)) { - assertEquals(in.readBitmap(innerType), - ClickHouseBitmap.wrap(Roaring64NavigableMap.bitmapOf(values), innerType)); - } - - statement.execute("drop table if exists " + tableName); - } - } - - @Test(groups = "integration") - public void testBitmap() throws Exception { - // TODO seems Int8, Int16 and Int32 are still not supported in ClickHouse - testBitmap(ClickHouseDataType.UInt8, 32); - testBitmap(ClickHouseDataType.UInt8, 256); - testBitmap(ClickHouseDataType.UInt16, 32); - testBitmap(ClickHouseDataType.UInt16, 65536); - testBitmap(ClickHouseDataType.UInt32, 32); - testBitmap(ClickHouseDataType.UInt32, 65537); - - testBitmap64(32, 0L, 1L); - testBitmap64(32, Long.MAX_VALUE, -1L); - - if (ClickHouseVersion.check(connection.getServerVersion(), "(20.8,]")) { - testBitmap64(65537, 100000L, 1L); // highToBitmap.size() == 1 - testBitmap64(65537, 9223372036854775807L, -1000000000L); // highToBitmap.size() > 1 - } - } - - @Test(groups = "integration") - public void testBigDecimals() throws Exception { - try (ClickHouseStatement statement = connection.createStatement()) { - statement.execute("set allow_experimental_bigint_types=1;" - + "create table if not exists test_big_decimals(d128 Decimal128(6), d256 Decimal256(12)) engine=Memory"); - } catch (SQLException e) { - return; - } - - try (ClickHouseStatement statement = connection.createStatement()) { - BigDecimal[] values = new BigDecimal[] { BigDecimal.valueOf(-123.123456789D), BigDecimal.ZERO, - BigDecimal.valueOf(123.123456789D) }; - statement.sendRowBinaryStream("insert into table test_big_decimals", new ClickHouseStreamCallback() { - @Override - public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { - for (int i = 0; i < values.length; i++) { - stream.writeDecimal128(values[i], 6); - stream.writeDecimal256(values[i], 12); - } - } - }); - - try (ResultSet rs = statement.executeQuery("select * from test_big_decimals order by d128")) { - int rowCounter = 0; - while (rs.next()) { - rowCounter++; - assertEquals(rs.getBigDecimal(1, 6), values[rowCounter - 1].setScale(6, BigDecimal.ROUND_DOWN)); - assertEquals(rs.getBigDecimal(2, 12), values[rowCounter - 1].setScale(12, BigDecimal.ROUND_DOWN)); - } - - assertEquals(rowCounter, values.length); - } - - statement.execute("drop table if exists test_big_decimals"); - } - } - - private void testRowBinaryStream(boolean rowBinaryResult) throws Exception { - createTable("raw_binary"); - ClickHouseStatement statement = connection.createStatement(); - final long timestamp = 1483230102000L; // 2017-01-01 03:21:42 - final Date date1 = new Date(timestamp); - final Date date2 = new Date(1494321702000L); // 2017-05-09 12:21:42 - final Date[] dates1 = { new Date(1263945600000L) }; - final Timestamp[] dateTimes1 = { new Timestamp(1483230102000L) }; - final String[] strings1 = { "test", "test2" }; - final byte[] int8s1 = { Byte.MIN_VALUE }; - final int[] uint8s1 = { 0 }; - final short[] int16s1 = { Short.MIN_VALUE }; - final int[] uint16s1 = { 0 }; - final int[] int32s1 = { Integer.MIN_VALUE }; - final long[] uint32s1 = { 0 }; - final long[] int64s1 = { Long.MIN_VALUE }; - final long[] uint64s1 = { 0 }; - final float[] float32s1 = { Float.MIN_VALUE }; - final double[] float64s1 = { Double.MIN_VALUE }; - final UUID uuid1 = UUID.fromString("123e4567-e89b-12d3-a456-426655440000"); - final UUID uuid2 = UUID.fromString("789e0123-e89b-12d3-a456-426655444444"); - - statement.sendRowBinaryStream("INSERT INTO raw_binary " - + "(date, dateTime, string, int8, uInt8, int16, uInt16, int32, uInt32, int64, uInt64, float32, " - + "float64, dateArray, dateTimeArray, stringArray, int8Array, uInt8Array, int16Array, uInt16Array, " - + "int32Array, uInt32Array, int64Array, uInt64Array, float32Array, float64Array, uuid, lowCardinality, " - + "fixedString)", new ClickHouseStreamCallback() { - @Override - public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { - - stream.writeDate(date1); - stream.writeDateTime(date1); - stream.writeString("string\n1"); - stream.writeInt8(Byte.MIN_VALUE); - stream.writeUInt8(0); - stream.writeInt16(Short.MIN_VALUE); - stream.writeUInt16(0); - stream.writeInt32(Integer.MIN_VALUE); - stream.writeUInt32(0); - stream.writeInt64(Long.MIN_VALUE); - stream.writeUInt64(0); - stream.writeFloat32((float) 123.456); - stream.writeFloat64(42.21); - stream.writeDateArray(dates1); - stream.writeDateTimeArray(dateTimes1); - stream.writeStringArray(strings1); - stream.writeInt8Array(int8s1); - stream.writeUInt8Array(uint8s1); - stream.writeInt16Array(int16s1); - stream.writeUInt16Array(uint16s1); - stream.writeInt32Array(int32s1); - stream.writeUInt32Array(uint32s1); - stream.writeInt64Array(int64s1); - stream.writeUInt64Array(uint64s1); - stream.writeFloat32Array(float32s1); - stream.writeFloat64Array(float64s1); - stream.writeUUID(uuid1); - stream.writeString("lowCardinality\n1"); - stream.writeFixedString("fixedString1\0\0\0"); - - stream.writeDate(date2); - stream.writeDateTime(date2); - stream.writeString("a\tbdasd''a"); - stream.writeInt8(Byte.MAX_VALUE); - stream.writeUInt8(255); - stream.writeInt16(Short.MAX_VALUE); - stream.writeUInt16(42000); - stream.writeInt32(Integer.MAX_VALUE); - stream.writeUInt32(Integer.MAX_VALUE + 100L); - stream.writeInt64(Long.MAX_VALUE); - stream.writeUInt64(new BigInteger(Long.toUnsignedString(-1L))); - stream.writeFloat32((float) 21.21); - stream.writeFloat64(77.77); - stream.writeDateArray(new Date[] { date2 }); - stream.writeDateTimeArray(new Date[] { date2 }); - stream.writeStringArray(new String[] {}); - stream.writeInt8Array(new byte[] {}); - stream.writeUInt8Array(new int[] {}); - stream.writeInt16Array(new short[] {}); - stream.writeUInt16Array(new int[] {}); - stream.writeInt32Array(new int[] {}); - stream.writeUInt32Array(new long[] {}); - stream.writeInt64Array(new long[] {}); - stream.writeUInt64Array(new long[] {}); - stream.writeFloat32Array(new float[] {}); - stream.writeFloat64Array(new double[] {}); - stream.writeUUID(uuid2); - stream.writeString("lowCardinality\n2"); - stream.writeFixedString("fixedString2", 15); - } - }); - - if (!rowBinaryResult) { - ResultSet rs = connection.createStatement().executeQuery("SELECT * FROM raw_binary ORDER BY date"); - - Assert.assertTrue(rs.next()); - assertEquals(rs.getString("date"), - Instant.ofEpochMilli(timestamp).atZone(connection.getTimeZone().toZoneId()) - .withZoneSameInstant(ZoneId.systemDefault()).toLocalDate().toString()); - assertEquals(rs.getTimestamp("dateTime").getTime(), date1.getTime()); - assertEquals(rs.getString("string"), "string\n1"); - assertEquals(rs.getInt("int8"), Byte.MIN_VALUE); - assertEquals(rs.getInt("uInt8"), 0); - assertEquals(rs.getInt("int16"), Short.MIN_VALUE); - assertEquals(rs.getInt("uInt16"), 0); - assertEquals(rs.getInt("int32"), Integer.MIN_VALUE); - assertEquals(rs.getInt("uInt32"), 0); - assertEquals(rs.getLong("int64"), Long.MIN_VALUE); - assertEquals(rs.getLong("uInt64"), 0); - assertEquals(rs.getDouble("float32"), 123.456); - assertEquals(rs.getDouble("float64"), 42.21); - assertEquals(rs.getObject("uuid").toString(), "123e4567-e89b-12d3-a456-426655440000"); - assertEquals(rs.getString("lowCardinality"), "lowCardinality\n1"); - assertEquals(rs.getString("fixedString"), "fixedString1\0\0\0"); - - Date[] expectedDates1 = new Date[dates1.length]; - for (int i = 0; i < dates1.length; i++) { - // expected is Date at start of the day in local timezone - expectedDates1[i] = withTimeAtStartOfDay(dates1[i]); - } - - assertEquals(rs.getArray("dateArray").getArray(), expectedDates1); - assertEquals(rs.getArray("dateTimeArray").getArray(), dateTimes1); - - assertEquals(rs.getArray("stringArray").getArray(), strings1); - - assertArrayEquals((int[]) rs.getArray("int8Array").getArray(), int8s1); - assertEquals(rs.getArray("uInt8Array").getArray(), uint8s1); - - assertArrayEquals((int[]) rs.getArray("int16Array").getArray(), int16s1); - assertEquals(rs.getArray("uInt16Array").getArray(), uint16s1); - - assertEquals(rs.getArray("int32Array").getArray(), int32s1); - assertEquals(rs.getArray("uInt32Array").getArray(), uint32s1); - - assertEquals(rs.getArray("int64Array").getArray(), int64s1); - assertArrayEquals((BigInteger[]) rs.getArray("uInt64Array").getArray(), uint64s1); - - assertEquals(rs.getArray("float32Array").getArray(), float32s1); - assertEquals(rs.getArray("float64Array").getArray(), float64s1); - - Assert.assertTrue(rs.next()); - assertEquals(rs.getString("date"), "2017-05-09"); - assertEquals(rs.getTimestamp("dateTime").getTime(), date2.getTime()); - assertEquals(rs.getString("string"), "a\tbdasd''a"); - assertEquals(rs.getInt("int8"), Byte.MAX_VALUE); - assertEquals(rs.getInt("uInt8"), 255); - assertEquals(rs.getInt("int16"), Short.MAX_VALUE); - assertEquals(rs.getInt("uInt16"), 42000); - assertEquals(rs.getInt("int32"), Integer.MAX_VALUE); - assertEquals(rs.getLong("uInt32"), 2147483747L); - assertEquals(rs.getLong("int64"), Long.MAX_VALUE); - assertEquals(rs.getString("uInt64"), "18446744073709551615"); - assertEquals(rs.getDouble("float32"), 21.21); - assertEquals(rs.getDouble("float64"), 77.77); - assertEquals(rs.getString("uuid"), "789e0123-e89b-12d3-a456-426655444444"); - assertEquals(rs.getString("lowCardinality"), "lowCardinality\n2"); - assertEquals(rs.getString("fixedString"), "fixedString2\0\0\0"); - - Assert.assertFalse(rs.next()); - } else { - ClickHouseRowBinaryInputStream is = connection.createStatement() - .executeQueryClickhouseRowBinaryStream("SELECT * FROM raw_binary ORDER BY date"); - - assertEquals(is.readDate(), withTimeAtStartOfDay(date1)); - assertEquals(is.readDateTime(), new Timestamp(timestamp)); - assertEquals(is.readString(), "string\n1"); - assertEquals(is.readInt8(), Byte.MIN_VALUE); - assertEquals(is.readUInt8(), (short) 0); - assertEquals(is.readInt16(), Short.MIN_VALUE); - assertEquals(is.readUInt16(), 0); - assertEquals(is.readInt32(), Integer.MIN_VALUE); - assertEquals(is.readUInt32(), 0); - assertEquals(is.readInt64(), Long.MIN_VALUE); - assertEquals(is.readUInt64(), BigInteger.valueOf(0)); - assertEquals(is.readFloat32(), (float) 123.456); - assertEquals(is.readFloat64(), 42.21); - - Date[] expectedDates1 = new Date[dates1.length]; - for (int i = 0; i < dates1.length; i++) { - // expected is Date at start of the day in local timezone - expectedDates1[i] = withTimeAtStartOfDay(dates1[i]); - } - - assertEquals(is.readDateArray(), expectedDates1); - assertEquals(is.readDateTimeArray(), dateTimes1); - - assertEquals(is.readStringArray(), strings1); - - assertEquals(is.readInt8Array(), int8s1); - assertArrayEquals(is.readUInt8Array(), uint8s1); - - assertEquals(is.readInt16Array(), int16s1); - assertEquals(is.readUInt16Array(), uint16s1); - - assertEquals(is.readInt32Array(), int32s1); - assertEquals(is.readUInt32Array(), uint32s1); - - assertEquals(is.readInt64Array(), int64s1); - assertArrayEquals(is.readUInt64Array(), uint64s1); - - assertEquals(is.readFloat32Array(), float32s1); - assertEquals(is.readFloat64Array(), float64s1); - - assertEquals(is.readUUID(), uuid1); - assertEquals(is.readString(), "lowCardinality\n1"); - assertEquals(is.readFixedString(15), "fixedString1\0\0\0"); - - assertEquals(is.readDate(), withTimeAtStartOfDay(date2)); - assertEquals(is.readDateTime().getTime(), date2.getTime()); - assertEquals(is.readString(), "a\tbdasd''a"); - assertEquals(is.readInt8(), Byte.MAX_VALUE); - assertEquals(is.readUInt8(), (short) 255); - assertEquals(is.readInt16(), Short.MAX_VALUE); - assertEquals(is.readUInt16(), 42000); - assertEquals(is.readInt32(), Integer.MAX_VALUE); - assertEquals(is.readUInt32(), (Integer.MAX_VALUE) + 100L); - assertEquals(is.readInt64(), Long.MAX_VALUE); - assertEquals(is.readUInt64(), new BigInteger(Long.toUnsignedString(-1L))); - assertEquals(is.readFloat32(), (float) 21.21); - assertEquals(is.readFloat64(), 77.77); - - // skip arrays - is.readDateArray(); - is.readDateTimeArray(); - is.readStringArray(); - is.readInt8Array(); - is.readUInt8Array(); - is.readInt16Array(); - is.readUInt16Array(); - is.readInt32Array(); - is.readUInt32Array(); - is.readInt64Array(); - is.readUInt64Array(); - is.readFloat32Array(); - is.readFloat64Array(); - - assertEquals(is.readUUID(), uuid2); - assertEquals(is.readString(), "lowCardinality\n2"); - assertEquals(is.readFixedString(15), "fixedString2\0\0\0"); - - // check EOF - try { - is.readInt8(); - Assert.fail(); - } catch (EOFException e) { - // expected - } - } - } - - @Test(groups = "integration") - public void testTimeZone() throws Exception { - final ClickHouseStatement statement = connection.createStatement(); - connection.createStatement().execute("DROP TABLE IF EXISTS binary_tz"); - connection.createStatement().execute( - "CREATE TABLE binary_tz (date Date, dateTime DateTime) ENGINE = MergeTree order by date"); - - // - final Date date1 = new Date(1497474018000L); - - statement.sendRowBinaryStream("INSERT INTO binary_tz (date, dateTime)", new ClickHouseStreamCallback() { - @Override - public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { - stream.writeDate(date1); - stream.writeDateTime(date1); - } - }); - - ResultSet rs = connection.createStatement().executeQuery("SELECT date, dateTime from binary_tz"); - - Assert.assertTrue(rs.next()); - - /* - * The following, commented-out assertion would be nice, but against the - * definition of the Time class: - * - * "The date components should be set to the "zero epoch" value of January 1, - * 1970 and should not be accessed." - * - * assertEquals(rs.getTime("dateTime"), new Time(date1.getTime())); - * - * The original timestamp is 2017-06-14 21:00:18 (UTC), so we expect 21:00:18 as - * the local time, regardless of a different DST offset - */ - assertEquals(Instant.ofEpochMilli(rs.getTime("dateTime").getTime()).atZone(ZoneId.of("UTC")).toLocalTime(), - LocalTime.of(21, 0, 18)); - - Date expectedDate = withTimeAtStartOfDay(date1); // expected start of the day in local timezone - assertEquals(rs.getDate("date"), expectedDate); - - assertEquals(rs.getTimestamp("dateTime"), new Timestamp(date1.getTime())); - } - - private static Date withTimeAtStartOfDay(Date date) { - Calendar cal = Calendar.getInstance(); - cal.setTime(date); - cal.set(Calendar.HOUR_OF_DAY, 0); - cal.set(Calendar.MINUTE, 0); - cal.set(Calendar.SECOND, 0); - cal.set(Calendar.MILLISECOND, 0); - return new Date(cal.getTimeInMillis()); - } - - private static void assertArrayEquals(int[] actual, byte[] expected) { - int[] expectedInts = new int[expected.length]; - for (int i = 0; i < expected.length; i++) { - expectedInts[i] = expected[i]; - } - assertEquals(actual, expectedInts); - } - - private static void assertArrayEquals(int[] actual, short[] expected) { - int[] expectedInts = new int[expected.length]; - for (int i = 0; i < expected.length; i++) { - expectedInts[i] = expected[i]; - } - - assertEquals(actual, expectedInts); - } - - private static void assertArrayEquals(short[] actual, int[] expected) { - int[] actualInts = new int[actual.length]; - for (int i = 0; i < actual.length; i++) { - actualInts[i] = actual[i]; - } - - assertEquals(actualInts, expected); - } - - private static void assertArrayEquals(long[] actual, int[] expected) { - long[] expectedLongs = new long[expected.length]; - for (int i = 0; i < expected.length; i++) { - expectedLongs[i] = expected[i]; - } - - assertEquals(actual, expectedLongs); - - } - - private static void assertArrayEquals(BigInteger[] actual, long[] expected) { - BigInteger[] expectedBigs = new BigInteger[expected.length]; - for (int i = 0; i < expected.length; i++) { - expectedBigs[i] = BigInteger.valueOf(expected[i]); - } - - assertEquals(actual, expectedBigs); - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/StreamSQLTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/StreamSQLTest.java deleted file mode 100644 index 95906c641..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/StreamSQLTest.java +++ /dev/null @@ -1,421 +0,0 @@ -package ru.yandex.clickhouse.integration; - - -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.math.BigDecimal; -import java.nio.charset.Charset; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; -import java.util.zip.GZIPOutputStream; - -import com.clickhouse.client.ClickHouseVersion; - -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import ru.yandex.clickhouse.ClickHouseConnection; -import ru.yandex.clickhouse.JdbcIntegrationTest; -import ru.yandex.clickhouse.domain.ClickHouseCompression; -import ru.yandex.clickhouse.domain.ClickHouseFormat; - -public class StreamSQLTest extends JdbcIntegrationTest { - private static final DateTimeFormatter DATE_TIME_FORMATTER_TZ = - DateTimeFormatter.ofPattern("yyyy-MM-dd['T'][ ]HH:mm:ss[.SSS][XXX]"); - - private ClickHouseConnection connection; - - private Timestamp utcToServerTimezone(String datetime) { - return Timestamp.from(LocalDateTime.parse(datetime, DATE_TIME_FORMATTER_TZ) - .atZone(ZoneId.of("UTC")).withZoneSameInstant(connection.getTimeZone().toZoneId()).toInstant()); - } - - @BeforeClass(groups = "integration") - public void setUp() throws Exception { - connection = newConnection(); - } - - @AfterClass(groups = "integration") - public void tearDown() throws Exception { - closeConnection(connection); - } - - @Test(groups = "integration") - public void simpleCSVInsert() throws SQLException { - connection.createStatement().execute("DROP TABLE IF EXISTS csv_stream_sql"); - connection.createStatement().execute( - "CREATE TABLE csv_stream_sql (value Int32, string_value String) ENGINE = Log()" - ); - - String string = "5,6\n1,6"; - InputStream inputStream = new ByteArrayInputStream(string.getBytes(Charset.forName("UTF-8"))); - - connection.createStatement() - .write() - .sql("insert into csv_stream_sql format CSV") - .data(inputStream) - .send(); - - ResultSet rs = connection.createStatement().executeQuery( - "SELECT count() AS cnt, sum(value) AS sum, uniqExact(string_value) uniq FROM csv_stream_sql"); - Assert.assertTrue(rs.next()); - Assert.assertEquals(rs.getInt("cnt"), 2); - Assert.assertEquals(rs.getLong("sum"), 6); - Assert.assertEquals(rs.getLong("uniq"), 1); - } - - private InputStream getTSVStream(final int rowsCount) { - return new InputStream() { - private int si = 0; - private String s = ""; - private int i = 0; - - private boolean genNextString() { - if (i >= rowsCount) return false; - si = 0; - s = String.format("%d\txxxx%d\n", 1, i); - i++; - return true; - } - - public int read() { - if (si >= s.length()) { - if ( ! genNextString() ) { - return -1; - } - } - return s.charAt( si++ ); - } - }; - } - - @Test(groups = "integration") - public void multiRowTSVInsert() throws SQLException { - connection.createStatement().execute("DROP TABLE IF EXISTS tsv_stream_sql"); - connection.createStatement().execute( - "CREATE TABLE tsv_stream_sql (value Int32, string_value String) ENGINE = Log()" - ); - - final int rowsCount = 100000; - - connection.createStatement(). - write() - .sql("insert into tsv_stream_sql format TSV") - .data(getTSVStream(rowsCount), ClickHouseFormat.TSV) - .send(); - - ResultSet rs = connection.createStatement().executeQuery( - "SELECT count() AS cnt, sum(value) AS sum, uniqExact(string_value) uniq FROM tsv_stream_sql"); - Assert.assertTrue(rs.next()); - Assert.assertEquals(rs.getInt("cnt"), rowsCount); - Assert.assertEquals(rs.getInt("sum"), rowsCount); - Assert.assertEquals(rs.getInt("uniq"), rowsCount); - } - - private InputStream gzStream( InputStream is ) throws IOException - { - final int bufferSize = 16384; - byte[] data = new byte[bufferSize]; - ByteArrayOutputStream os = new ByteArrayOutputStream(); - GZIPOutputStream gzipOutputStream = new GZIPOutputStream(os); - BufferedInputStream es = new BufferedInputStream(is, bufferSize); - int count; - while ( ( count = es.read( data, 0, bufferSize) ) != -1 ) - gzipOutputStream.write( data, 0, count ); - es.close(); - gzipOutputStream.close(); - - return new ByteArrayInputStream( os.toByteArray() ); - } - - @Test(groups = "integration") - public void multiRowTSVInsertCompressed() throws SQLException, IOException { - connection.createStatement().execute("DROP TABLE IF EXISTS tsv_compressed_stream_sql"); - connection.createStatement().execute( - "CREATE TABLE tsv_compressed_stream_sql (value Int32, string_value String) ENGINE = Log()" - ); - - final int rowsCount = 100000; - - InputStream gz = gzStream(getTSVStream(rowsCount)); - connection.createStatement() - .write() - .sql("insert into tsv_compressed_stream_sql format TSV") - .data(gz, ClickHouseFormat.TSV, ClickHouseCompression.gzip) - .send(); - - ResultSet rs = connection.createStatement().executeQuery( - "SELECT count() AS cnt, sum(value) AS sum, uniqExact(string_value) uniq FROM tsv_compressed_stream_sql"); - Assert.assertTrue(rs.next()); - Assert.assertEquals(rs.getInt("cnt"), rowsCount); - Assert.assertEquals(rs.getInt("sum"), rowsCount); - Assert.assertEquals(rs.getInt("uniq"), rowsCount); - } - - @Test(groups = "integration") - public void multiRowTSVInsertNotCompressed() throws SQLException, IOException { - connection.createStatement().execute("DROP TABLE IF EXISTS tsv_not_compressed_stream_sql"); - connection.createStatement().execute( - "CREATE TABLE tsv_not_compressed_stream_sql (value Int32, string_value String) ENGINE = Log()" - ); - - final int rowsCount = 100000; - - InputStream in = getTSVStream(rowsCount); - connection.createStatement() - .write() - .sql("insert into tsv_not_compressed_stream_sql format TSV") - .data(in, ClickHouseFormat.TSV, ClickHouseCompression.none) - .send(); - - ResultSet rs = connection.createStatement().executeQuery( - "SELECT count() AS cnt, sum(value) AS sum, uniqExact(string_value) uniq FROM tsv_not_compressed_stream_sql"); - Assert.assertTrue(rs.next()); - Assert.assertEquals(rs.getInt("cnt"), rowsCount); - Assert.assertEquals(rs.getInt("sum"), rowsCount); - Assert.assertEquals(rs.getInt("uniq"), rowsCount); - } - - - @Test(groups = "integration") - public void JSONEachRowInsert() throws SQLException { - connection.createStatement().execute("DROP TABLE IF EXISTS json_stream_sql"); - connection.createStatement().execute( - "CREATE TABLE json_stream_sql (value Int32, string_value String) ENGINE = Log()" - ); - - String string = "{\"value\":5,\"string_value\":\"6\"}\n{\"value\":1,\"string_value\":\"6\"}"; - InputStream inputStream = new ByteArrayInputStream(string.getBytes(Charset.forName("UTF-8"))); - - connection.createStatement(). - write() - .sql("insert into json_stream_sql") - .data(inputStream, ClickHouseFormat.JSONEachRow) - .data(inputStream) - .send(); - - ResultSet rs = connection.createStatement().executeQuery( - "SELECT count() AS cnt, sum(value) AS sum, uniqExact(string_value) uniq FROM json_stream_sql"); - Assert.assertTrue(rs.next()); - Assert.assertEquals(rs.getInt("cnt"), 2); - Assert.assertEquals(rs.getLong("sum"), 6); - Assert.assertEquals(rs.getLong("uniq"), 1); - } - - @Test(groups = "integration") - public void JSONEachRowCompressedInsert() throws SQLException, IOException { - connection.createStatement().execute("DROP TABLE IF EXISTS json_comressed_stream_sql"); - connection.createStatement().execute( - "CREATE TABLE json_comressed_stream_sql (value Int32, string_value String) ENGINE = Log()" - ); - - String string = "{\"value\":5,\"string_value\":\"6\"}\n{\"value\":1,\"string_value\":\"6\"}"; - InputStream inputStream = new ByteArrayInputStream(string.getBytes(Charset.forName("UTF-8"))); - - connection.createStatement(). - write() - .sql("insert into json_comressed_stream_sql") - .data(inputStream, ClickHouseFormat.JSONEachRow) - .data(gzStream(inputStream)) - .dataCompression(ClickHouseCompression.gzip) - .send(); - - ResultSet rs = connection.createStatement().executeQuery( - "SELECT count() AS cnt, sum(value) AS sum, uniqExact(string_value) uniq FROM json_comressed_stream_sql"); - Assert.assertTrue(rs.next()); - Assert.assertEquals(rs.getInt("cnt"), 2); - Assert.assertEquals(rs.getLong("sum"), 6); - Assert.assertEquals(rs.getLong("uniq"), 1); - } - - @Test(groups = "integration") - public void CSVInsertCompressedIntoTable() throws SQLException, IOException { - connection.createStatement().execute("DROP TABLE IF EXISTS csv_stream_compressed"); - connection.createStatement().execute( - "CREATE TABLE csv_stream_compressed (value Int32, string_value String) ENGINE = Log()" - ); - - String string = "5,6\n1,6"; - InputStream inputStream = new ByteArrayInputStream(string.getBytes(Charset.forName("UTF-8"))); - - connection.createStatement() - .write() - .table(dbName + ".csv_stream_compressed") - .format(ClickHouseFormat.CSV) - .dataCompression(ClickHouseCompression.gzip) - .data(gzStream(inputStream)) - .send(); - - ResultSet rs = connection.createStatement().executeQuery( - "SELECT count() AS cnt, sum(value) AS sum, uniqExact(string_value) uniq FROM csv_stream_compressed"); - Assert.assertTrue(rs.next()); - Assert.assertEquals(rs.getInt("cnt"), 2); - Assert.assertEquals(rs.getLong("sum"), 6); - Assert.assertEquals(rs.getLong("uniq"), 1); - } - - @Test(groups = "integration") - public void ORCInsertCompressedIntoTable() throws SQLException { - // clickhouse-client -q "select number int, toString(number) str, 1/number flt, toDecimal64( 1/(number+1) , 9) dcml, - // toDateTime('2020-01-01 00:00:00') + number time from numbers(100) format ORC"|gzip > test_sample.orc.gz - - if (ClickHouseVersion.check(connection.getServerVersion(), "(,20.8)")) { - return; - } - - connection.createStatement().execute("DROP TABLE IF EXISTS orc_stream_compressed"); - connection.createStatement().execute( - "CREATE TABLE orc_stream_compressed (int Int64, str String, flt Float64, " + - "dcml Decimal64(9), time DateTime) ENGINE = Log();" - ); - - InputStream inputStream = StreamSQLTest.class.getResourceAsStream("/data_samples/test_sample.orc.gz"); - - connection.createStatement(). - write() - .table(dbName + ".orc_stream_compressed") - .format(ClickHouseFormat.ORC) - .dataCompression(ClickHouseCompression.gzip) - .data(inputStream) - .send(); - - ResultSet rs = connection.createStatement().executeQuery( - "SELECT count() AS cnt, " + - "sum(int) sum_int, " + - "round(sum(flt),2) AS sum_flt, " + - "uniqExact(str) uniq_str, " + - "max(dcml) max_dcml, " + - "min(time) min_time, " + - "max(time) max_time " + - "FROM orc_stream_compressed"); - Assert.assertTrue(rs.next()); - Assert.assertEquals(rs.getInt("cnt"), 100); - Assert.assertEquals(rs.getLong("sum_int"), 4950); - Assert.assertEquals(rs.getFloat("sum_flt"), Float.POSITIVE_INFINITY); - Assert.assertEquals(rs.getLong("uniq_str"), 100); - Assert.assertEquals(rs.getBigDecimal("max_dcml").setScale(9), new BigDecimal("1.000000000")); - Assert.assertEquals(rs.getTimestamp("min_time"), utcToServerTimezone("2020-01-01 00:00:00")); - Assert.assertEquals(rs.getTimestamp("max_time"), utcToServerTimezone("2020-01-01 00:01:39")); - } - - @Test(groups = "integration") - public void ORCInsertCompressedIntoTable1() throws SQLException { - // clickhouse-client -q "select number int, toString(number) str, 1/number flt, toDecimal64( 1/(number+1) , 9) dcml, - // toDateTime('2020-01-01 00:00:00') + number time from numbers(100) format ORC"|gzip > test_sample.orc.gz - - if (ClickHouseVersion.check(connection.getServerVersion(), "(,20.8)")) { - return; - } - - connection.createStatement().execute("DROP TABLE IF EXISTS orc1_stream_compressed"); - connection.createStatement().execute( - "CREATE TABLE orc1_stream_compressed (int Int64, str String, flt Float64, " + - "dcml Decimal64(9), time DateTime) ENGINE = Log();" - ); - - InputStream inputStream = StreamSQLTest.class.getResourceAsStream("/data_samples/test_sample.orc.gz"); - - connection.createStatement(). - write() - .sql("insert into orc1_stream_compressed format ORC") - .dataCompression(ClickHouseCompression.gzip) - .data(inputStream) - .send(); - - ResultSet rs = connection.createStatement().executeQuery( - "select * from orc1_stream_compressed where int=42"); - Assert.assertTrue(rs.next()); - Assert.assertEquals(rs.getInt("int"), 42); - Assert.assertEquals(rs.getString("str"), "42"); - Assert.assertTrue( Math.abs(rs.getFloat("flt") - 0.023809524) < 0.0001); - Assert.assertTrue( Math.abs(rs.getFloat("dcml") - 0.023255813) < 0.0001); - Assert.assertEquals(rs.getTimestamp("time"), utcToServerTimezone("2020-01-01 00:00:42")); - } - - @Test(groups = "integration") - public void ParquetInsertCompressedIntoTable() throws SQLException { - // clickhouse-client -q "select number int, toString(number) str, 1/number flt, toDecimal64( 1/(number+1) , 9) dcml, - // toDateTime('2020-01-01 00:00:00') + number time from numbers(100) format Parquet"|gzip > test_sample.parquet.gz - - if (ClickHouseVersion.check(connection.getServerVersion(), "(,20.8)")) { - return; - } - - connection.createStatement().execute("DROP TABLE IF EXISTS parquet_stream_compressed"); - connection.createStatement().execute( - "CREATE TABLE parquet_stream_compressed (int Int64, str String, flt Float64, " + - "dcml Decimal64(9), time DateTime) ENGINE = Log();" - ); - - InputStream inputStream = StreamSQLTest.class.getResourceAsStream("/data_samples/test_sample.parquet.gz"); - - connection.createStatement(). - write() - .table(dbName + ".parquet_stream_compressed") - .format(ClickHouseFormat.Parquet) - .dataCompression(ClickHouseCompression.gzip) - .data(inputStream) - .send(); - - ResultSet rs = connection.createStatement().executeQuery( - "SELECT count() AS cnt, " + - "sum(int) sum_int, " + - "round(sum(flt),2) AS sum_flt, " + - "uniqExact(str) uniq_str, " + - "max(dcml) max_dcml, " + - "min(time) min_time, " + - "max(time) max_time " + - "FROM parquet_stream_compressed"); - Assert.assertTrue(rs.next()); - Assert.assertEquals(rs.getInt("cnt"), 100); - Assert.assertEquals(rs.getLong("sum_int"), 4950); - Assert.assertEquals(rs.getFloat("sum_flt"), Float.POSITIVE_INFINITY); - Assert.assertEquals(rs.getLong("uniq_str"), 100); - Assert.assertEquals(rs.getBigDecimal("max_dcml").setScale(9), new BigDecimal("1.000000000")); - Assert.assertEquals(rs.getTimestamp("min_time"), utcToServerTimezone("2020-01-01 00:00:00")); - Assert.assertEquals(rs.getTimestamp("max_time"), utcToServerTimezone("2020-01-01 00:01:39")); - } - - @Test(groups = "integration") - public void ParquetInsertCompressedIntoTable1() throws SQLException { - // clickhouse-client -q "select number int, toString(number) str, 1/number flt, toDecimal64( 1/(number+1) , 9) dcml, - // toDateTime('2020-01-01 00:00:00') + number time from numbers(100) format Parquet"|gzip > test_sample.parquet.gz - - if (ClickHouseVersion.check(connection.getServerVersion(), "(,20.8)")) { - return; - } - - connection.createStatement().execute("DROP TABLE IF EXISTS parquet1_stream_compressed"); - connection.createStatement().execute( - "CREATE TABLE parquet1_stream_compressed (int Int64, str String, flt Float64, " + - "dcml Decimal64(9), time DateTime) ENGINE = Log();" - ); - - InputStream inputStream = StreamSQLTest.class.getResourceAsStream("/data_samples/test_sample.parquet.gz"); - - connection.createStatement(). - write() - .sql("insert into parquet1_stream_compressed format Parquet") - .dataCompression(ClickHouseCompression.gzip) - .data(inputStream) - .send(); - - ResultSet rs = connection.createStatement().executeQuery( - "select * from parquet1_stream_compressed where int=42"); - Assert.assertTrue(rs.next()); - Assert.assertEquals(rs.getInt("int"), 42); - Assert.assertEquals(rs.getString("str"), "42"); - Assert.assertTrue( Math.abs(rs.getFloat("flt") - 0.023809524) < 0.0001); - Assert.assertTrue( Math.abs(rs.getFloat("dcml") - 0.023255813) < 0.0001); - Assert.assertEquals(rs.getTimestamp("time"), utcToServerTimezone("2020-01-01 00:00:42")); - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/TSVStreamTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/TSVStreamTest.java deleted file mode 100644 index 54cea5920..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/TSVStreamTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package ru.yandex.clickhouse.integration; - -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import ru.yandex.clickhouse.ClickHouseConnection; -import ru.yandex.clickhouse.JdbcIntegrationTest; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.nio.charset.Charset; -import java.sql.ResultSet; -import java.sql.SQLException; - -public class TSVStreamTest extends JdbcIntegrationTest { - private ClickHouseConnection connection; - - @BeforeClass(groups = "integration") - public void setUp() throws Exception { - connection = newConnection(); - } - - @AfterClass(groups = "integration") - public void tearDown() throws Exception { - closeConnection(connection); - } - - @Test(groups = "integration") - public void simpleInsert() throws SQLException { - connection.createStatement().execute("DROP TABLE IF EXISTS tsv_stream"); - connection.createStatement().execute( - "CREATE TABLE tsv_stream (value Int32, string_value String) ENGINE = Log()" - ); - - String string = "5\t6\n1\t6"; - InputStream inputStream = new ByteArrayInputStream(string.getBytes(Charset.forName("UTF-8"))); - - connection.createStatement().sendStream(inputStream, dbName + ".tsv_stream"); - - ResultSet rs = connection.createStatement().executeQuery( - "SELECT count() AS cnt, sum(value) AS sum, uniqExact(string_value) uniq FROM tsv_stream"); - Assert.assertTrue(rs.next()); - Assert.assertEquals(rs.getInt("cnt"), 2); - Assert.assertEquals(rs.getLong("sum"), 6); - Assert.assertEquals(rs.getLong("uniq"), 1); - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/TimeZoneTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/TimeZoneTest.java deleted file mode 100644 index b002d6768..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/TimeZoneTest.java +++ /dev/null @@ -1,406 +0,0 @@ -package ru.yandex.clickhouse.integration; - -import java.io.IOException; -import java.sql.Connection; -import java.sql.Date; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.sql.Timestamp; -import java.time.Instant; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.temporal.ChronoUnit; -import java.util.Calendar; -import java.util.TimeZone; -import java.util.concurrent.TimeUnit; - -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.ClickHouseConnection; -import ru.yandex.clickhouse.JdbcIntegrationTest; -import ru.yandex.clickhouse.settings.ClickHouseProperties; -import ru.yandex.clickhouse.util.ClickHouseRowBinaryStream; -import ru.yandex.clickhouse.util.ClickHouseStreamCallback; - -import static org.testng.Assert.fail; - -public class TimeZoneTest extends JdbcIntegrationTest { - - private ClickHouseConnection connectionServerTz; - private ClickHouseConnection connectionManualTz; - - private long currentTime = 1000 * (System.currentTimeMillis() / 1000); - - @BeforeClass(groups = "integration") - public void setUp() throws Exception { - connectionServerTz = newConnection(); - - TimeZone serverTimeZone = connectionServerTz.getTimeZone(); - ClickHouseProperties properties = new ClickHouseProperties(); - properties.setUseServerTimeZone(false); - int serverTimeZoneOffsetHours = (int) TimeUnit.MILLISECONDS.toHours(serverTimeZone.getOffset(currentTime)); - int manualTimeZoneOffsetHours = serverTimeZoneOffsetHours - 1; - properties.setUseTimeZone("GMT" + (manualTimeZoneOffsetHours > 0 ? "+" : "") + manualTimeZoneOffsetHours + ":00"); - connectionManualTz = newConnection(properties); - } - - @AfterClass(groups = "integration") - public void tearDown() throws Exception { - closeConnection(connectionServerTz); - closeConnection(connectionManualTz); - } - - @Test(groups = "integration") - public void timeZoneTestTimestamp() throws Exception { - try (Statement s = connectionServerTz.createStatement()) { - s.execute("DROP TABLE IF EXISTS time_zone_test"); - s.execute( - "CREATE TABLE IF NOT EXISTS time_zone_test (i Int32, d DateTime) ENGINE = TinyLog" - ); - } - - try (PreparedStatement statement = - connectionServerTz.prepareStatement("INSERT INTO time_zone_test (i, d) VALUES (?, ?)")) { - statement.setInt(1, 1); - statement.setTimestamp(2, new Timestamp(currentTime)); - statement.execute(); - } - - try (PreparedStatement statementUtc = - connectionManualTz.prepareStatement("INSERT INTO time_zone_test (i, d) VALUES (?, ?)")) { - statementUtc.setInt(1, 2); - statementUtc.setTimestamp(2, new Timestamp(currentTime)); - statementUtc.execute(); - } - - String query = "SELECT i, d as cnt from time_zone_test order by i"; - try (Statement s = connectionServerTz.createStatement(); ResultSet rs = s.executeQuery(query)) { - // server write, server read - rs.next(); - Assert.assertEquals(rs.getTimestamp(2).getTime(), currentTime); - - // manual write, server read - rs.next(); - Assert.assertEquals(rs.getTimestamp(2).getTime(), currentTime - TimeUnit.HOURS.toMillis(1)); - } - - try (Statement s = connectionManualTz.createStatement(); ResultSet rsMan = s.executeQuery(query)) { - // server write, manual read - rsMan.next(); - Assert.assertEquals(rsMan.getTimestamp(2).getTime(), currentTime); - // manual write, manual read - rsMan.next(); - Assert.assertEquals(rsMan.getTimestamp(2).getTime(), currentTime - TimeUnit.HOURS.toMillis(1)); - } - } - - /* - * These are the scenarios we need to test - * - * USE_SERVER_TIME_ZONE USE_TIME_ZONE USE_SERVER_TIME_ZONE_FOR_DATES effective TZ Date parsing - * -------------------- ------------- ------------------------------ ------------------------- - * false null false (forbidden) - * false TZ_DIFF false TZ_JVM - * false null true (forbidden) - * false TZ_DIFF true TZ_DIFF - * true null false TZ_JVM - * true TZ_DIFF false (forbidden) - * true null true TZ_SERVER - * true TZ_DIFF true (forbidden) - */ - - @Test(groups = "integration") - public void testTimeZoneParseSQLDate1() throws Exception { - try { - createConnection(false, null, false); - fail(); - } catch (IllegalArgumentException iae) { - // expected - } - } - - @Test(groups = "integration") - public void testTimeZoneParseSQLDate2() throws Exception { - int suffix = 2; - Long offset = Long.valueOf( - TimeUnit.MILLISECONDS.toHours( - connectionServerTz.getServerTimeZone().getOffset(currentTime))); - resetDateTestTable(suffix); - try (ClickHouseConnection conn = createConnection(false, offset, false)) { - insertDateTestData(suffix, connectionServerTz, 1); - insertDateTestData(suffix, conn, 1); - - assertDateResult(suffix, conn, Instant.ofEpochMilli(currentTime) - .atOffset(ZoneOffset.ofHours(offset.intValue())) - .truncatedTo(ChronoUnit.DAYS) - .toEpochSecond()); - } - } - - @Test(groups = "integration") - public void testTimeZoneParseSQLDate3() throws Exception { - try { - createConnection(false, null, false); - fail(); - } catch (IllegalArgumentException iae) { - // expected - } - } - - @Test(groups = "integration") - public void testTimeZoneParseSQLDate4() throws Exception { - int suffix = 4; - Long offset = Long.valueOf( - TimeUnit.MILLISECONDS.toHours( - connectionServerTz.getTimeZone().getOffset(currentTime))); - resetDateTestTable(suffix); - try (ClickHouseConnection conn = createConnection(false, offset, true)) { - insertDateTestData(suffix, connectionServerTz, 1); - insertDateTestData(suffix, conn, 1); - assertDateResult( - suffix, conn, - Instant.ofEpochMilli(currentTime) - .atOffset(ZoneOffset.ofHours(offset.intValue())) - .truncatedTo(ChronoUnit.DAYS) - .toEpochSecond()); - } - } - - @Test(groups = "integration") - public void testTimeZoneParseSQLDate5() throws Exception { - int suffix = 5; - resetDateTestTable(suffix); - try (ClickHouseConnection conn = createConnection(true, null, false)) { - insertDateTestData(suffix, connectionServerTz, 1); - insertDateTestData(suffix, conn, 1); - - assertDateResult( - suffix, conn, - Instant.ofEpochMilli(currentTime) - .atZone(ZoneId.systemDefault()) - .truncatedTo(ChronoUnit.DAYS) - .toEpochSecond()); - } - } - - @Test(groups = "integration") - public void testTimeZoneParseSQLDate6() throws Exception { - try { - createConnection(true, Long.valueOf(1L), false); - fail(); - } catch (IllegalArgumentException iae) { - // expected - } - } - - @Test(groups = "integration") - public void testTimeZoneParseSQLDate7() throws Exception { - int suffix = 7; - resetDateTestTable(suffix); - try (ClickHouseConnection conn = createConnection(true, null, true)) { - insertDateTestData(suffix, connectionServerTz, 1); - insertDateTestData(suffix, conn, 1); - assertDateResult( - suffix, conn, - Instant.ofEpochMilli(currentTime) - .atZone(ZoneId.systemDefault()) - .truncatedTo(ChronoUnit.DAYS) - .toEpochSecond()); - } - } - - @Test(groups = "integration") - public void testTimeZoneParseSQLDate8() throws Exception { - try { - createConnection(true, Long.valueOf(1L), true); - fail(); - } catch (IllegalArgumentException iae) { - // expected - } - } - - @Test(groups = "integration") - public void dateTest() throws SQLException { - ResultSet rsMan = connectionManualTz.createStatement().executeQuery("select toDate('2017-07-05')"); - ResultSet rsSrv = connectionServerTz.createStatement().executeQuery("select toDate('2017-07-05')"); - rsMan.next(); - rsSrv.next(); - // check it doesn't depend on server timezone - Assert.assertEquals(rsMan.getDate(1), rsSrv.getDate(1)); - - // check it is start of correct day in client timezone - Assert.assertEquals(rsMan.getDate(1), new Date(117, 6, 5)); - } - - @Test(groups = "integration") - public void dateInsertTest() throws SQLException { - connectionServerTz.createStatement().execute("DROP TABLE IF EXISTS date_insert"); - connectionServerTz.createStatement().execute( - "CREATE TABLE date_insert (" + - "i UInt8," + - "d Date" + - ") ENGINE = TinyLog" - ); - - - final Date date = new Date(currentTime); - Date localStartOfDay = withTimeAtStartOfDay(date); - - connectionServerTz.createStatement().sendRowBinaryStream( - "INSERT INTO date_insert (i, d)", - new ClickHouseStreamCallback() { - @Override - public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { - stream.writeUInt8(1); - stream.writeDate(date); - } - } - ); - - connectionManualTz.createStatement().sendRowBinaryStream( - "INSERT INTO date_insert (i, d)", - new ClickHouseStreamCallback() { - @Override - public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { - stream.writeUInt8(2); - stream.writeDate(date); - } - } - ); - - ResultSet rsMan = connectionManualTz.createStatement().executeQuery("select d from date_insert order by i"); - ResultSet rsSrv = connectionServerTz.createStatement().executeQuery("select d from date_insert order by i"); - rsMan.next(); - rsSrv.next(); - // inserted in server timezone - Assert.assertEquals(rsMan.getDate(1), localStartOfDay); - Assert.assertEquals(rsSrv.getDate(1), localStartOfDay); - - rsMan.next(); - rsSrv.next(); - // inserted in manual timezone - Assert.assertEquals(rsMan.getDate(1), localStartOfDay); - Assert.assertEquals(rsSrv.getDate(1), localStartOfDay); - } - - @Test(groups = "integration") - public void testParseColumnsWithDifferentTimeZones() throws Exception { - connectionServerTz.createStatement().execute("DROP TABLE IF EXISTS fun_with_timezones"); - connectionServerTz.createStatement().execute( - "CREATE TABLE fun_with_timezones (" + - "i UInt8," + - "dt_server DateTime," + - "dt_berlin DateTime('Europe/Berlin')," + - "dt_lax DateTime('America/Los_Angeles')" + - ") ENGINE = TinyLog" - ); - connectionServerTz.createStatement().execute( - "INSERT INTO fun_with_timezones (i, dt_server, dt_berlin, dt_lax) " + - "VALUES (42, 1557136800, 1557136800, 1557136800)"); - ResultSet rs_timestamps = connectionServerTz.createStatement().executeQuery( - "SELECT i, toUnixTimestamp(dt_server), toUnixTimestamp(dt_berlin), toUnixTimestamp(dt_lax) " + - "FROM fun_with_timezones"); - rs_timestamps.next(); - Assert.assertEquals(rs_timestamps.getLong(2), 1557136800); - Assert.assertEquals(rs_timestamps.getLong(3), 1557136800); - Assert.assertEquals(rs_timestamps.getLong(4), 1557136800); - - ResultSet rs_datetimes = connectionServerTz.createStatement().executeQuery( - "SELECT i, dt_server, dt_berlin, dt_lax " + - "FROM fun_with_timezones"); - rs_datetimes.next(); - Assert.assertEquals(rs_datetimes.getTimestamp(2).getTime(), 1557136800000L); - Assert.assertEquals(rs_datetimes.getTimestamp(3).getTime(), 1557136800000L); - Assert.assertEquals(rs_datetimes.getTimestamp(4).getTime(), 1557136800000L); - } - - @Test(groups = "integration") - public void testParseColumnsWithDifferentTimeZonesArray() throws Exception { - connectionServerTz.createStatement().execute("DROP TABLE IF EXISTS fun_with_timezones_array"); - connectionServerTz.createStatement().execute( - "CREATE TABLE fun_with_timezones_array (" + - "i UInt8," + - "dt_server Array(DateTime)," + - "dt_berlin Array(DateTime('Europe/Berlin'))," + - "dt_lax Array(DateTime('America/Los_Angeles'))" + - ") ENGINE = TinyLog" - ); - connectionServerTz.createStatement().execute( - "INSERT INTO fun_with_timezones_array (i, dt_server, dt_berlin, dt_lax) " + - "VALUES (42, [1557136800], [1557136800], [1557136800])"); - ResultSet rs_timestamps = connectionServerTz.createStatement().executeQuery( - "SELECT i, array(toUnixTimestamp(dt_server[1])), array(toUnixTimestamp(dt_berlin[1])), array(toUnixTimestamp(dt_lax[1])) " + - "FROM fun_with_timezones_array"); - rs_timestamps.next(); - Assert.assertEquals(((long[]) rs_timestamps.getArray(2).getArray())[0], 1557136800); - Assert.assertEquals(((long[]) rs_timestamps.getArray(3).getArray())[0], 1557136800); - Assert.assertEquals(((long[]) rs_timestamps.getArray(4).getArray())[0], 1557136800); - - ResultSet rs_datetimes = connectionServerTz.createStatement().executeQuery( - "SELECT i, dt_server, dt_berlin, dt_lax " + - "FROM fun_with_timezones_array"); - rs_datetimes.next(); - Assert.assertEquals(((Timestamp[]) rs_datetimes.getArray(2).getArray())[0].getTime(), 1557136800000L); - Assert.assertEquals(((Timestamp[]) rs_datetimes.getArray(3).getArray())[0].getTime(), 1557136800000L); - Assert.assertEquals(((Timestamp[]) rs_datetimes.getArray(4).getArray())[0].getTime(), 1557136800000L); - } - - private static Date withTimeAtStartOfDay(Date date) { - Calendar cal = Calendar.getInstance(); - cal.setTime(date); - cal.set(Calendar.HOUR_OF_DAY, 0); - cal.set(Calendar.MINUTE, 0); - cal.set(Calendar.SECOND, 0); - cal.set(Calendar.MILLISECOND, 0); - return new Date(cal.getTimeInMillis()); - } - - private ClickHouseConnection createConnection(boolean useServerTimeZone, - Long manualTimeZoneOffsetHours, boolean useServerTimeZoneForParsingDates) throws SQLException - { - ClickHouseProperties props = new ClickHouseProperties(); - props.setUseServerTimeZone(useServerTimeZone); - if (manualTimeZoneOffsetHours != null) { - props.setUseTimeZone( - "GMT" - + (manualTimeZoneOffsetHours.intValue() > 0 ? "+" : "") - + manualTimeZoneOffsetHours + ":00"); - } - props.setUseServerTimeZoneForDates(useServerTimeZoneForParsingDates); - return newConnection(props); - } - - private void resetDateTestTable(int suffix) throws Exception { - connectionServerTz.createStatement().execute( - "DROP TABLE IF EXISTS time_zone_test" + suffix); - connectionServerTz.createStatement().execute( - "CREATE TABLE IF NOT EXISTS time_zone_test" + suffix + " (i Int32, d DateTime) ENGINE = TinyLog" - ); - } - - private void insertDateTestData(int suffix, ClickHouseConnection conn, int id) throws Exception { - PreparedStatement statement = conn.prepareStatement( - "INSERT INTO time_zone_test" + suffix + " (i, d) VALUES (?, ?)"); - statement.setInt(1, id); - statement.setTimestamp(2, new Timestamp(currentTime)); - statement.execute(); - } - - private static void assertDateResult(int suffix, Connection conn, long expectedSecondsEpoch) - throws Exception - { - try (Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT i, d as cnt from time_zone_test" + suffix + " order by i")) { - Assert.assertTrue(rs.next()); - Assert.assertEquals(rs.getDate(2).getTime(), expectedSecondsEpoch * 1000); - Assert.assertTrue(rs.next()); - Assert.assertEquals(rs.getDate(2).getTime(), expectedSecondsEpoch * 1000); - } - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/WriterTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/WriterTest.java deleted file mode 100644 index 4ecc706fe..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/WriterTest.java +++ /dev/null @@ -1,143 +0,0 @@ -package ru.yandex.clickhouse.integration; - -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; -import ru.yandex.clickhouse.ClickHouseConnection; -import ru.yandex.clickhouse.ClickHouseStatement; -import ru.yandex.clickhouse.JdbcIntegrationTest; -import ru.yandex.clickhouse.domain.ClickHouseFormat; -import ru.yandex.clickhouse.settings.ClickHouseProperties; -import ru.yandex.clickhouse.util.ClickHouseRowBinaryStream; -import ru.yandex.clickhouse.util.ClickHouseStreamCallback; - -import java.io.*; -import java.sql.ResultSet; -import java.sql.SQLException; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; - -public class WriterTest extends JdbcIntegrationTest { - private ClickHouseConnection connection; - - @BeforeClass(groups = "integration") - public void setUp() throws Exception { - ClickHouseProperties properties = new ClickHouseProperties(); - properties.setDecompress(true); - properties.setCompress(true); - connection = newConnection(properties); - } - - @AfterClass(groups = "integration") - public void tearDown() throws Exception { - closeConnection(connection); - } - - @BeforeMethod(groups = "integration") - public void createTable() throws Exception { - try (ClickHouseStatement statement = connection.createStatement()) { - statement.execute("DROP TABLE IF EXISTS writer"); - statement.execute("CREATE TABLE writer (id Int32, name String) ENGINE = Log"); - statement.execute("TRUNCATE TABLE writer"); - } - } - - @Test(groups = "integration") - public void testCSV() throws Exception { - String data = "10;Фёдор\n20;Слава"; - - try (ClickHouseStatement statement = connection.createStatement()) { - statement.write().table(dbName + ".writer").format(ClickHouseFormat.CSV).option("format_csv_delimiter", ";") - .data(new ByteArrayInputStream(data.getBytes("UTF-8"))).send(); - assertTableRowCount(2); - } - } - - @Test(groups = "integration") - public void testTSV() throws Exception { - File tempFile = File.createTempFile("tmp-", ".tsv"); - tempFile.deleteOnExit(); - FileOutputStream fos = new FileOutputStream(tempFile); - for (int i = 0; i < 1000; i++) { - fos.write((i + "\tИмя " + i + "\n").getBytes("UTF-8")); - } - fos.close(); - - try (ClickHouseStatement statement = connection.createStatement()) { - statement.write().table(dbName + ".writer").format(ClickHouseFormat.TabSeparated).data(tempFile).send(); - - assertTableRowCount(1000); - - ResultSet rs = statement - .executeQuery("SELECT count() FROM writer WHERE name = concat('Имя ', toString(id))"); - rs.next(); - assertEquals(rs.getInt(1), 1000); - } - } - - @Test(groups = "integration") - public void testRowBinary() throws Exception { - try (ClickHouseStatement statement = connection.createStatement()) { - statement.write().send("INSERT INTO writer", new ClickHouseStreamCallback() { - @Override - public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { - for (int i = 0; i < 10; i++) { - stream.writeInt32(i); - stream.writeString("Имя " + i); - } - } - }, ClickHouseFormat.RowBinary); - - assertTableRowCount(10); - ResultSet rs = statement - .executeQuery("SELECT count() FROM writer WHERE name = concat('Имя ', toString(id))"); - rs.next(); - assertEquals(rs.getInt(1), 10); - } - } - - @Test(groups = "integration") - public void testNative() throws Exception { - try (ClickHouseStatement statement = connection.createStatement()) { - statement.write().send("INSERT INTO writer", new ClickHouseStreamCallback() { - @Override - public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { - - int numberOfRows = 1000; - stream.writeUnsignedLeb128(2); // 2 columns - stream.writeUnsignedLeb128(numberOfRows); - - stream.writeString("id"); - stream.writeString("Int32"); - - for (int i = 0; i < numberOfRows; i++) { - stream.writeInt32(i); - } - - stream.writeString("name"); - stream.writeString("String"); - - for (int i = 0; i < numberOfRows; i++) { - stream.writeString("Имя " + i); - } - } - }, ClickHouseFormat.Native); - - assertTableRowCount(1000); - ResultSet rs = statement - .executeQuery("SELECT count() FROM writer WHERE name = concat('Имя ', toString(id))"); - rs.next(); - assertEquals(rs.getInt(1), 1000); - } - } - - private void assertTableRowCount(int expected) throws SQLException { - try (ClickHouseStatement statement = connection.createStatement(); - ResultSet rs = statement.executeQuery("SELECT count() from writer");) { - assertTrue(rs.next()); - assertEquals(rs.getInt(1), expected); - } - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/ByteFragmentTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/ByteFragmentTest.java deleted file mode 100644 index 6dcc1bbd6..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/ByteFragmentTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package ru.yandex.clickhouse.response; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; - - -public class ByteFragmentTest { - - @DataProvider(name = "stringEscape") - public Object[][] stringEscape() { - return new Object[][]{ - {"abc'xyz", "abc\\'xyz"}, - {"\rabc\n\0xyz\b\f\txyz\\", "\\rabc\\n\\Nxyz\\b\\f\\txyz\\\\"}, - {"\n汉字'", "\\n汉字\\'"}, - {"юникод,'юникод'\n", "юникод,\\'юникод\\'\\n"} - }; - } - - @Test(groups = "unit", dataProvider = "stringEscape") - public void testEscape(String str, String escapedStr) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteFragment.escape(str.getBytes(StandardCharsets.UTF_8), out); - assertEquals(out.toString(StandardCharsets.UTF_8.name()), escapedStr); - } - - @Test(groups = "unit", dataProvider = "stringEscape") - public void testUnescape(String str, String escapedStr) throws IOException { - byte[] bytes = escapedStr.getBytes(StandardCharsets.UTF_8); - ByteFragment byteFragment = new ByteFragment(bytes, 0, bytes.length); - assertEquals(new String(byteFragment.unescape(), StandardCharsets.UTF_8.name()), str); - } - - @Test(groups = "unit") - public void testIsEmpty() { - ByteFragment byteFragment = new ByteFragment(new byte[0], 0, 0); - assertTrue(byteFragment.isEmpty()); - assertFalse(byteFragment.isNull()); - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/ClickHouseColumnInfoTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/ClickHouseColumnInfoTest.java deleted file mode 100644 index b6eec9a62..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/ClickHouseColumnInfoTest.java +++ /dev/null @@ -1,232 +0,0 @@ -package ru.yandex.clickhouse.response; - -import java.util.TimeZone; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.domain.ClickHouseDataType; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.fail; - -public class ClickHouseColumnInfoTest { - - @Test(groups = "unit") - public void testParseNull() { - try { - ClickHouseColumnInfo.parse(null, null, null); - fail(); - } catch (NullPointerException npe) { /* expected */ } - } - - @Test(groups = "unit") - public void testDateTimeWithoutTimeZone() { - ClickHouseColumnInfo info = ClickHouseColumnInfo.parse( - "DateTime", "column", null); - assertEquals(info.getClickHouseDataType(), ClickHouseDataType.DateTime); - } - - @Test(groups = "unit") - public void testDateTimeWithEmptyTimeZone() { - ClickHouseColumnInfo info = ClickHouseColumnInfo.parse( - "DateTime()", "column", null); - assertEquals(info.getClickHouseDataType(), ClickHouseDataType.DateTime); - } - - @Test(groups = "unit") - public void testDateTimeArrayWithTimeZonee() { - assertEquals( - ClickHouseColumnInfo.parse( - "Array(DateTime('America/Los_Angeles'))", "foo", TimeZone.getTimeZone("Asia/Chongqing")).getTimeZone(), - TimeZone.getTimeZone("America/Los_Angeles")); - } - - @Test(groups = "unit") - public void testSpuriousArguments() { - ClickHouseColumnInfo info = ClickHouseColumnInfo.parse( - "Decimal(12, 3), 42)", "column", null); - assertEquals(info.getScale(), 3); - } - - @Test(groups = "unit", dataProvider = "columnInfoParsingDataProvider") - public void testParser(String input, ClickHouseDataType dataType, ClickHouseDataType arrayBaseType, - boolean nullable, boolean lowCardinality, int precision, int scale, TimeZone timeZone, - int arrayLevel) - { - ClickHouseColumnInfo info = ClickHouseColumnInfo.parse(input, "columnName", null); - assertEquals(info.getClickHouseDataType(), dataType); - assertEquals(info.getArrayBaseType(), arrayBaseType); - assertEquals(info.isNullable(), nullable); - assertEquals(info.isLowCardinality(), lowCardinality); - assertEquals(info.getPrecision(), precision); - assertEquals(info.getScale(), scale); - assertEquals(info.getTimeZone(), timeZone); - assertEquals(info.getArrayLevel(), arrayLevel); - assertEquals(info.getOriginalTypeName(), input); - assertEquals(info.getColumnName(), "columnName"); - assertEquals( - info.getEffectiveClickHouseDataType(), - dataType == ClickHouseDataType.Array ? arrayBaseType : dataType); - } - - @SuppressWarnings("boxing") - @DataProvider(name = "columnInfoParsingDataProvider") - public Object[][] provideRegularParsingTestData() { - return new Object[][] { - { "Array(String)", - ClickHouseDataType.Array, ClickHouseDataType.String, false, false, 0, 0, null, 1 }, - { "Array(Array(String))", - ClickHouseDataType.Array, ClickHouseDataType.String, false, false, 0, 0, null, 2 }, - { "Array(Array(LowCardinality(Nullable(String))))", - ClickHouseDataType.Array, ClickHouseDataType.String, true, true, 0, 0, null, 2 }, - { "Array(Decimal(12, 3))", - ClickHouseDataType.Array, ClickHouseDataType.Decimal, false, false, 12, 3, null, 1 }, - { "Decimal(12, 3)", - ClickHouseDataType.Decimal, null, false, false, 12, 3, null, 0 }, - { "Decimal32(3)", - ClickHouseDataType.Decimal32, null, false, false, 9, 3, null, 0 }, - { "Decimal64(3)", - ClickHouseDataType.Decimal64, null, false, false, 18, 3, null, 0 }, - { "Decimal128(3)", - ClickHouseDataType.Decimal128, null, false, false, 38, 3, null, 0 }, - { "DateTime('Europe/Berlin')", - ClickHouseDataType.DateTime, null, false, false, 19, 0, TimeZone.getTimeZone("Europe/Berlin"), 0 }, - { "DateTime(Europe/Amsterdam)", - ClickHouseDataType.DateTime, null, false, false, 19, 0, TimeZone.getTimeZone("Europe/Amsterdam"), 0 }, - { "FixedString(42)", - ClickHouseDataType.FixedString, null, false, false, 42, 0, null, 0 }, - { "LowCardinality(Nullable(Int64))", // issue #325 - ClickHouseDataType.Int64, null, true, true, 20, 0, null, 0 } - }; - } - - @Test(groups = "unit", dataProvider = "columnInfoParsingUnknownDataProvider") - public void testParserUnknownDataTypes(String input, boolean nullable, - boolean lowCardinality) - { - ClickHouseColumnInfo info = ClickHouseColumnInfo.parse(input, "columnName", null); - assertEquals(info.getClickHouseDataType(), ClickHouseDataType.Unknown); - assertEquals(info.isNullable(), nullable); - assertEquals(info.isLowCardinality(), lowCardinality); - } - - @Test(groups = "unit", dataProvider = "columnInfoParsingUnknownDataProvider") - public void testParserUnknownArrayDataTypes(String input, boolean nullable, - boolean lowCardinality) - { - ClickHouseColumnInfo info = ClickHouseColumnInfo.parse( - "Array(" + input + ")", "columnName", null); - assertEquals(info.getClickHouseDataType(), ClickHouseDataType.Array); - assertEquals(info.getArrayBaseType(), ClickHouseDataType.Unknown); - assertEquals(info.isNullable(), nullable); - assertEquals(info.isLowCardinality(), lowCardinality); - } - - @SuppressWarnings("boxing") - @DataProvider(name = "columnInfoParsingUnknownDataProvider") - public Object[][] provideUnknownDataTypeParserInput() { - return new Object[][] { - { "Nullable(NewPhantasyDataType(42))", true, false}, - { "NewPhantasyDataType", false, false}, - { "LowCardinality(NewPhantasyDataType)", false, true } - }; - } - - @Test(groups = "unit") - public void testCleanTypeName() { - assertEquals( - ClickHouseColumnInfo.parse("Decimal(12,3)", "col", null).getCleanTypeName(), - "Decimal(12,3)"); - assertEquals( - ClickHouseColumnInfo.parse("LowCardinality(Nullable(Decimal(12,3)))", "col", null).getCleanTypeName(), - "Decimal(12,3)"); - assertEquals( - ClickHouseColumnInfo.parse("LowCardinality(Decimal(12,3))", "col", null).getCleanTypeName(), - "Decimal(12,3)"); - assertEquals( - ClickHouseColumnInfo.parse("Nullable(Decimal(12,3))", "col", null).getCleanTypeName(), - "Decimal(12,3)"); - assertEquals( - ClickHouseColumnInfo.parse("Array(LowCardinality(Nullable(Decimal(12,3))))", "col", null).getCleanTypeName(), - "Array(Decimal(12,3))"); - assertEquals( - ClickHouseColumnInfo.parse("Array(Array(LowCardinality(Nullable(Decimal(12,3)))))", "col", null).getCleanTypeName(), - "Array(Array(Decimal(12,3)))"); - } - - @Test(groups = "unit", dataProvider = "columnInfoNullableTypeDefinitions") - public void testTypeIsNullable(String typeDef, Boolean nullable) throws Exception { - assertEquals( - nullable.booleanValue(), - ClickHouseColumnInfo.parse(typeDef, "foo", null).isNullable()); - } - - @DataProvider(name = "columnInfoNullableTypeDefinitions") - public Object[][] provideNullableTypeDefinitions() { - return new Object[][] { - {"DateTime", Boolean.FALSE}, - {"Float64", Boolean.FALSE}, - {"Nullable(Float64)", Boolean.TRUE}, - {"Nullable(DateTime)", Boolean.TRUE} - }; - } - - @Test(groups = "unit", dataProvider = "columnInfoScales") - public void testGetScale(String typeDef, int scale) { - assertEquals( - ClickHouseColumnInfo.parse(typeDef, "foo", null).getScale(), - scale); - } - - @DataProvider(name = "columnInfoScales") - public Object[][] provideScaleTypeDefinitions() { - return new Object[][] { - {"DateTime", Integer.valueOf(0)}, - {"Int32", Integer.valueOf(0)}, - {"Array(String)", Integer.valueOf(0)}, - {"Nullable(Int32)", Integer.valueOf(0)}, - {"Nullable(DateTime)", Integer.valueOf(0)}, - {"Float64", Integer.valueOf(17)}, - {"Nullable(Float64)", Integer.valueOf(17)}, - {"Float32", Integer.valueOf(8)}, - {"Nullable(Float32)", Integer.valueOf(8)}, - {"Decimal(12,3)", Integer.valueOf(3)}, - {"Decimal(12, 3)", Integer.valueOf(3)}, - {"Decimal(12, )", Integer.valueOf(0)}, - {"Decimal(12, 0)", Integer.valueOf(0)}, - {"Nullable(Decimal(12,3)", Integer.valueOf(3)} - }; - } - - @Test(groups = "unit", dataProvider = "columnInfoPrecisions") - public void testGetPrecision(String typeDef, int precision) { - assertEquals( - ClickHouseColumnInfo.parse(typeDef, "foo", null).getPrecision(), - precision); - } - - - @DataProvider(name = "columnInfoPrecisions") - public Object[][] providePrecisionTypeDefinitions() { - return new Object[][] { - {"DateTime", Integer.valueOf(19)}, - {"DateTime('W-SU')", Integer.valueOf(19)}, - {"Date", Integer.valueOf(10)}, - {"UInt8", Integer.valueOf(3)}, - {"Int32", Integer.valueOf(11)}, - {"Float32", Integer.valueOf(8)}, - {"String", Integer.valueOf(0)}, - {"FixedString(12)", Integer.valueOf(12)}, - {"Enum8", Integer.valueOf(0)}, - {"Array(String)", Integer.valueOf(0)}, - {"Decimal(42,23)", Integer.valueOf(42)}, - {"Decimal(23)", Integer.valueOf(0)}, // illegal decimal def - {"Nullable(Int32)", Integer.valueOf(11)}, - {"Nullable(DateTime)", Integer.valueOf(19)}, - {"Nullable(FixedString(4))", Integer.valueOf(4)}, - - }; - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/ClickHouseResultBuilderTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/ClickHouseResultBuilderTest.java deleted file mode 100644 index 016fe9ed4..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/ClickHouseResultBuilderTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package ru.yandex.clickhouse.response; - - -import java.util.List; - -import org.testng.Assert; -import org.testng.annotations.Test; - -public class ClickHouseResultBuilderTest { - - @Test(groups = "unit") - public void testBuild() throws Exception { - ClickHouseResultSet resultSet = ClickHouseResultBuilder.builder(2) - .names("string", "int") - .types("String", "UInt32") - .addRow("ololo", 1000) - .addRow("o\tlo\nlo", 1000) - .addRow(null, null) - .build(); - List columns = resultSet.getColumns(); - - Assert.assertEquals(1, resultSet.findColumn("string")); - Assert.assertEquals(2, resultSet.findColumn("int")); - - Assert.assertEquals("string", columns.get(0).getColumnName()); - Assert.assertEquals("int", columns.get(1).getColumnName()); - - Assert.assertEquals("String", columns.get(0).getOriginalTypeName()); - Assert.assertEquals("UInt32", columns.get(1).getOriginalTypeName()); - - Assert.assertTrue(resultSet.next()); - Assert.assertEquals("ololo", resultSet.getString(1)); - Assert.assertEquals(1000, resultSet.getInt(2)); - - Assert.assertTrue(resultSet.next()); - Assert.assertEquals("o\tlo\nlo", resultSet.getString(1)); - Assert.assertEquals(1000, resultSet.getInt(2)); - - Assert.assertTrue(resultSet.next()); - Assert.assertNull(resultSet.getString(1)); - Assert.assertEquals(0, resultSet.getInt(2)); - - Assert.assertFalse(resultSet.next()); - - } -} \ No newline at end of file diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/ClickHouseResultSetMetaDataTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/ClickHouseResultSetMetaDataTest.java deleted file mode 100644 index 5114751c4..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/ClickHouseResultSetMetaDataTest.java +++ /dev/null @@ -1,69 +0,0 @@ -package ru.yandex.clickhouse.response; - -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.sql.Types; -import java.util.Arrays; -import java.util.Collections; - -import org.testng.Assert; -import org.testng.annotations.Test; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class ClickHouseResultSetMetaDataTest { - - - @Test(groups = "unit") - public void testIsNullable() throws SQLException { - - ClickHouseResultSet resultSet = mock(ClickHouseResultSet.class); - ClickHouseColumnInfo[] types = new ClickHouseColumnInfo[] { - ClickHouseColumnInfo.parse("DateTime", "column1", null), - ClickHouseColumnInfo.parse("Nullable(Float64)", "column2", null) - }; - when(resultSet.getColumns()).thenReturn(Arrays.asList(types)); - ClickHouseResultSetMetaData resultSetMetaData = new ClickHouseResultSetMetaData(resultSet); - Assert.assertEquals(resultSetMetaData.isNullable(1), ResultSetMetaData.columnNoNulls); - Assert.assertEquals(resultSetMetaData.isNullable(2), ResultSetMetaData.columnNullable); - } - - @Test(groups = "unit") - public void testIsNullableColumnTypeName() throws SQLException { - - ClickHouseResultSet resultSet = mock(ClickHouseResultSet.class); - when(resultSet.getColumns()).thenReturn(Collections.singletonList( - ClickHouseColumnInfo.parse("Nullable(Float64)", "column1", null))); - ClickHouseResultSetMetaData resultSetMetaData = new ClickHouseResultSetMetaData(resultSet); - Assert.assertEquals(resultSetMetaData.getColumnTypeName(1), "Float64"); - } - - @Test(groups = "unit") - public void testIsNullableSigned() throws SQLException { - ClickHouseResultSet resultSet = mock(ClickHouseResultSet.class); - ClickHouseColumnInfo[] types = new ClickHouseColumnInfo[]{ - ClickHouseColumnInfo.parse("Nullable(Float64)", "column1", null), - ClickHouseColumnInfo.parse("Nullable(UInt64)", "column2", null), - ClickHouseColumnInfo.parse("Nullable(UFantasy)", "column3", null) - }; - when(resultSet.getColumns()).thenReturn(Arrays.asList(types)); - ClickHouseResultSetMetaData resultSetMetaData = new ClickHouseResultSetMetaData( - resultSet); - Assert.assertTrue(resultSetMetaData.isSigned(1)); - Assert.assertFalse(resultSetMetaData.isSigned(2)); - Assert.assertFalse(resultSetMetaData.isSigned(3)); - } - - @Test(groups = "unit") - public void testDateTimeWithTimeZone() throws SQLException { - ClickHouseResultSet resultSet = mock(ClickHouseResultSet.class); - when(resultSet.getColumns()).thenReturn(Collections.singletonList( - ClickHouseColumnInfo.parse("DateTime('W-SU')", "column1", null))); - ClickHouseResultSetMetaData resultSetMetaData = new ClickHouseResultSetMetaData( - resultSet); - Assert.assertEquals(resultSetMetaData.getColumnTypeName(1), "DateTime('W-SU')"); - Assert.assertEquals(resultSetMetaData.getColumnType(1), Types.TIMESTAMP); - } - -} \ No newline at end of file diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/ClickHouseResultSetTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/ClickHouseResultSetTest.java deleted file mode 100644 index 378ccd7d1..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/ClickHouseResultSetTest.java +++ /dev/null @@ -1,991 +0,0 @@ -package ru.yandex.clickhouse.response; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.net.URL; -import java.sql.Array; -import java.sql.Blob; -import java.sql.Clob; -import java.sql.Date; -import java.sql.JDBCType; -import java.sql.NClob; -import java.sql.Ref; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.RowId; -import java.sql.SQLException; -import java.sql.SQLXML; -import java.sql.Struct; -import java.sql.Time; -import java.sql.Timestamp; -import java.sql.Types; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.util.Calendar; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.Map; -import java.util.TimeZone; - -import org.mockito.Mockito; -import org.testng.Assert; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.ClickHouseStatement; -import ru.yandex.clickhouse.settings.ClickHouseProperties; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; - -public class ClickHouseResultSetTest { - - private ClickHouseProperties props; - - @BeforeMethod(groups = "unit") - public void setUp() { - props = Mockito.mock(ClickHouseProperties.class); - } - - @DataProvider(name = "longArrays") - public Object[][] longArrays() { - return new Object[][]{ - {"[0]", new long[]{0}}, - {"[324000111222,123,-456]", new long[]{324000111222L, 123, -456}}, - {"[]", new long[]{}}, - }; - } - - @Test(groups = "unit", dataProvider = "longArrays") - public void toLongArrayTest(String str, long[] expected) throws Exception { - Assert.assertEquals( - ClickHouseResultSet.toLongArray( - ByteFragment.fromString(str), - ClickHouseColumnInfo.parse("Array(UInt64)", "columnName", null)), - expected - ); - } - - - @Test(groups = "unit") - public void withoutTotals() throws Exception { - String response = - "SiteName\tcount()\n" + - "String\tUInt64\n" + - "hello.com\t21209048\n" + - "there.com\t49302091\n"; - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - - ResultSet rs = buildResultSet(is, 1024, "db", "table", false, null, null, props); - - rs.next(); - assertEquals("hello.com", rs.getString(1)); - assertEquals(21209048L, rs.getLong(2)); - - rs.next(); - assertEquals("there.com", rs.getString(1)); - assertEquals(49302091L, rs.getLong(2)); - - assertFalse(rs.next()); - } - - @Test(groups = "unit") - public void withoutTotalsSingleColumn() throws Exception { - String response = - "SiteName\n" + - "String\n" + - "hello.com\n" + - "there.com\n" + - "\n" + - "\n"; - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - - ClickHouseResultSet rs = buildResultSet(is, 1024, "db", "table", false, null, null, props); - - rs.next(); - assertEquals("hello.com", rs.getString(1)); - - rs.next(); - assertEquals("there.com", rs.getString(1)); - - rs.next(); - assertEquals("", rs.getString(1)); - - rs.next(); - assertEquals("", rs.getString(1)); - - assertFalse(rs.next()); - try { - rs.getTotals(); - fail("The getTotals shall fail when usesWithTotals is set to false."); - } catch (IllegalStateException e) { - // this is expected - } - assertFalse(rs.next()); - } - - @Test(groups = "unit") - public void withTotals() throws Exception { - String response = "SiteName\tcount()\n" + - "String\tUInt64\n" + - "hello.com\t21209048\n" + - "there.com\t49302091\n" + - "\n" + - "\t70511139\n"; - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - - ClickHouseResultSet rs = buildResultSet(is, 1024, "db", "table", true, null, null, props); - - rs.next(); - assertEquals("hello.com", rs.getString(1)); - assertEquals(21209048L, rs.getLong(2)); - - rs.next(); - assertEquals("there.com", rs.getString(1)); - assertEquals(49302091L, rs.getLong(2)); - - assertFalse(rs.next()); - - rs.getTotals(); - assertEquals("", rs.getString(1)); - assertEquals(70511139L, rs.getLong(2)); - } - - @Test(groups = "unit") - public void withTotalsAndEmptyStrings() throws Exception { - String response = "SiteName\tCountry\n" + - "String\tString\n" + - "hello.com\tPoland\n" + - "there.com\tUSA\n" + - "\t\n" + - "other.com\t\n" + - "\n" + - "\t\n"; - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - - ClickHouseResultSet rs = buildResultSet(is, 1024, "db", "table", true, null, null, props); - - rs.next(); - assertEquals("hello.com", rs.getString(1)); - assertEquals("Poland", rs.getString(2)); - - - rs.next(); - assertEquals("there.com", rs.getString(1)); - assertEquals("USA", rs.getString(2)); - - rs.next(); - assertEquals("", rs.getString(1)); - assertEquals("", rs.getString(2)); - - rs.next(); - assertEquals("other.com", rs.getString(1)); - assertEquals("", rs.getString(2)); - - assertFalse(rs.next()); - - rs.getTotals(); - assertEquals("", rs.getString(1)); - assertEquals(0L, rs.getLong(2)); - } - - @Test(groups = "unit") - public void withTotalsSingleColumn() throws Exception { - String response = - "SiteName\n" + - "String\n" + - "hello.com\n" + - "there.com\n" + - "\n" + - "other.com\n" + - "\n" + // with totals separator row - "\n"; // with totals values row - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - - ResultSet rs = buildResultSet(is, 1024, "db", "table", true, null, null, props); - - rs.next(); - assertEquals("hello.com", rs.getString(1)); - - rs.next(); - assertEquals("there.com", rs.getString(1)); - - rs.next(); - assertEquals("", rs.getString(1)); - - rs.next(); - assertEquals("other.com", rs.getString(1)); - - assertFalse(rs.next()); - } - - @Test(groups = "unit") - public void withTotalsSingleIntColumn() throws Exception { - String response = - "Code\n" + - "UInt64\n" + - "1\n" + - "2\n" + - "3\n" + - "\n" + // with totals separator row - "0"; // with totals values row - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - - ClickHouseResultSet rs = buildResultSet(is, 1024, "db", "table", true, null, null, props); - - rs.next(); - assertEquals(1L, rs.getLong(1)); - - rs.next(); - assertEquals(2L, rs.getLong(1)); - - rs.next(); - assertEquals(3L, rs.getLong(1)); - - assertFalse(rs.next()); - - rs.getTotals(); - assertEquals(0L, rs.getLong(1)); - } - - @Test(groups = "unit") - public void withTotalsSingleFloatColumn() throws Exception { - String response = - "Code\n" - + "Float32\n" - + "1.0\n" - + "NaN\n" - + "nan\n" - + "Infinity\n" - + "+Infinity\n" - + "-Infinity\n" - + "inf\n" - + "+inf\n" - + "-inf\n" - + "\n" // with totals separator row - + "0"; // with totals values row - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - - ClickHouseResultSet rs = buildResultSet(is, 1024, "db", "table", true, null, null, props); - - rs.next(); - assertEquals(1f, rs.getObject(1)); - - rs.next(); - assertTrue(Float.isNaN((Float) rs.getObject(1))); - - rs.next(); - assertTrue(Float.isNaN((Float) rs.getObject(1))); - - rs.next(); - assertEquals(Float.POSITIVE_INFINITY, rs.getObject(1)); - - rs.next(); - assertEquals(Float.POSITIVE_INFINITY, rs.getObject(1)); - - rs.next(); - assertEquals(Float.NEGATIVE_INFINITY, rs.getObject(1)); - - rs.next(); - assertEquals(Float.POSITIVE_INFINITY, rs.getObject(1)); - - rs.next(); - assertEquals(Float.POSITIVE_INFINITY, rs.getObject(1)); - - rs.next(); - assertEquals(Float.NEGATIVE_INFINITY, rs.getObject(1)); - - assertFalse(rs.next()); - - rs.getTotals(); - assertEquals(0L, rs.getLong(1)); - } - - - @Test(groups = "unit") - public void withTotalsSingleNullableColumn() throws Exception { - String response = - "SiteName\n" + - "Nullable(String)\n" + - "hello.com\n" + - "there.com\n" + - "\n" + - "\\N\n" + - "other.com\n" + - "\n" + // with totals separator row - "\\N\n";// with totals values row - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - - ClickHouseResultSet rs = buildResultSet(is, 1024, "db", "table", true, null, null, props); - - rs.next(); - assertEquals("hello.com", rs.getString(1)); - - rs.next(); - assertEquals("there.com", rs.getString(1)); - - rs.next(); - assertEquals("", rs.getString(1)); - - rs.next(); - assertNull(rs.getString(1)); - - rs.next(); - assertEquals("other.com", rs.getString(1)); - - assertFalse(rs.next()); - - rs.getTotals(); - assertNull(rs.getString(1)); - } - - @Test(groups = "unit") - public void testIsLast() throws Exception { - String response = - "SiteName\tcount()\n" + - "String\tUInt64\n" + - "hello.com\t21209048\n" + - "there.com\t49302091\n"; - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - - ResultSet rs = buildResultSet(is, 1024, "db", "table", false, null, null, props); - - assertFalse(rs.isLast()); - assertTrue(rs.next()); - assertFalse(rs.isLast()); - assertTrue(rs.next()); - assertTrue(rs.isLast()); - assertFalse(rs.next()); - } - - @Test(groups = "unit") - public void testIsFirst() throws Exception { - String response = - "SiteName\tcount()\n" + - "String\tUInt64\n" + - "hello.com\t21209048\n" + - "there.com\t49302091\n"; - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - - ResultSet rs = buildResultSet(is, 1024, "db", "table", false, null, null, props); - - assertFalse(rs.isFirst()); - assertTrue(rs.next()); - assertTrue(rs.isFirst()); - assertTrue(rs.next()); - assertFalse(rs.isFirst()); - } - - @Test(groups = "unit") - public void testBeforeFirst() throws Exception { - String response = - "SiteName\tcount()\n" + - "String\tUInt64\n" + - "hello.com\t21209048\n" + - "there.com\t49302091\n"; - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - - ResultSet rs = buildResultSet(is, 1024, "db", "table", false, null, null, props); - - assertTrue(rs.isBeforeFirst()); - assertTrue(rs.next()); - assertFalse(rs.isBeforeFirst()); - is.close(); - } - - @Test(groups = "unit") - public void testIsAfterLast() throws Exception { - String response = - "SiteName\tcount()\n" + - "String\tUInt64\n" + - "hello.com\t21209048\n" + - "there.com\t49302091\n"; - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - - ResultSet rs = buildResultSet(is, 1024, "db", "table", false, null, null, props); - - assertFalse(rs.isAfterLast()); - assertTrue(rs.next()); - assertFalse(rs.isAfterLast()); - assertTrue(rs.next()); - assertFalse(rs.isAfterLast()); - assertFalse(rs.next()); - assertTrue(rs.isAfterLast()); - } - - @Test(groups = "unit") - public void testDecimalMetadata() throws Exception { - String response = - "sum(myMoney)\n" + - "Decimal(38, 3)\n" + - "12955152630.539"; - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - ResultSet rs = buildResultSet(is, 1024, "db", "table", false, null, null, props); - rs.next(); - assertEquals(rs.getMetaData().getColumnType(1), Types.DECIMAL); - assertEquals(rs.getMetaData().getColumnTypeName(1), "Decimal(38, 3)"); - assertEquals(rs.getMetaData().getColumnClassName(1), BigDecimal.class.getCanonicalName()); - assertEquals(rs.getObject(1), new BigDecimal("12955152630.539")); - assertEquals(rs.getMetaData().getScale(1), 3); - assertEquals(rs.getMetaData().getPrecision(1), 38); - } - - @Test(groups = "unit") - public void testArrayString() throws Exception { - String response = - "FOO\n" - + "Array(String)\n" - + "[foo,bar]\n"; - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - ResultSet rs = buildResultSet(is, 1024, "db", "table", false, null, null, props); - ResultSetMetaData meta = rs.getMetaData(); - assertEquals("java.sql.Array", meta.getColumnClassName(1)); - rs.next(); - Object o = rs.getObject(1); - assertTrue(Array.class.isAssignableFrom(o.getClass()), - o.getClass().getCanonicalName()); - String[] s = (String[]) ((Array) o).getArray(); - assertEquals("foo", s[0]); - assertEquals("bar", s[1]); - } - - @Test(groups = "unit") - public void test3dArrayString() throws Exception { - String response = - "FOO\n" - + "Array(Array(Array(String)))\n" - + "[[[a,b],[c,d]],[[e,f],[g,h]]]"; - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - ResultSet rs = buildResultSet(is, 1024, "db", "table", false, null, null, props); - ResultSetMetaData meta = rs.getMetaData(); - assertEquals("java.sql.Array", meta.getColumnClassName(1)); - rs.next(); - - Object o = rs.getObject(1); - assertTrue(Array.class.isAssignableFrom(o.getClass()), o.getClass().getCanonicalName()); - String[][][] actual = (String[][][]) ((Array) o).getArray(); - String[][][] expected = {{{"a", "b"}, {"c","d"}}, {{"e", "f"}, {"g", "h"}}}; - assertEquals(expected.length, actual.length); - for (int i = 0; i < expected.length; ++i) { - assertEquals(expected[i].length, actual[i].length); - for (int j = 0; j < expected[i].length; ++j) { - assertEquals(expected[i][j].length, actual[i][j].length); - for (int k = 0; k < expected[i][j].length; ++k) { - assertEquals(expected[i][j][k], actual[i][j][k]); - } - } - } - } - - @Test(groups = "unit") - public void testClassNamesObjects() throws Exception { - String testData = ClickHouseTypesTestData.buildTestString(); - ByteArrayInputStream is = new ByteArrayInputStream(testData.getBytes("UTF-8")); - ResultSet rs = buildResultSet(is, testData.length(), "db", "table", false, null, - TimeZone.getTimeZone("UTC"), props); - rs.next(); - ResultSetMetaData meta = rs.getMetaData(); - for (int i = 1; i <= meta.getColumnCount(); i++) { - String typeName = meta.getColumnTypeName(i); - String className = null; - try { - className = meta.getColumnClassName(i); - } catch (Exception e) { - fail("Unable to determine class name for " + typeName, e); - } - Class clazz = Class.forName(className); - assertNotNull( - clazz, - "Class not available. class name: " + className + ", type name: " + typeName); - Object o = rs.getObject(i); - if (o == null && meta.isNullable(i) > 0) { - continue; - } - assertNotNull( - o, - "Object null. class name: " + className + ", type name: " + typeName); - assertTrue( - clazz.isInstance(rs.getObject(i)), - "Class mismatch. class name: " + className + ", type name: " + typeName + - " object class: " + o.getClass().getCanonicalName()); - } - } - - @Test(groups = "unit") - public void testGetColumnNames() throws Exception { - String response = "SiteName\tCountry\n" + - "String\tString\n" + - "hello.com\tPoland\n" + - "there.com\tUSA\n" + - "\t\n" + - "other.com\t\n" + - "\n" + - "\t\n"; - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - - ClickHouseResultSet rs = buildResultSet(is, 1024, "db", "table", false, null, null, props); - String[] columnNames = rs.getColumnNames(); - assertEquals(2, columnNames.length); - assertEquals("SiteName", columnNames[0]); - assertEquals("Country", columnNames[1]); - } - - /** - * By jdbc specification - * - * If the value is SQL NULL, the value returned is 0 - * - * {@link java.sql.ResultSet#getByte(int)} - * {@link java.sql.ResultSet#getShort(int)} - * {@link java.sql.ResultSet#getInt(int)} - * {@link java.sql.ResultSet#getLong(int)} - * {@link java.sql.ResultSet#getFloat(int)} - * {@link java.sql.ResultSet#getDouble(int)} - * - * If the value is SQL NULL, the value returned is null - * - * {@link java.sql.ResultSet#getBigDecimal(int)} - * {@link java.sql.ResultSet#getTime(int)} - * {@link java.sql.ResultSet#getDate(int)} - * {@link java.sql.ResultSet#getTimestamp(int)} - * {@link java.sql.ResultSet#getURL(int)} unsupported now - * {@link java.sql.ResultSet#getAsciiStream(int)} unsupported now - */ - @Test(groups = "unit") - public void testNulls() throws Exception { - String response = - "Type\n" + - "Nullable(Int8)\n" + - "\\N\n"; - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - - ResultSet rs = buildResultSet(is, 1024, "db", "table", false, null, null, props); - - rs.next(); - //0 - assertEquals(0, rs.getByte(1)); - assertEquals(0, rs.getShort(1)); - assertEquals(0, rs.getInt(1)); - assertEquals(0, rs.getLong(1)); - assertEquals((float) 0, rs.getFloat(1)); - assertEquals((double)0, rs.getDouble(1)); - - //null - assertNull(rs.getBigDecimal(1)); - assertNull(rs.getTime(1)); - assertNull(rs.getDate(1)); - assertNull(rs.getTimestamp(1)); - - //unsupported now - //assertNull(rs.getURL(1)); - //assertNull(rs.getAsciiStream(1)); - - assertFalse(rs.next()); - } - - // this test checks mapping of SQL type to Java class - // according to spec appendix table B-3 - @Test(groups = "unit") - public void testJDBCTableB3() throws Exception { - String testData = ClickHouseTypesTestData.buildTestString(); - ByteArrayInputStream is = new ByteArrayInputStream(testData.getBytes("UTF-8")); - ResultSet rs = buildResultSet(is, testData.length(), "db", "table", false, null, - TimeZone.getTimeZone("UTC"), props); - rs.next(); - ResultSetMetaData meta = rs.getMetaData(); - for (int i = 1; i <= meta.getColumnCount(); i++) { - if (meta.isNullable(i) == ResultSetMetaData.columnNullable) { - continue; - } - JDBCType jdbcType = JDBCType.valueOf(meta.getColumnType(i)); - Class clazz = jdbcMappingTableB3().get(jdbcType); - // of course, we have one exception :-) - if ("UInt64".equals(meta.getColumnTypeName(i))) { - clazz = BigInteger.class; - } - assertNotNull(clazz, "no class mapping for type " + jdbcType); - Object o = rs.getObject(i); - assertNotNull(o, "null object for column " + i + " jdbcType: " + jdbcType.toString()); - assertTrue( - clazz.isInstance(o), - "type: " + jdbcType.toString() + " clazz: " + clazz.getName() + - " vs. object: " + o.getClass().getName()); - } - } - - @Test(groups = "unit") - public void testFindColumn() throws Exception { - - /* - * See JDBC 4.2 spec, 15.2.3: - * - * - case insensitive - * - duplicates: return first - * - throw SQLException if not found - */ - - String response = - "col_a\tcol_b\tcol_a\tCOL_C\n" + - "UInt8\tUInt8\tUInt8\tUInt8\n" + - "1\t1\t1\t1\n"; - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - ResultSet rs = buildResultSet(is, 1024, "db", "table", false, null, null, props); - assertEquals(rs.findColumn("col_a"), 1); - assertEquals(rs.findColumn("COL_A"), 1); - assertEquals(rs.findColumn("Col_A"), 1); - assertEquals(rs.findColumn("col_b"), 2); - assertEquals(rs.findColumn("col_c"), 4); - try { - rs.findColumn("col_d"); - fail(); - } catch (SQLException sqle) { - // expected - } - try { - rs.findColumn(null); - fail(); - } catch (SQLException sqle) { - // expected - } - try { - rs.findColumn(""); - fail(); - } catch (SQLException sqle) { - // expected - } - } - - // this test checks mapping of SQL type to Java class - // according to spec appendix table B-1 - @Test(groups = "unit") - public void testJDBCTableB1() throws Exception { - String testData = ClickHouseTypesTestData.buildTestString(); - ByteArrayInputStream is = new ByteArrayInputStream(testData.getBytes("UTF-8")); - ResultSet rs = buildResultSet(is, testData.length(), "db", "table", false, null, - TimeZone.getTimeZone("UTC"), props); - rs.next(); - ResultSetMetaData meta = rs.getMetaData(); - for (int i = 1; i <= meta.getColumnCount(); i++) { - if (meta.isNullable(i) == ResultSetMetaData.columnNullable) { - continue; - } - JDBCType jdbcType = JDBCType.valueOf(meta.getColumnType(i)); - Class clazz = jdbcMappingTableB1().get(jdbcType); - switch (clazz.getName()) { - case "byte": - rs.getByte(i); - break; - case "short": - rs.getShort(i); - break; - case "int": - rs.getInt(i); - break; - case "long": - rs.getLong(i); - break; - case "float": - rs.getFloat(i); - break; - case "double": - rs.getDouble(i); - break; - case "boolean": - rs.getBoolean(i); - break; - default: - Object o = rs.getObject(i, clazz); - if (o != null) { - assertTrue(clazz.isInstance(o)); - } - break; - } - } - } - - @Test(groups = "unit") - public void testGetDateCalendarJVMTime() throws Exception { - String testData = "column\nDateTime\n2020-02-08 01:02:03"; - ByteArrayInputStream is = new ByteArrayInputStream(testData.getBytes("UTF-8")); - ResultSet rs = buildResultSet(is, testData.length(), "db", "table", false, null, - TimeZone.getTimeZone("UTC"), props); - rs.next(); - Calendar cal = new GregorianCalendar(); - cal.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); - Date d = rs.getDate(1, cal); - // d.toLocalDate() is deprecated and it does not take TimeZone into count - assertEquals(Instant.ofEpochMilli( - rs.getDate(1, cal).getTime()).atZone(ZoneId.of("UTC")).toLocalDate(), LocalDate.of(2020, 2, 8)); - assertEquals( - d.getTime() / 1000, - ZonedDateTime - .of( - LocalDate.of(2020, 2, 8), - LocalTime.MIDNIGHT, - ZoneId.of("UTC")) - .toEpochSecond()); - } - - @Test(groups = "unit") - public void testGetDateCalendarServerTime() throws Exception { - Mockito - .when(props.isUseServerTimeZoneForDates()) - .thenReturn(Boolean.TRUE); - String testData = "column\nDateTime\n2020-02-08 01:02:03"; - ByteArrayInputStream is = new ByteArrayInputStream(testData.getBytes("UTF-8")); - ResultSet rs = buildResultSet(is, testData.length(), "db", "table", false, null, - TimeZone.getTimeZone("UTC"), props); - rs.next(); - Calendar cal = new GregorianCalendar(); - cal.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); - Date d = rs.getDate(1, cal); - assertEquals(d.getTime(), - LocalDate.of(2020, 2, 8).atStartOfDay(ZoneId.of("UTC")) - .toInstant().toEpochMilli()); - assertEquals( - d.getTime() / 1000, - ZonedDateTime - .of( - LocalDate.of(2020, 2, 8), - LocalTime.MIDNIGHT, - ZoneId.of("UTC")) - .toEpochSecond()); - } - - @Test(groups = "unit") - public void testLocalDateTime() throws Exception { - String response = - "SiteName\n" + - "Nullable(DateTime)\n" + - "2021-01-08 11:05:14\n" + - "there.com\n" + - "\n" + - "\\N\n" + - "other.com\n" + - "\n" + // with totals separator row - "\\N\n";// with totals values row - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - ClickHouseResultSet rs = buildResultSet(is, 1024, "db", "table", true, null, null, props); - rs.next(); - - LocalDateTime expectedTime = LocalDateTime.parse("2021-01-08 11:05:14", - DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); - assertEquals(expectedTime, rs.getObject(1, LocalDateTime.class)); - } - - private static ClickHouseResultSet buildResultSet(InputStream is, int bufferSize, String db, - String table, boolean usesWithTotals, ClickHouseStatement statement, TimeZone timezone, - ClickHouseProperties properties) - throws IOException - { - return new ClickHouseResultSet(is, bufferSize, db, table, usesWithTotals, statement, - timezone, properties); - } - - private static enum ClickHouseTypesTestData { - - // SELECT name FROM system.data_type_families WHERE alias_to <> '' ORDER BY name ASC - - // AggregateFunction - Array("Array(String)", "[foo, bar]", false, false), - Date("Date", "2019-03-03", false, true), - DateTime("DateTime", "2019-03-03 13:37:42", false, true), - Decimal("Decimal(12,2)", "42.23", false, true), - // Decimal128 - // Decimal32 - // Decimal64 - Enum16("Enum16('foo'=0,'bar'=1)", "FOO", false, true), - Enum8("Enum8('foo'=0,'bar'=1)", "BAR", false, true), - FixedString("FixedString(3)", "BAZ", false, true), - Float32("Float32", "42.23", false, true), - Float64("Float64", "42.23", false, true), - IPv4("IPv4", "127.0.0.1", false, true), - IPv6("IPv6", "::1", false, true), - Int16("Int16", "1337", false, true), - Int32("Int32", "1337", false, true), - Int64("Int64", "1337", false, true), - Int8("Int8", "42", false, true), - // IntervalDay - // IntervalHour - // IntervalMinute - // IntervalMonth - // IntervalQuarter - // IntervalSecond - // IntervalWeek - // IntervalYear - // LowCardinality - // Nested - // Nothing - // Nullable - String("String", "foo", true, true), - Tuple("Tuple(UInt8, String)", "(42, 'foo')", false, true), - UInt16("UInt16", "42", false, true), - UInt32("UInt32", "23", false, true), - UInt64("UInt64", "1337", false, true), - UInt8("UInt8", "1", false, true), - UUID("UUID", "61f0c404-5cb3-11e7-907b-a6006ad3dba0", true, true); - - private final String typeName; - private final String serializedValue; - private final boolean lowCardinalityCandidate; - private final boolean nullableCandidate; - - ClickHouseTypesTestData(String typeName, String serializedValue, - boolean lowCardinalityCandidate, boolean nullableCandidate) - { - this.typeName = typeName; - this.serializedValue = serializedValue; - this.lowCardinalityCandidate = lowCardinalityCandidate; - this.nullableCandidate = nullableCandidate; - } - - private static String buildTestString() { - StringBuilder sb = new StringBuilder(); - // row 1: column names - for (ClickHouseTypesTestData t : values()) { - sb.append(t.typeName) - .append("\t"); - if (t.nullableCandidate) { - sb.append("Nullable(") - .append(t.typeName) - .append(')') - .append("\t"); - } - if (t.lowCardinalityCandidate) { - sb.append("LowCardinality(") - .append(t.typeName) - .append(')') - .append("\t"); - } - } - sb.replace(sb.length(), sb.length(), "\n"); - - // row 2: type names - sb.append(sb.substring(0, sb.length())); - - // row 3 : example data - for (ClickHouseTypesTestData t : values()) { - sb.append(t.serializedValue) - .append("\t"); - if (t.nullableCandidate) { - sb.append("\\N\t"); - } - if (t.lowCardinalityCandidate) { - sb.append(t.serializedValue) - .append("\t"); - } - } - sb.replace(sb.length(), sb.length(), "\n"); - return sb.toString(); - } - } - - private static Map> jdbcMappingTableB3() { - Map> map = new HashMap<>(); - map.put(JDBCType.CHAR, String.class); - map.put(JDBCType.VARCHAR, String.class); - map.put(JDBCType.LONGVARCHAR, String.class); - map.put(JDBCType.NUMERIC, BigDecimal.class); - map.put(JDBCType.DECIMAL, BigDecimal.class); - map.put(JDBCType.BIT, Boolean.class); - map.put(JDBCType.BOOLEAN, Boolean.class); - map.put(JDBCType.TINYINT, Integer.class); - map.put(JDBCType.SMALLINT, Integer.class); - map.put(JDBCType.INTEGER, Integer.class); - map.put(JDBCType.BIGINT, Long.class); - map.put(JDBCType.REAL, Float.class); - map.put(JDBCType.FLOAT, Double.class); // sic - map.put(JDBCType.DOUBLE, Double.class); - map.put(JDBCType.BINARY, byte[].class); - map.put(JDBCType.VARBINARY, byte[].class); - map.put(JDBCType.LONGVARBINARY, byte[].class); - map.put(JDBCType.DATE, Date.class); - map.put(JDBCType.TIME, Time.class); - map.put(JDBCType.TIMESTAMP, Timestamp.class); - map.put(JDBCType.DISTINCT, Object.class); - map.put(JDBCType.CLOB, Clob.class); - map.put(JDBCType.BLOB, Blob.class); - map.put(JDBCType.ARRAY, Array.class); - map.put(JDBCType.STRUCT, Struct.class); - map.put(JDBCType.REF, Ref.class); - map.put(JDBCType.DATALINK, URL.class); - map.put(JDBCType.JAVA_OBJECT, Object.class); - map.put(JDBCType.ROWID, RowId.class); - map.put(JDBCType.NCHAR, String.class); - map.put(JDBCType.NVARCHAR, String.class); - map.put(JDBCType.LONGNVARCHAR, String.class); - map.put(JDBCType.NCLOB, NClob.class); - map.put(JDBCType.SQLXML, SQLXML.class); - map.put(JDBCType.OTHER, Object.class); - return map; - } - - private static Map> jdbcMappingTableB1() { - Map> map = new HashMap<>(); - map.put(JDBCType.CHAR, String.class); - map.put(JDBCType.VARCHAR, String.class); - map.put(JDBCType.LONGVARCHAR, String.class); - map.put(JDBCType.NUMERIC, BigDecimal.class); - map.put(JDBCType.DECIMAL, BigDecimal.class); - map.put(JDBCType.BIT, boolean.class); - map.put(JDBCType.BOOLEAN, boolean.class); - map.put(JDBCType.TINYINT, byte.class); - map.put(JDBCType.SMALLINT, short.class); - map.put(JDBCType.INTEGER, int.class); - map.put(JDBCType.BIGINT, long.class); - map.put(JDBCType.REAL, float.class); - map.put(JDBCType.FLOAT, double.class); // sic - map.put(JDBCType.DOUBLE, double.class); - map.put(JDBCType.BINARY, byte[].class); - map.put(JDBCType.VARBINARY, byte[].class); - map.put(JDBCType.LONGVARBINARY, byte[].class); - map.put(JDBCType.DATE, Date.class); - map.put(JDBCType.TIME, Time.class); - map.put(JDBCType.TIMESTAMP, Timestamp.class); - map.put(JDBCType.DISTINCT, Object.class); - map.put(JDBCType.CLOB, Clob.class); - map.put(JDBCType.BLOB, Blob.class); - map.put(JDBCType.ARRAY, Array.class); - map.put(JDBCType.STRUCT, Struct.class); - map.put(JDBCType.REF, Ref.class); - map.put(JDBCType.DATALINK, URL.class); - map.put(JDBCType.JAVA_OBJECT, Object.class); - map.put(JDBCType.ROWID, RowId.class); - map.put(JDBCType.NCHAR, String.class); - map.put(JDBCType.NVARCHAR, String.class); - map.put(JDBCType.LONGNVARCHAR, String.class); - map.put(JDBCType.NCLOB, NClob.class); - map.put(JDBCType.SQLXML, SQLXML.class); - map.put(JDBCType.OTHER, Object.class); - return map; - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/ClickHouseScrollableResultSetTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/ClickHouseScrollableResultSetTest.java deleted file mode 100644 index e2649c024..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/ClickHouseScrollableResultSetTest.java +++ /dev/null @@ -1,212 +0,0 @@ -package ru.yandex.clickhouse.response; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.sql.ResultSet; -import java.util.TimeZone; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.ClickHouseStatement; -import ru.yandex.clickhouse.settings.ClickHouseProperties; - -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; -import static org.testng.AssertJUnit.assertEquals; - -public class ClickHouseScrollableResultSetTest extends ClickHouseResultSetTest { - - ClickHouseProperties props = new ClickHouseProperties(); - TimeZone tz = TimeZone.getDefault(); - - - @Override - @DataProvider(name = "longArrays") - public Object[][] longArrays() { - return new Object[][]{ - {"[0]", new long[]{0}}, - {"[333000111222,1024,-8521551,9223372036854775807,-9223372036854775808]", - new long[]{333000111222L, 1024, -8521551,9223372036854775807L,-9223372036854775808L}}, - {"[]", new long[]{}}, - }; - } - - @Override - @Test(groups = "unit") - public void testIsLast() throws Exception { - String response = - "SiteName\tcount()\n" + - "String\tUInt64\n" + - "hello.com\t21209048\n" + - "there.com\t49302091\n"; - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - - ResultSet rs = buildResultSet(is, 1024, "db", "table", false, null, null, props); - - rs.next(); - assertFalse(rs.isLast()); - rs.next(); - assertTrue(rs.isLast()); - assertFalse(rs.next()); - } - - @Test(groups = "unit") - public void testPrevious() throws Exception { - String response = - "SiteName\tcount()\n" + - "String\tUInt64\n" + - "hello.com\t21209048\n" + - "there.com\t49302091\n"; - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - - ResultSet rs = buildResultSet(is, 1024, "db", "table", false, null, null, props); - - rs.next(); - assertEquals("hello.com", rs.getString(1)); - assertEquals(21209048L, rs.getLong(2)); - - rs.next(); - assertEquals("there.com", rs.getString(1)); - assertEquals(49302091L, rs.getLong(2)); - - rs.previous(); - assertEquals("hello.com", rs.getString(1)); - assertEquals(21209048L, rs.getLong(2)); - } - - @Test(groups = "unit") - public void testAbsolute() throws Exception { - String response = - "SiteName\tcount()\n" + - "String\tUInt64\n" + - "hello.com\t21209048\n" + - "there.com\t49302091\n"; - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - - ResultSet rs = buildResultSet(is, 1024, "db", "table", false, null, null, props); - - rs.absolute(2); - assertEquals("there.com", rs.getString(1)); - assertEquals(49302091L, rs.getLong(2)); - - rs.absolute(1); - assertEquals("hello.com", rs.getString(1)); - assertEquals(21209048L, rs.getLong(2)); - - rs.absolute(-1); - assertEquals("there.com", rs.getString(1)); - assertEquals(49302091L, rs.getLong(2)); - - assertTrue(rs.isLast()); - - } - - public void testAbsoluteWithTotal() throws Exception { - String response = "SiteName\tcount()\n" + - "String\tUInt64\n" + - "hello.com\t21209048\n" + - "there.com\t49302091\n" + - "\n" + - "\t70511139\n"; - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - - ClickHouseResultSet rs = buildResultSet(is, 1024, "db", "table", false, null, null, props); - - rs.absolute(2); - assertEquals("there.com", rs.getString(1)); - assertEquals(49302091L, rs.getLong(2)); - - rs.absolute(1); - assertEquals("hello.com", rs.getString(1)); - assertEquals(21209048L, rs.getLong(2)); - - rs.absolute(-1); - assertEquals("there.com", rs.getString(1)); - assertEquals(49302091L, rs.getLong(2)); - - assertTrue(rs.isLast()); - - assertFalse(rs.absolute(3)); - assertTrue(rs.isAfterLast()); - - assertFalse(rs.absolute(-3)); - assertTrue(rs.isBeforeFirst()); - - assertFalse(rs.absolute(0)); - assertTrue(rs.isBeforeFirst()); - - rs.getTotals(); - assertEquals("", rs.getString(1)); - assertEquals(70511139L, rs.getLong(2)); - - } - - @Test(groups = "unit") - public void testRelative() throws Exception { - String response = - "SiteName\tcount()\n" + - "String\tUInt64\n" + - "hello.com\t21209048\n" + - "there.com\t49302091\n"; - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - - ResultSet rs = buildResultSet(is, 1024, "db", "table", false, null, null, props); - - rs.next(); - assertEquals("hello.com", rs.getString(1)); - assertEquals(21209048L, rs.getLong(2)); - - rs.relative(0); - assertEquals("hello.com", rs.getString(1)); - assertEquals(21209048L, rs.getLong(2)); - - rs.relative(1); - assertEquals("there.com", rs.getString(1)); - assertEquals(49302091L, rs.getLong(2)); - - rs.relative(-1); - assertEquals("hello.com", rs.getString(1)); - assertEquals(21209048L, rs.getLong(2)); - - assertFalse(rs.relative(5)); - assertFalse(rs.relative(-5)); - - } - - @Test(groups = "unit") - public void testBeforeFirst() throws Exception { - String response = - "SiteName\tcount()\n" + - "String\tUInt64\n" + - "hello.com\t21209048\n" + - "there.com\t49302091\n"; - - ByteArrayInputStream is = new ByteArrayInputStream(response.getBytes("UTF-8")); - - ClickHouseResultSet rs = buildResultSet(is, 1024, "db", "table", false, null, null, props); - - rs.next(); - assertEquals("hello.com", rs.getString(1)); - assertEquals(21209048L, rs.getLong(2)); - - rs.beforeFirst(); - rs.next(); - assertEquals("hello.com", rs.getString(1)); - assertEquals(21209048L, rs.getLong(2)); - - rs.afterLast(); - assertFalse(rs.hasNext()); - - } - - private static ClickHouseResultSet buildResultSet(InputStream is, int bufferSize, String db, String table, boolean usesWithTotals, ClickHouseStatement statement, TimeZone timezone, ClickHouseProperties properties) throws IOException { - return new ClickHouseScrollableResultSet(is, bufferSize, db, table, usesWithTotals, statement, timezone, properties); - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseBigDecimalParserTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseBigDecimalParserTest.java deleted file mode 100644 index 425a19771..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseBigDecimalParserTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.math.BigDecimal; -import java.sql.SQLException; - -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotEquals; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.fail; - -public class ClickHouseBigDecimalParserTest { - - private ClickHouseValueParser parser; - private ClickHouseColumnInfo columnInfo; - - @BeforeClass(groups = "unit") - public void setUp() throws Exception { - parser = ClickHouseValueParser.getParser(BigDecimal.class); - columnInfo = ClickHouseColumnInfo.parse("Float64", "column_name", null); - } - - @Test(groups = "unit") - public void testParseBigDecimal() throws Exception { - assertNull(parser.parse(ByteFragment.fromString("\\N"), columnInfo, null)); - assertNull(parser.parse(ByteFragment.fromString(""), columnInfo, null)); - assertEquals( - parser.parse(ByteFragment.fromString("0"), columnInfo, null), - BigDecimal.ZERO); - assertNotEquals( - parser.parse(ByteFragment.fromString("0.000"), columnInfo, null), - BigDecimal.ZERO); - assertEquals( - parser.parse(ByteFragment.fromString("0.000"), columnInfo, null), - BigDecimal.ZERO.setScale(3)); - assertEquals( - parser.parse(ByteFragment.fromString("42.23"), columnInfo, null), - BigDecimal.valueOf(42.23)); - assertNotEquals( - parser.parse(ByteFragment.fromString("42.230"), columnInfo, null), - BigDecimal.valueOf(42.23)); - assertEquals( - parser.parse(ByteFragment.fromString("-42.23"), columnInfo, null), - BigDecimal.valueOf(-42.23)); - try { - parser.parse(ByteFragment.fromString("foo"), columnInfo, null); - fail(); - } catch (SQLException sqle) { - // expected - } - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseDoubleParserTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseDoubleParserTest.java deleted file mode 100644 index 551e772d0..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseDoubleParserTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNull; - -public class ClickHouseDoubleParserTest { - - private ClickHouseDoubleParser parser; - private ClickHouseColumnInfo columnInfo; - - @BeforeClass(groups = "unit") - public void setUp() { - parser = ClickHouseDoubleParser.getInstance(); - columnInfo = ClickHouseColumnInfo.parse("Float64", "columnName", null); - } - - @Test(groups = "unit") - public void testParseDouble() throws Exception { - assertNull(parse("\\N")); - assertEquals(parse("0"), Double.valueOf(0.0)); - assertEquals(parse("-1.23"), Double.valueOf(-1.23)); - assertEquals(parse("1.23"), Double.valueOf(1.23)); - assertEquals(parse("nan"), Double.valueOf(Double.NaN)); - assertEquals(parse("NaN"), Double.valueOf(Double.NaN)); - assertEquals(parse("inf"), Double.valueOf(Double.POSITIVE_INFINITY)); - assertEquals(parse("+inf"), Double.valueOf(Double.POSITIVE_INFINITY)); - assertEquals(parse("-inf"), Double.valueOf(Double.NEGATIVE_INFINITY)); - } - - @Test(groups = "unit") - public void testParseDefault() throws Exception { - assertEquals(parseWithDefault("\\N"), Double.valueOf(0)); - assertEquals(parseWithDefault("nan"), Double.valueOf(Double.NaN)); - } - - private Double parse(String s) throws Exception { - return parser.parse(ByteFragment.fromString(s), columnInfo, null); - } - - private Double parseWithDefault(String s) throws Exception { - return parser.parseWithDefault(ByteFragment.fromString(s), columnInfo, null); - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseInstantParserTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseInstantParserTest.java deleted file mode 100644 index 2e09b0eed..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseInstantParserTest.java +++ /dev/null @@ -1,152 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.math.BigInteger; -import java.time.Instant; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.util.TimeZone; - -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.domain.ClickHouseDataType; -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -import static org.testng.Assert.assertEquals; - -public class ClickHouseInstantParserTest { - - private TimeZone tzLosAngeles; - private TimeZone tzBerlin; - private ClickHouseInstantParser parser; - - @BeforeClass(groups = "unit") - public void setUp() { - parser = ClickHouseInstantParser.getInstance(); - tzLosAngeles = TimeZone.getTimeZone("America/Los_Angeles"); - tzBerlin = TimeZone.getTimeZone("Europe/Berlin"); - } - - @Test(groups = "unit") - public void testParseInstantDateTime() throws Exception { - Instant inst = parser.parse( - ByteFragment.fromString("2020-01-20 22:23:24"), - ClickHouseColumnInfo.parse("DateTime", "col", tzBerlin), tzBerlin); - assertEquals( - inst.getEpochSecond(), - 1579555404); - inst = parser.parse( - ByteFragment.fromString("2020-01-20 22:23:24"), - ClickHouseColumnInfo.parse("DateTime", "col", tzLosAngeles), tzLosAngeles); - assertEquals( - inst.getEpochSecond(), - 1579587804); - } - - @Test(groups = "unit") - public void testParseInstantDateTimeColumnOverride() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - "DateTime(Europe/Berlin)", "col", TimeZone.getTimeZone("Asia/Chongqing")); - Instant inst = parser.parse( - ByteFragment.fromString("2020-01-20 22:23:24"), columnInfo, tzLosAngeles); - assertEquals( - inst.getEpochSecond(), - 1579555404); - } - - @Test(groups = "unit") - public void testParseInstantDate() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - "Date", "col", null); - Instant inst = parser.parse( - ByteFragment.fromString("2020-01-20"), columnInfo, tzLosAngeles); - assertEquals( - inst.getEpochSecond(), - 1579478400); - } - - @Test( - groups = "unit", - dataProvider = ClickHouseTimeParserTestDataProvider.OTHER_DATA_TYPES, - dataProviderClass = ClickHouseTimeParserTestDataProvider.class) - public void testParseInstantTimestampSeconds(ClickHouseDataType dataType) throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - dataType.name(), "col", null); - Instant inst = parser.parse( - ByteFragment.fromString("1579507200"), columnInfo, tzLosAngeles); - assertEquals( - inst.getEpochSecond(), - 1579507200); - inst = parser.parse( - ByteFragment.fromString("1579507200"), columnInfo, tzBerlin); - assertEquals( - inst.getEpochSecond(), - 1579507200); - } - - @Test( - groups = "unit", - dataProvider = ClickHouseTimeParserTestDataProvider.OTHER_DATA_TYPES, - dataProviderClass = ClickHouseTimeParserTestDataProvider.class) - public void parseInstantTimestampMillis(ClickHouseDataType dataType) throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - dataType.name(), "col", null); - Instant inst = parser.parse( - ByteFragment.fromString("1579507200000"), columnInfo, tzLosAngeles); - assertEquals( - inst.getEpochSecond(), - 1579507200); - inst = parser.parse( - ByteFragment.fromString("1579507200"), columnInfo, tzBerlin); - assertEquals( - inst.getEpochSecond(), - 1579507200); - } - - @Test(groups = "unit") - public void testParseInstantString() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - "String", "col", null); - Instant inst = parser.parse( - ByteFragment.fromString("2020-01-20T22:23:24.123"), columnInfo, tzLosAngeles); - assertEquals( - inst.getEpochSecond(), - 1579587804); - inst = parser.parse( - ByteFragment.fromString("2020-01-20T22:23:24.123+01:00"), columnInfo, tzLosAngeles); - assertEquals( - inst.getEpochSecond(), - 1579555404); - } - - @Test(groups = "unit") - public void testParseInstantUInt64Overflow() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - "UInt64", "col", null); - Instant inst = parser.parse( - ByteFragment.fromString( - BigInteger.valueOf(Long.MAX_VALUE) - .add(BigInteger.valueOf(1337 * 100_000L)) - .toString()), - columnInfo, - tzLosAngeles); - assertEquals( - inst.atZone(ZoneId.of("UTC")), - ZonedDateTime.of( - 2262, 4, 11, 23, 47, 16, 988000000, ZoneId.of("UTC"))); - } - - @Test(groups = "unit") - public void testParseInstantUInt64Millis() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - "UInt64", "col", null); - Instant inst = parser.parse( - ByteFragment.fromString("9223372036854"), columnInfo, tzLosAngeles); - assertEquals( - inst.atZone(ZoneId.of("UTC")), - ZonedDateTime.of( - 2262, 4, 11, 23, 47, 16, 854000000, ZoneId.of("UTC"))); - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseLocalDateParserTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseLocalDateParserTest.java deleted file mode 100644 index 4992d8894..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseLocalDateParserTest.java +++ /dev/null @@ -1,227 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.sql.SQLException; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.TimeZone; - -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.domain.ClickHouseDataType; -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.fail; - -public class ClickHouseLocalDateParserTest { - - private TimeZone tzLosAngeles; - private TimeZone tzBerlin; - private ClickHouseLocalDateParser parser; - - @BeforeClass(groups = "unit") - public void setUp() { - tzLosAngeles = TimeZone.getTimeZone("America/Los_Angeles"); - tzBerlin = TimeZone.getTimeZone("Europe/Berlin"); - parser = ClickHouseLocalDateParser.getInstance(); - } - - @Test(groups = "unit") - public void testParseLocalDateNull() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse("Date", "col", null); - try { - parser.parse( - null, columnInfo, tzBerlin); - } catch (NullPointerException npe) { - // should be handled before calling the parser - } - } - - @Test(groups = "unit") - public void testParseLocalDateDate() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse("Date", "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12"), columnInfo, null), - LocalDate.of(2020, 1, 12)); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12"), columnInfo, tzLosAngeles), - LocalDate.of(2020, 1, 12)); - // local stays local - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12"), columnInfo, tzBerlin), - LocalDate.of(2020, 1, 12)); - assertNull( - parser.parse( - ByteFragment.fromString("0000-00-00"), columnInfo, tzLosAngeles)); - } - - @Test(groups = "unit") - public void testParseLocalDateDateNullable() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse("Nullable(Date)", "col", null); - assertNull( - parser.parse( - ByteFragment.fromString("0000-00-00"), columnInfo, tzLosAngeles)); - } - - @Test(groups = "unit") - public void testParseLocalDateDateTime() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse("DateTime", "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12 01:02:03"), columnInfo, null), - LocalDate.of(2020, 1, 12)); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12 22:23:24"), columnInfo, tzLosAngeles), - LocalDate.of(2020, 1, 12)); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12 22:23:24"), columnInfo, tzBerlin), - LocalDate.of(2020, 1, 12)); - assertNull( - parser.parse( - ByteFragment.fromString("0000-00-00 00:00:00"), columnInfo, null)); - } - - @Test(groups = "unit") - public void testParseLocalDateDateTimeTZColumn() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse("DateTime(Europe/Berlin)", "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12 01:02:03"), columnInfo, null), - LocalDate.of(2020, 1, 12)); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12 22:23:24"), columnInfo, tzLosAngeles), - LocalDate.of(2020, 1, 12)); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12 22:23:24"), columnInfo, tzBerlin), - LocalDate.of(2020, 1, 12)); - assertNull( - parser.parse( - ByteFragment.fromString("0000-00-00 00:00:00"), columnInfo, null)); - } - - @Test( - groups = "unit", - dataProvider = ClickHouseTimeParserTestDataProvider.OTHER_DATA_TYPES, - dataProviderClass = ClickHouseTimeParserTestDataProvider.class) - public void testParseLocalDateNumber(ClickHouseDataType dataType) throws Exception { - - // Instant in LA time zone - Instant instant = LocalDateTime.of(2020, 1, 12, 22, 23, 24) - .atZone(tzLosAngeles.toZoneId()) - .toInstant(); - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse(dataType.name(), "col", null); - - // same time zone: no problem - assertEquals( - parser.parse( - ByteFragment.fromString(String.valueOf(instant.getEpochSecond())), - columnInfo, - tzLosAngeles), - LocalDate.of(2020, 1, 12)); - - // different time zone: different date - assertEquals( - parser.parse( - ByteFragment.fromString(String.valueOf(instant.getEpochSecond())), - columnInfo, - tzBerlin), - LocalDate.of(2020, 1, 13)); - - try { - parser.parse( - ByteFragment.fromString("ABC"), columnInfo, null); - fail(); - } catch (SQLException sqle) { - // expected - } - - try { - parser.parse( - ByteFragment.fromString("3.14159265359"), columnInfo, null); - fail(); - } catch (SQLException sqle) { - // expected - } - - assertNull( - parser.parse( - ByteFragment.fromString(String.valueOf(0)), columnInfo, tzBerlin)); - } - - @Test(groups = "unit") - public void testParseLocalDateNumberNegative() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse(ClickHouseDataType.Int64.name(), "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString(String.valueOf(-386384400)), - columnInfo, tzBerlin), - LocalDate.of(1957, 10, 4)); - } - - @Test(groups = "unit") - public void testParseLocalDateOtherLikeDate() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse(ClickHouseDataType.Unknown.name(), "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-13"), columnInfo, null), - LocalDate.of(2020, 1, 13)); - try { - parser.parse( - ByteFragment.fromString("2020-1-13"), columnInfo, null); - fail(); - } catch (SQLException sqle) { - // expected - } - try { - parser.parse( - ByteFragment.fromString("2020-01-42"), columnInfo, null); - fail(); - } catch (SQLException sqle) { - // expected - } - } - - @Test(groups = "unit") - public void testParseLocalDateOtherLikeDateTime() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse(ClickHouseDataType.Unknown.name(), "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-13 22:23:24"), columnInfo, null), - LocalDate.of(2020, 1, 13)); - try { - parser.parse( - ByteFragment.fromString("2020-1-13 22:23:24"), columnInfo, null); - fail(); - } catch (SQLException sqle) { - // expected - } - try { - parser.parse( - ByteFragment.fromString("2020-01-42 22:23:24"), columnInfo, null); - fail(); - } catch (SQLException sqle) { - // expected - } - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseLocalDateTimeParserTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseLocalDateTimeParserTest.java deleted file mode 100644 index 8ebef8beb..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseLocalDateTimeParserTest.java +++ /dev/null @@ -1,246 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.util.TimeZone; - -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.domain.ClickHouseDataType; -import ru.yandex.clickhouse.except.ClickHouseException; -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.fail; - -public class ClickHouseLocalDateTimeParserTest { - - private TimeZone tzLosAngeles; - private TimeZone tzBerlin; - private ClickHouseLocalDateTimeParser parser; - - @BeforeClass(groups = "unit") - public void setUp() { - tzLosAngeles = TimeZone.getTimeZone("America/Los_Angeles"); - tzBerlin = TimeZone.getTimeZone("Europe/Berlin"); - parser = ClickHouseLocalDateTimeParser.getInstance(); - } - - @Test(groups = "unit") - public void testParseLocalDateTimeNull() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse("Date", "col", null); - try { - parser.parse( - null, columnInfo, tzBerlin); - fail(); - } catch (NullPointerException npe) { - // should be handled before calling the parser - } - } - - @Test(groups = "unit") - public void testParseLocalDateTimeDate() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse("Date", "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12"), columnInfo, null), - LocalDate.of(2020, 1, 12).atStartOfDay()); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12"), columnInfo, tzLosAngeles), - LocalDate.of(2020, 1, 12).atStartOfDay()); - // local stays local - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12"), columnInfo, tzBerlin), - LocalDate.of(2020, 1, 12).atStartOfDay()); - assertNull( - parser.parse( - ByteFragment.fromString("0000-00-00"), columnInfo, tzLosAngeles)); - } - - @Test(groups = "unit") - public void testParseLocalDateTimeDateTimeNullable() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse("Nullable(DateTime)", "col", null); - assertNull( - parser.parse( - ByteFragment.fromString("0000-00-00 00:00:00"), columnInfo, tzLosAngeles)); - } - - @Test(groups = "unit") - public void testParseLocalDateTimeDateTime() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse("DateTime", "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12 01:02:03"), columnInfo, null), - LocalDateTime.of(2020, 1, 12, 1, 2, 3)); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12 22:23:24"), columnInfo, tzLosAngeles), - LocalDateTime.of(2020, 1, 12, 22, 23, 24)); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12 22:23:24"), columnInfo, tzBerlin), - LocalDateTime.of(2020, 1, 12, 22, 23, 24)); - assertNull( - parser.parse( - ByteFragment.fromString("0000-00-00 00:00:00"), columnInfo, null)); - } - - /* - * No automatic conversion into any time zone, simply local date time - */ - @Test(groups = "unit") - public void testParseLocalDateTimeDateTimeTZColumn() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse("DateTime(Europe/Berlin)", "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12 01:02:03"), columnInfo, null), - LocalDateTime.of(2020, 1, 12, 0, 2, 3)); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12 22:23:24"), columnInfo, tzLosAngeles), - LocalDateTime.of(2020, 1, 12, 21, 23, 24)); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12 22:23:24"), columnInfo, tzBerlin), - LocalDateTime.of(2020, 1, 12, 21, 23, 24)); - assertNull( - parser.parse( - ByteFragment.fromString("0000-00-00 00:00:00"), columnInfo, null)); - } - - @Test( - groups = "unit", - dataProvider = ClickHouseTimeParserTestDataProvider.OTHER_DATA_TYPES, - dataProviderClass = ClickHouseTimeParserTestDataProvider.class) - public void testParseLocalDateTimeNumber(ClickHouseDataType dataType) throws Exception { - // Instant in LA time zone - Instant instant = LocalDateTime.of(2020, 1, 12, 22, 23, 24) - .atZone(tzLosAngeles.toZoneId()) - .toInstant(); - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse(dataType.name(), "col", null); - - // same time zone: no problem - assertEquals( - parser.parse( - ByteFragment.fromString( - String.valueOf(instant.getEpochSecond())), - columnInfo, - tzLosAngeles), - LocalDateTime.of(2020, 1, 12, 22, 23, 24)); - - // different time zone: different date - assertEquals( - parser.parse( - ByteFragment.fromString( - String.valueOf(instant.getEpochSecond())), - columnInfo, - tzBerlin), - LocalDateTime.of(2020, 1, 13, 7, 23, 24)); - - try { - parser.parse( - ByteFragment.fromString( - String.valueOf(instant.getEpochSecond())), - columnInfo, - null); - fail(); - } catch (ClickHouseException che) { - // time zone for parsing required - } - - try { - parser.parse( - ByteFragment.fromString("ABC"), columnInfo, null); - fail(); - } catch (ClickHouseException che) { - // expected - } - - try { - parser.parse( - ByteFragment.fromString("3.14159265359"), columnInfo, null); - fail(); - } catch (ClickHouseException che) { - // expected - } - - assertNull(parser.parse( - ByteFragment.fromString(String.valueOf(0)), columnInfo, tzBerlin)); - } - - @Test(groups = "unit") - public void testParseLocalDateTimeNumberNegative() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse(ClickHouseDataType.Int64.name(), "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString(String.valueOf(-386384400)), columnInfo, tzBerlin), - LocalDate.of(1957, 10, 4).atStartOfDay()); - } - - @Test(groups = "unit") - public void testParseLocalDateTimeOtherLikeDate() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse(ClickHouseDataType.Unknown.name(), "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-13"), columnInfo, null), - LocalDate.of(2020, 1, 13).atStartOfDay()); - try { - parser.parse( - ByteFragment.fromString("2020-1-13"), columnInfo, null); - fail(); - } catch (ClickHouseException che) { - // illegal format - } - try { - parser.parse( - ByteFragment.fromString("2020-01-42"), columnInfo, null); - fail(); - } catch (ClickHouseException che) { - // illegal format - } - } - - @Test(groups = "unit") - public void testParseLocalDateTimeOtherLikeDateTime() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse(ClickHouseDataType.Unknown.name(), "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-13 22:23:24"), columnInfo, null), - LocalDateTime.of(LocalDate.of(2020, 1, 13), LocalTime.of(22, 23, 24))); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-13T22:23:24"), columnInfo, null), - LocalDateTime.of(LocalDate.of(2020, 1, 13), LocalTime.of(22, 23, 24))); - try { - parser.parse( - ByteFragment.fromString("2020-1-13 22:23:24"), columnInfo, null); - fail(); - } catch (ClickHouseException che) { - // illegal format - } - try { - parser.parse( - ByteFragment.fromString("2020-01-42 22:23:24"), columnInfo, null); - fail(); - } catch (ClickHouseException che) { - // illegal format - } - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseLocalTimeParserTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseLocalTimeParserTest.java deleted file mode 100644 index 7f3b15757..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseLocalTimeParserTest.java +++ /dev/null @@ -1,195 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.time.LocalTime; -import java.util.TimeZone; - -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.domain.ClickHouseDataType; -import ru.yandex.clickhouse.except.ClickHouseException; -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.fail; - -public class ClickHouseLocalTimeParserTest { - - private TimeZone tzBerlin; - private TimeZone tzLosAngeles; - private ClickHouseLocalTimeParser parser; - - @BeforeClass(groups = "unit") - public void setUp() { - tzBerlin = TimeZone.getTimeZone("Europe/Berlin"); - tzLosAngeles = TimeZone.getTimeZone("America/Los_Angeles"); - parser = ClickHouseLocalTimeParser.getInstance(); - } - - @Test(groups = "unit") - public void testParseLocalTimeDate() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse("Date", "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-17"), columnInfo, tzBerlin), - LocalTime.MIDNIGHT); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-17"), columnInfo, tzLosAngeles), - LocalTime.MIDNIGHT); - } - - @Test(groups = "unit") - public void testParseLocalTimeDateTime() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse("DateTime", "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-17 22:23:24"), columnInfo, tzBerlin), - LocalTime.of(22, 23, 24)); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-17 22:23:24"), columnInfo, tzLosAngeles), - LocalTime.of(22, 23, 24)); - } - - /* - * No automatic conversion into any time zone, simply local time - */ - @Test(groups = "unit") - public void testParseLocalTimeDateTimeColumnTimeZone() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse("DateTime(Asia/Vladivostok)", "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-17 22:23:24"), columnInfo, tzBerlin), - LocalTime.of(12, 23, 24)); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-17 22:23:24"), columnInfo, tzLosAngeles), - LocalTime.of(12, 23, 24)); - } - - @Test( - groups = "unit", - dataProvider = ClickHouseTimeParserTestDataProvider.OTHER_DATA_TYPES, - dataProviderClass = ClickHouseTimeParserTestDataProvider.class) - public void testParseLocalTimeNumber(ClickHouseDataType dataType) throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse(dataType.name(), "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("222324"), columnInfo, null), - LocalTime.of(22, 23, 24)); - assertEquals( - parser.parse( - ByteFragment.fromString("2223"), columnInfo, null), - LocalTime.of(22, 23)); - assertEquals( - parser.parse( - ByteFragment.fromString("22"), columnInfo, null), - LocalTime.of(22, 0)); - assertEquals( - parser.parse( - ByteFragment.fromString("5"), columnInfo, null), - LocalTime.of(5, 0)); - assertNull( - parser.parse( - ByteFragment.fromString("0"), columnInfo, null)); - - try { - parser.parse( - ByteFragment.fromString("-42"), columnInfo, null); - fail(); - } catch (ClickHouseException che) { - // does not make sense - } - try { - parser.parse( - ByteFragment.fromString("42"), columnInfo, null); - fail(); - } catch (ClickHouseException che) { - // does not make sense - } - } - - @Test(groups = "unit") - public void testParseLocalTimeString() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse(ClickHouseDataType.String.name(), "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("22:23:24"), columnInfo, null), - LocalTime.of(22, 23, 24)); - assertEquals( - parser.parse( - ByteFragment.fromString("22:23:24.123"), columnInfo, null), - LocalTime.of(22, 23, 24, 123 * 1000 * 1000)); - assertEquals( - parser.parse( - ByteFragment.fromString("22:23"), columnInfo, null), - LocalTime.of(22, 23)); - assertEquals( - parser.parse( - ByteFragment.fromString("22"), columnInfo, null), - LocalTime.of(22, 0)); - assertEquals( - parser.parse( - ByteFragment.fromString("0022"), columnInfo, null), - LocalTime.of(0, 22)); - assertEquals( - parser.parse( - ByteFragment.fromString("002223"), columnInfo, null), - LocalTime.of(0, 22, 23)); - assertEquals( - parser.parse( - ByteFragment.fromString("00:22:23"), columnInfo, null), - LocalTime.of(0, 22, 23)); - assertEquals( - parser.parse( - ByteFragment.fromString("000000"), columnInfo, null), - LocalTime.MIDNIGHT); - assertEquals( - parser.parse( - ByteFragment.fromString("00:00:00"), columnInfo, null), - LocalTime.MIDNIGHT); - assertEquals( - parser.parse( - ByteFragment.fromString("00:00"), columnInfo, null), - LocalTime.MIDNIGHT); - assertEquals( - parser.parse( - ByteFragment.fromString("13:37:42"), columnInfo, null), - LocalTime.of(13, 37, 42)); - assertEquals( - parser.parse( - ByteFragment.fromString("13:37:42.107"), columnInfo, null), - LocalTime.of(13, 37, 42, 107000000)); - assertEquals( - parser.parse( - ByteFragment.fromString("13:37:42"), columnInfo, tzBerlin), - LocalTime.of(13, 37, 42)); - assertEquals( - parser.parse( - ByteFragment.fromString("13:37:42"), columnInfo, tzLosAngeles), - LocalTime.of(13, 37, 42)); - assertEquals( - parser.parse( - ByteFragment.fromString("13:37:42+02:00"), columnInfo, null), - LocalTime.of(13, 37, 42)); - assertEquals( - parser.parse( - ByteFragment.fromString("13:37:42Z"), columnInfo, null), - LocalTime.of(13, 37, 42)); - assertEquals( - parser.parse( - ByteFragment.fromString("13:37:42+02:00"), columnInfo, tzLosAngeles), - LocalTime.of(13, 37, 42)); - assertEquals( - parser.parse( - ByteFragment.fromString("13:37:42+02:00"), columnInfo, tzBerlin), - LocalTime.of(13, 37, 42)); - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseMapParserTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseMapParserTest.java deleted file mode 100644 index 0d2368ba9..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseMapParserTest.java +++ /dev/null @@ -1,130 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.math.BigInteger; -import java.util.Map; -import java.util.TimeZone; - -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.domain.ClickHouseDataType; -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; -import ru.yandex.clickhouse.util.Utils; - -import static org.testng.Assert.assertEquals; - -public class ClickHouseMapParserTest { - @Test(groups = "unit") - public void testReadPart() throws Exception { - ClickHouseMapParser parser = ClickHouseMapParser.getInstance(); - String s; - StringBuilder sb = new StringBuilder(); - int index = parser.readPart(ClickHouseDataType.String, s = " '' ", 0, s.length(), sb, ':'); - assertEquals(sb.toString(), ""); - - sb.setLength(0); - index = parser.readPart(ClickHouseDataType.String, s = "''", 0, s.length(), sb, ':'); - assertEquals(sb.toString(), ""); - - sb.setLength(0); - index = parser.readPart(ClickHouseDataType.String, s = "'':123", 0, s.length(), sb, ':'); - assertEquals(sb.toString(), ""); - - sb.setLength(0); - index = parser.readPart(ClickHouseDataType.String, s = "''}", 0, s.length(), sb, ':'); - assertEquals(sb.toString(), ""); - - sb.setLength(0); - index = parser.readPart(ClickHouseDataType.String, s = " '1''\\'' : 1", 0, s.length(), sb, ':'); - assertEquals(sb.toString(), "1''\\'"); - - sb.setLength(0); - index = parser.readPart(ClickHouseDataType.Int16, s = " 123 ", 0, s.length(), sb, ':'); - assertEquals(sb.toString(), s.trim()); - - sb.setLength(0); - index = parser.readPart(ClickHouseDataType.Int16, s = "123", 0, s.length(), sb, ':'); - assertEquals(sb.toString(), s.trim()); - - sb.setLength(0); - index = parser.readPart(ClickHouseDataType.Int16, s = "123:'aa'", 0, s.length(), sb, ':'); - assertEquals(sb.toString(), "123"); - - sb.setLength(0); - index = parser.readPart(ClickHouseDataType.Int16, s = "123}", 0, s.length(), sb, ':'); - assertEquals(sb.toString(), "123"); - - // now complex data types like Array, Tuple and Map - sb.setLength(0); - index = parser.readPart(ClickHouseDataType.Array, s = "[]", 0, s.length(), sb, ','); - assertEquals(sb.toString(), s); - - sb.setLength(0); - index = parser.readPart(ClickHouseDataType.Array, s = "[1,2,3]", 0, s.length(), sb, ','); - assertEquals(sb.toString(), s); - - sb.setLength(0); - index = parser.readPart(ClickHouseDataType.Array, s = "[1,2,3],", 0, s.length(), sb, ','); - assertEquals(sb.toString(), "[1,2,3]"); - - sb.setLength(0); - index = parser.readPart(ClickHouseDataType.Tuple, s = "()", 0, s.length(), sb, ','); - assertEquals(sb.toString(), s); - - sb.setLength(0); - index = parser.readPart(ClickHouseDataType.Tuple, s = "(1,2,3)", 0, s.length(), sb, ','); - assertEquals(sb.toString(), s); - - sb.setLength(0); - index = parser.readPart(ClickHouseDataType.Tuple, s = "(1,2,3),", 0, s.length(), sb, ','); - assertEquals(sb.toString(), "(1,2,3)"); - - sb.setLength(0); - index = parser.readPart(ClickHouseDataType.Map, s = "{}", 0, s.length(), sb, ','); - assertEquals(sb.toString(), s); - - sb.setLength(0); - index = parser.readPart(ClickHouseDataType.Map, s = "{1:2,3:4}", 0, s.length(), sb, ','); - assertEquals(sb.toString(), s); - - sb.setLength(0); - index = parser.readPart(ClickHouseDataType.Map, s = "{1:2,3:4},", 0, s.length(), sb, ','); - assertEquals(sb.toString(), "{1:2,3:4}"); - - // mixed - sb.setLength(0); - index = parser.readPart(ClickHouseDataType.Array, s = "['a,b', '[1,2]']", 0, s.length(), sb, ','); - assertEquals(sb.toString(), s); - - sb.setLength(0); - index = parser.readPart(ClickHouseDataType.Array, s = "[[[[[]]]]]", 0, s.length(), sb, ','); - assertEquals(sb.toString(), s); - } - - @Test(groups = "unit") - public void testParse() throws Exception { - ClickHouseMapParser parser = ClickHouseMapParser.getInstance(); - Map result = parser.parse(ByteFragment.fromString("{'a': 1, 'a''\\\\\\'b':2}"), - ClickHouseColumnInfo.parse("Map(String, Int8)", "dunno", TimeZone.getTimeZone("Asia/Chongqing")), - TimeZone.getDefault()); - assertEquals(result, Utils.mapOf("a", 1, "a''\\'b", 2)); - - result = parser.parse(ByteFragment.fromString("{'a': '1', 'a''\\\\\\'b':'1''\\\\\\'2'}"), - ClickHouseColumnInfo.parse("Map(String, String)", "dunno", TimeZone.getTimeZone("Asia/Chongqing")), - TimeZone.getDefault()); - assertEquals(result, Utils.mapOf("a", "1", "a''\\'b", "1''\\'2")); - - result = parser.parse(ByteFragment.fromString("{123: '1a1', -456:'331'}"), - ClickHouseColumnInfo.parse("Map(Int16, String)", "dunno", TimeZone.getTimeZone("Asia/Chongqing")), - TimeZone.getDefault()); - assertEquals(result, Utils.mapOf(123, "1a1", -456, "331")); - - result = parser.parse( - ByteFragment - .fromString("{123: 1111111111111111111111111111111111111, -456:222222222222222222222222222}"), - ClickHouseColumnInfo.parse("Map(Int16, UInt256)", "dunno", TimeZone.getTimeZone("Asia/Chongqing")), - TimeZone.getDefault()); - assertEquals(result, Utils.mapOf(123, new BigInteger("1111111111111111111111111111111111111"), -456, - new BigInteger("222222222222222222222222222"))); - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseOffsetDateTimeParserTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseOffsetDateTimeParserTest.java deleted file mode 100644 index 9b62dcc8c..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseOffsetDateTimeParserTest.java +++ /dev/null @@ -1,120 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.time.OffsetDateTime; -import java.util.TimeZone; - -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.domain.ClickHouseDataType; -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -import static org.testng.Assert.assertEquals; - -public class ClickHouseOffsetDateTimeParserTest { - - private TimeZone tzLosAngeles; - private TimeZone tzBerlin; - private ClickHouseOffsetDateTimeParser parser; - - @BeforeClass(groups = "unit") - public void setUp() { - tzLosAngeles = TimeZone.getTimeZone("America/Los_Angeles"); - tzBerlin = TimeZone.getTimeZone("Europe/Berlin"); - parser = ClickHouseOffsetDateTimeParser.getInstance(); - } - - @Test(groups = "unit") - public void testParseOffsetDateTimeDateTime() throws Exception { - OffsetDateTime inst = parser.parse( - ByteFragment.fromString("2020-01-20 22:23:24"), - ClickHouseColumnInfo.parse("DateTime", "col", tzBerlin), tzBerlin); - assertEquals( - inst.toInstant().getEpochSecond(), - 1579555404); - inst = parser.parse( - ByteFragment.fromString("2020-01-20 22:23:24"), - ClickHouseColumnInfo.parse("DateTime", "col", tzLosAngeles), tzLosAngeles); - assertEquals( - inst.toInstant().getEpochSecond(), - 1579587804); - } - - @Test(groups = "unit") - public void testParseOffsetDateTimeDateTimeColumnOverride() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - "DateTime(Europe/Berlin)", "col", null); - OffsetDateTime inst = parser.parse( - ByteFragment.fromString("2020-01-20 22:23:24"), columnInfo, tzLosAngeles); - assertEquals( - inst.toInstant().getEpochSecond(), - 1579555404); - } - - @Test(groups = "unit") - public void testParseOffsetDateTimeDate() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - "Date", "col", null); - OffsetDateTime inst = parser.parse( - ByteFragment.fromString("2020-01-20"), columnInfo, tzLosAngeles); - assertEquals( - inst.toInstant().getEpochSecond(), - 1579507200); - } - - @Test( - groups = "unit", - dataProvider = ClickHouseTimeParserTestDataProvider.OTHER_DATA_TYPES, - dataProviderClass = ClickHouseTimeParserTestDataProvider.class) - public void parseOffsetDateTimeTimestampSeconds(ClickHouseDataType dataType) throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - dataType.name(), "col", null); - OffsetDateTime inst = parser.parse( - ByteFragment.fromString("1579507200"), columnInfo, tzLosAngeles); - assertEquals( - inst.toInstant().getEpochSecond(), - 1579507200); - inst = parser.parse( - ByteFragment.fromString("1579507200"), columnInfo, tzBerlin); - assertEquals( - inst.toInstant().getEpochSecond(), - 1579507200); - } - - @Test( - groups = "unit", - dataProvider = ClickHouseTimeParserTestDataProvider.OTHER_DATA_TYPES, - dataProviderClass = ClickHouseTimeParserTestDataProvider.class) - public void parseOffsetDateTimeTimestampMillis(ClickHouseDataType dataType) throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - dataType.name(), "col", null); - OffsetDateTime inst = parser.parse( - ByteFragment.fromString("1579507200000"), columnInfo, tzLosAngeles); - assertEquals( - inst.toInstant().getEpochSecond(), - 1579507200); - inst = parser.parse(ByteFragment.fromString( - "1579507200"), columnInfo, tzBerlin); - assertEquals( - inst.toInstant().getEpochSecond(), - 1579507200); - } - - @Test(groups = "unit") - public void testParseOffsetDateTimeString() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - "String", "col", null); - OffsetDateTime inst = parser.parse( - ByteFragment.fromString("2020-01-20T22:23:24.123"), columnInfo, tzLosAngeles); - assertEquals( - inst.toInstant().getEpochSecond(), - 1579587804); - inst = parser.parse( - ByteFragment.fromString("2020-01-20T22:23:24.123+01:00"), columnInfo, tzLosAngeles); - assertEquals( - inst.toInstant().getEpochSecond(), - 1579555404); - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseOffsetTimeParserTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseOffsetTimeParserTest.java deleted file mode 100644 index 7d89e1b60..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseOffsetTimeParserTest.java +++ /dev/null @@ -1,190 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.util.TimeZone; - -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.domain.ClickHouseDataType; -import ru.yandex.clickhouse.except.ClickHouseException; -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.fail; - -public class ClickHouseOffsetTimeParserTest { - - private TimeZone tzBerlin; - private TimeZone tzLosAngeles; - private ZoneOffset offsetBerlin; - private ZoneOffset offsetLosAngeles; - private ZoneOffset offsetJVM; - private ClickHouseOffsetTimeParser parser; - - @BeforeClass(groups = "unit") - public void setUp() { - tzBerlin = TimeZone.getTimeZone("Europe/Berlin"); - offsetBerlin = tzBerlin.toZoneId().getRules().getOffset( - LocalDateTime.of(LocalDate.of(2020,01,17), LocalTime.MIDNIGHT)); - tzLosAngeles = TimeZone.getTimeZone("America/Los_Angeles"); - offsetLosAngeles = tzLosAngeles.toZoneId().getRules().getOffset( - LocalDateTime.of(LocalDate.of(2020,01,17), LocalTime.MIDNIGHT)); - offsetJVM = ZoneId.systemDefault().getRules().getOffset(Instant.now()); - parser = ClickHouseOffsetTimeParser.getInstance(); - } - - @Test(groups = "unit") - public void testParseOffsetTimeDate() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse("Date", "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-17"), columnInfo, tzBerlin), - LocalTime.MIDNIGHT.atOffset(offsetBerlin)); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-17"), columnInfo, tzLosAngeles), - LocalTime.MIDNIGHT.atOffset(offsetLosAngeles)); - } - - @Test(groups = "unit") - public void testParseOffsetTimeDateTime() throws Exception { - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-17 22:23:24"), - ClickHouseColumnInfo.parse("DateTime", "col", tzBerlin), tzBerlin), - LocalTime.of(22, 23, 24).atOffset(offsetBerlin)); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-17 22:23:24"), - ClickHouseColumnInfo.parse("DateTime", "col", tzLosAngeles), tzLosAngeles), - LocalTime.of(22, 23, 24).atOffset(offsetLosAngeles)); - } - - @Test(groups = "unit") - public void testParseOffsetTimeRegular() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse("String", "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("13:37:42.023+07:00"), columnInfo, null), - OffsetTime.of( - LocalTime.of(13, 37, 42, 23 * 1000000), - ZoneOffset.ofHours(7))); - } - - @Test(groups = "unit") - public void testParseOffsetTimeDateTimeColumnTimeZone() throws Exception { - LocalDateTime localDateTime = LocalDateTime.of(LocalDate.of(2020,01,17), LocalTime.MIDNIGHT); - ZoneOffset offsetVladivostok = ZoneId.of("Asia/Vladivostok").getRules().getOffset(localDateTime); - ZoneOffset offsetBerlin = tzBerlin.toZoneId().getRules().getOffset(localDateTime); - ZoneOffset offsetLosAngeles = tzLosAngeles.toZoneId().getRules().getOffset(localDateTime); - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse("DateTime(Asia/Vladivostok)", "col", TimeZone.getTimeZone("Europe/Moscow")); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-17 22:23:24"), columnInfo, tzBerlin), - LocalTime.of(13, 23, 24).atOffset(offsetBerlin)); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-17 22:23:24"), columnInfo, tzLosAngeles), - LocalTime.of(4, 23, 24).atOffset(offsetLosAngeles)); - } - - @Test( - groups = "unit", - dataProvider = ClickHouseTimeParserTestDataProvider.OTHER_DATA_TYPES, - dataProviderClass = ClickHouseTimeParserTestDataProvider.class) - public void testParseOffsetTimeNumber(ClickHouseDataType dataType) throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse(dataType.name(), "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("222324"), columnInfo, null), - LocalTime.of(22, 23, 24).atOffset(offsetJVM)); - assertEquals( - parser.parse( - ByteFragment.fromString("2223"), columnInfo, null), - LocalTime.of(22, 23).atOffset(offsetJVM)); - assertEquals( - parser.parse( - ByteFragment.fromString("22"), columnInfo, null), - LocalTime.of(22, 0).atOffset(offsetJVM)); - assertEquals( - parser.parse( - ByteFragment.fromString("5"), columnInfo, null), - LocalTime.of(5, 0).atOffset(offsetJVM)); - assertNull( - parser.parse( - ByteFragment.fromString("0"), columnInfo, null)); - - try { - parser.parse( - ByteFragment.fromString("-42"), columnInfo, null); - fail(); - } catch (ClickHouseException che) { - // does not make sense - } - try { - parser.parse( - ByteFragment.fromString("42"), columnInfo, null); - fail(); - } catch (ClickHouseException che) { - // does not make sense - } - } - - @Test(groups = "unit") - public void testParseOffsetTimeString() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse(ClickHouseDataType.String.name(), "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("22:23:24"), columnInfo, null), - LocalTime.of(22, 23, 24).atOffset(offsetJVM)); - assertEquals( - parser.parse( - ByteFragment.fromString("22:23:24.123"), columnInfo, null), - LocalTime.of(22, 23, 24, 123 * 1000 * 1000).atOffset(offsetJVM)); - assertEquals( - parser.parse( - ByteFragment.fromString("22:23"), columnInfo, null), - LocalTime.of(22, 23).atOffset(offsetJVM)); - assertEquals( - parser.parse( - ByteFragment.fromString("22"), columnInfo, null), - LocalTime.of(22, 0).atOffset(offsetJVM)); - assertEquals( - parser.parse( - ByteFragment.fromString("0022"), columnInfo, null), - LocalTime.of(0, 22).atOffset(offsetJVM)); - assertEquals( - parser.parse( - ByteFragment.fromString("002223"), columnInfo, null), - LocalTime.of(0, 22, 23).atOffset(offsetJVM)); - assertEquals( - parser.parse( - ByteFragment.fromString("00:22:23"), columnInfo, null), - LocalTime.of(0, 22, 23).atOffset(offsetJVM)); - assertEquals( - parser.parse( - ByteFragment.fromString("000000"), columnInfo, null), - LocalTime.MIDNIGHT.atOffset(offsetJVM)); - assertEquals( - parser.parse( - ByteFragment.fromString("00:00:00"), columnInfo, null), - LocalTime.MIDNIGHT.atOffset(offsetJVM)); - assertEquals( - parser.parse( - ByteFragment.fromString("00:00"), columnInfo, null), - LocalTime.MIDNIGHT.atOffset(offsetJVM)); - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseSQLDateParserTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseSQLDateParserTest.java deleted file mode 100644 index 319f71940..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseSQLDateParserTest.java +++ /dev/null @@ -1,328 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.sql.Date; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.temporal.ChronoUnit; -import java.util.TimeZone; - -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.domain.ClickHouseDataType; -import ru.yandex.clickhouse.except.ClickHouseException; -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.fail; - -public class ClickHouseSQLDateParserTest { - - private TimeZone tzLosAngeles; - private TimeZone tzBerlin; - private ClickHouseSQLDateParser parser; - - @BeforeClass(groups = "unit") - public void setUp() { - tzLosAngeles = TimeZone.getTimeZone("America/Los_Angeles"); - tzBerlin = TimeZone.getTimeZone("Europe/Berlin"); - parser = ClickHouseSQLDateParser.getInstance(); - } - - @Test(groups = "unit") - public void testParseSQLDateNull() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse("Date", "col", null); - try { - parser.parse( - null, columnInfo, tzBerlin); - fail(); - } catch (NullPointerException npe) { - // should be handled before calling the parser - } - } - - @Test(groups = "unit") - public void testParseSQLDateDate() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse("Date", "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12"), columnInfo, null), - new Date( - LocalDate.of(2020, 1, 12) - .atStartOfDay(ZoneId.systemDefault()) - .toInstant() - .toEpochMilli())); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12"), columnInfo, tzLosAngeles), - new Date( - LocalDate.of(2020, 1, 12) - .atStartOfDay(tzLosAngeles.toZoneId()) - .toInstant() - .toEpochMilli())); - // local stays local - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12"), columnInfo, tzBerlin), - new Date( - LocalDate.of(2020, 1, 12) - .atStartOfDay(tzBerlin.toZoneId()) - .toInstant() - .toEpochMilli())); - assertNull( - parser.parse( - ByteFragment.fromString("0000-00-00"), columnInfo, tzLosAngeles)); - } - - @Test(groups = "unit") - public void testParseSQLDateDateNullable() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse("Nullable(Date)", "col", null); - assertNull( - parser.parse( - ByteFragment.fromString("0000-00-00"), columnInfo, tzLosAngeles)); - } - - @Test(groups = "unit") - public void testParseSQLDateDateTime() throws Exception { - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12 01:02:03"), - ClickHouseColumnInfo.parse("DateTime", "col", TimeZone.getDefault()), null), - new Date( - LocalDate.of(2020, 1, 12) - .atStartOfDay(ZoneId.systemDefault()) - .toInstant() - .toEpochMilli())); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12 22:23:24"), - ClickHouseColumnInfo.parse("DateTime", "col", tzLosAngeles), tzLosAngeles), - new Date( - LocalDate.of(2020, 1, 12) - .atStartOfDay(tzLosAngeles.toZoneId()) - .toInstant() - .toEpochMilli())); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12 22:23:24"), - ClickHouseColumnInfo.parse("DateTime", "col", tzBerlin), tzBerlin), - new Date( - LocalDate.of(2020, 1, 12) - .atStartOfDay(tzBerlin.toZoneId()) - .toInstant() - .toEpochMilli())); - assertNull( - parser.parse( - ByteFragment.fromString("0000-00-00 00:00:00"), - ClickHouseColumnInfo.parse("DateTime", "col", TimeZone.getDefault()), null)); - } - - @Test(groups = "unit") - public void testParseSQLDateDateTimeTZColumn() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse("DateTime(Europe/Berlin)", "col", TimeZone.getTimeZone("Asia/Chongqing")); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12 01:02:03"), columnInfo, null), - new Date( - LocalDateTime.of(2020, 1, 12, 1, 2, 3) - .atZone(tzBerlin.toZoneId()) - .withZoneSameInstant(ZoneId.systemDefault()) - .truncatedTo(ChronoUnit.DAYS) - .toInstant() - .toEpochMilli())); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12 22:23:24"), columnInfo, tzLosAngeles), - new Date( - LocalDateTime.of(2020, 1, 12, 22, 23, 24) - .atZone(tzBerlin.toZoneId()) - .withZoneSameInstant(tzLosAngeles.toZoneId()) - .truncatedTo(ChronoUnit.DAYS) - .toInstant() - .toEpochMilli())); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12 22:23:24"), columnInfo, tzBerlin), - new Date( - LocalDateTime.of(2020, 1, 12, 22, 23, 24) - .atZone(tzBerlin.toZoneId()) - .truncatedTo(ChronoUnit.DAYS) - .toInstant() - .toEpochMilli())); - assertNull( - parser.parse( - ByteFragment.fromString("0000-00-00 00:00:00"), columnInfo, null)); - } - - @Test(groups = "unit") - public void testParseSQLDateDateTimeOtherTZColumn() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse("DateTime(Asia/Vladivostok)", "col", TimeZone.getTimeZone("Europe/Moscow")); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12 01:02:03"), columnInfo, null), - new Date( - LocalDate.of(2020, 1, 11) - .atStartOfDay(ZoneId.systemDefault()) - .toInstant() - .toEpochMilli())); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12 22:23:24"), columnInfo, tzLosAngeles), - new Date( - LocalDate.of(2020, 1, 12) - .atStartOfDay(tzLosAngeles.toZoneId()) - .toInstant() - .toEpochMilli())); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-12 22:23:24"), columnInfo, tzBerlin), - new Date( - LocalDate.of(2020, 1, 12) - .atStartOfDay(tzBerlin.toZoneId()) - .toInstant() - .toEpochMilli())); - assertNull( - parser.parse( - ByteFragment.fromString("0000-00-00 00:00:00"), columnInfo, null)); - } - - @Test( - groups = "unit", - dataProvider = ClickHouseTimeParserTestDataProvider.OTHER_DATA_TYPES, - dataProviderClass = ClickHouseTimeParserTestDataProvider.class) - public void testParseSQLDateNumber(ClickHouseDataType dataType) throws Exception { - - Instant instant = LocalDateTime.of(2020, 1, 12, 22, 23, 24) - .atZone(tzLosAngeles.toZoneId()) - .toInstant(); - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse(dataType.name(), "col", null); - - assertEquals( - parser.parse( - ByteFragment.fromString( - String.valueOf(instant.getEpochSecond())), - columnInfo, - tzLosAngeles), - new Date( - LocalDate.of(2020, 1, 12) - .atStartOfDay(tzLosAngeles.toZoneId()) - .toInstant() - .toEpochMilli())); - - assertEquals( - parser.parse( - ByteFragment.fromString( - String.valueOf(instant.getEpochSecond())), - columnInfo, - tzBerlin), - new Date( - LocalDate.of(2020, 1, 13) - .atStartOfDay(tzBerlin.toZoneId()) - .toInstant() - .toEpochMilli())); - - try { - parser.parse( - ByteFragment.fromString("ABC"), columnInfo, null); - fail(); - } catch (ClickHouseException che) { - // expected - } - - try { - parser.parse( - ByteFragment.fromString("3.14159265359"), columnInfo, null); - fail(); - } catch (ClickHouseException che) { - // expected - } - - assertNull( - parser.parse( - ByteFragment.fromString(String.valueOf(0)), columnInfo, tzBerlin)); - } - - @Test(groups = "unit") - public void testParseSQLDateNumberNegative() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse(ClickHouseDataType.Int64.name(), "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString( - String.valueOf(-386384400)), - columnInfo, - tzBerlin), - new Date( - LocalDate.of(1957, 10, 4) - .atStartOfDay(tzBerlin.toZoneId()) - .toInstant() - .toEpochMilli())); - } - - @Test(groups = "unit") - public void testParseSQLDateOtherLikeDate() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse(ClickHouseDataType.Unknown.name(), "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-13"), columnInfo, null), - new Date( - LocalDate.of(2020, 1, 13) - .atStartOfDay(ZoneId.systemDefault()) - .toInstant() - .toEpochMilli())); - try { - parser.parse( - ByteFragment.fromString("2020-1-13"), columnInfo, null); - fail(); - } catch (ClickHouseException che) { - // bad format - } - try { - parser.parse( - ByteFragment.fromString("2020-01-42"), columnInfo, null); - fail(); - } catch (ClickHouseException che) { - // bad format - } - } - - @Test(groups = "unit") - public void testParseSQLDateOtherLikeDateTime() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse(ClickHouseDataType.Unknown.name(), "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-13 22:23:24"), columnInfo, null), - new Date( - LocalDate.of(2020, 1, 13) - .atStartOfDay(ZoneId.systemDefault()) - .toInstant() - .toEpochMilli())); - try { - parser.parse( - ByteFragment.fromString("2020-1-13 22:23:24"), columnInfo, null); - fail(); - } catch (ClickHouseException che) { - // bad format - } - try { - parser.parse( - ByteFragment.fromString("2020-01-42 22:23:24"), columnInfo, null); - fail(); - } catch (ClickHouseException che) { - // bad format - } - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseSQLTimeParserTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseSQLTimeParserTest.java deleted file mode 100644 index b0eaec32a..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseSQLTimeParserTest.java +++ /dev/null @@ -1,180 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.sql.Time; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.util.TimeZone; - -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.domain.ClickHouseDataType; -import ru.yandex.clickhouse.except.ClickHouseException; -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.fail; - -public class ClickHouseSQLTimeParserTest { - - private TimeZone tzBerlin; - private TimeZone tzLosAngeles; - private ClickHouseSQLTimeParser parser; - - @BeforeClass(groups = "unit") - public void setUp() { - tzBerlin = TimeZone.getTimeZone("Europe/Berlin"); - tzLosAngeles = TimeZone.getTimeZone("America/Los_Angeles"); - parser = ClickHouseSQLTimeParser.getInstance(); - } - - @Test(groups = "unit") - public void testParseTimeTimeDate() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse("Date", "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-17"), columnInfo, tzBerlin), - createExpectedTime(LocalTime.MIDNIGHT, tzBerlin)); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-17"), columnInfo, tzLosAngeles), - createExpectedTime(LocalTime.MIDNIGHT, tzLosAngeles)); - } - - @Test(groups = "unit") - public void testParseOffsetTimeDateTime() throws Exception { - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-17 22:23:24"), - ClickHouseColumnInfo.parse("DateTime", "col", tzBerlin), tzBerlin), - createExpectedTime(LocalTime.of(22, 23, 24), tzBerlin)); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-17 22:23:24"), - ClickHouseColumnInfo.parse("DateTime", "col", tzLosAngeles), tzLosAngeles), - createExpectedTime(LocalTime.of(22, 23, 24), tzLosAngeles)); - } - - @Test(groups = "unit") - public void testParseOffsetTimeDateTimeColumnTimeZone() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse("DateTime(Asia/Vladivostok)", "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-17 22:23:24"), columnInfo, tzBerlin), - createExpectedTime(LocalTime.of(13, 23, 24), tzBerlin)); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-17 22:23:24"), columnInfo, tzLosAngeles), - createExpectedTime(LocalTime.of(04, 23, 24), tzLosAngeles)); - assertEquals( - parser.parse( - ByteFragment.fromString("2020-01-17 22:23:24"), columnInfo, - TimeZone.getTimeZone("Asia/Vladivostok")), - createExpectedTime(LocalTime.of(22, 23, 24), TimeZone.getTimeZone("Asia/Vladivostok"))); - } - - @Test( - groups = "unit", - dataProvider = ClickHouseTimeParserTestDataProvider.OTHER_DATA_TYPES, - dataProviderClass = ClickHouseTimeParserTestDataProvider.class) - public void testParseOffsetTimeNumber(ClickHouseDataType dataType) throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse(dataType.name(), "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("222324"), columnInfo, null), - createExpectedTime(LocalTime.of(22, 23, 24), TimeZone.getDefault())); - assertEquals( - parser.parse( - ByteFragment.fromString("2223"), columnInfo, null), - createExpectedTime(LocalTime.of(22, 23), TimeZone.getDefault())); - assertEquals( - parser.parse( - ByteFragment.fromString("22"), columnInfo, null), - createExpectedTime(LocalTime.of(22, 0), TimeZone.getDefault())); - assertEquals( - parser.parse( - ByteFragment.fromString("5"), columnInfo, null), - createExpectedTime(LocalTime.of(5, 0), TimeZone.getDefault())); - assertNull( - parser.parse( - ByteFragment.fromString("0"), columnInfo, null)); - - try { - parser.parse( - ByteFragment.fromString("-42"), columnInfo, null); - fail(); - } catch (ClickHouseException che) { - // does not make sense - } - try { - parser.parse( - ByteFragment.fromString("42"), columnInfo, null); - fail(); - } catch (ClickHouseException che) { - // does not make sense - } - } - - @Test(groups = "unit") - public void testParseOffsetTimeString() throws Exception { - ClickHouseColumnInfo columnInfo = - ClickHouseColumnInfo.parse(ClickHouseDataType.String.name(), "col", null); - assertEquals( - parser.parse( - ByteFragment.fromString("22:23:24"), columnInfo, null), - createExpectedTime(LocalTime.of(22, 23, 24), TimeZone.getDefault())); - assertEquals( - parser.parse( - ByteFragment.fromString("22:23:24.123"), columnInfo, null), - createExpectedTime(LocalTime.of(22, 23, 24, 123 * 1000 * 1000), TimeZone.getDefault())); - assertEquals( - parser.parse( - ByteFragment.fromString("22:23"), columnInfo, null), - createExpectedTime(LocalTime.of(22, 23), TimeZone.getDefault())); - assertEquals( - parser.parse( - ByteFragment.fromString("22"), columnInfo, null), - createExpectedTime(LocalTime.of(22, 0), TimeZone.getDefault())); - assertEquals( - parser.parse( - ByteFragment.fromString("0022"), columnInfo, null), - createExpectedTime(LocalTime.of(0, 22), TimeZone.getDefault())); - assertEquals( - parser.parse( - ByteFragment.fromString("002223"), columnInfo, null), - createExpectedTime(LocalTime.of(0, 22, 23), TimeZone.getDefault())); - assertEquals( - parser.parse( - ByteFragment.fromString("00:22:23"), columnInfo, null), - createExpectedTime(LocalTime.of(0, 22, 23), TimeZone.getDefault())); - assertEquals( - parser.parse( - ByteFragment.fromString("000000"), columnInfo, null), - createExpectedTime(LocalTime.MIDNIGHT, TimeZone.getDefault())); - assertEquals( - parser.parse( - ByteFragment.fromString("00:00:00"), columnInfo, null), - createExpectedTime(LocalTime.MIDNIGHT, TimeZone.getDefault())); - assertEquals( - parser.parse( - ByteFragment.fromString("00:00"), columnInfo, null), - createExpectedTime(LocalTime.MIDNIGHT, TimeZone.getDefault())); - } - - private static Time createExpectedTime(LocalTime expected, TimeZone timeZone) { - return new Time(ClickHouseSQLTimeParser.normalizeTime(null, - LocalDateTime.of( - LocalDate.ofEpochDay(0), - expected) - .atZone(timeZone.toZoneId()) - .toInstant() - .toEpochMilli())); - } - -} - diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseSQLTimestampParserTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseSQLTimestampParserTest.java deleted file mode 100644 index 537f617ba..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseSQLTimestampParserTest.java +++ /dev/null @@ -1,130 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.sql.Timestamp; -import java.util.TimeZone; - -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.domain.ClickHouseDataType; -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -import static org.testng.Assert.assertEquals; - -public class ClickHouseSQLTimestampParserTest { - - private TimeZone tzLosAngeles; - private TimeZone tzBerlin; - private ClickHouseSQLTimestampParser parser; - - @BeforeClass(groups = "unit") - public void setUp() { - tzLosAngeles = TimeZone.getTimeZone("America/Los_Angeles"); - tzBerlin = TimeZone.getTimeZone("Europe/Berlin"); - parser = ClickHouseSQLTimestampParser.getInstance(); - } - - @Test(groups = "unit") - public void testParseTimestampDateTime() throws Exception { - Timestamp inst = parser.parse( - ByteFragment.fromString("2020-01-20 22:23:24"), - ClickHouseColumnInfo.parse("DateTime", "col", tzBerlin), tzBerlin); - assertEquals( - inst.getTime(), - 1579555404000L); - inst = parser.parse( - ByteFragment.fromString("2020-01-20 22:23:24"), - ClickHouseColumnInfo.parse("DateTime", "col", tzLosAngeles), tzLosAngeles); - assertEquals( - inst.getTime(), - 1579587804000L); - } - - @Test(groups = "unit") - public void testParseTimestampDateTimeColumnOverride() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - "DateTime(Europe/Berlin)", "col", TimeZone.getTimeZone("Asia/Chongqing")); - Timestamp inst = parser.parse( - ByteFragment.fromString("2020-01-20 22:23:24"), columnInfo, tzLosAngeles); - assertEquals( - inst.getTime(), - 1579555404000L); - } - - @Test(groups = "unit") - public void testParseTimestampDate() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - "Date", "col", null); - Timestamp inst = parser.parse( - ByteFragment.fromString("2020-01-20"), columnInfo, tzLosAngeles); - assertEquals( - inst.getTime(), - 1579507200000L); - } - - @Test( - groups = "unit", - dataProvider = ClickHouseTimeParserTestDataProvider.OTHER_DATA_TYPES, - dataProviderClass = ClickHouseTimeParserTestDataProvider.class) - public void parseTimestampTimestampSeconds(ClickHouseDataType dataType) throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - dataType.name(), "col", null); - Timestamp inst = parser.parse( - ByteFragment.fromString("1579507200"), columnInfo, tzLosAngeles); - assertEquals( - inst.getTime(), - 1579507200000L); - inst = parser.parse( - ByteFragment.fromString("1579507200"), columnInfo, tzBerlin); - assertEquals( - inst.getTime(), - 1579507200000L); - } - - @Test( - groups = "unit", - dataProvider = ClickHouseTimeParserTestDataProvider.OTHER_DATA_TYPES, - dataProviderClass = ClickHouseTimeParserTestDataProvider.class) - public void parseTimestampTimestampMillis(ClickHouseDataType dataType) throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - dataType.name(), "col", null); - Timestamp inst = parser.parse( - ByteFragment.fromString("1579507200000"), columnInfo, tzLosAngeles); - assertEquals( - inst.getTime(), - 1579507200000L); - inst = parser.parse( - ByteFragment.fromString("1579507200"), columnInfo, tzBerlin); - assertEquals( - inst.getTime(), - 1579507200000L); - } - - @Test(groups = "unit") - public void testParseTimestampString() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - "String", "col", null); - Timestamp inst = parser.parse( - ByteFragment.fromString("2020-01-20T22:23:24.123"), columnInfo, tzLosAngeles); - assertEquals( - inst.getTime(), - 1579587804123L); - inst = parser.parse( - ByteFragment.fromString("2020-01-20T22:23:24.123+01:00"), columnInfo, tzLosAngeles); - assertEquals( - inst.getTime(), - 1579555404123L); - inst = parser.parse( - ByteFragment.fromString("2020-01-20 22:23:24.123"), columnInfo, tzLosAngeles); - assertEquals( - inst.getTime(), - 1579587804123L); - inst = parser.parse( - ByteFragment.fromString("2020-01-20 22:23:24.123+01:00"), columnInfo, tzLosAngeles); - assertEquals( - inst.getTime(), - 1579555404123L); - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseStringParserTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseStringParserTest.java deleted file mode 100644 index 43f3e5c05..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseStringParserTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNull; - -public class ClickHouseStringParserTest { - - private ClickHouseStringParser parser; - private ClickHouseColumnInfo columnInfo; - - @BeforeClass(groups = "unit") - public void setUp() { - parser = ClickHouseStringParser.getInstance(); - columnInfo = ClickHouseColumnInfo.parse("String", "column_name", null); - } - - @Test(groups = "unit") - public void testParseString() throws Exception { - assertNull(parser.parse(ByteFragment.fromString("\\N"), columnInfo, null)); - assertEquals(parser.parse(ByteFragment.fromString(""), columnInfo, null), ""); - assertEquals(parser.parse(ByteFragment.fromString("null"), columnInfo, null), "null"); - assertEquals(parser.parse(ByteFragment.fromString("NULL"), columnInfo, null), "NULL"); - assertEquals(parser.parse(ByteFragment.fromString("foo"), columnInfo, null), "foo"); - assertEquals( - parser.parse(ByteFragment.fromString(" \t \r\n"), columnInfo, null), - " \t \r\n"); - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseTimeParserTestDataProvider.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseTimeParserTestDataProvider.java deleted file mode 100644 index 1df785daa..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseTimeParserTestDataProvider.java +++ /dev/null @@ -1,23 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import org.testng.annotations.DataProvider; - -import ru.yandex.clickhouse.domain.ClickHouseDataType; - -final class ClickHouseTimeParserTestDataProvider { - - static final String OTHER_DATA_TYPES = "otherDataTypes"; - - @DataProvider(name = OTHER_DATA_TYPES) - static Object[][] provideNumberAndSimilarClickHouseDataTypes() { - return new ClickHouseDataType[][] { - {ClickHouseDataType.Int32}, - {ClickHouseDataType.Int64}, - {ClickHouseDataType.UInt32}, - {ClickHouseDataType.UInt64}, - {ClickHouseDataType.String}, - {ClickHouseDataType.Unknown} - }; - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseUUIDParserTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseUUIDParserTest.java deleted file mode 100644 index 2ac6b5747..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseUUIDParserTest.java +++ /dev/null @@ -1,61 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.util.UUID; - -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.except.ClickHouseException; -import ru.yandex.clickhouse.response.ByteFragment; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotEquals; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.fail; - -public class ClickHouseUUIDParserTest { - - private ClickHouseValueParser parser; - - @BeforeClass(groups = "unit") - public void setUp() throws Exception { - parser = ClickHouseValueParser.getParser(UUID.class); - } - - @Test(groups = "unit") - public void testNullValue() throws Exception { - assertNull(parser.parse( - ByteFragment.fromString("\\N"), null, null)); - } - - @Test(groups = "unit") - public void testEmptyValue() throws Exception { - assertNull(parser.parse( - ByteFragment.fromString(""), null, null)); - } - - @Test(groups = "unit") - public void testSimpleUUID() throws Exception { - UUID uuid = UUID.randomUUID(); - assertEquals( - parser.parse( - ByteFragment.fromString(uuid.toString()), null, null), - uuid); - assertNotEquals( - parser.parse( - ByteFragment.fromString(uuid.toString()), null, null), - UUID.randomUUID()); - } - - @Test(groups = "unit") - public void testBrokenUUID() throws Exception { - try { - parser.parse( - ByteFragment.fromString("BROKEN"), null, null); - fail(); - } catch (ClickHouseException che) { - // expected - } - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseValueParserTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseValueParserTest.java deleted file mode 100644 index beee501d4..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseValueParserTest.java +++ /dev/null @@ -1,259 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.sql.SQLException; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; - -public class ClickHouseValueParserTest { - /** - * Generates test data for floats. - */ - @DataProvider(name = "float_test_data") - public Object[][] floatTestData() { - return new Object [][] { - {"100.0", 100.0f}, - {"NaN", Float.NaN}, - {"Infinity", Float.POSITIVE_INFINITY}, - {"+Infinity", Float.POSITIVE_INFINITY}, - {"-Infinity", Float.NEGATIVE_INFINITY}, - {"nan", Float.NaN}, - {"inf", Float.POSITIVE_INFINITY}, - {"+inf", Float.POSITIVE_INFINITY}, - {"-inf", Float.NEGATIVE_INFINITY} - }; - } - - /** - * Generates test data for doubles. - */ - @DataProvider(name = "double_test_data") - public Object[][] doubleTestData() { - return new Object [][] { - {"100.0", 100.0d}, - {"Infinity", Double.POSITIVE_INFINITY}, - {"+Infinity", Double.POSITIVE_INFINITY}, - {"-Infinity", Double.NEGATIVE_INFINITY}, - {"nan", Double.NaN}, - {"inf", Double.POSITIVE_INFINITY}, - {"+inf", Double.POSITIVE_INFINITY}, - {"-inf", Double.NEGATIVE_INFINITY} - }; - } - - @Test(groups = "unit") - public void testParseInt() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse("Int64", "columnName", null); - assertEquals(ClickHouseValueParser.parseInt(ByteFragment.fromString("42"), columnInfo), 42); - assertEquals(ClickHouseValueParser.parseInt(ByteFragment.fromString("-42"), columnInfo), -42); - assertEquals(ClickHouseValueParser.parseInt(ByteFragment.fromString(""), columnInfo), 0); - assertEquals(0, ClickHouseValueParser.parseInt(ByteFragment.fromString("0"), columnInfo), 0); - assertEquals(0, ClickHouseValueParser.parseInt(ByteFragment.fromString("000"), columnInfo), 0); - assertEquals(0, ClickHouseValueParser.parseInt(ByteFragment.fromString("\\N"), columnInfo), 0 ); - try { - ClickHouseValueParser.parseInt(ByteFragment.fromString("foo"), columnInfo); - fail(); - } catch (SQLException sqle) { - // expected - } - assertEquals( - ClickHouseValueParser.parseInt( - ByteFragment.fromString(String.valueOf(Integer.MAX_VALUE)), - columnInfo), - Integer.MAX_VALUE); - try { - ClickHouseValueParser.parseInt( - ByteFragment.fromString(Long.valueOf(Integer.MAX_VALUE + 1L).toString()), - columnInfo); - fail(); - } catch (SQLException sqle) { - // expected - } - assertEquals( - ClickHouseValueParser.parseInt( - ByteFragment.fromString(String.valueOf(Integer.MIN_VALUE)), - columnInfo), - Integer.MIN_VALUE); - try { - ClickHouseValueParser.parseInt( - ByteFragment.fromString(Long.valueOf(Integer.MIN_VALUE - 1L).toString()), - columnInfo); - fail(); - } catch (SQLException sqle) { - // expected - } - } - - @Test(groups = "unit") - public void testParseLong() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse("Int64", "columnName", null); - assertEquals(ClickHouseValueParser.parseLong(ByteFragment.fromString("42"), columnInfo), 42); - assertEquals(ClickHouseValueParser.parseLong(ByteFragment.fromString("-42"), columnInfo), -42); - assertEquals(ClickHouseValueParser.parseLong(ByteFragment.fromString(""), columnInfo), 0L); - assertEquals(ClickHouseValueParser.parseLong(ByteFragment.fromString("0"), columnInfo), 0L); - assertEquals(ClickHouseValueParser.parseLong(ByteFragment.fromString("000"), columnInfo), 0L); - assertEquals(ClickHouseValueParser.parseLong(ByteFragment.fromString("\\N"), columnInfo), 0L); - try { - ClickHouseValueParser.parseLong(ByteFragment.fromString("foo"), columnInfo); - fail(); - } catch (SQLException sqle) { - // expected - } - assertEquals( - ClickHouseValueParser.parseLong( - ByteFragment.fromString(String.valueOf(Long.MAX_VALUE)), - columnInfo), - Long.MAX_VALUE); - try { - ClickHouseValueParser.parseLong( - ByteFragment.fromString( - Long.valueOf(Long.MAX_VALUE).toString() + "0"), - columnInfo); - fail(); - } catch (SQLException sqle) { - // expected - } - assertEquals( - ClickHouseValueParser.parseLong( - ByteFragment.fromString(String.valueOf(Long.MIN_VALUE)), - columnInfo), - Long.MIN_VALUE); - try { - ClickHouseValueParser.parseLong( - ByteFragment.fromString(Long.valueOf(Long.MIN_VALUE).toString() + "0"), - columnInfo); - fail(); - } catch (SQLException sqle) { - // expected - } - } - - @Test(groups = "unit") - public void testParseShort() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse("UInt16", "columnName", null); - assertEquals(ClickHouseValueParser.parseShort(ByteFragment.fromString("42"), columnInfo), 42); - assertEquals(ClickHouseValueParser.parseShort(ByteFragment.fromString("-42"), columnInfo), -42); - assertEquals(ClickHouseValueParser.parseShort(ByteFragment.fromString(""), columnInfo), 0); - assertEquals(ClickHouseValueParser.parseShort(ByteFragment.fromString("0"), columnInfo), 0); - assertEquals(ClickHouseValueParser.parseShort(ByteFragment.fromString("000"), columnInfo), 0); - assertEquals(ClickHouseValueParser.parseShort(ByteFragment.fromString("\\N"), columnInfo), 0); - try { - ClickHouseValueParser.parseShort(ByteFragment.fromString("foo"), columnInfo); - fail(); - } catch (SQLException sqle) { - // expected - } - assertEquals( - ClickHouseValueParser.parseShort( - ByteFragment.fromString(String.valueOf(Short.MAX_VALUE)), - columnInfo), - Short.MAX_VALUE); - try { - ClickHouseValueParser.parseShort( - ByteFragment.fromString(Integer.valueOf(Short.MAX_VALUE + 1).toString()), - columnInfo); - fail(); - } catch (SQLException sqle) { - // expected - } - assertEquals( - ClickHouseValueParser.parseShort( - ByteFragment.fromString(String.valueOf(Short.MIN_VALUE)), - columnInfo), - Short.MIN_VALUE); - try { - ClickHouseValueParser.parseShort( - ByteFragment.fromString(Integer.valueOf(Short.MIN_VALUE - 1).toString()), - columnInfo); - fail(); - } catch (SQLException sqle) { - // expected - } - } - - @Test(groups = "unit") - public void testParseBoolean() throws SQLException { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse("UInt8", "columnName", null); - assertFalse(ClickHouseValueParser.parseBoolean(ByteFragment.fromString(""), columnInfo)); - assertFalse(ClickHouseValueParser.parseBoolean(ByteFragment.fromString("\\N"), columnInfo)); - assertFalse(ClickHouseValueParser.parseBoolean(ByteFragment.fromString("0"), columnInfo)); - assertTrue(ClickHouseValueParser.parseBoolean(ByteFragment.fromString("1"), columnInfo)); - assertFalse(ClickHouseValueParser.parseBoolean(ByteFragment.fromString("10"), columnInfo)); - assertFalse(ClickHouseValueParser.parseBoolean(ByteFragment.fromString(" 10"), columnInfo)); - assertFalse(ClickHouseValueParser.parseBoolean(ByteFragment.fromString("foo"), columnInfo)); - assertTrue(ClickHouseValueParser.parseBoolean(ByteFragment.fromString("TRUE"), columnInfo)); - assertTrue(ClickHouseValueParser.parseBoolean(ByteFragment.fromString("true"), columnInfo)); - assertFalse(ClickHouseValueParser.parseBoolean(ByteFragment.fromString("FALSE"), columnInfo)); - assertFalse(ClickHouseValueParser.parseBoolean(ByteFragment.fromString("false"), columnInfo)); - assertFalse(ClickHouseValueParser.parseBoolean(ByteFragment.fromString(" true"), columnInfo)); - } - - @Test (dataProvider = "float_test_data", groups = "unit") - public void testParseFloat(String byteFragmentString, Float expectedValue) throws SQLException { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse("Float32", "columnName", null); - float floatDelta = 0.001f; - if (expectedValue.isNaN()) { - assertTrue(Float.isNaN(ClickHouseValueParser.parseFloat( - ByteFragment.fromString(byteFragmentString), columnInfo) - )); - } else { - assertEquals(ClickHouseValueParser.parseFloat( - ByteFragment.fromString(byteFragmentString), columnInfo), expectedValue, floatDelta - ); - } - } - - @Test (dataProvider = "double_test_data", groups = "unit") - public void testParseDouble(String byteFragmentString, Double expectedValue) throws SQLException { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse("Float64", "columnName", null); - double doubleDelta = 0.001; - if (expectedValue.isNaN()) { - assertTrue(Double.isNaN(ClickHouseValueParser.parseDouble( - ByteFragment.fromString(byteFragmentString), columnInfo) - )); - } else { - assertEquals(ClickHouseValueParser.parseDouble( - ByteFragment.fromString(byteFragmentString), columnInfo), expectedValue, doubleDelta - ); - } - } - - @Test (dataProvider = "float_test_data") - public void testGetParserFloat(String byteFragmentString, Float expectedValue) throws SQLException { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse("Float32", "columnName", null); - float floatDelta = 0.001f; - - if (expectedValue.isNaN()) { - assertTrue(Float.isNaN(ClickHouseValueParser.getParser(Float.class).parse( - ByteFragment.fromString(byteFragmentString), columnInfo, null) - )); - } else { - assertEquals(ClickHouseValueParser.getParser(Float.class).parse( - ByteFragment.fromString(byteFragmentString), columnInfo, null), expectedValue, floatDelta - ); - } - } - - @Test (dataProvider = "double_test_data", groups = "unit") - public void testGetParserDouble(String byteFragmentString, Double expectedValue) throws SQLException { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse("Float64", "columnName", null); - double doubleDelta = 0.001d; - - if (expectedValue.isNaN()) { - assertTrue(Double.isNaN(ClickHouseValueParser.getParser(Double.class).parse( - ByteFragment.fromString(byteFragmentString), columnInfo, null) - )); - } else { - assertEquals(ClickHouseValueParser.getParser(Double.class).parse( - ByteFragment.fromString(byteFragmentString), columnInfo, null), expectedValue, doubleDelta - ); - } - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseZonedDateTimeParserTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseZonedDateTimeParserTest.java deleted file mode 100644 index 62772b069..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/response/parser/ClickHouseZonedDateTimeParserTest.java +++ /dev/null @@ -1,119 +0,0 @@ -package ru.yandex.clickhouse.response.parser; - -import java.time.ZonedDateTime; -import java.util.TimeZone; - -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.domain.ClickHouseDataType; -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -import static org.testng.Assert.assertEquals; - -public class ClickHouseZonedDateTimeParserTest { - - private TimeZone tzLosAngeles; - private TimeZone tzBerlin; - private ClickHouseZonedDateTimeParser parser; - - @BeforeClass(groups = "unit") - public void setUp() { - tzLosAngeles = TimeZone.getTimeZone("America/Los_Angeles"); - tzBerlin = TimeZone.getTimeZone("Europe/Berlin"); - parser = ClickHouseZonedDateTimeParser.getInstance(); - } - - @Test(groups = "unit") - public void testParseZonedDateTimeDateTime() throws Exception { - ZonedDateTime inst = parser.parse( - ByteFragment.fromString("2020-01-20 22:23:24"), - ClickHouseColumnInfo.parse("DateTime", "col", tzBerlin), tzBerlin); - assertEquals( - inst.toInstant().getEpochSecond(), - 1579555404); - inst = parser.parse( - ByteFragment.fromString("2020-01-20 22:23:24"), - ClickHouseColumnInfo.parse("DateTime", "col", tzLosAngeles), tzLosAngeles); - assertEquals( - inst.toInstant().getEpochSecond(), - 1579587804); - } - - @Test(groups = "unit") - public void testParseZonedDateTimeDateTimeColumnOverride() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - "DateTime(Europe/Berlin)", "col", TimeZone.getTimeZone("Asia/Chongqing")); - ZonedDateTime inst = parser.parse( - ByteFragment.fromString("2020-01-20 22:23:24"), columnInfo, tzLosAngeles); - assertEquals( - inst.toInstant().getEpochSecond(), - 1579555404); - } - - @Test(groups = "unit") - public void testParseZonedDateTimeDate() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - "Date", "col", null); - ZonedDateTime inst = parser.parse( - ByteFragment.fromString("2020-01-20"), columnInfo, tzLosAngeles); - assertEquals( - inst.toInstant().getEpochSecond(), - 1579507200); - } - - @Test( - groups = "unit", - dataProvider = ClickHouseTimeParserTestDataProvider.OTHER_DATA_TYPES, - dataProviderClass = ClickHouseTimeParserTestDataProvider.class) - public void parseZonedDateTimeTimestampSeconds(ClickHouseDataType dataType) throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - dataType.name(), "col", null); - ZonedDateTime inst = parser.parse( - ByteFragment.fromString("1579507200"), columnInfo, tzLosAngeles); - assertEquals( - inst.toInstant().getEpochSecond(), - 1579507200); - inst = parser.parse( - ByteFragment.fromString("1579507200"), columnInfo, tzBerlin); - assertEquals( - inst.toInstant().getEpochSecond(), - 1579507200); - } - - @Test( - groups = "unit", - dataProvider = ClickHouseTimeParserTestDataProvider.OTHER_DATA_TYPES, - dataProviderClass = ClickHouseTimeParserTestDataProvider.class) - public void parseZonedDateTimeTimestampMillis(ClickHouseDataType dataType) throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - dataType.name(), "col", null); - ZonedDateTime inst = parser.parse( - ByteFragment.fromString("1579507200000"), columnInfo, tzLosAngeles); - assertEquals( - inst.toInstant().getEpochSecond(), - 1579507200); - inst = parser.parse( - ByteFragment.fromString("1579507200"), columnInfo, tzBerlin); - assertEquals( - inst.toInstant().getEpochSecond(), - 1579507200); - } - - @Test(groups = "unit") - public void testParseZonedDateTimeString() throws Exception { - ClickHouseColumnInfo columnInfo = ClickHouseColumnInfo.parse( - "String", "col", null); - ZonedDateTime inst = parser.parse( - ByteFragment.fromString("2020-01-20T22:23:24.123"), columnInfo, tzLosAngeles); - assertEquals( - inst.toInstant().getEpochSecond(), - 1579587804); - inst = parser.parse( - ByteFragment.fromString("2020-01-20T22:23:24.123+01:00"), columnInfo, tzLosAngeles); - assertEquals( - inst.toInstant().getEpochSecond(), - 1579555404); - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/settings/ClickHousePropertiesTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/settings/ClickHousePropertiesTest.java deleted file mode 100644 index 11e3f5f1d..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/settings/ClickHousePropertiesTest.java +++ /dev/null @@ -1,195 +0,0 @@ -package ru.yandex.clickhouse.settings; - -import java.net.URI; -import java.util.Map; -import java.util.Properties; - -import org.testng.Assert; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.BalancedClickhouseDataSource; -import ru.yandex.clickhouse.ClickHouseDataSource; - -import static org.testng.Assert.assertFalse; -import static org.testng.AssertJUnit.assertEquals; -import static org.testng.AssertJUnit.assertTrue; - -public class ClickHousePropertiesTest { - - /** - * Method {@link ru.yandex.clickhouse.ClickhouseJdbcUrlParser#parseUriQueryPart(URI, Properties)} returns instance - * of {@link Properties} with defaults. These defaults may be missed if method - * {@link java.util.Hashtable#get(Object)} is used for {@code Properties}. - */ - @Test(groups = "unit") - public void constructorShouldNotIgnoreDefaults() { - Properties defaults = new Properties(); - String expectedUsername = "superuser"; - defaults.setProperty("user", expectedUsername); - Properties propertiesWithDefaults = new Properties(defaults); - - ClickHouseProperties clickHouseProperties = new ClickHouseProperties(propertiesWithDefaults); - Assert.assertEquals(clickHouseProperties.getUser(), expectedUsername); - } - - @Test(groups = "unit") - public void constructorShouldNotIgnoreClickHouseProperties() { - int expectedConnectionTimeout = 1000; - boolean isCompress = false; - Integer maxParallelReplicas = 3; - Integer maxPartitionsPerInsertBlock = 200; - Long maxInsertBlockSize = 142L; - Boolean insertDeduplicate = true; - Boolean insertDistributedSync = true; - Boolean anyJoinDistinctRightTableKeys = true; - - ClickHouseProperties properties = new ClickHouseProperties(); - properties.setConnectionTimeout( expectedConnectionTimeout ); - properties.setMaxParallelReplicas( maxParallelReplicas ); - properties.setMaxPartitionsPerInsertBlock( maxPartitionsPerInsertBlock ); - properties.setCompress( isCompress ); - properties.setMaxInsertBlockSize(maxInsertBlockSize); - properties.setInsertDeduplicate(insertDeduplicate); - properties.setInsertDistributedSync(insertDistributedSync); - properties.setAnyJoinDistinctRightTableKeys(anyJoinDistinctRightTableKeys); - - ClickHouseDataSource clickHouseDataSource = new ClickHouseDataSource( - "jdbc:clickhouse://localhost:8123/test", - properties - ); - Assert.assertEquals( - clickHouseDataSource.getProperties().getConnectionTimeout(), - expectedConnectionTimeout - ); - Assert.assertEquals( - clickHouseDataSource.getProperties().isCompress(), - isCompress - ); - Assert.assertEquals( - clickHouseDataSource.getProperties().getMaxParallelReplicas(), - maxParallelReplicas - ); - Assert.assertEquals( - clickHouseDataSource.getProperties().getMaxPartitionsPerInsertBlock(), - maxPartitionsPerInsertBlock - ); - Assert.assertEquals( - clickHouseDataSource.getProperties().getTotalsMode(), - ClickHouseQueryParam.TOTALS_MODE.getDefaultValue() - ); - Assert.assertEquals( - clickHouseDataSource.getProperties().getMaxInsertBlockSize(), - maxInsertBlockSize - ); - Assert.assertEquals( - clickHouseDataSource.getProperties().getInsertDeduplicate(), - insertDeduplicate - ); - Assert.assertEquals( - clickHouseDataSource.getProperties().getInsertDistributedSync(), - insertDistributedSync - ); - Assert.assertEquals( - clickHouseDataSource.getProperties().getAnyJoinDistinctRightTableKeys(), - anyJoinDistinctRightTableKeys - ); - } - - @Test(groups = "unit") - public void additionalParametersTest_clickhouse_datasource() { - ClickHouseDataSource clickHouseDataSource = new ClickHouseDataSource("jdbc:clickhouse://localhost:1234/ppc?compress=1&decompress=1&user=root"); - - assertTrue(clickHouseDataSource.getProperties().isCompress()); - assertTrue(clickHouseDataSource.getProperties().isDecompress()); - assertEquals("root", clickHouseDataSource.getProperties().getUser()); - } - - @Test(groups = "unit") - public void additionalParametersTest_balanced_clickhouse_datasource() { - BalancedClickhouseDataSource clickHouseDataSource = new BalancedClickhouseDataSource("jdbc:clickhouse://localhost:1234,another.host.com:4321/ppc?compress=1&decompress=1&user=root"); - - assertTrue(clickHouseDataSource.getProperties().isCompress()); - assertTrue(clickHouseDataSource.getProperties().isDecompress()); - assertEquals("root", clickHouseDataSource.getProperties().getUser()); - } - - @Test(groups = "unit") - public void booleanParamCanBeParsedAsZeroAndOne() throws Exception { - Assert.assertTrue(new ClickHouseProperties().isCompress()); - Assert.assertFalse(new ClickHouseProperties(new Properties(){{setProperty("compress", "0");}}).isCompress()); - Assert.assertTrue(new ClickHouseProperties(new Properties(){{setProperty("compress", "1");}}).isCompress()); - } - - @Test(groups = "unit") - public void clickHouseQueryParamContainsMaxMemoryUsage() throws Exception { - final ClickHouseProperties clickHouseProperties = new ClickHouseProperties(); - clickHouseProperties.setMaxMemoryUsage(43L); - Assert.assertEquals(clickHouseProperties.asProperties().getProperty("max_memory_usage"), "43"); - } - - @Test(groups = "unit") - public void maxMemoryUsageParamShouldBeParsed() throws Exception { - final Properties driverProperties = new Properties(); - driverProperties.setProperty("max_memory_usage", "42"); - - ClickHouseDataSource ds = new ClickHouseDataSource("jdbc:clickhouse://localhost:8123/test", driverProperties); - Assert.assertEquals(ds.getProperties().getMaxMemoryUsage(), Long.valueOf(42L), "max_memory_usage is missing"); - } - - @Test(groups = "unit") - public void buildQueryParamsTest() { - ClickHouseProperties clickHouseProperties = new ClickHouseProperties(); - clickHouseProperties.setInsertQuorumTimeout(1000L); - clickHouseProperties.setInsertQuorum(3L); - clickHouseProperties.setSelectSequentialConsistency(1L); - clickHouseProperties.setMaxInsertBlockSize(42L); - clickHouseProperties.setInsertDeduplicate(true); - clickHouseProperties.setInsertDistributedSync(true); - clickHouseProperties.setUser("myUser"); - clickHouseProperties.setPassword("myPassword"); - - Map clickHouseQueryParams = clickHouseProperties.buildQueryParams(true); - Assert.assertEquals(clickHouseQueryParams.get(ClickHouseQueryParam.INSERT_QUORUM), "3"); - Assert.assertEquals(clickHouseQueryParams.get(ClickHouseQueryParam.INSERT_QUORUM_TIMEOUT), "1000"); - Assert.assertEquals(clickHouseQueryParams.get(ClickHouseQueryParam.SELECT_SEQUENTIAL_CONSISTENCY), "1"); - Assert.assertEquals(clickHouseQueryParams.get(ClickHouseQueryParam.MAX_INSERT_BLOCK_SIZE), "42"); - Assert.assertEquals(clickHouseQueryParams.get(ClickHouseQueryParam.INSERT_DEDUPLICATE), "1"); - Assert.assertEquals(clickHouseQueryParams.get(ClickHouseQueryParam.INSERT_DISTRIBUTED_SYNC), "1"); - assertFalse(clickHouseQueryParams.containsKey(ClickHouseQueryParam.USER)); - assertFalse(clickHouseQueryParams.containsKey(ClickHouseQueryParam.PASSWORD)); - } - - @Test(groups = "unit") - public void mergeClickHousePropertiesTest() { - ClickHouseProperties clickHouseProperties1 = new ClickHouseProperties(); - ClickHouseProperties clickHouseProperties2 = new ClickHouseProperties(); - clickHouseProperties1.setDatabase("click"); - clickHouseProperties1.setConnectionTimeout(13000); - clickHouseProperties2.setSocketTimeout(15000); - clickHouseProperties2.setUser("readonly"); - final ClickHouseProperties merged = clickHouseProperties1.merge(clickHouseProperties2); - // merge equals: clickHouseProperties1 overwrite with clickHouseProperties2's value or default not null value - Assert.assertEquals(merged.getDatabase(),"click"); // using properties1, because properties1 not setting and - // default value is null - Assert.assertEquals(merged.getConnectionTimeout(),ClickHouseConnectionSettings.CONNECTION_TIMEOUT.getDefaultValue());// overwrite with properties2's default value - Assert.assertEquals(merged.getSocketTimeout(),15000);// using properties2 - Assert.assertEquals(merged.getUser(),"readonly"); // using properties2 - } - - @Test(groups = "unit") - public void mergePropertiesTest() { - ClickHouseProperties clickHouseProperties1 = new ClickHouseProperties(); - Properties properties2 = new Properties(); - clickHouseProperties1.setDatabase("click"); - clickHouseProperties1.setMaxThreads(8); - clickHouseProperties1.setConnectionTimeout(13000); - properties2.put(ClickHouseConnectionSettings.SOCKET_TIMEOUT.getKey(), "15000"); - properties2.put(ClickHouseQueryParam.DATABASE.getKey(), "house"); - final ClickHouseProperties merged = clickHouseProperties1.merge(properties2); - // merge equals: clickHouseProperties1 overwrite with properties in properties2 not including default value - Assert.assertEquals( merged.getDatabase(),"house");// overwrite with properties2 - Assert.assertEquals(merged.getMaxThreads().intValue(),8);// using properties1 - Assert.assertEquals(merged.getConnectionTimeout(),13000);// using properties1 - Assert.assertEquals(merged.getSocketTimeout(),15000);// using properties2 - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseArrayUtilTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseArrayUtilTest.java deleted file mode 100644 index be83b1a60..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseArrayUtilTest.java +++ /dev/null @@ -1,662 +0,0 @@ -package ru.yandex.clickhouse.util; - -import java.math.BigDecimal; -import java.nio.charset.StandardCharsets; -import java.sql.Date; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.TimeZone; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; - -/** - * @author Dmitry Andreev - */ -public class ClickHouseArrayUtilTest { - - @Test(groups = "unit") - public void testArrayToString() throws Exception { - assertEquals( - ClickHouseArrayUtil.arrayToString(new String[]{"a", "b"}), - "['a','b']" - ); - - assertEquals( - ClickHouseArrayUtil.arrayToString(new String[]{"a", "'b\t"}), - "['a','\\'b\\t']" - ); - - assertEquals( - ClickHouseArrayUtil.arrayToString(new String[]{"\\xEF\\xBC", "\\x3C\\x22"}), // quote == true - "['\\\\xEF\\\\xBC','\\\\x3C\\\\x22']" - ); - - assertEquals( - ClickHouseArrayUtil.arrayToString(new Integer[]{21, 42}), - "[21,42]" - ); - - assertEquals( - ClickHouseArrayUtil.arrayToString(new int[]{21, 42}), - "[21,42]" - ); - - assertEquals( - ClickHouseArrayUtil.arrayToString(new double[]{0.1, 1.2}), - "[0.1,1.2]" - ); - - assertEquals( - ClickHouseArrayUtil.arrayToString(new char[]{'a', 'b'}), - "['a','b']" - ); - - assertEquals( - ClickHouseArrayUtil.arrayToString(new String[][]{{"a", "b"},{"c", "d"}}), - "[['a','b'],['c','d']]" - ); - - assertEquals( - ClickHouseArrayUtil.arrayToString(new String[][]{{"a", "'b\t"},{"c", "'d\t"}}), - "[['a','\\'b\\t'],['c','\\'d\\t']]" - ); - - assertEquals( - ClickHouseArrayUtil.arrayToString(new Integer[][]{{21, 42},{63, 84}}), - "[[21,42],[63,84]]" - ); - - assertEquals( - ClickHouseArrayUtil.arrayToString(new double[][]{{0.1, 1.2}, {0.2, 2.2}}), - "[[0.1,1.2],[0.2,2.2]]" - ); - - assertEquals( - ClickHouseArrayUtil.arrayToString(new int[][]{{1, 2}, {3, 4}}), - "[[1,2],[3,4]]" - ); - - assertEquals( - ClickHouseArrayUtil.arrayToString(new char[][]{{'a', 'b'}, {'c', 'd'}}), - "[['a','b'],['c','d']]" - ); - - assertEquals( - ClickHouseArrayUtil.arrayToString(new byte[][]{{'a', 'b'}, {'c', 'd'}}), - "['\\x61\\x62','\\x63\\x64']" - ); - - } - - @Test(groups = "unit") - public void testCollectionToString() throws Exception { - assertEquals( - ClickHouseArrayUtil.toString(new ArrayList(Arrays.asList("a", "b"))), - "['a','b']" - ); - - assertEquals( - ClickHouseArrayUtil.toString(new ArrayList(Arrays.asList("a", "'b\t"))), - "['a','\\'b\\t']" - ); - - assertEquals( - ClickHouseArrayUtil.toString(new ArrayList(Arrays.asList("\\xEF\\xBC", "\\x3C\\x22"))), // quote == true - "['\\\\xEF\\\\xBC','\\\\x3C\\\\x22']" - ); - - assertEquals( - ClickHouseArrayUtil.toString(new ArrayList(Arrays.asList(21, 42))), - "[21,42]" - ); - - assertEquals( - ClickHouseArrayUtil.toString(new ArrayList(Arrays.asList(21, 42))), - "[21,42]" - ); - - assertEquals( - ClickHouseArrayUtil.toString(new ArrayList(Arrays.asList(0.1, 1.2))), - "[0.1,1.2]" - ); - - assertEquals( - ClickHouseArrayUtil.toString(new ArrayList(Arrays.asList('a', 'b'))), - "['a','b']" - ); - - ArrayList arrayOfArrays = new ArrayList<>(); - arrayOfArrays.add(new ArrayList(Arrays.asList(1, 2))); - arrayOfArrays.add(new ArrayList(Arrays.asList(3, 4))); - assertEquals( - ClickHouseArrayUtil.toString(arrayOfArrays), - "[[1,2],[3,4]]" - ); - - arrayOfArrays = new ArrayList<>(); - arrayOfArrays.add(new ArrayList(Arrays.asList(1.1, 2.4))); - arrayOfArrays.add(new ArrayList(Arrays.asList(3.9, 4.16))); - assertEquals( - ClickHouseArrayUtil.toString(arrayOfArrays), - "[[1.1,2.4],[3.9,4.16]]" - ); - - arrayOfArrays = new ArrayList<>(); - arrayOfArrays.add(new ArrayList(Arrays.asList("a", "b"))); - arrayOfArrays.add(new ArrayList(Arrays.asList("c", "'d\t"))); - assertEquals( - ClickHouseArrayUtil.toString(arrayOfArrays), - "[['a','b'],['c','\\'d\\t']]" - ); - - arrayOfArrays = new ArrayList<>(); - arrayOfArrays.add(new ArrayList(Arrays.asList('a', 'b'))); - arrayOfArrays.add(new ArrayList(Arrays.asList('c', 'd'))); - assertEquals( - ClickHouseArrayUtil.toString(arrayOfArrays), - "[['a','b'],['c','d']]" - ); - - assertEquals( - ClickHouseArrayUtil.toString(new ArrayList(Arrays.asList(21, null))), - "[21,NULL]" - ); - - assertEquals( - ClickHouseArrayUtil.toString(new ArrayList(Arrays.asList(null, 42))), - "[NULL,42]" - ); - - assertEquals( - ClickHouseArrayUtil.toString(new ArrayList(Arrays.asList("a", null))), - "['a',NULL]" - ); - - assertEquals( - ClickHouseArrayUtil.toString(new ArrayList(Arrays.asList(null, "b"))), - "[NULL,'b']" - ); - - arrayOfArrays = new ArrayList<>(); - arrayOfArrays.add(new ArrayList(Arrays.asList(null, 'b'))); - arrayOfArrays.add(new ArrayList(Arrays.asList('c', 'd'))); - assertEquals( - ClickHouseArrayUtil.toString(arrayOfArrays), - "[[NULL,'b'],['c','d']]" - ); - - arrayOfArrays = new ArrayList<>(); - arrayOfArrays.add(new ArrayList(Arrays.asList(null, 'b'))); - arrayOfArrays.add(new ArrayList(Arrays.asList('c', null))); - assertEquals( - ClickHouseArrayUtil.toString(arrayOfArrays), - "[[NULL,'b'],['c',NULL]]" - ); - - List listOfByteArrays = new ArrayList<>(); - listOfByteArrays.add("foo".getBytes("UTF-8")); - listOfByteArrays.add("bar".getBytes("UTF-8")); - assertEquals( - ClickHouseArrayUtil.toString(listOfByteArrays), - "['\\x66\\x6F\\x6F','\\x62\\x61\\x72']" - ); - } - - @Test(groups = "unit") - public void testArrayDateTimeDefaultTimeZone() { - Timestamp ts0 = new Timestamp(1557136800000L); - Timestamp ts1 = new Timestamp(1560698526598L); - Timestamp[] timestamps = new Timestamp[] { ts0, null, ts1 }; - String formatted = ClickHouseArrayUtil.arrayToString(timestamps); - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - assertEquals( - formatted, - "['" + sdf.format(ts0) + "',NULL,'" + sdf.format(ts1) + "']"); - } - - @Test(groups = "unit") - public void testArrayDateTimeOtherTimeZone() { - TimeZone tzTokyo = TimeZone.getTimeZone("Asia/Tokyo"); - Timestamp ts0 = new Timestamp(1557136800000L); - Timestamp ts1 = new Timestamp(1560698526598L); - Timestamp[] timestamps = new Timestamp[] { ts0, null, ts1 }; - String formatted = ClickHouseArrayUtil.arrayToString( - timestamps, tzTokyo, tzTokyo); - assertEquals( - formatted, - "['2019-05-06 19:00:00',NULL,'2019-06-17 00:22:06']"); - } - - - @Test(groups = "unit", dataProvider = "doubleArrayWithNan") - public void testDoubleNan(String[] source, double[] expected) throws Exception - { - StringBuilder sb = new StringBuilder(); - for (String s : source) { - sb.append("','").append(s.replace("'", "\\'")); - } - if (sb.length() > 0) { - sb.deleteCharAt(0).deleteCharAt(0).append('\''); - } - sb.insert(0, "[").append("]"); - byte[] bytes = sb.toString().getBytes(StandardCharsets.UTF_8); - ByteFragment fragment = new ByteFragment(bytes, 0, bytes.length); - double[] arr= (double[]) ClickHouseArrayUtil.parseArray(fragment, Double.class, false, - getStringArrayColumnInfo(1)); - // TestNG Assert compares directly, but Double.NaN != Double.NaN - // assertEquals(arr, expected); - assertEquals(arr.length, expected.length); - for (int i = 0; i < expected.length; i++) { - double e = expected[i]; - if (Double.isNaN(e)) { - assertTrue(Double.isNaN(arr[i])); - } else { - assertEquals(arr[i], e, 0.0); - } - } - } - - @Test(groups = "unit", dataProvider = "floatArrayWithNan") - public void testFloatNan(String[] source, float[] expected) throws Exception - { - StringBuilder sb = new StringBuilder(); - for (String s : source) { - sb.append("','").append(s.replace("'", "\\'")); - } - if (sb.length() > 0) { - sb.deleteCharAt(0).deleteCharAt(0).append('\''); - } - sb.insert(0, "[").append("]"); - byte[] bytes = sb.toString().getBytes(StandardCharsets.UTF_8); - ByteFragment fragment = new ByteFragment(bytes, 0, bytes.length); - float[] arr= (float[]) ClickHouseArrayUtil.parseArray(fragment, Float.class, false, - getStringArrayColumnInfo(1)); - - assertEquals(arr.length, expected.length); - for (int i = 0; i < expected.length; i++) { - float e = expected[i]; - if (Float.isNaN(e)) { - assertTrue(Float.isNaN(arr[i])); - } else { - assertEquals(arr[i], e, 0.0); - } - } - } - - @Test(groups = "unit", dataProvider = "stringArray") - public void testParseArray(String[] array) throws Exception { - StringBuilder sb = new StringBuilder(); - for (String s : array) { - sb.append("','").append(s.replace("'", "\\'")); - } - if (sb.length() > 0) { - sb.deleteCharAt(0).deleteCharAt(0).append('\''); - } - sb.insert(0, "[").append("]"); - - byte[] bytes = sb.toString().getBytes(StandardCharsets.UTF_8); - ByteFragment fragment = new ByteFragment(bytes, 0, bytes.length); - String[] parsedArray = (String[]) ClickHouseArrayUtil.parseArray(fragment, String.class, false, - getStringArrayColumnInfo(1)); - - assertNotNull(parsedArray); - assertEquals(parsedArray.length, array.length); - for (int i = 0; i < parsedArray.length; i++) { - assertEquals(parsedArray[i], array[i]); - } - } - - @Test(groups = "unit", dataProvider = "intBoxedArray") - public void testParseBoxedArray(Integer[] array) throws Exception { - StringBuilder sb = new StringBuilder(); - for (Integer i : array) { - sb.append(",").append(i); - } - if (sb.length() > 0) { - sb.deleteCharAt(0); - } - sb.insert(0, "[").append("]"); - - byte[] bytes = sb.toString().getBytes(StandardCharsets.UTF_8); - ByteFragment fragment = new ByteFragment(bytes, 0, bytes.length); - Integer[] parsedArray = (Integer[]) ClickHouseArrayUtil.parseArray(fragment, Integer.class, true, - getStringArrayColumnInfo(1)); - - assertEquals(parsedArray.length, array.length); - for (int i = 0; i < parsedArray.length; i++) { - assertEquals(parsedArray[i], array[i]); - } - } - - @Test(groups = "unit", dataProvider = "longArray") - public void testParseArray(long[] array) throws Exception { - StringBuilder sb = new StringBuilder(); - for (long l : array) { - sb.append(",").append(l); - } - if (sb.length() > 0) { - sb.deleteCharAt(0); - } - sb.insert(0, "[").append("]"); - - byte[] bytes = sb.toString().getBytes(StandardCharsets.UTF_8); - ByteFragment fragment = new ByteFragment(bytes, 0, bytes.length); - long[] parsedArray = (long[]) ClickHouseArrayUtil.parseArray(fragment, Long.class, false, - getStringArrayColumnInfo(1)); - - assertEquals(parsedArray.length, array.length); - for (int i = 0; i < parsedArray.length; i++) { - assertEquals(parsedArray[i], array[i]); - } - } - - @Test(groups = "unit", dataProvider = "floatArray") - public void testParseArray(float[] array) throws Exception { - StringBuilder sb = new StringBuilder(); - for (float f : array) { - sb.append(",").append(f); - } - if (sb.length() > 0) { - sb.deleteCharAt(0); - } - sb.insert(0, "[").append("]"); - - byte[] bytes = sb.toString().getBytes(StandardCharsets.UTF_8); - ByteFragment fragment = new ByteFragment(bytes, 0, bytes.length); - float[] parsedArray = (float[]) ClickHouseArrayUtil.parseArray(fragment, Float.class, false, - getStringArrayColumnInfo(1)); - - assertEquals(parsedArray.length, array.length); - for (int i = 0; i < parsedArray.length; i++) { - assertEquals(parsedArray[i], array[i]); - } - } - - @Test(groups = "unit", dataProvider = "doubleArray") - public void testParseArray(double[] array) throws Exception { - StringBuilder sb = new StringBuilder(); - for (double d : array) { - sb.append(",").append(d); - } - if (sb.length() > 0) { - sb.deleteCharAt(0); - } - sb.insert(0, "[").append("]"); - - byte[] bytes = sb.toString().getBytes(StandardCharsets.UTF_8); - ByteFragment fragment = new ByteFragment(bytes, 0, bytes.length); - double[] parsedArray = (double[]) ClickHouseArrayUtil.parseArray(fragment, Double.class, false, - getStringArrayColumnInfo(1)); - - assertEquals(parsedArray.length, array.length); - for (int i = 0; i < parsedArray.length; i++) { - assertEquals(parsedArray[i], array[i]); - } - } - - @Test(groups = "unit", dataProvider = "booleanArray") - public void testParseArray(String[] input, boolean[] array) throws Exception { - String sourceString = "[" + String.join(",", input) + "]"; - byte[] bytes = sourceString.getBytes(StandardCharsets.UTF_8); - ByteFragment fragment = new ByteFragment(bytes, 0, bytes.length); - boolean[] parsedArray = (boolean[]) ClickHouseArrayUtil.parseArray( - fragment, Boolean.class, false, getStringArrayColumnInfo(1)); - assertEquals(parsedArray.length, array.length); - for (int i = 0; i < parsedArray.length; i++) { - assertEquals(parsedArray[i], array[i]); - } - } - - - @Test(groups = "unit", dataProvider = "dateArray") - public void testParseArray(Date[] array) throws Exception { - final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - StringBuilder sb = new StringBuilder(); - for (Date d : array) { - sb.append(",").append(dateFormat.format(d)); - } - if (sb.length() > 0) { - sb.deleteCharAt(0); - } - sb.insert(0, "[").append("]"); - - byte[] bytes = sb.toString().getBytes(StandardCharsets.UTF_8); - ByteFragment fragment = new ByteFragment(bytes, 0, bytes.length); - Date[] parsedArray = (Date[]) ClickHouseArrayUtil.parseArray(fragment, true, dateFormat.getTimeZone(), - ClickHouseColumnInfo.parse("Array(Date)", "myDate", null)); - - assertEquals(parsedArray.length, array.length); - for (int i = 0; i < parsedArray.length; i++) { - assertEquals(parsedArray[i], array[i]); - } - } - - @Test(groups = "unit", dataProvider = "decimalArray") - public void testParseArray(BigDecimal[] array) throws Exception { - StringBuilder sb = new StringBuilder(); - for (BigDecimal d : array) { - sb.append(",").append(d.toPlainString()); - } - if (sb.length() > 0) { - sb.deleteCharAt(0); - } - sb.insert(0, "[").append("]"); - - byte[] bytes = sb.toString().getBytes(StandardCharsets.UTF_8); - ByteFragment fragment = new ByteFragment(bytes, 0, bytes.length); - BigDecimal[] parsedArray = (BigDecimal[]) ClickHouseArrayUtil.parseArray(fragment, BigDecimal.class, true, - getStringArrayColumnInfo(1)); - - assertEquals(parsedArray.length, array.length); - for (int i = 0; i < parsedArray.length; i++) { - assertEquals(parsedArray[i], array[i]); - } - } - - @Test(groups = "unit") - public void testParseArrayThreeLevels() throws Exception { - int[][][] expected = {{{10,11,12},{13,14,15}},{{20,21,22},{23,24,25}},{{30,31,32},{33,34,35}}}; - String sourceString = "[[[10,11,12],[13,14,15]],[[20,21,22],[23,24,25]],[[30,31,32],[33,34,35]]]"; - byte[] bytes = sourceString.getBytes(StandardCharsets.UTF_8); - ByteFragment fragment = new ByteFragment(bytes, 0, bytes.length); - int[][][] actual = (int[][][]) ClickHouseArrayUtil.parseArray(fragment, Integer.class, false, - getStringArrayColumnInfo(3)); - // TestNG does not work like this - // assertEquals(actual, expected); - for (int i = 0; i < expected.length; i++) { - for (int j = 0; j < expected[i].length; j++) { - for (int k = 0; k < expected[i][j].length; k++) { - assertEquals(actual[i][j][k], expected[i][j][k]); - } - } - } - } - - @Test(groups = "unit") - public void testParseArrayTwoLevelsEmpty() throws Exception { - String sourceString = "[[]]"; - byte[] bytes = sourceString.getBytes(StandardCharsets.UTF_8); - ByteFragment fragment = new ByteFragment(bytes, 0, bytes.length); - String[][] actual = (String[][]) ClickHouseArrayUtil.parseArray(fragment, String.class, true, - getStringArrayColumnInfo(2)); - assertEquals(1, actual.length); - assertEquals(0, actual[0].length); - } - - @Test(groups = "unit") - public void testParseSparseArray() throws Exception { - String sourceString = "[[],[NULL],['a','b',NULL]]"; - byte[] bytes = sourceString.getBytes(StandardCharsets.UTF_8); - ByteFragment fragment = new ByteFragment(bytes, 0, bytes.length); - String[][] actual = (String[][]) ClickHouseArrayUtil.parseArray(fragment, String.class, true, - getStringArrayColumnInfo(2)); - assertEquals(3, actual.length); - assertEquals(0, actual[0].length); - assertEquals(1, actual[1].length); - assertEquals(3, actual[2].length); - assertNull(actual[1][0]); - assertEquals("a", actual[2][0]); - assertEquals("b", actual[2][1]); - assertNull(actual[2][2]); - } - - @Test(groups = "unit") - public void testParseArrayOf32Levels() throws Exception { - String sourceString = "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[32]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"; - byte[] bytes = sourceString.getBytes(StandardCharsets.UTF_8); - ByteFragment fragment = new ByteFragment(bytes, 0, bytes.length); - int[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] actual = - (int[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]) - ClickHouseArrayUtil.parseArray(fragment, Integer.class, false, getStringArrayColumnInfo(32)); - - assertEquals(actual[0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0], 32); - } - - @Test(groups = "unit", expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Maximum parse depth exceeded") - public void testParseArrayMaximumDepthExceeded() throws SQLException { - String sourceString = "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[33]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"; - byte[] bytes = sourceString.getBytes(StandardCharsets.UTF_8); - ByteFragment fragment = new ByteFragment(bytes, 0, bytes.length); - ClickHouseArrayUtil.parseArray(fragment, Integer.class, false, getStringArrayColumnInfo(33)); - } - - - @Test( - groups = "unit", - dataProvider = "invalidArray", - expectedExceptions = IllegalArgumentException.class, - expectedExceptionsMessageRegExp = "not an array.*" - ) - public void testParseInvalidArray(String sourceString, int arrayLevel) throws Exception { - byte[] bytes = sourceString.getBytes(StandardCharsets.UTF_8); - ByteFragment fragment = new ByteFragment(bytes, 0, bytes.length); - ClickHouseArrayUtil.parseArray(fragment, String.class, true, - getStringArrayColumnInfo(arrayLevel)); - } - - @DataProvider(name = "invalidArray") - private static Object[][] invalidArray() { - return new Object[][] { - {"['a']", 2}, // wrong level - {"[", 1}, - {"[]]", 2}, - {"[['a'],'b']", 2} // arrays of different levels - }; - } - - @DataProvider(name = "stringArray") - private static Object[][] stringArray() { - return new Object[][]{ - {new String[]{"a'aa", "a,,',,a"}}, - {new String[]{"a'','sadf',aa", "", ",", "юникод,'юникод'", ",2134,saldfk"}}, - {new String[]{"", ""}}, - {new String[]{""}}, - {new String[]{}} - }; - } - - @DataProvider(name = "intBoxedArray") - private static Object[][] intBoxedArray() { - return new Object[][]{ - {new Integer[]{1, 23, -123}}, - {new Integer[]{-87654321, 233252355, -12321342}}, - {new Integer[]{}} - }; - } - - @DataProvider(name = "longArray") - private static Object[][] longArray() { - return new Object[][]{ - {new long[]{1L, 23L, -123L}}, - {new long[]{-12345678987654321L, 23325235235L, -12321342L}}, - {new long[]{}} - }; - } - - @DataProvider(name = "decimalArray") - private static Object[][] decimalArray() { - return new Object[][]{ - {new BigDecimal[]{BigDecimal.ONE, BigDecimal.valueOf(23L), BigDecimal.valueOf(-123L)}}, - {new BigDecimal[]{BigDecimal.valueOf(-12345678987654321L), BigDecimal.valueOf(23325235235L), BigDecimal.valueOf(-12321342L)}}, - {new BigDecimal[]{}} - }; - } - - @DataProvider(name = "floatArray") - private static Object[][] floatArray() { - return new Object[][]{ - {new float[]{1F, 23F, -123F}}, - {new float[]{-123123123.123123F, 2332.12334234234F, -12321342F}}, - {new float[]{}} - }; - } - - @DataProvider(name = "doubleArray") - private static Object[][] doubleArray() { - return new Object[][]{ - {new double[]{1, 23, -123}}, - {new double[]{-123123123.123123, 2332.12334234234, -12321342}}, - {new double[]{}} - }; - } - - @DataProvider(name = "dateArray") - private static Object[][] dateArray() { - return new Object[][]{ - {new Date[]{new Date(0L)}}, - {new Date[]{new Date(1263945600000L), new Date(1606780800000L)}}, - {new Date[]{}} - }; - } - - @DataProvider(name = "doubleArrayWithNan") - private static Object[][] doubleArrayWithNan() { - return new Object[][]{ - { new String[]{ "nan", "23.45" }, new double[]{Double.NaN, 23.45}}, - { new String[]{}, new double[]{}} - }; - } - - @DataProvider(name = "floatArrayWithNan") - private static Object[][] floatArrayWithNan() { - return new Object[][]{ - { new String[]{ "nan", "23.45" }, new float[]{Float.NaN, 23.45F}}, - { new String[]{}, new float[]{}} - }; - } - - @DataProvider(name = "booleanArray") - private static Object[][] booleanArrayWithNan() { - return new Object[][]{ - { new String[]{ "1", "0" }, new boolean[]{ true, false }}, - { new String[]{ "1", "\\N", "1", "0"}, new boolean[]{ true, false, true, false }} - }; - } - - private static ClickHouseColumnInfo getStringArrayColumnInfo(int level) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < level; i++) { - sb.append("Array("); - } - sb.append("String"); - for (int i = 0; i < level; i++) { - sb.append(")"); - } - return ClickHouseColumnInfo.parse(sb.toString(), "columnName", null); - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseBitmapTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseBitmapTest.java deleted file mode 100644 index 6be49e923..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseBitmapTest.java +++ /dev/null @@ -1,29 +0,0 @@ -package ru.yandex.clickhouse.util; - -import static org.testng.Assert.assertEquals; - -import org.roaringbitmap.RoaringBitmap; -import org.roaringbitmap.buffer.ImmutableRoaringBitmap; -import org.roaringbitmap.buffer.MutableRoaringBitmap; -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.domain.ClickHouseDataType; - -public class ClickHouseBitmapTest { - @Test(groups = "unit") - public void testEmptyRoaringBitmap() { - byte[] expectedBytes = new byte[] { 0, 0 }; - - ClickHouseDataType[] types = new ClickHouseDataType[] { ClickHouseDataType.Int8, ClickHouseDataType.UInt8, - ClickHouseDataType.Int16, ClickHouseDataType.UInt16, ClickHouseDataType.Int32, - ClickHouseDataType.UInt32 }; - Object[] bitmaps = new Object[] { RoaringBitmap.bitmapOf(), MutableRoaringBitmap.bitmapOf(), - ImmutableRoaringBitmap.bitmapOf() }; - - for (Object bm : bitmaps) { - for (ClickHouseDataType t : types) { - assertEquals(ClickHouseBitmap.wrap(bm, t).toBytes(), expectedBytes); - } - } - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseBlockChecksumTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseBlockChecksumTest.java deleted file mode 100644 index a4eb4e767..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseBlockChecksumTest.java +++ /dev/null @@ -1,83 +0,0 @@ -package ru.yandex.clickhouse.util; - -import org.testng.Assert; -import org.testng.annotations.Test; -import ru.yandex.clickhouse.response.ClickHouseLZ4Stream; - -/** - * @author Anton Sukhonosenko - * @date 08.06.18 - */ -public class ClickHouseBlockChecksumTest { - private static final int HEADER_SIZE_BYTES = 9; - - private static int hexToBin(char ch) { - if ('0' <= ch && ch <= '9') { - return ch - '0'; - } - if ('A' <= ch && ch <= 'F') { - return ch - 'A' + 10; - } - if ('a' <= ch && ch <= 'f') { - return ch - 'a' + 10; - } - return -1; - } - - private static byte[] parseHexBinary(String s) { - final int len = s.length(); - - // "111" is not a valid hex encoding. - if (len % 2 != 0) { - throw new IllegalArgumentException("hexBinary needs to be even-length: " + s); - } - - byte[] out = new byte[len / 2]; - - for (int i = 0; i < len; i += 2) { - int h = hexToBin(s.charAt(i)); - int l = hexToBin(s.charAt(i + 1)); - if (h == -1 || l == -1) { - throw new IllegalArgumentException("contains illegal character for hexBinary: " + s); - } - - out[i / 2] = (byte) (h * 16 + l); - } - - return out; - } - - @Test(groups = "unit") - public void trickyBlock() { - byte[] compressedData = parseHexBinary("1F000100078078000000B4000000"); - int uncompressedSizeBytes = 35; - - ClickHouseBlockChecksum checksum = ClickHouseBlockChecksum.calculateForBlock( - (byte) ClickHouseLZ4Stream.MAGIC, - compressedData.length + HEADER_SIZE_BYTES, - uncompressedSizeBytes, - compressedData, - compressedData.length); - - Assert.assertEquals( - new ClickHouseBlockChecksum(-493639813825217902L, -6253550521065361778L), - checksum); - } - - @Test(groups = "unit") - public void anotherTrickyBlock() { - byte[] compressedData = parseHexBinary("80D9CEF753E3A59B3F"); - int uncompressedSizeBytes = 8; - - ClickHouseBlockChecksum checksum = ClickHouseBlockChecksum.calculateForBlock( - (byte) ClickHouseLZ4Stream.MAGIC, - compressedData.length + HEADER_SIZE_BYTES, - uncompressedSizeBytes, - compressedData, - compressedData.length); - - Assert.assertEquals( - new ClickHouseBlockChecksum(-7135037831041210418L, -8214889029657590490L), - checksum); - } -} \ No newline at end of file diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseCookieStoreProviderTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseCookieStoreProviderTest.java deleted file mode 100644 index a21258e39..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseCookieStoreProviderTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package ru.yandex.clickhouse.util; - -import org.testng.annotations.Test; -import ru.yandex.clickhouse.settings.ClickHouseProperties; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertNull; - -public class ClickHouseCookieStoreProviderTest { - ClickHouseCookieStoreProvider cookieStoreProvider = new ClickHouseCookieStoreProvider(); - - @Test(groups = "unit") - public void testCookieStoreProviderWithNullHost() { - ClickHouseProperties props = new ClickHouseProperties(); - props.setUseSharedCookieStore(true); - props.setPort(8080); - props.setDatabase("default"); - assertNull(cookieStoreProvider.getCookieStore(props)); - } - - @Test(groups = "unit") - public void testCookieStoreProviderWithInvalidPort() { - ClickHouseProperties props = new ClickHouseProperties(); - props.setUseSharedCookieStore(true); - props.setHost("127.0.0.1"); - props.setPort(0); - props.setDatabase("default"); - assertNull(cookieStoreProvider.getCookieStore(props)); - } - - @Test(groups = "unit") - public void testCookieStoreProviderWithNullDBName() { - ClickHouseProperties props = new ClickHouseProperties(); - props.setUseSharedCookieStore(true); - props.setHost("127.0.0.1"); - props.setPort(0); - assertNull(cookieStoreProvider.getCookieStore(props)); - } - - @Test(groups = "unit") - public void testCookieStoreProviderWithSameDBAndSharedCookieStore() { - ClickHouseProperties props = new ClickHouseProperties(); - props.setUseSharedCookieStore(true); - props.setHost("127.0.0.1"); - props.setPort(8080); - props.setDatabase("default"); - assertNotNull(cookieStoreProvider.getCookieStore(props)); - assertEquals(cookieStoreProvider.getCookieStore(props), cookieStoreProvider.getCookieStore(props)); - } - - @Test(groups = "unit") - public void testCookieStoreProviderWithPrivateCookieStore() { - ClickHouseProperties props = new ClickHouseProperties(); - props.setUseSharedCookieStore(false); - props.setHost("127.0.0.1"); - props.setPort(8080); - props.setDatabase("default"); - assertNull(cookieStoreProvider.getCookieStore(props)); - } - - @Test(groups = "unit") - public void testCookieStoreProviderWithDiffDB() { - ClickHouseProperties props1 = new ClickHouseProperties(); - props1.setUseSharedCookieStore(true); - props1.setHost("127.0.0.1"); - props1.setPort(8080); - props1.setDatabase("default1"); - ClickHouseProperties props2 = new ClickHouseProperties(props1); - props2.setDatabase("default2"); - assertNotEquals(cookieStoreProvider.getCookieStore(props1), cookieStoreProvider.getCookieStore(props2)); - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseHttpClientBuilderTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseHttpClientBuilderTest.java deleted file mode 100644 index a88db92a3..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseHttpClientBuilderTest.java +++ /dev/null @@ -1,317 +0,0 @@ -package ru.yandex.clickhouse.util; - -import org.apache.http.HttpHost; -import org.apache.http.HttpResponse; -import org.apache.http.NoHttpResponseException; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.conn.HttpHostConnectException; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.protocol.BasicHttpContext; -import org.apache.http.protocol.HttpContext; -import org.apache.http.util.EntityUtils; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import com.github.tomakehurst.wiremock.WireMockServer; -import com.github.tomakehurst.wiremock.client.WireMock; -import com.github.tomakehurst.wiremock.core.WireMockConfiguration; - -import ru.yandex.clickhouse.settings.ClickHouseProperties; - -import java.time.Instant; - -import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNull; - -import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; -import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; - - -public class ClickHouseHttpClientBuilderTest { - - private static WireMockServer mockServer; - - @BeforeClass(groups = "unit") - public static void beforeAll() { - mockServer = new WireMockServer( - WireMockConfiguration.wireMockConfig().dynamicPort()); - mockServer.start(); - } - - @AfterMethod(groups = "unit") - public void afterTest() { - mockServer.resetAll(); - } - - @AfterClass(groups = "unit") - public static void afterAll() { - mockServer.stop(); - mockServer = null; - } - - @Test(groups = "unit") - public void testCreateClientContextNull() { - assertNull(ClickHouseHttpClientBuilder.createClientContext(null).getAuthCache()); - } - - @Test(groups = "unit") - public void testCreateClientContextNoUserNoPass() { - assertNull(ClickHouseHttpClientBuilder.createClientContext(new ClickHouseProperties()) - .getAuthCache()); - } - - @Test(groups = "unit") - public void testCreateClientContextNoHost() { - ClickHouseProperties props = new ClickHouseProperties(); - props.setUser("myUser"); - props.setPassword("mySecret"); - assertNull(ClickHouseHttpClientBuilder.createClientContext(props).getAuthCache()); - } - - @Test(groups = "unit") - public void testCreateClientContextUserPass() { - ClickHouseProperties props = new ClickHouseProperties(); - props.setUser("myUser"); - props.setPassword("mySecret"); - props.setHost("127.0.0.1"); - assertEquals( - ClickHouseHttpClientBuilder.createClientContext(props).getAuthCache() - .get(HttpHost.create("http://127.0.0.1:80")).getSchemeName(), - "basic"); - } - - @Test(groups = "unit") - public void testCreateClientContextOnlyUser() { - ClickHouseProperties props = new ClickHouseProperties(); - props.setUser("myUser"); - props.setHost("127.0.0.1"); - assertEquals( - ClickHouseHttpClientBuilder.createClientContext(props).getAuthCache() - .get(HttpHost.create("http://127.0.0.1:80")).getSchemeName(), - "basic"); - } - - @Test(groups = "unit") - public void testCreateClientContextOnlyPass() { - ClickHouseProperties props = new ClickHouseProperties(); - props.setPassword("myPass"); - props.setHost("127.0.0.1"); - assertEquals( - ClickHouseHttpClientBuilder.createClientContext(props).getAuthCache() - .get(HttpHost.create("http://127.0.0.1:80")).getSchemeName(), - "basic"); - } - - @Test(groups = "unit") - public void testHttpClientsWithSharedCookie() throws Exception { - ClickHouseProperties props = new ClickHouseProperties(); - props.setHost("localhost"); - props.setPort(mockServer.port()); - props.setDatabase("default"); - props.setUseSharedCookieStore(true); - CloseableHttpClient client = new ClickHouseHttpClientBuilder(props).buildClient(); - String cookie = "AWS-ALB=random-value-" + Instant.now().toEpochMilli(); - mockServer.stubFor(WireMock.get(WireMock.urlPathMatching("/cookie/get")) - .willReturn(WireMock.aResponse() - .withStatus(200) - .withHeader("set-cookie", cookie) - .withBody("OK"))); - HttpGet getCookie = new HttpGet(mockServer.baseUrl() + "/cookie/get"); - client.execute(getCookie); - CloseableHttpClient clientWithSharedCookieStore = new ClickHouseHttpClientBuilder(props).buildClient(); - props.setUseSharedCookieStore(false); - CloseableHttpClient clientWithPrivateCookieStore = new ClickHouseHttpClientBuilder(props).buildClient(); - HttpGet checkCookie = new HttpGet(mockServer.baseUrl() + "/cookie/check"); - clientWithPrivateCookieStore.execute(checkCookie); - mockServer.verify(getRequestedFor(WireMock.urlEqualTo("/cookie/check")).withoutHeader("cookie")); - clientWithSharedCookieStore.execute(checkCookie); - mockServer.verify(getRequestedFor(WireMock.urlEqualTo("/cookie/check")).withHeader("cookie", equalTo(cookie))); - } - - @Test(groups = "unit", dataProvider = "authUserPassword") - public void testHttpAuthParametersCombination(String authorization, String user, - String password, String expectedAuthHeader) throws Exception - { - ClickHouseProperties props = new ClickHouseProperties(); - props.setHost("localhost"); - props.setPort(mockServer.port()); - props.setUser(user); - props.setPassword(password); - props.setHttpAuthorization(authorization); - CloseableHttpClient client = new ClickHouseHttpClientBuilder(props).buildClient(); - HttpPost post = new HttpPost(mockServer.baseUrl()); - client.execute(post, ClickHouseHttpClientBuilder.createClientContext(props)); - mockServer.verify( - postRequestedFor(WireMock.anyUrl()) - .withHeader("Authorization", equalTo(expectedAuthHeader))); - } - - @DataProvider(name = "authUserPassword") - private static Object[][] provideAuthUserPasswordTestData() { - return new Object[][] { - { - "Digest username=\"foo\"", null, null, "Digest username=\"foo\"" - }, - { - "Digest username=\"foo\"", "bar", null, "Digest username=\"foo\"" - }, - { - "Digest username=\"foo\"", null, "baz", "Digest username=\"foo\"" - }, - { - "Digest username=\"foo\"", "bar", "baz", "Digest username=\"foo\"" - }, - { - null, "bar", "baz", "Basic YmFyOmJheg==" // bar:baz - }, - { - null, "bar", null, "Basic YmFyOg==" // bar: - }, - { - null, null, "baz", "Basic ZGVmYXVsdDpiYXo=" // default:baz - }, - }; - } - - private static WireMockServer newServer(int delayMillis) { - WireMockServer server = new WireMockServer( - WireMockConfiguration.wireMockConfig().dynamicPort()); - server.start(); - server.stubFor(WireMock.post(WireMock.urlPathMatching("/*")) - .willReturn(WireMock.aResponse().withStatus(200).withHeader("Connection", "Keep-Alive") - .withHeader("Content-Type", "text/plain; charset=UTF-8") - .withHeader("Transfer-Encoding", "chunked").withHeader("Keep-Alive", "timeout=3") - .withBody("OK.........................").withFixedDelay(delayMillis))); - return server; - } - - private static WireMockServer newServer() { - return newServer(2); - } - - private static void shutDownServerWithDelay(final WireMockServer server, final long delayMs) { - new Thread() { - public void run() { - try { - Thread.sleep(delayMs); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - server.shutdownServer(); - server.stop(); - } - }.start(); - } - - @Test(expectedExceptions = { NoHttpResponseException.class }) - public void testReproduceFailedToResponseProblem() throws Exception { - final WireMockServer server = newServer(2); - - ClickHouseProperties props = new ClickHouseProperties(); - // Disable retry when "failed to respond" occurs. - props.setMaxRetries(0); - // Disable validation to reproduce "failed to respond" problem - props.setValidateAfterInactivityMillis(0); - // Ensure there is exactly one TCP connection in connection pool and therefore be re-used between - // multiple http requests. - props.setMaxTotal(1); - props.setDefaultMaxPerRoute(1); - - ClickHouseHttpClientBuilder builder = new ClickHouseHttpClientBuilder(props); - CloseableHttpClient client = builder.buildClient(); - HttpPost post = new HttpPost("http://localhost:" + server.port() + "/?db=system&query=select%201"); - - try { - // Make the 1st http request to establish one tcp connection and keep it in the pool. - { - HttpResponse response = client.execute(post); - EntityUtils.consume(response.getEntity()); - } - - // Close the server, now the pooling tcp connection is half closed. - server.shutdownServer(); - server.stop(); - - // The 2nd http request will re-use the pooling tcp connection which is stale - // and "failed to respond" occurs. - { - HttpResponse response = client.execute(post); - EntityUtils.consume(response.getEntity()); - } - } finally { - client.close(); - } - } - - @Test(expectedExceptions = { HttpHostConnectException.class }) - public void testEnableValidation() throws Exception { - final WireMockServer server = newServer(2); - - ClickHouseProperties props = new ClickHouseProperties(); - // Disable retry when "failed to respond" occurs. - props.setMaxRetries(0); - // Disable validation to reproduce "failed to respond" problem - props.setValidateAfterInactivityMillis(1); - // Ensure there is exactly one TCP connection in connection pool and therefore be re-used between - // multiple http requests. - props.setMaxTotal(1); - props.setDefaultMaxPerRoute(1); - - ClickHouseHttpClientBuilder builder = new ClickHouseHttpClientBuilder(props); - CloseableHttpClient client = builder.buildClient(); - HttpPost post = new HttpPost("http://localhost:" + server.port() + "/?db=system&query=select%201"); - - try { - // Make the 1st http request to establish one tcp connection and keep it in the pool. - { - HttpResponse response = client.execute(post); - EntityUtils.consume(response.getEntity()); - } - - // Sleep a while to wait for the validation reaches inactivity timeout. - Thread.sleep(5); - - // Close the server, now the pooling tcp connection is half closed. - server.shutdownServer(); - server.stop(); - - // The 2nd http request re-uses the pooling tcp connection. - // But the validation checks that the connection has been stale, thus a - // new tcp connection is attempted to establish to the closed server - // which leads to HttpHostConnectException. - { - HttpResponse response = client.execute(post); - EntityUtils.consume(response.getEntity()); - } - } finally { - client.close(); - } - } - - @Test(expectedExceptions = { HttpHostConnectException.class }) - public void testWithRetry() throws Exception { - final WireMockServer server = newServer(500); - - ClickHouseProperties props = new ClickHouseProperties(); - props.setMaxRetries(3); - ClickHouseHttpClientBuilder builder = new ClickHouseHttpClientBuilder(props); - CloseableHttpClient client = builder.buildClient(); - HttpContext context = new BasicHttpContext(); - context.setAttribute("is_idempotent", Boolean.TRUE); - HttpPost post = new HttpPost("http://localhost:" + server.port() + "/?db=system&query=select%202"); - - shutDownServerWithDelay(server, 100); - - try { - client.execute(post, context); - } finally { - client.close(); - } - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseLZ4OutputStreamTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseLZ4OutputStreamTest.java deleted file mode 100644 index 2a89a2c3c..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseLZ4OutputStreamTest.java +++ /dev/null @@ -1,209 +0,0 @@ -package ru.yandex.clickhouse.util; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import org.testng.Assert; -import org.testng.annotations.Test; - -public class ClickHouseLZ4OutputStreamTest { - private byte[] genCompressedByts(int b, int length, int blockSize) throws IOException { - ByteArrayOutputStream bas = new ByteArrayOutputStream(blockSize * 512); - try (ClickHouseLZ4OutputStream out = new ClickHouseLZ4OutputStream(bas, blockSize)) { - for (int i = 0; i < length; i++) { - out.write(b); - } - out.flush(); - } - - byte[] bytes = bas.toByteArray(); - bas.close(); - return bytes; - } - - @Test(groups = "unit") - public void testWrite() throws IOException { - ByteArrayOutputStream bas = new ByteArrayOutputStream(64); - - try (ClickHouseLZ4OutputStream out = new ClickHouseLZ4OutputStream(bas, 2)) { - byte[] bytes = new byte[] { (byte) -36, (byte) -86, (byte) 31, (byte) 113, (byte) -106, (byte) 44, - (byte) 99, (byte) 96, (byte) 112, (byte) -7, (byte) 47, (byte) 15, (byte) -63, (byte) 39, - (byte) -73, (byte) -104, (byte) -126, (byte) 12, (byte) 0, (byte) 0, (byte) 0, (byte) 2, (byte) 0, - (byte) 0, (byte) 0, (byte) 32, (byte) 1, (byte) 2 }; - out.write(1); - Assert.assertEquals(bas.toByteArray(), new byte[0]); - out.write(2); - Assert.assertEquals(bas.toByteArray(), bytes); - out.write(3); - Assert.assertEquals(bas.toByteArray(), bytes); - out.flush(); - Assert.assertEquals(bas.toByteArray(), - new byte[] { (byte) -36, (byte) -86, (byte) 31, (byte) 113, (byte) -106, (byte) 44, (byte) 99, - (byte) 96, (byte) 112, (byte) -7, (byte) 47, (byte) 15, (byte) -63, (byte) 39, (byte) -73, - (byte) -104, (byte) -126, (byte) 12, (byte) 0, (byte) 0, (byte) 0, (byte) 2, (byte) 0, - (byte) 0, (byte) 0, (byte) 32, (byte) 1, (byte) 2, (byte) 64, (byte) -39, (byte) 21, - (byte) 50, (byte) -77, (byte) -124, (byte) 25, (byte) 73, (byte) -59, (byte) 9, (byte) 112, - (byte) -38, (byte) 12, (byte) 99, (byte) 71, (byte) 74, (byte) -126, (byte) 11, (byte) 0, - (byte) 0, (byte) 0, (byte) 1, (byte) 0, (byte) 0, (byte) 0, (byte) 16, (byte) 3 }); - bas.close(); - } - } - - @Test(groups = "unit") - public void testWriteBytes() throws IOException { - Assert.assertThrows(NullPointerException.class, new Assert.ThrowingRunnable() { - @Override - public void run() throws Throwable { - try (ClickHouseLZ4OutputStream out = new ClickHouseLZ4OutputStream(new ByteArrayOutputStream(), 3)) { - out.write(null); - } - } - }); - - ByteArrayOutputStream bas = new ByteArrayOutputStream(64); - try (ClickHouseLZ4OutputStream out = new ClickHouseLZ4OutputStream(bas, 3)) { - out.write(new byte[0]); - Assert.assertEquals(bas.toByteArray(), new byte[0]); - out.flush(); - Assert.assertEquals(bas.toByteArray(), new byte[0]); - - byte[] bytes = new byte[] { (byte) 13, (byte) 13 }; - out.write(bytes); - Assert.assertEquals(bas.toByteArray(), new byte[0]); - out.flush(); - Assert.assertEquals(bas.toByteArray(), genCompressedByts(13, 2, 3)); - bas.close(); - } - - bas = new ByteArrayOutputStream(64); - try (ClickHouseLZ4OutputStream out = new ClickHouseLZ4OutputStream(bas, 3)) { - byte[] bytes = new byte[] { (byte) 13, (byte) 13, (byte) 13 }; - out.write(bytes); - byte[] expected = genCompressedByts(13, 3, 3); - Assert.assertEquals(bas.toByteArray(), expected); - out.flush(); - Assert.assertEquals(bas.toByteArray(), expected); - bas.close(); - } - - bas = new ByteArrayOutputStream(64); - try (ClickHouseLZ4OutputStream out = new ClickHouseLZ4OutputStream(bas, 3)) { - byte[] bytes = new byte[] { (byte) 13, (byte) 13, (byte) 13, (byte) 13 }; - out.write(bytes); - Assert.assertEquals(bas.toByteArray(), genCompressedByts(13, 3, 3)); - out.flush(); - Assert.assertEquals(bas.toByteArray(), genCompressedByts(13, 4, 3)); - bas.close(); - } - - bas = new ByteArrayOutputStream(64); - try (ClickHouseLZ4OutputStream out = new ClickHouseLZ4OutputStream(bas, 3)) { - byte[] bytes = new byte[] { (byte) 13, (byte) 13, (byte) 13, (byte) 13, (byte) 13, (byte) 13 }; - out.write(bytes); - byte[] expected = genCompressedByts(13, 6, 3); - Assert.assertEquals(bas.toByteArray(), expected); - out.flush(); - Assert.assertEquals(bas.toByteArray(), expected); - bas.close(); - } - - bas = new ByteArrayOutputStream(64); - try (ClickHouseLZ4OutputStream out = new ClickHouseLZ4OutputStream(bas, 3)) { - byte[] bytes = new byte[] { (byte) 13, (byte) 13, (byte) 13, (byte) 13, (byte) 13, (byte) 13, (byte) 13 }; - out.write(bytes); - Assert.assertEquals(bas.toByteArray(), genCompressedByts(13, 6, 3)); - out.flush(); - Assert.assertEquals(bas.toByteArray(), genCompressedByts(13, 7, 3)); - bas.close(); - } - } - - @Test(groups = "unit") - public void testWriteBytesWithOffset() throws IOException { - Assert.assertThrows(NullPointerException.class, new Assert.ThrowingRunnable() { - @Override - public void run() throws Throwable { - try (ClickHouseLZ4OutputStream out = new ClickHouseLZ4OutputStream(new ByteArrayOutputStream(), 3)) { - out.write(null, 0, 1); - } - } - }); - Assert.assertThrows(IndexOutOfBoundsException.class, new Assert.ThrowingRunnable() { - @Override - public void run() throws Throwable { - try (ClickHouseLZ4OutputStream out = new ClickHouseLZ4OutputStream(new ByteArrayOutputStream(), 3)) { - out.write(new byte[0], 0, 1); - } - } - }); - Assert.assertThrows(IndexOutOfBoundsException.class, new Assert.ThrowingRunnable() { - @Override - public void run() throws Throwable { - try (ClickHouseLZ4OutputStream out = new ClickHouseLZ4OutputStream(new ByteArrayOutputStream(), 3)) { - out.write(new byte[0], -1, 0); - } - } - }); - Assert.assertThrows(IndexOutOfBoundsException.class, new Assert.ThrowingRunnable() { - @Override - public void run() throws Throwable { - try (ClickHouseLZ4OutputStream out = new ClickHouseLZ4OutputStream(new ByteArrayOutputStream(), 3)) { - out.write(new byte[1], 1, 1); - } - } - }); - - final byte[] bytes = new byte[] { (byte) 0, (byte) 13, (byte) 13, (byte) 13, (byte) 13, (byte) 13, (byte) 13, - (byte) 13, (byte) 0 }; - ByteArrayOutputStream bas = new ByteArrayOutputStream(64); - try (ClickHouseLZ4OutputStream out = new ClickHouseLZ4OutputStream(bas, 3)) { - out.write(bytes, 1, 0); - Assert.assertEquals(bas.toByteArray(), new byte[0]); - out.flush(); - Assert.assertEquals(bas.toByteArray(), new byte[0]); - out.write(bytes, 1, 2); - Assert.assertEquals(bas.toByteArray(), new byte[0]); - out.flush(); - Assert.assertEquals(bas.toByteArray(), genCompressedByts(13, 2, 3)); - bas.close(); - } - - bas = new ByteArrayOutputStream(64); - try (ClickHouseLZ4OutputStream out = new ClickHouseLZ4OutputStream(bas, 3)) { - out.write(bytes, 1, 3); - byte[] expected = genCompressedByts(13, 3, 3); - Assert.assertEquals(bas.toByteArray(), expected); - out.flush(); - Assert.assertEquals(bas.toByteArray(), expected); - bas.close(); - } - - bas = new ByteArrayOutputStream(64); - try (ClickHouseLZ4OutputStream out = new ClickHouseLZ4OutputStream(bas, 3)) { - out.write(bytes, 1, 4); - Assert.assertEquals(bas.toByteArray(), genCompressedByts(13, 3, 3)); - out.flush(); - Assert.assertEquals(bas.toByteArray(), genCompressedByts(13, 4, 3)); - bas.close(); - } - - bas = new ByteArrayOutputStream(64); - try (ClickHouseLZ4OutputStream out = new ClickHouseLZ4OutputStream(bas, 3)) { - out.write(bytes, 1, 6); - byte[] expected = genCompressedByts(13, 6, 3); - Assert.assertEquals(bas.toByteArray(), expected); - out.flush(); - Assert.assertEquals(bas.toByteArray(), expected); - bas.close(); - } - - bas = new ByteArrayOutputStream(64); - try (ClickHouseLZ4OutputStream out = new ClickHouseLZ4OutputStream(bas, 3)) { - out.write(bytes, 1, 7); - Assert.assertEquals(bas.toByteArray(), genCompressedByts(13, 6, 3)); - out.flush(); - Assert.assertEquals(bas.toByteArray(), genCompressedByts(13, 7, 3)); - bas.close(); - } - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseRowBinaryInputStreamTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseRowBinaryInputStreamTest.java deleted file mode 100644 index 4650206c1..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseRowBinaryInputStreamTest.java +++ /dev/null @@ -1,133 +0,0 @@ -package ru.yandex.clickhouse.util; - -import org.testng.annotations.Test; -import ru.yandex.clickhouse.settings.ClickHouseProperties; - -import java.io.ByteArrayInputStream; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.Date; -import java.util.TimeZone; - -import static org.testng.Assert.assertEquals; - -public class ClickHouseRowBinaryInputStreamTest { - - @Test(groups = "unit") - public void testUInt8() throws Exception { - ClickHouseRowBinaryInputStream input = prepareStream(new byte[]{1, 0, 1, 0, -1, -128}); - - assertEquals(input.readBoolean(), true); - assertEquals(input.readBoolean(), false); - assertEquals(input.readUInt8(), 1); - assertEquals(input.readUInt8(), 0); - assertEquals(input.readUInt8(), 255); - assertEquals(input.readUInt8(), 128); - } - - @Test(groups = "unit") - public void testUInt8AsByte() throws Exception { - ClickHouseRowBinaryInputStream input = prepareStream(new byte[]{1, 0, 1, 0, -1, -128}); - - assertEquals(input.readUInt8AsByte(), (byte) 1); - assertEquals(input.readUInt8AsByte(), (byte) 0); - assertEquals(input.readUInt8AsByte(), (byte) 1); - assertEquals(input.readUInt8AsByte(), (byte) 0); - assertEquals(input.readUInt8AsByte(), (byte) 255); - assertEquals(input.readUInt8AsByte(), (byte) 128); - } - - @Test(groups = "unit") - public void testUInt16() throws Exception { - ClickHouseRowBinaryInputStream input = prepareStream(new byte[]{0, 0, -1, -1, 0, -128}); - - assertEquals(input.readUInt16(), 0); - assertEquals(input.readUInt16(), 65535); - assertEquals(input.readUInt16(), 32768); - } - - @Test(groups = "unit") - public void testUInt16AsShort() throws Exception { - ClickHouseRowBinaryInputStream input = prepareStream(new byte[]{0, 0, -1, -1, 0, -128}); - - assertEquals(input.readUInt16AsShort(), (short) 0); - assertEquals(input.readUInt16AsShort(), (short) 65535); - assertEquals(input.readUInt16AsShort(), (short) 32768); - } - - - @Test(groups = "unit") - public void testFloat64() throws Exception { - ClickHouseRowBinaryInputStream input = prepareStream(new byte[]{0, 0, 0, 0, 0, 0, -8, 127}); - - assertEquals(input.readFloat64(), Double.NaN); - } - - @Test(groups = "unit") - public void testUInt64() throws Exception { - ClickHouseRowBinaryInputStream input = prepareStream(new byte[]{0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1}); - - assertEquals(input.readUInt64(), BigInteger.ZERO); - assertEquals(input.readUInt64(), new BigInteger("18446744073709551615")); - } - - @Test(groups = "unit") - public void testUInt64AsLong() throws Exception { - ClickHouseRowBinaryInputStream input = prepareStream(new byte[]{0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1}); - - assertEquals(input.readUInt64AsLong(), 0); - assertEquals(input.readUInt64AsLong(), new BigInteger("18446744073709551615").longValue()); - } - - @Test(groups = "unit") - public void testDecimal128() throws Exception { - ClickHouseRowBinaryInputStream input = prepareStream(new byte[]{-10, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}); - assertEquals(input.readDecimal128(3), new BigDecimal("10.230")); - ClickHouseRowBinaryInputStream input2 = prepareStream(new byte[]{-2, 127, -58, -92, 126, -115, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0}); - assertEquals(input2.readDecimal128(2), new BigDecimal("9999999999999.98")); - } - - @Test(groups = "unit") - public void testDecimal64() throws Exception { - ClickHouseRowBinaryInputStream input = prepareStream(new byte[]{-10, 39, 0, 0, 0, 0, 0, 0}); - assertEquals(input.readDecimal64(3), new BigDecimal("10.23")); - } - - @Test(groups = "unit") - public void testDecimal32() throws Exception { - ClickHouseRowBinaryInputStream input = prepareStream(new byte[]{-10, 39, 0, 0}); - assertEquals(input.readDecimal32(3), new BigDecimal("10.23")); - } - - @Test(groups = "unit") - public void testFixedString() throws Exception { - ClickHouseRowBinaryInputStream input = prepareStream(new byte[]{48, 49, 48, 49, 55, 49, 50, 50, 48, 48}); - - assertEquals(input.readFixedString(10), "0101712200"); - - ClickHouseRowBinaryInputStream inputZeroPaddedString = prepareStream(new byte[]{104, 101, 108, 108, 111, 0, 0, 0, 0, 0}); - - assertEquals(inputZeroPaddedString.readFixedString(10), "hello\0\0\0\0\0"); - } - - @Test(groups = "unit") - public void testUnsignedLeb128() throws Exception { - ClickHouseRowBinaryInputStream input = prepareStream(new byte[] { -128, -62, -41, 47 }); - assertEquals(input.readUnsignedLeb128(), 100000000); - } - - @Test(groups = "unit") - public void testOne() throws Exception { - ClickHouseRowBinaryInputStream input = prepareStream(new byte[]{5, 97, 46, 98, 46, 99, 123, 20, -82, 71, -31, 26, 69, 64, 34, 87, -13, 88, 120, 67, 48, 116, -13, 88}); - - assertEquals(input.readString(), "a.b.c"); - assertEquals(input.readFloat64(), 42.21); - assertEquals(input.readUInt32(), 1492342562L); - assertEquals(input.readDate(), new Date(117, 3, 16)); - assertEquals(input.readUInt32(), 1492350000L); - } - - private ClickHouseRowBinaryInputStream prepareStream(byte[] input) throws Exception { - return new ClickHouseRowBinaryInputStream(new ByteArrayInputStream(input), TimeZone.getTimeZone("ETC"), new ClickHouseProperties()); - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseRowBinaryStreamTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseRowBinaryStreamTest.java deleted file mode 100644 index 1a9c9499d..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseRowBinaryStreamTest.java +++ /dev/null @@ -1,418 +0,0 @@ -package ru.yandex.clickhouse.util; - -import org.testng.Assert; -import org.testng.annotations.Test; -import ru.yandex.clickhouse.settings.ClickHouseProperties; - -import java.io.ByteArrayOutputStream; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.Date; -import java.util.TimeZone; -import java.util.UUID; - -/** - * @author Dmitry Andreev - */ -public class ClickHouseRowBinaryStreamTest { - - @Test(groups = "unit") - public void testUInt8() throws Exception { - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.writeUInt8(true); - stream.writeUInt8(false); - stream.writeUInt8(1); - stream.writeUInt8(0); - stream.writeUInt8(255); - stream.writeUInt8(128); - } - }, - new byte[]{1, 0, 1, 0, -1, -128} - ); - } - - @Test(groups = "unit") - public void testUInt16() throws Exception { - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.writeUInt16(0); - stream.writeUInt16(65535); - stream.writeUInt16(32768); - } - }, - new byte[]{0, 0, -1, -1, 0, -128} - ); - } - - @Test(groups = "unit") - public void testFloat64() throws Exception { - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.writeFloat64(Double.NaN); - } - }, - new byte[]{0, 0, 0, 0, 0, 0, -8, 127} - ); - } - - - @Test(groups = "unit") - public void testUInt64() throws Exception { - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.writeUInt64(0); - stream.writeUInt64(new BigInteger("18446744073709551615")); - } - }, - new byte[]{0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1,} - ); - } - - @Test(groups = "unit") - public void testDecimal32() throws Exception { - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.writeDecimal32(new BigDecimal(10.23), 3); - stream.writeDecimal32(new BigDecimal(-99999.9998), 4); - } - }, - new byte[]{-10, 39, 0, 0, 2, 54, 101, -60} - ); - } - - @Test(groups = "unit") - public void testDecimal64() throws Exception { - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.writeDecimal64(new BigDecimal(10.23), 3); - stream.writeDecimal64(new BigDecimal(-9999999999.99999998), 8); - } - }, - new byte[]{-10, 39, 0, 0, 0, 0, 0, 0, 0, 0, -100, 88, 76, 73, 31, -14} - ); - } - - @Test(groups = "unit") - public void testDecimal128() throws Exception { - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.writeDecimal128(new BigDecimal(10.23), 3); - stream.writeDecimal128(new BigDecimal(-10.23), 3); - } - }, - new byte[] { - -10, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 10, -40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - } - ); - } - - @Test(groups = "unit") - public void testDecimal256() throws Exception { - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.writeDecimal256(new BigDecimal(10.23), 3); - stream.writeDecimal256(new BigDecimal(-10.23), 3); - } - }, - new byte[] { - -10, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 10, -40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - } - ); - } - - @Test(groups = "unit") - public void testOne() throws Exception { - - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.writeString("a.b.c"); - stream.writeFloat64(42.21); - stream.writeUInt32(1492342562); - stream.writeDate(new Date(117, 3, 16)); - stream.writeUInt32(1492350000); - } - }, - new byte[]{5, 97, 46, 98, 46, 99, 123, 20, -82, 71, -31, 26, 69, 64, 34, 87, -13, 88, 120, 67, 48, 116, -13, 88} - ); - //Result of - //clickhouse-client -q "select 'a.b.c', toFloat64(42.21), toUInt32(1492342562), toDate('2017-04-16'), toUInt32(1492350000) format RowBinary" | od -vAn -td1 - - } - - @Test(groups = "unit") - public void testUnsignedLeb128() throws Exception { - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.writeUnsignedLeb128(0); - stream.writeUnsignedLeb128(624485); - stream.writeUnsignedLeb128(100000000); - } - }, - new byte[]{ - 0, - -27, -114, 38, - -128, -62, -41, 47 - } - ); - } - - - @Test(groups = "unit") - public void testNative() throws Exception { - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.writeUnsignedLeb128(2); - stream.writeUnsignedLeb128(1); - stream.writeString("1"); - stream.writeString("UInt8"); - stream.writeUInt8(1); - stream.writeString("2"); - stream.writeString("UInt8"); - stream.writeUInt8(2); - } - }, - //clickhouse-client -q "select 1, 2 FORMAT Native" | od -vAn -td1 - new byte[]{ - 2, //Columns - 1, //Rows - 1, 49, //'1' - 5, 85, 73, 110, 116, 56, //'UInt8' - 1, //1 - 1, 50, //'2' - 5, 85, 73, 110, 116, 56, //'Uint8' - 2 //2 - } - ); - } - - - @Test(groups = "unit") - public void testStringArray() throws Exception { - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.writeUnsignedLeb128(0); - stream.writeUnsignedLeb128(1); - stream.writeString("ax"); - } - }, - new byte[]{0, 1, 2, 97, 120} - ); - } - - @Test(groups = "unit") - public void testUInt64Array() throws Exception { - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.writeUInt64Array(new long[]{0, Long.MAX_VALUE}); - stream.writeUInt64Array(new BigInteger[]{BigInteger.ZERO, new BigInteger("18446744073709551615")}); - } - }, - new byte[] { 2, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, 127, // First array - 2, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, } // Second array - ); - } - - @Test(groups = "unit") - public void testString() throws Exception { - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.writeString( - "aaaa~����%20�&zzzzz" - ); - } - }, - new byte[]{ - 29, 97, 97, 97, 97, 126, -17, -65, -67, -17, -65, -67, -17, -65, -67, -17, - -65, -67, 37, 50, 48, -17, -65, -67, 38, 122, 122, 122, 122, 122 - } - //clickhouse-client -q "SELECT 'aaaa~����%20�&zzzzz' Format RowBinary" | od -vAn -td1 - ); - } - - @Test(groups = "unit") - public void testFixedString() throws Exception { - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.writeFixedString( - "aaaa~����%20�&zzzzz" - ); - } - }, - new byte[]{ - 97, 97, 97, 97, 126, -17, -65, -67, -17, -65, -67, -17, -65, -67, -17, - -65, -67, 37, 50, 48, -17, -65, -67, 38, 122, 122, 122, 122, 122 - } - //clickhouse-client -q "select toFixedString('aaaa~����%20�&zzzzz', 29) format RowBinary"| od -vAn -td1 - ); - } - - @Test(groups = "unit") - public void testFixedStringLen() throws Exception { - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.writeFixedString( - "aaaa~����%20�&zzzzz", 32 - ); - } - }, - new byte[]{ - 97, 97, 97, 97, 126, -17, -65, -67, -17, -65, -67, -17, -65, -67, -17, - -65, -67, 37, 50, 48, -17, -65, -67, 38, 122, 122, 122, 122, 122, 0, 0, 0 - } - //clickhouse-client -q "select toFixedString('aaaa~����%20�&zzzzz', 32) format RowBinary"| od -vAn -td1 - ); - } - - @Test(groups = "unit") - public void testFixedStringLen1() throws Exception { - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.writeFixedString( - "", 5 - ); - } - }, - new byte[]{ - 0, 0, 0, 0, 0 - } - //clickhouse-client -q "select toFixedString('', 5) format RowBinary"| od -vAn -td1 - ); - } - - @Test(groups = "unit") - public void testFixedStringLen2() throws Exception { - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.writeFixedString( - "1234567890", 5 - ); - } - }, - new byte[]{ - 49, 50, 51, 52, 53 - } - //clickhouse-client -q "select toFixedString('1234567890', 5) format RowBinary"| od -vAn -td1 - ); - } - - @Test(groups = "unit") - public void testUUID() throws Exception { - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.writeUUID(UUID.fromString("123e4567-e89b-12d3-a456-426655440000")); - } - }, - new byte[]{ - -45, 18, -101, -24, 103, 69, 62, 18, 0, 0, 68, 85, 102, 66, 86, -92 - } - ); - } - - @Test(groups = "unit") - public void testUUIDArray() throws Exception { - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.writeUUIDArray(new UUID[] { - UUID.fromString("123e4567-e89b-12d3-a456-426655440000"), - UUID.fromString("123e4567-e89b-12d3-a456-426655440001") - }); - } - }, - new byte[] { - 2, -45, 18, -101, -24, 103, 69, 62, 18, 0, 0, 68, 85, 102, 66, 86, -92, - -45, 18, -101, -24, 103, 69, 62, 18, 1, 0, 68, 85, 102, 66, 86, -92 - } - ); - } - - @Test(groups = "unit") - public void testWriteNullableInt32() throws Exception { - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.markNextNullable(false); - stream.writeInt32(1); - } - }, - new byte[]{ - 0, 1, 0, 0, 0 - } - ); - // clickhouse-client -q "SELECT CAST(1 AS Nullable(Int32)) Format RowBinary" | od -vAn -td1 - } - - @Test(groups = "unit") - public void testWriteNull() throws Exception { - check( - new StreamWriter() { - @Override - public void write(ClickHouseRowBinaryStream stream) throws Exception { - stream.markNextNullable(true); - } - }, - new byte[]{ - 1 - } - ); - // clickhouse-client -q "SELECT CAST(Null AS Nullable(Int32)) Format RowBinary" | od -vAn -td1 - } - - private void check(StreamWriter streamWriter, byte[] expected) throws Exception { - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - ClickHouseRowBinaryStream stream = new ClickHouseRowBinaryStream(byteArrayOutputStream, TimeZone.getTimeZone("ETC"), new ClickHouseProperties()); - streamWriter.write(stream); - Assert.assertEquals(byteArrayOutputStream.toByteArray(), expected); - } - - private interface StreamWriter { - void write(ClickHouseRowBinaryStream stream) throws Exception; - } - - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseValueFormatterTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseValueFormatterTest.java deleted file mode 100644 index b2a03bb76..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseValueFormatterTest.java +++ /dev/null @@ -1,399 +0,0 @@ -package ru.yandex.clickhouse.util; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.sql.Date; -import java.sql.Time; -import java.sql.Timestamp; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetDateTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.TimeZone; -import java.util.UUID; - -import org.testng.annotations.Test; - -import ru.yandex.clickhouse.response.ByteFragment; -import ru.yandex.clickhouse.response.ClickHouseColumnInfo; -import ru.yandex.clickhouse.response.parser.ClickHouseValueParser; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotEquals; -import static org.testng.Assert.assertNull; - -public class ClickHouseValueFormatterTest { - - @Test(groups = "unit") - public void testFormatBytesUUID() { - UUID uuid = UUID.randomUUID(); - byte[] bytes = ByteBuffer.allocate(16) - .putLong(uuid.getMostSignificantBits()) - .putLong(uuid.getLeastSignificantBits()) - .array(); - String formattedBytes = ClickHouseValueFormatter.formatBytes(bytes); - byte[] reparsedBytes = new byte[16]; - for (int i = 0; i < 16; i++) { - reparsedBytes[i] = (byte) - ((Character.digit(formattedBytes.charAt(i * 4 + 2), 16) << 4) - + Character.digit(formattedBytes.charAt(i * 4 + 3), 16)); - } - assertEquals(reparsedBytes, bytes); - } - - @Test(groups = "unit") - public void testFormatBytesHelloWorld() throws Exception { - byte[] bytes = "HELLO WORLD".getBytes("UTF-8"); - String formattedBytes = ClickHouseValueFormatter.formatBytes(bytes); - byte[] reparsedBytes = new byte[bytes.length]; - for (int i = 0; i < bytes.length; i++) { - reparsedBytes[i] = (byte) - ((Character.digit(formattedBytes.charAt(i * 4 + 2), 16) << 4) - + Character.digit(formattedBytes.charAt(i * 4 + 3), 16)); - } - assertEquals( - new String(reparsedBytes, Charset.forName("UTF-8")), - "HELLO WORLD"); - } - - @Test(groups = "unit") - public void testFormatBytesNull() { - assertNull(ClickHouseValueFormatter.formatBytes(null)); - } - - @Test(groups = "unit") - public void testFormatBytesEmpty() { - assertEquals(ClickHouseValueFormatter.formatBytes(new byte[0]), ""); - } - - @Test(groups = "unit") - public void testFormatLocalTime() { - LocalTime l = LocalTime.parse("13:37:42.023"); - assertEquals(ClickHouseValueFormatter.formatLocalTime(l), "13:37:42"); - } - - @Test(groups = "unit") - public void testFormatOffsetTime() { - OffsetTime o = OffsetTime.of( - LocalTime.parse("13:37:42.023"), - ZoneOffset.ofHoursMinutes(1, 7)); - assertEquals( - ClickHouseValueFormatter.formatOffsetTime(o), - "13:37:42.023+01:07"); - } - - @Test(groups = "unit") - public void testFormatLocalDate() { - LocalDate l = LocalDate.of(2020, 1, 7); - assertEquals(ClickHouseValueFormatter.formatLocalDate(l), "2020-01-07"); - } - - @Test(groups = "unit") - public void testFormatLocalDateTime() { - LocalDateTime l = LocalDateTime.of(2020, 1, 7, 13, 37, 42, 107); - assertEquals(ClickHouseValueFormatter.formatLocalDateTime(l), "2020-01-07 13:37:42"); - } - - @Test(groups = "unit") - public void testFormatOffsetDateTime() { - OffsetDateTime o = OffsetDateTime.of( - LocalDateTime.of(2020, 1, 7, 13, 37, 42, 107), - ZoneOffset.ofHoursMinutes(2, 30)); - assertEquals( - ClickHouseValueFormatter.formatOffsetDateTime(o, TimeZone.getTimeZone("Europe/Moscow")), - "2020-01-07 14:07:42"); - } - - @Test(groups = "unit") - public void testFormatZonedDateTime() { - ZonedDateTime z = ZonedDateTime.of( - LocalDateTime.of(2020, 1, 7, 13, 37, 42, 107), - ZoneId.of("America/Los_Angeles")); - assertEquals( - ClickHouseValueFormatter.formatZonedDateTime(z, TimeZone.getTimeZone("Europe/Moscow")), - "2020-01-08 00:37:42"); - } - - @Test(groups = "unit") - public void testFormatObject() throws Exception { - TimeZone tzUTC = TimeZone.getTimeZone("UTC"); - assertEquals(ClickHouseValueFormatter.formatObject(Byte.valueOf("42"), tzUTC, tzUTC), "42"); - assertEquals(ClickHouseValueFormatter.formatObject("foo", tzUTC, tzUTC), "foo"); - assertEquals(ClickHouseValueFormatter.formatObject("f'oo\to", tzUTC, tzUTC), "f\\'oo\\to"); - assertEquals(ClickHouseValueFormatter.formatObject(BigDecimal.valueOf(42.23), tzUTC, tzUTC), "42.23"); - assertEquals(ClickHouseValueFormatter.formatObject(BigInteger.valueOf(1337), tzUTC, tzUTC), "1337"); - assertEquals(ClickHouseValueFormatter.formatObject(Short.valueOf("-23"), tzUTC, tzUTC), "-23"); - assertEquals(ClickHouseValueFormatter.formatObject(Integer.valueOf(1337), tzUTC, tzUTC), "1337"); - assertEquals(ClickHouseValueFormatter.formatObject(Long.valueOf(-23L), tzUTC, tzUTC), "-23"); - assertEquals(ClickHouseValueFormatter.formatObject(Float.valueOf(4.2f), tzUTC, tzUTC), "4.2"); - assertEquals(ClickHouseValueFormatter.formatObject(Double.valueOf(23.42), tzUTC, tzUTC), "23.42"); - byte[] bytes = "HELLO WORLD".getBytes("UTF-8"); - assertEquals(ClickHouseValueFormatter.formatObject(bytes, tzUTC, tzUTC), - "\\x48\\x45\\x4C\\x4C\\x4F\\x20\\x57\\x4F\\x52\\x4C\\x44"); - Date d = new Date(1557136800000L); - assertEquals(ClickHouseValueFormatter.formatObject(d, tzUTC, tzUTC), "2019-05-06"); - Time t = new Time(1557136800000L); - assertEquals(ClickHouseValueFormatter.formatObject(t, tzUTC, tzUTC), "10:00:00"); - Timestamp ts = new Timestamp(1557136800000L); - assertEquals(ClickHouseValueFormatter.formatObject(ts, tzUTC, tzUTC), "2019-05-06 10:00:00"); - assertEquals(ClickHouseValueFormatter.formatObject(Boolean.TRUE, tzUTC, tzUTC), "1"); - UUID u = UUID.randomUUID(); - assertEquals(ClickHouseValueFormatter.formatObject(u, tzUTC, tzUTC), u.toString()); - int[] ints = new int[] { 23, 42 }; - assertEquals(ClickHouseValueFormatter.formatObject(ints, tzUTC, tzUTC), "[23,42]"); - assertEquals(ClickHouseValueFormatter.formatObject(new Timestamp[] {ts, ts}, tzUTC, tzUTC), - "['2019-05-06 10:00:00','2019-05-06 10:00:00']"); - assertEquals( - ClickHouseValueFormatter.formatObject(LocalTime.parse("13:37:42.023"), tzUTC, tzUTC), - "13:37:42"); - OffsetTime offTime = OffsetTime.of( - LocalTime.parse("13:37:42.023"), - ZoneOffset.ofHoursMinutes(1, 7)); - assertEquals( - ClickHouseValueFormatter.formatObject(offTime, tzUTC, TimeZone.getTimeZone("Europe/Moscow")), - "13:37:42.023+01:07"); - assertEquals( - ClickHouseValueFormatter.formatObject(offTime, tzUTC, tzUTC), - "13:37:42.023+01:07"); - assertEquals( - ClickHouseValueFormatter.formatObject( - OffsetTime.of( - LocalTime.parse("13:37:42.023"), - ZoneOffset.ofHoursMinutes(1, 7)), - tzUTC, - TimeZone.getTimeZone("Europe/Moscow")), - "13:37:42.023+01:07"); - assertEquals( - ClickHouseValueFormatter.formatObject(LocalDate.of(2020, 1, 7), tzUTC, tzUTC), - "2020-01-07"); - assertEquals( - ClickHouseValueFormatter.formatObject( - LocalDateTime.of(2020, 1, 7, 13, 37, 42, 23), - tzUTC, - tzUTC), - "2020-01-07 13:37:42"); - OffsetDateTime o = OffsetDateTime.of( - LocalDateTime.of(2020, 1, 7, 13, 37, 42, 107), - ZoneOffset.ofHoursMinutes(2, 30)); - assertEquals( - ClickHouseValueFormatter.formatObject(o, tzUTC, TimeZone.getTimeZone("Europe/Moscow")), - "2020-01-07 14:07:42"); - assertEquals( - ClickHouseValueFormatter.formatObject(o, tzUTC, tzUTC), - "2020-01-07 11:07:42"); - ZonedDateTime z = ZonedDateTime.of( - LocalDateTime.of(2020, 1, 7, 13, 37, 42, 107), - ZoneId.of("America/Los_Angeles")); - assertEquals( - ClickHouseValueFormatter.formatObject(z, tzUTC, TimeZone.getTimeZone("Europe/Moscow")), - "2020-01-08 00:37:42"); - assertEquals( - ClickHouseValueFormatter.formatObject(z, tzUTC, tzUTC), - "2020-01-07 21:37:42"); - } - - @Test(groups = "unit") - public void testRoundTripLocalDate() throws Exception { - LocalDate l0 = LocalDate.of(1957, 10, 4); - LocalDate l1 = (LocalDate) ClickHouseValueParser.getParser(LocalDate.class).parse( - ByteFragment.fromString(ClickHouseValueFormatter.formatLocalDate(l0)), - ClickHouseColumnInfo.parse("Date", "col", null), null); - assertEquals(l1, l0); - l1 = (LocalDate) ClickHouseValueParser.getParser(LocalDate.class).parse( - ByteFragment.fromString(ClickHouseValueFormatter.formatLocalDate(l0)), - ClickHouseColumnInfo.parse("String", "col", null), null); - assertEquals(l1, l0); - } - - @Test(groups = "unit") - public void testRoundTripLocalTime() throws Exception { - LocalTime l0 = LocalTime.of(13, 37, 42); - LocalTime l1 = (LocalTime) ClickHouseValueParser.getParser(LocalTime.class).parse( - ByteFragment.fromString(ClickHouseValueFormatter.formatLocalTime(l0)), - ClickHouseColumnInfo.parse("String", "col", null), null); - assertEquals(l1, l0); - } - - @Test(groups = "unit") - public void testRoundTripLocalDateTime() throws Exception { - LocalDateTime l0 = LocalDateTime.of(1957, 10, 4, 13, 37, 42); - LocalDateTime l1 = (LocalDateTime) ClickHouseValueParser.getParser(LocalDateTime.class) - .parse(ByteFragment.fromString(ClickHouseValueFormatter.formatLocalDateTime(l0)), - ClickHouseColumnInfo.parse("DateTime", "col", null), null); - assertEquals(l1, l0); - l1 = (LocalDateTime) ClickHouseValueParser.getParser(LocalDateTime.class) - .parse(ByteFragment.fromString(ClickHouseValueFormatter.formatLocalDateTime(l0)), - ClickHouseColumnInfo.parse("String", "col", null), null); - assertEquals(l1, l0); - } - - @Test(groups = "unit") - public void testRoundTripOffsetTime() throws Exception { - ZoneOffset offset = ZoneId.of("Asia/Vladivostok") - .getRules().getOffset(Instant.now()); - OffsetTime ot0 = OffsetTime.of(LocalTime.of(13, 37, 42), offset); - OffsetTime ot1 = (OffsetTime) ClickHouseValueParser.getParser(OffsetTime.class) - .parse(ByteFragment.fromString(ClickHouseValueFormatter.formatOffsetTime(ot0)), - ClickHouseColumnInfo.parse("String", "col", null), null); - assertEquals(ot1, ot0); - } - - @Test(groups = "unit") - public void testRoundTripOffsetDateTime() throws Exception { - TimeZone tzBerlin = TimeZone.getTimeZone("Europe/Berlin"); - TimeZone tzLosAngeles = TimeZone.getTimeZone("America/Los_Angeles"); - TimeZone tzVladivostok = TimeZone.getTimeZone("Asia/Vladivostok"); - LocalDateTime ldt = LocalDateTime.of(1957, 10, 4, 13, 37, 42); - OffsetDateTime odt0 = OffsetDateTime.of( - ldt, - tzVladivostok.toZoneId().getRules().getOffset(ldt)); - - OffsetDateTime odt1 = (OffsetDateTime) ClickHouseValueParser.getParser(OffsetDateTime.class) - .parse(ByteFragment.fromString(ClickHouseValueFormatter.formatOffsetDateTime(odt0, tzLosAngeles)), - ClickHouseColumnInfo.parse("String", "col", tzLosAngeles), tzBerlin); - assertEquals(odt1, OffsetDateTime.of( - LocalDateTime.of(1957, 10, 3, 19, 37, 42), - tzBerlin.toZoneId().getRules().getOffset(ldt))); - - odt1 = (OffsetDateTime) ClickHouseValueParser.getParser(OffsetDateTime.class) - .parse(ByteFragment.fromString(ClickHouseValueFormatter.formatOffsetDateTime(odt0, tzLosAngeles)), - ClickHouseColumnInfo.parse("DateTime", "col", tzBerlin), tzBerlin); - assertEquals(odt1, OffsetDateTime.of( - LocalDateTime.of(1957, 10, 3, 19, 37, 42), - tzBerlin.toZoneId().getRules().getOffset(ldt))); - - odt1 = (OffsetDateTime) ClickHouseValueParser.getParser(OffsetDateTime.class) - .parse(ByteFragment.fromString(ClickHouseValueFormatter.formatOffsetDateTime(odt0, tzLosAngeles)), - ClickHouseColumnInfo.parse("DateTime", "col", tzLosAngeles), tzLosAngeles); - assertEquals(odt1, OffsetDateTime.of( - LocalDateTime.of(1957, 10, 3, 19, 37, 42), - tzLosAngeles.toZoneId().getRules().getOffset(ldt))); - } - - @Test(groups = "unit") - public void testRoundTripZonedDateTime() throws Exception { - TimeZone tzBerlin = TimeZone.getTimeZone("Europe/Berlin"); - TimeZone tzLosAngeles = TimeZone.getTimeZone("America/Los_Angeles"); - TimeZone tzVladivostok = TimeZone.getTimeZone("Asia/Vladivostok"); - LocalDateTime ldt = LocalDateTime.of(1957, 10, 4, 13, 37, 42); - ZonedDateTime odt0 = ZonedDateTime.of( - ldt, - tzVladivostok.toZoneId()); - - ZonedDateTime odt1 = (ZonedDateTime) ClickHouseValueParser.getParser(ZonedDateTime.class) - .parse(ByteFragment.fromString(ClickHouseValueFormatter.formatZonedDateTime(odt0, tzLosAngeles)), - ClickHouseColumnInfo.parse("String", "col", tzLosAngeles), tzBerlin); - assertEquals(odt1, ZonedDateTime.of( - LocalDateTime.of(1957, 10, 3, 19, 37, 42), - tzBerlin.toZoneId())); - - odt1 = (ZonedDateTime) ClickHouseValueParser.getParser(ZonedDateTime.class) - .parse(ByteFragment.fromString(ClickHouseValueFormatter.formatZonedDateTime(odt0, tzLosAngeles)), - ClickHouseColumnInfo.parse("DateTime", "col", tzBerlin), tzBerlin); - assertEquals(odt1, ZonedDateTime.of( - LocalDateTime.of(1957, 10, 3, 19, 37, 42), - tzBerlin.toZoneId())); - - odt1 = (ZonedDateTime) ClickHouseValueParser.getParser(ZonedDateTime.class) - .parse(ByteFragment.fromString(ClickHouseValueFormatter.formatZonedDateTime(odt0, tzLosAngeles)), - ClickHouseColumnInfo.parse("DateTime", "col", tzLosAngeles), tzLosAngeles); - assertEquals(odt1, ZonedDateTime.of( - LocalDateTime.of(1957, 10, 3, 19, 37, 42), - tzLosAngeles.toZoneId())); - } - - @Test(groups = "unit") - public void testRoundTripSQLTimestamp() throws Exception { - TimeZone tzLosAngeles = TimeZone.getTimeZone("America/Los_Angeles"); - TimeZone tzBerlin = TimeZone.getTimeZone("Europe/Berlin"); - Timestamp t0 = new Timestamp(1497474018000L); - Timestamp t1 = (Timestamp) ClickHouseValueParser.getParser(Timestamp.class) - .parse(ByteFragment.fromString(ClickHouseValueFormatter.formatTimestamp(t0, tzLosAngeles)), - ClickHouseColumnInfo.parse("String", "col", tzLosAngeles), tzLosAngeles); - assertEquals(t1, t0); - - t1 = (Timestamp) ClickHouseValueParser.getParser(Timestamp.class) - .parse(ByteFragment.fromString(ClickHouseValueFormatter.formatTimestamp(t0, tzLosAngeles)), - ClickHouseColumnInfo.parse("DateTime", "col", tzLosAngeles), tzLosAngeles); - assertEquals(t1, t0); - - t1 = (Timestamp) ClickHouseValueParser.getParser(Timestamp.class) - .parse(ByteFragment.fromString(ClickHouseValueFormatter.formatTimestamp(t0, tzLosAngeles)), - ClickHouseColumnInfo.parse("String", "col", tzLosAngeles), tzBerlin); - Timestamp t2 = new Timestamp( - ZonedDateTime.of(LocalDateTime.of(2017,6, 14, 14, 0, 18), - tzBerlin.toZoneId()) - .toInstant() - .toEpochMilli()); - assertNotEquals(t1, t0); - assertEquals(t1, t2); - } - - @Test(groups = "unit") - public void testRoundTripSQLTime() throws Exception { - TimeZone tzLosAngeles = TimeZone.getTimeZone("America/Los_Angeles"); - TimeZone tzBerlin = TimeZone.getTimeZone("Europe/Berlin"); - Time t0 = Time.valueOf(LocalTime.of(13, 37, 42)); - Time t1 = (Time) ClickHouseValueParser.getParser(Time.class) - .parse(ByteFragment.fromString(ClickHouseValueFormatter.formatTime(t0, tzLosAngeles)), - ClickHouseColumnInfo.parse("String", "col", null), tzLosAngeles); - assertEquals(t1, t0); - - t1 = (Time) ClickHouseValueParser.getParser(Time.class) - .parse(ByteFragment.fromString(ClickHouseValueFormatter.formatTime(t0, tzLosAngeles)), - ClickHouseColumnInfo.parse("String", "col", null), tzBerlin); - assertEquals( - Instant.ofEpochMilli(t1.getTime()), - Instant.ofEpochMilli((t0.getTime() + (24 - 9) * 3600 * 1000) % (24 * 3600 * 1000))); - } - - @Test(groups = "unit") - public void testRoundTripSQLDate() throws Exception { - TimeZone tzLosAngeles = TimeZone.getTimeZone("America/Los_Angeles"); - TimeZone tzBerlin = TimeZone.getTimeZone("Europe/Berlin"); - - /* - * This is a case with intended discrepancy: - * - * Input: 2017-06-14T14:00:18-07:00 - * Output: 2017-06-14T00:00:00-07:00 - * - * See Javadoc for java.sql.Date: - * - * the millisecond values wrapped by a java.sql.Date instance must be "normalized" - * by setting the hours, minutes, seconds, and milliseconds to zero in the particular - * time zone with which the instance is associated. - */ - Date t0 = new Date(1497474018000L); - Date t1 = (Date) ClickHouseValueParser.getParser(Date.class) - .parse(ByteFragment.fromString(ClickHouseValueFormatter.formatDate(t0, tzLosAngeles)), - ClickHouseColumnInfo.parse("String", "col", null), tzLosAngeles); - assertNotEquals(t1, t0); - assertEquals( - t1, - new Date(OffsetDateTime.parse("2017-06-14T00:00:00-07:00") - .toInstant() - .toEpochMilli())); - - // now try parsing with a different time zone. The values should be "normalized" - // for the particular time zone. - - Date t2 = (Date) ClickHouseValueParser.getParser(Date.class) - .parse(ByteFragment.fromString(ClickHouseValueFormatter.formatDate(t0, tzLosAngeles)), - ClickHouseColumnInfo.parse("String", "col", null), tzBerlin); - assertNotEquals(t2, t0); - assertEquals( - t2, - new Date(OffsetDateTime.parse("2017-06-14T00:00:00+02:00") - .toInstant() - .toEpochMilli())); - } - -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseVersionNumberUtilTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseVersionNumberUtilTest.java deleted file mode 100644 index fb218c84f..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseVersionNumberUtilTest.java +++ /dev/null @@ -1,78 +0,0 @@ -package ru.yandex.clickhouse.util; - -import org.testng.Assert; -import org.testng.annotations.Test; - -public class ClickHouseVersionNumberUtilTest { - - @Test(groups = "unit") - public void testMajorNull() { - try { - ClickHouseVersionNumberUtil.getMajorVersion(null); - Assert.fail(); - } catch (NullPointerException npe) { - /* expected */ } - } - - @Test(groups = "unit") - public void testMinorNull() { - try { - ClickHouseVersionNumberUtil.getMinorVersion(null); - Assert.fail(); - } catch (NullPointerException npe) { - /* expected */ } - } - - @Test(groups = "unit") - public void testMajorGarbage() { - Assert.assertEquals(0, ClickHouseVersionNumberUtil.getMajorVersion("")); - Assert.assertEquals(0, ClickHouseVersionNumberUtil.getMajorVersion(" \t")); - Assert.assertEquals(0, ClickHouseVersionNumberUtil.getMajorVersion(" \n ")); - Assert.assertEquals(0, ClickHouseVersionNumberUtil.getMajorVersion(".")); - Assert.assertEquals(0, ClickHouseVersionNumberUtil.getMajorVersion(". . ")); - Assert.assertEquals(0, ClickHouseVersionNumberUtil.getMajorVersion("F.O.O")); - Assert.assertEquals(0, ClickHouseVersionNumberUtil.getMajorVersion("42.foo")); - } - - @Test(groups = "unit") - public void testMajorSimple() { - Assert.assertEquals(ClickHouseVersionNumberUtil.getMajorVersion("1.0"), 1); - Assert.assertEquals(ClickHouseVersionNumberUtil.getMajorVersion("1.0.42"), 1); - Assert.assertEquals(ClickHouseVersionNumberUtil.getMajorVersion("23.42"), 23); - Assert.assertEquals(ClickHouseVersionNumberUtil.getMajorVersion("1.0.foo"), 1); - Assert.assertEquals(ClickHouseVersionNumberUtil.getMajorVersion(" 1.0"), 1); - Assert.assertEquals(ClickHouseVersionNumberUtil.getMajorVersion("1.0-SNAPSHOT"), 1); - } - - @Test(groups = "unit") - public void testMinorGarbage() { - Assert.assertEquals(0, ClickHouseVersionNumberUtil.getMinorVersion("")); - Assert.assertEquals(0, ClickHouseVersionNumberUtil.getMinorVersion(" \t")); - Assert.assertEquals(0, ClickHouseVersionNumberUtil.getMinorVersion(" \n ")); - Assert.assertEquals(0, ClickHouseVersionNumberUtil.getMinorVersion(".")); - Assert.assertEquals(0, ClickHouseVersionNumberUtil.getMinorVersion(". . ")); - Assert.assertEquals(0, ClickHouseVersionNumberUtil.getMinorVersion("F.O.O")); - Assert.assertEquals(0, ClickHouseVersionNumberUtil.getMinorVersion("42.foo")); - } - - @Test(groups = "unit") - public void testMinorSimple() { - Assert.assertEquals(ClickHouseVersionNumberUtil.getMinorVersion("0.1"), 1); - Assert.assertEquals(ClickHouseVersionNumberUtil.getMinorVersion("42.1.42"), 1); - Assert.assertEquals(ClickHouseVersionNumberUtil.getMinorVersion("1.42.foo"), 42); - Assert.assertEquals(ClickHouseVersionNumberUtil.getMinorVersion(" 1.1"), 1); - Assert.assertEquals(ClickHouseVersionNumberUtil.getMinorVersion("1.1-SNAPSHOT"), 1); - } - - @Test(groups = "unit") - public void testCompare() { - Assert.assertEquals(ClickHouseVersionNumberUtil.compare("1", "1"), 0); - Assert.assertEquals(ClickHouseVersionNumberUtil.compare("21.3", "21.12"), -1); - Assert.assertEquals(ClickHouseVersionNumberUtil.compare("21 .3", "21. 12"), -1); - Assert.assertEquals(ClickHouseVersionNumberUtil.compare("21 .3", "21. 12-test"), -1); - Assert.assertEquals(ClickHouseVersionNumberUtil.compare("21.3", "21.1"), 1); - Assert.assertEquals(ClickHouseVersionNumberUtil.compare("21. 3", "21 .1"), 1); - Assert.assertEquals(ClickHouseVersionNumberUtil.compare("21. 3-test", "21 .1"), 1); - Assert.assertEquals(ClickHouseVersionNumberUtil.compare("18.16", "18.16.0"), 0); - } -} diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/UtilsTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/UtilsTest.java deleted file mode 100644 index a6329130f..000000000 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/UtilsTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package ru.yandex.clickhouse.util; - -import static org.testng.Assert.assertEquals; - -import java.io.ByteArrayInputStream; -import java.io.DataInputStream; -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; - -import org.testng.annotations.Test; - -public class UtilsTest { - @Test(groups = "unit") - public void testUnsignedLeb128() throws Exception { - DataInputStream input = prepareStream(new byte[] { 0 }); - assertEquals(Utils.readUnsignedLeb128(input), 0); - - input = prepareStream(new byte[] { -27, -114, 38 }); - assertEquals(Utils.readUnsignedLeb128(input), 624485); - - input = prepareStream(new byte[] { -128, -62, -41, 47 }); - assertEquals(Utils.readUnsignedLeb128(input), 100000000); - } - - @Test(groups = "unit") - public void testString() { - Charset charset = Charset.forName("ISO-8859-15"); - byte[] b1 = new byte[] { (byte) 127, (byte) 128 }; - String s = new String(b1, charset); - byte[] b2 = s.getBytes(charset); - assertEquals(b2, b1); - } - - @Test(groups = "unit") - public void testVarInt() { - ByteBuffer buffer; - for (int i : new int[] { 0, 128, 255, 65535, 1023 * 1024 }) { - buffer = ByteBuffer.allocate(8); - Utils.writeVarInt(i, buffer); - Utils.writeVarInt(0 - i, buffer); - buffer = (ByteBuffer) ((Buffer) buffer).flip(); - assertEquals(Utils.readVarInt(buffer), i); - assertEquals(Utils.readVarInt(buffer), 0 - i); - } - } - - private DataInputStream prepareStream(byte[] input) { - return new DataInputStream(new ByteArrayInputStream(input)); - } -} diff --git a/clickhouse-r2dbc/src/main/java9/module-info.java b/clickhouse-r2dbc/src/main/java9/module-info.java index c4b940d47..7a3a7669b 100644 --- a/clickhouse-r2dbc/src/main/java9/module-info.java +++ b/clickhouse-r2dbc/src/main/java9/module-info.java @@ -1,5 +1,5 @@ /** - * Declares ru.yandex.clickhouse module. + * Declares com.clickhouse.r2dbc module. */ module com.clickhouse.r2dbc { exports com.clickhouse.r2dbc; diff --git a/examples/r2dbc/misc/docker/compose.yaml b/examples/r2dbc/misc/docker/compose.yaml index 48672b736..769ea4700 100644 --- a/examples/r2dbc/misc/docker/compose.yaml +++ b/examples/r2dbc/misc/docker/compose.yaml @@ -1,6 +1,6 @@ services: db: - image: yandex/clickhouse-server + image: clickhouse/clickhouse-server:22.8 ports: - 8123:8123 - 9009:9009 diff --git a/pom.xml b/pom.xml index d23785043..ff9d25fc6 100644 --- a/pom.xml +++ b/pom.xml @@ -90,7 +90,6 @@ 8.5.8 1.48.1 2.9.1 - 4.5.13 3.21.4 1.8.0 0.9.31 @@ -214,16 +213,6 @@ commons-compress ${compress.version} - - org.apache.httpcomponents - httpclient - ${httpclient.version} - - - org.apache.httpcomponents - httpmime - ${httpclient.version} - org.apache.tomcat annotations-api