diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index a3976baac..c788f3588 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -96,9 +96,9 @@ jobs: continue-on-error: true - name: Update version and group id run: | - find . -type f -name "pom.xml" -exec sed -i -e 's|${revision}|${{ github.event.inputs.version }}|g' \ + find . -type f -name "pom.xml" -exec sed -i -e 's|${revision}|${{ github.event.inputs.driver }}|g' \ -e 's|^\( \).*\(\)$|\1${{ github.event.inputs.driver }}\2|' \ - -e 's|${parent.groupId}|com.clickhouse|g' '{}' \; + -e 's|${parent.groupId}|com.clickhouse|g' -e 's|${project.parent.groupId}|com.clickhouse|g' '{}' \; find . -type f -name "log4j.*" -exec rm -fv '{}' \; continue-on-error: true - name: Install driver as needed diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 43d558a4c..53d031180 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,7 +24,7 @@ jobs: run: | 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|${parent.groupId}|com.clickhouse|g' -e 's|${project.parent.groupId}|com.clickhouse|g' '{}' \; find . -type f -name "log4j.*" -exec rm -fv '{}' \; - name: Release Maven package uses: samuelmeuli/action-maven-publish@v1 diff --git a/.github/workflows/third_party_libs.yml b/.github/workflows/third_party_libs.yml index 02880566b..6e0f53f04 100644 --- a/.github/workflows/third_party_libs.yml +++ b/.github/workflows/third_party_libs.yml @@ -24,7 +24,7 @@ jobs: run: | 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|${parent.groupId}|com.clickhouse|g' -e 's|${project.parent.groupId}|com.clickhouse|g' '{}' \; find . -type f -name "log4j.*" -exec rm -fv '{}' \; - name: Release Maven package uses: samuelmeuli/action-maven-publish@v1 diff --git a/README.md b/README.md index e37bf9f3b..3c6f4fe01 100644 --- a/README.md +++ b/README.md @@ -162,19 +162,22 @@ Java 8 or higher is required in order to use Java client and/or JDBC driver. ### Data Type -| Data Type(s) | Java Client | JDBC Driver | Remark | -| ------------------ | ----------- | -------------------------- | --------------------------------------------------------------------- | -| Date\* | Y | Y | | -| DateTime\* | Y | Y | | -| Decimal\* | Y | Y | `SET output_format_decimal_trailing_zeros=1` in 21.9+ for consistency | -| Enum\* | Y | Treated as integer | -| Int*, UInt* | Y | UInt64 is mapped to `long` | -| Geo Types | Y | N | | -| AggregatedFunction | N | N | Partially supported | -| Array | Y | N | | -| Map | Y | Y | | -| Nested | Y | N | | -| Tuple | Y | N | | +| Data Type(s) | Java Client | JDBC Driver | Remark | +| ------------------ | ----------- | ----------- | --------------------------------------------------------------------- | +| Date\* | Y | Y | | +| DateTime\* | Y | Y | | +| Decimal\* | Y | Y | `SET output_format_decimal_trailing_zeros=1` in 21.9+ for consistency | +| Enum\* | Y | Y | Treated as integer | +| Int*, UInt* | Y | Y | UInt64 is mapped to `long` | +| IPv\* | Y | Y | | +| Geo Types | Y | N | | +| \*String | Y | Y | | +| UUID | Y | Y | | +| AggregatedFunction | N | N | Partially supported | +| Array | Y | N | | +| Map | Y | Y | | +| Nested | Y | N | | +| Tuple | Y | N | | ### Server Version @@ -196,11 +199,16 @@ By default, docker container will be created automatically during integration te In the case you prefer to test against an existing server, please follow instructions below: -- make sure the server can be accessed using default account(`default` user without password), which has both DDL and DML privileges -- add below two configuration files to the existing server and expose all ports for external access - - [ports.xml](./tree/master/clickhouse-client/src/test/resources/containers/clickhouse-server/config.d/ports.xml) - enable all ports - - and [users.xml](./tree/master/clickhouse-client/src/test/resources/containers/clickhouse-server/users.d/users.xml) - accounts used for integration test -- put `test.properties` under either `test/resources` or `~/.m2/clickhouse` with content like below: - ```properties - clickhouseServer=127.0.0.1 - ``` +- make sure the server can be accessed using default account(`default` user without password), which has both DDL and DML privileges +- add below two configuration files to the existing server and expose all ports for external access + - [ports.xml](./tree/master/clickhouse-client/src/test/resources/containers/clickhouse-server/config.d/ports.xml) - enable all ports + - and [users.xml](./tree/master/clickhouse-client/src/test/resources/containers/clickhouse-server/users.d/users.xml) - accounts used for integration test +- put `test.properties` under either `~/.m2/clickhouse` or `src/test/resources` of your project, with content like below: + ```properties + clickhouseServer=127.0.0.1 + # below properties are only useful for test containers + #clickhouseVersion=latest + #clickhouseTimezone=UTC + #clickhouseImage=clickhouse/clickhouse-server + #additionalPackages= + ``` diff --git a/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseClient.java b/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseClient.java index 8b429c72c..594bd96bd 100644 --- a/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseClient.java +++ b/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseClient.java @@ -5,9 +5,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; diff --git a/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseVersion.java b/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseVersion.java index 3353fb64a..359b36294 100644 --- a/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseVersion.java +++ b/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseVersion.java @@ -12,15 +12,17 @@ public final class ClickHouseVersion implements Comparable, Serializable { private static final long serialVersionUID = 6721014333437055314L; - private static final ClickHouseVersion defaultVersion = new ClickHouseVersion(0, 0, 0, 0); + private static final String STR_LATEST = "latest"; + private static final ClickHouseVersion defaultVersion = new ClickHouseVersion(false, 0, 0, 0, 0); + private static final ClickHouseVersion latestVersion = new ClickHouseVersion(true, 0, 0, 0, 0); @SuppressWarnings({ "squid:S5843", "squid:S5857" }) private static final Pattern versionPattern = Pattern.compile( - "^(?:.*?\\s)?(\\d+)(?:\\s*\\.\\s*(\\d+))?(?:\\s*\\.\\s*(\\d+))?(?:\\s*\\.\\s*(\\d+))?(?:|[\\.\\s].*)", + "^(?:.*?[\\s:])?(\\d+)(?:\\s*\\.\\s*(\\d+))?(?:\\s*\\.\\s*(\\d+))?(?:\\s*\\.\\s*(\\d+))?(?:|[\\.\\s].*)", Pattern.DOTALL); /** - * Compare two versions. + * Compares two versions. * * @param fromVersion version * @param toVersion version to compare with @@ -33,9 +35,9 @@ public static int compare(String fromVersion, String toVersion) { } /** - * Parse given version number in string format. + * Parses given version in string format. * - * @param version version number + * @param version version, null or empty string is treated as {@code 0.0.0.0} * @return parsed version */ public static ClickHouseVersion of(String version) { @@ -43,6 +45,7 @@ public static ClickHouseVersion of(String version) { return defaultVersion; } + boolean latest = false; int[] parts = new int[4]; Matcher m = versionPattern.matcher(version); if (m.matches()) { @@ -53,11 +56,18 @@ public static ClickHouseVersion of(String version) { // definitely don't want to break anything } } + } else { + version = version.trim().toLowerCase(); + + int index = Math.max(version.lastIndexOf(' '), version.lastIndexOf(':')); + latest = STR_LATEST.equals(index == -1 ? version : version.substring(index + 1)); } - return new ClickHouseVersion(parts[0], parts[1], parts[2], parts[3]); + return latest ? latestVersion : new ClickHouseVersion(false, parts[0], parts[1], parts[2], parts[3]); } + private final boolean latest; + private final int year; private final int major; private final int minor; @@ -65,25 +75,63 @@ public static ClickHouseVersion of(String version) { // Active Releases: // https://github.com/ClickHouse/ClickHouse/pulls?q=is%3Aopen+is%3Apr+label%3Arelease - protected ClickHouseVersion(int year, int major, int minor, int internal) { - this.year = year > 0 ? year : 0; - this.major = major > 0 ? major : 0; - this.minor = minor > 0 ? minor : 0; - this.internal = internal > 0 ? internal : 0; + protected ClickHouseVersion(boolean latest, int year, int major, int minor, int internal) { + this.latest = latest; + + if (latest) { + this.year = 0; + this.major = 0; + this.minor = 0; + this.internal = 0; + } else { + this.year = year > 0 ? year : 0; + this.major = major > 0 ? major : 0; + this.minor = minor > 0 ? minor : 0; + this.internal = internal > 0 ? internal : 0; + } + } + + /** + * Checks if the version is latest or not. + * + * @return true if it's latest; false otherwise + */ + public boolean isLatest() { + return latest; } + /** + * Gets year number. + * + * @return year number + */ public int getYear() { return year; } + /** + * Gets major/feature version. + * + * @return major/feature version + */ public int getMajor() { return major; } + /** + * Gets minor version. + * + * @return minor version + */ public int getMinor() { return minor; } + /** + * Gets internal build number. + * + * @return internal build number + */ public int getInternal() { return internal; } @@ -95,16 +143,170 @@ public int getInternal() { * @return true if current version is newer or equal to the given one; false * otherwise */ - public boolean isNewerOrEqual(String version) { + public boolean isNewerOrEqualTo(String version) { return compareTo(ClickHouseVersion.of(version)) >= 0; } + /** + * Checks if current version is newer than the given version. + * + * @param version version to compare + * @return true if current version is newer than the given one; false otherwise + */ + public boolean isNewerThan(String version) { + return compareTo(ClickHouseVersion.of(version)) > 0; + } + + /** + * Checks if current version is older or equal to the given version. + * + * @param version version to compare + * @return true if current version is older or equal to the given one; false + * otherwise + */ + public boolean isOlderOrEqualTo(String version) { + return compareTo(ClickHouseVersion.of(version)) <= 0; + } + + /** + * Checks if current version is older than the given version. + * + * @param version version to compare + * @return true if current version is older than the given one; false otherwise + */ + public boolean isOlderThan(String version) { + return compareTo(ClickHouseVersion.of(version)) < 0; + } + + /** + * Checks if this version belongs to the given series. For example: 21.3.1 + * belongs to 21.3 but not 21.6 or 21.3.2. No version except {@code latest} + * belongs to {@code latest} and vice versa. + * + * @param version version series + * @return true if this version belongs to the given series; false otherwise + */ + public boolean belongsTo(String version) { + return belongsTo(ClickHouseVersion.of(version)); + } + + /** + * Checks if this version belongs to the given series. For example: 21.3.1 + * belongs to 21.3 but not 21.6 or 21.3.2. No version except {@code latest} + * belongs to {@code latest} and vice versa. + * + * @param version version series, null is treated as {@code 0.0.0.0} + * @return true if this version belongs to the given series; false otherwise + */ + public boolean belongsTo(ClickHouseVersion version) { + if (version == null) { + version = defaultVersion; + } + + if (isLatest()) { + return version.isLatest(); + } else if (version.isLatest()) { + return false; + } + + if (year != version.year) { + return false; + } + + if (version.major == 0) { + return true; + } else if (major != version.major) { + return false; + } + + if (version.minor == 0) { + return true; + } else if (minor != version.minor) { + return false; + } + + return version.internal == 0 || internal == version.internal; + } + + /** + * Checks if this version is beyond the given series. For example: 21.3.1 is + * beyond 21.2, but not 21.3 or 21.3.1(because they all belong to 21.3 series). + * No version is beyond {@code latest} but it's beyond all other versions. + * + * @param version version series + * @return true if this version belongs to the given series; false otherwise + */ + public boolean isBeyond(String version) { + return isBeyond(ClickHouseVersion.of(version)); + } + + /** + * Checks if this version is beyond the given series. For example: 21.3.1 is + * beyond 21.2, but not 21.3 or 21.3.1(because they all belong to 21.3 series). + * No version is beyond {@code latest} but it's beyond all other versions. + * + * @param version version series, null is treated as {@code 0.0.0.0} + * @return true if this version is beyond the given series; false otherwise + */ + public boolean isBeyond(ClickHouseVersion version) { + if (version == null) { + version = defaultVersion; + } + + if (isLatest()) { + return !version.isLatest(); + } else if (version.isLatest()) { + return false; + } + + int result = year - version.year; + if (result != 0) { + return result > 0; + } else if (version.major == 0 && version.minor == 0 && version.internal == 0) { + return false; + } + + result = major - version.major; + if (result != 0) { + return result > 0; + } else if (version.minor == 0 && version.internal == 0) { + return false; + } + + result = minor - version.minor; + if (result != 0) { + return result > 0; + } else if (version.internal == 0) { + return false; + } + + return internal > version.internal; + } + + /** + * Checks if this version is older than or belongs to the given version. + * + * @param version version + * @return true if this version is older than or belongs to the given version; + * false otherwise + */ + public boolean isOlderOrBelongsTo(String version) { + ClickHouseVersion theOther = ClickHouseVersion.of(version); + return compareTo(theOther) < 0 || belongsTo(theOther); + } + @Override public int compareTo(ClickHouseVersion o) { if (this == o) { return 0; } + if (latest) { + return o.latest ? 0 : 1; + } else if (o.latest) { + return -1; + } + int result = year - o.year; if (result != 0) { return result; @@ -134,13 +336,15 @@ public boolean equals(Object obj) { } ClickHouseVersion other = (ClickHouseVersion) obj; - return year == other.year && major == other.major && minor == other.minor && internal == other.internal; + return (latest && other.latest) || latest == other.latest && year == other.year && major == other.major + && minor == other.minor && internal == other.internal; } @Override public int hashCode() { final int prime = 31; int result = 1; + result = prime * result + (latest ? 1231 : 1237); result = prime * result + year; result = prime * result + major; result = prime * result + minor; @@ -150,7 +354,8 @@ public int hashCode() { @Override public String toString() { - return new StringBuilder().append(year).append('.').append(major).append('.').append(minor).append('.') - .append(internal).toString(); + return isLatest() ? STR_LATEST + : new StringBuilder().append(year).append('.').append(major).append('.').append(minor).append('.') + .append(internal).toString(); } } diff --git a/clickhouse-client/src/test/java/com/clickhouse/client/ClickHouseServerForTest.java b/clickhouse-client/src/test/java/com/clickhouse/client/ClickHouseServerForTest.java index 89a4a9c6c..32f897952 100644 --- a/clickhouse-client/src/test/java/com/clickhouse/client/ClickHouseServerForTest.java +++ b/clickhouse-client/src/test/java/com/clickhouse/client/ClickHouseServerForTest.java @@ -86,12 +86,22 @@ public class ClickHouseServerForTest { } String imageNameWithTag = imageName + imageTag; - String additionalPackages = ClickHouseUtils.getProperty("additionalPackages", properties); + String customPackages = ClickHouseUtils.getProperty("additionalPackages", properties); + if (!ClickHouseChecker.isNullOrEmpty(clickhouseVersion) + && ClickHouseVersion.of(clickhouseVersion).isOlderOrBelongsTo("21.3")) { + if (ClickHouseChecker.isNullOrEmpty(customPackages)) { + customPackages = "tzdata"; + } else if (!customPackages.contains("tzdata")) { + customPackages += " tzdata"; + } + } + + final String additionalPackages = customPackages; clickhouseContainer = (ClickHouseChecker.isNullOrEmpty(additionalPackages) ? new GenericContainer<>(imageNameWithTag) : new GenericContainer<>(new ImageFromDockerfile().withDockerfileFromBuilder(builder -> builder - .from(imageNameWithTag).run("apt-get update && apt-get install " + additionalPackages)))) + .from(imageNameWithTag).run("apt-get update && apt-get install -y " + additionalPackages)))) .withEnv("TZ", timezone) .withExposedPorts(ClickHouseProtocol.GRPC.getDefaultPort(), ClickHouseProtocol.HTTP.getDefaultPort(), diff --git a/clickhouse-client/src/test/java/com/clickhouse/client/ClickHouseVersionTest.java b/clickhouse-client/src/test/java/com/clickhouse/client/ClickHouseVersionTest.java index c57c2c249..7516cdd4d 100644 --- a/clickhouse-client/src/test/java/com/clickhouse/client/ClickHouseVersionTest.java +++ b/clickhouse-client/src/test/java/com/clickhouse/client/ClickHouseVersionTest.java @@ -1,44 +1,60 @@ package com.clickhouse.client; import org.testng.Assert; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class ClickHouseVersionTest { - private void check(ClickHouseVersion v, int year, int major, int minor, int internal) { + private void check(ClickHouseVersion v, boolean latest, int year, int major, int minor, int internal) { Assert.assertNotNull(v); + Assert.assertEquals(v.isLatest(), latest); Assert.assertEquals(v.getYear(), year); Assert.assertEquals(v.getMajor(), major); Assert.assertEquals(v.getMinor(), minor); Assert.assertEquals(v.getInternal(), internal); } + @DataProvider(name = "versionProvider") + private Object[][] getVersions() { + // newVersion, oldVersion, sameOrNot + return new Object[][] { { "21.3.1.2345", "21.0", false }, { "21.3.1.2345", "21.3", false }, + { "21.3.12.2345", "21.3.2", false }, { "21.3.2.2345", "21.3.2.2345", true } }; + } + @Test(groups = { "unit" }) public void testConstructor() { - check(new ClickHouseVersion(-1, -2, -3, -4), 0, 0, 0, 0); - check(new ClickHouseVersion(0, 0, 0, 0), 0, 0, 0, 0); - check(new ClickHouseVersion(5, 4, 3, 2), 5, 4, 3, 2); + check(new ClickHouseVersion(false, -1, -2, -3, -4), false, 0, 0, 0, 0); + check(new ClickHouseVersion(true, -1, -2, -3, -4), true, 0, 0, 0, 0); + check(new ClickHouseVersion(false, 0, 0, 0, 0), false, 0, 0, 0, 0); + check(new ClickHouseVersion(true, 0, 0, 0, 0), true, 0, 0, 0, 0); + check(new ClickHouseVersion(false, 5, 4, 3, 2), false, 5, 4, 3, 2); + check(new ClickHouseVersion(true, 5, 4, 3, 2), true, 0, 0, 0, 0); } @Test(groups = { "unit" }) public void testParser() { - check(ClickHouseVersion.of(null), 0, 0, 0, 0); - check(ClickHouseVersion.of(""), 0, 0, 0, 0); - check(ClickHouseVersion.of("twenty-one.three"), 0, 0, 0, 0); - - check(ClickHouseVersion.of("a1b2"), 0, 0, 0, 0); - check(ClickHouseVersion.of("a1b 2abc"), 0, 0, 0, 0); - check(ClickHouseVersion.of("a1.2.3.4"), 0, 0, 0, 0); - check(ClickHouseVersion.of("a1b 2"), 2, 0, 0, 0); - check(ClickHouseVersion.of("a1b 2 aaa"), 2, 0, 0, 0); - check(ClickHouseVersion.of("1.2.3.4"), 1, 2, 3, 4); - check(ClickHouseVersion.of("1.2.3.4.6"), 1, 2, 3, 4); - check(ClickHouseVersion.of(" 1 . 2 . 3 . 4 . 6 "), 1, 2, 3, 4); - check(ClickHouseVersion.of("upgrade from 021.03.00.01 to 21.7.8.9"), 21, 3, 0, 1); - check(ClickHouseVersion.of("21.7..9 is supported"), 21, 7, 0, 0); + check(ClickHouseVersion.of(null), false, 0, 0, 0, 0); + check(ClickHouseVersion.of(""), false, 0, 0, 0, 0); + check(ClickHouseVersion.of("twenty-one.three"), false, 0, 0, 0, 0); + + check(ClickHouseVersion.of(":21.3"), false, 21, 3, 0, 0); + check(ClickHouseVersion.of(": 21.3"), false, 21, 3, 0, 0); + check(ClickHouseVersion.of(":latest"), true, 0, 0, 0, 0); + + check(ClickHouseVersion.of("a1b2"), false, 0, 0, 0, 0); + check(ClickHouseVersion.of("a1b 2abc"), false, 0, 0, 0, 0); + check(ClickHouseVersion.of("a1.2.3.4"), false, 0, 0, 0, 0); + check(ClickHouseVersion.of("a1b 2"), false, 2, 0, 0, 0); + check(ClickHouseVersion.of("a1b 2 aaa"), false, 2, 0, 0, 0); + check(ClickHouseVersion.of("1.2.3.4"), false, 1, 2, 3, 4); + check(ClickHouseVersion.of("1.2.3.4.6"), false, 1, 2, 3, 4); + check(ClickHouseVersion.of(" 1 . 2 . 3 . 4 . 6 "), false, 1, 2, 3, 4); + check(ClickHouseVersion.of("upgrade from 021.03.00.01 to 21.7.8.9"), false, 21, 3, 0, 1); + check(ClickHouseVersion.of("21.7..9 is supported"), false, 21, 7, 0, 0); check(ClickHouseVersion.of( "100000000000000000.10000000000000000000000000.100000000000000000000000000000.10000000000000000000000"), - 0, 0, 0, 0); + false, 0, 0, 0, 0); } @Test(groups = { "unit" }) @@ -47,7 +63,105 @@ public void testCompare() { Assert.assertTrue(ClickHouseVersion.of("21.9").compareTo(ClickHouseVersion.of("19.16")) > 0); Assert.assertTrue(ClickHouseVersion.of("021.03").compareTo(ClickHouseVersion.of("21.3.0.0")) == 0); Assert.assertTrue(ClickHouseVersion.of(null).compareTo(ClickHouseVersion.of(" ")) == 0); + Assert.assertTrue(ClickHouseVersion.of("21.3").compareTo(ClickHouseVersion.of("latest")) < 0); Assert.assertThrows(NullPointerException.class, () -> ClickHouseVersion.of(null).compareTo(null)); } + + @Test(groups = { "unit" }) + public void testLatest() { + Assert.assertTrue(ClickHouseVersion.of(":latest").isLatest()); + Assert.assertTrue(ClickHouseVersion.of("latest").isLatest()); + Assert.assertTrue(ClickHouseVersion.of(" Latest").isLatest()); + Assert.assertTrue(ClickHouseVersion.of("version: latest ").isLatest()); + Assert.assertFalse(ClickHouseVersion.of("latest version").isLatest()); + } + + @Test(dataProvider = "versionProvider", groups = { "unit" }) + public void testNewerVersion(String newVersion, String oldVersion, boolean same) { + Assert.assertTrue(ClickHouseVersion.of(newVersion).isNewerOrEqualTo(oldVersion), + newVersion + " should be newer than or equal to " + oldVersion); + if (same) { + Assert.assertFalse(ClickHouseVersion.of(newVersion).isNewerThan(oldVersion), + newVersion + " should NOT be newer than " + oldVersion); + } else { + Assert.assertTrue(ClickHouseVersion.of(newVersion).isNewerThan(oldVersion), + newVersion + " should be newer than " + oldVersion); + } + } + + @Test(dataProvider = "versionProvider", groups = { "unit" }) + public void testOlderVersion(String newVersion, String oldVersion, boolean same) { + Assert.assertTrue(ClickHouseVersion.of(oldVersion).isOlderOrEqualTo(newVersion), + oldVersion + " should be older than or euqal to " + newVersion); + if (same) { + Assert.assertFalse(ClickHouseVersion.of(oldVersion).isOlderThan(newVersion), + oldVersion + " should NOT be older than " + newVersion); + } else { + Assert.assertTrue(ClickHouseVersion.of(oldVersion).isOlderThan(newVersion), + oldVersion + " should be older than " + newVersion); + } + } + + @Test(groups = { "unit" }) + public void testBelongsTo() { + Assert.assertFalse(ClickHouseVersion.of("21.3").belongsTo("latest")); + Assert.assertFalse(ClickHouseVersion.of("latest").belongsTo("21.3")); + Assert.assertTrue(ClickHouseVersion.of("latest").belongsTo("latest")); + Assert.assertTrue(ClickHouseVersion.of("21").belongsTo("21")); + Assert.assertTrue(ClickHouseVersion.of("21.3").belongsTo("21")); + Assert.assertTrue(ClickHouseVersion.of("21.3.2").belongsTo("21")); + Assert.assertTrue(ClickHouseVersion.of("21.3.2.1").belongsTo("21")); + Assert.assertFalse(ClickHouseVersion.of("21").belongsTo("21.3")); + Assert.assertTrue(ClickHouseVersion.of("21.3").belongsTo("21.3")); + Assert.assertTrue(ClickHouseVersion.of("21.3.2").belongsTo("21.3")); + Assert.assertTrue(ClickHouseVersion.of("21.3.2.1").belongsTo("21.3")); + Assert.assertFalse(ClickHouseVersion.of("21").belongsTo("21.3.2")); + Assert.assertFalse(ClickHouseVersion.of("21.3").belongsTo("21.3.2")); + Assert.assertTrue(ClickHouseVersion.of("21.3.2").belongsTo("21.3.2")); + Assert.assertTrue(ClickHouseVersion.of("21.3.2.1").belongsTo("21.3.2")); + Assert.assertFalse(ClickHouseVersion.of("21").belongsTo("21.3.2.1")); + Assert.assertFalse(ClickHouseVersion.of("21.3").belongsTo("21.3.2.1")); + Assert.assertFalse(ClickHouseVersion.of("21.3.2").belongsTo("21.3.2.1")); + Assert.assertTrue(ClickHouseVersion.of("21.3.2.1").belongsTo("21.3.2.1")); + } + + @Test(groups = { "unit" }) + public void testIsBeyond() { + Assert.assertFalse(ClickHouseVersion.of("21.3").isBeyond("latest")); + Assert.assertTrue(ClickHouseVersion.of("latest").isBeyond("21.3")); + Assert.assertFalse(ClickHouseVersion.of("latest").isBeyond("latest")); + Assert.assertFalse(ClickHouseVersion.of("21").isBeyond("21")); + Assert.assertFalse(ClickHouseVersion.of("21.3").isBeyond("21")); + Assert.assertFalse(ClickHouseVersion.of("21.3.2").isBeyond("21")); + Assert.assertFalse(ClickHouseVersion.of("21.3.2.1").isBeyond("21")); + Assert.assertTrue(ClickHouseVersion.of("22").isBeyond("21")); + Assert.assertTrue(ClickHouseVersion.of("22.3").isBeyond("21")); + Assert.assertTrue(ClickHouseVersion.of("22.3.2").isBeyond("21")); + Assert.assertTrue(ClickHouseVersion.of("22.3.2.1").isBeyond("21")); + Assert.assertFalse(ClickHouseVersion.of("21").isBeyond("21.3")); + Assert.assertFalse(ClickHouseVersion.of("21.3").isBeyond("21.3")); + Assert.assertFalse(ClickHouseVersion.of("21.3.2").isBeyond("21.3")); + Assert.assertFalse(ClickHouseVersion.of("21.3.2.1").isBeyond("21.3")); + Assert.assertTrue(ClickHouseVersion.of("22").isBeyond("21.3")); + Assert.assertTrue(ClickHouseVersion.of("21.4").isBeyond("21.3")); + Assert.assertTrue(ClickHouseVersion.of("21.4.2").isBeyond("21.3")); + Assert.assertTrue(ClickHouseVersion.of("21.4.2.1").isBeyond("21.3")); + Assert.assertFalse(ClickHouseVersion.of("21").isBeyond("21.3.2")); + Assert.assertFalse(ClickHouseVersion.of("21.3").isBeyond("21.3.2")); + Assert.assertFalse(ClickHouseVersion.of("21.3.2").isBeyond("21.3.2")); + Assert.assertFalse(ClickHouseVersion.of("21.3.2.1").isBeyond("21.3.2")); + Assert.assertTrue(ClickHouseVersion.of("22").isBeyond("21.3.2")); + Assert.assertTrue(ClickHouseVersion.of("21.4").isBeyond("21.3.2")); + Assert.assertTrue(ClickHouseVersion.of("21.3.3").isBeyond("21.3.2")); + Assert.assertTrue(ClickHouseVersion.of("21.3.3.1").isBeyond("21.3.2")); + Assert.assertFalse(ClickHouseVersion.of("21").isBeyond("21.3.2.1")); + Assert.assertFalse(ClickHouseVersion.of("21.3").isBeyond("21.3.2.1")); + Assert.assertFalse(ClickHouseVersion.of("21.3.2").isBeyond("21.3.2.1")); + Assert.assertFalse(ClickHouseVersion.of("21.3.2.1").isBeyond("21.3.2.1")); + Assert.assertTrue(ClickHouseVersion.of("22").isBeyond("21.3.2.1")); + Assert.assertTrue(ClickHouseVersion.of("21.4").isBeyond("21.3.2.1")); + Assert.assertTrue(ClickHouseVersion.of("21.3.3").isBeyond("21.3.2.1")); + Assert.assertTrue(ClickHouseVersion.of("21.3.2.2").isBeyond("21.3.2.1")); + } } diff --git a/clickhouse-grpc-client/src/test/java/com/clickhouse/client/grpc/ClickHouseGrpcClientTest.java b/clickhouse-grpc-client/src/test/java/com/clickhouse/client/grpc/ClickHouseGrpcClientTest.java index 595bd7b99..216f3cc7e 100644 --- a/clickhouse-grpc-client/src/test/java/com/clickhouse/client/grpc/ClickHouseGrpcClientTest.java +++ b/clickhouse-grpc-client/src/test/java/com/clickhouse/client/grpc/ClickHouseGrpcClientTest.java @@ -33,6 +33,7 @@ import com.clickhouse.client.ClickHouseResponseSummary; import com.clickhouse.client.ClickHouseUtils; import com.clickhouse.client.ClickHouseValue; +import com.clickhouse.client.ClickHouseVersion; import com.clickhouse.client.ClickHouseWriter; import com.clickhouse.client.config.ClickHouseClientOption; import com.clickhouse.client.data.ClickHouseDateTimeValue; @@ -378,10 +379,6 @@ public void testReadWriteGeoTypes() throws Exception { @Test(dataProvider = "simpleTypeProvider", groups = "integration") public void testReadWriteSimpleTypes(String dataType, String zero, String negativeOne, String positiveOne) throws Exception { - // if (ClickHouseDataType.Date32.name().equals(dataType)) { - // return; - // } - ClickHouseNode server = getServer(ClickHouseProtocol.GRPC); String typeName = dataType; @@ -423,9 +420,11 @@ public void testReadWriteSimpleTypes(String dataType, String zero, String negati return; } + ClickHouseVersion version = null; try (ClickHouseClient client = ClickHouseClient.newInstance(ClickHouseProtocol.GRPC); - ClickHouseResponse resp = client.connect(server).format(ClickHouseFormat.RowBinaryWithNamesAndTypes) - .query(ClickHouseUtils.format("select * except(no) from test_%s order by no", columnName)) + ClickHouseResponse resp = client + .connect(server).format(ClickHouseFormat.RowBinaryWithNamesAndTypes).query(ClickHouseUtils + .format("select * except(no), version() from test_%s order by no", columnName)) .execute().get()) { List records = new ArrayList<>(); for (ClickHouseRecord record : resp.records()) { @@ -440,12 +439,24 @@ public void testReadWriteSimpleTypes(String dataType, String zero, String negati Assert.assertEquals(records.size(), 4); Assert.assertEquals(records.get(0)[0], zero); Assert.assertEquals(records.get(0)[1], null); + if (version == null) { + version = ClickHouseVersion.of(records.get(0)[2]); + } + Assert.assertEquals(records.get(1)[0], zero); Assert.assertEquals(records.get(1)[1], zero); - Assert.assertEquals(records.get(2)[0], negativeOne); - Assert.assertEquals(records.get(2)[1], negativeOne); Assert.assertEquals(records.get(3)[0], positiveOne); Assert.assertEquals(records.get(3)[1], positiveOne); + + if ((ClickHouseDataType.DateTime.name().equals(dataType) + || ClickHouseDataType.DateTime32.name().equals(dataType)) && version.getYear() == 21 + && version.getMajor() == 3) { + // skip DateTime and DateTime32 negative test on 21.3 since it's not doing well + // see https://github.com/ClickHouse/ClickHouse/issues/29835 for more + } else { + Assert.assertEquals(records.get(2)[0], negativeOne); + Assert.assertEquals(records.get(2)[1], negativeOne); + } } } diff --git a/clickhouse-http-client/pom.xml b/clickhouse-http-client/pom.xml index 5a558e0fb..5a7a60dc2 100644 --- a/clickhouse-http-client/pom.xml +++ b/clickhouse-http-client/pom.xml @@ -7,7 +7,6 @@ ${revision} - ${project.parent.groupId} clickhouse-http-client ${revision} jar diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHouseStatementImplTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHouseStatementImplTest.java index 268b8005d..2127a6228 100644 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHouseStatementImplTest.java +++ b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/ClickHouseStatementImplTest.java @@ -27,17 +27,15 @@ 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.ClickHouseConnection; -import ru.yandex.clickhouse.ClickHouseDataSource; -import ru.yandex.clickhouse.ClickHouseExternalData; -import ru.yandex.clickhouse.ClickHouseStatement; import ru.yandex.clickhouse.settings.ClickHouseProperties; import ru.yandex.clickhouse.settings.ClickHouseQueryParam; -import ru.yandex.clickhouse.util.ClickHouseVersionNumberUtil; public class ClickHouseStatementImplTest extends JdbcIntegrationTest { private ClickHouseConnection connection; @@ -126,8 +124,7 @@ public void testSelectUInt64() throws SQLException { public void testExternalData() throws SQLException, UnsupportedEncodingException { String serverVersion = connection.getServerVersion(); ClickHouseStatement stmt = connection.createStatement(); - String[] rows = ClickHouseVersionNumberUtil.getMajorVersion(serverVersion) >= 21 - && ClickHouseVersionNumberUtil.getMinorVersion(serverVersion) >= 3 + String[] rows = ClickHouseVersion.of(serverVersion).isNewerOrEqualTo("21.3") ? new String[] { "1\tGroup\n" } : new String[] { "1\tGroup", "1\tGroup\n" }; @@ -154,8 +151,7 @@ public void testExternalData() throws SQLException, UnsupportedEncodingException @Test(groups = "integration") public void testLargeQueryWithExternalData() throws Exception { String serverVersion = connection.getServerVersion(); - String[] rows = ClickHouseVersionNumberUtil.getMajorVersion(serverVersion) >= 21 - && ClickHouseVersionNumberUtil.getMinorVersion(serverVersion) >= 3 + String[] rows = ClickHouseVersion.of(serverVersion).isNewerOrEqualTo("21.3") ? new String[] { "1\tGroup\n" } : new String[] { "1\tGroup", "1\tGroup\n" }; 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 index b6c8452df..6b72c2546 100644 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseBitmapTest.java +++ b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseBitmapTest.java @@ -11,6 +11,8 @@ 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; @@ -171,7 +173,7 @@ public void testRoaringBitmap() throws Exception { @Test(groups = "integration") public void testRoaringBitmap64() throws Exception { - if (conn == null) { + if (conn == null || ClickHouseVersion.of(conn.getServerVersion()).isOlderOrBelongsTo("20.8")) { return; } 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 index 60bdd816f..46d84b8c5 100644 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseDatabaseMetadataTest.java +++ b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseDatabaseMetadataTest.java @@ -7,6 +7,8 @@ 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; @@ -17,7 +19,6 @@ import ru.yandex.clickhouse.ClickHouseConnection; import ru.yandex.clickhouse.ClickHouseDatabaseMetadata; import ru.yandex.clickhouse.JdbcIntegrationTest; -import ru.yandex.clickhouse.util.ClickHouseVersionNumberUtil; public class ClickHouseDatabaseMetadataTest extends JdbcIntegrationTest { private ClickHouseConnection connection; @@ -56,7 +57,7 @@ public void testMetadata() throws Exception { @Test(groups = "integration") public void testMetadataColumns() throws Exception { - boolean supportComment = ClickHouseVersionNumberUtil.compare(connection.getServerVersion(), "18.16") >= 0; + boolean supportComment = ClickHouseVersion.of(connection.getServerVersion()).isNewerOrEqualTo("18.16"); connection.createStatement().executeQuery( "DROP TABLE IF EXISTS testMetadata"); connection.createStatement().executeQuery( @@ -157,10 +158,8 @@ public void testToDateTimeTZ() throws Exception { ResultSetMetaData meta = rs.getMetaData(); Assert.assertEquals(meta.getColumnClassName(1), Timestamp.class.getCanonicalName()); TimeZone timezone = ((ClickHouseConnection) connection).getTimeZone(); - String version = ((ClickHouseConnection) connection).getServerVersion(); - int majorVersion = ClickHouseVersionNumberUtil.getMajorVersion(version); - int minorVersion = ClickHouseVersionNumberUtil.getMinorVersion(version); - if (majorVersion > 21 || (majorVersion == 21 && minorVersion >= 6)) { + ClickHouseVersion version = ClickHouseVersion.of(((ClickHouseConnection) connection).getServerVersion()); + if (version.isNewerOrEqualTo("21.6")) { Assert.assertEquals(meta.getColumnTypeName(1), "DateTime"); } else { Assert.assertEquals(meta.getColumnTypeName(1), "DateTime('" + timezone.getID() + "')"); 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 index d955747ea..6b5d577ff 100644 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseLargeNumberTest.java +++ b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseLargeNumberTest.java @@ -16,6 +16,8 @@ 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; @@ -27,7 +29,6 @@ import ru.yandex.clickhouse.except.ClickHouseException; import ru.yandex.clickhouse.settings.ClickHouseProperties; import ru.yandex.clickhouse.settings.ClickHouseQueryParam; -import ru.yandex.clickhouse.util.ClickHouseVersionNumberUtil; public class ClickHouseLargeNumberTest extends JdbcIntegrationTest { private ClickHouseConnection conn; @@ -58,7 +59,7 @@ public void tearDown() throws Exception { @Test(groups = "integration") public void testBigIntSupport() throws SQLException { - if (conn == null || ClickHouseVersionNumberUtil.compare(conn.getServerVersion(), "21.7") >= 0) { + if (conn == null || ClickHouseVersion.of(conn.getServerVersion()).isNewerOrEqualTo("21.7")) { return; } @@ -167,7 +168,7 @@ public void testDecimal256() throws Exception { } // check max scale - if (ClickHouseVersionNumberUtil.compare(conn.getServerVersion(), "21.9") >= 0) { + if (ClickHouseVersion.of(conn.getServerVersion()).isNewerOrEqualTo("21.9")) { s.execute("set output_format_decimal_trailing_zeros=1"); } try (ResultSet rs = s.executeQuery("select d from test_decimal256 order by d")) { 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 index 97aa36786..8d349c940 100644 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseMapTest.java +++ b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseMapTest.java @@ -16,6 +16,8 @@ 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; @@ -27,7 +29,6 @@ import ru.yandex.clickhouse.except.ClickHouseException; import ru.yandex.clickhouse.settings.ClickHouseProperties; import ru.yandex.clickhouse.settings.ClickHouseQueryParam; -import ru.yandex.clickhouse.util.ClickHouseVersionNumberUtil; import ru.yandex.clickhouse.util.Utils; public class ClickHouseMapTest extends JdbcIntegrationTest { @@ -78,19 +79,16 @@ public void testMapSupport() throws SQLException { 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()) { + try (ClickHouseConnection conn = newDataSource().getConnection(); Statement s = conn.createStatement()) { s.execute("set allow_experimental_map_type=0;" + testSql); - String version = conn.getServerVersion(); - if (version.compareTo("21.8") < 0) { + if (ClickHouseVersion.of(conn.getServerVersion()).isOlderThan("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()) { + try (Connection conn = newDataSource().getConnection(); Statement s = conn.createStatement()) { assertFalse(s.execute("set allow_experimental_map_type=1;" + testSql)); } @@ -102,8 +100,7 @@ public void testMapSupport() throws SQLException { params.put(ClickHouseQueryParam.ALLOW_EXPERIMENTAL_MAP_TYPE, "0"); s.executeQuery(testSql, params); - String version = conn.getServerVersion(); - if (version.compareTo("21.8") < 0) { + if (ClickHouseVersion.of(conn.getServerVersion()).isOlderThan("21.8")) { fail("Should fail without enabling map support"); } } catch (SQLException e) { @@ -117,23 +114,24 @@ public void testMaps() throws Exception { 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 version = ((ClickHouseConnection) conn).getServerVersion(); - int majorVersion = ClickHouseVersionNumberUtil.getMajorVersion(version); - int minorVersion = ClickHouseVersionNumberUtil.getMinorVersion(version); - if (majorVersion > 21 || (majorVersion == 21 && minorVersion >= 3)) { + ClickHouseVersion version = ClickHouseVersion.of(conn.getServerVersion()); + if (version.isOlderOrBelongsTo("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.isNewerOrEqualTo("21.4") && version.isOlderThan("21.9")) { columns = ""; values = ""; - - return; + 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 + ")"); + s.execute("insert into test_maps values ({'k1':'v1','k2':'v2'}" + values + ")"); try (ResultSet rs = s.executeQuery("select * from test_maps")) { assertTrue(rs.next()); @@ -148,7 +146,7 @@ public void testMaps() throws Exception { s.execute("truncate table test_maps"); } - try (PreparedStatement s = conn.prepareStatement("insert into test_maps values(?,?,?)")) { + 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" })); 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 index 163730bfe..61f6c7a3d 100644 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ErrorsTest.java +++ b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ErrorsTest.java @@ -9,8 +9,8 @@ import ru.yandex.clickhouse.JdbcIntegrationTest; import ru.yandex.clickhouse.except.ClickHouseException; import ru.yandex.clickhouse.settings.ClickHouseProperties; -import ru.yandex.clickhouse.util.ClickHouseVersionNumberUtil; import com.clickhouse.client.ClickHouseServerForTest; +import com.clickhouse.client.ClickHouseVersion; import java.sql.Connection; import java.sql.Date; @@ -40,7 +40,7 @@ public void testWrongUser() { try (Connection connection = newConnection(properties)) { } catch (Exception e) { String version = ClickHouseServerForTest.getClickHouseVersion(); - if (!version.isEmpty() && ClickHouseVersionNumberUtil.getMajorVersion(version) <= 19) { + if (!version.isEmpty() && ClickHouseVersion.of(version).isOlderOrBelongsTo("19")) { Assert.assertEquals((getClickhouseException(e)).getErrorCode(), 192); } else { Assert.assertEquals((getClickhouseException(e)).getErrorCode(), 516); 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 index 1af34d107..a3ca6a32f 100644 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/RowBinaryStreamTest.java +++ b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/RowBinaryStreamTest.java @@ -18,6 +18,9 @@ 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; @@ -35,7 +38,6 @@ import ru.yandex.clickhouse.util.ClickHouseRowBinaryInputStream; import ru.yandex.clickhouse.util.ClickHouseRowBinaryStream; import ru.yandex.clickhouse.util.ClickHouseStreamCallback; -import ru.yandex.clickhouse.util.ClickHouseVersionNumberUtil; /** * @author Dmitry Andreev @@ -55,53 +57,28 @@ public void tearDown() throws Exception { 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" - ); + 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()" - ); + 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)", + connection.createStatement().sendRowBinaryStream("INSERT INTO big_data (value)", new ClickHouseStreamCallback() { @Override public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { @@ -110,17 +87,16 @@ public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { sum.addAndGet(i); } } - } - ); + }); - ResultSet rs = connection.createStatement().executeQuery("SELECT count() AS cnt, sum(value) AS sum FROM big_data"); + 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); @@ -137,8 +113,8 @@ private String createtestBitmapTable(ClickHouseDataType innerType) throws Except 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"); + statement.execute("CREATE TABLE IF NOT EXISTS " + tableName + "(i UInt8, a " + arrType + ", b " + rbTypeName + + ") engine=Memory"); } return tableName; @@ -164,8 +140,8 @@ private long[] gen64BitmapValues(int length, long base, long step) { return values; } - private void writeValues(ClickHouseRowBinaryStream stream, - int [] values, ClickHouseDataType innerType) throws IOException { + private void writeValues(ClickHouseRowBinaryStream stream, int[] values, ClickHouseDataType innerType) + throws IOException { switch (innerType) { case Int8: case UInt8: @@ -204,16 +180,17 @@ public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { }); for (int i = 0; i < 3; i++) { - String sql = "select b = bitmapBuild(a) ? 1 : 0 from " + tableName + " where i = " + (i+1); + 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); + 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)); + assertEquals(in.readBitmap(innerType), + ClickHouseBitmap.wrap(RoaringBitmap.bitmapOf(values), innerType)); } } @@ -231,10 +208,12 @@ private void testBitmap64(int valueLength, long base, long step) throws Exceptio public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { stream.writeByte((byte) 1); stream.writeUInt64Array(values); - stream.writeBitmap(ClickHouseBitmap.wrap(Roaring64NavigableMap.bitmapOf(values), ClickHouseDataType.UInt64)); + 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)); + stream.writeBitmap( + ClickHouseBitmap.wrap(Roaring64Bitmap.bitmapOf(values), ClickHouseDataType.UInt64)); } }); @@ -249,13 +228,14 @@ public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { sql = "select b from " + tableName + " order by i"; try (ClickHouseRowBinaryInputStream in = statement.executeQueryClickhouseRowBinaryStream(sql)) { - assertEquals(in.readBitmap(innerType), ClickHouseBitmap.wrap(Roaring64NavigableMap.bitmapOf(values), innerType)); + 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 @@ -269,10 +249,7 @@ public void testBitmap() throws Exception { testBitmap64(32, 0L, 1L); testBitmap64(32, Long.MAX_VALUE, -1L); - String versionNumber = connection.getServerVersion(); - int majorVersion = ClickHouseVersionNumberUtil.getMajorVersion(versionNumber); - int minorVersion = ClickHouseVersionNumberUtil.getMinorVersion(versionNumber); - if (majorVersion > 20 || (majorVersion == 20 && minorVersion > 8)) { + if (ClickHouseVersion.of(connection.getServerVersion()).isBeyond("20.8")) { testBitmap64(65537, 100000L, 1L); // highToBitmap.size() == 1 testBitmap64(65537, 9223372036854775807L, -1000000000L); // highToBitmap.size() > 1 } @@ -282,17 +259,14 @@ public void testBitmap() throws Exception { 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"); + + "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) - }; + 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 { @@ -321,32 +295,30 @@ public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { 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 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 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() { + 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 { @@ -393,33 +365,32 @@ public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { 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.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.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); @@ -482,8 +453,8 @@ public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { Assert.assertFalse(rs.next()); } else { - ClickHouseRowBinaryInputStream is = connection.createStatement().executeQueryClickhouseRowBinaryStream( - "SELECT * FROM raw_binary ORDER BY date"); + ClickHouseRowBinaryInputStream is = connection.createStatement() + .executeQueryClickhouseRowBinaryStream("SELECT * FROM raw_binary ORDER BY date"); assertEquals(is.readDate(), withTimeAtStartOfDay(date1)); assertEquals(is.readDateTime(), new Timestamp(timestamp)); @@ -572,32 +543,25 @@ public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { } } - @Test(groups = "integration") - public void testTimeZone() throws Exception{ + 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(date, (date), 8192)" - ); + "CREATE TABLE binary_tz (date Date, dateTime DateTime) ENGINE = MergeTree(date, (date), 8192)"); // 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); - } + 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" - ); + ResultSet rs = connection.createStatement().executeQuery("SELECT date, dateTime from binary_tz"); Assert.assertTrue(rs.next()); @@ -605,19 +569,16 @@ public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { * 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." + * "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 + * 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)); + 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); 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 index 73d01100e..9600c4247 100644 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/StreamSQLTest.java +++ b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/StreamSQLTest.java @@ -15,6 +15,9 @@ 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; @@ -23,7 +26,6 @@ import ru.yandex.clickhouse.JdbcIntegrationTest; import ru.yandex.clickhouse.domain.ClickHouseCompression; import ru.yandex.clickhouse.domain.ClickHouseFormat; -import ru.yandex.clickhouse.util.ClickHouseVersionNumberUtil; public class StreamSQLTest extends JdbcIntegrationTest { private static final DateTimeFormatter DATE_TIME_FORMATTER_TZ = @@ -266,7 +268,7 @@ public void ORCInsertCompressedIntoTable() throws SQLException { // toDateTime('2020-01-01 00:00:00') + number time from numbers(100) format ORC"|gzip > test_sample.orc.gz String version = connection.getServerVersion(); - if (ClickHouseVersionNumberUtil.compare(version, "20.8") < 0) { + if (ClickHouseVersion.of(version).isOlderThan("20.8")) { return; } @@ -310,8 +312,7 @@ 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 - String version = connection.getServerVersion(); - if (version.compareTo("20.8") < 0) { + if (ClickHouseVersion.of(connection.getServerVersion()).isOlderThan("20.8")) { return; } @@ -345,8 +346,7 @@ 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 - String version = connection.getServerVersion(); - if (version.compareTo("20.8") < 0) { + if (ClickHouseVersion.of(connection.getServerVersion()).isOlderThan("20.8")) { return; } @@ -390,8 +390,7 @@ 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 - String version = connection.getServerVersion(); - if (version.compareTo("20.8") < 0) { + if (ClickHouseVersion.of(connection.getServerVersion()).isOlderThan("20.8")) { return; } diff --git a/clickhouse-tcp-client/pom.xml b/clickhouse-tcp-client/pom.xml index 9098716d6..8d3cb1093 100644 --- a/clickhouse-tcp-client/pom.xml +++ b/clickhouse-tcp-client/pom.xml @@ -7,7 +7,6 @@ ${revision} - ${project.parent.groupId} clickhouse-tcp-client ${revision} jar