Skip to content

Instantly share code, notes, and snippets.

@junwen12221
Created February 4, 2022 06:54
Show Gist options
  • Save junwen12221/73557f335b4ef5ffdd1b504539f25b36 to your computer and use it in GitHub Desktop.
Save junwen12221/73557f335b4ef5ffdd1b504539f25b36 to your computer and use it in GitHub Desktop.
package io.sqlengine;
import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.*;
import com.alibaba.druid.sql.ast.expr.*;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectStatement;
import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitorAdapter;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;
import com.alibaba.druid.util.FnvHash;
import com.google.common.collect.ImmutableSet;
import org.apache.calcite.jdbc.CalciteSchema;
import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.plan.RelOptUtil;
import org.apache.calcite.rel.RelCollations;
import org.apache.calcite.rel.RelFieldCollation;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.CorrelationId;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.logical.LogicalTableScan;
import org.apache.calcite.rex.RexCorrelVariable;
import org.apache.calcite.rex.RexNode;
import org.apache.calcite.rex.RexSlot;
import org.apache.calcite.rex.RexSubQuery;
import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.apache.calcite.tools.FrameworkConfig;
import org.apache.calcite.tools.Frameworks;
import org.apache.calcite.tools.RelBuilder;
import org.apache.calcite.util.Holder;
import org.apache.calcite.util.NameMap;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NULL;
public class CalciteMySqlNodeVisitor extends PGASTVisitorAdapter implements SQLASTVisitor {
final CalciteSchema rootSchema;
public CalciteMySqlNodeVisitor( CalciteSchema rootSchema) {
this.rootSchema = rootSchema;
}
public RelBuilder getRelBuilder (){
FrameworkConfig config = Frameworks.newConfigBuilder().defaultSchema(rootSchema.plus()).build();
RelBuilder relBuilder = RelBuilder.create(config);
return relBuilder;
}
public static RelNode convert(String defaultSchema, String sql) {
CalciteSchema rootSchema = CalciteSchema.createRootSchema(true);
SQLStatement statement = SQLUtils.parseSingleStatement(sql, DbType.postgresql);
CalciteMySqlNodeVisitor calciteMySqlNodeVisitor = new CalciteMySqlNodeVisitor(rootSchema);
RelScope rootScope = RelScope.createNewRootScope(defaultSchema);
if (statement instanceof PGSelectStatement) {
PGSelectStatement pgSelectStatement = (PGSelectStatement) statement;
SQLSelect select = pgSelectStatement.getSelect();
SQLSelectQuery query = select.getQuery();
RelNode relNode;
if (query instanceof PGSelectQueryBlock) {
return calciteMySqlNodeVisitor.convertSelectQueryBlock(rootScope, (PGSelectQueryBlock) query);
}
}
return null;
}
public static void main(String[] args) {
// String defaultSchema = null;
// FrameworkConfig config = Frameworks.newConfigBuilder().build();
// RelBuilder relBuilder = RelBuilder.create(config);
// CalciteMySqlNodeVisitor calciteMySqlNodeVisitor = new CalciteMySqlNodeVisitor(relBuilder, new NameMap<>());
// SQLStatement sqlStatement = SQLUtils.parseSingleStatement("select 1", DbType.postgresql);
// if (sqlStatement instanceof PGSelectStatement) {
// PGSelectStatement pgSelectStatement = (PGSelectStatement) sqlStatement;
// SQLSelect select = pgSelectStatement.getSelect();
// // convertSQLSelect(defaultSchema, relBuilder, select);
// }
// sqlStatement.accept(calciteMySqlNodeVisitor);
//
// System.out.println();
}
private RelNode convertSQLSelect(RelScope relScope, SQLSelect select) {
SQLSelectQuery query = select.getQuery();
RelNode relNode;
if (query instanceof PGSelectQueryBlock) {
return convertSelectQueryBlock(relScope, (PGSelectQueryBlock) query);
}
return null;
}
private static class AggregationStatVisitor extends SQLASTVisitorAdapter {
private boolean aggregation = false;
List<SQLAggregateExpr> exprs = new ArrayList<>();
public AggregationStatVisitor(RelBuilder relBuilder, int size) {
}
public boolean visit(SQLAggregateExpr x) {
aggregation = true;
exprs.add(x);
return false;
}
}
;
private RelNode convertSelectQueryBlock(RelScope parentRelScope , PGSelectQueryBlock query) {
RelBuilder relBuilder = getRelBuilder();
RelNode relNode;
PGSelectQueryBlock pgSelectQueryBlock = query;
SQLTableSource from = pgSelectQueryBlock.getFrom();
relNode = convertTableSource(parentRelScope, from);
//////////////////////////////////////////////////////////////////////////////////////////
String alias = from.computeAlias();
RelScope curScope = parentRelScope.createNewScope(alias, relNode, getRelBuilder());
////////////////////////////////////////////////////////////////////////////////////////
SQLExpr where = pgSelectQueryBlock.getWhere();
if (where != null) {
SubQueryContext subQueryContext = convertSubQuery(curScope, relBuilder, where, relNode);
Set<CorrelationId> variablesSet = subQueryContext.getVariablesSet();
RexNode predicates = subQueryContext.getExpr();
if (curScope.getRefColumns().isEmpty()) {
relNode = relBuilder.push(relNode).filter(variablesSet, predicates).build();
} else {
relNode = relBuilder.push(relNode).filter(ImmutableSet.of(curScope.getRexCorrelVariable().id), predicates).build();
}
}
List<SQLSelectItem> selectList = pgSelectQueryBlock.getSelectList();
AggregationStatVisitor aggregationStatVisitor = new AggregationStatVisitor(relBuilder, selectList.size());
pgSelectQueryBlock.accept(aggregationStatVisitor);
final boolean hasSelectAggregation = aggregationStatVisitor.aggregation;
if (hasSelectAggregation || pgSelectQueryBlock.getGroupBy() != null) {
relBuilder.push(relNode);
SQLSelectGroupByClause groupByClause = pgSelectQueryBlock.getGroupBy();
RelBuilder.GroupKey groupKey;
SQLExpr having = null;
if (groupByClause != null) {
List<SQLExpr> items = groupByClause.getItems();
ArrayList<RexNode> keys = new ArrayList<>();
for (SQLExpr item : items) {
keys.add(convertExpr(parentRelScope, item));
}
groupKey = relBuilder.groupKey(keys);
having = groupByClause.getHaving();
} else {
groupKey = relBuilder.groupKey();
}
List<RelBuilder.AggCall> calls = new ArrayList<>();
for (SQLAggregateExpr expr : aggregationStatVisitor.exprs) {
RelBuilder.AggCall call = convertAggOrExpr(curScope, relBuilder, expr);
calls.add(call);
}
RelBuilder aggregate = relBuilder.aggregate(groupKey, calls);
if (having != null) {
aggregate.filter(convertExpr(curScope, having));
}
relNode = aggregate.build();
}
relBuilder.push(relNode);
if (selectList.size() == 1 && selectList.get(0).getExpr() instanceof SQLAllColumnExpr) {
relNode = relBuilder.build();
} else {
// Set<String> curTableAlias = getCurTableAlias(relNode);
// HashSet<String> curTableSet = getCurTableSet();
List<SQLSelectItem> orginalProject = new ArrayList<>(selectList);
// Map<Boolean, List<SQLSelectItem>> collect = selectList.stream().collect(Collectors.partitioningBy(i -> !curScope.isCol(i.getExpr())));
List<SQLSelectItem> pure =orginalProject;
List<SQLSelectItem> col = new ArrayList<>();
List<RexNode> pureProjects = getRexNodes(curScope, pure, relBuilder, relNode);
List<RexNode> corProjects = getRexNodes(curScope, col, relBuilder, relNode);
if (!corProjects.isEmpty()) {
relBuilder.push(relNode);
Holder<RexCorrelVariable> v = Holder.empty();
relBuilder.variable(v);
RelNode corProject = relBuilder.values(new String[]{"X"}, "x").project(corProjects).build();
relBuilder.push(corProject);
relNode = relBuilder.join(JoinRelType.LEFT, relBuilder.literal(true), ImmutableSet.of(v.get().id)).build();
relBuilder.push(relNode);
List<RexNode> columns = new ArrayList<>();
for (SQLSelectItem sqlSelectItem : orginalProject) {
RexNode field = relBuilder.field(sqlSelectItem.computeAlias());
columns.add(field);
}
return relBuilder.project(columns).build();
}
relNode = relBuilder.project(pureProjects).build();
}
SQLOrderBy orderBy = pgSelectQueryBlock.getOrderBy();
if (orderBy != null) {
relBuilder.push(relNode);
List<SQLSelectOrderByItem> items = orderBy.getItems();
RelFieldCollation[] fieldCollations = new RelFieldCollation[items.size()];
for (int i = 0; i < items.size(); i++) {
SQLSelectOrderByItem sqlSelectOrderByItem = items.get(i);
SQLExpr expr = sqlSelectOrderByItem.getExpr();
SQLSelectOrderByItem.NullsOrderType nullsOrderType = sqlSelectOrderByItem.getNullsOrderType();
SQLOrderingSpecification type = sqlSelectOrderByItem.getType();
RexSlot rexNode = (RexSlot) convertExpr(curScope, expr);
int fieldIndex = rexNode.getIndex();
RelFieldCollation.Direction direction = RelFieldCollation.Direction.ASCENDING;
RelFieldCollation.NullDirection nullDirection = RelFieldCollation.NullDirection.UNSPECIFIED;
if (type != null) {
switch (type) {
case ASC:
direction = RelFieldCollation.Direction.ASCENDING;
break;
case DESC:
direction = RelFieldCollation.Direction.DESCENDING;
break;
default:
throw new IllegalStateException("Unexpected value: " + type);
}
}
if (nullsOrderType != null) {
switch (nullsOrderType) {
case NullsFirst:
nullDirection = RelFieldCollation.NullDirection.FIRST;
break;
case NullsLast:
nullDirection = RelFieldCollation.NullDirection.LAST;
break;
}
}
fieldCollations[i] = new RelFieldCollation(fieldIndex, direction, nullDirection);
}
relNode = relBuilder.sort(RelCollations.of(fieldCollations)).build();
}
SQLLimit limit = pgSelectQueryBlock.getLimit();
if (limit != null) {
relBuilder.push(relNode);
int rowCount = Optional.ofNullable(limit.getRowCount()).map(sqlExpr -> ((SQLIntegerExpr) sqlExpr).getNumber().intValue()).orElse(Integer.MAX_VALUE);
int offset = Optional.ofNullable(limit.getOffset()).map(sqlExpr -> ((SQLIntegerExpr) sqlExpr).getNumber().intValue()).orElse(0);
relNode = relBuilder.limit(offset, rowCount).build();
}
return relNode;
}
private List<RexNode> getRexNodes(RelScope relScope, List<SQLSelectItem> col, RelBuilder relBuilder, RelNode relNode) {
List<RexNode> corProjects = new ArrayList<>();
for (SQLSelectItem sqlSelectItem : col) {
SQLExpr expr = sqlSelectItem.getExpr();
String s = sqlSelectItem.computeAlias();
SubQueryContext subQueryContext = convertSubQuery(relScope, relBuilder, expr, relNode);
RexNode rexNode = subQueryContext.getExpr();
if (s != null) {
rexNode = relBuilder.alias(rexNode, s);
}
corProjects.add(rexNode);
}
return corProjects;
}
private SubQueryContext convertSubQuery(RelScope relScope, RelBuilder relBuilder, SQLExpr sqlExpr, RelNode relNode) {
// Set<String> outerTableSet = getCurTableSet();
// Set<String> curTableAlias = getCurTableAlias(relNode);
// boolean col = Util.isCol(outerTableSet, sqlExpr);
// Set<CorrelationId> variablesSet;
// if (col && !this.refMap.containsKey(curTableAlias.iterator().next(), false)) {
// relBuilder.push(relNode);
// Holder<RexCorrelVariable> v = Holder.of(null);
// relBuilder.variable(v);
// for (String tableAlias : curTableAlias) {
// this.refMap.put(tableAlias, new ColInfo(v.get(), relNode));
// }
// variablesSet = ImmutableSet.of(v.get().id);
// } else {
// variablesSet = ImmutableSet.of();
// }
RexNode rexNode = convertExpr(relScope, sqlExpr);
return new SubQueryContext(ImmutableSet.of(), rexNode);
}
//
// private Set<String> getCurTableAlias(RelNode relNode) {
// Set<String> set = new HashSet<>();
// for (Map.Entry<String, RelNode> entry : aliasMap.map().entrySet()) {
// if (entry.getValue() == relNode) {
// set.add(entry.getKey());
// }
// }
// return set;
// }
//
// private HashSet<String> getCurTableSet() {
// return new HashSet<>(aliasMap.map().keySet());
// }
static class BottomProjects {
List<SQLExpr> projects = new ArrayList<>();
}
private RelBuilder.AggCall convertAggOrExpr(RelScope relScope, RelBuilder relBuilder,
SQLAggregateExpr expr
) {
SQLAggregateExpr sqlAggregateExpr = (SQLAggregateExpr) expr;
SQLAggregateOption option = sqlAggregateExpr.getOption();
SQLKeep keep = sqlAggregateExpr.getKeep();
SQLExpr filter = sqlAggregateExpr.getFilter();
SQLOver over = sqlAggregateExpr.getOver();
SQLName overRef = sqlAggregateExpr.getOverRef();
SQLOrderBy orderBy = sqlAggregateExpr.getOrderBy();
boolean withinGroup = sqlAggregateExpr.isWithinGroup();
Boolean ignoreNulls = sqlAggregateExpr.getIgnoreNulls();
String methodName = SQLUtils.normalize(sqlAggregateExpr.getMethodName()).toUpperCase();
String alias = expr.toString();
RelBuilder.AggCall call;
switch (methodName) {
case "COUNT": {
List<SQLExpr> arguments = sqlAggregateExpr.getArguments();
if (arguments.size() == 1 && arguments.get(0) instanceof SQLAllColumnExpr) {
call = relBuilder.countStar(null);
} else {
List<RexNode> rexNodes = new ArrayList<>();
for (SQLExpr argument : arguments) {
rexNodes.add(convertExpr(relScope, argument));
}
call = relBuilder.count(rexNodes);
}
break;
}
default: {
throw new UnsupportedOperationException();
}
}
return call.as(alias);
}
private static boolean isSqlAllExpr(SQLExpr x) {
return x.getClass() == SQLAllExpr.class;
}
private static boolean isAnyOrSomeExpr(SQLExpr x) {
return x.getClass() == SQLAnyExpr.class || x.getClass() == SQLSomeExpr.class;
}
private RexNode convertExpr(RelScope relScope, SQLExpr expr) {
RelBuilder relBuilder = getRelBuilder();
relBuilder.push(relScope.getCurRelNode());
if (expr instanceof SQLIntegerExpr) {
return relBuilder.literal(((SQLIntegerExpr) expr).getValue());
}
if (expr instanceof SQLCharExpr) {
return relBuilder.literal(((SQLCharExpr) expr).getValue());
}
if (expr instanceof SQLAggregateExpr) {
return relBuilder.field(expr.toString());
}
if (expr instanceof SQLBinaryOpExpr) {
SQLBinaryOpExpr sqlBinaryOpExpr = (SQLBinaryOpExpr) expr;
SQLExpr leftExpr = sqlBinaryOpExpr.getLeft();
SQLExpr rightExpr = sqlBinaryOpExpr.getRight();
RexNode leftRex = convertExpr(relScope, leftExpr);
RexNode rightRex = convertExpr(relScope, rightExpr);
SqlOperator someOrAllOperator;
SqlOperator operator = null;
switch (sqlBinaryOpExpr.getOperator()) {
case Equality:
if (isSqlAllExpr(rightExpr)) {
someOrAllOperator = SqlStdOperatorTable.ALL_EQ;
} else if (isAnyOrSomeExpr(rightExpr)) {
someOrAllOperator = SqlStdOperatorTable.SOME_EQ;
} else {
operator = SqlStdOperatorTable.EQUALS;
}
break;
case GreaterThan:
if (isSqlAllExpr(rightExpr)) {
someOrAllOperator = SqlStdOperatorTable.ALL_GT;
} else if (isAnyOrSomeExpr(rightExpr)) {
someOrAllOperator = SqlStdOperatorTable.SOME_GT;
} else {
operator = SqlStdOperatorTable.GREATER_THAN;
}
break;
case GreaterThanOrEqual:
if (isSqlAllExpr(rightExpr)) {
someOrAllOperator = SqlStdOperatorTable.ALL_GE;
} else if (isAnyOrSomeExpr(rightExpr)) {
someOrAllOperator = SqlStdOperatorTable.SOME_GE;
} else {
operator = SqlStdOperatorTable.GREATER_THAN_OR_EQUAL;
}
break;
case LessThan:
if (isSqlAllExpr(rightExpr)) {
someOrAllOperator = SqlStdOperatorTable.ALL_LT;
} else if (isAnyOrSomeExpr(rightExpr)) {
someOrAllOperator = SqlStdOperatorTable.SOME_LT;
} else {
operator = SqlStdOperatorTable.LESS_THAN;
}
break;
case LessThanOrEqual:
if (isSqlAllExpr(rightExpr)) {
someOrAllOperator = SqlStdOperatorTable.ALL_LE;
} else if (isAnyOrSomeExpr(rightExpr)) {
someOrAllOperator = SqlStdOperatorTable.SOME_LE;
} else {
operator = SqlStdOperatorTable.LESS_THAN_OR_EQUAL;
}
break;
case NotEqual:
case LessThanOrGreater:
if (isSqlAllExpr(rightExpr)) {
someOrAllOperator = SqlStdOperatorTable.ALL_NE;
} else if (isAnyOrSomeExpr(rightExpr)) {
someOrAllOperator = SqlStdOperatorTable.SOME_NE;
} else {
operator = SqlStdOperatorTable.NOT_EQUALS;
}
break;
case Add:
operator = SqlStdOperatorTable.PLUS;
break;
case Subtract:
operator = SqlStdOperatorTable.MINUS;
break;
case Union:
operator = SqlStdOperatorTable.UNION;
break;
case COLLATE: {
throw new UnsupportedOperationException();
}
case BitwiseXor:
operator = SqlStdOperatorTable.BIT_XOR;
break;
case BitwiseXorEQ:
break;
case Multiply:
operator = SqlStdOperatorTable.MULTIPLY;
break;
case Divide:
operator = SqlStdOperatorTable.DIVIDE;
break;
case DIV:
operator = SqlStdOperatorTable.DIVIDE_INTEGER;
break;
case Modulus:
operator = SqlStdOperatorTable.MOD;
break;
case Like:
operator = SqlStdOperatorTable.LIKE;
break;
case NotLike:
operator = SqlStdOperatorTable.NOT_LIKE;
break;
case BooleanAnd:
operator = SqlStdOperatorTable.AND;
break;
case BooleanOr:
operator = SqlStdOperatorTable.OR;
break;
case Concat:
operator = SqlStdOperatorTable.CONCAT;
break;
case Is: {
if (rightExpr instanceof SQLNullExpr) {
operator = IS_NULL;
} else if (rightExpr instanceof SQLIdentifierExpr) {
long hashCode64 = ((SQLIdentifierExpr) rightExpr).nameHashCode64();
if (hashCode64 == FnvHash.Constants.JSON
|| hashCode64 == JSON_VALUE) {
operator = SqlStdOperatorTable.IS_JSON_VALUE;
} else if (hashCode64 == JSON_OBJECT) {
operator = SqlStdOperatorTable.IS_JSON_OBJECT;
} else if (hashCode64 == JSON_ARRAY) {
operator = SqlStdOperatorTable.IS_JSON_ARRAY;
} else if (hashCode64 == JSON_SCALAR) {
operator = SqlStdOperatorTable.IS_JSON_SCALAR;
} else if (hashCode64 == FnvHash.Constants.UNKNOWN) {
operator = SqlStdOperatorTable.IS_UNKNOWN;
}
} else if (rightExpr instanceof SQLBooleanExpr) {
if (((SQLBooleanExpr) rightExpr).getValue()) {
operator = SqlStdOperatorTable.IS_TRUE;
} else {
operator = SqlStdOperatorTable.IS_FALSE;
}
}
}
break;
case IsNot:
if (rightExpr instanceof SQLNullExpr) {
operator = SqlStdOperatorTable.IS_NOT_NULL;
} else if (rightExpr instanceof SQLIdentifierExpr) {
long hashCode64 = ((SQLIdentifierExpr) rightExpr).nameHashCode64();
if (hashCode64 == FnvHash.Constants.JSON
|| hashCode64 == JSON_VALUE) {
operator = SqlStdOperatorTable.IS_NOT_JSON_VALUE;
} else if (hashCode64 == JSON_OBJECT) {
operator = SqlStdOperatorTable.IS_NOT_JSON_OBJECT;
} else if (hashCode64 == JSON_ARRAY) {
operator = SqlStdOperatorTable.IS_NOT_JSON_ARRAY;
} else if (hashCode64 == JSON_SCALAR) {
operator = SqlStdOperatorTable.IS_NOT_JSON_SCALAR;
} else if (hashCode64 == FnvHash.Constants.UNKNOWN) {
operator = SqlStdOperatorTable.IS_NOT_UNKNOWN;
}
} else if (rightExpr instanceof SQLBooleanExpr) {
if (((SQLBooleanExpr) rightExpr).getValue()) {
operator = SqlStdOperatorTable.IS_NOT_TRUE;
} else {
operator = SqlStdOperatorTable.IS_NOT_FALSE;
}
}
break;
case Escape:
case BitwiseOr:
case LessThanOrEqualOrGreaterThan:
case NotRegExp:
case RLike:
case RegExp:
case SoudsLike:
case Mod:
case SubGt:
case SubGtGt:
case PoundGt:
case PoundGtGt:
case QuesQues:
case QuesBar:
case QuesAmp:
case LeftShift:
case RightShift:
case BitwiseAnd:
case IsDistinctFrom:
case IsNotDistinctFrom:
case ILike:
case NotILike:
case AT_AT:
case SIMILAR_TO:
case POSIX_Regular_Match:
case POSIX_Regular_Match_Insensitive:
case POSIX_Regular_Not_Match:
case POSIX_Regular_Not_Match_POSIX_Regular_Match_Insensitive:
case Array_Contains:
case Array_ContainedBy:
case SAME_AS:
case JSONContains:
case NotRLike:
case NotLessThan:
case NotGreaterThan:
case BitwiseNot:
case BooleanXor:
case Assignment:
case PG_And:
case PG_ST_DISTANCE:
default:
}
return relBuilder.call(operator, leftRex, rightRex);
}
if (expr instanceof SQLQueryExpr) {
SQLQueryExpr sqlQueryExpr = (SQLQueryExpr) expr;
RelNode relNode = relBuilder.peek();
boolean col = relScope.checkCol(sqlQueryExpr);
SQLSelect select = sqlQueryExpr.getSubQuery();
RexSubQuery rexSubQuery = relBuilder.scalarQuery(relBuilder1 -> {
return convertSQLSelect(relScope, select);
});
if (col) {
return rexSubQuery;
} else {
return rexSubQuery;
}
}
if (expr instanceof SQLInSubQueryExpr) {
SQLInSubQueryExpr sqlQueryExpr = (SQLInSubQueryExpr) expr;
SQLExpr sqlQueryExprExpr = sqlQueryExpr.getExpr();
SQLSelect select = sqlQueryExpr.getSubQuery();
return relBuilder.in(convertExpr(relScope, sqlQueryExprExpr), new Function<RelBuilder, RelNode>() {
@Override
public RelNode apply(RelBuilder relBuilder) {
return convertSQLSelect(relScope, select);
}
});
}
if (expr instanceof SQLIdentifierExpr) {
String name = SQLUtils.normalize(((SQLIdentifierExpr) expr).getName());
List<String> fieldNames = relBuilder.peek().getRowType().getFieldNames();
if (fieldNames.contains(name)) {
return relBuilder.field(name);
} else {
throw new UnsupportedOperationException();
}
}
if (expr instanceof SQLPropertyExpr) {
List<String> path = Arrays.asList(expr.toString().split("\\.")).stream().map(i -> i.replaceAll("`", "")).collect(Collectors.toList());
return relScope.findColumn(relBuilder, path);
// String column;
// SQLPropertyExpr sqlPropertyExpr = (SQLPropertyExpr) expr;
// SQLExpr owner = sqlPropertyExpr.getOwner();
//
// String uniqueName = owner.toString().replaceAll("`", "");
// column = SQLUtils.normalize(sqlPropertyExpr.getSimpleName());
// if (!refMap.map().isEmpty()) {
// for (ColInfo rexCorrelVariable : this.refMap.range(uniqueName, false).values()) {
// return relBuilder.field(rexCorrelVariable.getRexCorrelVariable(), column);
// }
// }
// int size = relBuilder.size();
// for (int i = 0; i < size; i++) {
// RelNode relNode = relBuilder.peek(i);
// List<String> fieldNames = relNode.getRowType().getFieldNames();
// int index = 0;
// for (String fieldName : fieldNames) {
// if (fieldName.equalsIgnoreCase(column)) {
// for (RelNode node : this.aliasMap.range(uniqueName, false).values()) {
// if (relNode == node) {
// return relBuilder.field(size, i, index);
// }
// }
// }
// index++;
// }
// }
// for (ColInfo rexCorrelVariable : this.refMap.range(uniqueName, false).values()) {
// return relBuilder.field(rexCorrelVariable.getRexCorrelVariable(), column);
// }
}
throw new UnsupportedOperationException();
}
private RelNode convertTableSource(RelScope relScope, SQLTableSource from) {
RelBuilder relBuilder = getRelBuilder();
RelNode tableScan = null;
if (from == null) {
tableScan = relBuilder.values(new String[]{"x"}, "x").build();
}
if (from instanceof SQLExprTableSource) {
SQLExprTableSource exprTableSource = (SQLExprTableSource) from;
String schemaName = SQLUtils.normalize(
Optional.ofNullable(exprTableSource.getSchema()).orElse(relScope.getDefaultSchema()));
String tableName = SQLUtils.normalize(exprTableSource.getName().getSimpleName());
tableScan = relBuilder.scan(schemaName, tableName).build();
} else if (from instanceof SQLJoinTableSource) {
SQLJoinTableSource sqlJoinTableSource = (SQLJoinTableSource) from;
SQLTableSource left = sqlJoinTableSource.getLeft();
SQLJoinTableSource.JoinType joinType = sqlJoinTableSource.getJoinType();
SQLTableSource right = sqlJoinTableSource.getRight();
SQLExpr condition = sqlJoinTableSource.getCondition();
final List<SQLExpr> using = sqlJoinTableSource.getUsing();
boolean natural = sqlJoinTableSource.isNatural();
RelNode leftRelNode = convertTableSource(relScope, left);
RelNode rightRelNode = convertTableSource(relScope, right);
relBuilder.push(leftRelNode).push(rightRelNode);
String[] usingColumns = using.stream().map(i -> SQLUtils.normalize(i.toString())).toArray(value -> new String[value]);
JoinRelType joinRelType;
switch (joinType) {
case COMMA:
case JOIN:
case INNER_JOIN:
case NATURAL_JOIN:
case CROSS_JOIN:
case NATURAL_CROSS_JOIN:
joinRelType = JoinRelType.INNER;
break;
case LEFT_OUTER_JOIN:
joinRelType = JoinRelType.LEFT;
break;
case RIGHT_OUTER_JOIN:
joinRelType = JoinRelType.RIGHT;
break;
case FULL_OUTER_JOIN:
joinRelType = JoinRelType.FULL;
break;
default:
throw new UnsupportedOperationException("unsupported : " + joinType);
}
if (condition == null && using.isEmpty()) {
tableScan = relBuilder.join(joinRelType, Collections.emptyList()).build();
} else if (condition != null) {
tableScan = relBuilder.join(joinRelType, convertExpr(relScope, condition)).build();
} else if (!using.isEmpty()) {
tableScan = relBuilder.join(joinRelType, usingColumns).build();
}
}
return tableScan;
}
static long JSON_VALUE = FnvHash.fnv1a_64_lower("JSON VALUE");
static long JSON_OBJECT = FnvHash.fnv1a_64_lower("JSON OBJECT");
static long JSON_ARRAY = FnvHash.fnv1a_64_lower("JSON ARRAY");
static long JSON_SCALAR = FnvHash.fnv1a_64_lower("JSON SCALAR");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment