-
Notifications
You must be signed in to change notification settings - Fork 187
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Coral-Trino] Fix substring start index issue (#499)
* use greatest between 1 and substring start index * update test * spotless apply * spotless apply * SUBSTRING operator UT * dedicated substring index transfer + delete old transformer + update tests * match tests * clean up * use ImmutableSet for substring operator names
- Loading branch information
Showing
5 changed files
with
126 additions
and
41 deletions.
There are no files selected for viewing
2 changes: 1 addition & 1 deletion
2
...src/main/java/com/linkedin/coral/common/transformers/JsonTransformSqlCallTransformer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
65 changes: 65 additions & 0 deletions
65
...src/main/java/com/linkedin/coral/trino/rel2trino/transformers/SubstrIndexTransformer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/** | ||
* Copyright 2023-2024 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.Arrays; | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
import org.apache.calcite.sql.SqlCall; | ||
import org.apache.calcite.sql.SqlIdentifier; | ||
import org.apache.calcite.sql.SqlNode; | ||
import org.apache.calcite.sql.SqlNumericLiteral; | ||
import org.apache.calcite.sql.fun.SqlStdOperatorTable; | ||
|
||
import com.linkedin.coral.com.google.common.collect.ImmutableSet; | ||
import com.linkedin.coral.common.calcite.CalciteUtil; | ||
import com.linkedin.coral.common.transformers.SqlCallTransformer; | ||
|
||
import static org.apache.calcite.rel.rel2sql.SqlImplementor.*; | ||
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.*; | ||
|
||
|
||
/** | ||
* This class transforms the substr indexing in the input SqlCall to be compatible with Trino engine. | ||
* Trino uses 1-based indexing for substr, so the lowest possible index is 1. While other engines like Hive | ||
* allow for 0 as a valid index. | ||
* | ||
* This transformer guarantees that starting index will always 1 or greater. | ||
*/ | ||
public class SubstrIndexTransformer extends SqlCallTransformer { | ||
private final static Set<String> SUBSTRING_OPERATORS = ImmutableSet.of("substr", "substring"); | ||
@Override | ||
protected boolean condition(SqlCall sqlCall) { | ||
return SUBSTRING_OPERATORS.contains(sqlCall.getOperator().getName().toLowerCase()); | ||
} | ||
|
||
@Override | ||
protected SqlCall transform(SqlCall sqlCall) { | ||
final List<SqlNode> operandList = sqlCall.getOperandList(); | ||
SqlNode start = operandList.get(1); | ||
if (start instanceof SqlNumericLiteral) { | ||
int startInt = ((SqlNumericLiteral) operandList.get(1)).getValueAs(Integer.class); | ||
|
||
if (startInt == 0) { | ||
SqlNumericLiteral newStart = SqlNumericLiteral.createExactNumeric(String.valueOf(1), POS); | ||
sqlCall.setOperand(1, newStart); | ||
} | ||
|
||
} else if (start instanceof SqlIdentifier) { | ||
// If we don't have a literal start index value, we need to use a case statement with the column identifier to ensure the value is always 1 or greater | ||
// So instead of just "col_name" as the start index, we have "CASE WHEN col_name = 0 THEN 1 ELSE col_name END" | ||
List<SqlNode> whenClauses = Arrays | ||
.asList(SqlStdOperatorTable.EQUALS.createCall(POS, start, SqlNumericLiteral.createExactNumeric("0", POS))); | ||
List<SqlNode> thenClauses = Arrays.asList(SqlNumericLiteral.createExactNumeric("1", POS)); | ||
|
||
sqlCall.setOperand(1, CASE.createCall(null, POS, null, CalciteUtil.createSqlNodeList(whenClauses, POS), | ||
CalciteUtil.createSqlNodeList(thenClauses, POS), start)); | ||
} | ||
|
||
return sqlCall; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.