Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
4597300
Workaround
julianhyde Jul 29, 2019
b338f15
Looker instructions
julianhyde Mar 10, 2020
a941d29
Temporary workaround: change SqlInternalOperator's syntax back to FUN…
julianhyde Sep 16, 2020
d8933aa
[CALCITE-5052] Allow Source based on a URL with jar: protocol
Mar 22, 2022
327c3fe
[CALCITE-3312] WIP: TIMESTAMPDIFF cannot be converted to SQL
tjbanghart Mar 28, 2023
09d6b99
[CALCITE-5449] Allow EXTRACT() to accept DAYOFWEEK, DAYOFYEAR, ISOWEE…
tjbanghart Mar 28, 2023
6be9119
Use first datetime operand as DATE_TRUNC return type
tjbanghart Feb 28, 2023
3b36c51
Fix for sorting by literals
wnob Jun 28, 2023
d4ba4aa
Fixup for MetaColumn constructor changes in [CALCITE-5549]
olivrlee Sep 28, 2023
3932e8d
[CALCITE-6055] Customize handling of type name based on type system
wnob Oct 17, 2023
17495d3
[CALCITE-6062] Parse timestamps more permissively
wnob Oct 19, 2023
220a97f
[CALCITE-5508] Allow no-op versions of DATETIME and TIMESTAMP
wnob Nov 14, 2023
dc71cc9
Revert "[CALCITE-6006] RelToSqlConverter loses charset information"
tanclary Feb 16, 2024
68e97cd
[CALCITE-6196] Accept BigQuery PERCENTILE functions without OVER clause
tanclary Jan 9, 2024
b718179
Misc constructor changes from upgrading Avatica to 1.25.0
tanclary Feb 17, 2024
27298b2
[CALCITE-6343] Don't strip MEASUREness from measures when typing AS a…
barrkel Mar 26, 2024
9414b77
[CALCITE-6301] Extend ‘Must-filter’ columns to support a conditional …
olivrlee Oct 23, 2024
2bd7938
Prepare for calcite-1.36.10-looker release
olivrlee Oct 23, 2024
a9c0673
Bump rexml from 3.2.5 to 3.3.9 in /site
dependabot[bot] Oct 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ public static void main(String[] args) throws Exception {
ConnectionFactories.addType("TIMESTAMP", typeFactory ->
typeFactory.createSqlType(
SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE)))
.with(CalciteConnectionProperty.TIME_ZONE, "UTC")
.connect();
case "scott-postgresql":
return CalciteAssert.that()
Expand Down
99 changes: 63 additions & 36 deletions babel/src/test/resources/sql/big-query.iq
Original file line number Diff line number Diff line change
Expand Up @@ -410,14 +410,12 @@ SELECT
# In the following example, EXTRACT returns values corresponding to
# different date parts from a column of dates near the end of the
# year.

!if (false) {
SELECT
d,
EXTRACT(ISOYEAR FROM d) AS isoyear,
EXTRACT(ISOWEEK FROM d) AS isoweek,
EXTRACT(YEAR FROM d) AS year,
EXTRACT(WEEK FROM d) AS week
EXTRACT(ISOWEEK FROM d) as isoweek,
EXTRACT(WEEK(TUESDAY) FROM d) AS week_tues,
EXTRACT(YEAR FROM d) AS year
FROM UNNEST(
ARRAY [DATE '2015-12-23',
DATE '2015-12-24',
Expand All @@ -438,48 +436,62 @@ FROM UNNEST(
DATE '2016-01-08',
DATE '2016-01-09']) AS d
ORDER BY d;
+------------+---------+---------+------+------+
| date | isoyear | isoweek | year | week |
+------------+---------+---------+------+------+
| 2015-12-23 | 2015 | 52 | 2015 | 51 |
| 2015-12-24 | 2015 | 52 | 2015 | 51 |
| 2015-12-25 | 2015 | 52 | 2015 | 51 |
| 2015-12-26 | 2015 | 52 | 2015 | 51 |
| 2015-12-27 | 2015 | 52 | 2015 | 52 |
| 2015-12-28 | 2015 | 53 | 2015 | 52 |
| 2015-12-29 | 2015 | 53 | 2015 | 52 |
| 2015-12-30 | 2015 | 53 | 2015 | 52 |
| 2015-12-31 | 2015 | 53 | 2015 | 52 |
| 2016-01-01 | 2015 | 53 | 2016 | 0 |
| 2016-01-02 | 2015 | 53 | 2016 | 0 |
| 2016-01-03 | 2015 | 53 | 2016 | 1 |
| 2016-01-04 | 2016 | 1 | 2016 | 1 |
| 2016-01-05 | 2016 | 1 | 2016 | 1 |
| 2016-01-06 | 2016 | 1 | 2016 | 1 |
| 2016-01-07 | 2016 | 1 | 2016 | 1 |
| 2016-01-08 | 2016 | 1 | 2016 | 1 |
| 2016-01-09 | 2016 | 1 | 2016 | 1 |
+------------+---------+---------+------+------+
+------------+---------+---------+-----------+------+
| d | isoyear | isoweek | week_tues | year |
+------------+---------+---------+-----------+------+
| 2015-12-23 | 2015 | 52 | 51 | 2015 |
| 2015-12-24 | 2015 | 52 | 51 | 2015 |
| 2015-12-25 | 2015 | 52 | 51 | 2015 |
| 2015-12-26 | 2015 | 52 | 51 | 2015 |
| 2015-12-27 | 2015 | 52 | 51 | 2015 |
| 2015-12-28 | 2015 | 53 | 51 | 2015 |
| 2015-12-29 | 2015 | 53 | 52 | 2015 |
| 2015-12-30 | 2015 | 53 | 52 | 2015 |
| 2015-12-31 | 2015 | 53 | 52 | 2015 |
| 2016-01-01 | 2015 | 53 | 0 | 2016 |
| 2016-01-02 | 2015 | 53 | 0 | 2016 |
| 2016-01-03 | 2015 | 53 | 0 | 2016 |
| 2016-01-04 | 2016 | 1 | 0 | 2016 |
| 2016-01-05 | 2016 | 1 | 1 | 2016 |
| 2016-01-06 | 2016 | 1 | 1 | 2016 |
| 2016-01-07 | 2016 | 1 | 1 | 2016 |
| 2016-01-08 | 2016 | 1 | 1 | 2016 |
| 2016-01-09 | 2016 | 1 | 1 | 2016 |
+------------+---------+---------+-----------+------+
(18 rows)

!ok
!}


# In the following example, date_expression falls on a Sunday. EXTRACT
# calculates the first column using weeks that begin on Sunday, and it
# calculates the second column using weeks that begin on Monday.

!if (false) {
WITH t AS (SELECT DATE('2017-11-05') AS d)
SELECT
d,
EXTRACT(ISOWEEK FROM d) AS isoweek,
EXTRACT(WEEK(SUNDAY) FROM d) AS week_sunday,
EXTRACT(WEEK(MONDAY) FROM d) AS week_monday FROM t;
+------------+-------------+-------------+
| date | week_sunday | week_monday |
+------------+-------------+-------------+
| 2017-11-05 | 45 | 44 |
+------------+-------------+-------------+
+------------+---------+-------------+-------------+
| d | isoweek | week_sunday | week_monday |
+------------+---------+-------------+-------------+
| 2017-11-05 | 44 | 45 | 44 |
+------------+---------+-------------+-------------+
(1 row)

!ok

SELECT EXTRACT(DAYOFWEEK FROM DATE '2008-12-25') as dow,
EXTRACT(DAYOFYEAR FROM DATE '2008-12-25') as doy;
+-----+-----+
| dow | doy |
+-----+-----+
| 5 | 360 |
+-----+-----+
(1 row)

!ok
!}

# In the following example, EXTRACT returns a value corresponding to
# the HOUR time part.
Expand Down Expand Up @@ -2708,6 +2720,18 @@ SELECT TIMESTAMP(DATE "2008-12-25") AS timestamp_date;

!ok

# This tests the no-op TIMESTAMP and DATETIME functions.
select TIMESTAMP(TIMESTAMP "2008-01-01 01:03:05") as ts,
DATETIME(DATETIME "2008-01-01 01:03:05") as dt;
+---------------------+---------------------+
| ts | dt |
+---------------------+---------------------+
| 2008-01-01 01:03:05 | 2008-01-01 01:03:05 |
+---------------------+---------------------+
(1 row)

!ok

# All these timestamps should be equal.
# This tests the BQ timestamp literal string formatter
# (optional 'T', optional leading zeros, optional offset with conversion).
Expand Down Expand Up @@ -3428,7 +3452,8 @@ SELECT
(1 row)

!ok

# Bug.CALCITE_2539_FIXED
!if (false) {
#####################################################################
# DATE_DIFF
#
Expand Down Expand Up @@ -3739,6 +3764,8 @@ SELECT TIMESTAMP_DIFF(TIMESTAMP '2008-12-25', TIMESTAMP '2008-09-25', `quarter`)
(1 row)

!ok

!}
#####################################################################
# DATE_TRUNC
#
Expand Down
16 changes: 15 additions & 1 deletion core/src/main/codegen/templates/Parser.jj
Original file line number Diff line number Diff line change
Expand Up @@ -6127,6 +6127,15 @@ SqlTypeNameSpec DateTimeTypeName() :
typeName = SqlTypeName.DATE;
return new SqlBasicTypeNameSpec(typeName, getPos());
}
|
// DATETIME is the BigQuery-specific name for ISO SQL's TIMESTAMP type.
// In order to support this, the schema UDT map must be properly configued.
// See the BigQuery Quidem tests in the babel component for an example.
<DATETIME> {
s = span();
return new SqlUserDefinedTypeNameSpec(
unquotedIdentifier(), precision, s.end(this));
}
|
LOOKAHEAD(2)
<TIME> { s = span(); }
Expand All @@ -6140,7 +6149,12 @@ SqlTypeNameSpec DateTimeTypeName() :
precision = PrecisionOpt()
typeName = TimeZoneOpt(false)
{
return new SqlBasicTypeNameSpec(typeName, precision, s.end(this));
// Like DATETIME above, TIMESTAMP may have a different meaning for
// certain SQL dialects (namely, BigQuery). Unlike DATETIME, TIMESTAMP
// types names have default standard types that will be used in the
// absence of a UDT mapping.
return new SqlUserDefinedTypeNameSpec(
typeName.getSpaceName(), precision, s.end(this));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3074,6 +3074,10 @@ private static class ExtractImplementor extends AbstractRexCallImplementor {

@Override Expression implementSafe(final RexToLixTranslator translator,
final RexCall call, final List<Expression> argValueList) {
if (argValueList.get(0).getType() == String.class) {
return Expressions.call(BuiltInMethod.CUSTOM_DATE_EXTRACT.method,
translator.getRoot(), argValueList.get(0), argValueList.get(1));
}
final TimeUnitRange timeUnitRange =
(TimeUnitRange) translator.getLiteralValue(argValueList.get(0));
final TimeUnit unit = requireNonNull(timeUnitRange, "timeUnitRange").startUnit;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ MetaColumn createColumn(Table table, String tableCat, String tableSchem,
String tableName, String columnName, int dataType, String typeName,
Integer columnSize, @Nullable Integer decimalDigits, int numPrecRadix,
int nullable, Integer charOctetLength, int ordinalPosition,
String isNullable);
String isNullable, String isAutoincrement, String isGeneratedcolumn);

/** Returns the list of expected column names.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ protected CalciteMetaColumnFactoryImpl() {}
int nullable,
Integer charOctetLength,
int ordinalPosition,
String isNullable) {
String isNullable,
String isAutoincrement,
String isGeneratedcolumn) {
return new MetaColumn(
tableCat,
tableSchem,
Expand All @@ -60,7 +62,9 @@ protected CalciteMetaColumnFactoryImpl() {}
nullable,
charOctetLength,
ordinalPosition,
isNullable);
isNullable,
isAutoincrement,
isGeneratedcolumn);
}

@Override public Class<? extends MetaColumn> getMetaColumnClass() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,11 @@ public Enumerable<MetaColumn> columns(final MetaTable table_) {
: DatabaseMetaData.columnNoNulls,
precision,
field.getIndex() + 1,
field.getType().isNullable() ? "YES" : "NO");
field.getType().isNullable() ? "YES" : "NO",
"NO",
field.getType().getSqlTypeName() == SqlTypeName.MEASURE
? "YES"
: "NO");
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -468,9 +468,8 @@ public Aggregate.AggCallBinding createBinding(
final RelDataTypeFactory typeFactory =
aggregateRelBase.getCluster().getTypeFactory();

if (aggFunction.getKind() == SqlKind.PERCENTILE_DISC
|| aggFunction.getKind() == SqlKind.PERCENTILE_CONT) {
assert collation.getKeys().size() == 1;
if (this.argList.size() == 1 && (aggFunction.getKind() == SqlKind.PERCENTILE_DISC
|| aggFunction.getKind() == SqlKind.PERCENTILE_CONT)) {
return new Aggregate.PercentileDiscAggCallBinding(typeFactory,
aggFunction, SqlTypeUtil.projectTypes(rowType, argList),
SqlTypeUtil.projectTypes(rowType, collation.getKeys()).get(0),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,7 @@ public Object toJson(RexNode node) {
}
map.put("operands", list);
switch (node.getKind()) {
case TIMESTAMP_DIFF:
case MINUS:
case CAST:
case SAFE_CAST:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
*/
package org.apache.calcite.rel.rel2sql;

import org.apache.calcite.config.CalciteSystemProperty;
import org.apache.calcite.linq4j.Ord;
import org.apache.calcite.linq4j.tree.Expressions;
import org.apache.calcite.plan.RelOptUtil;
Expand Down Expand Up @@ -94,7 +93,6 @@
import org.apache.calcite.sql.validate.SqlValidatorUtil;
import org.apache.calcite.util.DateString;
import org.apache.calcite.util.ImmutableBitSet;
import org.apache.calcite.util.NlsString;
import org.apache.calcite.util.Pair;
import org.apache.calcite.util.RangeSets;
import org.apache.calcite.util.Sarg;
Expand Down Expand Up @@ -571,6 +569,8 @@ private boolean requiresAlias(SqlNode node) {
case JOIN:
case EXPLICIT_TABLE:
return false;
case SELECT:
return node instanceof SqlSelect; // TODO workaround asIs hack
default:
return true;
}
Expand Down Expand Up @@ -618,17 +618,9 @@ protected Context(SqlDialect dialect, int fieldCount, boolean ignoreCast) {
*/
public SqlNode orderField(int ordinal) {
final SqlNode node = field(ordinal);
if (node instanceof SqlNumericLiteral
&& dialect.getConformance().isSortByOrdinal()) {
// An integer literal will be wrongly interpreted as a field ordinal.
// Convert it to a character literal, which will have the same effect.
final String strValue = ((SqlNumericLiteral) node).toValue();
return SqlLiteral.createCharString(strValue, node.getParserPosition());
}
if (node instanceof SqlCall
&& dialect.getConformance().isSortByOrdinal()) {
// If the field is expression and sort by ordinal is set in dialect,
// convert it to ordinal.
if (!(node instanceof SqlIdentifier) && dialect.getConformance().shouldSortByOrdinal()) {
// If the dialect allows sorting by ordinal, and the field is anything but a named field
// reference, prefer to sort by ordinal instead.
return SqlLiteral.createExactNumeric(
Integer.toString(ordinal + 1), SqlParserPos.ZERO);
}
Expand Down Expand Up @@ -1431,20 +1423,8 @@ public static SqlNode toSql(RexLiteral literal) {
() -> "literal " + literal
+ " has null SqlTypeFamily, and is SqlTypeName is " + typeName);
switch (family) {
case CHARACTER: {
final NlsString value = literal.getValueAs(NlsString.class);
if (value != null) {
final String defaultCharset = CalciteSystemProperty.DEFAULT_CHARSET.value();
final String charsetName = value.getCharsetName();
if (!defaultCharset.equals(charsetName)) {
// Set the charset only if it is not the same as the default charset
return SqlLiteral.createCharString(
castNonNull(value).getValue(), charsetName, POS);
}
}
// Create a string without specifying a charset
case CHARACTER:
return SqlLiteral.createCharString((String) castNonNull(literal.getValue2()), POS);
}
case NUMERIC:
case EXACT_NUMERIC: {
if (SqlTypeName.APPROX_TYPES.contains(typeName)) {
Expand Down
35 changes: 35 additions & 0 deletions core/src/main/java/org/apache/calcite/rel/type/TimeFrameSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,41 @@ public long diffTimestamp(long timestamp, long timestamp2, TimeFrame frame) {
return timestamp;
}

/** For ISOWEEK and WEEK(WEEKDAY), EXTRACT can be rewritten
* as the composition of DATE_DIFF and DATE_TRUNC. DAYOFWEEK and DAYOFYEAR
* are just translated to DOW and DOY respectively. */
public long extractDate(int date, TimeFrame timeFrame) {
TimeUnitRange timeUnitRange;
int offset = 0;
// Date will be truncated to either ISOYEAR or YEAR depending on time frame.
switch (timeFrame.name()) {
case "DAYOFWEEK":
return DateTimeUtils.unixDateExtract(TimeUnitRange.DOW, date);
case "DAYOFYEAR":
return DateTimeUtils.unixDateExtract(TimeUnitRange.DOY, date);
case "ISOWEEK":
timeUnitRange = TimeUnitRange.ISOYEAR;
offset += 1;
break;
default:
if (TimeFrames.WEEK_FRAME_NAMES.contains(timeFrame.name())) {
timeUnitRange = TimeUnitRange.YEAR;
} else {
throw new IllegalArgumentException("Unsupported frame for EXTRACT: " + timeFrame.name());
}
break;
}
// Date is truncated first to year/isoyear and then to the provided time frame.
int y0 = (int) DateTimeUtils.unixDateFloor(timeUnitRange, date);
int date2 = floorDate(y0, timeFrame);

// For WEEK(WEEKDAY), if year starts on WEEKDAY then offset of +1 is required.
if (date2 == y0 && timeUnitRange != TimeUnitRange.ISOYEAR) {
offset += 1;
}
return (long) diffDate(date2, date, timeFrame) + offset;
}

/** Builds a collection of time frames. */
public interface Builder {
/** Creates a {@code TimeFrameSet}. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ private static BuilderImpl addCore(BuilderImpl b) {

b.addQuotient(TimeUnit.DOY, TimeUnit.DAY, TimeUnit.YEAR);
b.addQuotient(TimeUnit.DOW, TimeUnit.DAY, TimeUnit.WEEK);
b.addQuotient("DAYOFYEAR", TimeUnit.DAY.name(), TimeUnit.YEAR.name());
b.addQuotient("DAYOFWEEK", TimeUnit.DAY.name(), TimeUnit.WEEK.name());
b.addQuotient(TimeUnit.ISODOW.name(), TimeUnit.DAY.name(), "ISOWEEK");

b.addRollup(TimeUnit.DAY, TimeUnit.MONTH);
Expand Down
Loading
Loading