Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Coral-Trino] Support hive function unix_timestamp() when translate Hive to Trino #427

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -34,6 +34,7 @@
import com.linkedin.coral.trino.rel2trino.transformers.ReturnTypeAdjustmentTransformer;
import com.linkedin.coral.trino.rel2trino.transformers.SqlSelectAliasAppenderTransformer;
import com.linkedin.coral.trino.rel2trino.transformers.ToDateOperatorTransformer;
import com.linkedin.coral.trino.rel2trino.transformers.UnixTimestampOperatorTransformer;
import com.linkedin.coral.trino.rel2trino.transformers.UnnestOperatorTransformer;

import static com.linkedin.coral.trino.rel2trino.CoralTrinoConfigKeys.*;
Expand Down Expand Up @@ -106,6 +107,7 @@ protected SqlCall transform(SqlCall sqlCall) {
null, null),
new ToDateOperatorTransformer(configs.getOrDefault(AVOID_TRANSFORM_TO_DATE_UDF, false)),
new CurrentTimestampTransformer(), new FromUnixtimeOperatorTransformer(),
new UnixTimestampOperatorTransformer(),

// LinkedIn specific functions
new CoralRegistryOperatorRenameSqlCallTransformer(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* Copyright 2023 LinkedIn Corporation. All rights reserved.
* Licensed under the BSD-2 Clause license.
* See LICENSE in the project root for license information.
*/
package com.linkedin.coral.trino.rel2trino.transformers;

import java.util.List;

import org.apache.calcite.sql.*;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.sql.type.OperandTypes;
import org.apache.calcite.sql.type.SqlSingleOperandTypeChecker;
import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.calcite.util.NlsString;

import com.linkedin.coral.common.transformers.SqlCallTransformer;

import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_TIMESTAMP;
import static org.apache.calcite.sql.type.ReturnTypes.explicit;
import static org.apache.calcite.sql.type.SqlTypeName.DOUBLE;


/**
* This class implements the transformation from the operation of "unix_timestamp()、unix_timestamp(string date)、unix_timestamp(string date, string pattern)"
*/
public class UnixTimestampOperatorTransformer extends SqlCallTransformer {
private static final String UNIX_TIMESTAMP_FUNCTION_NAME = "unix_timestamp";

@Override
protected boolean condition(SqlCall sqlCall) {
return sqlCall.getOperator().getName().equalsIgnoreCase(UNIX_TIMESTAMP_FUNCTION_NAME);
}

@Override
protected SqlCall transform(SqlCall sqlCall) {
List<SqlNode> operandList = sqlCall.getOperandList();
SqlSingleOperandTypeChecker sqlSingleOperandTypeChecker =
OperandTypes.or(OperandTypes.POSITIVE_INTEGER_LITERAL, OperandTypes.NILADIC);
SqlFunction sqlFunction = CURRENT_TIMESTAMP;
if (operandList != null && operandList.size() > 0) {
int size = operandList.size();
if (size == 2) {
SqlNode sqlNode = operandList.get(1);
if (sqlNode instanceof SqlCharStringLiteral) {
SqlCharStringLiteral sqlCharStringLiteral = (SqlCharStringLiteral) sqlNode;
NlsString value = (NlsString) (sqlCharStringLiteral.getValue());
String sourceFormat = value.getValue();
// hive https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html
// trino https://trino.io/docs/current/functions/datetime.html#date
String formatNew =
sourceFormat.replaceAll("yyyy", "%Y").replaceAll("MM", "%m").replaceAll("LL", "%M").replaceAll("dd", "%d")
.replaceAll("HH", "%H").replaceAll("hh", "%h").replaceAll("mm", "%i").replaceAll("ss", "%s");
SqlCharStringLiteral sqlCharStringLiteralNew =
SqlLiteral.createCharString(formatNew, value.getCharsetName(), sqlCharStringLiteral.getParserPosition());
sqlCall.setOperand(1, sqlCharStringLiteralNew);
sqlFunction = new SqlFunction("date_parse", SqlKind.OTHER_FUNCTION, null, null, sqlSingleOperandTypeChecker,
SqlFunctionCategory.TIMEDATE);
}
} else if (size == 1) {
String formatNew = "%Y-%m-%d %H:%i:%s";
SqlCharStringLiteral sqlCharStringLiteralNew = SqlLiteral.createCharString(formatNew, SqlParserPos.ZERO);
SqlNode[] sqlNodes = { operandList.get(0), sqlCharStringLiteralNew };
sqlCall = new SqlBasicCall(sqlCall.getOperator(), sqlNodes, sqlCall.getParserPosition());
sqlFunction = new SqlFunction("date_parse", SqlKind.OTHER_FUNCTION, null, null, sqlSingleOperandTypeChecker,
SqlFunctionCategory.TIMEDATE);
}
}

SqlDataTypeSpec timestampType =
new SqlDataTypeSpec(new SqlBasicTypeNameSpec(SqlTypeName.TIMESTAMP, 0, SqlParserPos.ZERO), SqlParserPos.ZERO);
SqlBasicCall sqlBasicCall =
new SqlBasicCall(sqlFunction, ((SqlBasicCall) sqlCall).operands, sqlCall.getParserPosition());
SqlCall call = SqlStdOperatorTable.CAST.createCall(SqlParserPos.ZERO, sqlBasicCall, timestampType);
SqlFunction toUnixTimeFun = new SqlFunction("to_unixtime", SqlKind.OTHER_FUNCTION, explicit(DOUBLE), null,
sqlSingleOperandTypeChecker, SqlFunctionCategory.TIMEDATE);
return toUnixTimeFun.createCall(SqlParserPos.ZERO, call);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,9 @@ public Object[][] viewTestCasesProvider() {
{ "test", "date_calculation_view", "SELECT \"date\"(CAST(\"substr\"('2021-08-20', 1, 10) AS TIMESTAMP)), \"date\"(CAST('2021-08-20' AS TIMESTAMP)), \"date\"(CAST('2021-08-20 00:00:00' AS TIMESTAMP)), \"date_add\"('day', 1, \"date\"(CAST('2021-08-20' AS TIMESTAMP))), \"date_add\"('day', 1, \"date\"(CAST('2021-08-20 00:00:00' AS TIMESTAMP))), \"date_add\"('day', 1 * -1, \"date\"(CAST('2021-08-20' AS TIMESTAMP))), \"date_add\"('day', 1 * -1, \"date\"(CAST('2021-08-20 00:00:00' AS TIMESTAMP))), CAST(\"date_diff\"('day', \"date\"(CAST('2021-08-21' AS TIMESTAMP)), \"date\"(CAST('2021-08-20' AS TIMESTAMP))) AS INTEGER), CAST(\"date_diff\"('day', \"date\"(CAST('2021-08-19' AS TIMESTAMP)), \"date\"(CAST('2021-08-20' AS TIMESTAMP))) AS INTEGER), CAST(\"date_diff\"('day', \"date\"(CAST('2021-08-19 23:59:59' AS TIMESTAMP)), \"date\"(CAST('2021-08-20 00:00:00' AS TIMESTAMP))) AS INTEGER)\n"
+ "FROM \"test\".\"tablea\" AS \"tablea\"" },

{ "test", "unix_timestamp_view", "SELECT TO_UNIXTIME(CAST(CURRENT_TIMESTAMP AS TIMESTAMP(0))), TO_UNIXTIME(CAST(DATE_PARSE('2023-06-14 00:00:00', '%Y-%m-%d %H:%i:%s') AS TIMESTAMP(0))), TO_UNIXTIME(CAST(DATE_PARSE('20230614', '%Y%m%d') AS TIMESTAMP(0)))\n"
+ "FROM \"test\".\"tablea\" AS \"tablea\"" },

{ "test", "pmod_view", "SELECT MOD(MOD(- 9, 4) + 4, 4)\n" + "FROM \"test\".\"tablea\" AS \"tablea\"" },

{ "test", "nullscollationd_view", "SELECT *\n" + "FROM \"test\".\"tabler\" AS \"tabler\"\n"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,11 @@ public static void initializeTablesAndViews(HiveConf conf) throws HiveException,
+ "datediff('2021-08-20', '2021-08-19'), " + "datediff('2021-08-20 00:00:00', '2021-08-19 23:59:59')"
+ "FROM test.tableA");

run(driver,
"CREATE VIEW IF NOT EXISTS test.unix_timestamp_view AS \n"
+ "SELECT unix_timestamp(), unix_timestamp('2023-06-14 00:00:00'), unix_timestamp('20230614','yyyyMMdd')"
+ "FROM test.tableA");

run(driver, "CREATE VIEW IF NOT EXISTS test.pmod_view AS \n" + "SELECT pmod(-9, 4) FROM test.tableA");

run(driver, "CREATE TABLE IF NOT EXISTS test.tableR(a int, b string, c int)");
Expand Down