[FLINK-37834] Flink JDBC support ClickHouse Dialect#171
Conversation
|
@eskabetxe could you please start CI or review PR? |
eskabetxe
left a comment
There was a problem hiding this comment.
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.
| @@ -1,24 +1,24 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <project version="4"> | |||
There was a problem hiding this comment.
the changes in this file should be reverted
| <packaging>jar</packaging> | ||
|
|
||
| <properties> | ||
| <clickhouse.version>0.6.2</clickhouse.version> |
There was a problem hiding this comment.
Why not use the last version available 0.8.6?
|
@eskabetxe
|
Is it okay if I refactor some of the core classes in the tests, like making them protected? |
Its ok to bump some versions and is ok also change some test methods from private to protected if you need to override them.. |
… archunit, 3. Driver version for tests = 0.6.2 (ClickHouse testcontainers support that version) 4. Refactored UPDATE statement
|
Ive refactored tests but cannot use click house driver version 0.7+ since click house testcontainers support 0.6.2. |
|
@eskabetxe |
|
@davidradl maybe you can review? |
|
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. |
|
Hi @gaaraG! Ive passed the tests and got everything working, the only issue is driver version. If jdbc version is a major issue i am ready to update it Overall |
|
That sounds great! Thanks for getting back to us. Looking forward to seeing your updates! |
|
I'll check the driver version and get back to you |
1. refactored some tests and CI fixes
|
Hi @gaaraG! This branch is ready to merge Changelog:
Lineage:
Driver:
|
|
This PR is being marked as stale since it has not had any activity in the last 90 days. If you are having difficulty finding a reviewer, please reach out to the If this PR is no longer valid or desired, please feel free to close it. |
|
Hi, @Biasqo ! |
|
Hi, @och5351 |
|
@Biasqo Thank you for your contribution. |
|
@och5351 |
|
@och5351
I've passed the tests in my forked repo, so its ready to merge after your review |
There was a problem hiding this comment.
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:"); |
There was a problem hiding this comment.
Should we support the jdbc:ch: alias as well?
| return url.startsWith("jdbc:clickhouse:"); | |
| return url.startsWith("jdbc:clickhouse:") || url.startsWith("jdbc:ch:"); |
There was a problem hiding this comment.
That's a good idea
I will add it
…tory and JdbcExtractor, 2. Refactored ClickHouseJdbcExtractor (#4)
|
@och5351 Upd: |
|
|
||
| @Override | ||
| public String timestampFilterExpression() { | ||
| return "timestamp6_col > TO_TIMESTAMP_LTZ('2020-01-01 15:35:00') " |
There was a problem hiding this comment.
Why we change this to a zoned timestamp??
There was a problem hiding this comment.
That's an old typo
I will refresh the tests, there are not enough tests for clickhouse
|
Hi @RocMarshal, @davidradl, @eskabetxe, @Biasqo! Could you please share your thoughts on this plan?
That's the plan I came up with. If you have any better ideas or advice, |
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
|
@eskabetxe @och5351 |
I think we should wait for the PR in OpenLineage, it will keep the codebase clean |
* Adding openlineage for ClickHouse * Minor compatibility tweaks
|
Hi @och5351, @davidradl, @eskabetxe! |
|
Hi @och5351, @davidradl, @eskabetxe! |
CI seems to be unstable once again |
|
By the way, just to confirm — was this Jira ticket If that's correct, would it be okay to ask @RocMarshal |
Yes thats correct, I created FLINK-37834, Arsene is my name))) |
| "BINARY/VARBINARY types are not supported by ClickHouse dialect. " | ||
| + "Use STRING instead."); | ||
| case CHAR: | ||
| case VARCHAR: |
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
How about changing it to private?
| () -> | ||
| new RuntimeException( | ||
| "Unknown array element type")); | ||
| final JdbcDeserializationConverter elementConverter = |
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
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?
|
Hi, @Biasqo ! 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: |
There was a problem hiding this comment.
| 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()
There was a problem hiding this comment.
No, DATE already returns java.sql.Date correctly.
| : value instanceof Timestamp | ||
| ? TimestampData.fromTimestamp((Timestamp) value) | ||
| : value; | ||
| case DECIMAL: |
There was a problem hiding this comment.
| case DECIMAL: | |
| case DECIMAL: | |
| return ((DecimalData) value).toBigDecimal(); |
Refactored code based on requested changes
* Added test for MAP and ARRAY in JdbcSink and JdbcSource
|
Could you @eskabetxe help take a look ? thx |

🔌 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