Skip to content

Commit 6832e54

Browse files
committed
HHH-18956 Fix native query brace replacement dollar quoted literal support
1 parent bab80b4 commit 6832e54

File tree

2 files changed

+98
-3
lines changed

2 files changed

+98
-3
lines changed

hibernate-core/src/main/java/org/hibernate/query/sql/internal/SQLQueryParser.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,15 @@ protected String substituteBrackets(String sqlQuery) throws QueryException {
9797
}
9898
break;
9999
case '"':
100-
if (!singleQuoted && !escaped) {
101-
doubleQuoted = !doubleQuoted;
100+
if (escaped) {
101+
token.append(ch);
102+
}
103+
else {
104+
if ( !singleQuoted ) {
105+
doubleQuoted = !doubleQuoted;
106+
}
107+
result.append( ch );
102108
}
103-
result.append(ch);
104109
break;
105110
case '{':
106111
if (!singleQuoted && !doubleQuoted) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.spatial.dialect.postgis;
6+
7+
import jakarta.persistence.Entity;
8+
import jakarta.persistence.Id;
9+
import org.geolatte.geom.G2D;
10+
import org.geolatte.geom.Point;
11+
import org.hibernate.annotations.JdbcTypeCode;
12+
import org.hibernate.dialect.PostgreSQLDialect;
13+
import org.hibernate.testing.orm.junit.DomainModel;
14+
import org.hibernate.testing.orm.junit.Jira;
15+
import org.hibernate.testing.orm.junit.RequiresDialect;
16+
import org.hibernate.testing.orm.junit.SessionFactory;
17+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
18+
import org.hibernate.type.SqlTypes;
19+
import org.junit.jupiter.api.Test;
20+
21+
22+
import static org.geolatte.geom.builder.DSL.g;
23+
import static org.geolatte.geom.builder.DSL.point;
24+
import static org.geolatte.geom.crs.CoordinateReferenceSystems.WGS84;
25+
import static org.junit.jupiter.api.Assertions.assertEquals;
26+
27+
@DomainModel(annotatedClasses = PostgisDollarQuoteNativeQueryTest.Location.class )
28+
@SessionFactory
29+
@RequiresDialect(PostgreSQLDialect.class)
30+
@Jira( "https://hibernate.atlassian.net/browse/HHH-18956" )
31+
class PostgisDollarQuoteNativeQueryTest {
32+
33+
private static final Long LOCATION_ID = 123412L;
34+
private static final String DOLLAR_QUOTE = "$asdas$";
35+
36+
@Test
37+
void test(SessionFactoryScope scope) {
38+
scope.inTransaction( s -> {
39+
final Point<G2D> point = point( WGS84, g( 30.5, 50.4 ) );
40+
//noinspection SqlSourceToSinkFlow
41+
s.createNativeMutationQuery(
42+
String.format(
43+
"INSERT INTO location (id, point) " +
44+
"VALUES (%s, %s) " +
45+
"ON CONFLICT DO NOTHING;",
46+
DOLLAR_QUOTE + LOCATION_ID + DOLLAR_QUOTE,
47+
String.format(
48+
"ST_SetSRID(ST_GeomFromGeoJSON(%s%s%s), 4326)",
49+
DOLLAR_QUOTE,
50+
toJsonString( point ),
51+
DOLLAR_QUOTE
52+
)
53+
)
54+
).executeUpdate();
55+
56+
final Location location = s.find( Location.class, LOCATION_ID );
57+
assertEquals( point, location.point );
58+
} );
59+
}
60+
61+
private static String toJsonString(Point<G2D> point) {
62+
return "{\"type\":\"" + point.getGeometryType().getCamelCased() + "\",\"coordinates\":" + point.getPosition() + "}";
63+
}
64+
65+
@Entity(name = "Location")
66+
public static class Location {
67+
68+
@Id
69+
Long id;
70+
71+
@JdbcTypeCode(SqlTypes.GEOMETRY)
72+
Point<G2D> point;
73+
74+
public Location() {
75+
}
76+
77+
public Location(Long id, Point<G2D> point) {
78+
this.id = id;
79+
this.point = point;
80+
}
81+
82+
@Override
83+
public String toString() {
84+
return "Location{" +
85+
"id=" + id +
86+
", point=" + point +
87+
'}';
88+
}
89+
}
90+
}

0 commit comments

Comments
 (0)