Skip to content

Commit d861905

Browse files
committed
HHH-18956 Fix native query brace replacement dollar quoted literal support
1 parent 425be29 commit d861905

File tree

2 files changed

+100
-3
lines changed

2 files changed

+100
-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
@@ -92,10 +92,15 @@ protected String substituteBrackets(String sqlQuery) throws QueryException {
9292
}
9393
break;
9494
case '"':
95-
if (!singleQuoted && !escaped) {
96-
doubleQuoted = !doubleQuoted;
95+
if (escaped) {
96+
token.append(ch);
97+
}
98+
else {
99+
if ( !singleQuoted ) {
100+
doubleQuoted = !doubleQuoted;
101+
}
102+
result.append( ch );
97103
}
98-
result.append(ch);
99104
break;
100105
case '{':
101106
if (!singleQuoted && !doubleQuoted) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.spatial.dialect.postgis;
8+
9+
import jakarta.persistence.Entity;
10+
import jakarta.persistence.Id;
11+
import org.geolatte.geom.G2D;
12+
import org.geolatte.geom.Point;
13+
import org.hibernate.annotations.JdbcTypeCode;
14+
import org.hibernate.dialect.PostgreSQLDialect;
15+
import org.hibernate.testing.orm.junit.DomainModel;
16+
import org.hibernate.testing.orm.junit.Jira;
17+
import org.hibernate.testing.orm.junit.RequiresDialect;
18+
import org.hibernate.testing.orm.junit.SessionFactory;
19+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
20+
import org.hibernate.type.SqlTypes;
21+
import org.junit.jupiter.api.Test;
22+
23+
24+
import static org.geolatte.geom.builder.DSL.g;
25+
import static org.geolatte.geom.builder.DSL.point;
26+
import static org.geolatte.geom.crs.CoordinateReferenceSystems.WGS84;
27+
import static org.junit.jupiter.api.Assertions.assertEquals;
28+
29+
@DomainModel(annotatedClasses = PostgisDollarQuoteNativeQueryTest.Location.class )
30+
@SessionFactory
31+
@RequiresDialect(PostgreSQLDialect.class)
32+
@Jira( "https://hibernate.atlassian.net/browse/HHH-18956" )
33+
class PostgisDollarQuoteNativeQueryTest {
34+
35+
private static final Long LOCATION_ID = 123412L;
36+
private static final String DOLLAR_QUOTE = "$asdas$";
37+
38+
@Test
39+
void test(SessionFactoryScope scope) {
40+
scope.inTransaction( s -> {
41+
final Point<G2D> point = point( WGS84, g( 30.5, 50.4 ) );
42+
//noinspection SqlSourceToSinkFlow
43+
s.createNativeMutationQuery(
44+
String.format(
45+
"INSERT INTO location (id, point) " +
46+
"VALUES (%s, %s) " +
47+
"ON CONFLICT DO NOTHING;",
48+
DOLLAR_QUOTE + LOCATION_ID + DOLLAR_QUOTE,
49+
String.format(
50+
"ST_SetSRID(ST_GeomFromGeoJSON(%s%s%s), 4326)",
51+
DOLLAR_QUOTE,
52+
toJsonString( point ),
53+
DOLLAR_QUOTE
54+
)
55+
)
56+
).executeUpdate();
57+
58+
final Location location = s.find( Location.class, LOCATION_ID );
59+
assertEquals( point, location.point );
60+
} );
61+
}
62+
63+
private static String toJsonString(Point<G2D> point) {
64+
return "{\"type\":\"" + point.getGeometryType().getCamelCased() + "\",\"coordinates\":" + point.getPosition() + "}";
65+
}
66+
67+
@Entity(name = "Location")
68+
public static class Location {
69+
70+
@Id
71+
Long id;
72+
73+
@JdbcTypeCode(SqlTypes.GEOMETRY)
74+
Point<G2D> point;
75+
76+
public Location() {
77+
}
78+
79+
public Location(Long id, Point<G2D> point) {
80+
this.id = id;
81+
this.point = point;
82+
}
83+
84+
@Override
85+
public String toString() {
86+
return "Location{" +
87+
"id=" + id +
88+
", point=" + point +
89+
'}';
90+
}
91+
}
92+
}

0 commit comments

Comments
 (0)