-
Notifications
You must be signed in to change notification settings - Fork 40
Geospatial datatype support #988
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 12 commits
ab7556e
6d2cd46
c1b8ce2
6d02081
e93c3f8
e911082
2a7e20a
5178087
4aad99d
b01f240
61bfff4
f080ff6
28d493f
761bdee
585f9fc
ea2f8fa
c90bc62
50f27cc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| package com.databricks.jdbc.api.impl; | ||
|
|
||
| import com.databricks.jdbc.api.impl.converters.WKTConverter; | ||
| import com.databricks.jdbc.exception.DatabricksValidationException; | ||
| import com.databricks.jdbc.log.JdbcLogger; | ||
| import com.databricks.jdbc.log.JdbcLoggerFactory; | ||
| import java.util.Objects; | ||
|
|
||
| /** | ||
| * Abstract base class for geospatial data types in Databricks JDBC driver. | ||
| * | ||
| * <p>This class provides common functionality for both GEOMETRY and GEOGRAPHY types, including | ||
| * storage of WKT (Well-Known Text) format data and access to both WKT and WKB representations. | ||
| */ | ||
| public abstract class AbstractDatabricksGeospatial implements IDatabricksGeospatial { | ||
|
sreekanth-db marked this conversation as resolved.
|
||
|
|
||
| private static final JdbcLogger LOGGER = | ||
| JdbcLoggerFactory.getLogger(AbstractDatabricksGeospatial.class); | ||
|
|
||
| private final String wkt; | ||
| private final int srid; // Spatial Reference System Identifier | ||
|
|
||
| /** | ||
| * Constructs an AbstractDatabricksGeospatial with the specified WKT and SRID. | ||
| * | ||
| * @param wkt the Well-Known Text representation of the geospatial object | ||
| * @param srid the Spatial Reference System Identifier | ||
| * @throws DatabricksValidationException if the WKT is invalid | ||
| */ | ||
| protected AbstractDatabricksGeospatial(String wkt, int srid) | ||
| throws DatabricksValidationException { | ||
| if (wkt == null || wkt.trim().isEmpty()) { | ||
| LOGGER.error("WKT string cannot be null or empty"); | ||
| throw new DatabricksValidationException("WKT string cannot be null or empty"); | ||
|
sreekanth-db marked this conversation as resolved.
|
||
| } | ||
|
|
||
| this.wkt = wkt.trim(); | ||
| this.srid = srid; | ||
| } | ||
|
|
||
| /** | ||
| * Returns the Well-Known Binary (WKB) representation of the geospatial object. | ||
| * | ||
| * @return the WKB representation as a byte array | ||
| * @throws DatabricksValidationException if WKT to WKB conversion fails | ||
| */ | ||
| @Override | ||
| public byte[] getWKB() throws DatabricksValidationException { | ||
| return WKTConverter.toWKB(wkt); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should consider storing this value as computation can be very expensive
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Storing wkb it in a class variable for reuse. Implemented in #1062 |
||
| } | ||
|
|
||
| /** | ||
| * Returns the Spatial Reference System Identifier (SRID) of the geospatial object. | ||
| * | ||
| * @return the SRID value | ||
| */ | ||
| @Override | ||
| public int getSRID() { | ||
| return srid; | ||
| } | ||
|
|
||
| /** | ||
| * Returns the Well-Known Text (WKT) representation of the geospatial object. | ||
| * | ||
| * @return the WKT string | ||
| */ | ||
| @Override | ||
| public String getWKT() { | ||
| return wkt; | ||
|
sreekanth-db marked this conversation as resolved.
|
||
| } | ||
|
|
||
| /** | ||
| * Returns a string representation of the geospatial object in EWKT format. | ||
| * | ||
| * @return the EWKT string representation | ||
| */ | ||
| @Override | ||
| public String toString() { | ||
| return String.format("SRID=%d;%s", srid, wkt); | ||
|
sreekanth-db marked this conversation as resolved.
|
||
| } | ||
|
|
||
| /** | ||
| * Checks if this geospatial object is equal to another object. | ||
| * | ||
| * @param obj the object to compare | ||
| * @return true if the objects are equal, false otherwise | ||
| */ | ||
| @Override | ||
| public boolean equals(Object obj) { | ||
| if (this == obj) { | ||
| return true; | ||
| } | ||
| if (obj == null || getClass() != obj.getClass()) { | ||
| return false; | ||
| } | ||
|
|
||
| AbstractDatabricksGeospatial that = (AbstractDatabricksGeospatial) obj; | ||
| return srid == that.srid && wkt.equals(that.wkt); | ||
| } | ||
|
|
||
| /** | ||
| * Returns the hash code for this geospatial object. | ||
| * | ||
| * @return the hash code | ||
| */ | ||
| @Override | ||
| public int hashCode() { | ||
| return Objects.hash(wkt, srid); | ||
| } | ||
|
|
||
| /** | ||
| * Returns the data type of the geospatial object. | ||
| * | ||
| * @return the type as a string, either "GEOMETRY" or "GEOGRAPHY" | ||
| */ | ||
| @Override | ||
| public abstract String getType(); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package com.databricks.jdbc.api.impl; | ||
|
|
||
| import static com.databricks.jdbc.common.util.DatabricksTypeUtil.GEOGRAPHY; | ||
|
|
||
| import com.databricks.jdbc.exception.DatabricksValidationException; | ||
|
|
||
| public class DatabricksGeography extends AbstractDatabricksGeospatial { | ||
|
|
||
| /** | ||
| * Constructs a DatabricksGeography with the specified WKT and SRID. | ||
| * | ||
| * @param wkt the Well-Known Text representation of the geography | ||
| * @param srid the Spatial Reference System Identifier | ||
| * @throws DatabricksValidationException if the WKT is invalid | ||
| */ | ||
| public DatabricksGeography(String wkt, int srid) throws DatabricksValidationException { | ||
|
sreekanth-db marked this conversation as resolved.
|
||
| super(wkt, srid); | ||
| } | ||
|
|
||
| @Override | ||
| public String getType() { | ||
| return GEOGRAPHY; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package com.databricks.jdbc.api.impl; | ||
|
|
||
| import static com.databricks.jdbc.common.util.DatabricksTypeUtil.GEOMETRY; | ||
|
|
||
| import com.databricks.jdbc.exception.DatabricksValidationException; | ||
|
|
||
| public class DatabricksGeometry extends AbstractDatabricksGeospatial { | ||
|
sreekanth-db marked this conversation as resolved.
Outdated
|
||
|
|
||
| /** | ||
| * Constructs a DatabricksGeometry with the specified WKT and SRID. | ||
| * | ||
| * @param wkt the Well-Known Text representation of the geometry | ||
| * @param srid the Spatial Reference System Identifier | ||
| * @throws DatabricksValidationException if the WKT is invalid | ||
| */ | ||
| public DatabricksGeometry(String wkt, int srid) throws DatabricksValidationException { | ||
| super(wkt, srid); | ||
| } | ||
|
|
||
| @Override | ||
| public String getType() { | ||
| return GEOMETRY; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,10 +5,7 @@ | |
| import static com.databricks.jdbc.common.MetadataResultConstants.LARGE_DISPLAY_COLUMNS; | ||
| import static com.databricks.jdbc.common.MetadataResultConstants.REMARKS_COLUMN; | ||
| import static com.databricks.jdbc.common.util.DatabricksThriftUtil.*; | ||
| import static com.databricks.jdbc.common.util.DatabricksTypeUtil.TIMESTAMP; | ||
| import static com.databricks.jdbc.common.util.DatabricksTypeUtil.TIMESTAMP_NTZ; | ||
| import static com.databricks.jdbc.common.util.DatabricksTypeUtil.VARIANT; | ||
| import static com.databricks.jdbc.common.util.DatabricksTypeUtil.getBasePrecisionAndScale; | ||
| import static com.databricks.jdbc.common.util.DatabricksTypeUtil.*; | ||
|
|
||
| import com.databricks.jdbc.api.internal.IDatabricksConnectionContext; | ||
| import com.databricks.jdbc.common.AccessType; | ||
|
|
@@ -178,6 +175,7 @@ public DatabricksResultSetMetaData( | |
| columnIndex < resultManifest.getSchema().getColumnsSize(); | ||
| columnIndex++) { | ||
| TColumnDesc columnDesc = resultManifest.getSchema().getColumns().get(columnIndex); | ||
|
|
||
| ColumnInfo columnInfo = getColumnInfoFromTColumnDesc(columnDesc); | ||
| int[] precisionAndScale = getPrecisionAndScale(columnInfo); | ||
| int precision = precisionAndScale[0]; | ||
|
|
@@ -205,6 +203,16 @@ public DatabricksResultSetMetaData( | |
| .columnTypeClassName("java.lang.String") | ||
| .columnType(Types.OTHER) | ||
| .columnTypeText(VARIANT); | ||
| } else if (isGeometryColumn(arrowMetadata, columnIndex)) { | ||
| columnBuilder | ||
| .columnTypeClassName(GEOMETRY_CLASS_NAME) | ||
| .columnType(Types.OTHER) | ||
| .columnTypeText(GEOMETRY); | ||
| } else if (isGeographyColumn(arrowMetadata, columnIndex)) { | ||
| columnBuilder | ||
| .columnTypeClassName(GEOGRAPHY_CLASS_NAME) | ||
| .columnType(Types.OTHER) | ||
| .columnTypeText(GEOGRAPHY); | ||
| } | ||
| columnsBuilder.add(columnBuilder.build()); | ||
| columnNameToIndexMap.putIfAbsent(columnInfo.getName(), ++currIndex); | ||
|
|
@@ -642,6 +650,20 @@ private boolean isVariantColumn(List<String> arrowMetadata, int i) { | |
| && arrowMetadata.get(i).equalsIgnoreCase(VARIANT); | ||
| } | ||
|
|
||
| private boolean isGeometryColumn(List<String> arrowMetadata, int index) { | ||
| return arrowMetadata != null | ||
|
sreekanth-db marked this conversation as resolved.
|
||
| && arrowMetadata.size() > index | ||
| && arrowMetadata.get(index) != null | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. where is this coming from?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed the metadata usage completely (#1062) |
||
| && arrowMetadata.get(index).contains(GEOMETRY); | ||
| } | ||
|
|
||
| private boolean isGeographyColumn(List<String> arrowMetadata, int index) { | ||
| return arrowMetadata != null | ||
| && arrowMetadata.size() > index | ||
| && arrowMetadata.get(index) != null | ||
| && arrowMetadata.get(index).contains(GEOGRAPHY); | ||
| } | ||
|
|
||
| private ImmutableDatabricksColumn.Builder getColumnBuilder() { | ||
| return ImmutableDatabricksColumn.builder() | ||
| .isAutoIncrement(false) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| package com.databricks.jdbc.api.impl; | ||
|
|
||
| import com.databricks.jdbc.exception.DatabricksValidationException; | ||
|
|
||
| /** | ||
| * Interface for geospatial data types in Databricks JDBC driver. | ||
| * | ||
| * <p>This interface provides common functionality for both GEOMETRY and GEOGRAPHY types, allowing | ||
| * access to Well-Known Text (WKT), Well-Known Binary (WKB) representation and Spatial Reference | ||
| * System Identifier (SRID). | ||
| * | ||
| * <p>Following the established patterns of DatabricksStruct, DatabricksArray, and DatabricksMap, | ||
| * this interface enables consistent handling of geospatial data across the JDBC driver. | ||
| */ | ||
| public interface IDatabricksGeospatial { | ||
|
|
||
| /** | ||
| * Returns the Well-Known Binary (WKB) representation of the geospatial object. | ||
| * | ||
| * <p>WKB is a binary format for representing geometry data that is compact and suitable for | ||
| * storage and transmission. This method converts the internal representation to WKB format on | ||
| * demand. | ||
| * | ||
| * @return the WKB representation as a byte array | ||
| * @throws DatabricksValidationException if WKT to WKB conversion fails | ||
| */ | ||
| byte[] getWKB() throws DatabricksValidationException; | ||
|
|
||
| /** | ||
| * Returns the Spatial Reference System Identifier (SRID) of the geospatial object. | ||
| * | ||
| * <p>SRID identifies the coordinate system used by the geometry. Common values include: | ||
| * | ||
| * <ul> | ||
| * <li>4326 - WGS 84 (World Geodetic System 1984) | ||
| * <li>3857 - Web Mercator | ||
| * <li>0 - No SRID specified | ||
| * </ul> | ||
| * | ||
| * @return the SRID value | ||
| */ | ||
| int getSRID(); | ||
|
|
||
| /** | ||
| * Returns the Well-Known Text (WKT) representation of the geospatial object. | ||
| * | ||
| * <p>WKT is a human-readable text format for representing geometry data. This provides a | ||
| * complement to the binary WKB format, allowing easy inspection and debugging of geospatial data. | ||
| * | ||
| * @return the WKT string representation | ||
| */ | ||
| String getWKT(); | ||
|
|
||
| /** | ||
| * Returns the data type of the geospatial object. | ||
| * | ||
| * @return the type as a string, either "GEOMETRY" or "GEOGRAPHY" | ||
| */ | ||
| String getType(); | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.