allow collation names to be quoted
This commit is contained in:
parent
0e3791cb64
commit
ef16d42c65
|
@ -797,6 +797,7 @@ Here we summarize the ones we've just seen in the second half of this chapter, a
|
|||
| `@Struct` | Map an embeddable to a SQL UDT with the given name
|
||||
| `@TimeZoneStorage` | Specify how the time zone information should be persisted
|
||||
| `@JdbcType` or `@JdbcTypeCode` | Use an implementation of `JdbcType` to map an arbitrary SQL type
|
||||
| `@Collate` | Specify a collation for a column
|
||||
|===
|
||||
|
||||
In addition, there are some configuration properties which have a _global_ affect on how basic types map to SQL column types:
|
||||
|
|
|
@ -876,13 +876,17 @@ Its BNF is given by:
|
|||
[discrete]
|
||||
===== Collations
|
||||
|
||||
Selects a collation to be used for its string-valued argument.
|
||||
The `collate()` function selects a collation to be used for its string-valued argument.
|
||||
Collations are useful for <<relational-comparisons,binary comparisons>> with `<` or `>`, and in the <<order-by,order by clause>>.
|
||||
|
||||
For example, `collate(p.name as ucs_basic)` specifies the SQL standard collation `ucs_basic`.
|
||||
|
||||
IMPORTANT: Collations aren't very portable between databases.
|
||||
|
||||
TIP: Some PostgreSQL collation names must be quoted with backticks, for example, ``collate(name as \`zh_TW.UTF-8`)``.
|
||||
|
||||
TIP: The `@Collate` annotation may be used to specify the collation of a column, which is usually more convenient than using the `collate()` function.
|
||||
|
||||
[[functions-numeric]]
|
||||
==== Numeric functions
|
||||
|
||||
|
|
|
@ -742,7 +742,7 @@ public final class StringHelper {
|
|||
final char first = name.charAt( 0 );
|
||||
final char last = name.charAt( name.length() - 1 );
|
||||
|
||||
return ( ( first == last ) && ( first == '`' || first == '"' ) );
|
||||
return first == last && ( first == '`' || first == '"' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -39,7 +39,6 @@ import org.hibernate.grammars.hql.HqlLexer;
|
|||
import org.hibernate.grammars.hql.HqlParser;
|
||||
import org.hibernate.grammars.hql.HqlParserBaseVisitor;
|
||||
import org.hibernate.internal.util.CharSequenceHelper;
|
||||
import org.hibernate.internal.util.QuotingHelper;
|
||||
import org.hibernate.internal.util.collections.Stack;
|
||||
import org.hibernate.internal.util.collections.StandardStack;
|
||||
import org.hibernate.metamodel.CollectionClassification;
|
||||
|
@ -247,7 +246,10 @@ import static org.hibernate.grammars.hql.HqlParser.INTERSECT;
|
|||
import static org.hibernate.grammars.hql.HqlParser.ListaggFunctionContext;
|
||||
import static org.hibernate.grammars.hql.HqlParser.OnOverflowClauseContext;
|
||||
import static org.hibernate.grammars.hql.HqlParser.PLUS;
|
||||
import static org.hibernate.grammars.hql.HqlParser.QUOTED_IDENTIFIER;
|
||||
import static org.hibernate.grammars.hql.HqlParser.UNION;
|
||||
import static org.hibernate.internal.util.QuotingHelper.unquoteIdentifier;
|
||||
import static org.hibernate.internal.util.QuotingHelper.unquoteJavaStringLiteral;
|
||||
import static org.hibernate.internal.util.QuotingHelper.unquoteStringLiteral;
|
||||
import static org.hibernate.query.hql.internal.SqmTreeCreationHelper.extractJpaCompliantAlias;
|
||||
import static org.hibernate.query.sqm.TemporalUnit.DATE;
|
||||
|
@ -1953,8 +1955,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
public String visitNakedIdentifier(HqlParser.NakedIdentifierContext ctx) {
|
||||
final TerminalNode node = (TerminalNode) ctx.getChild( 0 );
|
||||
final String text = node.getText();
|
||||
return node.getSymbol().getType() == HqlParser.QUOTED_IDENTIFIER
|
||||
? QuotingHelper.unquoteIdentifier( text )
|
||||
return node.getSymbol().getType() == QUOTED_IDENTIFIER
|
||||
? unquoteIdentifier( text )
|
||||
: text;
|
||||
}
|
||||
|
||||
|
@ -3166,9 +3168,21 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
|
||||
@Override
|
||||
public Object visitCollation(HqlParser.CollationContext ctx) {
|
||||
return new SqmCollation(
|
||||
ctx.simplePath().getText(),
|
||||
null,
|
||||
final StringBuilder collation = new StringBuilder();
|
||||
final HqlParser.SimplePathContext simplePathContext = ctx.simplePath();
|
||||
final boolean quoted = simplePathContext.getStart().getType() == QUOTED_IDENTIFIER;
|
||||
if ( quoted ) {
|
||||
collation.append("\"");
|
||||
}
|
||||
collation.append( visitIdentifier( simplePathContext.identifier() ) );
|
||||
for ( HqlParser.SimplePathElementContext pathElementContext
|
||||
: simplePathContext.simplePathElement() ) {
|
||||
collation.append( visitIdentifier( pathElementContext.identifier() ) );
|
||||
}
|
||||
if ( quoted ) {
|
||||
collation.append("\"");
|
||||
}
|
||||
return new SqmCollation( collation.toString(), null,
|
||||
creationContext.getNodeBuilder() );
|
||||
}
|
||||
|
||||
|
@ -3721,7 +3735,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
}
|
||||
|
||||
private SqmLiteral<String> javaStringLiteral(String text) {
|
||||
String unquoted = QuotingHelper.unquoteJavaStringLiteral( text );
|
||||
String unquoted = unquoteJavaStringLiteral( text );
|
||||
return new SqmLiteral<>(
|
||||
unquoted,
|
||||
resolveExpressibleTypeBasic( String.class ),
|
||||
|
|
|
@ -51,6 +51,12 @@ public class CollateTests {
|
|||
|
||||
@Test @RequiresDialect(PostgreSQLDialect.class)
|
||||
public void testCollatePostgreSQL(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.createQuery("from EntityOfBasics e where e.theString is not null order by collate(e.theString as `ucs_basic`)").getResultList();
|
||||
assertThat( session.createQuery("select collate('bar' as `ucs_basic`) < 'foo'").getSingleResult(), is(true) );
|
||||
}
|
||||
);
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.createQuery("from EntityOfBasics e where e.theString is not null order by collate(e.theString as ucs_basic)").getResultList();
|
||||
|
|
Loading…
Reference in New Issue