17 package com.mapd.calcite.parser;
19 import static org.apache.calcite.sql.parser.SqlParserPos.ZERO;
21 import com.google.common.collect.ImmutableList;
25 import com.mapd.parser.extension.ddl.ExtendedSqlParser;
29 import org.apache.calcite.avatica.util.Casing;
30 import org.apache.calcite.config.CalciteConnectionConfig;
31 import org.apache.calcite.config.CalciteConnectionConfigImpl;
32 import org.apache.calcite.config.CalciteConnectionProperty;
33 import org.apache.calcite.plan.Context;
34 import org.apache.calcite.plan.RelOptTable;
35 import org.apache.calcite.plan.RelOptUtil;
36 import org.apache.calcite.plan.hep.HepPlanner;
37 import org.apache.calcite.plan.hep.HepProgramBuilder;
40 import org.apache.calcite.rel.RelNode;
41 import org.apache.calcite.rel.RelRoot;
42 import org.apache.calcite.rel.RelShuttleImpl;
43 import org.apache.calcite.rel.RelWriter;
44 import org.apache.calcite.rel.core.TableModify;
45 import org.apache.calcite.rel.core.TableModify.Operation;
47 import org.apache.calcite.rel.externalize.RelWriterImpl;
48 import org.apache.calcite.rel.logical.LogicalProject;
49 import org.apache.calcite.rel.logical.LogicalTableModify;
50 import org.apache.calcite.rel.rules.CoreRules;
52 import org.apache.calcite.rel.type.RelDataType;
53 import org.apache.calcite.rel.type.RelDataTypeFactory;
54 import org.apache.calcite.rel.type.RelDataTypeSystem;
55 import org.apache.calcite.rex.*;
56 import org.apache.calcite.runtime.CalciteException;
57 import org.apache.calcite.schema.SchemaPlus;
58 import org.apache.calcite.schema.Statistic;
59 import org.apache.calcite.schema.Table;
60 import org.apache.calcite.sql.*;
61 import org.apache.calcite.sql.advise.SqlAdvisorValidator;
62 import org.apache.calcite.sql.dialect.CalciteSqlDialect;
63 import org.apache.calcite.sql.fun.SqlCase;
64 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
65 import org.apache.calcite.sql.parser.SqlParseException;
66 import org.apache.calcite.sql.parser.SqlParser;
67 import org.apache.calcite.sql.parser.SqlParserPos;
68 import org.apache.calcite.sql.type.OperandTypes;
69 import org.apache.calcite.sql.type.ReturnTypes;
70 import org.apache.calcite.sql.type.SqlTypeName;
71 import org.apache.calcite.sql.type.SqlTypeUtil;
72 import org.apache.calcite.sql.util.SqlBasicVisitor;
73 import org.apache.calcite.sql.util.SqlShuttle;
74 import org.apache.calcite.sql.util.SqlVisitor;
75 import org.apache.calcite.sql.validate.SqlConformanceEnum;
76 import org.apache.calcite.sql.validate.SqlValidator;
79 import org.apache.calcite.tools.*;
80 import org.apache.calcite.util.Pair;
81 import org.apache.calcite.util.Util;
82 import org.slf4j.Logger;
83 import org.slf4j.LoggerFactory;
85 import java.io.IOException;
86 import java.io.PrintWriter;
87 import java.io.StringWriter;
88 import java.lang.reflect.Field;
90 import java.util.concurrent.ConcurrentHashMap;
91 import java.util.function.BiPredicate;
92 import java.util.function.Supplier;
93 import java.util.stream.Stream;
95 import ai.heavy.thrift.server.TColumnType;
96 import ai.heavy.thrift.server.TDatumType;
97 import ai.heavy.thrift.server.TEncodingType;
98 import ai.heavy.thrift.server.TTableDetails;
101 public static final ThreadLocal<HeavyDBParser>
CURRENT_PARSER =
new ThreadLocal<>();
102 private static final EnumSet<SqlKind>
SCALAR =
103 EnumSet.of(SqlKind.SCALAR_QUERY, SqlKind.SELECT);
104 private static final EnumSet<SqlKind>
EXISTS = EnumSet.of(SqlKind.EXISTS);
105 private static final EnumSet<SqlKind>
DELETE = EnumSet.of(SqlKind.DELETE);
106 private static final EnumSet<SqlKind>
UPDATE = EnumSet.of(SqlKind.UPDATE);
107 private static final EnumSet<SqlKind>
IN = EnumSet.of(SqlKind.IN);
109 EnumSet.of(SqlKind.ARRAY_VALUE_CONSTRUCTOR);
111 EnumSet.of(SqlKind.OTHER_FUNCTION);
113 final static Logger
HEAVYDBLOGGER = LoggerFactory.getLogger(HeavyDBParser.class);
132 this.sock_transport_properties = skT;
136 SubqueryCorrMemo.clear();
141 CalciteConnectionConfig config =
new CalciteConnectionConfigImpl(
new Properties()) {
143 properties.put(CalciteConnectionProperty.CASE_SENSITIVE.camelName(),
144 String.valueOf(
false));
145 properties.put(CalciteConnectionProperty.CONFORMANCE.camelName(),
146 String.valueOf(SqlConformanceEnum.LENIENT));
149 @SuppressWarnings(
"unchecked")
150 public <T extends Object>
T typeSystem(
151 java.lang.Class<
T> typeSystemClass,
T defaultTypeSystem) {
152 return (
T) myTypeSystem;
155 public boolean caseSensitive() {
159 public org.apache.calcite.sql.validate.SqlConformance conformance() {
160 return SqlConformanceEnum.LENIENT;
165 public <C> C unwrap(Class<C> aClass) {
166 if (aClass.isInstance(config)) {
167 return aClass.cast(config);
178 String queryString = expression.toSqlString(CalciteSqlDialect.DEFAULT).getSql();
179 Boolean isCorrelatedSubquery = SubqueryCorrMemo.get(queryString);
180 if (null != isCorrelatedSubquery) {
181 return isCorrelatedSubquery;
189 parser.processSql(expression, options);
190 }
catch (Exception e) {
192 SubqueryCorrMemo.put(queryString,
true);
195 SubqueryCorrMemo.put(queryString,
false);
200 switch (type.getCol_type().type) {
208 return type.col_type.encoding == TEncodingType.DICT;
217 List<String> joinColumnIdentifier,
MetaConnect mc) {
219 TTableDetails tableDetails = mc.get_table_details(joinColumnIdentifier.get(0));
221 != tableDetails.row_desc.stream()
223 -> c.col_name.toLowerCase(Locale.ROOT)
224 .equals(joinColumnIdentifier.get(1)
230 }
catch (Exception e) {
236 final boolean isWatchdogEnabled,
237 final boolean isDistributedMode) {
245 BiPredicate<SqlNode, SqlNode> expandPredicate =
new BiPredicate<SqlNode, SqlNode>() {
247 public boolean test(SqlNode
root, SqlNode expression) {
248 if (!allowSubQueryExpansion) {
252 if (expression.isA(
EXISTS) || expression.isA(
IN)) {
257 if (expression.isA(
IN)) {
263 if (expression instanceof SqlCall) {
264 SqlCall outerSelectCall = (SqlCall) expression;
265 if (outerSelectCall.getOperandList().size() == 2) {
272 if (outerSelectCall.getOperandList().get(1) instanceof SqlSelect) {
276 SqlSelect innerSelectCall =
277 (SqlSelect) outerSelectCall.getOperandList().get(1);
278 if (innerSelectCall.hasWhere()) {
284 innerSelectCall.getWhere())) {
288 if (isDistributedMode) {
293 boolean hasHashJoinableExpression =
false;
294 if (isWatchdogEnabled) {
298 Map<String, String> tableAliasMap =
new HashMap<>();
299 if (root instanceof SqlSelect) {
303 if (outerSelectCall.getOperandList().get(0) instanceof SqlIdentifier
304 && innerSelectCall.getSelectList().get(0)
305 instanceof SqlIdentifier) {
306 SqlIdentifier outerColIdentifier =
307 (SqlIdentifier) outerSelectCall.getOperandList().get(0);
308 SqlIdentifier innerColIdentifier =
309 (SqlIdentifier) innerSelectCall.getSelectList().get(0);
310 if (tableAliasMap.containsKey(outerColIdentifier.names.get(0))
311 && tableAliasMap.containsKey(
312 innerColIdentifier.names.get(0))) {
313 String outerTableName =
314 tableAliasMap.get(outerColIdentifier.names.get(0));
315 String innerTableName =
316 tableAliasMap.get(innerColIdentifier.names.get(0));
318 outerColIdentifier.names.get(1)),
321 ImmutableList.of(innerTableName,
322 innerColIdentifier.names.get(1)),
324 hasHashJoinableExpression =
true;
328 if (!hasHashJoinableExpression) {
335 if (root instanceof SqlSelect) {
336 SqlSelect selectCall = (SqlSelect) root;
338 selectCall, expression)) {
344 if (null != selectCall.getWhere()) {
346 selectCall.getWhere(), expression)) {
352 if (null != selectCall.getHaving()) {
354 selectCall.getHaving(), expression)) {
370 SqlSelect select = null;
371 if (expression instanceof SqlCall) {
372 SqlCall call = (SqlCall) expression;
373 if (call.getOperator().equals(SqlStdOperatorTable.SCALAR_QUERY)) {
374 expression = call.getOperandList().
get(0);
378 if (expression instanceof SqlSelect) {
379 select = (SqlSelect) expression;
382 if (null != select) {
383 if (null != select.getFetch() || null != select.getOffset()
384 || (null != select.getOrderList()
385 && select.getOrderList().size() != 0)) {
386 throw new CalciteException(
387 "Correlated sub-queries with ordering not supported.", null);
400 final SchemaPlus rootSchema = Frameworks.createRootSchema(
true);
401 final SchemaPlus defaultSchemaPlus = rootSchema.add(dbUser.getDB(), defaultSchema);
410 final FrameworkConfig config =
411 Frameworks.newConfigBuilder()
412 .defaultSchema(defaultSchemaPlus)
413 .operatorTable(dbSqlOperatorTable.get())
414 .parserConfig(SqlParser.configBuilder()
415 .setConformance(SqlConformanceEnum.LENIENT)
416 .setUnquotedCasing(Casing.UNCHANGED)
417 .setCaseSensitive(
false)
419 .setIdentifierMaxLength(512)
420 .setParserFactory(ExtendedSqlParser.FACTORY)
422 .sqlToRelConverterConfig(
426 .withExpandPredicate(expandPredicate)
428 .withInSubQueryThreshold(Integer.MAX_VALUE)
429 .withHintStrategyTable(
437 planner.setRestrictions(dbUser.getRestrictions());
445 public Pair<String, SqlIdentifierCapturer>
process(
447 throws SqlParseException, ValidationException, RelConversionException {
449 true, parserOptions.isWatchdogEnabled(), parserOptions.isDistributedMode());
450 final SqlNode sqlNode =
parseSql(sql, parserOptions.isLegacySyntax(), planner);
453 return new Pair<String, SqlIdentifierCapturer>(
res, capture);
461 true, parserOptions.isWatchdogEnabled(), parserOptions.isDistributedMode());
463 planner.setFilterPushDownInfo(parserOptions.getFilterPushDownInfo());
464 RelRoot optRel = planner.buildRATreeAndPerformQueryOptimization(query, schema);
466 return HeavyDBSerializer.toString(optRel.project());
470 throws SqlParseException, ValidationException, RelConversionException {
474 true, parserOptions.isWatchdogEnabled(), parserOptions.isDistributedMode());
475 final SqlNode sqlNode =
parseSql(sql, parserOptions.isLegacySyntax(), planner);
482 throws SqlParseException, ValidationException, RelConversionException {
486 return ((JsonSerializableDdl) sqlNode).toJsonString();
489 if (sqlNode instanceof SqlDdl) {
490 return sqlNode.toString();
494 true, parserOptions.isWatchdogEnabled(), parserOptions.isDistributedMode());
495 planner.advanceToValidate();
498 RelNode project = sqlRel.project();
499 if (project == null) {
500 throw new RuntimeException(
"Cannot convert the sql to AST");
502 if (parserOptions.isExplainDetail()) {
503 StringWriter sw =
new StringWriter();
505 new PrintWriter(sw), SqlExplainLevel.EXPPLAN_ATTRIBUTES,
false);
506 project.explain(planWriter);
507 return sw.toString();
508 }
else if (parserOptions.isExplain()) {
509 return RelOptUtil.toString(sqlRel.project());
511 return HeavyDBSerializer.toString(project);
515 String sql,
int cursor, List<String> visible_tables) {
516 return getPlanner().getCompletionHints(sql, cursor, visible_tables);
521 HashSet<ImmutableList<String>> resolved =
new HashSet<ImmutableList<String>>();
523 for (ImmutableList<String> names : capturer.
selects) {
528 throw new RuntimeException(
"table/view not found: " + names.get(0));
532 HeavyDBView view = (HeavyDBView) table;
543 if (node.isA(EnumSet.of(SqlKind.AS))) {
544 node = ((SqlCall) node).getOperandList().
get(1);
546 if (node instanceof SqlIdentifier) {
547 SqlIdentifier
id = (SqlIdentifier) node;
548 return id.names.get(id.names.size() - 1);
554 SqlNode where = update.getCondition();
556 if (update.getSourceExpressionList().size() != 1) {
560 if (!(update.getSourceExpressionList().get(0) instanceof SqlSelect)) {
564 final SqlSelect inner = (SqlSelect) update.getSourceExpressionList().get(0);
566 if (null != inner.getGroup() || null != inner.getFetch() || null != inner.getOffset()
567 || (null != inner.getOrderList() && inner.getOrderList().size() != 0)
568 || (null != inner.getGroup() && inner.getGroup().size() != 0)
577 final String updateTableName =
getTableName(update.getTargetTable());
580 where = where.accept(
new SqlShuttle() {
582 public SqlNode visit(SqlIdentifier
id) {
584 id =
new SqlIdentifier(Arrays.asList(updateTableName,
id.getSimple()),
585 id.getParserPosition());
593 SqlJoin
join =
new SqlJoin(ZERO,
594 update.getTargetTable(),
595 SqlLiteral.createBoolean(
false, ZERO),
596 SqlLiteral.createSymbol(
JoinType.LEFT, ZERO),
598 SqlLiteral.createSymbol(JoinConditionType.ON, ZERO),
601 SqlNode select0 = inner.getSelectList().
get(0);
603 boolean wrapInSingleValue =
true;
604 if (select0 instanceof SqlCall) {
605 SqlCall selectExprCall = (SqlCall) select0;
606 if (Util.isSingleValue(selectExprCall)) {
607 wrapInSingleValue =
false;
611 if (wrapInSingleValue) {
612 if (select0.isA(EnumSet.of(SqlKind.AS))) {
613 select0 = ((SqlCall) select0).getOperandList().
get(0);
615 select0 =
new SqlBasicCall(
616 SqlStdOperatorTable.SINGLE_VALUE,
new SqlNode[] {select0}, ZERO);
619 SqlNodeList selectList =
new SqlNodeList(ZERO);
620 selectList.add(select0);
621 selectList.add(
new SqlBasicCall(SqlStdOperatorTable.AS,
622 new SqlNode[] {
new SqlBasicCall(
623 new SqlUnresolvedFunction(
624 new SqlIdentifier(
"OFFSET_IN_FRAGMENT", ZERO),
629 SqlFunctionCategory.USER_DEFINED_FUNCTION),
632 new SqlIdentifier(
"EXPR$DELETE_OFFSET_IN_FRAGMENT", ZERO)},
635 SqlNodeList groupBy =
new SqlNodeList(ZERO);
636 groupBy.add(
new SqlIdentifier(
"EXPR$DELETE_OFFSET_IN_FRAGMENT", ZERO));
638 SqlSelect select =
new SqlSelect(ZERO,
654 throws SqlParseException, ValidationException, RelConversionException {
655 SqlIdentifier targetTable = (SqlIdentifier) update.getTargetTable();
656 String targetTableName = targetTable.toString();
658 String dummySql =
"DELETE FROM " + targetTableName;
659 SqlNode dummyNode = planner.parse(dummySql);
660 dummyNode = planner.validate(dummyNode);
661 RelRoot dummyRoot = planner.rel(dummyNode);
662 LogicalTableModify dummyModify = (LogicalTableModify) dummyRoot.rel;
668 throws SqlParseException, ValidationException, RelConversionException {
669 int correlatedQueriesCount[] =
new int[1];
670 SqlBasicVisitor<Void> correlatedQueriesCounter =
new SqlBasicVisitor<Void>() {
672 public Void visit(SqlCall call) {
674 && ((call instanceof SqlBasicCall && call.operandCount() == 1
675 && !call.operand(0).isA(SCALAR))
676 || !(call instanceof SqlBasicCall))) {
677 if (isCorrelated(call)) {
678 correlatedQueriesCount[0]++;
681 return super.visit(call);
685 update.accept(correlatedQueriesCounter);
686 if (correlatedQueriesCount[0] > 1) {
687 throw new CalciteException(
688 "table modifications with multiple correlated sub-queries not supported.",
692 boolean allowSubqueryDecorrelation =
true;
693 SqlNode updateCondition = update.getCondition();
694 if (null != updateCondition) {
695 boolean hasInClause =
696 new FindSqlOperator().containsSqlOperator(updateCondition, SqlKind.IN);
698 SqlNode updateTargetTable = update.getTargetTable();
699 if (null != updateTargetTable && updateTargetTable instanceof SqlIdentifier) {
700 SqlIdentifier targetTable = (SqlIdentifier) updateTargetTable;
701 if (targetTable.names.size() == 2) {
706 sock_transport_properties,
707 targetTable.names.get(0));
708 TTableDetails updateTargetTableDetails =
709 mc.get_table_details(targetTable.names.get(1));
710 if (null != updateTargetTableDetails
711 && updateTargetTableDetails.is_temporary) {
712 allowSubqueryDecorrelation =
false;
719 SqlNodeList sourceExpression =
new SqlNodeList(SqlParserPos.ZERO);
720 LogicalTableModify dummyModify = getDummyUpdate(update);
721 RelOptTable targetTable = dummyModify.getTable();
722 RelDataType targetTableType = targetTable.getRowType();
724 SqlSelect select = rewriteSimpleUpdateAsSelect(update);
725 boolean applyRexCast = null == select;
727 if (null == select) {
728 for (
int i = 0; i < update.getSourceExpressionList().size(); i++) {
729 SqlNode targetColumn = update.getTargetColumnList().
get(i);
730 SqlNode expression = update.getSourceExpressionList().
get(i);
732 if (!(targetColumn instanceof SqlIdentifier)) {
733 throw new RuntimeException(
"Unknown identifier type!");
735 SqlIdentifier
id = (SqlIdentifier) targetColumn;
736 RelDataType fieldType =
737 targetTableType.getField(id.names.get(id.names.size() - 1),
false,
false)
740 if (expression.isA(ARRAY_VALUE) && null != fieldType.getComponentType()) {
743 SqlDataTypeSpec elementType =
new SqlDataTypeSpec(
744 new SqlBasicTypeNameSpec(fieldType.getComponentType().getSqlTypeName(),
745 fieldType.getPrecision(),
746 fieldType.getScale(),
747 null == fieldType.getCharset() ? null
748 : fieldType.getCharset().
name(),
751 SqlCall array_expression = (SqlCall) expression;
752 ArrayList<SqlNode> values =
new ArrayList<>();
754 for (SqlNode value : array_expression.getOperandList()) {
755 if (value.isA(EnumSet.of(SqlKind.LITERAL))) {
756 SqlNode casted_value =
new SqlBasicCall(SqlStdOperatorTable.CAST,
757 new SqlNode[] {value, elementType},
758 value.getParserPosition());
759 values.add(casted_value);
766 values.toArray(
new SqlNode[0]),
767 expression.getParserPosition());
769 sourceExpression.add(expression);
772 sourceExpression.add(
new SqlBasicCall(SqlStdOperatorTable.AS,
774 new SqlBasicCall(
new SqlUnresolvedFunction(
775 new SqlIdentifier(
"OFFSET_IN_FRAGMENT",
781 SqlFunctionCategory.USER_DEFINED_FUNCTION),
784 new SqlIdentifier(
"EXPR$DELETE_OFFSET_IN_FRAGMENT", ZERO)},
787 select =
new SqlSelect(SqlParserPos.ZERO,
790 update.getTargetTable(),
791 update.getCondition(),
802 parserOptions.isWatchdogEnabled(),
803 parserOptions.isDistributedMode());
806 node = planner.parse(select.toSqlString(CalciteSqlDialect.DEFAULT).getSql());
807 node = planner.validate(node);
808 }
catch (Exception e) {
809 HEAVYDBLOGGER.error(
"Error processing UPDATE rewrite, rewritten stmt was: "
810 + select.toSqlString(CalciteSqlDialect.DEFAULT).getSql());
814 RelRoot
root = planner.rel(node);
815 LogicalProject project = (LogicalProject)
root.project();
817 ArrayList<String> fields =
new ArrayList<String>();
818 ArrayList<RexNode> nodes =
new ArrayList<RexNode>();
819 final RexBuilder builder =
new RexBuilder(planner.getTypeFactory());
821 for (SqlNode
n : update.getTargetColumnList()) {
822 if (
n instanceof SqlIdentifier) {
823 SqlIdentifier
id = (SqlIdentifier)
n;
824 fields.add(id.names.get(id.names.size() - 1));
826 throw new RuntimeException(
"Unknown identifier type!");
834 for (RexNode exp : project.getProjects()) {
835 if (applyRexCast && idx + 1 < project.getProjects().size()) {
836 RelDataType expectedFieldType =
837 targetTableType.getField(fields.get(idx),
false,
false).getType();
838 boolean is_array_kind = exp.isA(ARRAY_VALUE);
839 boolean is_func_kind = exp.isA(OTHER_FUNCTION);
842 if (!exp.getType().equals(expectedFieldType)
843 && !(is_array_kind || is_func_kind)) {
844 exp = builder.makeCast(expectedFieldType, exp);
852 ArrayList<RexNode> inputs =
new ArrayList<RexNode>();
854 for (
int i = 0; i < fields.size(); i++) {
856 new RexInputRef(
n, project.getRowType().getFieldList().
get(
n).getType()));
860 fields.add(
"EXPR$DELETE_OFFSET_IN_FRAGMENT");
861 inputs.add(
new RexInputRef(
n, project.getRowType().getFieldList().
get(
n).getType()));
863 project = project.copy(
864 project.getTraitSet(), project.getInput(), nodes, project.getRowType());
866 LogicalTableModify modify = LogicalTableModify.create(targetTable,
867 dummyModify.getCatalogReader(),
873 return RelRoot.of(modify, SqlKind.UPDATE);
877 throws SqlParseException, ValidationException, RelConversionException {
879 true, parserOptions.isWatchdogEnabled(), parserOptions.isDistributedMode());
880 final SqlNode sqlNode = parseSql(sql, parserOptions.isLegacySyntax(), planner);
881 return convertSqlToRelNode(sqlNode, planner, parserOptions);
887 throws SqlParseException, ValidationException, RelConversionException {
888 SqlNode node = sqlNode;
890 boolean allowCorrelatedSubQueryExpansion =
true;
891 boolean patchUpdateToDelete =
false;
892 if (node.isA(DELETE)) {
893 SqlDelete sqlDelete = (SqlDelete) node;
894 node =
new SqlUpdate(node.getParserPosition(),
895 sqlDelete.getTargetTable(),
898 sqlDelete.getCondition(),
899 sqlDelete.getSourceSelect(),
900 sqlDelete.getAlias());
902 patchUpdateToDelete =
true;
904 if (node.isA(UPDATE)) {
905 SqlUpdate update = (SqlUpdate) node;
906 update = (SqlUpdate) planner.validate(update);
907 RelRoot
root = rewriteUpdateAsSelect(update, parserOptions);
909 if (patchUpdateToDelete) {
910 LogicalTableModify modify = (LogicalTableModify) root.rel;
913 Field
f = TableModify.class.getDeclaredField(
"operation");
914 f.setAccessible(
true);
915 f.set(modify, Operation.DELETE);
916 }
catch (Throwable e) {
917 throw new RuntimeException(e);
920 root = RelRoot.of(modify, SqlKind.DELETE);
925 if (parserOptions.isLegacySyntax()) {
929 planner = getPlanner(allowCorrelatedSubQueryExpansion,
930 parserOptions.isWatchdogEnabled(),
931 parserOptions.isDistributedMode());
933 node.toSqlString(CalciteSqlDialect.DEFAULT).toString(),
false, planner);
936 SqlNode validateR = planner.validate(node);
937 planner.setFilterPushDownInfo(parserOptions.getFilterPushDownInfo());
939 boolean foundView =
false;
940 SqlIdentifierCapturer capturer = captureIdentifiers(sqlNode);
941 for (ImmutableList<String> names : capturer.selects) {
942 HeavyDBSchema schema =
new HeavyDBSchema(
943 dataDir,
this, dbPort, dbUser, sock_transport_properties, names.get(1));
944 HeavyDBTable table = (HeavyDBTable) schema.getTable(names.get(0));
946 throw new RuntimeException(
"table/view not found: " + names.get(0));
948 if (table instanceof HeavyDBView) {
952 RelRoot relRootNode = planner.getRelRoot(validateR);
953 relRootNode = replaceIsTrue(planner.getTypeFactory(), relRootNode);
954 RelNode rootNode = planner.optimizeRATree(
955 relRootNode.project(), parserOptions.isViewOptimizeEnabled(), foundView);
957 return new RelRoot(rootNode,
958 relRootNode.validatedRowType,
961 relRootNode.collation,
962 Collections.emptyList());
966 final RexShuttle callShuttle =
new RexShuttle() {
967 RexBuilder builder =
new RexBuilder(typeFactory);
969 public RexNode visitCall(RexCall call) {
970 call = (RexCall) super.visitCall(call);
971 if (call.getKind() == SqlKind.IS_TRUE) {
972 return builder.makeCall(SqlStdOperatorTable.AND,
974 SqlStdOperatorTable.IS_NOT_NULL, call.getOperands().
get(0)),
975 call.getOperands().get(0));
976 }
else if (call.getKind() == SqlKind.IS_NOT_TRUE) {
977 return builder.makeCall(SqlStdOperatorTable.OR,
979 SqlStdOperatorTable.IS_NULL, call.getOperands().
get(0)),
980 builder.makeCall(SqlStdOperatorTable.NOT, call.getOperands().get(0)));
981 }
else if (call.getKind() == SqlKind.IS_FALSE) {
982 return builder.makeCall(SqlStdOperatorTable.AND,
984 SqlStdOperatorTable.IS_NOT_NULL, call.getOperands().
get(0)),
985 builder.makeCall(SqlStdOperatorTable.NOT, call.getOperands().get(0)));
986 }
else if (call.getKind() == SqlKind.IS_NOT_FALSE) {
987 return builder.makeCall(SqlStdOperatorTable.OR,
989 SqlStdOperatorTable.IS_NULL, call.getOperands().
get(0)),
990 call.getOperands().get(0));
997 RelNode node = root.rel.accept(
new RelShuttleImpl() {
999 protected RelNode visitChild(RelNode parent,
int i, RelNode child) {
1000 RelNode node = super.visitChild(parent, i, child);
1001 return node.accept(callShuttle);
1005 return new RelRoot(node,
1006 root.validatedRowType,
1010 Collections.emptyList());
1013 private SqlNode
parseSql(String sql,
final boolean legacy_syntax, Planner planner)
1014 throws SqlParseException {
1015 SqlNode parseR = null;
1017 parseR = planner.parse(sql);
1018 HEAVYDBLOGGER.debug(
" node is \n" + parseR.toString());
1019 }
catch (SqlParseException ex) {
1020 HEAVYDBLOGGER.error(
"failed to parse SQL '" + sql +
"' \n" + ex.toString());
1024 if (!legacy_syntax) {
1028 RelDataTypeFactory typeFactory = planner.getTypeFactory();
1029 SqlSelect select_node = null;
1030 if (parseR instanceof SqlSelect) {
1031 select_node = (SqlSelect) parseR;
1032 desugar(select_node, typeFactory);
1033 }
else if (parseR instanceof SqlOrderBy) {
1034 SqlOrderBy order_by_node = (SqlOrderBy) parseR;
1035 if (order_by_node.query instanceof SqlSelect) {
1036 select_node = (SqlSelect) order_by_node.query;
1037 SqlOrderBy new_order_by_node = desugar(select_node, order_by_node, typeFactory);
1038 if (new_order_by_node != null) {
1039 return new_order_by_node;
1041 }
else if (order_by_node.query instanceof SqlWith) {
1042 SqlWith old_with_node = (SqlWith) order_by_node.query;
1043 if (old_with_node.body instanceof SqlSelect) {
1044 select_node = (SqlSelect) old_with_node.body;
1045 desugar(select_node, typeFactory);
1048 }
else if (parseR instanceof SqlWith) {
1049 SqlWith old_with_node = (SqlWith) parseR;
1050 if (old_with_node.body instanceof SqlSelect) {
1051 select_node = (SqlSelect) old_with_node.body;
1052 desugar(select_node, typeFactory);
1058 private void desugar(SqlSelect select_node, RelDataTypeFactory typeFactory) {
1059 desugar(select_node, null, typeFactory);
1062 private SqlNode
expandCase(SqlCase old_case_node, RelDataTypeFactory typeFactory) {
1063 SqlNodeList newWhenList =
1064 new SqlNodeList(old_case_node.getWhenOperands().getParserPosition());
1065 SqlNodeList newThenList =
1066 new SqlNodeList(old_case_node.getThenOperands().getParserPosition());
1067 java.util.Map<String, SqlNode> id_to_expr =
new java.util.HashMap<String, SqlNode>();
1068 for (SqlNode node : old_case_node.getWhenOperands()) {
1069 SqlNode newCall = expand(node, id_to_expr, typeFactory);
1070 if (null != newCall) {
1071 newWhenList.add(newCall);
1073 newWhenList.add(node);
1076 for (SqlNode node : old_case_node.getThenOperands()) {
1077 SqlNode newCall = expand(node, id_to_expr, typeFactory);
1078 if (null != newCall) {
1079 newThenList.add(newCall);
1081 newThenList.add(node);
1084 SqlNode new_else_operand = old_case_node.getElseOperand();
1085 if (null != new_else_operand) {
1086 SqlNode candidate_else_operand =
1087 expand(old_case_node.getElseOperand(), id_to_expr, typeFactory);
1088 if (null != candidate_else_operand) {
1089 new_else_operand = candidate_else_operand;
1092 SqlNode new_value_operand = old_case_node.getValueOperand();
1093 if (null != new_value_operand) {
1094 SqlNode candidate_value_operand =
1095 expand(old_case_node.getValueOperand(), id_to_expr, typeFactory);
1096 if (null != candidate_value_operand) {
1097 new_value_operand = candidate_value_operand;
1100 SqlNode newCaseNode = SqlCase.createSwitched(old_case_node.getParserPosition(),
1109 SqlOrderBy order_by_node,
1110 RelDataTypeFactory typeFactory) {
1111 HEAVYDBLOGGER.debug(
"desugar: before: " + select_node.toString());
1112 desugarExpression(select_node.getFrom(), typeFactory);
1113 desugarExpression(select_node.getWhere(), typeFactory);
1114 SqlNodeList select_list = select_node.getSelectList();
1115 SqlNodeList new_select_list =
new SqlNodeList(select_list.getParserPosition());
1116 java.util.Map<String, SqlNode> id_to_expr =
new java.util.HashMap<String, SqlNode>();
1117 for (SqlNode proj : select_list) {
1118 if (!(proj instanceof SqlBasicCall)) {
1119 if (proj instanceof SqlCase) {
1120 new_select_list.add(expandCase((SqlCase) proj, typeFactory));
1122 new_select_list.add(proj);
1125 assert proj instanceof SqlBasicCall;
1126 SqlBasicCall proj_call = (SqlBasicCall) proj;
1127 if (proj_call.operands.length > 0) {
1128 for (
int i = 0; i < proj_call.operands.length; i++) {
1129 if (proj_call.operand(i) instanceof SqlCase) {
1130 SqlNode new_op = expandCase(proj_call.operand(i), typeFactory);
1131 proj_call.setOperand(i, new_op);
1135 new_select_list.add(expand(proj_call, id_to_expr, typeFactory));
1138 select_node.setSelectList(new_select_list);
1139 SqlNodeList group_by_list = select_node.getGroup();
1140 if (group_by_list != null) {
1141 select_node.setGroupBy(expand(group_by_list, id_to_expr, typeFactory));
1143 SqlNode having = select_node.getHaving();
1144 if (having != null) {
1145 expand(having, id_to_expr, typeFactory);
1147 SqlOrderBy new_order_by_node = null;
1148 if (order_by_node != null && order_by_node.orderList != null
1149 && order_by_node.orderList.size() > 0) {
1150 SqlNodeList new_order_by_list =
1151 expand(order_by_node.orderList, id_to_expr, typeFactory);
1152 new_order_by_node =
new SqlOrderBy(order_by_node.getParserPosition(),
1155 order_by_node.offset,
1156 order_by_node.fetch);
1159 HEAVYDBLOGGER.debug(
"desugar: after: " + select_node.toString());
1160 return new_order_by_node;
1164 if (node instanceof SqlSelect) {
1165 desugar((SqlSelect) node, typeFactory);
1168 if (!(node instanceof SqlBasicCall)) {
1171 SqlBasicCall basic_call = (SqlBasicCall) node;
1172 for (SqlNode
operator : basic_call.getOperands()) {
1173 if (
operator instanceof SqlOrderBy) {
1174 desugarExpression(((SqlOrderBy)
operator).query, typeFactory);
1176 desugarExpression(
operator, typeFactory);
1182 final java.util.Map<String, SqlNode> id_to_expr,
1183 RelDataTypeFactory typeFactory) {
1184 HEAVYDBLOGGER.debug(
"expand: " + node.toString());
1185 if (node instanceof SqlBasicCall) {
1186 SqlBasicCall node_call = (SqlBasicCall) node;
1187 SqlNode[] operands = node_call.getOperands();
1188 for (
int i = 0; i < operands.length; ++i) {
1189 node_call.setOperand(i, expand(operands[i], id_to_expr, typeFactory));
1191 SqlNode expanded_string_function = expandStringFunctions(node_call, typeFactory);
1192 if (expanded_string_function != null) {
1193 return expanded_string_function;
1195 SqlNode expanded_variance = expandVariance(node_call, typeFactory);
1196 if (expanded_variance != null) {
1197 return expanded_variance;
1199 SqlNode expanded_covariance = expandCovariance(node_call, typeFactory);
1200 if (expanded_covariance != null) {
1201 return expanded_covariance;
1203 SqlNode expanded_correlation = expandCorrelation(node_call, typeFactory);
1204 if (expanded_correlation != null) {
1205 return expanded_correlation;
1208 if (node instanceof SqlSelect) {
1209 SqlSelect select_node = (SqlSelect) node;
1210 desugar(select_node, typeFactory);
1215 private SqlNodeList
expand(
final SqlNodeList group_by_list,
1216 final java.util.Map<String, SqlNode> id_to_expr,
1217 RelDataTypeFactory typeFactory) {
1218 SqlNodeList new_group_by_list =
new SqlNodeList(
new SqlParserPos(-1, -1));
1219 for (SqlNode group_by : group_by_list) {
1220 if (!(group_by instanceof SqlIdentifier)) {
1221 new_group_by_list.add(expand(group_by, id_to_expr, typeFactory));
1224 SqlIdentifier group_by_id = ((SqlIdentifier) group_by);
1225 if (id_to_expr.containsKey(group_by_id.toString())) {
1226 new_group_by_list.add(id_to_expr.get(group_by_id.toString()));
1228 new_group_by_list.add(group_by);
1231 return new_group_by_list;
1235 final SqlBasicCall proj_call, RelDataTypeFactory typeFactory) {
1240 final int operandCount = proj_call.operandCount();
1242 if (proj_call.getOperator().isName(
"MID",
false)
1243 || proj_call.getOperator().isName(
"SUBSTR",
false)) {
1248 final SqlParserPos pos = proj_call.getParserPosition();
1249 if (operandCount == 2) {
1250 final SqlNode primary_operand = proj_call.operand(0);
1251 final SqlNode from_operand = proj_call.operand(1);
1252 return SqlStdOperatorTable.SUBSTRING.createCall(
1253 pos, primary_operand, from_operand);
1255 }
else if (operandCount == 3) {
1256 final SqlNode primary_operand = proj_call.operand(0);
1257 final SqlNode from_operand = proj_call.operand(1);
1258 final SqlNode for_operand = proj_call.operand(2);
1259 return SqlStdOperatorTable.SUBSTRING.createCall(
1260 pos, primary_operand, from_operand, for_operand);
1264 }
else if (proj_call.getOperator().isName(
"CONTAINS",
false)) {
1267 final SqlParserPos pos = proj_call.getParserPosition();
1268 if (operandCount == 2) {
1269 final SqlNode primary = proj_call.operand(0);
1270 final SqlNode pattern = proj_call.operand(1);
1272 if (pattern instanceof SqlLiteral) {
1274 SqlLiteral literalPattern = (SqlLiteral) pattern;
1275 String sPattern = literalPattern.getValueAs(String.class);
1276 SqlLiteral withWildcards =
1277 SqlLiteral.createCharString(
"%" + sPattern +
"%", pos);
1278 return SqlStdOperatorTable.LIKE.createCall(pos, primary, withWildcards);
1283 }
else if (proj_call.getOperator().isName(
"ENDSWITH",
false)) {
1285 final SqlParserPos pos = proj_call.getParserPosition();
1286 if (operandCount == 2) {
1287 final SqlNode primary = proj_call.operand(0);
1288 final SqlNode pattern = proj_call.operand(1);
1290 if (pattern instanceof SqlLiteral) {
1292 SqlLiteral literalPattern = (SqlLiteral) pattern;
1293 String sPattern = literalPattern.getValueAs(String.class);
1294 SqlLiteral withWildcards = SqlLiteral.createCharString(
"%" + sPattern, pos);
1295 return SqlStdOperatorTable.LIKE.createCall(pos, primary, withWildcards);
1299 }
else if (proj_call.getOperator().isName(
"LCASE",
false)) {
1301 final SqlParserPos pos = proj_call.getParserPosition();
1302 if (operandCount == 1) {
1303 final SqlNode primary = proj_call.operand(0);
1304 return SqlStdOperatorTable.LOWER.createCall(pos, primary);
1308 }
else if (proj_call.getOperator().isName(
"LEFT",
false)) {
1310 final SqlParserPos pos = proj_call.getParserPosition();
1312 if (operandCount == 2) {
1313 final SqlNode primary = proj_call.operand(0);
1314 SqlNode start = SqlLiteral.createExactNumeric(
"0", SqlParserPos.ZERO);
1315 final SqlNode count = proj_call.operand(1);
1316 return SqlStdOperatorTable.SUBSTRING.createCall(pos, primary, start, count);
1320 }
else if (proj_call.getOperator().isName(
"LEN",
false)) {
1322 final SqlParserPos pos = proj_call.getParserPosition();
1323 if (operandCount == 1) {
1324 final SqlNode primary = proj_call.operand(0);
1325 return SqlStdOperatorTable.CHARACTER_LENGTH.createCall(pos, primary);
1329 }
else if (proj_call.getOperator().isName(
"MAX",
false)
1330 || proj_call.getOperator().isName(
"MIN",
false)) {
1332 final SqlParserPos pos = proj_call.getParserPosition();
1334 if (operandCount == 2) {
1335 final SqlNode arg1 = proj_call.operand(0);
1336 final SqlNode arg2 = proj_call.operand(1);
1338 SqlNodeList whenList =
new SqlNodeList(pos);
1339 SqlNodeList thenList =
new SqlNodeList(pos);
1340 SqlNodeList elseClause =
new SqlNodeList(pos);
1342 if (proj_call.getOperator().isName(
"MAX",
false)) {
1344 SqlStdOperatorTable.GREATER_THAN_OR_EQUAL.createCall(pos, arg1, arg2));
1347 SqlStdOperatorTable.LESS_THAN_OR_EQUAL.createCall(pos, arg1, arg2));
1350 elseClause.add(arg2);
1352 SqlNode caseIdentifier = null;
1353 return SqlCase.createSwitched(
1354 pos, caseIdentifier, whenList, thenList, elseClause);
1358 }
else if (proj_call.getOperator().isName(
"RIGHT",
false)) {
1360 final SqlParserPos pos = proj_call.getParserPosition();
1362 if (operandCount == 2) {
1363 final SqlNode primary = proj_call.operand(0);
1364 final SqlNode count = proj_call.operand(1);
1365 if (count instanceof SqlNumericLiteral) {
1366 SqlNumericLiteral numericCount = (SqlNumericLiteral) count;
1367 if (numericCount.intValue(
true) > 0) {
1369 final SqlNode negativeCount =
1370 SqlNumericLiteral.createNegative(numericCount, pos);
1371 return SqlStdOperatorTable.SUBSTRING.createCall(pos, primary, negativeCount);
1375 SqlNode zero = SqlLiteral.createExactNumeric(
"0", SqlParserPos.ZERO);
1376 return SqlStdOperatorTable.SUBSTRING.createCall(pos, primary, zero, zero);
1380 return SqlStdOperatorTable.SUBSTRING.createCall(pos, primary, count);
1384 }
else if (proj_call.getOperator().isName(
"SPACE",
false)) {
1386 final SqlParserPos pos = proj_call.getParserPosition();
1387 if (operandCount == 1) {
1388 final SqlNode count = proj_call.operand(0);
1389 SqlFunction fn_repeat =
new SqlFunction(
"REPEAT",
1390 SqlKind.OTHER_FUNCTION,
1391 ReturnTypes.ARG0_NULLABLE,
1393 OperandTypes.CHARACTER,
1394 SqlFunctionCategory.STRING);
1395 SqlLiteral space = SqlLiteral.createCharString(
" ", pos);
1396 return fn_repeat.createCall(pos, space, count);
1400 }
else if (proj_call.getOperator().isName(
"SPLIT",
false)) {
1402 final SqlParserPos pos = proj_call.getParserPosition();
1403 if (operandCount == 3) {
1404 final SqlNode primary = proj_call.operand(0);
1405 final SqlNode delimeter = proj_call.operand(1);
1406 final SqlNode count = proj_call.operand(2);
1407 SqlFunction fn_split =
new SqlFunction(
"SPLIT_PART",
1408 SqlKind.OTHER_FUNCTION,
1409 ReturnTypes.ARG0_NULLABLE,
1411 OperandTypes.CHARACTER,
1412 SqlFunctionCategory.STRING);
1414 return fn_split.createCall(pos, primary, delimeter, count);
1418 }
else if (proj_call.getOperator().isName(
"STARTSWITH",
false)) {
1420 final SqlParserPos pos = proj_call.getParserPosition();
1421 if (operandCount == 2) {
1422 final SqlNode primary = proj_call.operand(0);
1423 final SqlNode pattern = proj_call.operand(1);
1425 if (pattern instanceof SqlLiteral) {
1427 SqlLiteral literalPattern = (SqlLiteral) pattern;
1428 String sPattern = literalPattern.getValueAs(String.class);
1429 SqlLiteral withWildcards = SqlLiteral.createCharString(sPattern +
"%", pos);
1430 return SqlStdOperatorTable.LIKE.createCall(pos, primary, withWildcards);
1435 }
else if (proj_call.getOperator().isName(
"UCASE",
false)) {
1437 final SqlParserPos pos = proj_call.getParserPosition();
1438 if (operandCount == 1) {
1439 final SqlNode primary = proj_call.operand(0);
1440 return SqlStdOperatorTable.UPPER.createCall(pos, primary);
1449 final SqlBasicCall proj_call, RelDataTypeFactory typeFactory) {
1451 if (proj_call.operandCount() != 1) {
1457 if (proj_call.getOperator().isName(
"STDDEV_POP",
false)) {
1461 }
else if (proj_call.getOperator().getName().equalsIgnoreCase(
"STDDEV_POP_FLOAT")) {
1465 }
else if (proj_call.getOperator().isName(
"STDDEV_SAMP",
false)
1466 || proj_call.getOperator().getName().equalsIgnoreCase(
"STDDEV")) {
1470 }
else if (proj_call.getOperator().getName().equalsIgnoreCase(
"STDDEV_SAMP_FLOAT")
1471 || proj_call.getOperator().getName().equalsIgnoreCase(
"STDDEV_FLOAT")) {
1475 }
else if (proj_call.getOperator().isName(
"VAR_POP",
false)) {
1479 }
else if (proj_call.getOperator().getName().equalsIgnoreCase(
"VAR_POP_FLOAT")) {
1483 }
else if (proj_call.getOperator().isName(
"VAR_SAMP",
false)
1484 || proj_call.getOperator().getName().equalsIgnoreCase(
"VARIANCE")) {
1488 }
else if (proj_call.getOperator().getName().equalsIgnoreCase(
"VAR_SAMP_FLOAT")
1489 || proj_call.getOperator().getName().equalsIgnoreCase(
"VARIANCE_FLOAT")) {
1496 final SqlNode operand = proj_call.operand(0);
1497 final SqlParserPos pos = proj_call.getParserPosition();
1498 SqlNode expanded_proj_call =
1499 expandVariance(pos, operand, biased, sqrt, flt, typeFactory);
1500 HEAVYDBLOGGER.debug(
"Expanded select_list SqlCall: " + proj_call.toString());
1501 HEAVYDBLOGGER.debug(
"to : " + expanded_proj_call.toString());
1502 return expanded_proj_call;
1506 final SqlNode operand,
1510 RelDataTypeFactory typeFactory) {
1531 final SqlNode arg = SqlStdOperatorTable.CAST.createCall(pos,
1533 SqlTypeUtil.convertTypeToSpec(typeFactory.createSqlType(
1534 flt ? SqlTypeName.FLOAT : SqlTypeName.DOUBLE)));
1535 final SqlNode argSquared = SqlStdOperatorTable.MULTIPLY.createCall(pos, arg, arg);
1536 final SqlNode sumArgSquared = SqlStdOperatorTable.SUM.createCall(pos, argSquared);
1537 final SqlNode sum = SqlStdOperatorTable.SUM.createCall(pos, arg);
1538 final SqlNode sumSquared = SqlStdOperatorTable.MULTIPLY.createCall(pos, sum, sum);
1539 final SqlNode count = SqlStdOperatorTable.COUNT.createCall(pos, arg);
1540 final SqlLiteral nul = SqlLiteral.createNull(pos);
1541 final SqlNumericLiteral zero = SqlLiteral.createExactNumeric(
"0", pos);
1542 final SqlNode countEqZero = SqlStdOperatorTable.EQUALS.createCall(pos, count, zero);
1543 SqlNodeList whenList =
new SqlNodeList(pos);
1544 SqlNodeList thenList =
new SqlNodeList(pos);
1545 whenList.add(countEqZero);
1547 final SqlNode int_denominator = SqlStdOperatorTable.CASE.createCall(
1548 null, pos, null, whenList, thenList, count);
1549 final SqlNode denominator = SqlStdOperatorTable.CAST.createCall(pos,
1551 SqlTypeUtil.convertTypeToSpec(typeFactory.createSqlType(
1552 flt ? SqlTypeName.FLOAT : SqlTypeName.DOUBLE)));
1553 final SqlNode avgSumSquared =
1554 SqlStdOperatorTable.DIVIDE.createCall(pos, sumSquared, denominator);
1555 final SqlNode diff =
1556 SqlStdOperatorTable.MINUS.createCall(pos, sumArgSquared, avgSumSquared);
1557 final SqlNode denominator1;
1559 denominator1 = denominator;
1561 final SqlNumericLiteral one = SqlLiteral.createExactNumeric(
"1", pos);
1562 final SqlNode countEqOne = SqlStdOperatorTable.EQUALS.createCall(pos, count, one);
1563 final SqlNode countMinusOne = SqlStdOperatorTable.MINUS.createCall(pos, count, one);
1564 SqlNodeList whenList1 =
new SqlNodeList(pos);
1565 SqlNodeList thenList1 =
new SqlNodeList(pos);
1566 whenList1.add(countEqOne);
1568 final SqlNode int_denominator1 = SqlStdOperatorTable.CASE.createCall(
1569 null, pos, null, whenList1, thenList1, countMinusOne);
1570 denominator1 = SqlStdOperatorTable.CAST.createCall(pos,
1572 SqlTypeUtil.convertTypeToSpec(typeFactory.createSqlType(
1573 flt ? SqlTypeName.FLOAT : SqlTypeName.DOUBLE)));
1575 final SqlNode div = SqlStdOperatorTable.DIVIDE.createCall(pos, diff, denominator1);
1578 final SqlNumericLiteral half = SqlLiteral.createExactNumeric(
"0.5", pos);
1579 result = SqlStdOperatorTable.POWER.createCall(pos, div, half);
1581 return SqlStdOperatorTable.CAST.createCall(pos,
1583 SqlTypeUtil.convertTypeToSpec(typeFactory.createSqlType(
1584 flt ? SqlTypeName.FLOAT : SqlTypeName.DOUBLE)));
1588 final SqlBasicCall proj_call, RelDataTypeFactory typeFactory) {
1590 if (proj_call.operandCount() != 2) {
1595 if (proj_call.getOperator().isName(
"COVAR_POP",
false)) {
1598 }
else if (proj_call.getOperator().isName(
"COVAR_SAMP",
false)) {
1601 }
else if (proj_call.getOperator().getName().equalsIgnoreCase(
"COVAR_POP_FLOAT")) {
1604 }
else if (proj_call.getOperator().getName().equalsIgnoreCase(
"COVAR_SAMP_FLOAT")) {
1610 final SqlNode operand0 = proj_call.operand(0);
1611 final SqlNode operand1 = proj_call.operand(1);
1612 final SqlParserPos pos = proj_call.getParserPosition();
1613 SqlNode expanded_proj_call =
1614 expandCovariance(pos, operand0, operand1, pop, flt, typeFactory);
1615 HEAVYDBLOGGER.debug(
"Expanded select_list SqlCall: " + proj_call.toString());
1616 HEAVYDBLOGGER.debug(
"to : " + expanded_proj_call.toString());
1617 return expanded_proj_call;
1621 final SqlNode operand0,
1622 final SqlNode operand1,
1625 RelDataTypeFactory typeFactory) {
1629 final SqlNode arg0 = SqlStdOperatorTable.CAST.createCall(operand0.getParserPosition(),
1631 SqlTypeUtil.convertTypeToSpec(typeFactory.createSqlType(
1632 flt ? SqlTypeName.FLOAT : SqlTypeName.DOUBLE)));
1633 final SqlNode arg1 = SqlStdOperatorTable.CAST.createCall(operand1.getParserPosition(),
1635 SqlTypeUtil.convertTypeToSpec(typeFactory.createSqlType(
1636 flt ? SqlTypeName.FLOAT : SqlTypeName.DOUBLE)));
1637 final SqlNode mulArg = SqlStdOperatorTable.MULTIPLY.createCall(pos, arg0, arg1);
1638 final SqlNode avgArg1 = SqlStdOperatorTable.AVG.createCall(pos, arg1);
1640 final SqlNode avgMulArg = SqlStdOperatorTable.AVG.createCall(pos, mulArg);
1641 final SqlNode avgArg0 = SqlStdOperatorTable.AVG.createCall(pos, arg0);
1642 final SqlNode mulAvgAvg =
1643 SqlStdOperatorTable.MULTIPLY.createCall(pos, avgArg0, avgArg1);
1644 final SqlNode covarPop =
1645 SqlStdOperatorTable.MINUS.createCall(pos, avgMulArg, mulAvgAvg);
1646 return SqlStdOperatorTable.CAST.createCall(pos,
1648 SqlTypeUtil.convertTypeToSpec(typeFactory.createSqlType(
1649 flt ? SqlTypeName.FLOAT : SqlTypeName.DOUBLE)));
1651 final SqlNode sumMulArg = SqlStdOperatorTable.SUM.createCall(pos, mulArg);
1652 final SqlNode sumArg0 = SqlStdOperatorTable.SUM.createCall(pos, arg0);
1653 final SqlNode mulSumAvg =
1654 SqlStdOperatorTable.MULTIPLY.createCall(pos, sumArg0, avgArg1);
1655 final SqlNode sub = SqlStdOperatorTable.MINUS.createCall(pos, sumMulArg, mulSumAvg);
1656 final SqlNode count = SqlStdOperatorTable.COUNT.createCall(pos, operand0);
1657 final SqlNumericLiteral one = SqlLiteral.createExactNumeric(
"1", pos);
1658 final SqlNode countEqOne = SqlStdOperatorTable.EQUALS.createCall(pos, count, one);
1659 final SqlNode countMinusOne = SqlStdOperatorTable.MINUS.createCall(pos, count, one);
1660 final SqlLiteral nul = SqlLiteral.createNull(pos);
1661 SqlNodeList whenList1 =
new SqlNodeList(pos);
1662 SqlNodeList thenList1 =
new SqlNodeList(pos);
1663 whenList1.add(countEqOne);
1665 final SqlNode int_denominator = SqlStdOperatorTable.CASE.createCall(
1666 null, pos, null, whenList1, thenList1, countMinusOne);
1667 final SqlNode denominator = SqlStdOperatorTable.CAST.createCall(pos,
1669 SqlTypeUtil.convertTypeToSpec(typeFactory.createSqlType(
1670 flt ? SqlTypeName.FLOAT : SqlTypeName.DOUBLE)));
1671 final SqlNode covarSamp =
1672 SqlStdOperatorTable.DIVIDE.createCall(pos, sub, denominator);
1673 return SqlStdOperatorTable.CAST.createCall(pos,
1675 SqlTypeUtil.convertTypeToSpec(typeFactory.createSqlType(
1676 flt ? SqlTypeName.FLOAT : SqlTypeName.DOUBLE)));
1680 final SqlBasicCall proj_call, RelDataTypeFactory typeFactory) {
1682 if (proj_call.operandCount() != 2) {
1686 if (proj_call.getOperator().isName(
"CORR",
false)
1687 || proj_call.getOperator().getName().equalsIgnoreCase(
"CORRELATION")) {
1690 }
else if (proj_call.getOperator().getName().equalsIgnoreCase(
"CORR_FLOAT")
1691 || proj_call.getOperator().getName().equalsIgnoreCase(
"CORRELATION_FLOAT")) {
1700 final SqlNode operand0 = proj_call.operand(0);
1701 final SqlNode operand1 = proj_call.operand(1);
1702 final SqlParserPos pos = proj_call.getParserPosition();
1703 SqlNode covariance =
1704 expandCovariance(pos, operand0, operand1,
true, flt, typeFactory);
1705 SqlNode stddev0 = expandVariance(pos, operand0,
true,
true, flt, typeFactory);
1706 SqlNode stddev1 = expandVariance(pos, operand1,
true,
true, flt, typeFactory);
1707 final SqlNode mulStddev =
1708 SqlStdOperatorTable.MULTIPLY.createCall(pos, stddev0, stddev1);
1709 final SqlNumericLiteral zero = SqlLiteral.createExactNumeric(
"0.0", pos);
1710 final SqlNode mulStddevEqZero =
1711 SqlStdOperatorTable.EQUALS.createCall(pos, mulStddev, zero);
1712 final SqlLiteral nul = SqlLiteral.createNull(pos);
1713 SqlNodeList whenList1 =
new SqlNodeList(pos);
1714 SqlNodeList thenList1 =
new SqlNodeList(pos);
1715 whenList1.add(mulStddevEqZero);
1717 final SqlNode denominator = SqlStdOperatorTable.CASE.createCall(
1718 null, pos, null, whenList1, thenList1, mulStddev);
1719 final SqlNode expanded_proj_call =
1720 SqlStdOperatorTable.DIVIDE.createCall(pos, covariance, denominator);
1721 HEAVYDBLOGGER.debug(
"Expanded select_list SqlCall: " + proj_call.toString());
1722 HEAVYDBLOGGER.debug(
"to : " + expanded_proj_call.toString());
1723 return expanded_proj_call;
1727 throws SqlParseException {
1729 Planner planner = getPlanner();
1730 SqlNode node = parseSql(sql, legacy_syntax, planner);
1731 return captureIdentifiers(node);
1732 }
catch (Exception | Error e) {
1733 HEAVYDBLOGGER.error(
"Error parsing sql: " + sql, e);
1741 capturer.scan(node);
1742 capturer.selects = addDbContextIfMissing(capturer.
selects);
1743 capturer.updates = addDbContextIfMissing(capturer.
updates);
1744 capturer.deletes = addDbContextIfMissing(capturer.
deletes);
1745 capturer.inserts = addDbContextIfMissing(capturer.
inserts);
1747 }
catch (Exception | Error e) {
1748 HEAVYDBLOGGER.error(
"Error parsing sql: " + node, e);
1754 Set<ImmutableList<String>> names) {
1755 Set<ImmutableList<String>>
result =
new HashSet<>();
1756 for (ImmutableList<String>
name : names) {
1757 if (
name.size() == 1) {
1758 result.add(
new ImmutableList.Builder<String>()
1760 .add(dbUser.getDB())
1774 HEAVYDBLOGGER.debug(
"schema :" + schema +
" table :" + table);
1776 dataDir,
this, dbPort, null, sock_transport_properties, schema);
1777 db.updateMetaData(schema, table);
1786 extends SqlBasicVisitor<Void> {
1789 if (call instanceof SqlSelect) {
1790 SqlSelect selectNode = (SqlSelect) call;
1791 String targetString = targetExpression.toString();
1792 for (SqlNode listedNode : selectNode.getSelectList()) {
1793 if (listedNode.toString().contains(targetString)) {
1794 throw Util.FoundOne.NULL;
1798 return super.visit(call);
1803 this.targetExpression = targetExpression;
1806 }
catch (Util.FoundOne e) {
1815 extends SqlBasicVisitor<Void> {
1818 if (call instanceof SqlBasicCall) {
1819 SqlBasicCall basicCall = (SqlBasicCall) call;
1820 if (basicCall.getKind() == SqlKind.OR) {
1821 String targetString = targetExpression.toString();
1822 for (SqlNode listedOperand : basicCall.operands) {
1823 if (listedOperand.toString().contains(targetString)) {
1824 throw Util.FoundOne.NULL;
1829 return super.visit(call);
1834 this.targetExpression = targetExpression;
1837 }
catch (Util.FoundOne e) {
1846 Set<SqlBasicCall> targetCalls =
new HashSet<>();
1849 if (null != basicCall) {
1850 if (basicCall.operands.length == 2
1851 && (basicCall.getKind() == SqlKind.EQUALS
1852 || basicCall.getKind() == SqlKind.NOT_EQUALS)
1853 && basicCall.operand(0) instanceof SqlIdentifier
1854 && basicCall.operand(1) instanceof SqlIdentifier) {
1863 if (call instanceof SqlBasicCall) {
1864 targetCalls.add((SqlBasicCall) call);
1866 for (SqlNode node : call.getOperandList()) {
1867 if (null != node && !targetCalls.contains(node)) {
1871 return super.visit(call);
1878 for (SqlBasicCall basicCall : targetCalls) {
1879 if (isEqualityJoinOperator(basicCall)) {
1880 throw Util.FoundOne.NULL;
1885 }
catch (Util.FoundOne e) {
1897 if (call instanceof SqlBasicCall) {
1898 SqlBasicCall basicCall = (SqlBasicCall) call;
1899 if (basicCall.getKind().equals(targetKind)) {
1900 throw Util.FoundOne.NULL;
1903 return super.visit(call);
1908 targetKind = operatorKind;
1911 }
catch (Util.FoundOne e) {
1920 final SqlVisitor<Void> aliasCollector =
new SqlBasicVisitor<Void>() {
1922 public Void visit(SqlCall call) {
1923 if (call instanceof SqlBasicCall) {
1924 SqlBasicCall basicCall = (SqlBasicCall) call;
1925 if (basicCall.getKind() == SqlKind.AS) {
1926 if (basicCall.operand(0) instanceof SqlIdentifier) {
1929 SqlIdentifier colNameIdentifier = (SqlIdentifier) basicCall.operand(0);
1930 String tblName = colNameIdentifier.names.size() == 1
1931 ? colNameIdentifier.names.get(0)
1932 : colNameIdentifier.names.get(1);
1933 tableAliasMap.put(basicCall.operand(1).
toString(), tblName);
1937 return super.visit(call);
1940 sqlNode.accept(aliasCollector);
void desugarExpression(SqlNode node, RelDataTypeFactory typeFactory)
boolean containsExpression(SqlNode node, SqlNode targetExpression)
SqlIdentifierCapturer captureIdentifiers(SqlNode node)
static final Logger HEAVYDBLOGGER
SqlNode expandCovariance(final SqlBasicCall proj_call, RelDataTypeFactory typeFactory)
SqlNode expandVariance(final SqlBasicCall proj_call, RelDataTypeFactory typeFactory)
SqlSelect rewriteSimpleUpdateAsSelect(final SqlUpdate update)
SqlOrderBy desugar(SqlSelect select_node, SqlOrderBy order_by_node, RelDataTypeFactory typeFactory)
boolean containsExpression(SqlNode node, SqlNode targetExpression)
Set< ImmutableList< String > > deletes
RelRoot replaceIsTrue(final RelDataTypeFactory typeFactory, RelRoot root)
SqlNode expandCase(SqlCase old_case_node, RelDataTypeFactory typeFactory)
SqlNode parseSql(String sql, final boolean legacy_syntax, Planner planner)
static final EnumSet< SqlKind > ARRAY_VALUE
Set< ImmutableList< String > > updates
void setUser(HeavyDBUser dbUser)
Table getTable(String string)
boolean isColumnHashJoinable(List< String > joinColumnIdentifier, MetaConnect mc)
HashSet< ImmutableList< String > > resolveSelectIdentifiers(SqlIdentifierCapturer capturer)
boolean containsExpression(SqlNode node)
SqlNode expandStringFunctions(final SqlBasicCall proj_call, RelDataTypeFactory typeFactory)
RelRoot convertSqlToRelNode(final SqlNode sqlNode, final HeavyDBPlanner HeavyDBPlanner, final HeavyDBParserOptions parserOptions)
static final ThreadLocal< HeavyDBParser > CURRENT_PARSER
static final EnumSet< SqlKind > UPDATE
Set< ImmutableList< String > > inserts
LogicalTableModify getDummyUpdate(SqlUpdate update)
String processSql(final SqlNode sqlNode, final HeavyDBParserOptions parserOptions)
static final EnumSet< SqlKind > IN
static final EnumSet< SqlKind > OTHER_FUNCTION
static final HintStrategyTable HINT_STRATEGY_TABLE
SqlIdentifierCapturer getAccessedObjects()
String getTableName(SqlNode node)
static Map< String, Boolean > SubqueryCorrMemo
boolean isHashJoinableType(TColumnType type)
SockTransportProperties sock_transport_properties
RelDataTypeSystem createTypeSystem()
RelRoot rewriteUpdateAsSelect(SqlUpdate update, HeavyDBParserOptions parserOptions)
std::string toString(const Executor::ExtModuleKinds &kind)
String processSql(String sql, final HeavyDBParserOptions parserOptions)
Set< ImmutableList< String > > selects
void updateMetaData(String schema, String table)
static final Context DB_CONNECTION_CONTEXT
static final EnumSet< SqlKind > DELETE
String buildRATreeAndPerformQueryOptimization(String query, final HeavyDBParserOptions parserOptions)
SqlIdentifierCapturer captureIdentifiers(String sql, boolean legacy_syntax)
torch::Tensor f(torch::Tensor x, torch::Tensor W_target, torch::Tensor b_target)
HeavyDBPlanner getPlanner()
SqlNode expandVariance(final SqlParserPos pos, final SqlNode operand, boolean biased, boolean sqrt, boolean flt, RelDataTypeFactory typeFactory)
void desugar(SqlSelect select_node, RelDataTypeFactory typeFactory)
boolean containsSqlOperator(SqlNode node, SqlKind operatorKind)
static final EnumSet< SqlKind > SCALAR
HeavyDBPlanner.CompletionResult getCompletionHints(String sql, int cursor, List< String > visible_tables)
RelRoot queryToRelNode(final String sql, final HeavyDBParserOptions parserOptions)
SqlNode expandCovariance(SqlParserPos pos, final SqlNode operand0, final SqlNode operand1, boolean pop, boolean flt, RelDataTypeFactory typeFactory)
SqlNodeList expand(final SqlNodeList group_by_list, final java.util.Map< String, SqlNode > id_to_expr, RelDataTypeFactory typeFactory)
Set< ImmutableList< String > > addDbContextIfMissing(Set< ImmutableList< String >> names)
SqlNode expandCorrelation(final SqlBasicCall proj_call, RelDataTypeFactory typeFactory)
Pair< String, SqlIdentifierCapturer > process(String sql, final HeavyDBParserOptions parserOptions)
static final SqlArrayValueConstructorAllowingEmpty ARRAY_VALUE_CONSTRUCTOR
static final EnumSet< SqlKind > EXISTS
void tableAliasFinder(SqlNode sqlNode, Map< String, String > tableAliasMap)
boolean isCorrelated(SqlNode expression)
boolean isEqualityJoinOperator(SqlBasicCall basicCall)
HeavyDBParser(String dataDir, final Supplier< HeavyDBSqlOperatorTable > dbSqlOperatorTable, int dbPort, SockTransportProperties skT)
SqlNode expand(final SqlNode node, final java.util.Map< String, SqlNode > id_to_expr, RelDataTypeFactory typeFactory)
HeavyDBPlanner getPlanner(final boolean allowSubQueryExpansion, final boolean isWatchdogEnabled, final boolean isDistributedMode)
final Supplier< HeavyDBSqlOperatorTable > dbSqlOperatorTable