Skip to content

[FLINK-37834] Flink JDBC support ClickHouse Dialect#171

Open
Biasqo wants to merge 15 commits into
apache:mainfrom
Biasqo:main
Open

[FLINK-37834] Flink JDBC support ClickHouse Dialect#171
Biasqo wants to merge 15 commits into
apache:mainfrom
Biasqo:main

Conversation

@Biasqo

@Biasqo Biasqo commented Jun 2, 2025

Copy link
Copy Markdown

🔌 ClickHouse Dialect for Flink Link JDBC Connector

This project provides a ClickHouse SQL dialect implementation for the Apache Flink JDBC Connector.

🚀 Purpose
Apache Flink’s Link JDBC connector offers a flexible way to integrate with relational databases through dialects. However, native support for ClickHouse’s SQL features (e.g. merge trees, upserts, batch writes) is limited in SQL CLI.

✨ Features
✅ Custom ClickHouseDialect integration
✅ Column quoting and identifier case sensitivity fixes
✅ Insert/update query support tailored for ClickHouse (pkFields removed from update statement)

TODO:
Refactor Tests: Some methods are private (like getStreamFields() that's why I had to recreate some test classes)

Jira Issue:
https://issues.apache.org/jira/projects/FLINK/issues/FLINK-37834

@Biasqo

Biasqo commented Jun 7, 2025

Copy link
Copy Markdown
Author

@eskabetxe could you please start CI or review PR?

@eskabetxe eskabetxe left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution, I can't start CI/CD sorry. @1996fanrui can you start it?

I review the main code and left minor comments.
I dont review the tests as you have a TODO to some refactoring there.

You also need to add this module on flink-connector-jdbc-architecture.

Comment thread .idea/vcs.xml
@@ -1,24 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the changes in this file should be reverted

Comment thread flink-connector-jdbc-clickhouse/pom.xml Outdated
<packaging>jar</packaging>

<properties>
<clickhouse.version>0.6.2</clickhouse.version>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use the last version available 0.8.6?

@Biasqo

Biasqo commented Jun 12, 2025

Copy link
Copy Markdown
Author

@eskabetxe
Thanks for getting back to me

  1. I’m using version 0.6.2 since 0.8+ has some dependency issues with httpcore, and I didn’t want to change the existing httpcore version. If it’s okay to upgrade some of the libraries already included in the distribution, I can go ahead and fix it.
  2. I will revert .vcs
  3. About the tests: I’m not sure if I can override some private methods that are part of abstract test classes (for example, the abstract class TableBase, method getStreamFields). If I’m allowed to make them protected, the number of test classes could be significantly reduced. Clickhouse has its unique create statement - that's why it was a problem

@Biasqo

Biasqo commented Jun 14, 2025

Copy link
Copy Markdown
Author

Thanks for your contribution, I can't start CI/CD sorry. @1996fanrui can you start it?

I review the main code and left minor comments.

I dont review the tests as you have a TODO to some refactoring there.

You also need to add this module on flink-connector-jdbc-architecture.

Is it okay if I refactor some of the core classes in the tests, like making them protected?

@eskabetxe

Copy link
Copy Markdown
Member

@eskabetxe Thanks for getting back to me

  1. I’m using version 0.6.2 since 0.8+ has some dependency issues with httpcore, and I didn’t want to change the existing httpcore version. If it’s okay to upgrade some of the libraries already included in the distribution, I can go ahead and fix it.
  2. I will revert .vcs
  3. About the tests: I’m not sure if I can override some private methods that are part of abstract test classes (for example, the abstract class TableBase, method getStreamFields). If I’m allowed to make them protected, the number of test classes could be significantly reduced. Clickhouse has its unique create statement - that's why it was a problem

Its ok to bump some versions and is ok also change some test methods from private to protected if you need to override them..

Biasqo added 2 commits June 20, 2025 23:05
… archunit, 3. Driver version for tests = 0.6.2 (ClickHouse testcontainers support that version) 4. Refactored UPDATE statement
@Biasqo

Biasqo commented Jun 20, 2025

Copy link
Copy Markdown
Author

Ive refactored tests but cannot use click house driver version 0.7+ since click house testcontainers support 0.6.2.
Clickhouse driver dependency is only needed for tests

@Biasqo Biasqo requested a review from eskabetxe June 20, 2025 20:38
@Biasqo

Biasqo commented Sep 2, 2025

Copy link
Copy Markdown
Author

@eskabetxe
Whenever you get a chance, could you please take a look again?

@Biasqo

Biasqo commented Nov 29, 2025

Copy link
Copy Markdown
Author

@davidradl maybe you can review?

@gaaraG

gaaraG commented Dec 21, 2025

Copy link
Copy Markdown

Hi @Biasqo,

Thank you for working on the ClickHouse dialect support!

I noticed that this PR hasn't been updated for a while. Are you still planning to continue working on this? If you are busy or no longer interested, please let us know so that others in the community might pick it up.

If you intend to drop this, I would be happy to take over and address the review comments.

Looking forward to your reply.

@Biasqo

Biasqo commented Dec 21, 2025

Copy link
Copy Markdown
Author

Hi @gaaraG!

Ive passed the tests and got everything working, the only issue is driver version.
I stuck to the 0.6.2 version which is suitable for most cases

If jdbc version is a major issue i am ready to update it
If there are any major problems with connector, I'll fix it

Overall
I am ready to continue working on it

@gaaraG

gaaraG commented Dec 22, 2025

Copy link
Copy Markdown

That sounds great! Thanks for getting back to us.

Looking forward to seeing your updates!

@Biasqo

Biasqo commented Dec 22, 2025

Copy link
Copy Markdown
Author

I'll check the driver version and get back to you
If everything will be ok we can merge

@Biasqo

Biasqo commented Dec 31, 2025

Copy link
Copy Markdown
Author

Hi @gaaraG!

This branch is ready to merge
If there are any comments on the code please let me know

Changelog:

  • Fixed CI and changed some tests
  • Added timestampFilterExpression method to be compatible with ClickHouse

Lineage:

  • ClickHouse is not included among the built‑in extractors

Driver:

  • Version 0.9.5 is dependent on commons io version 2.16, so I stuck to the working 0.6.2 classic clickhouse jdbc

@github-actions

github-actions Bot commented Apr 1, 2026

Copy link
Copy Markdown

This PR is being marked as stale since it has not had any activity in the last 90 days.
If you would like to keep this PR alive, please leave a comment asking for a review.
If the PR has merge conflicts, update it with the latest from the base branch.

If you are having difficulty finding a reviewer, please reach out to the
community, contact details can be found here: https://flink.apache.org/what-is-flink/community/

If this PR is no longer valid or desired, please feel free to close it.
If no activity occurs in the next 30 days, it will be automatically closed.

@github-actions github-actions Bot added the stale label Apr 1, 2026
@och5351

och5351 commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Hi, @Biasqo !
Are you still looking at this PR?

@Biasqo

Biasqo commented Apr 23, 2026

Copy link
Copy Markdown
Author

Hi, @och5351
The code was ready for its time.
I've waited for so long and got no answer.
I don't know if anyone actually needs a clickhouse connector, so it's up to you.

@och5351

och5351 commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

@Biasqo
I think the ClickHouse connector will be really useful.
I will review and support this PR as soon as I have time (as soon as possible).
Of course, as long as you're okay with it.

Thank you for your contribution.

@Biasqo

Biasqo commented Apr 23, 2026

Copy link
Copy Markdown
Author

@och5351
Alright,
If there are any issues with the pr leave a comment and I'll do my best to fix them.

@github-actions github-actions Bot removed the stale label Apr 23, 2026
@Biasqo

Biasqo commented Apr 24, 2026

Copy link
Copy Markdown
Author

@och5351
I've made some changes you mentioned above

  1. I've updated clickhouse server to 25.8
  2. I've updated clickhouse driver to 0.9.7
  3. I've added lineage to clickhouse (I think its better to add that clickhouse support into openlineage)
  4. I've also changed deprecated class com.clickhouse.jdbc.ClickHouseDriver to com.clickhouse.jdbc.Driver class

I've passed the tests in my forked repo, so its ready to merge after your review

@och5351 och5351 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Biasqo!
I've submitted an OpenLineage PR for this (OpenLineage/OpenLineage#4495), but it will take time to merge.

@RocMarshal @eskabetxe Should we use this custom extractor for now and migrate later, or would you prefer to wait for the OpenLineage release?

public class ClickHouseFactory implements JdbcFactory {
@Override
public boolean acceptsURL(String url) {
return url.startsWith("jdbc:clickhouse:");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we support the jdbc:ch: alias as well?

Suggested change
return url.startsWith("jdbc:clickhouse:");
return url.startsWith("jdbc:clickhouse:") || url.startsWith("jdbc:ch:");

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good idea
I will add it

…tory and JdbcExtractor, 2. Refactored ClickHouseJdbcExtractor (#4)
@Biasqo

Biasqo commented Apr 26, 2026

Copy link
Copy Markdown
Author

@och5351
Thank you for your review
Added ch prefix + suggested your changes in latest commit

Upd:
Should i also add some documentation on clickhouse connector?
I've seen some documentation in docs folder


@Override
public String timestampFilterExpression() {
return "timestamp6_col > TO_TIMESTAMP_LTZ('2020-01-01 15:35:00') "

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we change this to a zoned timestamp??

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's an old typo
I will refresh the tests, there are not enough tests for clickhouse

@davidradl davidradl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry updated by mistake

@och5351

och5351 commented May 8, 2026

Copy link
Copy Markdown
Contributor

Hi @RocMarshal, @davidradl, @eskabetxe, @Biasqo!

Could you please share your thoughts on this plan?

Flink Clickhouse JDBC Connector needs OpenLineage support.

  1. Wait for the PR in OpenLineage to be merged and update the version in this repo. (flink: add ClickHouse JDBC support OpenLineage/OpenLineage#4495)
  2. First merge the custom lineage implementation, then update the version and apply it.

That's the plan I came up with. If you have any better ideas or advice,
I'd really appreciate it if you could share them!

1. Refactored ClickHouseDynamicTableSourceITCase (adding more columns to source table)
2. Added MAP type support to JdbcTypeUtil (since MAP type is actively used in ClickHouse DB)
3. Refactored ClickHouseDialectConverter: added MAP and ARRAY support to internal converter and did some minor fixes
@Biasqo

Biasqo commented May 8, 2026

Copy link
Copy Markdown
Author

 @eskabetxe @och5351
I refactored  ClickHouse tests and they look cleaner now.
Also fixed minor bugs in ClickHouse converter.

@Biasqo

Biasqo commented May 8, 2026

Copy link
Copy Markdown
Author

Hi @RocMarshal, @davidradl, @eskabetxe, @Biasqo!

Could you please share your thoughts on this plan?

Flink Clickhouse JDBC Connector needs OpenLineage support.

  1. Wait for the PR in OpenLineage to be merged and update the version in this repo. (flink: add ClickHouse JDBC support OpenLineage/OpenLineage#4495)
  2. First merge the custom lineage implementation, then update the version and apply it.

That's the plan I came up with. If you have any better ideas or advice, I'd really appreciate it if you could share them!

I think we should wait for the PR in OpenLineage, it will keep the codebase clean

@Biasqo

Biasqo commented May 25, 2026

Copy link
Copy Markdown
Author

Hi @och5351, @davidradl, @eskabetxe!
Ive added OpenLineage native support for ClickHouse DB and made some minor fixes.
Looking forward to seeing your comments!

@Biasqo

Biasqo commented Jun 18, 2026

Copy link
Copy Markdown
Author

Hi @och5351, @davidradl, @eskabetxe!
Could you please rerun checks?
The error seems to be in core module, I've passed all checks in my forked main branch

@Biasqo

Biasqo commented Jun 19, 2026

Copy link
Copy Markdown
Author

Hi @och5351, @davidradl, @eskabetxe!

Could you please rerun checks?

The error seems to be in core module, I've passed all checks in my forked main branch

CI seems to be unstable once again
Now the error is in Db2 module

@och5351

och5351 commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

By the way, just to confirm — was this Jira ticket
(FLINK-37834) created by @Biasqo, and is the account name Arsene?

https://issues.apache.org/jira/browse/FLINK-37834

If that's correct, would it be okay to ask @RocMarshal
to assign it?

@RocMarshal RocMarshal self-assigned this Jun 20, 2026
@Biasqo

Biasqo commented Jun 20, 2026

Copy link
Copy Markdown
Author

By the way, just to confirm — was this Jira ticket (FLINK-37834) created by @Biasqo, and is the account name Arsene?

https://issues.apache.org/jira/browse/FLINK-37834

If that's correct, would it be okay to ask @RocMarshal to assign it?

Yes thats correct, I created FLINK-37834, Arsene is my name)))
Thx for checking

"BINARY/VARBINARY types are not supported by ClickHouse dialect. "
+ "Use STRING instead.");
case CHAR:
case VARCHAR:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already handled identically in AbstractDialectConverter. Consider removing this case and delegating via a default fallthrough to avoid duplication.

switch (type.getTypeRoot()) {
case NULL:
return null;
case BOOLEAN:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already handled identically in AbstractDialectConverter. Consider removing this case and delegating via a default fallthrough to avoid duplication.

@Override
public JdbcDeserializationConverter createInternalConverter(LogicalType type) {
switch (type.getTypeRoot()) {
case NULL:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already handled identically in AbstractDialectConverter. Consider removing this case and delegating via a default fallthrough to avoid duplication.

: val instanceof Timestamp
? TimestampData.fromTimestamp((Timestamp) val)
: val;
case DECIMAL:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already handled identically in AbstractDialectConverter. Consider removing this case and delegating via a default fallthrough to avoid duplication.

}

// adding support to MAP and ARRAY types
public static Object toExternalSerializer(Object value, LogicalType type) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about changing it to private?

() ->
new RuntimeException(
"Unknown array element type"));
final JdbcDeserializationConverter elementConverter =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using createNullableInternalConverter instead of createInternalConverter for the element converter. PostgresDialectConverter follows this pattern, which delegates null handling to the framework and removes the need for the manual null check on the next line.

}
return new GenericArrayData(converted);
};
case MAP:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be cleaner to extract the ARRAY and MAP logic into separate private methods (e.g., createArrayConverter, createMapConverter), following the pattern in PostgresDialectConverter.createPostgresArrayConverter.

This keeps the switch cases concise and separates traversal logic from null handling.
What do you think about handling it this way?

@och5351

och5351 commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Hi, @Biasqo !
I apologize for the delay.

PTAL !

case TIME_WITHOUT_TIME_ZONE:
return Time.valueOf(LocalTime.ofNanoOfDay((int) value * 1_000_000L));
case TIMESTAMP_WITH_TIME_ZONE:
case TIMESTAMP_WITHOUT_TIME_ZONE:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
case TIMESTAMP_WITHOUT_TIME_ZONE:
case TIMESTAMP_WITH_TIME_ZONE:
case TIMESTAMP_WITHOUT_TIME_ZONE:
return ((TimestampData) value).toTimestamp();

The value here is TimestampData (Flink's internal type returned by ElementGetter), not LocalDateTime or Timestamp. This falls through to : value, returning TimestampData directly to the ClickHouse JDBC driver, which will cause a failure. Following the same approach as AbstractDialectConverter.createExternalConverter, which calls val.getTimestamp(...).toTimestamp()

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I do same for DATE type?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, DATE already returns java.sql.Date correctly.

: value instanceof Timestamp
? TimestampData.fromTimestamp((Timestamp) value)
: value;
case DECIMAL:

@och5351 och5351 Jun 20, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
case DECIMAL:
case DECIMAL:
return ((DecimalData) value).toBigDecimal();

Biasqo added 2 commits June 20, 2026 20:11
Refactored code based on requested changes
@Biasqo

Biasqo commented Jun 21, 2026

Copy link
Copy Markdown
Author

Hi @och5351!
Ive refactored converter based on your changes and added MAP and ARRAY into tests (latest commit a1d4bfc)
Let me know if there are any remaining comments.

Biasqo and others added 2 commits June 21, 2026 20:05
* Added test for MAP and ARRAY in JdbcSink and JdbcSource
@Biasqo

Biasqo commented Jun 22, 2026

Copy link
Copy Markdown
Author

CI checks are failing, but they're all passing on my branch.
ci_checks

@RocMarshal

Copy link
Copy Markdown
Contributor

Thanks @Biasqo @och5351

Could you @eskabetxe help take a look ? thx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants