Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
c361379
Prepare for JDBC 4.2 #406
enqueue Jan 11, 2020
9cee6c3
Rebase on master
enqueue Feb 1, 2021
96ff1b1
It is time for Java 1.8!
enqueue Feb 1, 2021
619e469
fix rebase
enqueue Feb 2, 2021
568e0e1
fix tests
enqueue Feb 6, 2021
4e57663
Reduce merge conflict potential
enqueue Feb 6, 2021
1eb0220
Merge branch 'develop' into jdbc_4.2
enqueue Feb 6, 2021
853b9ee
fix compile
enqueue Feb 17, 2021
430deec
Reconcile with develop branch
enqueue Feb 17, 2021
65f5063
Merge branch 'develop' into jdbc_4.2
enqueue Feb 18, 2021
1e6896a
Merge pull request #418 from enqueue/jdbc_4.2
zhicwu Feb 26, 2021
e0ef706
Consider server timezone in SIT
zhicwu Feb 26, 2021
697f339
Bump version and remove hard-coded timezone
zhicwu Feb 26, 2021
ce338b4
Fix issues introduced in PR #571
zhicwu Feb 26, 2021
af97634
test for large external data
den-crane Feb 26, 2021
e554c1a
Fix failures found in PR #418
zhicwu Feb 27, 2021
6a7ac51
Avoid conflict among test methods
zhicwu Feb 27, 2021
20b3e15
Skip testTimeZoneParseSQLDate5 for now
zhicwu Feb 27, 2021
640b401
Fix more issues related to Date and Time
zhicwu Feb 27, 2021
7f8cd7c
Disable unstable test case for now
zhicwu Feb 27, 2021
896bb6d
Update benchmark workflow
zhicwu Feb 27, 2021
bf6d0d1
Revert the change in case someone extended this class - will refactor…
zhicwu Feb 27, 2021
c4fe4d0
Merge pull request #580 from zhicwu/fix-build-break
zhicwu Feb 27, 2021
0bc6d8e
Merge pull request #579 from den-crane/test/ext_data
zhicwu Feb 27, 2021
38c1b50
restructure code
zhicwu Feb 28, 2021
ef3b27b
Enhance parent pom for static code analysis
zhicwu Feb 28, 2021
7dee3b3
Merge pull request #581 from zhicwu/multi-modules
zhicwu Feb 28, 2021
28e6e99
Feat: ClickHouseRowBinaryStream add writeBytes function
Feb 28, 2021
074a030
Remove guava
zhicwu Mar 3, 2021
3afc9c2
Merge pull request #584 from zhicwu/remove-guava
zhicwu Mar 3, 2021
d146847
Use pull_request_target instead of pull_request
zhicwu Mar 3, 2021
37c11c3
restrict target branches
zhicwu Mar 3, 2021
55f30b8
Merge pull request #585 from zhicwu/fix-workflow
zhicwu Mar 3, 2021
da45afb
throw SQLException ClickHouseConnectionImpl constructor
zhicwu Mar 3, 2021
660608e
Fix build break
zhicwu Mar 3, 2021
f99a67a
Merge pull request #586 from zhicwu/exception
zhicwu Mar 3, 2021
b5e6c53
Remove duplicated CLI
zhicwu Mar 3, 2021
09ae9eb
Fix issues in benchmark
zhicwu Mar 4, 2021
22c4cc0
Merge pull request #587 from zhicwu/benchmark
zhicwu Mar 4, 2021
c69fad0
Test UUID Array
enqueue Mar 4, 2021
6f69853
Support more data types
zhicwu Mar 5, 2021
0bf7044
Split test cases
zhicwu Mar 5, 2021
03b2476
Add 21.3(LTS), and remove 19.14 and 20.3 from regression as they're n…
zhicwu Mar 12, 2021
e89a322
Add workaround for timezone issue and update test cases accordingly
zhicwu Mar 12, 2021
8341dd7
Remove 21.3 as it's not available in public
zhicwu Mar 12, 2021
c4aad78
Fix build failure caused by Date.toLocalDate()
zhicwu Mar 12, 2021
5b1947b
Fix issue of converting DateTime to Date
zhicwu Mar 12, 2021
63cdf55
Add seperate check for timezone testing
zhicwu Mar 12, 2021
5e9e16e
Merge pull request #589 from zhicwu/new-data-types
zhicwu Mar 12, 2021
f4e786f
Merge pull request #588 from enqueue/uuid_array
zhicwu Mar 12, 2021
defb610
Fix bugs reported by sonarcloud
zhicwu Mar 12, 2021
8157816
Add client_name connection setting
zhicwu Mar 12, 2021
f517e87
optionally return unwrapped array
zhicwu Mar 12, 2021
4a063dd
Add more tests
zhicwu Mar 12, 2021
b2555be
Fix build break
zhicwu Mar 12, 2021
11f3184
Use UTC for generic testing
zhicwu Mar 12, 2021
659b3fe
Use UTC for generic testing
zhicwu Mar 12, 2021
553c907
Remove useless file
zhicwu Mar 12, 2021
a90da54
Merge pull request #592 from zhicwu/client-name
zhicwu Mar 12, 2021
b8702a3
Do NOT fail build on error
zhicwu Mar 21, 2021
d67832e
Only test against supported LTS and latest stable version
zhicwu Mar 21, 2021
e9514e7
Bump native driver version
zhicwu Mar 21, 2021
71c8655
Add more dependencies
zhicwu Mar 21, 2021
8100c6f
Add Bitmap support
zhicwu Mar 21, 2021
479b491
Fix checkstyle issues
zhicwu Mar 22, 2021
d4ec483
Merge PR #598
zhicwu Mar 22, 2021
e3a9a9a
Merge PR #598
zhicwu Mar 22, 2021
3797d4f
Disable fail-fast in build workflow
zhicwu Mar 22, 2021
cf9c610
Skip bitmap64 test in 20.8
zhicwu Mar 22, 2021
411874f
Merge branch 'develop' into roaringbitmap
zhicwu Mar 22, 2021
3fc7aa1
Disable 3 test cases on 21.3.3.14 due to build failures caused by server
zhicwu Mar 23, 2021
bbfca81
Merge branch 'roaringbitmap' of github.com:zhicwu/clickhouse-jdbc int…
zhicwu Mar 23, 2021
9267440
Merge pull request #596 from zhicwu/roaringbitmap
zhicwu Mar 23, 2021
c3fb547
Explicitly add "compress" query parameter according to given option, …
zhicwu Mar 23, 2021
9be5e87
Merge pull request #599 from zhicwu/fix-591
zhicwu Mar 23, 2021
5654830
Switch to new Sonatype server for deployment
zhicwu Mar 24, 2021
d697279
Fix 64-bit bitmap deser issue
zhicwu Mar 24, 2021
cc6be0b
Merge pull request #582 from fishisnow/feature/ClickhouseBinaryStream…
zhicwu Mar 24, 2021
cceb1cf
merge PR #559
zhicwu Mar 24, 2021
4932653
Update changelog for 0.3.0
zhicwu Mar 24, 2021
549a62f
Merge pull request #601 from zhicwu/prepare-release
zhicwu Mar 24, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions .github/workflows/analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ on:
- master
- develop
- 0.2.x
pull_request:
pull_request_target:
branches:
- master
- develop
types:
- opened
- synchronize
Expand All @@ -28,7 +31,7 @@ jobs:
uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.sha }}
if: github.event_name == 'pull_request'
if: github.event_name == 'pull_request_target'
- name: Check out PR
run: |
git fetch --no-tags --prune --progress --no-recurse-submodules --depth=1 \
Expand Down Expand Up @@ -57,11 +60,18 @@ jobs:
reporter: 'github-pr-check'
# added,diff_context,file,nofilter
filter_mode: 'added'
if: github.event_name == 'pull_request' || github.event.inputs.pr != ''
if: github.event_name == 'pull_request_target' || github.event.inputs.pr != ''
continue-on-error: true
- name: Update sonar config
run: |
sed -i -e 's|^\(.*<sonar.projectKey>\).*\(</sonar.projectKey>\)$|\1ClickHouse_clickhouse-jdbc\2|' \
-e 's|^\(.*<sonar.organization>\).*\(</sonar.organization>\)$|\1clickhouse-java\2|' pom.xml
if: github.repository_owner == 'ClickHouse'
- name: Build and analyze
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
find . -type f -name "log4j.*" -exec rm -fv '{}' \;
mvn -q --batch-mode -Panalysis verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar
continue-on-error: true
20 changes: 10 additions & 10 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
name: Benchmark

on:
pull_request:
pull_request_target:
branches:
- master
- develop
types:
- opened
- synchronize
Expand Down Expand Up @@ -36,7 +39,7 @@ jobs:
benchmark-pull-request:
runs-on: ubuntu-latest
name: Benchmark pull request
if: github.event_name == 'pull_request'
if: github.event_name == 'pull_request_target'
steps:
- name: Check out repository
uses: actions/checkout@v2
Expand Down Expand Up @@ -69,13 +72,10 @@ jobs:
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
if (process.env.BENCHMARK_REPORT) {
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '```\n' + process.env.BENCHMARK_REPORT + '\n```'
});
const report = process.env.BENCHMARK_REPORT;
const { issue: { number: issue_number }, repo: { owner, repo } } = context;
if (report) {
github.issues.createComment({issue_number, owner, repo, body: '```\n' + report + '\n```'});
}

benchmark-on-demand:
Expand Down Expand Up @@ -108,8 +108,8 @@ jobs:
continue-on-error: true
- name: Build project
run: |
mvn --batch-mode --update-snapshots -DskipTests -pl clickhouse-benchmark -am package
cd clickhouse-benchmark
mvn --batch-mode --update-snapshots -DclickhouseVersion=${{ github.event.inputs.clickhouse }} install
java -jar target/benchmarks.jar -rf json ${{ github.event.inputs.options }} > output.txt
echo "BENCHMARK_REPORT<<EOF" >> $GITHUB_ENV
tail -n +$(grep -n '^REMEMBER:' output.txt | tail -1 | awk -F: '{print $1+6}') output.txt | head -n -2 | grep -v ':·' >> $GITHUB_ENV
Expand Down
26 changes: 4 additions & 22 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
java: [8, 11]
java: [8, 11, 15]
# most recent LTS releases as well as latest stable builds
clickhouse: ["19.14", "20.3", "20.8", "20.10", "20.12", "21.2", "latest"]
clickhouse: ["20.8", "21.3", "latest"]
fail-fast: false
name: Build using JDK ${{ matrix.java }} against ClickHouse ${{ matrix.clickhouse }}
steps:
- name: Check out Git repository
Expand All @@ -56,25 +57,6 @@ jobs:
key: ${{ runner.os }}-build-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-build-
- name: Generate build properties
uses: actions/github-script@v3
id: props
env:
CURRENT_VERSION: ${{ steps.version.outputs.value }}
with:
script: |
const timezones = [
'Asia/Chongqing', 'America/Los_Angeles', 'Etc/UTC', 'Europe/Berlin', 'Europe/Moscow'
];
// surprise me
return {
clickhouse: timezones[Math.floor(Math.random() * Math.floor(timezones.length))] || '',
java: timezones[Math.floor(Math.random() * Math.floor(timezones.length))] || ''
};
- name: Build with Maven
run: |
find . -type f -name "pom.xml" -exec sed -i -e 's|.*argLine.*timezone=.*||g' '{}' \;
mvn --batch-mode --update-snapshots \
-DclickhouseVersion=${{ matrix.clickhouse }} \
-DclickhouseTimezone=${{ fromJSON(steps.props.outputs.result).clickhouse }} \
-Duser.timezone=${{ fromJSON(steps.props.outputs.result).java }} verify
mvn --batch-mode --update-snapshots -DclickhouseVersion=${{ matrix.clickhouse }} verify
62 changes: 62 additions & 0 deletions .github/workflows/timezone.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: TimeZone

on:
push:
branches:
- master
- develop
paths-ignore:
- "**.md"
- "docs/**"
- "**/CHANGELOG"

pull_request:
types:
- opened
- synchronize
- reopened
paths-ignore:
- "**.md"
- "docs/**"
- "**/CHANGELOG"

workflow_dispatch:
inputs:
pr:
description: "Pull request#"
required: false

jobs:
timezone:
runs-on: ubuntu-latest
strategy:
matrix:
serverTz: ["Asia/Chongqing", "America/Los_Angeles", "Etc/UTC", "Europe/Berlin", "Europe/Moscow"]
clientTz: ["Asia/Chongqing", "America/Los_Angeles", "Etc/UTC", "Europe/Berlin", "Europe/Moscow"]
fail-fast: false
name: "Test TimeZones - Server: ${{ matrix.serverTz }}, Client: ${{ matrix.clientTz }}"
steps:
- name: Check out Git repository
uses: actions/checkout@v2
- name: Check out PR
run: |
git fetch --no-tags --prune --progress --no-recurse-submodules --depth=1 \
origin pull/${{ github.event.inputs.pr }}/merge:merged-pr && git checkout merged-pr
if: github.event.inputs.pr != ''
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Cache maven dependencies
uses: actions/cache@v2
with:
path: ~/.m2/repository
key: ${{ runner.os }}-build-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-build-
- name: Test using Maven
run: |
find . -type f -name "pom.xml" -exec sed -i -e 's|.*argLine.*timezone=.*||g' '{}' \;
mvn --batch-mode --update-snapshots \
-DclickhouseTimezone=${{ matrix.serverTz }} \
-Duser.timezone=${{ matrix.clientTz }} verify
8 changes: 4 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ log/
target/

# Generated files
src/main/java/ru/yandex/clickhouse/jdbc/parser/*CharStream.java
src/main/java/ru/yandex/clickhouse/jdbc/parser/ClickHouseSqlParser*.java
src/main/java/ru/yandex/clickhouse/jdbc/parser/Token*.java
src/main/java/ru/yandex/clickhouse/jdbc/parser/ParseException.java
**/parser/*CharStream.java
**/parser/ClickHouseSqlParser*.java
**/parser/Token*.java
**/parser/ParseException.java

# Shell scripts
*.sh
13 changes: 13 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
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
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
ClickHouse JDBC driver
===============
[![clickhouse-jdbc](https://maven-badges.herokuapp.com/maven-central/ru.yandex.clickhouse/clickhouse-jdbc/badge.svg)](https://maven-badges.herokuapp.com/maven-central/ru.yandex.clickhouse/clickhouse-jdbc) ![Build Status(https://github.com/ClickHouse/clickhouse-jdbc/workflows/Build/badge.svg)](https://github.com/ClickHouse/clickhouse-jdbc/workflows/Build/badge.svg)
[![clickhouse-jdbc](https://maven-badges.herokuapp.com/maven-central/ru.yandex.clickhouse/clickhouse-jdbc/badge.svg)](https://maven-badges.herokuapp.com/maven-central/ru.yandex.clickhouse/clickhouse-jdbc) ![Build Status(https://github.com/ClickHouse/clickhouse-jdbc/workflows/Build/badge.svg)](https://github.com/ClickHouse/clickhouse-jdbc/workflows/Build/badge.svg) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=ClickHouse_clickhouse-jdbc&metric=coverage)](https://sonarcloud.io/dashboard?id=ClickHouse_clickhouse-jdbc)

This is a basic and restricted implementation of jdbc driver for ClickHouse.
It has support of a minimal subset of features to be usable.
Expand All @@ -10,7 +10,7 @@ It has support of a minimal subset of features to be usable.
<dependency>
<groupId>ru.yandex.clickhouse</groupId>
<artifactId>clickhouse-jdbc</artifactId>
<version>0.2.6</version>
<version>0.3.0</version>
</dependency>
```

Expand Down
23 changes: 12 additions & 11 deletions clickhouse-benchmark/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,28 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>tech.clickhouse</groupId>
<parent>
<groupId>tech.clickhouse</groupId>
<artifactId>clickhouse-java</artifactId>
<version>${revision}</version>
</parent>

<groupId>${parent.groupId}</groupId>
<artifactId>clickhouse-benchmark</artifactId>
<version>${revision}</version>
<packaging>jar</packaging>

<name>clickhouse-benchmark</name>
<description>Benchmarks for ClickHouse clients</description>

<properties>
<revision>0.3.0-SNAPSHOT</revision>
<clickhouse4j-driver.version>1.4.4</clickhouse4j-driver.version>
<native-driver.version>2.5.3</native-driver.version>
<mariadb-driver.version>2.7.2</mariadb-driver.version>
<mysql-driver.version>8.0.23</mysql-driver.version>
<native-driver.version>2.5.3</native-driver.version>
<native-driver.version>2.5.4</native-driver.version>
<testcontainers.version>1.15.2</testcontainers.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jmh.version>1.27</jmh.version>
<javac.target>1.8</javac.target>
<shade.name>benchmarks</shade.name>
</properties>

Expand Down Expand Up @@ -96,7 +100,6 @@
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>${testcontainers.version}</version>
</dependency>
</dependencies>

Expand All @@ -105,17 +108,15 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<compilerVersion>${javac.target}</compilerVersion>
<source>${javac.target}</source>
<target>${javac.target}</target>
<compilerVersion>${jdk.version}</compilerVersion>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Collections;

import java.util.Random;
import org.openjdk.jmh.annotations.Benchmark;

public class Basic extends JdbcBenchmark {
@Benchmark
public int selectOneRandomNumber(ClientState state) throws Throwable {
final int num = (int) (Math.random() * 1000);
final int num = new Random().nextInt(1000);

try (Statement stmt = executeQuery(state, "select ? as n", num)) {
ResultSet rs = stmt.getResultSet();
Expand All @@ -26,7 +26,7 @@ public int selectOneRandomNumber(ClientState state) throws Throwable {

@Benchmark
public int insertOneRandomNumber(ClientState state) throws Throwable {
final int num = (int) (Math.random() * 1000);
final int num = new Random().nextInt(1000);

return executeInsert(state, "insert into test_insert(i) values(?)",
Collections.enumeration(Collections.singletonList(new Object[] { num })));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package tech.clickhouse.benchmark;

/**
* Constant interface.
*/
public interface Constants {
public static final String CLICKHOUSE_DRIVER = "clickhouse-jdbc";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@
import java.sql.Timestamp;
// import java.util.Collections;
import java.util.Enumeration;

import java.util.Random;
import org.openjdk.jmh.annotations.Benchmark;

public class Insertion extends JdbcBenchmark {
// @Benchmark
// public int insertOneNumber(ClientState state) throws Throwable {
// return executeInsert(state, "insert into test_insert(i) values(?)",
// Collections.enumeration(Collections.singletonList(new Object[] { (int)
// (Math.random() * 1000) })));
// Collections.enumeration(Collections.singletonList(new Object[] { new
// Random().nextInt(1000) })));
// }

@Benchmark
public int insert10kUInt64Rows(ClientState state) throws Throwable {
final int rows = 10000;
final int num = (int) (Math.random() * rows);
final int num = new Random().nextInt(rows);

return executeInsert(state, "insert into test_insert(i) values(?)", new Enumeration<Object[]>() {
int counter = 0;
Expand All @@ -37,7 +37,7 @@ public Object[] nextElement() {
@Benchmark
public int insert10kStringRows(ClientState state) throws Throwable {
final int rows = 10000;
final int num = (int) (Math.random() * rows);
final int num = new Random().nextInt(rows);

return executeInsert(state, "insert into test_insert(s) values(?)", new Enumeration<Object[]>() {
int counter = 0;
Expand All @@ -57,7 +57,7 @@ public Object[] nextElement() {
@Benchmark
public int insert10kTimestampRows(ClientState state) throws Throwable {
final int rows = 10000;
final int num = (int) (Math.random() * rows);
final int num = new Random().nextInt(rows);

return executeInsert(state, "insert into test_insert(t) values(?)", new Enumeration<Object[]>() {
int counter = 0;
Expand All @@ -69,7 +69,7 @@ public boolean hasMoreElements() {

@Override
public Object[] nextElement() {
return new Object[] { new Timestamp(num + (counter++)) };
return new Object[] { new Timestamp((long) num + (counter++)) };
}
});
}
Expand Down
Loading