Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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.dialect;
import com.hazelcast.org.apache.calcite.avatica.util.Casing;
import com.hazelcast.org.apache.calcite.avatica.util.TimeUnit;
import com.hazelcast.org.apache.calcite.config.NullCollation;
import com.hazelcast.org.apache.calcite.rel.type.RelDataType;
import com.hazelcast.org.apache.calcite.rel.type.RelDataTypeSystem;
import com.hazelcast.org.apache.calcite.rex.RexCall;
import com.hazelcast.org.apache.calcite.rex.RexUtil;
import com.hazelcast.org.apache.calcite.sql.SqlAlienSystemTypeNameSpec;
import com.hazelcast.org.apache.calcite.sql.SqlCall;
import com.hazelcast.org.apache.calcite.sql.SqlDataTypeSpec;
import com.hazelcast.org.apache.calcite.sql.SqlDialect;
import com.hazelcast.org.apache.calcite.sql.SqlIntervalLiteral;
import com.hazelcast.org.apache.calcite.sql.SqlIntervalQualifier;
import com.hazelcast.org.apache.calcite.sql.SqlKind;
import com.hazelcast.org.apache.calcite.sql.SqlLiteral;
import com.hazelcast.org.apache.calcite.sql.SqlNode;
import com.hazelcast.org.apache.calcite.sql.SqlOperator;
import com.hazelcast.org.apache.calcite.sql.SqlSetOperator;
import com.hazelcast.org.apache.calcite.sql.SqlSyntax;
import com.hazelcast.org.apache.calcite.sql.SqlWriter;
import com.hazelcast.org.apache.calcite.sql.fun.SqlTrimFunction;
import com.hazelcast.org.apache.calcite.sql.parser.SqlParserPos;
import com.hazelcast.org.apache.calcite.sql.type.BasicSqlType;
import com.hazelcast.org.apache.calcite.sql.type.SqlTypeName;
import com.hazelcast.org.apache.calcite.sql.type.SqlTypeUtil;
import com.hazelcast.com.google.common.collect.ImmutableList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;
/**
* A SqlDialect implementation for Google BigQuery's "Standard SQL"
* dialect.
*/
public class BigQuerySqlDialect extends SqlDialect {
public static final SqlDialect.Context DEFAULT_CONTEXT = SqlDialect.EMPTY_CONTEXT
.withDatabaseProduct(SqlDialect.DatabaseProduct.BIG_QUERY)
.withLiteralQuoteString("'")
.withLiteralEscapedQuoteString("\\'")
.withIdentifierQuoteString("`")
.withNullCollation(NullCollation.LOW)
.withUnquotedCasing(Casing.UNCHANGED)
.withQuotedCasing(Casing.UNCHANGED)
.withCaseSensitive(false);
public static final SqlDialect DEFAULT = new BigQuerySqlDialect(DEFAULT_CONTEXT);
private static final List RESERVED_KEYWORDS =
ImmutableList.copyOf(
Arrays.asList("ALL", "AND", "ANY", "ARRAY", "AS", "ASC",
"ASSERT_ROWS_MODIFIED", "AT", "BETWEEN", "BY", "CASE", "CAST",
"COLLATE", "CONTAINS", "CREATE", "CROSS", "CUBE", "CURRENT",
"DEFAULT", "DEFINE", "DESC", "DISTINCT", "ELSE", "END", "ENUM",
"ESCAPE", "EXCEPT", "EXCLUDE", "EXISTS", "EXTRACT", "FALSE",
"FETCH", "FOLLOWING", "FOR", "FROM", "FULL", "GROUP", "GROUPING",
"GROUPS", "HASH", "HAVING", "IF", "IGNORE", "IN", "INNER",
"INTERSECT", "INTERVAL", "INTO", "IS", "JOIN", "LATERAL", "LEFT",
"LIKE", "LIMIT", "LOOKUP", "MERGE", "NATURAL", "NEW", "NO",
"NOT", "NULL", "NULLS", "OF", "ON", "OR", "ORDER", "OUTER",
"OVER", "PARTITION", "PRECEDING", "PROTO", "RANGE", "RECURSIVE",
"RESPECT", "RIGHT", "ROLLUP", "ROWS", "SELECT", "SET", "SOME",
"STRUCT", "TABLESAMPLE", "THEN", "TO", "TREAT", "TRUE",
"UNBOUNDED", "UNION", "UNNEST", "USING", "WHEN", "WHERE",
"WINDOW", "WITH", "WITHIN"));
/** An unquoted BigQuery identifier must start with a letter and be followed
* by zero or more letters, digits or _. */
private static final Pattern IDENTIFIER_REGEX =
Pattern.compile("[A-Za-z][A-Za-z0-9_]*");
/** Creates a BigQuerySqlDialect. */
public BigQuerySqlDialect(SqlDialect.Context context) {
super(context);
}
@Override protected boolean identifierNeedsQuote(String val) {
return !IDENTIFIER_REGEX.matcher(val).matches()
|| RESERVED_KEYWORDS.contains(val.toUpperCase(Locale.ROOT));
}
@Override public SqlNode emulateNullDirection(SqlNode node,
boolean nullsFirst, boolean desc) {
return emulateNullDirectionWithIsNull(node, nullsFirst, desc);
}
@Override public boolean supportsImplicitTypeCoercion(RexCall call) {
return super.supportsImplicitTypeCoercion(call)
&& RexUtil.isLiteral(call.getOperands().get(0), false)
&& !SqlTypeUtil.isNumeric(call.type);
}
@Override public boolean supportsNestedAggregations() {
return false;
}
@Override public void unparseOffsetFetch(SqlWriter writer, SqlNode offset,
SqlNode fetch) {
unparseFetchUsingLimit(writer, offset, fetch);
}
@Override public void unparseCall(final SqlWriter writer, final SqlCall call, final int leftPrec,
final int rightPrec) {
switch (call.getKind()) {
case POSITION:
final SqlWriter.Frame frame = writer.startFunCall("STRPOS");
writer.sep(",");
call.operand(1).unparse(writer, leftPrec, rightPrec);
writer.sep(",");
call.operand(0).unparse(writer, leftPrec, rightPrec);
if (3 == call.operandCount()) {
throw new RuntimeException("3rd operand Not Supported for Function STRPOS in Big Query");
}
writer.endFunCall(frame);
break;
case UNION:
if (((SqlSetOperator) call.getOperator()).isAll()) {
super.unparseCall(writer, call, leftPrec, rightPrec);
} else {
SqlSyntax.BINARY.unparse(writer, UNION_DISTINCT, call, leftPrec,
rightPrec);
}
break;
case EXCEPT:
if (((SqlSetOperator) call.getOperator()).isAll()) {
throw new RuntimeException("BigQuery does not support EXCEPT ALL");
}
SqlSyntax.BINARY.unparse(writer, EXCEPT_DISTINCT, call, leftPrec,
rightPrec);
break;
case INTERSECT:
if (((SqlSetOperator) call.getOperator()).isAll()) {
throw new RuntimeException("BigQuery does not support INTERSECT ALL");
}
SqlSyntax.BINARY.unparse(writer, INTERSECT_DISTINCT, call, leftPrec,
rightPrec);
break;
case TRIM:
unparseTrim(writer, call, leftPrec, rightPrec);
break;
default:
super.unparseCall(writer, call, leftPrec, rightPrec);
}
}
/** BigQuery interval syntax: INTERVAL int64 time_unit. */
@Override public void unparseSqlIntervalLiteral(
SqlWriter writer, SqlIntervalLiteral literal, int leftPrec, int rightPrec) {
SqlIntervalLiteral.IntervalValue interval =
(SqlIntervalLiteral.IntervalValue) literal.getValue();
writer.keyword("INTERVAL");
if (interval.getSign() == -1) {
writer.print("-");
}
Long intervalValueInLong;
try {
intervalValueInLong = Long.parseLong(literal.getValue().toString());
} catch (NumberFormatException e) {
throw new RuntimeException("Only INT64 is supported as the interval value for BigQuery.");
}
writer.literal(intervalValueInLong.toString());
unparseSqlIntervalQualifier(writer, interval.getIntervalQualifier(),
RelDataTypeSystem.DEFAULT);
}
@Override public void unparseSqlIntervalQualifier(
SqlWriter writer, SqlIntervalQualifier qualifier, RelDataTypeSystem typeSystem) {
final String start = validate(qualifier.timeUnitRange.startUnit).name();
if (qualifier.timeUnitRange.endUnit == null) {
writer.keyword(start);
} else {
throw new RuntimeException("Range time unit is not supported for BigQuery.");
}
}
/**
* For usage of TRIM, LTRIM and RTRIM in BQ see
*
* BQ Trim Function.
*/
private void unparseTrim(SqlWriter writer, SqlCall call, int leftPrec,
int rightPrec) {
final String operatorName;
SqlLiteral trimFlag = call.operand(0);
SqlLiteral valueToTrim = call.operand(1);
switch (trimFlag.getValueAs(SqlTrimFunction.Flag.class)) {
case LEADING:
operatorName = "LTRIM";
break;
case TRAILING:
operatorName = "RTRIM";
break;
default:
operatorName = call.getOperator().getName();
break;
}
final SqlWriter.Frame trimFrame = writer.startFunCall(operatorName);
call.operand(2).unparse(writer, leftPrec, rightPrec);
// If the trimmed character is a non-space character, add it to the target SQL.
// eg: TRIM(BOTH 'A' from 'ABCD'
// Output Query: TRIM('ABC', 'A')
if (!valueToTrim.toValue().matches("\\s+")) {
writer.literal(",");
call.operand(1).unparse(writer, leftPrec, rightPrec);
}
writer.endFunCall(trimFrame);
}
private TimeUnit validate(TimeUnit timeUnit) {
switch (timeUnit) {
case MICROSECOND:
case MILLISECOND:
case SECOND:
case MINUTE:
case HOUR:
case DAY:
case WEEK:
case MONTH:
case QUARTER:
case YEAR:
case ISOYEAR:
return timeUnit;
default:
throw new RuntimeException("Time unit " + timeUnit + " is not supported for BigQuery.");
}
}
/** BigQuery data type reference:
*
* BigQuery Standard SQL Data Types
*/
@Override public SqlNode getCastSpec(final RelDataType type) {
if (type instanceof BasicSqlType) {
final SqlTypeName typeName = type.getSqlTypeName();
switch (typeName) {
// BigQuery only supports INT64 for integer types.
case TINYINT:
case SMALLINT:
case INTEGER:
case BIGINT:
return createSqlDataTypeSpecByName("INT64", typeName);
// BigQuery only supports FLOAT64(aka. Double) for floating point types.
case FLOAT:
case DOUBLE:
return createSqlDataTypeSpecByName("FLOAT64", typeName);
case DECIMAL:
return createSqlDataTypeSpecByName("NUMERIC", typeName);
case BOOLEAN:
return createSqlDataTypeSpecByName("BOOL", typeName);
case CHAR:
case VARCHAR:
return createSqlDataTypeSpecByName("STRING", typeName);
case BINARY:
case VARBINARY:
return createSqlDataTypeSpecByName("BYTES", typeName);
case DATE:
return createSqlDataTypeSpecByName("DATE", typeName);
case TIME:
return createSqlDataTypeSpecByName("TIME", typeName);
case TIMESTAMP:
return createSqlDataTypeSpecByName("TIMESTAMP", typeName);
}
}
return super.getCastSpec(type);
}
private SqlDataTypeSpec createSqlDataTypeSpecByName(String typeAlias, SqlTypeName typeName) {
SqlAlienSystemTypeNameSpec typeNameSpec = new SqlAlienSystemTypeNameSpec(
typeAlias, typeName, SqlParserPos.ZERO);
return new SqlDataTypeSpec(typeNameSpec, SqlParserPos.ZERO);
}
/**
* List of BigQuery Specific Operators needed to form Syntactically Correct SQL.
*/
private static final SqlOperator UNION_DISTINCT = new SqlSetOperator(
"UNION DISTINCT", SqlKind.UNION, 14, false);
private static final SqlSetOperator EXCEPT_DISTINCT =
new SqlSetOperator("EXCEPT DISTINCT", SqlKind.EXCEPT, 14, false);
private static final SqlSetOperator INTERSECT_DISTINCT =
new SqlSetOperator("INTERSECT DISTINCT", SqlKind.INTERSECT, 18, false);
}