com.alibaba.druid.support.calcite.CalciteMySqlNodeVisitor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of druid Show documentation
Show all versions of druid Show documentation
A JDBC datasource implementation.
package com.alibaba.druid.support.calcite;
import com.alibaba.druid.DbType;
import com.alibaba.druid.FastsqlException;
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.mysql.ast.statement.*;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.util.FnvHash;
import org.apache.calcite.avatica.util.TimeUnit;
import org.apache.calcite.sql.*;
import org.apache.calcite.sql.fun.*;
import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.sql.parser.SqlParserUtil;
import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.calcite.util.DateString;
import org.apache.calcite.util.TimeString;
import org.apache.calcite.util.TimestampString;
import java.util.*;
public class CalciteMySqlNodeVisitor extends MySqlASTVisitorAdapter {
static Map operators = new HashMap();
static {
List list = SqlStdOperatorTable.instance().getOperatorList();
for (SqlOperator op : list) {
long h = FnvHash.hashCode64(op.getName());
if (h == FnvHash.Constants.TRIM) {
continue;
}
operators.put(h, op);
}
operators.put(FnvHash.Constants.CEILING, SqlStdOperatorTable.CEIL);
}
static SqlOperator func(long hash) {
return operators.get(hash);
}
private SqlNode sqlNode;
public SqlNode getSqlNode() {
return sqlNode;
}
public boolean visit(SQLInsertStatement x) {
SqlNodeList keywords = new SqlNodeList(new ArrayList(), SqlParserPos.ZERO);
SQLExprTableSource tableSource = (SQLExprTableSource) x.getTableSource();
SqlNode targetTable = convertToSqlNode(tableSource.getExpr());
SqlNode source;
SQLSelect query = x.getQuery();
if (query != null) {
query.accept(this);
source = sqlNode;
} else {
List valuesList = x.getValuesList();
SqlNode[] rows = new SqlNode[valuesList.size()];
for (int j = 0; j < valuesList.size(); j++) {
List values = valuesList.get(j).getValues();
SqlNode[] valueNodes = new SqlNode[values.size()];
for (int i = 0; i < values.size(); i++) {
SqlNode valueNode = convertToSqlNode(values.get(i));
valueNodes[i] = valueNode;
}
SqlBasicCall row = new SqlBasicCall(SqlStdOperatorTable.ROW, valueNodes, SqlParserPos.ZERO);
rows[j] = row;
}
source = new SqlBasicCall(SqlStdOperatorTable.VALUES, rows, SqlParserPos.ZERO);
}
SqlNodeList columnList = x.getColumns().size() > 0
? convertToSqlNodeList(x.getColumns())
: null;
this.sqlNode = new SqlInsert(SqlParserPos.ZERO, keywords, targetTable, source, columnList);
return false;
}
public boolean visit(MySqlInsertStatement x) {
return visit((SQLInsertStatement) x);
}
private boolean visit(List valuesList) {
boolean isBatch = false;
List newValuesList = convertToSingleValuesIfNeed(valuesList);
if (newValuesList.size() < valuesList.size()) {
isBatch = true;
valuesList = newValuesList;
}
SqlNode[] rows = new SqlNode[valuesList.size()];
for (int j = 0; j < valuesList.size(); j++) {
List values = valuesList.get(j).getValues();
SqlNode[] valueNodes = new SqlNode[values.size()];
for (int i = 0; i < values.size(); i++) {
SqlNode valueNode = convertToSqlNode(values.get(i));
valueNodes[i] = valueNode;
}
SqlBasicCall row = new SqlBasicCall(SqlStdOperatorTable.ROW, valueNodes, SqlParserPos.ZERO);
rows[j] = row;
}
this.sqlNode = new SqlBasicCall(SqlStdOperatorTable.VALUES, rows, SqlParserPos.ZERO);
return isBatch;
}
public boolean visit(MySqlUpdateStatement x) {
if (x.getTableSource().getClass() != SQLExprTableSource.class) {
throw new UnsupportedOperationException("Support single table only for SqlUpdate statement of calcite.");
}
SQLExprTableSource tableSource = (SQLExprTableSource) x.getTableSource();
SqlNode targetTable = convertToSqlNode(tableSource.getExpr());
List columns = new ArrayList();
List values = new ArrayList();
for (SQLUpdateSetItem item : x.getItems()) {
columns.add(convertToSqlNode(item.getColumn()));
values.add(convertToSqlNode(item.getValue()));
}
SqlNodeList targetColumnList = new SqlNodeList(columns, SqlParserPos.ZERO);
SqlNodeList sourceExpressList = new SqlNodeList(values, SqlParserPos.ZERO);
SqlNode condition = convertToSqlNode(x.getWhere());
SqlIdentifier alias = null;
if (x.getTableSource().getAlias() != null) {
alias = new SqlIdentifier(tableSource.getAlias(), SqlParserPos.ZERO);
}
sqlNode = new SqlUpdate(SqlParserPos.ZERO, targetTable, targetColumnList, sourceExpressList, condition, null, alias);
return false;
}
public boolean visit(MySqlDeleteStatement x) {
SQLExprTableSource tableSource = (SQLExprTableSource) x.getTableSource();
SqlNode targetTable = convertToSqlNode(tableSource.getExpr());
SqlNode condition = convertToSqlNode(x.getWhere());
SqlIdentifier alias = null;
if (x.getTableSource().getAlias() != null) {
alias = new SqlIdentifier(tableSource.getAlias(), SqlParserPos.ZERO);
}
sqlNode = new SqlDelete(SqlParserPos.ZERO, targetTable, condition, null, alias);
return false;
}
@Override
public boolean visit(SQLUnionQuery x) {
SqlNode[] nodes;
if (x.getRelations().size() > 2) {
nodes = new SqlNode[x.getRelations().size()];
for (int i = 0; i < x.getRelations().size(); i++) {
nodes[i] = convertToSqlNode(x.getRelations().get(i));
}
} else {
SqlNode left = convertToSqlNode(x.getLeft());
SqlNode right = convertToSqlNode(x.getRight());
nodes = new SqlNode[]{left, right};
}
//order by
SqlNodeList orderBySqlNode = null;
SQLOrderBy orderBy = x.getOrderBy();
if (orderBy != null) {
orderBySqlNode = convertOrderby(orderBy);
}
//limit
SqlNode offset = null;
SqlNode fetch = null;
SQLLimit limit = x.getLimit();
if (limit != null) {
offset = convertToSqlNode(limit.getOffset());
fetch = convertToSqlNode(limit.getRowCount());
}
SQLUnionOperator operator = x.getOperator();
SqlNode union = null;
switch (operator) {
case UNION_ALL:
union = new SqlBasicCall(SqlStdOperatorTable.UNION_ALL,
nodes,
SqlParserPos.ZERO);
break;
case UNION:
case DISTINCT:
union = new SqlBasicCall(SqlStdOperatorTable.UNION,
nodes,
SqlParserPos.ZERO);
break;
case INTERSECT:
union = new SqlBasicCall(SqlStdOperatorTable.INTERSECT,
nodes,
SqlParserPos.ZERO);
break;
case EXCEPT:
union = new SqlBasicCall(SqlStdOperatorTable.EXCEPT,
nodes,
SqlParserPos.ZERO);
break;
default:
throw new FastsqlException("unsupported join type: " + operator);
}
if (null == orderBy && null == offset && null == fetch) {
sqlNode = union;
} else {
if (orderBySqlNode == null) {
orderBySqlNode = SqlNodeList.EMPTY;
}
sqlNode = new SqlOrderBy(SqlParserPos.ZERO, union, orderBySqlNode, offset, fetch);
}
return false;
}
public boolean visit(MySqlSelectQueryBlock x) {
return visit((SQLSelectQueryBlock) x);
}
private static Map nameHashCode64SqlTypeNameMapping = new HashMap<>();
public boolean visit(SQLTableSource x) {
Class clazz = x.getClass();
if (clazz == SQLJoinTableSource.class) {
visit((SQLJoinTableSource) x);
} else if (clazz == SQLExprTableSource.class) {
visit((SQLExprTableSource) x);
} else if (clazz == SQLSubqueryTableSource.class) {
visit((SQLSubqueryTableSource) x);
} else {
x.accept(this);
}
return false;
}
@Override
public boolean visit(SQLExprTableSource x) {
SqlIdentifier table;
SQLExpr expr = x.getExpr();
if (expr instanceof SQLIdentifierExpr) {
table = buildIdentifier((SQLIdentifierExpr) expr);
} else if (expr instanceof SQLPropertyExpr) {
table = buildIdentifier((SQLPropertyExpr) expr);
} else {
throw new FastsqlException("not support : " + expr);
}
if (x.getAlias() != null) {
SqlIdentifier alias = new SqlIdentifier(x.computeAlias(), SqlParserPos.ZERO);
SqlBasicCall as = new SqlBasicCall(SqlStdOperatorTable.AS, new SqlNode[]{table, alias},
SqlParserPos.ZERO);
sqlNode = as;
} else {
sqlNode = table;
}
return false;
}
@Override
public boolean visit(SQLJoinTableSource x) {
SQLJoinTableSource.JoinType joinType = x.getJoinType();
SqlNode left = convertToSqlNode(x.getLeft());
SqlNode right = convertToSqlNode(x.getRight());
SqlNode condition = convertToSqlNode(x.getCondition());
SqlLiteral conditionType = condition == null
? JoinConditionType.NONE.symbol(SqlParserPos.ZERO)
: JoinConditionType.ON.symbol(SqlParserPos.ZERO);
if (condition == null && !x.getUsing().isEmpty()) {
List using = x.getUsing();
conditionType = JoinConditionType.USING.symbol(SqlParserPos.ZERO);
condition = convertToSqlNodeList(x.getUsing());
}
switch (joinType) {
case COMMA:
this.sqlNode = new SqlJoin(SqlParserPos.ZERO, left,
SqlLiteral.createBoolean(false, SqlParserPos.ZERO),
JoinType.COMMA.symbol(SqlParserPos.ZERO), right,
JoinConditionType.NONE.symbol(SqlParserPos.ZERO),
null);
break;
case JOIN:
case INNER_JOIN:
if (condition == null) {
this.sqlNode = new SqlJoin(
SqlParserPos.ZERO,
left,
SqlLiteral.createBoolean(false, SqlParserPos.ZERO),
JoinType.COMMA.symbol(SqlParserPos.ZERO),
right,
conditionType,
null
);
} else {
this.sqlNode = new SqlJoin(
SqlParserPos.ZERO,
left,
SqlLiteral.createBoolean(false, SqlParserPos.ZERO),
JoinType.INNER.symbol(SqlParserPos.ZERO),
right,
conditionType,
condition
);
}
break;
case LEFT_OUTER_JOIN:
this.sqlNode = new SqlJoin(SqlParserPos.ZERO,
left,
SqlLiteral.createBoolean(false, SqlParserPos.ZERO),
JoinType.LEFT.symbol(SqlParserPos.ZERO),
right,
conditionType,
condition);
break;
case RIGHT_OUTER_JOIN:
this.sqlNode = new SqlJoin(SqlParserPos.ZERO,
left,
SqlLiteral.createBoolean(false, SqlParserPos.ZERO),
JoinType.RIGHT.symbol(SqlParserPos.ZERO),
right,
conditionType,
condition);
break;
case NATURAL_JOIN:
this.sqlNode = new SqlJoin(
SqlParserPos.ZERO,
left,
SqlLiteral.createBoolean(true, SqlParserPos.ZERO),
JoinType.COMMA.symbol(SqlParserPos.ZERO),
right,
JoinConditionType.NONE.symbol(SqlParserPos.ZERO),
null);
break;
case CROSS_JOIN:
this.sqlNode = new SqlJoin(
SqlParserPos.ZERO,
left,
SqlLiteral.createBoolean(false, SqlParserPos.ZERO),
JoinType.CROSS.symbol(SqlParserPos.ZERO),
right,
JoinConditionType.NONE.symbol(SqlParserPos.ZERO),
null);
break;
case NATURAL_CROSS_JOIN:
this.sqlNode = new SqlJoin(SqlParserPos.ZERO,
left,
SqlLiteral.createBoolean(true, SqlParserPos.ZERO),
JoinType.CROSS.symbol(SqlParserPos.ZERO),
right,
JoinConditionType.NONE.symbol(SqlParserPos.ZERO),
null);
break;
case FULL_OUTER_JOIN:
this.sqlNode = new SqlJoin(
SqlParserPos.ZERO,
left,
SqlLiteral.createBoolean(false, SqlParserPos.ZERO),
JoinType.FULL.symbol(SqlParserPos.ZERO),
right,
condition == null
? JoinConditionType.NONE.symbol(SqlParserPos.ZERO)
: conditionType,
condition
);
break;
default:
throw new UnsupportedOperationException("unsupported : " + joinType);
}
return false;
}
@Override
public boolean visit(SQLSubqueryTableSource x) {
sqlNode = convertToSqlNode(x.getSelect());
final String alias = x.getAlias();
if (alias != null) {
SqlIdentifier aliasIdentifier = new SqlIdentifier(alias, SqlParserPos.ZERO);
List columns = x.getColumns();
SqlNode[] operands;
if (columns.isEmpty()) {
operands = new SqlNode[]{sqlNode, aliasIdentifier};
} else {
operands = new SqlNode[columns.size() + 2];
operands[0] = sqlNode;
operands[1] = aliasIdentifier;
for (int i = 0; i < columns.size(); i++) {
SQLName column = columns.get(i);
operands[i + 2] = new SqlIdentifier(
SQLUtils.normalize(column.getSimpleName()), SqlParserPos.ZERO);
}
}
sqlNode = new SqlBasicCall(SqlStdOperatorTable.AS, operands, SqlParserPos.ZERO);
}
return false;
}
public boolean visit(SQLUnionQueryTableSource x) {
x.getUnion().accept(this);
final String alias = x.getAlias();
if (alias != null) {
SqlIdentifier aliasIdentifier = new SqlIdentifier(alias, SqlParserPos.ZERO);
sqlNode = new SqlBasicCall(SqlStdOperatorTable.AS,
new SqlNode[]{sqlNode, aliasIdentifier},
SqlParserPos.ZERO);
}
return false;
}
@Override
public boolean visit(SQLInSubQueryExpr x) {
SqlNode left = convertToSqlNode(x.getExpr());
SqlBinaryOperator subOperator = SqlStdOperatorTable.IN;
if (x.isNot()) {
subOperator = SqlStdOperatorTable.NOT_IN;
}
SqlNode right = convertToSqlNode(x.subQuery);
sqlNode = new SqlBasicCall(subOperator, new SqlNode[]{left, right}, SqlParserPos.ZERO);
return false;
}
static {
nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.BIT, SqlTypeName.BOOLEAN);
nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.BOOLEAN, SqlTypeName.BOOLEAN);
nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.TINYINT, SqlTypeName.TINYINT);
nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.SMALLINT, SqlTypeName.SMALLINT);
nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.INT, SqlTypeName.INTEGER);
nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.INTEGER, SqlTypeName.INTEGER);
nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.BIGINT, SqlTypeName.BIGINT);
nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.DECIMAL, SqlTypeName.DECIMAL);
nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.FLOAT, SqlTypeName.FLOAT);
nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.REAL, SqlTypeName.REAL);
nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.DOUBLE, SqlTypeName.DOUBLE);
nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.DATE, SqlTypeName.DATE);
nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.TIME, SqlTypeName.TIME);
nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.TIMESTAMP, SqlTypeName.TIMESTAMP);
nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.CHAR, SqlTypeName.CHAR);
nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.VARCHAR, SqlTypeName.VARCHAR);
nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.BINARY, SqlTypeName.BINARY);
nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.VARBINARY, SqlTypeName.VARBINARY);
}
public boolean visit(SQLSelectQueryBlock x) {
SqlNodeList keywordList = null;
List keywordNodes = new ArrayList(5);
int option = x.getDistionOption();
if (option != 0) {
if (option == SQLSetQuantifier.DISTINCT
|| option == SQLSetQuantifier.DISTINCTROW) {
keywordNodes.add(SqlSelectKeyword.DISTINCT.symbol(SqlParserPos.ZERO));
} else if (option == SQLSetQuantifier.ALL) {
keywordNodes.add(SqlSelectKeyword.ALL.symbol(SqlParserPos.ZERO));
}
keywordList = new SqlNodeList(keywordNodes, SqlParserPos.ZERO);
}
// select list
List columnNodes = new ArrayList(x.getSelectList().size());
for (SQLSelectItem selectItem : x.getSelectList()) {
SqlNode column = convertToSqlNode(selectItem);
columnNodes.add(column);
}
//select item
SqlNodeList selectList = new SqlNodeList(columnNodes, SqlParserPos.ZERO);
//from
SqlNode from = null;
SQLTableSource tableSource = x.getFrom();
if (tableSource != null) {
from = convertToSqlNode(tableSource);
}
//where
SqlNode where = convertToSqlNode(x.getWhere());
//order by
SqlNodeList orderBySqlNode = null;
SQLOrderBy orderBy = x.getOrderBy();
if (orderBy != null) {
orderBySqlNode = convertOrderby(orderBy);
}
//group by
SqlNodeList groupBySqlNode = null;
SqlNode having = null;
SQLSelectGroupByClause groupBys = x.getGroupBy();
if (groupBys != null) {
if (groupBys.getHaving() != null) {
having = convertToSqlNode(groupBys.getHaving());
}
if (groupBys.getItems().size() > 0) {
List groupByNodes = new ArrayList(groupBys.getItems().size());
for (SQLExpr groupBy : groupBys.getItems()) {
SqlNode groupByNode = convertToSqlNode(groupBy);
groupByNodes.add(groupByNode);
}
groupBySqlNode = new SqlNodeList(groupByNodes, SqlParserPos.ZERO);
}
SqlInternalOperator op = null;
if (groupBys.isWithRollUp()) {
op = SqlStdOperatorTable.ROLLUP;
} else if (groupBys.isWithCube()) {
op = SqlStdOperatorTable.CUBE;
}
if (op != null) {
List rollupNodes = new ArrayList(1);
boolean isRow = false;
for (SqlNode node : groupBySqlNode.getList()) {
if (node instanceof SqlBasicCall && ((SqlBasicCall) node).getOperator() == SqlStdOperatorTable.ROW) {
isRow = true;
break;
}
}
if (isRow) {
rollupNodes.add(op.createCall(SqlParserPos.ZERO, groupBySqlNode.toArray()));
groupBySqlNode = new SqlNodeList(rollupNodes, SqlParserPos.ZERO);
} else {
rollupNodes.add(op.createCall(SqlParserPos.ZERO, groupBySqlNode));
groupBySqlNode = new SqlNodeList(rollupNodes, SqlParserPos.ZERO);
}
}
}
//limit
SqlNode offset = null;
SqlNode fetch = null;
SQLLimit limit = x.getLimit();
if (limit != null) {
offset = convertToSqlNode(limit.getOffset());
fetch = convertToSqlNode(limit.getRowCount());
}
//hints
SqlNodeList hints = convertHints(x.getHints());
if (orderBy != null && x.getParent() instanceof SQLUnionQuery) {
this.sqlNode = new com.alibaba.druid.support.calcite.TDDLSqlSelect(
SqlParserPos.ZERO,
keywordList,
selectList,
from,
where,
groupBySqlNode,
having,
null,
null,
offset,
fetch,
hints,
null
);
sqlNode = new SqlOrderBy(
SqlParserPos.ZERO,
sqlNode,
orderBySqlNode,
null,
fetch
);
} else {
if (orderBySqlNode == null) {
orderBySqlNode = SqlNodeList.EMPTY;
}
if (hints == null || SqlNodeList.isEmptyList(hints)) {
this.sqlNode = new SqlSelect(
SqlParserPos.ZERO,
keywordList,
selectList,
from,
where,
groupBySqlNode,
having,
null,
SqlNodeList.EMPTY,
null,
null,
null
);
if ((!SqlNodeList.isEmptyList(orderBySqlNode))
|| offset != null
|| fetch != null
) {
sqlNode = new SqlOrderBy(
SqlParserPos.ZERO,
sqlNode,
orderBySqlNode,
offset,
fetch
);
}
} else {
this.sqlNode = new com.alibaba.druid.support.calcite.TDDLSqlSelect(
SqlParserPos.ZERO,
keywordList,
selectList,
from,
where,
groupBySqlNode,
having,
null,
orderBySqlNode,
offset,
fetch,
hints,
null
);
}
}
return false;
}
private SqlTypeName toSqlTypeName(SQLDataType dataType) {
long nameHashCode64 = dataType.nameHashCode64();
SqlTypeName sqlTypeName = nameHashCode64SqlTypeNameMapping.get(nameHashCode64);
if (sqlTypeName != null) {
return sqlTypeName;
}
throw new FastsqlException("TODO");
}
public boolean visit(SQLCastExpr x) {
SqlLiteral functionQualifier = null;
SqlNode sqlNode = convertToSqlNode(x.getExpr());
SQLDataType dataType = x.getDataType();
String typeName = dataType.getName().toUpperCase();
if (dataType.nameHashCode64() == FnvHash.Constants.INT) {
typeName = "INTEGER";
} else if (dataType.nameHashCode64() == FnvHash.Constants.NUMERIC) {
typeName = "DECIMAL";
}
SqlIdentifier dataTypeNode = (SqlIdentifier) convertToSqlNode(
new SQLIdentifierExpr(typeName));
int scale = -1;
int precision = -1;
List arguments = dataType.getArguments();
if (arguments != null && !arguments.isEmpty()) {
scale = ((SQLNumericLiteralExpr) arguments.get(0)).getNumber().intValue();
if (arguments.size() > 1) {
precision = ((SQLNumericLiteralExpr) arguments.get(1)).getNumber().intValue();
}
}
SqlDataTypeSpec sqlDataTypeSpec = new SqlDataTypeSpec(
new SqlBasicTypeNameSpec(
toSqlTypeName(dataType),
scale,
precision,
SqlParserPos.ZERO
),
SqlParserPos.ZERO
);
SqlOperator sqlOperator = new SqlCastFunction();
this.sqlNode = new com.alibaba.druid.support.calcite.CalciteSqlBasicCall(
sqlOperator,
new SqlNode[]{sqlNode, sqlDataTypeSpec},
SqlParserPos.ZERO,
false,
functionQualifier
);
return false;
}
public boolean visit(SQLCaseExpr x) {
SQLExpr valueExpr = x.getValueExpr();
SqlNode nodeValue = null;
SqlNodeList nodeWhen = new SqlNodeList(SqlParserPos.ZERO);
SqlNodeList nodeThen = new SqlNodeList(SqlParserPos.ZERO);
if (valueExpr != null) {
nodeValue = convertToSqlNode(valueExpr);
}
List items = x.getItems();
int elExpr = 0;
for (int size = items.size(); elExpr < size; ++elExpr) {
this.visit((SQLCaseExpr.Item) items.get(elExpr));
if (this.sqlNode != null && this.sqlNode instanceof SqlNodeList) {
SqlNodeList nodeListTemp = (SqlNodeList) this.sqlNode;
nodeWhen.add(nodeListTemp.get(0));
nodeThen.add(nodeListTemp.get(1));
}
}
SQLExpr elseExpr = x.getElseExpr();
SqlNode nodeElse = convertToSqlNode(elseExpr);
SqlNodeList sqlNodeList = new SqlNodeList(SqlParserPos.ZERO);
sqlNodeList.add(nodeValue);
sqlNodeList.add(nodeWhen);
sqlNodeList.add(nodeThen);
sqlNodeList.add(nodeElse);
sqlNode = SqlCase.createSwitched(SqlParserPos.ZERO, nodeValue, nodeWhen, nodeThen, nodeElse);
return false;
}
public boolean visit(SQLCaseExpr.Item x) {
SQLExpr conditionExpr = x.getConditionExpr();
SqlNode sqlNode1 = convertToSqlNode(conditionExpr);
SQLExpr valueExpr = x.getValueExpr();
SqlNode sqlNode2 = convertToSqlNode(valueExpr);
SqlNodeList sqlNodeList = new SqlNodeList(SqlParserPos.ZERO);
sqlNodeList.add(sqlNode1);
sqlNodeList.add(sqlNode2);
sqlNode = sqlNodeList;
return false;
}
public boolean visit(SQLListExpr x) {
List items = x.getItems();
List objects = new ArrayList();
for (int i = 0; i < items.size(); i++) {
SQLExpr sqlExpr = items.get(i);
SqlNode sqlNode = convertToSqlNode(sqlExpr);
objects.add(sqlNode);
}
sqlNode = SqlStdOperatorTable.ROW.createCall(SqlParserPos.ZERO, objects);
return false;
}
@Override
public boolean visit(SQLSelect x) {
SQLWithSubqueryClause with = x.getWithSubQuery();
if (with != null) {
SqlNodeList withList = new SqlNodeList(SqlParserPos.ZERO);
final List entries = with.getEntries();
for (SQLWithSubqueryClause.Entry entry : entries) {
visit(entry);
withList.add(sqlNode);
}
SqlNode query = convertToSqlNode(x.getQuery());
if (query instanceof SqlOrderBy) {
SqlOrderBy orderBy = (SqlOrderBy) query;
SqlWith w = new SqlWith(SqlParserPos.ZERO, withList, orderBy.query);
sqlNode = new SqlOrderBy(
SqlParserPos.ZERO,
w,
orderBy.orderList,
orderBy.offset,
orderBy.fetch
);
} else {
sqlNode = new SqlWith(SqlParserPos.ZERO, withList, query);
}
if (query instanceof SqlSelect) {
SqlSelect select = (SqlSelect) query;
SqlNode fetch = select.getFetch();
SqlNodeList orderList = select.getOrderList();
if (fetch != null
|| (orderList != null && orderList.size() > 0)) {
SqlNodeList orderByList = null;
if (orderList != null) {
orderByList = new SqlNodeList(orderList.getList(), SqlParserPos.ZERO);
orderList.getList().clear();
} else {
orderByList = SqlNodeList.EMPTY;
}
sqlNode = new SqlOrderBy(
SqlParserPos.ZERO,
sqlNode,
orderByList,
null,
fetch
);
if (fetch != null) {
select.setFetch(null);
}
}
}
} else {
sqlNode = convertToSqlNode(x.getQuery());
}
return false;
}
public boolean visit(SQLWithSubqueryClause.Entry x) {
SqlNodeList columnList = null;
final List columns = x.getColumns();
if (columns.size() > 0) {
columnList = new SqlNodeList(SqlParserPos.ZERO);
for (SQLName column : columns) {
columnList.add(new SqlIdentifier(column.getSimpleName(), SqlParserPos.ZERO));
}
}
SqlNode query = convertToSqlNode(x.getSubQuery());
SqlIdentifier name = new SqlIdentifier(x.getAlias(), SqlParserPos.ZERO);
sqlNode = new SqlWithItem(SqlParserPos.ZERO, name, columnList, query);
return false;
}
@Override
public boolean visit(SQLSelectStatement x) {
SqlNode sqlNode = convertToSqlNode(x.getSelect());
if (sqlNode instanceof com.alibaba.druid.support.calcite.TDDLSqlSelect) {
com.alibaba.druid.support.calcite.TDDLSqlSelect select = (com.alibaba.druid.support.calcite.TDDLSqlSelect) sqlNode;
SqlNodeList headHints = convertHints(x.getHeadHintsDirect());
select.setHeadHints(headHints);
this.sqlNode = select;
} else {
this.sqlNode = sqlNode;
}
return false;
}
protected void visit(SQLSelectQuery x) {
Class clazz = x.getClass();
if (clazz == MySqlSelectQueryBlock.class) {
visit((MySqlSelectQueryBlock) x);
} else if (clazz == SQLUnionQuery.class) {
visit((SQLUnionQuery) x);
} else {
x.accept(this);
}
}
public boolean visit(SQLAllExpr x) {
sqlNode = convertToSqlNode(x.getSubQuery());
return false;
}
public boolean visit(SQLAnyExpr x) {
sqlNode = convertToSqlNode(x.getSubQuery());
return false;
}
private boolean isSqlAllExpr(SQLExpr x) {
return x.getClass() == SQLAllExpr.class;
}
private boolean isAnyOrSomeExpr(SQLExpr x) {
return x.getClass() == SQLAnyExpr.class || x.getClass() == SQLSomeExpr.class;
}
public boolean visit(SQLSelectItem x) {
SQLExpr expr = x.getExpr();
if (expr instanceof SQLIdentifierExpr) {
visit((SQLIdentifierExpr) expr);
} else if (expr instanceof SQLPropertyExpr) {
visit((SQLPropertyExpr) expr);
} else if (expr instanceof SQLAggregateExpr) {
visit((SQLAggregateExpr) expr);
} else {
expr.accept(this);
} // select a + (select count(1) from b) as mm from c;
// select a + (select COUNT(1) from b) as 'a + (select count(1) as
// 'count(1)' from b)' from c;
String alias = x.getAlias();
if (alias != null && alias.length() > 0) {
String alias2 = x.getAlias2();
sqlNode = new SqlBasicCall(SqlStdOperatorTable.AS,
new SqlNode[]{sqlNode, new SqlIdentifier(SQLUtils.normalize(alias2, DbType.mysql), SqlParserPos.ZERO)},
SqlParserPos.ZERO);
}
return false;
}
@Override
public boolean visit(SQLIdentifierExpr x) {
if (x.getName().equalsIgnoreCase("unknown")) {
sqlNode = SqlLiteral.createUnknown(SqlParserPos.ZERO);
return false;
}
sqlNode = buildIdentifier(x);
return false;
}
public boolean visit(SQLPropertyExpr x) {
sqlNode = buildIdentifier(x);
return false;
}
SqlIdentifier buildIdentifier(SQLIdentifierExpr x) {
return new SqlIdentifier(SQLUtils.normalize(x.getName()), SqlParserPos.ZERO);
}
SqlIdentifier buildIdentifier(SQLPropertyExpr x) {
String name = SQLUtils.normalize(x.getName());
if ("*".equals(name)) {
name = "";
}
SQLExpr owner = x.getOwner();
List names;
if (owner instanceof SQLIdentifierExpr) {
names = Arrays.asList(((SQLIdentifierExpr) owner).normalizedName(), name);
} else if (owner instanceof SQLPropertyExpr) {
names = new ArrayList();
buildIdentifier((SQLPropertyExpr) owner, names);
names.add(name);
} else {
throw new FastsqlException("not support : " + owner);
}
return new SqlIdentifier(names, SqlParserPos.ZERO);
}
void buildIdentifier(SQLPropertyExpr x, List names) {
String name = SQLUtils.normalize(x.getName());
SQLExpr owner = x.getOwner();
if (owner instanceof SQLIdentifierExpr) {
names.add(((SQLIdentifierExpr) owner).normalizedName());
} else if (owner instanceof SQLPropertyExpr) {
buildIdentifier((SQLPropertyExpr) owner, names);
} else {
throw new FastsqlException("not support : " + owner);
}
names.add(name);
}
public boolean visit(SQLBinaryOpExprGroup x) {
SqlOperator operator = null;
switch (x.getOperator()) {
case BooleanAnd:
operator = SqlStdOperatorTable.AND;
break;
case BooleanOr:
operator = SqlStdOperatorTable.OR;
break;
default:
break;
}
final List items = x.getItems();
SqlNode group = null;
for (int i = 0; i < items.size(); i++) {
SQLExpr item = items.get(i);
final SqlNode calciteNode = convertToSqlNode(item);
if (group == null) {
group = calciteNode;
} else {
group = new SqlBasicCall(operator, new SqlNode[]{group, calciteNode}, SqlParserPos.ZERO);
}
}
this.sqlNode = group;
return false;
}
public boolean visit(SQLBinaryOpExpr x) {
SqlOperator operator = null;
SqlQuantifyOperator someOrAllOperator = null;
SqlNode left = convertToSqlNode(x.getLeft());
SQLExpr rightExpr = x.getRight();
SqlNode right = convertToSqlNode(rightExpr);
switch (x.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 Multiply:
operator = SqlStdOperatorTable.MULTIPLY;
break;
case Divide:
operator = SqlStdOperatorTable.DIVIDE;
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 = SqlStdOperatorTable.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: {
SqlBasicCall like = (SqlBasicCall) left;
sqlNode = new SqlBasicCall(like.getOperator(), new SqlNode[]{like.operands[0], like.operands[1], right},
SqlParserPos.ZERO);
return false;
}
default:
throw new FastsqlException("not support " + x.getOperator());
}
if (someOrAllOperator != null) {
this.sqlNode = new SqlBasicCall(someOrAllOperator, new SqlNode[]{left, right},
SqlParserPos.ZERO);
} else {
if (operator == SqlStdOperatorTable.IS_NULL
|| operator == SqlStdOperatorTable.IS_NOT_NULL
|| operator == SqlStdOperatorTable.IS_TRUE
|| operator == SqlStdOperatorTable.IS_NOT_TRUE) {
this.sqlNode = new SqlBasicCall(operator,
new SqlNode[]{left},
SqlParserPos.ZERO);
} else {
this.sqlNode = new SqlBasicCall(operator,
new SqlNode[]{left, right},
SqlParserPos.ZERO);
}
}
return false;
}
public boolean visit(SQLBetweenExpr x) {
SQLExpr testExpr = x.getTestExpr();
SqlOperator sqlOperator = SqlStdOperatorTable.BETWEEN;
if (x.isNot()) {
sqlOperator = SqlStdOperatorTable.NOT_BETWEEN;
}
SqlNode sqlNode = convertToSqlNode(testExpr);
SqlNode sqlNodeBegin = convertToSqlNode(x.getBeginExpr());
SqlNode sqlNodeEnd = convertToSqlNode(x.getEndExpr());
ArrayList sqlNodes = new ArrayList(3);
sqlNodes.add(sqlNode);
sqlNodes.add(sqlNodeBegin);
sqlNodes.add(sqlNodeEnd);
this.sqlNode = new SqlBasicCall(sqlOperator, SqlParserUtil.toNodeArray(sqlNodes), SqlParserPos.ZERO);
return false;
}
public boolean visit(SQLExistsExpr x) {
SqlOperator sqlOperator = SqlStdOperatorTable.EXISTS;
SqlNode sqlNode = sqlOperator.createCall(SqlParserPos.ZERO,
convertToSqlNode(x.getSubQuery()));
if (x.isNot()) {
sqlNode = SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO, sqlNode);
}
this.sqlNode = sqlNode;
return false;
}
public boolean visit(SQLAllColumnExpr x) {
sqlNode = new SqlIdentifier(Arrays.asList(""), SqlParserPos.ZERO);
return false;
}
public boolean visit(SQLCharExpr x) {
String text = x.getText();
text = text.replaceAll("\\\\", "\\\\\\\\");
sqlNode = SqlLiteral.createCharString(text, SqlParserPos.ZERO);
return false;
}
public boolean visit(SQLNCharExpr x) {
String text = x.getText();
text = text.replaceAll("\\\\", "\\\\\\\\");
sqlNode = SqlLiteral.createCharString(text, SqlParserPos.ZERO);
return false;
}
public boolean visit(SQLNullExpr x) {
sqlNode = SqlLiteral.createNull(SqlParserPos.ZERO);
return false;
}
public boolean visit(SQLIntegerExpr x) {
sqlNode = SqlLiteral.createExactNumeric(x.getNumber().toString(), SqlParserPos.ZERO);
return false;
}
public boolean visit(SQLBooleanExpr x) {
sqlNode = SqlLiteral.createBoolean(x.getBooleanValue(), SqlParserPos.ZERO);
return false;
}
public boolean visit(SQLNumberExpr x) {
String str = x.toString();
if (str.indexOf('E') > 0 || str.indexOf('e') > 0) {
sqlNode = SqlLiteral.createApproxNumeric(str, SqlParserPos.ZERO);
} else {
sqlNode = SqlLiteral.createExactNumeric(str, SqlParserPos.ZERO);
}
return false;
}
public boolean visit(SQLTimestampExpr x) {
String literal = x.getLiteral();
int precision = 0;
if (literal.endsWith("00")) {
char c3 = literal.charAt(literal.length() - 3);
if (c3 >= '0' && c3 <= '9') {
literal = literal.substring(0, literal.length() - 2);
precision = 3;
}
}
TimestampString ts = new TimestampString(literal);
sqlNode = SqlLiteral.createTimestamp(ts, precision, SqlParserPos.ZERO);
return false;
}
public boolean visit(SQLDateExpr x) {
String literal = x.getLiteral();
DateString ds = new DateString(literal);
sqlNode = SqlLiteral.createDate(ds, SqlParserPos.ZERO);
return false;
}
public boolean visit(SQLTimeExpr x) {
String literal = ((SQLCharExpr) x.getLiteral()).getText();
TimeString ds = new TimeString(literal);
sqlNode = SqlLiteral.createTime(ds, 0, SqlParserPos.ZERO);
return false;
}
public boolean visit(SQLCurrentTimeExpr x) {
sqlNode = new SqlIdentifier(x.getType().name, SqlParserPos.ZERO);
return false;
}
public boolean visit(SQLAggregateExpr x) {
SqlOperator functionOperator;
String methodName = x.getMethodName();
long hashCode64 = x.methodNameHashCode64();
functionOperator = func(hashCode64);
if (functionOperator == null) {
functionOperator = new SqlUnresolvedFunction(new SqlIdentifier(methodName, SqlParserPos.ZERO),
null,
null,
null,
null,
SqlFunctionCategory.USER_DEFINED_FUNCTION);
}
SqlLiteral functionQualifier = null;
if (x.getOption() == SQLAggregateOption.DISTINCT) {
functionQualifier = SqlSelectKeyword.DISTINCT.symbol(SqlParserPos.ZERO);
}
List arguments = x.getArguments();
List argNodes = new ArrayList(arguments.size());
for (int i = 0, size = arguments.size(); i < size; ++i) {
argNodes.add(convertToSqlNode(arguments.get(i)));
}
this.sqlNode = functionOperator.createCall(functionQualifier,
SqlParserPos.ZERO,
SqlParserUtil.toNodeArray(argNodes)
);
SQLOrderBy orderBy = x.getOrderBy();
if (orderBy != null) {
SqlNodeList orderByItems = convertOrderby(orderBy);
this.sqlNode = SqlStdOperatorTable.WITHIN_GROUP
.createCall(SqlParserPos.ZERO, this.sqlNode, orderByItems);
}
SQLOver over = x.getOver();
if (over != null) {
SqlNode aggNode = this.sqlNode;
SQLOver.WindowingBound windowingBetweenBeginBound = over.getWindowingBetweenBeginBound();
SQLOver.WindowingBound windowingBetweenEndBound = over.getWindowingBetweenEndBound();
boolean isRow = over.getWindowingType() != SQLOver.WindowingType.RANGE;
SqlNode lowerBound;
if (over.getWindowingBetweenBegin() != null) {
over.getWindowingBetweenBegin().accept(this);
lowerBound = SqlWindow.createPreceding(sqlNode, SqlParserPos.ZERO);
} else {
lowerBound = createSymbol(windowingBetweenBeginBound);
}
SqlNode upperBound = createSymbol(windowingBetweenEndBound);
SqlWindow window = new SqlWindow(
SqlParserPos.ZERO,
null,
null,
convertToSqlNodeList(over.getPartitionBy()),
convertOrderby(over.getOrderBy()),
SqlLiteral.createBoolean(isRow, SqlParserPos.ZERO),
lowerBound,
upperBound,
null
);
sqlNode = SqlStdOperatorTable.OVER.createCall(
SqlParserPos.ZERO,
aggNode,
window);
}
SQLExpr filter = x.getFilter();
if (filter != null) {
SqlNode aggNode = this.sqlNode;
filter.accept(this);
sqlNode = SqlStdOperatorTable.FILTER.createCall(
SqlParserPos.ZERO,
aggNode,
sqlNode);
}
return false;
}
protected static SqlNode createSymbol(SQLOver.WindowingBound bound) {
if (bound == null) {
return null;
}
switch (bound) {
case CURRENT_ROW:
return SqlWindow.createCurrentRow(SqlParserPos.ZERO);
case UNBOUNDED_FOLLOWING:
return SqlWindow.createUnboundedFollowing(SqlParserPos.ZERO);
case UNBOUNDED_PRECEDING:
return SqlWindow.createUnboundedPreceding(SqlParserPos.ZERO);
default:
return null;
}
}
public boolean visit(SQLMethodInvokeExpr x) {
List arguments = x.getArguments();
List argNodes = new ArrayList(arguments.size());
long nameHashCode64 = x.methodNameHashCode64();
SqlOperator functionOperator = func(nameHashCode64);
String methodName = x.getMethodName();
if (functionOperator == null) {
if (nameHashCode64 == FnvHash.Constants.TRIM) {
functionOperator = SqlStdOperatorTable.TRIM;
if (arguments.size() == 1) {
SqlNode sqlNode = convertToSqlNode(arguments.get(0));
this.sqlNode = new com.alibaba.druid.support.calcite.CalciteSqlBasicCall(functionOperator,
new SqlNode[]{
SqlLiteral.createSymbol(SqlTrimFunction.Flag.BOTH, SqlParserPos.ZERO),
SqlCharStringLiteral.createCharString(" ", SqlParserPos.ZERO),
sqlNode
},
SqlParserPos.ZERO,
false,
null);
return false;
}
} else {
functionOperator = new SqlUnresolvedFunction(
new SqlIdentifier(methodName, SqlParserPos.ZERO),
null,
null,
null,
null,
SqlFunctionCategory.USER_DEFINED_FUNCTION);
}
}
SqlLiteral functionQualifier = null;
for (SQLExpr exp : arguments) {
argNodes.add(convertToSqlNode(exp));
}
if ((nameHashCode64 == FnvHash.Constants.TIMESTAMPDIFF || nameHashCode64 == FnvHash.Constants.TIMESTAMPADD)
&& argNodes.size() > 0
&& argNodes.get(0) instanceof SqlIdentifier
) {
SqlIdentifier arg0 = (SqlIdentifier) argNodes.get(0);
TimeUnit timeUnit = TimeUnit.valueOf(arg0.toString().toUpperCase());
argNodes.set(0, SqlLiteral.createSymbol(timeUnit, SqlParserPos.ZERO));
}
this.sqlNode = new com.alibaba.druid.support.calcite.CalciteSqlBasicCall(functionOperator,
SqlParserUtil.toNodeArray(argNodes),
SqlParserPos.ZERO,
false,
functionQualifier);
return false;
}
public boolean visit(SQLInListExpr x) {
SqlNodeList sqlNodes = convertToSqlNodeList(x.getTargetList());
SqlOperator sqlOperator = x.isNot() ? SqlStdOperatorTable.NOT_IN : SqlStdOperatorTable.IN;
sqlNode = new SqlBasicCall(sqlOperator, new SqlNode[]{convertToSqlNode(x.getExpr()), sqlNodes},
SqlParserPos.ZERO);
return false;
}
public boolean visit(SQLVariantRefExpr x) {
if ("?".equals(x.getName())) {
this.sqlNode = new SqlDynamicParam(x.getIndex(),
SqlParserPos.ZERO);
return false;
} else {
System.out.println("end");
}
return false;
}
@Override
public boolean visit(SQLUnaryExpr x) {
SQLUnaryOperator operator = x.getOperator();
switch (operator) {
case NOT:
this.sqlNode = SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO,
convertToSqlNode(x.getExpr()));
break;
case Negative:
this.sqlNode = SqlStdOperatorTable.UNARY_MINUS.createCall(SqlParserPos.ZERO,
convertToSqlNode(x.getExpr()));
break;
case Not:
case Compl:
case BINARY:
default:
super.visit(x);
}
return false;
}
protected SqlNodeList convertToSqlNodeList(SQLExpr expr) {
if (expr instanceof SQLListExpr) {
return convertToSqlNodeList(((SQLListExpr) expr).getItems());
} else {
List nodes = new ArrayList(1);
return new SqlNodeList(nodes, SqlParserPos.ZERO);
}
}
protected SqlNodeList convertToSqlNodeList(List exprList) {
final int size = exprList.size();
List nodes = new ArrayList(size);
for (int i = 0; i < size; ++i) {
SQLExpr expr = exprList.get(i);
SqlNode node;
if (expr instanceof SQLListExpr) {
node = convertToSqlNodeList(((SQLListExpr) expr).getItems());
} else {
node = convertToSqlNode(expr);
}
nodes.add(node);
}
return new SqlNodeList(nodes, SqlParserPos.ZERO);
}
protected SqlNode convertToSqlNode(SQLObject ast) {
if (ast == null) {
return null;
}
CalciteMySqlNodeVisitor visitor = new CalciteMySqlNodeVisitor();
ast.accept(visitor);
return visitor.getSqlNode();
}
private SqlNodeList convertOrderby(SQLOrderBy orderBy) {
if (orderBy == null) {
return new SqlNodeList(new ArrayList(), SqlParserPos.ZERO);
}
List items = orderBy.getItems();
List orderByNodes = new ArrayList(items.size());
for (SQLSelectOrderByItem item : items) {
SqlNode node = convertToSqlNode(item.getExpr());
if (item.getType() == SQLOrderingSpecification.DESC) {
node = new SqlBasicCall(SqlStdOperatorTable.DESC, new SqlNode[]{node}, SqlParserPos.ZERO);
}
SQLSelectOrderByItem.NullsOrderType nullsOrderType = item.getNullsOrderType();
if (nullsOrderType != null) {
switch (nullsOrderType) {
case NullsFirst:
node = new SqlBasicCall(SqlStdOperatorTable.NULLS_FIRST, new SqlNode[]{node}, SqlParserPos.ZERO);
break;
case NullsLast:
node = new SqlBasicCall(SqlStdOperatorTable.NULLS_LAST, new SqlNode[]{node}, SqlParserPos.ZERO);
break;
default:
break;
}
}
orderByNodes.add(node);
}
return new SqlNodeList(orderByNodes, SqlParserPos.ZERO);
}
private SqlNodeList convertHints(List hints) {
if (hints == null) {
return null;
}
List nodes = new ArrayList(hints.size());
for (SQLCommentHint hint : hints) {
if (hint instanceof TDDLHint) {
nodes.add(convertTDDLHint((TDDLHint) hint));
}
}
return new SqlNodeList(nodes, SqlParserPos.ZERO);
}
private SqlNodeList convertTDDLHint(TDDLHint hint) {
List functions = hint.getFunctions();
List funNodes = new ArrayList(functions.size());
for (TDDLHint.Function function : functions) {
String functionName = function.getName();
List arguments = function.getArguments();
SqlNode[] argNodes = new SqlNode[arguments.size()];
for (int i = 0; i < arguments.size(); i++) {
TDDLHint.Argument argument = arguments.get(i);
SqlNode argName = convertToSqlNode(argument.getName());
SqlNode argValue = convertToSqlNode(argument.getValue());
List arg = new ArrayList();
if (argName != null) {
arg.add(argName);
}
if (argValue != null) {
arg.add(argValue);
}
SqlNode argNode = null;
if (arg.size() == 2) {
argNode = SqlStdOperatorTable.EQUALS.createCall(SqlParserPos.ZERO, arg);
} else if (arg.size() == 1) {
argNode = argName;
}
argNodes[i] = argNode;
}
SqlNode funNode = new SqlBasicCall(
new SqlUnresolvedFunction(new SqlIdentifier(functionName, SqlParserPos.ZERO), null, null,
null, null, SqlFunctionCategory.USER_DEFINED_FUNCTION), argNodes,
SqlParserPos.ZERO);
funNodes.add(funNode);
}
return new SqlNodeList(funNodes, SqlParserPos.ZERO);
}
/**
* If there are multiple VALUES, and all values in VALUES CLAUSE are literal,
* convert the value clauses to a single value clause.
*
* @param valuesClauseList
* @return
*/
public static List convertToSingleValuesIfNeed(List valuesClauseList) {
if (valuesClauseList.size() <= 1) {
return valuesClauseList;
}
// If they are all literals
for (SQLInsertStatement.ValuesClause clause : valuesClauseList) {
for (SQLExpr expr : clause.getValues()) {
if (expr instanceof SQLVariantRefExpr) {
if (((SQLVariantRefExpr) expr).getName().equals("?")) {
continue;
}
}
return valuesClauseList;
}
}
// Return only the first values clause.
return Arrays.asList(valuesClauseList.get(0));
}
public boolean visit(SQLIntervalExpr x) {
TimeUnit[] timeUnits = getTimeUnit(x.getUnit());
List convertedArgs = new ArrayList(2);
SqlIntervalQualifier unitNode = new SqlIntervalQualifier(timeUnits[0], timeUnits[1], SqlParserPos.ZERO);
SqlLiteral valueNode = (SqlLiteral) convertToSqlNode(x.getValue());
sqlNode = SqlIntervalLiteral.createInterval(1, valueNode.toValue(), unitNode, SqlParserPos.ZERO);
return false;
}
public static TimeUnit[] getTimeUnit(SQLIntervalUnit unit) {
TimeUnit[] timeUnits = new TimeUnit[2];
switch (unit) {
// case MICROSECOND:
// timeUnits[0] = TimeUnit.MICROSECOND;
// timeUnits[1] = TimeUnit.MICROSECOND;
// break;
case SECOND:
timeUnits[0] = TimeUnit.SECOND;
timeUnits[1] = TimeUnit.SECOND;
break;
case MINUTE:
timeUnits[0] = TimeUnit.MINUTE;
timeUnits[1] = TimeUnit.MINUTE;
break;
case HOUR:
timeUnits[0] = TimeUnit.HOUR;
timeUnits[1] = TimeUnit.HOUR;
break;
case DAY:
timeUnits[0] = TimeUnit.DAY;
timeUnits[1] = TimeUnit.DAY;
break;
case WEEK:
timeUnits[0] = TimeUnit.WEEK;
timeUnits[1] = TimeUnit.WEEK;
break;
case MONTH:
timeUnits[0] = TimeUnit.MONTH;
timeUnits[1] = TimeUnit.MONTH;
break;
case QUARTER:
timeUnits[0] = TimeUnit.QUARTER;
timeUnits[1] = TimeUnit.QUARTER;
break;
case YEAR:
timeUnits[0] = TimeUnit.YEAR;
timeUnits[1] = TimeUnit.YEAR;
break;
// case MINUTE_MICROSECOND:
// timeUnits[0] = TimeUnit.MINUTE;
// timeUnits[1] = TimeUnit.MICROSECOND;
// break;
case MINUTE_SECOND:
timeUnits[0] = TimeUnit.MINUTE;
timeUnits[1] = TimeUnit.SECOND;
break;
// case HOUR_MICROSECOND:
// timeUnits[0] = TimeUnit.HOUR;
// timeUnits[1] = TimeUnit.MICROSECOND;
// break;
case HOUR_SECOND:
timeUnits[0] = TimeUnit.HOUR;
timeUnits[1] = TimeUnit.SECOND;
break;
case HOUR_MINUTE:
timeUnits[0] = TimeUnit.HOUR;
timeUnits[1] = TimeUnit.MINUTE;
break;
// case DAY_MICROSECOND:
// timeUnits[0] = TimeUnit.DAY;
// timeUnits[1] = TimeUnit.MICROSECOND;
// break;
case DAY_SECOND:
timeUnits[0] = TimeUnit.DAY;
timeUnits[1] = TimeUnit.SECOND;
break;
case DAY_MINUTE:
timeUnits[0] = TimeUnit.DAY;
timeUnits[1] = TimeUnit.MINUTE;
break;
case DAY_HOUR:
timeUnits[0] = TimeUnit.DAY;
timeUnits[1] = TimeUnit.HOUR;
break;
case YEAR_MONTH:
timeUnits[0] = TimeUnit.YEAR;
timeUnits[1] = TimeUnit.MONTH;
break;
default:
throw new ParserException("Unsupported time unit");
}
return timeUnits;
}
public boolean visit(SQLNotExpr x) {
SQLExpr expr = x.getExpr();
if (expr instanceof SQLIdentifierExpr) {
long hashCode64 = ((SQLIdentifierExpr) expr).nameHashCode64();
if (hashCode64 == FnvHash.Constants.UNKNOWN) {
sqlNode = SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO, SqlLiteral.createUnknown(SqlParserPos.ZERO));
return false;
}
}
expr.accept(this);
sqlNode = SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO, sqlNode);
return false;
}
@Override
public boolean visit(SQLExtractExpr x) {
x.getValue().accept(this);
TimeUnit[] timeUnits = getTimeUnit(x.getUnit());
sqlNode = SqlStdOperatorTable.EXTRACT
.createCall(
SqlParserPos.ZERO,
new SqlIntervalQualifier(timeUnits[0], timeUnits[1], SqlParserPos.ZERO),
sqlNode
);
return false;
}
@Override
public boolean visit(SQLGroupingSetExpr x) {
sqlNode = SqlStdOperatorTable.GROUPING_SETS.createCall(
SqlParserPos.ZERO,
convertToSqlNodeList(x.getParameters())
);
return false;
}
@Override
public boolean visit(SQLValuesQuery x) {
List valuesNodes = new ArrayList();
for (SQLExpr value : x.getValues()) {
valuesNodes.add(
SqlStdOperatorTable.ROW.createCall(SqlParserPos.ZERO, convertToSqlNodeList(value)));
}
sqlNode = SqlStdOperatorTable.VALUES.createCall(SqlParserPos.ZERO, valuesNodes);
return false;
}
@Override
public boolean visit(SQLUnnestTableSource x) {
sqlNode = SqlStdOperatorTable.UNNEST
.createCall(
SqlParserPos.ZERO,
convertToSqlNodeList(x.getItems())
);
String alias = x.getAlias();
if (alias != null) {
sqlNode = new SqlBasicCall(
SqlStdOperatorTable.AS,
new SqlNode[]{sqlNode, new SqlIdentifier(alias, SqlParserPos.ZERO)},
SqlParserPos.ZERO
);
}
return false;
}
@Override
public boolean visit(SQLDefaultExpr x) {
sqlNode = SqlStdOperatorTable.DEFAULT.createCall(SqlParserPos.ZERO);
return false;
}
@Override
public boolean visit(MySqlExplainStatement x) {
x.getStatement().accept(this);
SqlNode explicandum = this.sqlNode;
sqlNode = new SqlExplain(
SqlParserPos.ZERO,
explicandum,
SqlLiteral.createSymbol(SqlExplainLevel.EXPPLAN_ATTRIBUTES, SqlParserPos.ZERO),
SqlLiteral.createSymbol(SqlExplain.Depth.PHYSICAL, SqlParserPos.ZERO),
SqlLiteral.createSymbol(SqlExplainFormat.TEXT, SqlParserPos.ZERO),
0
);
return false;
}
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");
}