com.hazelcast.org.apache.calcite.sql.SqlCollation Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hazelcast.org.apache.calcite.sql;
import com.hazelcast.org.apache.calcite.config.CalciteSystemProperty;
import com.hazelcast.org.apache.calcite.sql.parser.SqlParserUtil;
import com.hazelcast.org.apache.calcite.util.Glossary;
import com.hazelcast.org.apache.calcite.util.SerializableCharset;
import com.hazelcast.org.apache.calcite.util.Util;
import com.hazelcast.org.checkerframework.checker.initialization.qual.UnderInitialization;
import com.hazelcast.org.checkerframework.checker.nullness.qual.Nullable;
import com.hazelcast.org.checkerframework.dataflow.qual.Pure;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.text.Collator;
import java.util.Locale;
import static com.hazelcast.org.apache.calcite.util.Static.RESOURCE;
/**
* A SqlCollation
is an object representing a Collate
* statement. It is immutable.
*/
public class SqlCollation implements Serializable {
public static final SqlCollation COERCIBLE =
new SqlCollation(Coercibility.COERCIBLE);
public static final SqlCollation IMPLICIT =
new SqlCollation(Coercibility.IMPLICIT);
//~ Enums ------------------------------------------------------------------
/**
* A <character value expression> consisting of a column
* reference has the coercibility characteristic Implicit, with collating
* sequence as defined when the column was created. A <character value
* expression> consisting of a value other than a column (e.g., a host
* variable or a literal) has the coercibility characteristic Coercible,
* with the default collation for its character repertoire. A <character
* value expression> simply containing a <collate clause> has the
* coercibility characteristic Explicit, with the collating sequence
* specified in the <collate clause>.
*
* @see Glossary#SQL99 SQL:1999 Part 2 Section 4.2.3
*/
public enum Coercibility {
/** Strongest coercibility. */
EXPLICIT,
IMPLICIT,
COERCIBLE,
/** Weakest coercibility. */
NONE
}
//~ Instance fields --------------------------------------------------------
protected final String collationName;
protected final SerializableCharset wrappedCharset;
protected final Locale locale;
protected final String strength;
private final Coercibility coercibility;
//~ Constructors -----------------------------------------------------------
/**
* Creates a SqlCollation with the default collation name and the given
* coercibility.
*
* @param coercibility Coercibility
*/
public SqlCollation(Coercibility coercibility) {
this(
CalciteSystemProperty.DEFAULT_COLLATION.value(),
coercibility);
}
/**
* Creates a Collation by its name and its coercibility.
*
* @param collation Collation specification
* @param coercibility Coercibility
*/
public SqlCollation(
String collation,
Coercibility coercibility) {
this.coercibility = coercibility;
SqlParserUtil.ParsedCollation parseValues =
SqlParserUtil.parseCollation(collation);
Charset charset = parseValues.getCharset();
this.wrappedCharset = SerializableCharset.forCharset(charset);
this.locale = parseValues.getLocale();
this.strength = parseValues.getStrength().toLowerCase(Locale.ROOT);
this.collationName = generateCollationName(charset);
}
/**
* Creates a Collation by its coercibility, locale, charset and strength.
*/
public SqlCollation(
Coercibility coercibility,
Locale locale,
Charset charset,
String strength) {
this.coercibility = coercibility;
charset = SqlUtil.getCharset(charset.name());
this.wrappedCharset = SerializableCharset.forCharset(charset);
this.locale = locale;
this.strength = strength.toLowerCase(Locale.ROOT);
this.collationName = generateCollationName(charset);
}
//~ Methods ----------------------------------------------------------------
@Override public boolean equals(@Nullable Object o) {
return this == o
|| o instanceof SqlCollation
&& collationName.equals(((SqlCollation) o).collationName);
}
@Override public int hashCode() {
return collationName.hashCode();
}
protected String generateCollationName(
@UnderInitialization SqlCollation this,
Charset charset) {
return charset.name().toUpperCase(Locale.ROOT) + "$" + String.valueOf(locale) + "$" + strength;
}
/**
* Returns the collating sequence (the collation name) and the coercibility
* for the resulting value of a dyadic operator.
*
* @param col1 first operand for the dyadic operation
* @param col2 second operand for the dyadic operation
* @return the resulting collation sequence. The "no collating sequence"
* result is returned as null.
*
* @see Glossary#SQL99 SQL:1999 Part 2 Section 4.2.3 Table 2
*/
public static @Nullable SqlCollation getCoercibilityDyadicOperator(
SqlCollation col1,
SqlCollation col2) {
return getCoercibilityDyadic(col1, col2);
}
/**
* Returns the collating sequence (the collation name) and the coercibility
* for the resulting value of a dyadic operator.
*
* @param col1 first operand for the dyadic operation
* @param col2 second operand for the dyadic operation
* @return the resulting collation sequence
*
* @throws com.hazelcast.org.apache.calcite.runtime.CalciteException from
* {@link com.hazelcast.org.apache.calcite.runtime.CalciteResource#invalidCompare} or
* {@link com.hazelcast.org.apache.calcite.runtime.CalciteResource#differentCollations}
* if no collating sequence can be deduced
*
* @see Glossary#SQL99 SQL:1999 Part 2 Section 4.2.3 Table 2
*/
public static SqlCollation getCoercibilityDyadicOperatorThrows(
SqlCollation col1,
SqlCollation col2) {
SqlCollation ret = getCoercibilityDyadic(col1, col2);
if (null == ret) {
throw RESOURCE.invalidCompare(
col1.collationName,
"" + col1.coercibility,
col2.collationName,
"" + col2.coercibility).ex();
}
return ret;
}
/**
* Returns the collating sequence (the collation name) to use for the
* resulting value of a comparison.
*
* @param col1 first operand for the dyadic operation
* @param col2 second operand for the dyadic operation
*
* @return the resulting collation sequence. If no collating
* sequence could be deduced throws a
* {@link com.hazelcast.org.apache.calcite.runtime.CalciteResource#invalidCompare}
*
* @see Glossary#SQL99 SQL:1999 Part 2 Section 4.2.3 Table 3
*/
public static String getCoercibilityDyadicComparison(
SqlCollation col1,
SqlCollation col2) {
return getCoercibilityDyadicOperatorThrows(col1, col2).collationName;
}
/**
* Returns the result for {@link #getCoercibilityDyadicComparison} and
* {@link #getCoercibilityDyadicOperator}.
*/
protected static @Nullable SqlCollation getCoercibilityDyadic(
SqlCollation col1,
SqlCollation col2) {
assert null != col1;
assert null != col2;
final Coercibility coercibility1 = col1.getCoercibility();
final Coercibility coercibility2 = col2.getCoercibility();
switch (coercibility1) {
case COERCIBLE:
switch (coercibility2) {
case COERCIBLE:
return col2;
case IMPLICIT:
return col2;
case NONE:
return null;
case EXPLICIT:
return col2;
default:
throw Util.unexpected(coercibility2);
}
case IMPLICIT:
switch (coercibility2) {
case COERCIBLE:
return col1;
case IMPLICIT:
if (col1.collationName.equals(col2.collationName)) {
return col2;
}
return null;
case NONE:
return null;
case EXPLICIT:
return col2;
default:
throw Util.unexpected(coercibility2);
}
case NONE:
switch (coercibility2) {
case COERCIBLE:
case IMPLICIT:
case NONE:
return null;
case EXPLICIT:
return col2;
default:
throw Util.unexpected(coercibility2);
}
case EXPLICIT:
switch (coercibility2) {
case COERCIBLE:
case IMPLICIT:
case NONE:
return col1;
case EXPLICIT:
if (col1.collationName.equals(col2.collationName)) {
return col2;
}
throw RESOURCE.differentCollations(
col1.collationName,
col2.collationName).ex();
default:
throw Util.unexpected(coercibility2);
}
default:
throw Util.unexpected(coercibility1);
}
}
@Override public String toString() {
return "COLLATE " + collationName;
}
public void unparse(
SqlWriter writer) {
writer.keyword("COLLATE");
writer.identifier(collationName, false);
}
public Charset getCharset() {
return wrappedCharset.getCharset();
}
public final String getCollationName() {
return collationName;
}
public final SqlCollation.Coercibility getCoercibility() {
return coercibility;
}
public final Locale getLocale() {
return locale;
}
/**
* Returns the {@link Collator} to compare values having the current
* collation, or {@code null} if no specific {@link Collator} is needed, in
* which case {@link String#compareTo} will be used.
*/
@Pure
public @Nullable Collator getCollator() {
return null;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy