feat(client-v2, jdbc-v2): add MultiPoint data type support - #3050
feat(client-v2, jdbc-v2): add MultiPoint data type support#3050polyglotAI-bot wants to merge 2 commits into
Conversation
MultiPoint is a geo type added in ClickHouse 26.8 and is Array(Point) on the wire, the same representation as Ring and LineString, so it is read and written as double[][]. The server also adds MultiPoint to the Geometry variant. It appends the new variant after the existing six instead of ordering it by type name, so the Geometry helper column now pins that order explicitly rather than relying on the generic Variant name ordering. MultiPoint is deliberately left out of the Geometry write-side mappings: it shares double[][] with Ring and LineString, so a value written to a Geometry column keeps resolving to Ring exactly as before. Implements: #3048
Client V2 CoverageCoverage Report
Class Coverage
|
JDBC V2 CoverageCoverage Report
Class Coverage
|
JDBC V1 CoverageCoverage Report
Class Coverage
|
Client V1 CoverageCoverage Report
Class Coverage
|
The Sonar quality gate reported 75% coverage on new code. The single uncovered spot was the two dimensional branch of DataTypeConverter.isGeoTypeForDimensions, where only one of the three type comparisons was exercised. Add a unit test that converts the same double[][] value through Variant(String, Ring), Variant(String, LineString) and Variant(String, MultiPoint), plus a contrast case with Variant(String, Polygon) that matches no two dimensional geo type and thus keeps the plain array form.
|
CI triage after the first run:
|
|
|
@cursor review |
There was a problem hiding this comment.
Pull request overview
Adds end-to-end support for ClickHouse 26.8+ MultiPoint geo type across the client-v2 and jdbc-v2 stacks, including correct Geometry variant discriminator handling (with MultiPoint appended last to preserve existing discriminator stability).
Changes:
- Introduces
ClickHouseDataType.MultiPointand wires it through column templates, binary read/write, dynamic geo tagging, SQL/parameter string rendering, and JDBC type mapping. - Updates
Geometryvariant construction to keep the server’s discriminator order stable while enabling decoding ofMultiPointstored insideGeometry. - Adds/extends unit and integration tests plus updates
docs/features.mdandCHANGELOG.mdfor the new user-visible behavior.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataTest.java | Extends type-literal expectations and nested-type expectations for server versions with/without MultiPoint. |
| jdbc-v2/src/test/java/com/clickhouse/jdbc/JdbcDataTypeTests.java | Adds integration coverage for MultiPoint JDBC metadata, getObject/getArray, and insert paths. |
| jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/ResultSetMetaDataImpl.java | Treats MultiPoint like other geo types (“read as-is”) for class resolution. |
| jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataImpl.java | Adds MultiPoint literal prefix/suffix info ([ / ]) for type info rows. |
| jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/JdbcUtils.java | Maps MultiPoint to JDBCType.ARRAY and to double[][].class in JDBC type/class mappings. |
| docs/features.md | Documents MultiPoint support and the Geometry discriminator ordering/ambiguity constraints. |
| client-v2/src/test/java/com/clickhouse/client/datatypes/DataTypeTests.java | Adds integration tests for concrete MultiPoint columns and decoding MultiPoint from Geometry. |
| client-v2/src/test/java/com/clickhouse/client/api/internal/DataTypeConverterTest.java | Adds coverage that 2D geo variants (incl. MultiPoint) render as point-sequence literals. |
| client-v2/src/test/java/com/clickhouse/client/api/data_formats/internal/SerializerUtilsTest.java | Adds MultiPoint custom dynamic-tag coverage and a byte-for-byte round-trip equivalence test vs Ring. |
| client-v2/src/main/java/com/clickhouse/client/api/internal/DataTypeConverter.java | Treats MultiPoint as a geo type and as a supported 2D geo literal rendering target. |
| client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/SerializerUtils.java | Serializes MultiPoint via the existing geo ring array path and emits its custom dynamic type tag. |
| client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/BinaryStreamReader.java | Reads MultiPoint using the existing readGeoRing() path. |
| clickhouse-data/src/test/java/com/clickhouse/data/ClickHouseColumnTest.java | Pins Geometry variant nested order (including MultiPoint last) and adds basic MultiPoint parsing/template tests. |
| clickhouse-data/src/main/java/com/clickhouse/data/ClickHouseDataType.java | Adds the MultiPoint enum constant and its Java class mappings (double[][], ClickHouseGeoRingValue). |
| clickhouse-data/src/main/java/com/clickhouse/data/ClickHouseColumn.java | Adds MultiPoint column template and constructs Geometry variant with explicit MultiPoint append. |
| CHANGELOG.md | Adds a user-facing entry describing MultiPoint support and the Geometry discriminator behavior. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 58487f5. Configure here.



Description
Implements #3048.
MultiPointis a geo type added in ClickHouse26.8. It isArray(Point)on the wire — the samerepresentation
RingandLineStringalready use — so the client reads and writes it asdouble[][]. Before this change the type was unknown to the client: reading or writing aMultiPointcolumn failed withUnknown data type: MultiPoint, and aMultiPointvalue inside aGeometrycolumn failed with an out-of-range variant discriminator.No public API is added; the change is a new
ClickHouseDataTypeconstant plus the type's handling onthe existing read, write, SQL-formatting, and JDBC metadata paths.
Design
Concrete
MultiPointcolumns followRing/LineStringat every site:double[][]/ClickHouseGeoRingValuevalue mapping,readGeoRingon the read path,GEO_RING_ARRAYserialization on the write path, the custom
Dynamictype tag, geo SQL rendering, and — injdbc-v2—Types.ARRAYwith type nameMultiPoint,double[][]fromgetObject, ajava.sql.ArrayfromgetArray, and[/]literal quoting ingetTypeInfo.Geometryneeds an explicit variant order. The server's discriminators (measured by reading thefirst
RowBinarybyte ofCAST(x AS Geometry)on26.8.1.1307) are:The first six are type-name-alphabetical, which is why the generic
Variantnested-column sort inClickHouseColumn.readColumnproduced the correct order for free.MultiPointbreaks thatcoincidence — the server appends it at 6 rather than inserting it name-ordered at 2, keeping the
existing discriminators stable.
createGeometryVariantColumn()therefore builds the columnexplicitly with
MultiPointlast instead of relying on the sort. The six pre-existing variants keeptheir positions, so
Geometrydecoding on25.11–26.7servers is unchanged.MultiPointis intentionally not writable throughGeometry. It shares its Java representation(
double[][]) withRingandLineString, so it cannot be selected by value shape. It is left outof both write-side maps (
classToVariantOrdNumMap,geometryTypeDimensionsToVariantOrdNumMap), whichmeans a 2D value written to a
Geometrycolumn keeps resolving toRingexactly as before — nobehavior change for existing users. Writing
MultiPointrequires a concreteMultiPointcolumn.This mirrors the pre-existing
Ring-vs-LineStringandPolygon-vs-MultiLineStringambiguityalready documented in
docs/features.md. For the same reasonMultiPointis read-only in aDynamiccolumn.Entry points covered:
client-v2(generic records, binary reader, POJO binding, insert path, SQLparameter formatting,
Dynamicread) andjdbc-v2(ResultSet,PreparedStatement,ResultSetMetaData,DatabaseMetaData).Changes
clickhouse-dataClickHouseDataType: newMultiPointconstant, and itsdouble[][]/ClickHouseGeoRingValueclass mapping.clickhouse-dataClickHouseColumn:MultiPointcolumn template;createGeometryVariantColumn()appendsMultiPointas the last variant while keeping the existingwrite-side mappings untouched.
client-v2BinaryStreamReader: readMultiPointviareadGeoRing.client-v2SerializerUtils: serializeMultiPointasGEO_RING_ARRAY; emit the custom geo typetag for
MultiPointin aDynamiccolumn.client-v2DataTypeConverter:MultiPointrenders as a geo literal and counts as a 2D geo type.jdbc-v2JdbcUtils/ResultSetMetaDataImpl/DatabaseMetaDataImpl:Types.ARRAYmapping,read-as-is handling, and
getTypeInfoliteral quoting.CHANGELOG.md,docs/features.md.Test
ClickHouseColumnTest.testGeometryVariantOrderpins the full nested order above, and asserts that a2D value and a
ClickHouseGeoRingValuestill resolve toRingon theGeometrywrite path.ClickHouseColumnTest.testMultiPointColumn: type parsing, column template,Array(MultiPoint).SerializerUtilsTest.testMultiPointRoundTrip: byte-for-byte identical output toRing, then readsthe value back.
testDynamicTypeTagUsesCustomEncodingForGeoTypesextended withMultiPoint.DataTypeTests.testMultiPoint(integration): aMultiPointcolumn in the middle of the schema witha trailing
Float64, written both through the POJO insert path and server-side viareadWKTMultiPoint, read back through generic records and the binary reader, asserting the values,the geo string rendering, and the trailing column.
DataTypeTests.testGeometryWithMultiPoint(integration): reads aMultiPointout of aGeometrycolumn (discriminator 6) with a
Ringrow as the contrast case, pinning thatRingdecoding isunchanged.
JdbcDataTypeTests.testGeoMultiPoint(integration): metadata (getColumnType,getColumnTypeName,getColumnClassName),getObject,getArray, insert throughcreateArrayOf("Array(Point)", ...)and throughreadWKTMultiPoint.(,26.7].Verified green on both ClickHouse
26.7.3.19and26.8.1.1307:clickhouse-data(1667 tests),client-v2andjdbc-v2unit tests, andDataTypeTests,RowBinaryFormatWriterTest,JdbcDataTypeTests,DatabaseMetaDataTestintegration suites.Existing tests touched
Three existing tests needed the new enum constant registered; none were weakened:
DataTypeTests— the two exhaustiveClickHouseDataType.values()loops that buildVariant(String, <type>)tables skipMultiPointfor the same reason they already skipLineStringandMultiLineString(identical Java representation, tested separately).DatabaseMetaDataTest.TYPE_LITERAL_EXPECTATIONS— addedMultiPointwith the[/]literals usedby every other array-like geo type; without it the test would assert null literals.
DatabaseMetaDataTest.testFindNestedTypes—MultiPointis absent fromsystem.data_type_familiesbefore26.8, so it is expected to be missing there. The assertion isstill an exact comparison.
Docs / surface
CHANGELOG.mdentry added, with the issue link.docs/features.mdupdated in all four affected places: theclient-v2andjdbc-v2featurebullets (new
MultiPointsupport plus the extendedGeometryvariant), the twocompatibility-sensitive notes on
Geometrywrite inference, and thejdbc-v2custom type-mapbullet that enumerates the geometry types bypassing the map.
VERSIONis already the unreleased0.11.0-rc1this entry belongs to.docs/changes_checklist.md— "Enum constant added"MultiPointisinserted into the geo block (after
MultiLineString) rather than appended at the end of the enum.Ordinals are not persisted or serialized anywhere: the binary type tag is the explicit
binTagfield, which is
-1for every geo type. Appending at the very end would in fact have been theriskier choice —
binTag2Typeis keyed bybinTag, so all-1types collide and the lastconstant wins; inserting in the geo block leaves that entry unchanged. This also follows the
placement precedent set by
LineStringandMultiLineString.switch/map sites inclickhouse-data,client-v2, andjdbc-v2were updated. The v1 stack (clickhouse-jdbcJdbcTypeMapping,clickhouse-dataClickHouseRowBinaryProcessor) enumerates onlyPoint/Ring/Polygon/MultiPolygonand already predatesLineString,MultiLineString, andGeometry; it is out of scope for aclient-v2/jdbc-v2feature.and the three integration tests above.
Pre-PR validation gate
ResultSet/PreparedStatement)MultiPointfollowsRing/LineStringat every siteclient-v2+jdbc-v2, concrete column +Geometry+Dynamicread)RingpathCHANGELOG.md+docs/features.mdupdatedAGENTS.md,docs/changes_checklist.md,docs/features.md