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
|
| `@Struct` | Map an embeddable to a SQL UDT with the given name
|
||||||
| `@TimeZoneStorage` | Specify how the time zone information should be persisted
|
| `@TimeZoneStorage` | Specify how the time zone information should be persisted
|
||||||
| `@JdbcType` or `@JdbcTypeCode` | Use an implementation of `JdbcType` to map an arbitrary SQL type
|
| `@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:
|
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]
|
[discrete]
|
||||||
===== Collations
|
===== 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>>.
|
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`.
|
For example, `collate(p.name as ucs_basic)` specifies the SQL standard collation `ucs_basic`.
|
||||||
|
|
||||||
IMPORTANT: Collations aren't very portable between databases.
|
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]]
|
[[functions-numeric]]
|
||||||
==== Numeric functions
|
==== Numeric functions
|
||||||
|
|
||||||
|
|
|
@ -742,7 +742,7 @@ public final class StringHelper {
|
||||||
final char first = name.charAt( 0 );
|
final char first = name.charAt( 0 );
|
||||||
final char last = name.charAt( name.length() - 1 );
|
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.HqlParser;
|
||||||
import org.hibernate.grammars.hql.HqlParserBaseVisitor;
|
import org.hibernate.grammars.hql.HqlParserBaseVisitor;
|
||||||
import org.hibernate.internal.util.CharSequenceHelper;
|
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.Stack;
|
||||||
import org.hibernate.internal.util.collections.StandardStack;
|
import org.hibernate.internal.util.collections.StandardStack;
|
||||||
import org.hibernate.metamodel.CollectionClassification;
|
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.ListaggFunctionContext;
|
||||||
import static org.hibernate.grammars.hql.HqlParser.OnOverflowClauseContext;
|
import static org.hibernate.grammars.hql.HqlParser.OnOverflowClauseContext;
|
||||||
import static org.hibernate.grammars.hql.HqlParser.PLUS;
|
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.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.internal.util.QuotingHelper.unquoteStringLiteral;
|
||||||
import static org.hibernate.query.hql.internal.SqmTreeCreationHelper.extractJpaCompliantAlias;
|
import static org.hibernate.query.hql.internal.SqmTreeCreationHelper.extractJpaCompliantAlias;
|
||||||
import static org.hibernate.query.sqm.TemporalUnit.DATE;
|
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) {
|
public String visitNakedIdentifier(HqlParser.NakedIdentifierContext ctx) {
|
||||||
final TerminalNode node = (TerminalNode) ctx.getChild( 0 );
|
final TerminalNode node = (TerminalNode) ctx.getChild( 0 );
|
||||||
final String text = node.getText();
|
final String text = node.getText();
|
||||||
return node.getSymbol().getType() == HqlParser.QUOTED_IDENTIFIER
|
return node.getSymbol().getType() == QUOTED_IDENTIFIER
|
||||||
? QuotingHelper.unquoteIdentifier( text )
|
? unquoteIdentifier( text )
|
||||||
: text;
|
: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3166,9 +3168,21 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitCollation(HqlParser.CollationContext ctx) {
|
public Object visitCollation(HqlParser.CollationContext ctx) {
|
||||||
return new SqmCollation(
|
final StringBuilder collation = new StringBuilder();
|
||||||
ctx.simplePath().getText(),
|
final HqlParser.SimplePathContext simplePathContext = ctx.simplePath();
|
||||||
null,
|
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() );
|
creationContext.getNodeBuilder() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3721,7 +3735,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
||||||
}
|
}
|
||||||
|
|
||||||
private SqmLiteral<String> javaStringLiteral(String text) {
|
private SqmLiteral<String> javaStringLiteral(String text) {
|
||||||
String unquoted = QuotingHelper.unquoteJavaStringLiteral( text );
|
String unquoted = unquoteJavaStringLiteral( text );
|
||||||
return new SqmLiteral<>(
|
return new SqmLiteral<>(
|
||||||
unquoted,
|
unquoted,
|
||||||
resolveExpressibleTypeBasic( String.class ),
|
resolveExpressibleTypeBasic( String.class ),
|
||||||
|
|
|
@ -51,6 +51,12 @@ public class CollateTests {
|
||||||
|
|
||||||
@Test @RequiresDialect(PostgreSQLDialect.class)
|
@Test @RequiresDialect(PostgreSQLDialect.class)
|
||||||
public void testCollatePostgreSQL(SessionFactoryScope scope) {
|
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(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
session.createQuery("from EntityOfBasics e where e.theString is not null order by collate(e.theString as ucs_basic)").getResultList();
|
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