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
An 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 extends SQLExpr> 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);
}
/**
* Converts a list of SQLInsertStatement.ValuesClause objects to a single values clause if necessary.
*
* @param valuesClauseList the list of SQLInsertStatement.ValuesClause objects to be converted
* @return a list containing a single SQLInsertStatement.ValuesClause object if the input list contains more than one clause and they are all literals; otherwise, the original list is returned
*/
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");
}