77
77
* @author Nils Borrmann
78
78
* @author Reda.Housni-Alaoui
79
79
* @author Florian Lüdiger
80
+ * @author Grégoire Druant
80
81
*/
81
82
public abstract class QueryUtils {
82
83
@@ -121,6 +122,7 @@ public abstract class QueryUtils {
121
122
122
123
private static final Pattern PUNCTATION_PATTERN = Pattern .compile (".*((?![\\ ._])[\\ p{Punct}|\\ s])" );
123
124
private static final Pattern FUNCTION_PATTERN ;
125
+ private static final Pattern FIELD_ALIAS_PATTERN ;
124
126
125
127
private static final String UNSAFE_PROPERTY_REFERENCE = "Sort expression '%s' must only contain property references or "
126
128
+ "aliases used in the select clause. If you really want to use something other than that for sorting, please use "
@@ -177,6 +179,14 @@ public abstract class QueryUtils {
177
179
builder .append ("\\ s+[as|AS]+\\ s+(([\\ w\\ .]+))" );
178
180
179
181
FUNCTION_PATTERN = compile (builder .toString ());
182
+
183
+ builder = new StringBuilder ();
184
+ builder .append ("\\ s+" ); // at least one space
185
+ builder .append ("[^\\ s\\ (\\ )]+" ); // No white char no bracket
186
+ builder .append ("\\ s+[as|AS]+\\ s+(([\\ w\\ .]+))" ); // the potential alias
187
+
188
+ FIELD_ALIAS_PATTERN = compile (builder .toString ());
189
+
180
190
}
181
191
182
192
/**
@@ -253,10 +263,11 @@ public static String applySorting(String query, Sort sort, @Nullable String alia
253
263
}
254
264
255
265
Set <String > aliases = getOuterJoinAliases (query );
256
- Set <String > functionAliases = getFunctionAliases (query );
266
+ Set <String > fieldAliases = getFunctionAliases (query );
267
+ fieldAliases .addAll (getFieldAliases (query ));
257
268
258
269
for (Order order : sort ) {
259
- builder .append (getOrderClause (aliases , functionAliases , alias , order )).append (", " );
270
+ builder .append (getOrderClause (aliases , fieldAliases , alias , order )).append (", " );
260
271
}
261
272
262
273
builder .delete (builder .length () - 2 , builder .length ());
@@ -273,14 +284,14 @@ public static String applySorting(String query, Sort sort, @Nullable String alia
273
284
* @param order the order object to build the clause for. Must not be {@literal null}.
274
285
* @return a String containing a order clause. Guaranteed to be not {@literal null}.
275
286
*/
276
- private static String getOrderClause (Set <String > joinAliases , Set <String > functionAlias , @ Nullable String alias ,
287
+ private static String getOrderClause (Set <String > joinAliases , Set <String > fieldAlias , @ Nullable String alias ,
277
288
Order order ) {
278
289
279
290
String property = order .getProperty ();
280
291
281
292
checkSortExpression (order );
282
293
283
- if (functionAlias .contains (property )) {
294
+ if (fieldAlias .contains (property )) {
284
295
return String .format ("%s %s" , property , toJpaDirection (order ));
285
296
}
286
297
@@ -322,6 +333,26 @@ static Set<String> getOuterJoinAliases(String query) {
322
333
return result ;
323
334
}
324
335
336
+ /**
337
+ * Returns the aliases used for fields in the query.
338
+ *
339
+ * @param query a {@literal String} containing a query. Must not be {@literal null}.
340
+ * @return a {@literal Set} containing all found aliases. Guaranteed to be not {@literal null}.
341
+ */
342
+ private static Set <String > getFieldAliases (String query ) {
343
+ Set <String > result = new HashSet <>();
344
+ Matcher matcher = FIELD_ALIAS_PATTERN .matcher (query );
345
+
346
+ while (matcher .find ()) {
347
+ String alias = matcher .group (1 );
348
+
349
+ if (StringUtils .hasText (alias )) {
350
+ result .add (alias );
351
+ }
352
+ }
353
+ return result ;
354
+ }
355
+
325
356
/**
326
357
* Returns the aliases used for aggregate functions like {@code SUM, COUNT, ...}.
327
358
*
0 commit comments