Skip to content

Commit c2ae869

Browse files
divangandreasdmb2b
andauthored
Fix parsing of Geography coordinates with scientific notation #2819 (#2837)
Very small coordinates that contain three or more zeros after the dot (like 0.000123) have a string representation of 1.23E-4. The readPointWkt did not account for this and set the end pos to the E, thus the BigDecimal tried to parse "1.23E". This resulted in a NumberFormatException. Co-authored-by: Andreas Muttscheller <[email protected]>
1 parent caef383 commit c2ae869

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSpatialDatatype.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1484,7 +1484,11 @@ void readPointWkt() throws SQLServerException {
14841484

14851485
while (currentWktPos < wkt.length()
14861486
&& (Character.isDigit(wkt.charAt(currentWktPos)) || wkt.charAt(currentWktPos) == '.'
1487-
|| wkt.charAt(currentWktPos) == 'E' || wkt.charAt(currentWktPos) == 'e')) {
1487+
|| wkt.charAt(currentWktPos) == 'E' || wkt.charAt(currentWktPos) == 'e'
1488+
|| ((wkt.charAt(currentWktPos) == '-' || wkt.charAt(currentWktPos) == '+')
1489+
&& currentWktPos > startPos
1490+
&& (wkt.charAt(currentWktPos - 1) == 'E'
1491+
|| wkt.charAt(currentWktPos - 1) == 'e')))) {
14881492
currentWktPos++;
14891493
}
14901494

src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SQLServerSpatialDatatypeTest.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2122,6 +2122,43 @@ public void testLargeCases() throws SQLException {
21222122
}
21232123
}
21242124

2125+
/**
2126+
* Tests Geography almost zero coordinates like 0.0001234. The string representation is "1.234E-4", which
2127+
* caused a bug when creating a Geography object.
2128+
*/
2129+
@Test
2130+
public void testGeographySmallCoordinates() throws SQLException {
2131+
// Scientific notation with 'e' (lowercase)
2132+
Geography g1 = Geography.point(1.234e-1, 5.678e-1, 4326);
2133+
assertEquals(1.234e-1, g1.getLatitude(), "Latitude should match for scientific notation with lowercase e");
2134+
assertEquals(5.678e-1, g1.getLongitude(), "Longitude should match for scientific notation with lowercase e");
2135+
2136+
// Scientific notation with 'E' (uppercase) and positive exponent
2137+
Geography g2 = Geography.point(1.234E+1, 5.678E+1, 4326);
2138+
assertEquals(1.234E+1, g2.getLatitude(), "Latitude should match for scientific notation with uppercase E and positive exponent");
2139+
assertEquals(5.678E+1, g2.getLongitude(), "Longitude should match for scientific notation with uppercase E and positive exponent");
2140+
2141+
// Negative scientific notation
2142+
Geography g3 = Geography.point(-1.234e-1, -5.678e-1, 4326);
2143+
assertEquals(-1.234e-1, g3.getLatitude(), "Latitude should match for negative scientific notation");
2144+
assertEquals(-5.678e-1, g3.getLongitude(), "Longitude should match for negative scientific notation");
2145+
2146+
// Mix of minus sign and scientific notation
2147+
Geography g4 = Geography.point(-2.5e-1, 3.7e+1, 4326);
2148+
assertEquals(-2.5e-1, g4.getLatitude(), "Latitude should match for negative value with scientific notation");
2149+
assertEquals(3.7e+1, g4.getLongitude(), "Longitude should match for positive scientific notation");
2150+
2151+
// All four coordinates (X, Y, Z, M) with scientific notation
2152+
// Note: Geography.STGeomFromText supports Z and M coordinates
2153+
// WKT format: POINT(longitude latitude altitude measure)
2154+
String wktWithAllCoords = "POINT(1.234e-1 5.678e-1 1.5e+1 2.3e+1)";
2155+
Geography g5 = Geography.STGeomFromText(wktWithAllCoords, 4326);
2156+
assertEquals(5.678e-1, g5.getLatitude(), "Latitude (Y) should match for WKT with all 4 coordinates");
2157+
assertEquals(1.234e-1, g5.getLongitude(), "Longitude (X) should match for WKT with all 4 coordinates");
2158+
assertEquals(1.5e+1, g5.getZ(), "Z coordinate should match for WKT with all 4 coordinates");
2159+
assertEquals(2.3e+1, g5.getM(), "M coordinate should match for WKT with all 4 coordinates");
2160+
}
2161+
21252162
private void beforeEachSetup() throws SQLException {
21262163
try (Statement stmt = connection.createStatement()) {
21272164
TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(geomTableName), stmt);

0 commit comments

Comments
 (0)