You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by sh...@apache.org on 2018/11/15 12:56:42 UTC

[kylin] branch master updated: KYLIN-3676 Update customized Calctie

This is an automated email from the ASF dual-hosted git repository.

shaofengshi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kylin.git


The following commit(s) were added to refs/heads/master by this push:
     new 6344986  KYLIN-3676 Update customized Calctie
6344986 is described below

commit 634498649f20ce61fcabe0b46fe515bb6ca96af0
Author: Lijun Cao <64...@qq.com>
AuthorDate: Mon Nov 12 14:22:49 2018 +0800

    KYLIN-3676 Update customized Calctie
---
 .../.settings/org.eclipse.core.resources.prefs     |    6 -
 atopcalcite/.settings/org.eclipse.jdt.core.prefs   |  386 --
 atopcalcite/.settings/org.eclipse.jdt.ui.prefs     |    7 -
 atopcalcite/pom.xml                                |   56 -
 .../adapter/enumerable/EnumerableWindowBridge.java |   39 -
 .../apache/calcite/prepare/CalcitePrepareImpl.java | 1518 ------
 .../prepare/OnlyPrepareEarlyAbortException.java    |   40 -
 .../apache/calcite/rel/rules/FilterJoinRule.java   |  311 --
 .../rel/rules/OLAPJoinPushThroughJoinRule.java     |  172 -
 .../rel/rules/OLAPJoinPushThroughJoinRule2.java    |  205 -
 .../org/apache/calcite/runtime/SqlFunctions.java   | 2238 --------
 .../org/apache/calcite/sql/type/SqlTypeUtil.java   | 1336 -----
 .../apache/calcite/sql2rel/RelFieldTrimmer.java    |   45 -
 .../apache/calcite/sql2rel/SqlToRelConverter.java  | 5656 --------------------
 .../java/org/apache/calcite/tools/Programs.java    |  438 --
 .../java/org/apache/calcite/tools/RelUtils.java    |   71 -
 .../apache/calcite/runtime/SqlFunctionsTest.java   |   38 -
 .../apache/kylin/cube/CubeCapabilityChecker.java   |   13 +
 core-metadata/pom.xml                              |   15 +-
 .../apache/kylin/metadata/model/FunctionDesc.java  |    1 +
 .../storage/gtrecord/GTCubeStorageQueryBase.java   |    2 +-
 kylin-it/pom.xml                                   |   15 +-
 pom.xml                                            |    3 +-
 query/pom.xml                                      |   15 +-
 .../query/optrule/AggregateMultipleExpandRule.java |   17 -
 .../kylin/query/relnode/OLAPAggregateRel.java      |    9 +-
 .../relnode/visitor/TupleExpressionVisitor.java    |    5 +-
 27 files changed, 64 insertions(+), 12593 deletions(-)

diff --git a/atopcalcite/.settings/org.eclipse.core.resources.prefs b/atopcalcite/.settings/org.eclipse.core.resources.prefs
deleted file mode 100644
index 29abf99..0000000
--- a/atopcalcite/.settings/org.eclipse.core.resources.prefs
+++ /dev/null
@@ -1,6 +0,0 @@
-eclipse.preferences.version=1
-encoding//src/main/java=UTF-8
-encoding//src/main/resources=UTF-8
-encoding//src/test/java=UTF-8
-encoding//src/test/resources=UTF-8
-encoding/<project>=UTF-8
diff --git a/atopcalcite/.settings/org.eclipse.jdt.core.prefs b/atopcalcite/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index 500de29..0000000
--- a/atopcalcite/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,386 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
-org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
-org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
-org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
-org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
-org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
-org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
-org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
-org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
-org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
-org.eclipse.jdt.core.compiler.debug.lineNumber=generate
-org.eclipse.jdt.core.compiler.debug.localVariable=generate
-org.eclipse.jdt.core.compiler.debug.sourceFile=generate
-org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
-org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
-org.eclipse.jdt.core.compiler.problem.deadCode=warning
-org.eclipse.jdt.core.compiler.problem.deprecation=warning
-org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
-org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
-org.eclipse.jdt.core.compiler.problem.discouragedReference=ignore
-org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
-org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
-org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
-org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
-org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
-org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=ignore
-org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
-org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
-org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
-org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
-org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
-org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
-org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
-org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
-org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
-org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
-org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
-org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
-org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
-org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
-org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
-org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
-org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
-org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
-org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
-org.eclipse.jdt.core.compiler.problem.nullReference=warning
-org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
-org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
-org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
-org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
-org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
-org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
-org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
-org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
-org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
-org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
-org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
-org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
-org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
-org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
-org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
-org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
-org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
-org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
-org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
-org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=ignore
-org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
-org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
-org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
-org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
-org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
-org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedImport=warning
-org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
-org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
-org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
-org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
-org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
-org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.7
-org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
-org.eclipse.jdt.core.formatter.alignment_for_assignment=0
-org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
-org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
-org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
-org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
-org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
-org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
-org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
-org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
-org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
-org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
-org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
-org.eclipse.jdt.core.formatter.blank_lines_after_package=1
-org.eclipse.jdt.core.formatter.blank_lines_before_field=0
-org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
-org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
-org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
-org.eclipse.jdt.core.formatter.blank_lines_before_method=1
-org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
-org.eclipse.jdt.core.formatter.blank_lines_before_package=0
-org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
-org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
-org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
-org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
-org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
-org.eclipse.jdt.core.formatter.comment.format_block_comments=false
-org.eclipse.jdt.core.formatter.comment.format_header=false
-org.eclipse.jdt.core.formatter.comment.format_html=true
-org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=false
-org.eclipse.jdt.core.formatter.comment.format_line_comments=false
-org.eclipse.jdt.core.formatter.comment.format_source_code=true
-org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
-org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
-org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
-org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
-org.eclipse.jdt.core.formatter.comment.line_length=80
-org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
-org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
-org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
-org.eclipse.jdt.core.formatter.compact_else_if=true
-org.eclipse.jdt.core.formatter.continuation_indentation=2
-org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
-org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
-org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
-org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
-org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
-org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
-org.eclipse.jdt.core.formatter.indent_empty_lines=false
-org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
-org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
-org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
-org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
-org.eclipse.jdt.core.formatter.indentation.size=4
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
-org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
-org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
-org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
-org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
-org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
-org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.join_lines_in_comments=true
-org.eclipse.jdt.core.formatter.join_wrapped_lines=true
-org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
-org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
-org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
-org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
-org.eclipse.jdt.core.formatter.lineSplit=120
-org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
-org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
-org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
-org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
-org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
-org.eclipse.jdt.core.formatter.tabulation.char=space
-org.eclipse.jdt.core.formatter.tabulation.size=4
-org.eclipse.jdt.core.formatter.use_on_off_tags=false
-org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
-org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
-org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
-org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/atopcalcite/.settings/org.eclipse.jdt.ui.prefs b/atopcalcite/.settings/org.eclipse.jdt.ui.prefs
deleted file mode 100644
index d521bab..0000000
--- a/atopcalcite/.settings/org.eclipse.jdt.ui.prefs
+++ /dev/null
@@ -1,7 +0,0 @@
-eclipse.preferences.version=1
-formatter_profile=_Space Indent & Long Lines
-formatter_settings_version=12
-org.eclipse.jdt.ui.ignorelowercasenames=true
-org.eclipse.jdt.ui.importorder=java;javax;org;com;
-org.eclipse.jdt.ui.ondemandthreshold=99
-org.eclipse.jdt.ui.staticondemandthreshold=99
diff --git a/atopcalcite/pom.xml b/atopcalcite/pom.xml
deleted file mode 100644
index 58e40ef..0000000
--- a/atopcalcite/pom.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements.  See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership.  The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License.  You may obtain a copy of the License at
- 
-     http://www.apache.org/licenses/LICENSE-2.0
- 
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>atopcalcite</artifactId>
-    <packaging>jar</packaging>
-    <name>Apache Kylin - Calcite Overrides</name>
-    <description>Apache Kylin - Calcite Overrides</description>
-
-    <parent>
-        <groupId>org.apache.kylin</groupId>
-        <artifactId>kylin</artifactId>
-        <version>2.6.0-SNAPSHOT</version>
-    </parent>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.calcite</groupId>
-            <artifactId>calcite-core</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.apache.calcite.avatica</groupId>
-                    <artifactId>avatica-core</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <!-- It should be avatica(the shaded one), not avatica-core, since the inconsistency protobuf dependency with Hadoop -->
-        <dependency>
-            <groupId>org.apache.calcite.avatica</groupId>
-            <artifactId>avatica</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-</project>
diff --git a/atopcalcite/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableWindowBridge.java b/atopcalcite/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableWindowBridge.java
deleted file mode 100644
index 13a33e3..0000000
--- a/atopcalcite/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableWindowBridge.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
-*/
-
-package org.apache.calcite.adapter.enumerable;
-
-import org.apache.calcite.plan.RelOptCluster;
-import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.core.Window;
-import org.apache.calcite.rel.type.RelDataType;
-import org.apache.calcite.rex.RexLiteral;
-
-import java.util.List;
-
-/**
- * EnumerableWindow cant'be created out of package, here's hack of workaround
- */
-public class EnumerableWindowBridge {
-
-    public static EnumerableWindow createEnumerableWindow(RelOptCluster cluster, RelTraitSet traits, RelNode child,
-                                                   List<RexLiteral> constants, RelDataType rowType, List<Window.Group> groups) {
-        return new EnumerableWindow(cluster, traits, child, constants, rowType, groups);
-    }
-}
diff --git a/atopcalcite/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java b/atopcalcite/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
deleted file mode 100644
index b63beee..0000000
--- a/atopcalcite/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
+++ /dev/null
@@ -1,1518 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
-*/
-package org.apache.calcite.prepare;
-
-import static org.apache.calcite.util.Static.RESOURCE;
-
-import java.lang.reflect.Type;
-import java.math.BigDecimal;
-import java.sql.DatabaseMetaData;
-import java.sql.Types;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.calcite.DataContext;
-import org.apache.calcite.adapter.enumerable.EnumerableBindable;
-import org.apache.calcite.adapter.enumerable.EnumerableCalc;
-import org.apache.calcite.adapter.enumerable.EnumerableConvention;
-import org.apache.calcite.adapter.enumerable.EnumerableInterpretable;
-import org.apache.calcite.adapter.enumerable.EnumerableInterpreterRule;
-import org.apache.calcite.adapter.enumerable.EnumerableRel;
-import org.apache.calcite.adapter.enumerable.EnumerableRules;
-import org.apache.calcite.adapter.enumerable.RexToLixTranslator;
-import org.apache.calcite.adapter.java.JavaTypeFactory;
-import org.apache.calcite.avatica.AvaticaParameter;
-import org.apache.calcite.avatica.ColumnMetaData;
-import org.apache.calcite.avatica.Meta;
-import org.apache.calcite.config.CalciteConnectionConfig;
-import org.apache.calcite.interpreter.BindableConvention;
-import org.apache.calcite.interpreter.Bindables;
-import org.apache.calcite.interpreter.Interpreters;
-import org.apache.calcite.jdbc.CalcitePrepare;
-import org.apache.calcite.jdbc.CalciteSchema;
-import org.apache.calcite.jdbc.CalciteSchema.LatticeEntry;
-import org.apache.calcite.linq4j.Enumerable;
-import org.apache.calcite.linq4j.Linq4j;
-import org.apache.calcite.linq4j.Ord;
-import org.apache.calcite.linq4j.Queryable;
-import org.apache.calcite.linq4j.function.Function1;
-import org.apache.calcite.linq4j.tree.BinaryExpression;
-import org.apache.calcite.linq4j.tree.BlockStatement;
-import org.apache.calcite.linq4j.tree.Blocks;
-import org.apache.calcite.linq4j.tree.ConstantExpression;
-import org.apache.calcite.linq4j.tree.Expression;
-import org.apache.calcite.linq4j.tree.Expressions;
-import org.apache.calcite.linq4j.tree.MemberExpression;
-import org.apache.calcite.linq4j.tree.MethodCallExpression;
-import org.apache.calcite.linq4j.tree.NewExpression;
-import org.apache.calcite.linq4j.tree.ParameterExpression;
-import org.apache.calcite.materialize.MaterializationService;
-import org.apache.calcite.plan.Contexts;
-import org.apache.calcite.plan.Convention;
-import org.apache.calcite.plan.ConventionTraitDef;
-import org.apache.calcite.plan.RelOptCluster;
-import org.apache.calcite.plan.RelOptCostFactory;
-import org.apache.calcite.plan.RelOptPlanner;
-import org.apache.calcite.plan.RelOptRule;
-import org.apache.calcite.plan.RelOptTable;
-import org.apache.calcite.plan.RelOptUtil;
-import org.apache.calcite.plan.hep.HepPlanner;
-import org.apache.calcite.plan.hep.HepProgramBuilder;
-import org.apache.calcite.plan.volcano.VolcanoPlanner;
-import org.apache.calcite.rel.RelCollation;
-import org.apache.calcite.rel.RelCollationTraitDef;
-import org.apache.calcite.rel.RelCollations;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.RelRoot;
-import org.apache.calcite.rel.core.Filter;
-import org.apache.calcite.rel.core.Project;
-import org.apache.calcite.rel.core.Sort;
-import org.apache.calcite.rel.core.TableScan;
-import org.apache.calcite.rel.rules.AbstractMaterializedViewRule;
-import org.apache.calcite.rel.rules.AggregateExpandDistinctAggregatesRule;
-import org.apache.calcite.rel.rules.AggregateReduceFunctionsRule;
-import org.apache.calcite.rel.rules.AggregateStarTableRule;
-import org.apache.calcite.rel.rules.AggregateValuesRule;
-import org.apache.calcite.rel.rules.FilterAggregateTransposeRule;
-import org.apache.calcite.rel.rules.FilterJoinRule;
-import org.apache.calcite.rel.rules.FilterProjectTransposeRule;
-import org.apache.calcite.rel.rules.FilterTableScanRule;
-import org.apache.calcite.rel.rules.JoinAssociateRule;
-import org.apache.calcite.rel.rules.JoinCommuteRule;
-import org.apache.calcite.rel.rules.JoinPushExpressionsRule;
-import org.apache.calcite.rel.rules.JoinPushThroughJoinRule;
-import org.apache.calcite.rel.rules.MaterializedViewFilterScanRule;
-import org.apache.calcite.rel.rules.ProjectFilterTransposeRule;
-import org.apache.calcite.rel.rules.ProjectMergeRule;
-import org.apache.calcite.rel.rules.ProjectTableScanRule;
-import org.apache.calcite.rel.rules.ProjectWindowTransposeRule;
-import org.apache.calcite.rel.rules.ReduceExpressionsRule;
-import org.apache.calcite.rel.rules.SortJoinTransposeRule;
-import org.apache.calcite.rel.rules.SortProjectTransposeRule;
-import org.apache.calcite.rel.rules.SortUnionTransposeRule;
-import org.apache.calcite.rel.rules.TableScanRule;
-import org.apache.calcite.rel.rules.ValuesReduceRule;
-import org.apache.calcite.rel.stream.StreamRules;
-import org.apache.calcite.rel.type.RelDataType;
-import org.apache.calcite.rel.type.RelDataTypeFactory;
-import org.apache.calcite.rel.type.RelDataTypeField;
-import org.apache.calcite.rex.RexBuilder;
-import org.apache.calcite.rex.RexInputRef;
-import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.rex.RexProgram;
-import org.apache.calcite.runtime.Bindable;
-import org.apache.calcite.runtime.Hook;
-import org.apache.calcite.runtime.Typed;
-import org.apache.calcite.schema.Schemas;
-import org.apache.calcite.schema.Table;
-import org.apache.calcite.server.CalciteServerStatement;
-import org.apache.calcite.sql.SqlBinaryOperator;
-import org.apache.calcite.sql.SqlExecutableStatement;
-import org.apache.calcite.sql.SqlExplainFormat;
-import org.apache.calcite.sql.SqlExplainLevel;
-import org.apache.calcite.sql.SqlKind;
-import org.apache.calcite.sql.SqlNode;
-import org.apache.calcite.sql.SqlOperator;
-import org.apache.calcite.sql.SqlOperatorTable;
-import org.apache.calcite.sql.SqlUtil;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
-import org.apache.calcite.sql.parser.SqlParseException;
-import org.apache.calcite.sql.parser.SqlParser;
-import org.apache.calcite.sql.parser.SqlParserImplFactory;
-import org.apache.calcite.sql.type.SqlTypeName;
-import org.apache.calcite.sql.util.ChainedSqlOperatorTable;
-import org.apache.calcite.sql.validate.SqlConformance;
-import org.apache.calcite.sql.validate.SqlValidator;
-import org.apache.calcite.sql2rel.SqlRexConvertletTable;
-import org.apache.calcite.sql2rel.SqlToRelConverter;
-import org.apache.calcite.sql2rel.StandardConvertletTable;
-import org.apache.calcite.tools.Frameworks;
-import org.apache.calcite.tools.RelUtils;
-import org.apache.calcite.util.ImmutableIntList;
-import org.apache.calcite.util.Pair;
-import org.apache.calcite.util.Util;
-
-import com.google.common.base.Supplier;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Maps;
-
-/*
- * OVERRIDE POINT:
- * - grep KYLIN_ONLY_PREPARE
- */
-
-/**
- * Shit just got real.
- *
- * <p>This class is public so that projects that create their own JDBC driver
- * and server can fine-tune preferences. However, this class and its methods are
- * subject to change without notice.</p>
- */
-public class CalcitePrepareImpl implements CalcitePrepare {
-
-  public static final ThreadLocal<Boolean> KYLIN_ONLY_PREPARE = new ThreadLocal<>();
-
-  public static final boolean DEBUG = Util.getBooleanProperty("calcite.debug");
-
-  public static final boolean COMMUTE =
-      Util.getBooleanProperty("calcite.enable.join.commute");
-
-  /** Whether to enable the collation trait. Some extra optimizations are
-   * possible if enabled, but queries should work either way. At some point
-   * this will become a preference, or we will run multiple phases: first
-   * disabled, then enabled. */
-  private static final boolean ENABLE_COLLATION_TRAIT = true;
-
-  /** Whether the bindable convention should be the root convention of any
-   * plan. If not, enumerable convention is the default. */
-  public final boolean enableBindable = Hook.ENABLE_BINDABLE.get(false);
-
-  /** Whether the enumerable convention is enabled. */
-  public static final boolean ENABLE_ENUMERABLE = true;
-
-  /** Whether the streaming is enabled. */
-  public static final boolean ENABLE_STREAM = true;
-
-  private static final Set<String> SIMPLE_SQLS =
-      ImmutableSet.of(
-          "SELECT 1",
-          "select 1",
-          "SELECT 1 FROM DUAL",
-          "select 1 from dual",
-          "values 1",
-          "VALUES 1");
-
-  public static final List<RelOptRule> ENUMERABLE_RULES =
-      ImmutableList.of(
-          EnumerableRules.ENUMERABLE_JOIN_RULE,
-          EnumerableRules.ENUMERABLE_MERGE_JOIN_RULE,
-          EnumerableRules.ENUMERABLE_SEMI_JOIN_RULE,
-          EnumerableRules.ENUMERABLE_CORRELATE_RULE,
-          EnumerableRules.ENUMERABLE_PROJECT_RULE,
-          EnumerableRules.ENUMERABLE_FILTER_RULE,
-          EnumerableRules.ENUMERABLE_AGGREGATE_RULE,
-          EnumerableRules.ENUMERABLE_SORT_RULE,
-          EnumerableRules.ENUMERABLE_LIMIT_RULE,
-          EnumerableRules.ENUMERABLE_COLLECT_RULE,
-          EnumerableRules.ENUMERABLE_UNCOLLECT_RULE,
-          EnumerableRules.ENUMERABLE_UNION_RULE,
-          EnumerableRules.ENUMERABLE_INTERSECT_RULE,
-          EnumerableRules.ENUMERABLE_MINUS_RULE,
-          EnumerableRules.ENUMERABLE_TABLE_MODIFICATION_RULE,
-          EnumerableRules.ENUMERABLE_VALUES_RULE,
-          EnumerableRules.ENUMERABLE_WINDOW_RULE,
-          EnumerableRules.ENUMERABLE_TABLE_SCAN_RULE,
-          EnumerableRules.ENUMERABLE_TABLE_FUNCTION_SCAN_RULE);
-
-  private static final List<RelOptRule> DEFAULT_RULES =
-      ImmutableList.of(
-          AggregateStarTableRule.INSTANCE,
-          AggregateStarTableRule.INSTANCE2,
-          TableScanRule.INSTANCE,
-          COMMUTE
-              ? JoinAssociateRule.INSTANCE
-              : ProjectMergeRule.INSTANCE,
-          FilterTableScanRule.INSTANCE,
-          ProjectFilterTransposeRule.INSTANCE,
-          FilterProjectTransposeRule.INSTANCE,
-          FilterJoinRule.FILTER_ON_JOIN,
-          JoinPushExpressionsRule.INSTANCE,
-          AggregateExpandDistinctAggregatesRule.INSTANCE,
-          AggregateReduceFunctionsRule.INSTANCE,
-          FilterAggregateTransposeRule.INSTANCE,
-          ProjectWindowTransposeRule.INSTANCE,
-          JoinCommuteRule.INSTANCE,
-          JoinPushThroughJoinRule.RIGHT,
-          JoinPushThroughJoinRule.LEFT,
-          SortProjectTransposeRule.INSTANCE,
-          SortJoinTransposeRule.INSTANCE,
-          SortUnionTransposeRule.INSTANCE);
-
-  private static final List<RelOptRule> CONSTANT_REDUCTION_RULES =
-      ImmutableList.of(
-          ReduceExpressionsRule.PROJECT_INSTANCE,
-          ReduceExpressionsRule.FILTER_INSTANCE,
-          ReduceExpressionsRule.CALC_INSTANCE,
-          ReduceExpressionsRule.JOIN_INSTANCE,
-          ValuesReduceRule.FILTER_INSTANCE,
-          ValuesReduceRule.PROJECT_FILTER_INSTANCE,
-          ValuesReduceRule.PROJECT_INSTANCE,
-          AggregateValuesRule.INSTANCE);
-
-  public CalcitePrepareImpl() {
-  }
-
-  public ParseResult parse(
-          Context context, String sql) {
-    return parse_(context, sql, false, false, false);
-  }
-
-  public ConvertResult convert(Context context, String sql) {
-    return (ConvertResult) parse_(context, sql, true, false, false);
-  }
-
-  public AnalyzeViewResult analyzeView(Context context, String sql, boolean fail) {
-    return (AnalyzeViewResult) parse_(context, sql, true, true, fail);
-  }
-
-  /** Shared implementation for {@link #parse}, {@link #convert} and
-   * {@link #analyzeView}. */
-  private ParseResult parse_(Context context, String sql, boolean convert,
-                             boolean analyze, boolean fail) {
-    final JavaTypeFactory typeFactory = context.getTypeFactory();
-    CalciteCatalogReader catalogReader =
-        new CalciteCatalogReader(
-            context.getRootSchema(),
-            context.config().caseSensitive(),
-            context.getDefaultSchemaPath(),
-            typeFactory);
-    SqlParser parser = createParser(sql);
-    SqlNode sqlNode;
-    try {
-      sqlNode = parser.parseStmt();
-    } catch (SqlParseException e) {
-      throw new RuntimeException("parse failed", e);
-    }
-    final SqlValidator validator = createSqlValidator(context, catalogReader);
-    SqlNode sqlNode1 = validator.validate(sqlNode);
-    if (convert) {
-      return convert_(
-          context, sql, analyze, fail, catalogReader, validator, sqlNode1);
-    }
-    return new ParseResult(this, validator, sql, sqlNode1,
-        validator.getValidatedNodeType(sqlNode1));
-  }
-
-  private ParseResult convert_(Context context, String sql, boolean analyze,
-                               boolean fail, CalciteCatalogReader catalogReader, SqlValidator validator,
-                               SqlNode sqlNode1) {
-    final JavaTypeFactory typeFactory = context.getTypeFactory();
-    final Convention resultConvention =
-        enableBindable ? BindableConvention.INSTANCE
-            : EnumerableConvention.INSTANCE;
-    final HepPlanner planner = new HepPlanner(new HepProgramBuilder().build());
-    planner.addRelTraitDef(ConventionTraitDef.INSTANCE);
-
-    final SqlToRelConverter.ConfigBuilder configBuilder =
-        SqlToRelConverter.configBuilder().withTrimUnusedFields(true);
-    if (analyze) {
-      configBuilder.withConvertTableAccess(false);
-    }
-
-    final CalcitePreparingStmt preparingStmt =
-        new CalcitePreparingStmt(this, context, catalogReader, typeFactory,
-            context.getRootSchema(), null, planner, resultConvention,
-            createConvertletTable());
-    final SqlToRelConverter converter =
-        preparingStmt.getSqlToRelConverter(validator, catalogReader,
-            configBuilder.build());
-
-    final RelRoot root = converter.convertQuery(sqlNode1, false, true);
-    if (analyze) {
-      return analyze_(validator, sql, sqlNode1, root, fail);
-    }
-    return new ConvertResult(this, validator, sql, sqlNode1,
-        validator.getValidatedNodeType(sqlNode1), root);
-  }
-
-  private AnalyzeViewResult analyze_(SqlValidator validator, String sql,
-                                     SqlNode sqlNode, RelRoot root, boolean fail) {
-    final RexBuilder rexBuilder = root.rel.getCluster().getRexBuilder();
-    RelNode rel = root.rel;
-    final RelNode viewRel = rel;
-    Project project;
-    if (rel instanceof Project) {
-      project = (Project) rel;
-      rel = project.getInput();
-    } else {
-      project = null;
-    }
-    Filter filter;
-    if (rel instanceof Filter) {
-      filter = (Filter) rel;
-      rel = filter.getInput();
-    } else {
-      filter = null;
-    }
-    TableScan scan;
-    if (rel instanceof TableScan) {
-      scan = (TableScan) rel;
-    } else {
-      scan = null;
-    }
-    if (scan == null) {
-      if (fail) {
-        throw validator.newValidationError(sqlNode,
-            RESOURCE.modifiableViewMustBeBasedOnSingleTable());
-      }
-      return new AnalyzeViewResult(this, validator, sql, sqlNode,
-          validator.getValidatedNodeType(sqlNode), root, null, null, null,
-          null, false);
-    }
-    final RelOptTable targetRelTable = scan.getTable();
-    final RelDataType targetRowType = targetRelTable.getRowType();
-    final Table table = targetRelTable.unwrap(Table.class);
-    final List<String> tablePath = targetRelTable.getQualifiedName();
-    assert table != null;
-    List<Integer> columnMapping;
-    final Map<Integer, RexNode> projectMap = new HashMap<>();
-    if (project == null) {
-      columnMapping = ImmutableIntList.range(0, targetRowType.getFieldCount());
-    } else {
-      columnMapping = new ArrayList<>();
-      for (Ord<RexNode> node : Ord.zip(project.getProjects())) {
-        if (node.e instanceof RexInputRef) {
-          RexInputRef rexInputRef = (RexInputRef) node.e;
-          int index = rexInputRef.getIndex();
-          if (projectMap.get(index) != null) {
-            if (fail) {
-              throw validator.newValidationError(sqlNode,
-                  RESOURCE.moreThanOneMappedColumn(
-                      targetRowType.getFieldList().get(index).getName(),
-                      Util.last(tablePath)));
-            }
-            return new AnalyzeViewResult(this, validator, sql, sqlNode,
-                validator.getValidatedNodeType(sqlNode), root, null, null, null,
-                null, false);
-          }
-          projectMap.put(index, rexBuilder.makeInputRef(viewRel, node.i));
-          columnMapping.add(index);
-        } else {
-          columnMapping.add(-1);
-        }
-      }
-    }
-    final RexNode constraint;
-    if (filter != null) {
-      constraint = filter.getCondition();
-    } else {
-      constraint = rexBuilder.makeLiteral(true);
-    }
-    final List<RexNode> filters = new ArrayList<>();
-    // If we put a constraint in projectMap above, then filters will not be empty despite
-    // being a modifiable view.
-    final List<RexNode> filters2 = new ArrayList<>();
-    boolean retry = false;
-    RelOptUtil.inferViewPredicates(projectMap, filters, constraint);
-    if (fail && !filters.isEmpty()) {
-      final Map<Integer, RexNode> projectMap2 = new HashMap<>();
-      RelOptUtil.inferViewPredicates(projectMap2, filters2, constraint);
-      if (!filters2.isEmpty()) {
-        throw validator.newValidationError(sqlNode,
-            RESOURCE.modifiableViewMustHaveOnlyEqualityPredicates());
-      }
-      retry = true;
-    }
-
-    // Check that all columns that are not projected have a constant value
-    for (RelDataTypeField field : targetRowType.getFieldList()) {
-      final int x = columnMapping.indexOf(field.getIndex());
-      if (x >= 0) {
-        assert Util.skip(columnMapping, x + 1).indexOf(field.getIndex()) < 0
-            : "column projected more than once; should have checked above";
-        continue; // target column is projected
-      }
-      if (projectMap.get(field.getIndex()) != null) {
-        continue; // constant expression
-      }
-      if (field.getType().isNullable()) {
-        continue; // don't need expression for nullable columns; NULL suffices
-      }
-      if (fail) {
-        throw validator.newValidationError(sqlNode,
-            RESOURCE.noValueSuppliedForViewColumn(field.getName(),
-                Util.last(tablePath)));
-      }
-      return new AnalyzeViewResult(this, validator, sql, sqlNode,
-          validator.getValidatedNodeType(sqlNode), root, null, null, null,
-          null, false);
-    }
-
-    final boolean modifiable = filters.isEmpty() || retry && filters2.isEmpty();
-    return new AnalyzeViewResult(this, validator, sql, sqlNode,
-        validator.getValidatedNodeType(sqlNode), root, modifiable ? table : null,
-        ImmutableList.copyOf(tablePath),
-        constraint, ImmutableIntList.copyOf(columnMapping),
-        modifiable);
-  }
-
-  @Override public void executeDdl(Context context, SqlNode node) {
-    if (node instanceof SqlExecutableStatement) {
-      SqlExecutableStatement statement = (SqlExecutableStatement) node;
-      statement.execute(context);
-      return;
-    }
-    throw new UnsupportedOperationException();
-  }
-
-  /** Factory method for default SQL parser. */
-  protected SqlParser createParser(String sql) {
-    return createParser(sql, createParserConfig());
-  }
-
-  /** Factory method for SQL parser with a given configuration. */
-  protected SqlParser createParser(String sql,
-                                   SqlParser.ConfigBuilder parserConfig) {
-    return SqlParser.create(sql, parserConfig.build());
-  }
-
-  /** Factory method for SQL parser configuration. */
-  protected SqlParser.ConfigBuilder createParserConfig() {
-    return SqlParser.configBuilder();
-  }
-
-  /** Factory method for default convertlet table. */
-  protected SqlRexConvertletTable createConvertletTable() {
-    return StandardConvertletTable.INSTANCE;
-  }
-
-  /** Factory method for cluster. */
-  protected RelOptCluster createCluster(RelOptPlanner planner,
-                                        RexBuilder rexBuilder) {
-    return RelOptCluster.create(planner, rexBuilder);
-  }
-
-  /** Creates a collection of planner factories.
-   *
-   * <p>The collection must have at least one factory, and each factory must
-   * create a planner. If the collection has more than one planner, Calcite will
-   * try each planner in turn.</p>
-   *
-   * <p>One of the things you can do with this mechanism is to try a simpler,
-   * faster, planner with a smaller rule set first, then fall back to a more
-   * complex planner for complex and costly queries.</p>
-   *
-   * <p>The default implementation returns a factory that calls
-   * {@link #createPlanner(org.apache.calcite.jdbc.CalcitePrepare.Context)}.</p>
-   */
-  protected List<Function1<Context, RelOptPlanner>> createPlannerFactories() {
-    return Collections.<Function1<Context, RelOptPlanner>>singletonList(
-        new Function1<Context, RelOptPlanner>() {
-          public RelOptPlanner apply(Context context) {
-            return createPlanner(context, null, null);
-          }
-        });
-  }
-
-  /** Creates a query planner and initializes it with a default set of
-   * rules. */
-  protected RelOptPlanner createPlanner(CalcitePrepare.Context prepareContext) {
-    return createPlanner(prepareContext, null, null);
-  }
-
-  /** Creates a query planner and initializes it with a default set of
-   * rules. */
-  protected RelOptPlanner createPlanner(
-      final CalcitePrepare.Context prepareContext,
-      org.apache.calcite.plan.Context externalContext,
-      RelOptCostFactory costFactory) {
-    if (externalContext == null) {
-      externalContext = Contexts.of(prepareContext.config());
-    }
-    final VolcanoPlanner planner =
-        new VolcanoPlanner(costFactory, externalContext);
-    planner.addRelTraitDef(ConventionTraitDef.INSTANCE);
-    if (ENABLE_COLLATION_TRAIT) {
-      planner.addRelTraitDef(RelCollationTraitDef.INSTANCE);
-      planner.registerAbstractRelationalRules();
-    }
-    RelOptUtil.registerAbstractRels(planner);
-    for (RelOptRule rule : DEFAULT_RULES) {
-      planner.addRule(rule);
-    }
-    if (prepareContext.config().materializationsEnabled()) {
-      planner.addRule(MaterializedViewFilterScanRule.INSTANCE);
-      planner.addRule(AbstractMaterializedViewRule.INSTANCE_PROJECT_FILTER);
-      planner.addRule(AbstractMaterializedViewRule.INSTANCE_FILTER);
-      planner.addRule(AbstractMaterializedViewRule.INSTANCE_PROJECT_JOIN);
-      planner.addRule(AbstractMaterializedViewRule.INSTANCE_JOIN);
-      planner.addRule(AbstractMaterializedViewRule.INSTANCE_PROJECT_AGGREGATE);
-      planner.addRule(AbstractMaterializedViewRule.INSTANCE_AGGREGATE);
-    }
-    if (enableBindable) {
-      for (RelOptRule rule : Bindables.RULES) {
-        planner.addRule(rule);
-      }
-    }
-    planner.addRule(Bindables.BINDABLE_TABLE_SCAN_RULE);
-    planner.addRule(ProjectTableScanRule.INSTANCE);
-    planner.addRule(ProjectTableScanRule.INTERPRETER);
-
-    if (ENABLE_ENUMERABLE) {
-      for (RelOptRule rule : ENUMERABLE_RULES) {
-        planner.addRule(rule);
-      }
-      planner.addRule(EnumerableInterpreterRule.INSTANCE);
-    }
-
-    if (enableBindable && ENABLE_ENUMERABLE) {
-      planner.addRule(
-          EnumerableBindable.EnumerableToBindableConverterRule.INSTANCE);
-    }
-
-    if (ENABLE_STREAM) {
-      for (RelOptRule rule : StreamRules.RULES) {
-        planner.addRule(rule);
-      }
-    }
-
-    // Change the below to enable constant-reduction.
-    if (false) {
-      for (RelOptRule rule : CONSTANT_REDUCTION_RULES) {
-        planner.addRule(rule);
-      }
-    }
-
-    final SparkHandler spark = prepareContext.spark();
-    if (spark.enabled()) {
-      spark.registerRules(
-          new SparkHandler.RuleSetBuilder() {
-          public void addRule(RelOptRule rule) {
-            // TODO:
-          }
-
-          public void removeRule(RelOptRule rule) {
-            // TODO:
-          }
-        });
-    }
-
-    Hook.PLANNER.run(planner); // allow test to add or remove rules
-
-    return planner;
-  }
-
-  public <T> CalciteSignature<T> prepareQueryable(
-      Context context,
-      Queryable<T> queryable) {
-    return prepare_(context, Query.of(queryable), queryable.getElementType(),
-        -1);
-  }
-
-  public <T> CalciteSignature<T> prepareSql(
-      Context context,
-      Query<T> query,
-      Type elementType,
-      long maxRowCount) {
-    return prepare_(context, query, elementType, maxRowCount);
-  }
-
-  <T> CalciteSignature<T> prepare_(
-      Context context,
-      Query<T> query,
-      Type elementType,
-      long maxRowCount) {
-    if (SIMPLE_SQLS.contains(query.sql)) {
-      return simplePrepare(context, query.sql);
-    }
-
-    if(KYLIN_ONLY_PREPARE.get() != null && KYLIN_ONLY_PREPARE.get()) {
-      ParseResult parseResult = parse(context, query.sql);
-      Class<OnlyPrepareEarlyAbortException> onlyPrepareEarlyAbortExceptionClass =
-              OnlyPrepareEarlyAbortException.class;
-      throw new OnlyPrepareEarlyAbortException(context, parseResult);
-    }
-
-    final JavaTypeFactory typeFactory = context.getTypeFactory();
-    CalciteCatalogReader catalogReader =
-        new CalciteCatalogReader(
-            context.getRootSchema(),
-            context.config().caseSensitive(),
-            context.getDefaultSchemaPath(),
-            typeFactory);
-    final List<Function1<Context, RelOptPlanner>> plannerFactories =
-        createPlannerFactories();
-    if (plannerFactories.isEmpty()) {
-      throw new AssertionError("no planner factories");
-    }
-    RuntimeException exception = Util.FoundOne.NULL;
-    for (Function1<Context, RelOptPlanner> plannerFactory : plannerFactories) {
-      final RelOptPlanner planner = plannerFactory.apply(context);
-      if (planner == null) {
-        throw new AssertionError("factory returned null planner");
-      }
-      try {
-        return prepare2_(context, query, elementType, maxRowCount,
-            catalogReader, planner);
-      } catch (RelOptPlanner.CannotPlanException e) {
-        exception = e;
-      }
-    }
-    throw exception;
-  }
-
-  /** Quickly prepares a simple SQL statement, circumventing the usual
-   * preparation process. */
-  private <T> CalciteSignature<T> simplePrepare(Context context, String sql) {
-    final JavaTypeFactory typeFactory = context.getTypeFactory();
-    final RelDataType x =
-        typeFactory.builder()
-            .add(SqlUtil.deriveAliasFromOrdinal(0), SqlTypeName.INTEGER)
-            .build();
-    @SuppressWarnings("unchecked")
-    final List<T> list = (List) ImmutableList.of(1);
-    final List<String> origin = null;
-    final List<List<String>> origins =
-        Collections.nCopies(x.getFieldCount(), origin);
-    final List<ColumnMetaData> columns =
-        getColumnMetaDataList(typeFactory, x, x, origins);
-    final Meta.CursorFactory cursorFactory =
-        Meta.CursorFactory.deduce(columns, null);
-    return new CalciteSignature<>(
-        sql,
-        ImmutableList.<AvaticaParameter>of(),
-        ImmutableMap.<String, Object>of(),
-        x,
-        columns,
-        cursorFactory,
-        context.getRootSchema(),
-        ImmutableList.<RelCollation>of(),
-        -1,
-        new Bindable<T>() {
-          public Enumerable<T> bind(DataContext dataContext) {
-            return Linq4j.asEnumerable(list);
-          }
-        },
-        Meta.StatementType.SELECT);
-  }
-
-  /**
-   * Deduces the broad type of statement.
-   * Currently returns SELECT for most statement types, but this may change.
-   *
-   * @param kind Kind of statement
-   */
-  private Meta.StatementType getStatementType(SqlKind kind) {
-    switch (kind) {
-    case INSERT:
-    case DELETE:
-    case UPDATE:
-      return Meta.StatementType.IS_DML;
-    default:
-      return Meta.StatementType.SELECT;
-    }
-  }
-
-  /**
-   * Deduces the broad type of statement for a prepare result.
-   * Currently returns SELECT for most statement types, but this may change.
-   *
-   * @param preparedResult Prepare result
-   */
-  private Meta.StatementType getStatementType(Prepare.PreparedResult preparedResult) {
-    if (preparedResult.isDml()) {
-      return Meta.StatementType.IS_DML;
-    } else {
-      return Meta.StatementType.SELECT;
-    }
-  }
-
-  <T> CalciteSignature<T> prepare2_(
-      Context context,
-      Query<T> query,
-      Type elementType,
-      long maxRowCount,
-      CalciteCatalogReader catalogReader,
-      RelOptPlanner planner) {
-    final JavaTypeFactory typeFactory = context.getTypeFactory();
-    final EnumerableRel.Prefer prefer;
-    if (elementType == Object[].class) {
-      prefer = EnumerableRel.Prefer.ARRAY;
-    } else {
-      prefer = EnumerableRel.Prefer.CUSTOM;
-    }
-    final Convention resultConvention =
-        enableBindable ? BindableConvention.INSTANCE
-            : EnumerableConvention.INSTANCE;
-    final CalcitePreparingStmt preparingStmt =
-        new CalcitePreparingStmt(this, context, catalogReader, typeFactory,
-            context.getRootSchema(), prefer, planner, resultConvention,
-            createConvertletTable());
-
-    final RelDataType x;
-    final Prepare.PreparedResult preparedResult;
-    final Meta.StatementType statementType;
-    if (query.sql != null) {
-      final CalciteConnectionConfig config = context.config();
-      final SqlParser.ConfigBuilder parserConfig = createParserConfig()
-          .setQuotedCasing(config.quotedCasing())
-          .setUnquotedCasing(config.unquotedCasing())
-          .setQuoting(config.quoting())
-          .setConformance(config.conformance());
-      final SqlParserImplFactory parserFactory =
-          config.parserFactory(SqlParserImplFactory.class, null);
-      if (parserFactory != null) {
-        parserConfig.setParserFactory(parserFactory);
-      }
-      SqlParser parser = createParser(query.sql,  parserConfig);
-      SqlNode sqlNode;
-      try {
-        sqlNode = parser.parseStmt();
-        statementType = getStatementType(sqlNode.getKind());
-      } catch (SqlParseException e) {
-        throw new RuntimeException(
-            "parse failed: " + e.getMessage(), e);
-      }
-
-      Hook.PARSE_TREE.run(new Object[] {query.sql, sqlNode});
-
-      if (sqlNode.getKind().belongsTo(SqlKind.DDL)) {
-        executeDdl(context, sqlNode);
-
-        // Return a dummy signature that contains no rows
-        final Bindable<T> bindable = new Bindable<T>() {
-          public Enumerable<T> bind(DataContext dataContext) {
-            return Linq4j.emptyEnumerable();
-          }
-        };
-        return new CalciteSignature<>(query.sql,
-            ImmutableList.<AvaticaParameter>of(),
-            ImmutableMap.<String, Object>of(), null,
-            ImmutableList.<ColumnMetaData>of(), Meta.CursorFactory.OBJECT,
-            null, ImmutableList.<RelCollation>of(), -1, bindable);
-      }
-
-      final SqlValidator validator =
-          createSqlValidator(context, catalogReader);
-      validator.setIdentifierExpansion(true);
-      validator.setDefaultNullCollation(config.defaultNullCollation());
-
-      preparedResult = preparingStmt.prepareSql(
-          sqlNode, Object.class, validator, true);
-      switch (sqlNode.getKind()) {
-      case INSERT:
-      case DELETE:
-      case UPDATE:
-      case EXPLAIN:
-        // FIXME: getValidatedNodeType is wrong for DML
-        x = RelOptUtil.createDmlRowType(sqlNode.getKind(), typeFactory);
-        break;
-      default:
-        x = validator.getValidatedNodeType(sqlNode);
-      }
-    } else if (query.queryable != null) {
-      x = context.getTypeFactory().createType(elementType);
-      preparedResult =
-          preparingStmt.prepareQueryable(query.queryable, x);
-      statementType = getStatementType(preparedResult);
-    } else {
-      assert query.rel != null;
-      x = query.rel.getRowType();
-      preparedResult = preparingStmt.prepareRel(query.rel);
-      statementType = getStatementType(preparedResult);
-    }
-
-    final List<AvaticaParameter> parameters = new ArrayList<>();
-    final RelDataType parameterRowType = preparedResult.getParameterRowType();
-    for (RelDataTypeField field : parameterRowType.getFieldList()) {
-      RelDataType type = field.getType();
-      parameters.add(
-          new AvaticaParameter(
-              false,
-              getPrecision(type),
-              getScale(type),
-              getTypeOrdinal(type),
-              getTypeName(type),
-              getClassName(type),
-              field.getName()));
-    }
-
-    RelDataType jdbcType = makeStruct(typeFactory, x);
-    final List<List<String>> originList = preparedResult.getFieldOrigins();
-    final List<ColumnMetaData> columns =
-        getColumnMetaDataList(typeFactory, x, jdbcType, originList);
-    Class resultClazz = null;
-    if (preparedResult instanceof Typed) {
-      resultClazz = (Class) ((Typed) preparedResult).getElementType();
-    }
-    final Meta.CursorFactory cursorFactory =
-        preparingStmt.resultConvention == BindableConvention.INSTANCE
-            ? Meta.CursorFactory.ARRAY
-            : Meta.CursorFactory.deduce(columns, resultClazz);
-    //noinspection unchecked
-    final Bindable<T> bindable = preparedResult.getBindable(cursorFactory);
-    return new CalciteSignature<>(
-        query.sql,
-        parameters,
-        preparingStmt.internalParameters,
-        jdbcType,
-        columns,
-        cursorFactory,
-        context.getRootSchema(),
-        preparedResult instanceof Prepare.PreparedResultImpl
-            ? ((Prepare.PreparedResultImpl) preparedResult).collations
-            : ImmutableList.<RelCollation>of(),
-        maxRowCount,
-        bindable,
-        statementType);
-  }
-
-  private SqlValidator createSqlValidator(Context context,
-                                          CalciteCatalogReader catalogReader) {
-    final SqlOperatorTable opTab0 =
-        context.config().fun(SqlOperatorTable.class,
-            SqlStdOperatorTable.instance());
-    final SqlOperatorTable opTab =
-        ChainedSqlOperatorTable.of(opTab0, catalogReader);
-    final JavaTypeFactory typeFactory = context.getTypeFactory();
-    final SqlConformance conformance = context.config().conformance();
-    return new CalciteSqlValidator(opTab, catalogReader, typeFactory,
-        conformance);
-  }
-
-  private List<ColumnMetaData> getColumnMetaDataList(
-          JavaTypeFactory typeFactory, RelDataType x, RelDataType jdbcType,
-          List<List<String>> originList) {
-    final List<ColumnMetaData> columns = new ArrayList<>();
-    for (Ord<RelDataTypeField> pair : Ord.zip(jdbcType.getFieldList())) {
-      final RelDataTypeField field = pair.e;
-      final RelDataType type = field.getType();
-      final RelDataType fieldType =
-          x.isStruct() ? x.getFieldList().get(pair.i).getType() : type;
-      columns.add(
-          metaData(typeFactory, columns.size(), field.getName(), type,
-              fieldType, originList.get(pair.i)));
-    }
-    return columns;
-  }
-
-  private ColumnMetaData metaData(JavaTypeFactory typeFactory, int ordinal,
-                                  String fieldName, RelDataType type, RelDataType fieldType,
-                                  List<String> origins) {
-    final ColumnMetaData.AvaticaType avaticaType =
-        avaticaType(typeFactory, type, fieldType);
-    return new ColumnMetaData(
-        ordinal,
-        false,
-        true,
-        false,
-        false,
-        type.isNullable()
-            ? DatabaseMetaData.columnNullable
-            : DatabaseMetaData.columnNoNulls,
-        true,
-        type.getPrecision(),
-        fieldName,
-        origin(origins, 0),
-        origin(origins, 2),
-        getPrecision(type),
-        getScale(type),
-        origin(origins, 1),
-        null,
-        avaticaType,
-        true,
-        false,
-        false,
-        avaticaType.columnClassName());
-  }
-
-  private ColumnMetaData.AvaticaType avaticaType(JavaTypeFactory typeFactory,
-                                                 RelDataType type, RelDataType fieldType) {
-    final String typeName = getTypeName(type);
-    if (type.getComponentType() != null) {
-      final ColumnMetaData.AvaticaType componentType =
-          avaticaType(typeFactory, type.getComponentType(), null);
-      final Type clazz = typeFactory.getJavaClass(type.getComponentType());
-      final ColumnMetaData.Rep rep = ColumnMetaData.Rep.of(clazz);
-      assert rep != null;
-      return ColumnMetaData.array(componentType, typeName, rep);
-    } else {
-      final int typeOrdinal = getTypeOrdinal(type);
-      switch (typeOrdinal) {
-      case Types.STRUCT:
-        final List<ColumnMetaData> columns = new ArrayList<>();
-        for (RelDataTypeField field : type.getFieldList()) {
-          columns.add(
-              metaData(typeFactory, field.getIndex(), field.getName(),
-                  field.getType(), null, null));
-        }
-        return ColumnMetaData.struct(columns);
-      default:
-        final Type clazz =
-            typeFactory.getJavaClass(Util.first(fieldType, type));
-        final ColumnMetaData.Rep rep = ColumnMetaData.Rep.of(clazz);
-        assert rep != null;
-        return ColumnMetaData.scalar(typeOrdinal, typeName, rep);
-      }
-    }
-  }
-
-  private static String origin(List<String> origins, int offsetFromEnd) {
-    return origins == null || offsetFromEnd >= origins.size()
-        ? null
-        : origins.get(origins.size() - 1 - offsetFromEnd);
-  }
-
-  private int getTypeOrdinal(RelDataType type) {
-    return type.getSqlTypeName().getJdbcOrdinal();
-  }
-
-  private static String getClassName(RelDataType type) {
-    return null;
-  }
-
-  private static int getScale(RelDataType type) {
-    return type.getScale() == RelDataType.SCALE_NOT_SPECIFIED
-        ? 0
-        : type.getScale();
-  }
-
-  private static int getPrecision(RelDataType type) {
-    return type.getPrecision() == RelDataType.PRECISION_NOT_SPECIFIED
-        ? 0
-        : type.getPrecision();
-  }
-
-  /** Returns the type name in string form. Does not include precision, scale
-   * or whether nulls are allowed. Example: "DECIMAL" not "DECIMAL(7, 2)";
-   * "INTEGER" not "JavaType(int)". */
-  private static String getTypeName(RelDataType type) {
-    final SqlTypeName sqlTypeName = type.getSqlTypeName();
-    switch (sqlTypeName) {
-    case ARRAY:
-    case MULTISET:
-    case MAP:
-    case ROW:
-      return type.toString(); // e.g. "INTEGER ARRAY"
-    case INTERVAL_YEAR_MONTH:
-      return "INTERVAL_YEAR_TO_MONTH";
-    case INTERVAL_DAY_HOUR:
-      return "INTERVAL_DAY_TO_HOUR";
-    case INTERVAL_DAY_MINUTE:
-      return "INTERVAL_DAY_TO_MINUTE";
-    case INTERVAL_DAY_SECOND:
-      return "INTERVAL_DAY_TO_SECOND";
-    case INTERVAL_HOUR_MINUTE:
-      return "INTERVAL_HOUR_TO_MINUTE";
-    case INTERVAL_HOUR_SECOND:
-      return "INTERVAL_HOUR_TO_SECOND";
-    case INTERVAL_MINUTE_SECOND:
-      return "INTERVAL_MINUTE_TO_SECOND";
-    default:
-      return sqlTypeName.getName(); // e.g. "DECIMAL", "INTERVAL_YEAR_MONTH"
-    }
-  }
-
-  protected void populateMaterializations(Context context,
-                                          RelOptPlanner planner, Prepare.Materialization materialization) {
-    // REVIEW: initialize queryRel and tableRel inside MaterializationService,
-    // not here?
-    try {
-      final CalciteSchema schema = materialization.materializedTable.schema;
-      CalciteCatalogReader catalogReader =
-          new CalciteCatalogReader(
-              schema.root(),
-              context.config().caseSensitive(),
-              materialization.viewSchemaPath,
-              context.getTypeFactory());
-      final CalciteMaterializer materializer =
-          new CalciteMaterializer(this, context, catalogReader, schema, planner,
-              createConvertletTable());
-      materializer.populate(materialization);
-    } catch (Exception e) {
-      throw new RuntimeException("While populating materialization "
-          + materialization.materializedTable.path(), e);
-    }
-  }
-
-  private static RelDataType makeStruct(
-      RelDataTypeFactory typeFactory,
-      RelDataType type) {
-    if (type.isStruct()) {
-      return type;
-    }
-    return typeFactory.builder().add("$0", type).build();
-  }
-
-  /** Executes a prepare action. */
-  public <R> R perform(CalciteServerStatement statement,
-      Frameworks.PrepareAction<R> action) {
-    final CalcitePrepare.Context prepareContext =
-        statement.createPrepareContext();
-    final JavaTypeFactory typeFactory = prepareContext.getTypeFactory();
-    final CalciteSchema schema =
-        action.getConfig().getDefaultSchema() != null
-            ? CalciteSchema.from(action.getConfig().getDefaultSchema())
-            : prepareContext.getRootSchema();
-    CalciteCatalogReader catalogReader =
-        new CalciteCatalogReader(schema.root(),
-            prepareContext.config().caseSensitive(),
-            schema.path(null),
-            typeFactory);
-    final RexBuilder rexBuilder = new RexBuilder(typeFactory);
-    final RelOptPlanner planner =
-        createPlanner(prepareContext,
-            action.getConfig().getContext(),
-            action.getConfig().getCostFactory());
-    final RelOptCluster cluster = createCluster(planner, rexBuilder);
-    return action.apply(cluster, catalogReader,
-        prepareContext.getRootSchema().plus(), statement);
-  }
-
-  /** Holds state for the process of preparing a SQL statement. */
-  static class CalcitePreparingStmt extends Prepare
-      implements RelOptTable.ViewExpander {
-    protected final RelOptPlanner planner;
-    protected final RexBuilder rexBuilder;
-    protected final CalcitePrepareImpl prepare;
-    protected final CalciteSchema schema;
-    protected final RelDataTypeFactory typeFactory;
-    protected final SqlRexConvertletTable convertletTable;
-    private final EnumerableRel.Prefer prefer;
-    private final Map<String, Object> internalParameters =
-        Maps.newLinkedHashMap();
-    private int expansionDepth;
-    private SqlValidator sqlValidator;
-
-    public CalcitePreparingStmt(CalcitePrepareImpl prepare,
-        Context context,
-        CatalogReader catalogReader,
-        RelDataTypeFactory typeFactory,
-        CalciteSchema schema,
-        EnumerableRel.Prefer prefer,
-        RelOptPlanner planner,
-        Convention resultConvention,
-        SqlRexConvertletTable convertletTable) {
-      super(context, catalogReader, resultConvention);
-      this.prepare = prepare;
-      this.schema = schema;
-      this.prefer = prefer;
-      this.planner = planner;
-      this.typeFactory = typeFactory;
-      this.convertletTable = convertletTable;
-      this.rexBuilder = new RexBuilder(typeFactory);
-    }
-
-    @Override protected void init(Class runtimeContextClass) {
-    }
-
-    public PreparedResult prepareQueryable(
-        final Queryable queryable,
-        RelDataType resultType) {
-      return prepare_(
-          new Supplier<RelNode>() {
-            public RelNode get() {
-              final RelOptCluster cluster =
-                  prepare.createCluster(planner, rexBuilder);
-              return new LixToRelTranslator(cluster, CalcitePreparingStmt.this)
-                  .translate(queryable);
-            }
-          }, resultType);
-    }
-
-    public PreparedResult prepareRel(final RelNode rel) {
-      return prepare_(
-          new Supplier<RelNode>() {
-            public RelNode get() {
-              return rel;
-            }
-          }, rel.getRowType());
-    }
-
-    private PreparedResult prepare_(Supplier<RelNode> fn,
-                                    RelDataType resultType) {
-      queryString = null;
-      Class runtimeContextClass = Object.class;
-      init(runtimeContextClass);
-
-      final RelNode rel = fn.get();
-      final RelDataType rowType = rel.getRowType();
-      final List<Pair<Integer, String>> fields =
-          Pair.zip(ImmutableIntList.identity(rowType.getFieldCount()),
-              rowType.getFieldNames());
-      final RelCollation collation =
-          rel instanceof Sort
-              ? ((Sort) rel).collation
-              : RelCollations.EMPTY;
-      RelRoot root = new RelRoot(rel, resultType, SqlKind.SELECT, fields,
-          collation);
-
-      if (timingTracer != null) {
-        timingTracer.traceTime("end sql2rel");
-      }
-
-      final RelDataType jdbcType =
-          makeStruct(rexBuilder.getTypeFactory(), resultType);
-      fieldOrigins = Collections.nCopies(jdbcType.getFieldCount(), null);
-      parameterRowType = rexBuilder.getTypeFactory().builder().build();
-
-      // Structured type flattening, view expansion, and plugging in
-      // physical storage.
-      root = root.withRel(flattenTypes(root.rel, true));
-
-      // Trim unused fields.
-      root = trimUnusedFields(root);
-
-      final List<Materialization> materializations = ImmutableList.of();
-      final List<LatticeEntry> lattices = ImmutableList.of();
-      long start = System.currentTimeMillis();
-      LOGGER.info("Begin optimize");
-      root = optimize(root, materializations, lattices);
-      LOGGER.info("End optimize, take : " + (System.currentTimeMillis() - start));
-
-      if (timingTracer != null) {
-          timingTracer.traceTime("end optimization");
-      }
-
-      return implement(root);
-    }
-
-    @Override protected SqlToRelConverter getSqlToRelConverter(
-        SqlValidator validator,
-        CatalogReader catalogReader,
-        SqlToRelConverter.Config config) {
-      final RelOptCluster cluster = prepare.createCluster(planner, rexBuilder);
-      SqlToRelConverter sqlToRelConverter =
-          new SqlToRelConverter(this, validator, catalogReader, cluster,
-              convertletTable, config);
-      return sqlToRelConverter;
-    }
-
-    @Override public RelNode flattenTypes(
-        RelNode rootRel,
-        boolean restructure) {
-      final SparkHandler spark = context.spark();
-      if (spark.enabled()) {
-        return spark.flattenTypes(planner, rootRel, restructure);
-      }
-      return rootRel;
-    }
-
-    @Override protected RelNode decorrelate(SqlToRelConverter sqlToRelConverter,
-                                            SqlNode query, RelNode rootRel) {
-      return sqlToRelConverter.decorrelate(query, rootRel);
-    }
-
-    @Override public RelRoot expandView(RelDataType rowType, String queryString,
-                                        List<String> schemaPath, List<String> viewPath) {
-      expansionDepth++;
-
-      SqlParser parser = prepare.createParser(queryString);
-      SqlNode sqlNode;
-      try {
-        sqlNode = parser.parseQuery();
-      } catch (SqlParseException e) {
-        throw new RuntimeException("parse failed", e);
-      }
-      // View may have different schema path than current connection.
-      final CatalogReader catalogReader =
-          this.catalogReader.withSchemaPath(schemaPath);
-      SqlValidator validator = createSqlValidator(catalogReader);
-      SqlNode sqlNode1 = validator.validate(sqlNode);
-      final SqlToRelConverter.Config config = SqlToRelConverter.configBuilder()
-              .withTrimUnusedFields(true).build();
-      SqlToRelConverter sqlToRelConverter =
-          getSqlToRelConverter(validator, catalogReader, config);
-      RelRoot root =
-          sqlToRelConverter.convertQuery(sqlNode1, true, false);
-
-      --expansionDepth;
-      return root;
-    }
-
-    protected SqlValidator createSqlValidator(CatalogReader catalogReader) {
-      return prepare.createSqlValidator(context,
-          (CalciteCatalogReader) catalogReader);
-    }
-
-    @Override protected SqlValidator getSqlValidator() {
-      if (sqlValidator == null) {
-        sqlValidator = createSqlValidator(catalogReader);
-      }
-      return sqlValidator;
-    }
-
-    @Override protected PreparedResult createPreparedExplanation(
-        RelDataType resultType,
-        RelDataType parameterRowType,
-        RelRoot root,
-        SqlExplainFormat format,
-        SqlExplainLevel detailLevel) {
-      return new CalcitePreparedExplain(resultType, parameterRowType, root,
-          format, detailLevel);
-    }
-
-    @Override protected PreparedResult implement(RelRoot root) {
-      if(RelUtils.findOLAPRel(root.rel) && !root.rel.getClass().getName().contains("OLAPToEnumerableConverter")){
-        String dumpPlan = RelOptUtil.dumpPlan("", root.rel, false, SqlExplainLevel.DIGEST_ATTRIBUTES);
-        throw new IllegalArgumentException("Error planer:" + dumpPlan);
-      }
-      RelDataType resultType = root.rel.getRowType();
-      boolean isDml = root.kind.belongsTo(SqlKind.DML);
-      final Bindable bindable;
-      if (resultConvention == BindableConvention.INSTANCE) {
-        bindable = Interpreters.bindable(root.rel);
-      } else {
-        EnumerableRel enumerable = (EnumerableRel) root.rel;
-        if (!root.isRefTrivial()) {
-          final List<RexNode> projects = new ArrayList<>();
-          final RexBuilder rexBuilder = enumerable.getCluster().getRexBuilder();
-          for (int field : Pair.left(root.fields)) {
-            projects.add(rexBuilder.makeInputRef(enumerable, field));
-          }
-          RexProgram program = RexProgram.create(enumerable.getRowType(),
-              projects, null, root.validatedRowType, rexBuilder);
-          enumerable = EnumerableCalc.create(enumerable, program);
-        }
-
-        try {
-          CatalogReader.THREAD_LOCAL.set(catalogReader);
-          bindable = EnumerableInterpretable.toBindable(internalParameters,
-              context.spark(), enumerable, prefer);
-        } finally {
-          CatalogReader.THREAD_LOCAL.remove();
-        }
-      }
-
-      if (timingTracer != null) {
-        timingTracer.traceTime("end codegen");
-      }
-
-      if (timingTracer != null) {
-        timingTracer.traceTime("end compilation");
-      }
-
-      return new PreparedResultImpl(
-          resultType,
-          parameterRowType,
-          fieldOrigins,
-          root.collation.getFieldCollations().isEmpty()
-              ? ImmutableList.<RelCollation>of()
-              : ImmutableList.of(root.collation),
-          root.rel,
-          mapTableModOp(isDml, root.kind),
-          isDml) {
-        public String getCode() {
-          throw new UnsupportedOperationException();
-        }
-
-        public Bindable getBindable(Meta.CursorFactory cursorFactory) {
-          return bindable;
-        }
-
-        public Type getElementType() {
-          return ((Typed) bindable).getElementType();
-        }
-      };
-    }
-
-    @Override protected List<Materialization> getMaterializations() {
-      final List<Materialization> materializations =
-          context.config().materializationsEnabled()
-              ? MaterializationService.instance().query(schema)
-              : ImmutableList.<Prepare.Materialization>of();
-      for (Prepare.Materialization materialization : materializations) {
-        prepare.populateMaterializations(context, planner, materialization);
-      }
-      return materializations;
-    }
-
-    @Override protected List<LatticeEntry> getLattices() {
-      return Schemas.getLatticeEntries(schema);
-    }
-  }
-
-  /** An {@code EXPLAIN} statement, prepared and ready to execute. */
-  private static class CalcitePreparedExplain extends Prepare.PreparedExplain {
-    public CalcitePreparedExplain(
-        RelDataType resultType,
-        RelDataType parameterRowType,
-        RelRoot root,
-        SqlExplainFormat format,
-        SqlExplainLevel detailLevel) {
-      super(resultType, parameterRowType, root, format, detailLevel);
-    }
-
-    public Bindable getBindable(final Meta.CursorFactory cursorFactory) {
-      final String explanation = getCode();
-      return new Bindable() {
-        public Enumerable bind(DataContext dataContext) {
-          switch (cursorFactory.style) {
-          case ARRAY:
-            return Linq4j.singletonEnumerable(new String[] {explanation});
-          case OBJECT:
-          default:
-            return Linq4j.singletonEnumerable(explanation);
-          }
-        }
-      };
-    }
-  }
-
-  /** Translator from Java AST to {@link RexNode}. */
-  interface ScalarTranslator {
-    RexNode toRex(BlockStatement statement);
-    List<RexNode> toRexList(BlockStatement statement);
-    RexNode toRex(Expression expression);
-    ScalarTranslator bind(List<ParameterExpression> parameterList,
-                          List<RexNode> values);
-  }
-
-  /** Basic translator. */
-  static class EmptyScalarTranslator implements ScalarTranslator {
-    private final RexBuilder rexBuilder;
-
-    public EmptyScalarTranslator(RexBuilder rexBuilder) {
-      this.rexBuilder = rexBuilder;
-    }
-
-    public static ScalarTranslator empty(RexBuilder builder) {
-      return new EmptyScalarTranslator(builder);
-    }
-
-    public List<RexNode> toRexList(BlockStatement statement) {
-      final List<Expression> simpleList = simpleList(statement);
-      final List<RexNode> list = new ArrayList<>();
-      for (Expression expression1 : simpleList) {
-        list.add(toRex(expression1));
-      }
-      return list;
-    }
-
-    public RexNode toRex(BlockStatement statement) {
-      return toRex(Blocks.simple(statement));
-    }
-
-    private static List<Expression> simpleList(BlockStatement statement) {
-      Expression simple = Blocks.simple(statement);
-      if (simple instanceof NewExpression) {
-        NewExpression newExpression = (NewExpression) simple;
-        return newExpression.arguments;
-      } else {
-        return Collections.singletonList(simple);
-      }
-    }
-
-    public RexNode toRex(Expression expression) {
-      switch (expression.getNodeType()) {
-      case MemberAccess:
-        // Case-sensitive name match because name was previously resolved.
-        return rexBuilder.makeFieldAccess(
-            toRex(
-                ((MemberExpression) expression).expression),
-            ((MemberExpression) expression).field.getName(),
-            true);
-      case GreaterThan:
-        return binary(expression, SqlStdOperatorTable.GREATER_THAN);
-      case LessThan:
-        return binary(expression, SqlStdOperatorTable.LESS_THAN);
-      case Parameter:
-        return parameter((ParameterExpression) expression);
-      case Call:
-        MethodCallExpression call = (MethodCallExpression) expression;
-        SqlOperator operator =
-            RexToLixTranslator.JAVA_TO_SQL_METHOD_MAP.get(call.method);
-        if (operator != null) {
-          return rexBuilder.makeCall(
-              type(call),
-              operator,
-              toRex(
-                  Expressions.<Expression>list()
-                      .appendIfNotNull(call.targetExpression)
-                      .appendAll(call.expressions)));
-        }
-        throw new RuntimeException(
-            "Could translate call to method " + call.method);
-      case Constant:
-        final ConstantExpression constant =
-            (ConstantExpression) expression;
-        Object value = constant.value;
-        if (value instanceof Number) {
-          Number number = (Number) value;
-          if (value instanceof Double || value instanceof Float) {
-            return rexBuilder.makeApproxLiteral(
-                BigDecimal.valueOf(number.doubleValue()));
-          } else if (value instanceof BigDecimal) {
-            return rexBuilder.makeExactLiteral((BigDecimal) value);
-          } else {
-            return rexBuilder.makeExactLiteral(
-                BigDecimal.valueOf(number.longValue()));
-          }
-        } else if (value instanceof Boolean) {
-          return rexBuilder.makeLiteral((Boolean) value);
-        } else {
-          return rexBuilder.makeLiteral(constant.toString());
-        }
-      default:
-        throw new UnsupportedOperationException(
-            "unknown expression type " + expression.getNodeType() + " "
-            + expression);
-      }
-    }
-
-    private RexNode binary(Expression expression, SqlBinaryOperator op) {
-      BinaryExpression call = (BinaryExpression) expression;
-      return rexBuilder.makeCall(type(call), op,
-          toRex(ImmutableList.of(call.expression0, call.expression1)));
-    }
-
-    private List<RexNode> toRex(List<Expression> expressions) {
-      final List<RexNode> list = new ArrayList<>();
-      for (Expression expression : expressions) {
-        list.add(toRex(expression));
-      }
-      return list;
-    }
-
-    protected RelDataType type(Expression expression) {
-      final Type type = expression.getType();
-      return ((JavaTypeFactory) rexBuilder.getTypeFactory()).createType(type);
-    }
-
-    public ScalarTranslator bind(
-            List<ParameterExpression> parameterList, List<RexNode> values) {
-      return new LambdaScalarTranslator(
-          rexBuilder, parameterList, values);
-    }
-
-    public RexNode parameter(ParameterExpression param) {
-      throw new RuntimeException("unknown parameter " + param);
-    }
-  }
-
-  /** Translator that looks for parameters. */
-  private static class LambdaScalarTranslator extends EmptyScalarTranslator {
-    private final List<ParameterExpression> parameterList;
-    private final List<RexNode> values;
-
-    public LambdaScalarTranslator(
-        RexBuilder rexBuilder,
-        List<ParameterExpression> parameterList,
-        List<RexNode> values) {
-      super(rexBuilder);
-      this.parameterList = parameterList;
-      this.values = values;
-    }
-
-    public RexNode parameter(ParameterExpression param) {
-      int i = parameterList.indexOf(param);
-      if (i >= 0) {
-        return values.get(i);
-      }
-      throw new RuntimeException("unknown parameter " + param);
-    }
-  }
-}
-
-// End CalcitePrepareImpl.java
diff --git a/atopcalcite/src/main/java/org/apache/calcite/prepare/OnlyPrepareEarlyAbortException.java b/atopcalcite/src/main/java/org/apache/calcite/prepare/OnlyPrepareEarlyAbortException.java
deleted file mode 100644
index 8493484..0000000
--- a/atopcalcite/src/main/java/org/apache/calcite/prepare/OnlyPrepareEarlyAbortException.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
-*/
-package org.apache.calcite.prepare;
-
-import org.apache.calcite.jdbc.CalcitePrepare;
-
-public class OnlyPrepareEarlyAbortException extends RuntimeException {
-    
-    private CalcitePrepare.Context context;
-    private org.apache.calcite.jdbc.CalcitePrepare.ParseResult preparedResult;
-
-    public OnlyPrepareEarlyAbortException(CalcitePrepare.Context context,
-            org.apache.calcite.jdbc.CalcitePrepare.ParseResult preparedResult) {
-        this.context = context;
-        this.preparedResult = preparedResult;
-    }
-
-    public CalcitePrepare.Context getContext() {
-        return context;
-    }
-
-    public CalcitePrepare.ParseResult getPreparedResult() {
-        return preparedResult;
-    }
-}
diff --git a/atopcalcite/src/main/java/org/apache/calcite/rel/rules/FilterJoinRule.java b/atopcalcite/src/main/java/org/apache/calcite/rel/rules/FilterJoinRule.java
deleted file mode 100644
index f758b40..0000000
--- a/atopcalcite/src/main/java/org/apache/calcite/rel/rules/FilterJoinRule.java
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.calcite.rel.rules;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.calcite.plan.RelOptRule;
-import org.apache.calcite.plan.RelOptRuleCall;
-import org.apache.calcite.plan.RelOptRuleOperand;
-import org.apache.calcite.plan.RelOptUtil;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.core.EquiJoin;
-import org.apache.calcite.rel.core.Filter;
-import org.apache.calcite.rel.core.Join;
-import org.apache.calcite.rel.core.JoinRelType;
-import org.apache.calcite.rel.core.RelFactories;
-import org.apache.calcite.rel.type.RelDataType;
-import org.apache.calcite.rex.RexBuilder;
-import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.rex.RexUtil;
-import org.apache.calcite.tools.RelBuilder;
-import org.apache.calcite.tools.RelBuilderFactory;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
-/**
- * Turn it off.
- * Though try to turn it off in OLAPTableScan, sometimes it still triggerd.
- */
-
-/**
- * Planner rule that pushes filters above and
- * within a join node into the join node and/or its children nodes.
- */
-public abstract class FilterJoinRule extends RelOptRule {
-    /** Predicate that always returns true. With this predicate, every filter
-     * will be pushed into the ON clause. */
-    public static final Predicate TRUE_PREDICATE = new Predicate() {
-        public boolean apply(Join join, JoinRelType joinType, RexNode exp) {
-            return true;
-        }
-    };
-
-    /** Rule that pushes predicates from a Filter into the Join below them. */
-    public static final FilterJoinRule FILTER_ON_JOIN = new FilterIntoJoinRule(true, RelFactories.LOGICAL_BUILDER,
-            TRUE_PREDICATE);
-
-    /** Dumber version of {@link #FILTER_ON_JOIN}. Not intended for production
-     * use, but keeps some tests working for which {@code FILTER_ON_JOIN} is too
-     * smart. */
-    public static final FilterJoinRule DUMB_FILTER_ON_JOIN = new FilterIntoJoinRule(false, RelFactories.LOGICAL_BUILDER,
-            TRUE_PREDICATE);
-
-    /** Rule that pushes predicates in a Join into the inputs to the join. */
-    public static final FilterJoinRule JOIN = new JoinConditionPushRule(RelFactories.LOGICAL_BUILDER, TRUE_PREDICATE);
-
-    /** Whether to try to strengthen join-type. */
-    private final boolean smart;
-
-    /** Predicate that returns whether a filter is valid in the ON clause of a
-     * join for this particular kind of join. If not, Calcite will push it back to
-     * above the join. */
-    private final Predicate predicate;
-
-    //~ Constructors -----------------------------------------------------------
-
-    /**
-     * Creates a FilterProjectTransposeRule with an explicit root operand and
-     * factories.
-     */
-    protected FilterJoinRule(RelOptRuleOperand operand, String id, boolean smart, RelBuilderFactory relBuilderFactory,
-            Predicate predicate) {
-        super(operand, relBuilderFactory, "FilterJoinRule:" + id);
-        this.smart = smart;
-        this.predicate = Preconditions.checkNotNull(predicate);
-    }
-
-    /**
-     * Creates a FilterJoinRule with an explicit root operand and
-     * factories.
-     */
-    @Deprecated // to be removed before 2.0
-    protected FilterJoinRule(RelOptRuleOperand operand, String id, boolean smart,
-            RelFactories.FilterFactory filterFactory, RelFactories.ProjectFactory projectFactory) {
-        this(operand, id, smart, RelBuilder.proto(filterFactory, projectFactory), TRUE_PREDICATE);
-    }
-
-    /**
-     * Creates a FilterProjectTransposeRule with an explicit root operand and
-     * factories.
-     */
-    @Deprecated // to be removed before 2.0
-    protected FilterJoinRule(RelOptRuleOperand operand, String id, boolean smart,
-            RelFactories.FilterFactory filterFactory, RelFactories.ProjectFactory projectFactory, Predicate predicate) {
-        this(operand, id, smart, RelBuilder.proto(filterFactory, projectFactory), predicate);
-    }
-
-    //~ Methods ----------------------------------------------------------------
-
-    protected void perform(RelOptRuleCall call, Filter filter, Join join) {
-        final List<RexNode> joinFilters = RelOptUtil.conjunctions(join.getCondition());
-        final List<RexNode> origJoinFilters = ImmutableList.copyOf(joinFilters);
-
-        // If there is only the joinRel,
-        // make sure it does not match a cartesian product joinRel
-        // (with "true" condition), otherwise this rule will be applied
-        // again on the new cartesian product joinRel.
-        if (filter == null && joinFilters.isEmpty()) {
-            return;
-        }
-
-        final List<RexNode> aboveFilters = filter != null ? RelOptUtil.conjunctions(filter.getCondition())
-                : Lists.<RexNode> newArrayList();
-        final ImmutableList<RexNode> origAboveFilters = ImmutableList.copyOf(aboveFilters);
-
-        // Simplify Outer Joins
-        JoinRelType joinType = join.getJoinType();
-        if (smart && !origAboveFilters.isEmpty() && join.getJoinType() != JoinRelType.INNER) {
-            joinType = RelOptUtil.simplifyJoin(join, origAboveFilters, joinType);
-        }
-
-        final List<RexNode> leftFilters = new ArrayList<>();
-        final List<RexNode> rightFilters = new ArrayList<>();
-
-        // TODO - add logic to derive additional filters.  E.g., from
-        // (t1.a = 1 AND t2.a = 2) OR (t1.b = 3 AND t2.b = 4), you can
-        // derive table filters:
-        // (t1.a = 1 OR t1.b = 3)
-        // (t2.a = 2 OR t2.b = 4)
-
-        // Try to push down above filters. These are typically where clause
-        // filters. They can be pushed down if they are not on the NULL
-        // generating side.
-        boolean filterPushed = false;
-        if (RelOptUtil.classifyFilters(join, aboveFilters, joinType, !(join instanceof EquiJoin),
-                !joinType.generatesNullsOnLeft(), !joinType.generatesNullsOnRight(), joinFilters, leftFilters,
-                rightFilters)) {
-            filterPushed = true;
-        }
-
-        // Move join filters up if needed
-        validateJoinFilters(aboveFilters, joinFilters, join, joinType);
-
-        // If no filter got pushed after validate, reset filterPushed flag
-        if (leftFilters.isEmpty() && rightFilters.isEmpty() && joinFilters.size() == origJoinFilters.size()) {
-            if (Sets.newHashSet(joinFilters).equals(Sets.newHashSet(origJoinFilters))) {
-                filterPushed = false;
-            }
-        }
-
-        // Try to push down filters in ON clause. A ON clause filter can only be
-        // pushed down if it does not affect the non-matching set, i.e. it is
-        // not on the side which is preserved.
-        if (RelOptUtil.classifyFilters(join, joinFilters, joinType, false, !joinType.generatesNullsOnRight(),
-                !joinType.generatesNullsOnLeft(), joinFilters, leftFilters, rightFilters)) {
-            filterPushed = true;
-        }
-
-        // if nothing actually got pushed and there is nothing leftover,
-        // then this rule is a no-op
-        if ((!filterPushed && joinType == join.getJoinType())
-                || (joinFilters.isEmpty() && leftFilters.isEmpty() && rightFilters.isEmpty())) {
-            return;
-        }
-
-        // create Filters on top of the children if any filters were
-        // pushed to them
-        final RexBuilder rexBuilder = join.getCluster().getRexBuilder();
-        final RelBuilder relBuilder = call.builder();
-        final RelNode leftRel = relBuilder.push(join.getLeft()).filter(leftFilters).build();
-        final RelNode rightRel = relBuilder.push(join.getRight()).filter(rightFilters).build();
-
-        // create the new join node referencing the new children and
-        // containing its new join filters (if there are any)
-        final ImmutableList<RelDataType> fieldTypes = ImmutableList.<RelDataType> builder()
-                .addAll(RelOptUtil.getFieldTypeList(leftRel.getRowType()))
-                .addAll(RelOptUtil.getFieldTypeList(rightRel.getRowType())).build();
-        final RexNode joinFilter = RexUtil.composeConjunction(rexBuilder,
-                RexUtil.fixUp(rexBuilder, joinFilters, fieldTypes), false);
-
-        // If nothing actually got pushed and there is nothing leftover,
-        // then this rule is a no-op
-        if (joinFilter.isAlwaysTrue() && leftFilters.isEmpty() && rightFilters.isEmpty()
-                && joinType == join.getJoinType()) {
-            return;
-        }
-
-        RelNode newJoinRel = join.copy(join.getTraitSet(), joinFilter, leftRel, rightRel, joinType,
-                join.isSemiJoinDone());
-        call.getPlanner().onCopy(join, newJoinRel);
-        if (!leftFilters.isEmpty()) {
-            call.getPlanner().onCopy(filter, leftRel);
-        }
-        if (!rightFilters.isEmpty()) {
-            call.getPlanner().onCopy(filter, rightRel);
-        }
-
-        relBuilder.push(newJoinRel);
-
-        // Create a project on top of the join if some of the columns have become
-        // NOT NULL due to the join-type getting stricter.
-        relBuilder.convert(join.getRowType(), false);
-
-        // create a FilterRel on top of the join if needed
-        relBuilder.filter(
-                RexUtil.fixUp(rexBuilder, aboveFilters, RelOptUtil.getFieldTypeList(relBuilder.peek().getRowType())));
-
-        call.transformTo(relBuilder.build());
-    }
-
-    /**
-     * Validates that target execution framework can satisfy join filters.
-     *
-     * <p>If the join filter cannot be satisfied (for example, if it is
-     * {@code l.c1 > r.c2} and the join only supports equi-join), removes the
-     * filter from {@code joinFilters} and adds it to {@code aboveFilters}.
-     *
-     * <p>The default implementation does nothing; i.e. the join can handle all
-     * conditions.
-     *
-     * @param aboveFilters Filter above Join
-     * @param joinFilters Filters in join condition
-     * @param join Join
-     * @param joinType JoinRelType could be different from type in Join due to
-     * outer join simplification.
-     */
-    protected void validateJoinFilters(List<RexNode> aboveFilters, List<RexNode> joinFilters, Join join,
-            JoinRelType joinType) {
-        final Iterator<RexNode> filterIter = joinFilters.iterator();
-        while (filterIter.hasNext()) {
-            RexNode exp = filterIter.next();
-            if (!predicate.apply(join, joinType, exp)) {
-                aboveFilters.add(exp);
-                filterIter.remove();
-            }
-        }
-    }
-
-    /** Rule that pushes parts of the join condition to its inputs. */
-    public static class JoinConditionPushRule extends FilterJoinRule {
-        public JoinConditionPushRule(RelBuilderFactory relBuilderFactory, Predicate predicate) {
-            super(RelOptRule.operand(Join.class, RelOptRule.any()), "FilterJoinRule:no-filter", true, relBuilderFactory,
-                    predicate);
-        }
-
-        @Deprecated // to be removed before 2.0
-        public JoinConditionPushRule(RelFactories.FilterFactory filterFactory,
-                RelFactories.ProjectFactory projectFactory, Predicate predicate) {
-            this(RelBuilder.proto(filterFactory, projectFactory), predicate);
-        }
-
-        @Override
-        public void onMatch(RelOptRuleCall call) {
-            Join join = call.rel(0);
-            // HACK POINT
-//            perform(call, null, join);
-        }
-    }
-
-    /** Rule that tries to push filter expressions into a join
-     * condition and into the inputs of the join. */
-    public static class FilterIntoJoinRule extends FilterJoinRule {
-        public FilterIntoJoinRule(boolean smart, RelBuilderFactory relBuilderFactory, Predicate predicate) {
-            super(operand(Filter.class, operand(Join.class, RelOptRule.any())), "FilterJoinRule:filter", smart,
-                    relBuilderFactory, predicate);
-        }
-
-        @Deprecated // to be removed before 2.0
-        public FilterIntoJoinRule(boolean smart, RelFactories.FilterFactory filterFactory,
-                RelFactories.ProjectFactory projectFactory, Predicate predicate) {
-            this(smart, RelBuilder.proto(filterFactory, projectFactory), predicate);
-        }
-
-        @Override
-        public void onMatch(RelOptRuleCall call) {
-            Filter filter = call.rel(0);
-            Join join = call.rel(1);
-            // HACK POINT
-//            perform(call, filter, join);
-        }
-    }
-
-    /** Predicate that returns whether a filter is valid in the ON clause of a
-     * join for this particular kind of join. If not, Calcite will push it back to
-     * above the join. */
-    public interface Predicate {
-        boolean apply(Join join, JoinRelType joinType, RexNode exp);
-    }
-}
-
-// End FilterJoinRule.java
\ No newline at end of file
diff --git a/atopcalcite/src/main/java/org/apache/calcite/rel/rules/OLAPJoinPushThroughJoinRule.java b/atopcalcite/src/main/java/org/apache/calcite/rel/rules/OLAPJoinPushThroughJoinRule.java
deleted file mode 100644
index 35f2ae6..0000000
--- a/atopcalcite/src/main/java/org/apache/calcite/rel/rules/OLAPJoinPushThroughJoinRule.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
-*/
-package org.apache.calcite.rel.rules;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.annotation.Nullable;
-
-import org.apache.calcite.plan.RelOptCluster;
-import org.apache.calcite.plan.RelOptRule;
-import org.apache.calcite.plan.RelOptRuleCall;
-import org.apache.calcite.plan.RelOptUtil;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.core.Join;
-import org.apache.calcite.rel.core.RelFactories;
-import org.apache.calcite.rel.core.TableScan;
-import org.apache.calcite.rel.logical.LogicalJoin;
-import org.apache.calcite.rex.RexBuilder;
-import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.rex.RexPermuteInputsShuttle;
-import org.apache.calcite.rex.RexUtil;
-import org.apache.calcite.tools.RelBuilder;
-import org.apache.calcite.tools.RelBuilderFactory;
-import org.apache.calcite.util.ImmutableBitSet;
-import org.apache.calcite.util.mapping.Mappings;
-
-import com.google.common.base.Predicate;
-
-/**
- * modified form org.apache.calcite.rel.rules.JoinPushThroughJoinRule.
- * The goal is to move joins with sub-queries after joins with tables,
- * so that pre-defined join with tables can be matched
- */
-public class OLAPJoinPushThroughJoinRule extends RelOptRule {
-    /**
-     * Instance of the rule that works on logical joins only, and pushes to the
-     * right.
-     */
-    public static final RelOptRule INSTANCE = new OLAPJoinPushThroughJoinRule("OLAPJoinPushThroughJoinRule", LogicalJoin.class, RelFactories.LOGICAL_BUILDER);
-
-    public OLAPJoinPushThroughJoinRule(String description, Class<? extends Join> clazz, RelBuilderFactory relBuilderFactory) {
-        super(operand(clazz,
-
-                operand(clazz, operand(RelNode.class, any()), operand(RelNode.class, null, new Predicate<RelNode>() {
-                    @Override
-                    public boolean apply(@Nullable RelNode input) {
-                        return !(input instanceof TableScan);
-                    }
-                }, any())),
-
-                operand(TableScan.class, any())), relBuilderFactory, description);
-    }
-
-    @Override
-    public void onMatch(RelOptRuleCall call) {
-        onMatchRight(call);
-    }
-
-    private void onMatchRight(RelOptRuleCall call) {
-        final Join topJoin = call.rel(0);
-        final Join bottomJoin = call.rel(1);
-        final RelNode relC = call.rel(4);
-        final RelNode relA = bottomJoin.getLeft();
-        final RelNode relB = bottomJoin.getRight();
-        final RelOptCluster cluster = topJoin.getCluster();
-        //        Preconditions.checkState(relA == call.rel(2));
-        //        Preconditions.checkState(relB == call.rel(3));
-
-        //        topJoin
-        //        /     \
-        //   bottomJoin  C
-        //    /    \
-        //   A      B
-
-        final int aCount = relA.getRowType().getFieldCount();
-        final int bCount = relB.getRowType().getFieldCount();
-        final int cCount = relC.getRowType().getFieldCount();
-        final ImmutableBitSet bBitSet = ImmutableBitSet.range(aCount, aCount + bCount);
-
-        // becomes
-        //
-        //        newTopJoin
-        //        /        \
-        //   newBottomJoin  B
-        //    /    \
-        //   A      C
-
-        // If either join is not inner, we cannot proceed.
-        // (Is this too strict?)
-        //        if (topJoin.getJoinType() != JoinRelType.INNER || bottomJoin.getJoinType() != JoinRelType.INNER) {
-        //            return;
-        //        }
-
-        // Split the condition of topJoin into a conjunction. Each of the
-        // parts that does not use columns from B can be pushed down.
-        final List<RexNode> intersecting = new ArrayList<>();
-        final List<RexNode> nonIntersecting = new ArrayList<>();
-        split(topJoin.getCondition(), bBitSet, intersecting, nonIntersecting);
-
-        // If there's nothing to push down, it's not worth proceeding.
-        if (nonIntersecting.isEmpty()) {
-            return;
-        }
-
-        // Split the condition of bottomJoin into a conjunction. Each of the
-        // parts that use columns from B will need to be pulled up.
-        final List<RexNode> bottomIntersecting = new ArrayList<>();
-        final List<RexNode> bottomNonIntersecting = new ArrayList<>();
-        split(bottomJoin.getCondition(), bBitSet, bottomIntersecting, bottomNonIntersecting);
-
-        // target: | A       | C      |
-        // source: | A       | B | C      |
-        //        final Mappings.TargetMapping bottomMapping = Mappings
-        //            .createShiftMapping(aCount + bCount + cCount, 0, 0, aCount, aCount, aCount + bCount,
-        //                cCount);
-
-        final Mappings.TargetMapping bottomMapping = Mappings.createShiftMapping(aCount + bCount + cCount, 0, 0, aCount, aCount + cCount, aCount, bCount, aCount, aCount + bCount, cCount);
-        final List<RexNode> newBottomList = new ArrayList<>();
-        new RexPermuteInputsShuttle(bottomMapping, relA, relC).visitList(nonIntersecting, newBottomList);
-        new RexPermuteInputsShuttle(bottomMapping, relA, relC).visitList(bottomNonIntersecting, newBottomList);
-        final RexBuilder rexBuilder = cluster.getRexBuilder();
-        RexNode newBottomCondition = RexUtil.composeConjunction(rexBuilder, newBottomList, false);
-        final Join newBottomJoin = bottomJoin.copy(bottomJoin.getTraitSet(), newBottomCondition, relA, relC, bottomJoin.getJoinType(), bottomJoin.isSemiJoinDone());
-
-        // target: | A       | C      | B |
-        // source: | A       | B | C      |
-        final Mappings.TargetMapping topMapping = Mappings.createShiftMapping(aCount + bCount + cCount, 0, 0, aCount, aCount + cCount, aCount, bCount, aCount, aCount + bCount, cCount);
-        final List<RexNode> newTopList = new ArrayList<>();
-        new RexPermuteInputsShuttle(topMapping, newBottomJoin, relB).visitList(intersecting, newTopList);
-        new RexPermuteInputsShuttle(topMapping, newBottomJoin, relB).visitList(bottomIntersecting, newTopList);
-        RexNode newTopCondition = RexUtil.composeConjunction(rexBuilder, newTopList, false);
-        @SuppressWarnings("SuspiciousNameCombination")
-        final Join newTopJoin = topJoin.copy(topJoin.getTraitSet(), newTopCondition, newBottomJoin, relB, topJoin.getJoinType(), topJoin.isSemiJoinDone());
-
-        assert !Mappings.isIdentity(topMapping);
-        final RelBuilder relBuilder = call.builder();
-        relBuilder.push(newTopJoin);
-        relBuilder.project(relBuilder.fields(topMapping));
-        call.transformTo(relBuilder.build());
-    }
-
-    /**
-     * Splits a condition into conjunctions that do or do not intersect with
-     * a given bit set.
-     */
-    static void split(RexNode condition, ImmutableBitSet bitSet, List<RexNode> intersecting, List<RexNode> nonIntersecting) {
-        for (RexNode node : RelOptUtil.conjunctions(condition)) {
-            ImmutableBitSet inputBitSet = RelOptUtil.InputFinder.bits(node);
-            if (bitSet.intersects(inputBitSet)) {
-                intersecting.add(node);
-            } else {
-                nonIntersecting.add(node);
-            }
-        }
-    }
-}
diff --git a/atopcalcite/src/main/java/org/apache/calcite/rel/rules/OLAPJoinPushThroughJoinRule2.java b/atopcalcite/src/main/java/org/apache/calcite/rel/rules/OLAPJoinPushThroughJoinRule2.java
deleted file mode 100644
index a769cbd..0000000
--- a/atopcalcite/src/main/java/org/apache/calcite/rel/rules/OLAPJoinPushThroughJoinRule2.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
-*/
-package org.apache.calcite.rel.rules;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.annotation.Nullable;
-
-import org.apache.calcite.plan.RelOptCluster;
-import org.apache.calcite.plan.RelOptRule;
-import org.apache.calcite.plan.RelOptRuleCall;
-import org.apache.calcite.plan.RelOptUtil;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.core.Join;
-import org.apache.calcite.rel.core.Project;
-import org.apache.calcite.rel.core.RelFactories;
-import org.apache.calcite.rel.core.TableScan;
-import org.apache.calcite.rel.logical.LogicalJoin;
-import org.apache.calcite.rex.RexBuilder;
-import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.rex.RexPermuteInputsShuttle;
-import org.apache.calcite.rex.RexUtil;
-import org.apache.calcite.tools.RelBuilder;
-import org.apache.calcite.tools.RelBuilderFactory;
-import org.apache.calcite.util.ImmutableBitSet;
-import org.apache.calcite.util.Permutation;
-import org.apache.calcite.util.mapping.AbstractTargetMapping;
-import org.apache.calcite.util.mapping.Mapping;
-import org.apache.calcite.util.mapping.Mappings;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-
-/**
- * modified form org.apache.calcite.rel.rules.JoinPushThroughJoinRule.
- * The goal is to move joins with sub-queries after joins with tables,
- * so that pre-defined join with tables can be matched
- * 
- * differ from OLAPJoinPushThroughJoinRule in the pattern to match. OLAPJoinPushThroughJoinRule
- * will generate a result pattern which cannot recursively match OLAPJoinPushThroughJoinRule's pattern.
- * So OLAPJoinPushThroughJoinRule2 is introduced to allow recursive matching
- */
-public class OLAPJoinPushThroughJoinRule2 extends RelOptRule {
-    /**
-     * Instance of the rule that works on logical joins only, and pushes to the
-     * right.
-     */
-    public static final RelOptRule INSTANCE = new OLAPJoinPushThroughJoinRule2("OLAPJoinPushThroughJoinRule2", LogicalJoin.class, RelFactories.LOGICAL_BUILDER);
-
-    public OLAPJoinPushThroughJoinRule2(String description, Class<? extends Join> clazz, RelBuilderFactory relBuilderFactory) {
-        super(operand(clazz,
-
-                operand(Project.class, //project is added on top by OLAPJoinPushThroughJoinRule
-                        null, new Predicate<Project>() {
-                            @Override
-                            public boolean apply(@Nullable Project input) {
-                                return input.getPermutation() != null;
-                            }
-                        }, operand(clazz, //
-                                operand(RelNode.class, any()), operand(RelNode.class, null, new Predicate<RelNode>() {
-                                    @Override
-                                    public boolean apply(@Nullable RelNode input) {
-                                        return !(input instanceof TableScan);
-                                    }
-                                }, any()))),
-
-                operand(TableScan.class, any())), relBuilderFactory, description);
-    }
-
-    @Override
-    public void onMatch(RelOptRuleCall call) {
-        onMatchRight(call);
-    }
-
-    private void onMatchRight(RelOptRuleCall call) {
-        final Join topJoin = call.rel(0);
-        final Project projectOnBottomJoin = call.rel(1);
-        final Join bottomJoin = call.rel(2);
-        final RelNode relC = call.rel(5);
-        final RelNode relA = bottomJoin.getLeft();
-        final RelNode relB = bottomJoin.getRight();
-        final RelOptCluster cluster = topJoin.getCluster();
-        final Permutation projectPermu = projectOnBottomJoin.getPermutation();
-        final Permutation inverseProjectPermu = projectPermu.inverse();
-        //        Preconditions.checkState(relA == call.rel(3));
-        //        Preconditions.checkState(relB == call.rel(4));
-        Preconditions.checkNotNull(projectPermu);
-
-        //            topJoin
-        //           /        \
-        //        project      C
-        //        /     
-        //   bottomJoin  
-        //    /    \
-        //   A      B
-
-        final int aCount = relA.getRowType().getFieldCount();
-        final int bCount = relB.getRowType().getFieldCount();
-        final int cCount = relC.getRowType().getFieldCount();
-        final ImmutableBitSet bBitSetBelowProject = ImmutableBitSet.range(aCount, aCount + bCount);
-        final ImmutableBitSet bBitSetAboveProject = Mappings.apply(inverseProjectPermu, bBitSetBelowProject);
-
-        final Mapping extendedProjectPerm = createAbstractTargetMapping(Mappings.append(projectPermu, Mappings.createIdentity(cCount)));
-
-        // becomes
-        //
-        //            project
-        //             /
-        //        newTopJoin
-        //        /        \
-        //   newBottomJoin  B
-        //    /    \
-        //   A      C
-
-        // If either join is not inner, we cannot proceed.
-        // (Is this too strict?)
-        //        if (topJoin.getJoinType() != JoinRelType.INNER || bottomJoin.getJoinType() != JoinRelType.INNER) {
-        //            return;
-        //        }
-
-        // Split the condition of topJoin into a conjunction. Each of the
-        // parts that does not use columns from B can be pushed down.
-        final List<RexNode> intersecting = new ArrayList<>();
-        final List<RexNode> nonIntersecting = new ArrayList<>();
-        split(topJoin.getCondition(), bBitSetAboveProject, intersecting, nonIntersecting);
-
-        // If there's nothing to push down, it's not worth proceeding.
-        if (nonIntersecting.isEmpty()) {
-            return;
-        }
-
-        // Split the condition of bottomJoin into a conjunction. Each of the
-        // parts that use columns from B will need to be pulled up.
-        final List<RexNode> bottomIntersecting = new ArrayList<>();
-        final List<RexNode> bottomNonIntersecting = new ArrayList<>();
-        split(bottomJoin.getCondition(), bBitSetBelowProject, bottomIntersecting, bottomNonIntersecting);
-        Preconditions.checkState(bottomNonIntersecting.isEmpty());
-
-        // target: | A       | C      |
-        // source: | A       | B | C      |
-        final Mappings.TargetMapping tempMapping = Mappings.createShiftMapping(aCount + bCount + cCount, 0, 0, aCount, aCount + cCount, aCount, bCount, aCount, aCount + bCount, cCount);
-        final Mappings.TargetMapping thruProjectMapping = Mappings.multiply(extendedProjectPerm, createAbstractTargetMapping(tempMapping));
-        final List<RexNode> newBottomList = new ArrayList<>();
-        new RexPermuteInputsShuttle(thruProjectMapping, relA, relC).visitList(nonIntersecting, newBottomList);
-        final RexBuilder rexBuilder = cluster.getRexBuilder();
-        RexNode newBottomCondition = RexUtil.composeConjunction(rexBuilder, newBottomList, false);
-        final Join newBottomJoin = bottomJoin.copy(bottomJoin.getTraitSet(), newBottomCondition, relA, relC, bottomJoin.getJoinType(), bottomJoin.isSemiJoinDone());
-
-        // target: | A       | C      | B |
-        // source: | A       | B | C      |
-        final Mappings.TargetMapping nonThruProjectMapping = Mappings.createShiftMapping(aCount + bCount + cCount, 0, 0, aCount, aCount + cCount, aCount, bCount, aCount, aCount + bCount, cCount);
-        final List<RexNode> newTopList = new ArrayList<>();
-        new RexPermuteInputsShuttle(thruProjectMapping, newBottomJoin, relB).visitList(intersecting, newTopList);
-        new RexPermuteInputsShuttle(nonThruProjectMapping, newBottomJoin, relB).visitList(bottomIntersecting, newTopList);
-        RexNode newTopCondition = RexUtil.composeConjunction(rexBuilder, newTopList, false);
-        @SuppressWarnings("SuspiciousNameCombination")
-        final Join newTopJoin = topJoin.copy(topJoin.getTraitSet(), newTopCondition, newBottomJoin, relB, topJoin.getJoinType(), topJoin.isSemiJoinDone());
-
-        assert !Mappings.isIdentity(thruProjectMapping);
-        final RelBuilder relBuilder = call.builder();
-        relBuilder.push(newTopJoin);
-        relBuilder.project(relBuilder.fields(thruProjectMapping));
-        call.transformTo(relBuilder.build());
-    }
-
-    private AbstractTargetMapping createAbstractTargetMapping(final Mappings.TargetMapping targetMapping) {
-        return new AbstractTargetMapping(targetMapping.getSourceCount(), targetMapping.getTargetCount()) {
-            @Override
-            public int getTargetOpt(int source) {
-                return targetMapping.getTargetOpt(source);
-            }
-        };
-    }
-
-    /**
-     * Splits a condition into conjunctions that do or do not intersect with
-     * a given bit set.
-     */
-    static void split(RexNode condition, ImmutableBitSet bitSet, List<RexNode> intersecting, List<RexNode> nonIntersecting) {
-        for (RexNode node : RelOptUtil.conjunctions(condition)) {
-            ImmutableBitSet inputBitSet = RelOptUtil.InputFinder.bits(node);
-            if (bitSet.intersects(inputBitSet)) {
-                intersecting.add(node);
-            } else {
-                nonIntersecting.add(node);
-            }
-        }
-    }
-}
diff --git a/atopcalcite/src/main/java/org/apache/calcite/runtime/SqlFunctions.java b/atopcalcite/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
deleted file mode 100644
index 38bd223..0000000
--- a/atopcalcite/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
+++ /dev/null
@@ -1,2238 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.calcite.runtime;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.math.MathContext;
-import java.math.RoundingMode;
-import java.sql.SQLException;
-import java.sql.Timestamp;
-import java.text.DecimalFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.TimeZone;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.regex.Pattern;
-
-import org.apache.calcite.DataContext;
-import org.apache.calcite.avatica.util.ByteString;
-import org.apache.calcite.avatica.util.DateTimeUtils;
-import org.apache.calcite.avatica.util.Spaces;
-import org.apache.calcite.avatica.util.TimeUnitRange;
-import org.apache.calcite.linq4j.AbstractEnumerable;
-import org.apache.calcite.linq4j.CartesianProductEnumerator;
-import org.apache.calcite.linq4j.Enumerable;
-import org.apache.calcite.linq4j.Enumerator;
-import org.apache.calcite.linq4j.Linq4j;
-import org.apache.calcite.linq4j.function.Deterministic;
-import org.apache.calcite.linq4j.function.Function1;
-import org.apache.calcite.linq4j.function.NonDeterministic;
-import org.apache.calcite.linq4j.tree.Primitive;
-import org.apache.calcite.runtime.FlatLists.ComparableList;
-import org.apache.calcite.util.Bug;
-import org.apache.calcite.util.NumberUtil;
-
-/*
- * OVERRIDE POINT:
- * - more power() overloads
- * - refined org.apache.calcite.runtime.SqlFunctions#addMonths(int, int)
- * - corner case subString()
- * - corner case trim_()
- * - upper()
- * - lower()
- * - charLength()
- * - addMonths()
- */
-
-/**
- * Helper methods to implement SQL functions in generated code.
- *
- * <p>Not present: and, or, not (builtin operators are better, because they
- * use lazy evaluation. Implementations do not check for null values; the
- * calling code must do that.</p>
- *
- * <p>Many of the functions do not check for null values. This is intentional.
- * If null arguments are possible, the code-generation framework checks for
- * nulls before calling the functions.</p>
- */
-
-@SuppressWarnings("UnnecessaryUnboxing")
-@Deterministic
-public class SqlFunctions {
-    private static final DecimalFormat DOUBLE_FORMAT = NumberUtil.decimalFormat("0.0E0");
-
-    private static final TimeZone LOCAL_TZ = TimeZone.getDefault();
-
-    private static final Function1<List<Object>, Enumerable<Object>> LIST_AS_ENUMERABLE = new Function1<List<Object>, Enumerable<Object>>() {
-        public Enumerable<Object> apply(List<Object> list) {
-            return Linq4j.asEnumerable(list);
-        }
-    };
-
-    private static final Function1<Object[], Enumerable<Object[]>> ARRAY_CARTESIAN_PRODUCT = new Function1<Object[], Enumerable<Object[]>>() {
-        public Enumerable<Object[]> apply(Object[] lists) {
-            final List<Enumerator<Object>> enumerators = new ArrayList<>();
-            for (Object list : lists) {
-                enumerators.add(Linq4j.enumerator((List) list));
-            }
-            final Enumerator<List<Object>> product = Linq4j.product(enumerators);
-            return new AbstractEnumerable<Object[]>() {
-                public Enumerator<Object[]> enumerator() {
-                    return Linq4j.transform(product, new Function1<List<Object>, Object[]>() {
-                        public Object[] apply(List<Object> list) {
-                            return list.toArray();
-                        }
-                    });
-                }
-            };
-        }
-    };
-
-    /** Holds, for each thread, a map from sequence name to sequence current
-     * value.
-     *
-     * <p>This is a straw man of an implementation whose main goal is to prove
-     * that sequences can be parsed, validated and planned. A real application
-     * will want persistent values for sequences, shared among threads. */
-    private static final ThreadLocal<Map<String, AtomicLong>> THREAD_SEQUENCES = new ThreadLocal<Map<String, AtomicLong>>() {
-        @Override
-        protected Map<String, AtomicLong> initialValue() {
-            return new HashMap<String, AtomicLong>();
-        }
-    };
-
-    private SqlFunctions() {
-    }
-
-    /** SQL SUBSTRING(string FROM ... FOR ...) function. */
-    // override
-    public static String substring(String s, int from, int for_) {
-        if (s == null) {
-            return null;
-        }
-        return s.substring(from - 1, Math.min(from - 1 + for_, s.length()));
-    }
-
-    public static String substring(String s, long from, long for_) {
-        if (from < Integer.MIN_VALUE || from > Integer.MAX_VALUE || for_ < Integer.MIN_VALUE
-                || for_ > Integer.MAX_VALUE) {
-            throw new IllegalArgumentException("Cannot be cast to int due to risk of overflow.");
-        }
-        return substring(s, (int) from, (int) for_);
-    }
-
-    /** SQL SUBSTRING(string FROM ...) function. */
-    public static String substring(String s, int from) {
-        return s.substring(from - 1);
-    }
-
-    public static String substring(String s, long from) {
-        if (from < Integer.MIN_VALUE || from > Integer.MAX_VALUE) {
-            throw new IllegalArgumentException("Cannot be cast to int due to risk of overflow.");
-        }
-        return substring(s, (int) from);
-    }
-
-    /** SQL SUBSTRING(binary FROM ... FOR ...) function. */
-    public static ByteString substring(ByteString b, int from, int for_) {
-        return b.substring(from - 1, Math.min(from - 1 + for_, b.length()));
-    }
-
-    public static ByteString substring(ByteString b, long from, long for_) {
-        if (from < Integer.MIN_VALUE || from > Integer.MAX_VALUE || for_ < Integer.MIN_VALUE
-                || for_ > Integer.MAX_VALUE) {
-            throw new IllegalArgumentException("Cannot be cast to int due to risk of overflow.");
-        }
-        return substring(b, (int) from, (int) for_);
-    }
-
-    /** SQL SUBSTRING(binary FROM ...) function. */
-    public static ByteString substring(ByteString b, int from) {
-        return b.substring(from - 1);
-    }
-
-    public static ByteString substring(ByteString b, long from) {
-        if (from < Integer.MIN_VALUE || from > Integer.MAX_VALUE) {
-            throw new IllegalArgumentException("Cannot be cast to int due to risk of overflow.");
-        }
-        return substring(b, (int) from);
-    }
-
-    /** SQL UPPER(string) function. */
-    //overrivde
-    public static String upper(String s) {
-        if (s == null) {
-            return "";
-        }
-        return s.toUpperCase(Locale.ROOT);
-    }
-
-    /** SQL LOWER(string) function. */
-    //override
-    public static String lower(String s) {
-        if (s == null) {
-            return "";
-        }
-        return s.toLowerCase(Locale.ROOT);
-    }
-
-    /** SQL INITCAP(string) function. */
-    public static String initcap(String s) {
-        // Assumes Alpha as [A-Za-z0-9]
-        // white space is treated as everything else.
-        final int len = s.length();
-        boolean start = true;
-        final StringBuilder newS = new StringBuilder();
-
-        for (int i = 0; i < len; i++) {
-            char curCh = s.charAt(i);
-            final int c = (int) curCh;
-            if (start) { // curCh is whitespace or first character of word.
-                if (c > 47 && c < 58) { // 0-9
-                    start = false;
-                } else if (c > 64 && c < 91) { // A-Z
-                    start = false;
-                } else if (c > 96 && c < 123) { // a-z
-                    start = false;
-                    curCh = (char) (c - 32); // Uppercase this character
-                }
-                // else {} whitespace
-            } else { // Inside of a word or white space after end of word.
-                if (c > 47 && c < 58) { // 0-9
-                    // noop
-                } else if (c > 64 && c < 91) { // A-Z
-                    curCh = (char) (c + 32); // Lowercase this character
-                } else if (c > 96 && c < 123) { // a-z
-                    // noop
-                } else { // whitespace
-                    start = true;
-                }
-            }
-            newS.append(curCh);
-        } // for each character in s
-        return newS.toString();
-    }
-
-    /** SQL CHARACTER_LENGTH(string) function. */
-    public static int charLength(String s) {
-        if (s == null) {
-            return 0;
-        }
-        return s.length();
-    }
-
-    /** SQL {@code string || string} operator. */
-    public static String concat(String s0, String s1) {
-        return s0 + s1;
-    }
-
-    /** SQL {@code binary || binary} operator. */
-    public static ByteString concat(ByteString s0, ByteString s1) {
-        return s0.concat(s1);
-    }
-
-    /** SQL {@code RTRIM} function applied to string. */
-    public static String rtrim(String s) {
-        return trim_(s, false, true, ' ');
-    }
-
-    /** SQL {@code LTRIM} function. */
-    public static String ltrim(String s) {
-        return trim_(s, true, false, ' ');
-    }
-
-    /** SQL {@code TRIM(... seek FROM s)} function. */
-    public static String trim(boolean leading, boolean trailing, String seek, String s) {
-        return trim_(s, leading, trailing, seek.charAt(0));
-    }
-
-    /** SQL {@code TRIM} function. */
-    private static String trim_(String s, boolean left, boolean right, char c) {
-        if (s == null) {
-            return null;
-        }
-        int j = s.length();
-        if (right) {
-            for (;;) {
-                if (j == 0) {
-                    return "";
-                }
-                if (s.charAt(j - 1) != c) {
-                    break;
-                }
-                --j;
-            }
-        }
-        int i = 0;
-        if (left) {
-            for (;;) {
-                if (i == j) {
-                    return "";
-                }
-                if (s.charAt(i) != c) {
-                    break;
-                }
-                ++i;
-            }
-        }
-        return s.substring(i, j);
-    }
-
-    /** SQL {@code TRIM} function applied to binary string. */
-    public static ByteString trim(ByteString s) {
-        return trim_(s, true, true);
-    }
-
-    /** Helper for CAST. */
-    public static ByteString rtrim(ByteString s) {
-        return trim_(s, false, true);
-    }
-
-    /** SQL {@code TRIM} function applied to binary string. */
-    private static ByteString trim_(ByteString s, boolean left, boolean right) {
-        int j = s.length();
-        if (right) {
-            for (;;) {
-                if (j == 0) {
-                    return ByteString.EMPTY;
-                }
-                if (s.byteAt(j - 1) != 0) {
-                    break;
-                }
-                --j;
-            }
-        }
-        int i = 0;
-        if (left) {
-            for (;;) {
-                if (i == j) {
-                    return ByteString.EMPTY;
-                }
-                if (s.byteAt(i) != 0) {
-                    break;
-                }
-                ++i;
-            }
-        }
-        return s.substring(i, j);
-    }
-
-    /** SQL {@code OVERLAY} function. */
-    public static String overlay(String s, String r, int start) {
-        if (s == null || r == null) {
-            return null;
-        }
-        return s.substring(0, start - 1) + r + s.substring(start - 1 + r.length());
-    }
-
-    /** SQL {@code OVERLAY} function. */
-    public static String overlay(String s, String r, int start, int length) {
-        if (s == null || r == null) {
-            return null;
-        }
-        return s.substring(0, start - 1) + r + s.substring(start - 1 + length);
-    }
-
-    /** SQL {@code OVERLAY} function applied to binary strings. */
-    public static ByteString overlay(ByteString s, ByteString r, int start) {
-        if (s == null || r == null) {
-            return null;
-        }
-        return s.substring(0, start - 1).concat(r).concat(s.substring(start - 1 + r.length()));
-    }
-
-    /** SQL {@code OVERLAY} function applied to binary strings. */
-    public static ByteString overlay(ByteString s, ByteString r, int start, int length) {
-        if (s == null || r == null) {
-            return null;
-        }
-        return s.substring(0, start - 1).concat(r).concat(s.substring(start - 1 + length));
-    }
-
-    /** SQL {@code LIKE} function. */
-    public static boolean like(String s, String pattern) {
-        final String regex = Like.sqlToRegexLike(pattern, null);
-        return Pattern.matches(regex, s);
-    }
-
-    /** SQL {@code LIKE} function with escape. */
-    public static boolean like(String s, String pattern, String escape) {
-        final String regex = Like.sqlToRegexLike(pattern, escape);
-        return Pattern.matches(regex, s);
-    }
-
-    /** SQL {@code SIMILAR} function. */
-    public static boolean similar(String s, String pattern) {
-        final String regex = Like.sqlToRegexSimilar(pattern, null);
-        return Pattern.matches(regex, s);
-    }
-
-    /** SQL {@code SIMILAR} function with escape. */
-    public static boolean similar(String s, String pattern, String escape) {
-        final String regex = Like.sqlToRegexSimilar(pattern, escape);
-        return Pattern.matches(regex, s);
-    }
-
-    // =
-
-    /** SQL <code>=</code> operator applied to BigDecimal values (neither may be
-     * null). */
-    public static boolean eq(BigDecimal b0, BigDecimal b1) {
-        return b0.stripTrailingZeros().equals(b1.stripTrailingZeros());
-    }
-
-    /** SQL <code>=</code> operator applied to Object values (including String;
-     * neither side may be null). */
-    public static boolean eq(Object b0, Object b1) {
-        return b0.equals(b1);
-    }
-
-    /** SQL <code>=</code> operator applied to Object values (at least one operand
-     * has ANY type; neither may be null). */
-    public static boolean eqAny(Object b0, Object b1) {
-        if (b0.getClass().equals(b1.getClass())) {
-            // The result of SqlFunctions.eq(BigDecimal, BigDecimal) makes more sense
-            // than BigDecimal.equals(BigDecimal). So if both of types are BigDecimal,
-            // we just use SqlFunctions.eq(BigDecimal, BigDecimal).
-            if (BigDecimal.class.isInstance(b0)) {
-                return eq((BigDecimal) b0, (BigDecimal) b1);
-            } else {
-                return b0.equals(b1);
-            }
-        } else if (allAssignable(Number.class, b0, b1)) {
-            return eq(toBigDecimal((Number) b0), toBigDecimal((Number) b1));
-        }
-        // We shouldn't rely on implementation even though overridden equals can
-        // handle other types which may create worse result: for example,
-        // a.equals(b) != b.equals(a)
-        return false;
-    }
-
-    /** Returns whether two objects can both be assigned to a given class. */
-    private static boolean allAssignable(Class clazz, Object o0, Object o1) {
-        return clazz.isInstance(o0) && clazz.isInstance(o1);
-    }
-
-    // <>
-
-    /** SQL <code>&lt;gt;</code> operator applied to BigDecimal values. */
-    public static boolean ne(BigDecimal b0, BigDecimal b1) {
-        return b0.compareTo(b1) != 0;
-    }
-
-    /** SQL <code>&lt;gt;</code> operator applied to Object values (including
-     * String; neither side may be null). */
-    public static boolean ne(Object b0, Object b1) {
-        return !eq(b0, b1);
-    }
-
-    /** SQL <code>&lt;gt;</code> operator applied to Object values (at least one
-     *  operand has ANY type, including String; neither may be null). */
-    public static boolean neAny(Object b0, Object b1) {
-        return !eqAny(b0, b1);
-    }
-
-    // <
-
-    /** SQL <code>&lt;</code> operator applied to boolean values. */
-    public static boolean lt(boolean b0, boolean b1) {
-        return compare(b0, b1) < 0;
-    }
-
-    /** SQL <code>&lt;</code> operator applied to String values. */
-    public static boolean lt(String b0, String b1) {
-        return b0.compareTo(b1) < 0;
-    }
-
-    /** SQL <code>&lt;</code> operator applied to ByteString values. */
-    public static boolean lt(ByteString b0, ByteString b1) {
-        return b0.compareTo(b1) < 0;
-    }
-
-    /** SQL <code>&lt;</code> operator applied to BigDecimal values. */
-    public static boolean lt(BigDecimal b0, BigDecimal b1) {
-        return b0.compareTo(b1) < 0;
-    }
-
-    /** SQL <code>&lt;</code> operator applied to Object values. */
-    public static boolean ltAny(Object b0, Object b1) {
-        if (b0.getClass().equals(b1.getClass()) && b0 instanceof Comparable) {
-            //noinspection unchecked
-            return ((Comparable) b0).compareTo(b1) < 0;
-        } else if (allAssignable(Number.class, b0, b1)) {
-            return lt(toBigDecimal((Number) b0), toBigDecimal((Number) b1));
-        }
-
-        throw notComparable("<", b0, b1);
-    }
-
-    // <=
-
-    /** SQL <code>&le;</code> operator applied to boolean values. */
-    public static boolean le(boolean b0, boolean b1) {
-        return compare(b0, b1) <= 0;
-    }
-
-    /** SQL <code>&le;</code> operator applied to String values. */
-    public static boolean le(String b0, String b1) {
-        return b0.compareTo(b1) <= 0;
-    }
-
-    /** SQL <code>&le;</code> operator applied to ByteString values. */
-    public static boolean le(ByteString b0, ByteString b1) {
-        return b0.compareTo(b1) <= 0;
-    }
-
-    /** SQL <code>&le;</code> operator applied to BigDecimal values. */
-    public static boolean le(BigDecimal b0, BigDecimal b1) {
-        return b0.compareTo(b1) <= 0;
-    }
-
-    /** SQL <code>&le;</code> operator applied to Object values (at least one
-     * operand has ANY type; neither may be null). */
-    public static boolean leAny(Object b0, Object b1) {
-        if (b0.getClass().equals(b1.getClass()) && b0 instanceof Comparable) {
-            //noinspection unchecked
-            return ((Comparable) b0).compareTo(b1) <= 0;
-        } else if (allAssignable(Number.class, b0, b1)) {
-            return le(toBigDecimal((Number) b0), toBigDecimal((Number) b1));
-        }
-
-        throw notComparable("<=", b0, b1);
-    }
-
-    // >
-
-    /** SQL <code>&gt;</code> operator applied to boolean values. */
-    public static boolean gt(boolean b0, boolean b1) {
-        return compare(b0, b1) > 0;
-    }
-
-    /** SQL <code>&gt;</code> operator applied to String values. */
-    public static boolean gt(String b0, String b1) {
-        return b0.compareTo(b1) > 0;
-    }
-
-    /** SQL <code>&gt;</code> operator applied to ByteString values. */
-    public static boolean gt(ByteString b0, ByteString b1) {
-        return b0.compareTo(b1) > 0;
-    }
-
-    /** SQL <code>&gt;</code> operator applied to BigDecimal values. */
-    public static boolean gt(BigDecimal b0, BigDecimal b1) {
-        return b0.compareTo(b1) > 0;
-    }
-
-    /** SQL <code>&gt;</code> operator applied to Object values (at least one
-     * operand has ANY type; neither may be null). */
-    public static boolean gtAny(Object b0, Object b1) {
-        if (b0.getClass().equals(b1.getClass()) && b0 instanceof Comparable) {
-            //noinspection unchecked
-            return ((Comparable) b0).compareTo(b1) > 0;
-        } else if (allAssignable(Number.class, b0, b1)) {
-            return gt(toBigDecimal((Number) b0), toBigDecimal((Number) b1));
-        }
-
-        throw notComparable(">", b0, b1);
-    }
-
-    // >=
-
-    /** SQL <code>&ge;</code> operator applied to boolean values. */
-    public static boolean ge(boolean b0, boolean b1) {
-        return compare(b0, b1) >= 0;
-    }
-
-    /** SQL <code>&ge;</code> operator applied to String values. */
-    public static boolean ge(String b0, String b1) {
-        return b0.compareTo(b1) >= 0;
-    }
-
-    /** SQL <code>&ge;</code> operator applied to ByteString values. */
-    public static boolean ge(ByteString b0, ByteString b1) {
-        return b0.compareTo(b1) >= 0;
-    }
-
-    /** SQL <code>&ge;</code> operator applied to BigDecimal values. */
-    public static boolean ge(BigDecimal b0, BigDecimal b1) {
-        return b0.compareTo(b1) >= 0;
-    }
-
-    /** SQL <code>&ge;</code> operator applied to Object values (at least one
-     * operand has ANY type; neither may be null). */
-    public static boolean geAny(Object b0, Object b1) {
-        if (b0.getClass().equals(b1.getClass()) && b0 instanceof Comparable) {
-            //noinspection unchecked
-            return ((Comparable) b0).compareTo(b1) >= 0;
-        } else if (allAssignable(Number.class, b0, b1)) {
-            return ge(toBigDecimal((Number) b0), toBigDecimal((Number) b1));
-        }
-
-        throw notComparable(">=", b0, b1);
-    }
-
-    // +
-
-    /** SQL <code>+</code> operator applied to int values. */
-    public static int plus(int b0, int b1) {
-        return b0 + b1;
-    }
-
-    /** SQL <code>+</code> operator applied to int values; left side may be
-     * null. */
-    public static Integer plus(Integer b0, int b1) {
-        return b0 == null ? null : (b0 + b1);
-    }
-
-    /** SQL <code>+</code> operator applied to int values; right side may be
-     * null. */
-    public static Integer plus(int b0, Integer b1) {
-        return b1 == null ? null : (b0 + b1);
-    }
-
-    /** SQL <code>+</code> operator applied to nullable int values. */
-    public static Integer plus(Integer b0, Integer b1) {
-        return (b0 == null || b1 == null) ? null : (b0 + b1);
-    }
-
-    /** SQL <code>+</code> operator applied to nullable long and int values. */
-    public static Long plus(Long b0, Integer b1) {
-        return (b0 == null || b1 == null) ? null : (b0.longValue() + b1.longValue());
-    }
-
-    /** SQL <code>+</code> operator applied to nullable int and long values. */
-    public static Long plus(Integer b0, Long b1) {
-        return (b0 == null || b1 == null) ? null : (b0.longValue() + b1.longValue());
-    }
-
-    /** SQL <code>+</code> operator applied to BigDecimal values. */
-    public static BigDecimal plus(BigDecimal b0, BigDecimal b1) {
-        return (b0 == null || b1 == null) ? null : b0.add(b1);
-    }
-
-    /** SQL <code>+</code> operator applied to String values. Same as string concat operator. */
-    public static String plus(String s0, String s1) {
-        return s0 + s1;
-    }
-
-    /** SQL <code>+</code> operator applied to Object values (at least one operand
-     * has ANY type; either may be null). */
-    public static Object plusAny(Object b0, Object b1) {
-        if (b0 == null || b1 == null) {
-            return null;
-        }
-
-        if (allAssignable(Number.class, b0, b1)) {
-            return plus(toBigDecimal((Number) b0), toBigDecimal((Number) b1));
-        }
-
-        throw notArithmetic("+", b0, b1);
-    }
-
-    // -
-
-    /** SQL <code>-</code> operator applied to int values. */
-    public static int minus(int b0, int b1) {
-        return b0 - b1;
-    }
-
-    /** SQL <code>-</code> operator applied to int values; left side may be
-     * null. */
-    public static Integer minus(Integer b0, int b1) {
-        return b0 == null ? null : (b0 - b1);
-    }
-
-    /** SQL <code>-</code> operator applied to int values; right side may be
-     * null. */
-    public static Integer minus(int b0, Integer b1) {
-        return b1 == null ? null : (b0 - b1);
-    }
-
-    /** SQL <code>-</code> operator applied to nullable int values. */
-    public static Integer minus(Integer b0, Integer b1) {
-        return (b0 == null || b1 == null) ? null : (b0 - b1);
-    }
-
-    /** SQL <code>-</code> operator applied to nullable long and int values. */
-    public static Long minus(Long b0, Integer b1) {
-        return (b0 == null || b1 == null) ? null : (b0.longValue() - b1.longValue());
-    }
-
-    /** SQL <code>-</code> operator applied to nullable int and long values. */
-    public static Long minus(Integer b0, Long b1) {
-        return (b0 == null || b1 == null) ? null : (b0.longValue() - b1.longValue());
-    }
-
-    /** SQL <code>-</code> operator applied to BigDecimal values. */
-    public static BigDecimal minus(BigDecimal b0, BigDecimal b1) {
-        return (b0 == null || b1 == null) ? null : b0.subtract(b1);
-    }
-
-    /** SQL <code>-</code> operator applied to Object values (at least one operand
-     * has ANY type; either may be null). */
-    public static Object minusAny(Object b0, Object b1) {
-        if (b0 == null || b1 == null) {
-            return null;
-        }
-
-        if (allAssignable(Number.class, b0, b1)) {
-            return minus(toBigDecimal((Number) b0), toBigDecimal((Number) b1));
-        }
-
-        throw notArithmetic("-", b0, b1);
-    }
-
-    // /
-
-    /** SQL <code>/</code> operator applied to int values. */
-    public static int divide(int b0, int b1) {
-        return b0 / b1;
-    }
-
-    /** SQL <code>/</code> operator applied to int values; left side may be
-     * null. */
-    public static Integer divide(Integer b0, int b1) {
-        return b0 == null ? null : (b0 / b1);
-    }
-
-    /** SQL <code>/</code> operator applied to int values; right side may be
-     * null. */
-    public static Integer divide(int b0, Integer b1) {
-        return b1 == null ? null : (b0 / b1);
-    }
-
-    /** SQL <code>/</code> operator applied to nullable int values. */
-    public static Integer divide(Integer b0, Integer b1) {
-        return (b0 == null || b1 == null) ? null : (b0 / b1);
-    }
-
-    /** SQL <code>/</code> operator applied to nullable long and int values. */
-    public static Long divide(Long b0, Integer b1) {
-        return (b0 == null || b1 == null) ? null : (b0.longValue() / b1.longValue());
-    }
-
-    /** SQL <code>/</code> operator applied to nullable int and long values. */
-    public static Long divide(Integer b0, Long b1) {
-        return (b0 == null || b1 == null) ? null : (b0.longValue() / b1.longValue());
-    }
-
-    /** SQL <code>/</code> operator applied to BigDecimal values. */
-    public static BigDecimal divide(BigDecimal b0, BigDecimal b1) {
-        return (b0 == null || b1 == null) ? null : b0.divide(b1, MathContext.DECIMAL64);
-    }
-
-    /** SQL <code>/</code> operator applied to Object values (at least one operand
-     * has ANY type; either may be null). */
-    public static Object divideAny(Object b0, Object b1) {
-        if (b0 == null || b1 == null) {
-            return null;
-        }
-
-        if (allAssignable(Number.class, b0, b1)) {
-            return divide(toBigDecimal((Number) b0), toBigDecimal((Number) b1));
-        }
-
-        throw notArithmetic("/", b0, b1);
-    }
-
-    public static int divide(int b0, BigDecimal b1) {
-        return BigDecimal.valueOf(b0).divide(b1, RoundingMode.HALF_DOWN).intValue();
-    }
-
-    public static long divide(long b0, BigDecimal b1) {
-        return BigDecimal.valueOf(b0).divide(b1, RoundingMode.HALF_DOWN).longValue();
-    }
-
-    // *
-
-    /** SQL <code>*</code> operator applied to int values. */
-    public static int multiply(int b0, int b1) {
-        return b0 * b1;
-    }
-
-    /** SQL <code>*</code> operator applied to int values; left side may be
-     * null. */
-    public static Integer multiply(Integer b0, int b1) {
-        return b0 == null ? null : (b0 * b1);
-    }
-
-    /** SQL <code>*</code> operator applied to int values; right side may be
-     * null. */
-    public static Integer multiply(int b0, Integer b1) {
-        return b1 == null ? null : (b0 * b1);
-    }
-
-    /** SQL <code>*</code> operator applied to nullable int values. */
-    public static Integer multiply(Integer b0, Integer b1) {
-        return (b0 == null || b1 == null) ? null : (b0 * b1);
-    }
-
-    /** SQL <code>*</code> operator applied to nullable long and int values. */
-    public static Long multiply(Long b0, Integer b1) {
-        return (b0 == null || b1 == null) ? null : (b0.longValue() * b1.longValue());
-    }
-
-    /** SQL <code>*</code> operator applied to nullable int and long values. */
-    public static Long multiply(Integer b0, Long b1) {
-        return (b0 == null || b1 == null) ? null : (b0.longValue() * b1.longValue());
-    }
-
-    /** SQL <code>*</code> operator applied to BigDecimal values. */
-    public static BigDecimal multiply(BigDecimal b0, BigDecimal b1) {
-        return (b0 == null || b1 == null) ? null : b0.multiply(b1);
-    }
-
-    /** SQL <code>*</code> operator applied to Object values (at least one operand
-     * has ANY type; either may be null). */
-    public static Object multiplyAny(Object b0, Object b1) {
-        if (b0 == null || b1 == null) {
-            return null;
-        }
-
-        if (allAssignable(Number.class, b0, b1)) {
-            return multiply(toBigDecimal((Number) b0), toBigDecimal((Number) b1));
-        }
-
-        throw notArithmetic("*", b0, b1);
-    }
-
-    private static IllegalArgumentException notArithmetic(String op, Object b0, Object b1) {
-        return new IllegalArgumentException(
-                "Invalid types for arithmetic: " + b0.getClass() + " " + op + " " + b1.getClass());
-    }
-
-    private static IllegalArgumentException notComparable(String op, Object b0, Object b1) {
-        return new IllegalArgumentException(
-                "Invalid types for comparison: " + b0.getClass() + " " + op + " " + b1.getClass());
-    }
-
-    // EXP
-
-    /** SQL <code>EXP</code> operator applied to double values. */
-    public static double exp(double b0) {
-        return Math.exp(b0);
-    }
-
-    public static double exp(BigDecimal b0) {
-        return Math.exp(b0.doubleValue());
-    }
-
-    public static double exp(long b0) {
-        return Math.exp(b0);
-    }
-
-    // POWER
-
-    /** SQL <code>POWER</code> operator applied to double values. */
-    public static double power(double b0, double b1) {
-        return Math.pow(b0, b1);
-    }
-
-    public static double power(long b0, long b1) {
-        return Math.pow(b0, b1);
-    }
-
-    public static double power(BigDecimal b0, BigDecimal b1) {
-        return Math.pow(b0.doubleValue(), b1.doubleValue());
-    }
-
-    public static double power(long b0, BigDecimal b1) {
-        return Math.pow(b0, b1.doubleValue());
-    }
-
-    // OVERRIDE POINT starts, more power overloads
-    public static double power(double n1, long n2) {
-        return Math.pow(n1, (double) n2);
-    }
-
-    public static double power(double n1, BigDecimal n2) {
-        return Math.pow(n1, n2.doubleValue());
-    }
-
-    public static double power(long n1, double n2) {
-        return Math.pow((double) n1, n2);
-    }
-
-    public static double power(BigDecimal n1, double n2) {
-        return Math.pow(n1.doubleValue(), n2);
-    }
-
-    public static double power(BigDecimal n1, long n2) {
-        return Math.pow(n1.doubleValue(), (double) n2);
-    }
-
-    public static double power(double n1, int n2) {
-        return Math.pow(n1, (double) n2);
-    }
-
-    public static double power(long n1, int n2) {
-        return Math.pow((double) n1, (double) n2);
-    }
-
-    public static double power(BigDecimal n1, int n2) {
-        return Math.pow(n1.doubleValue(), (double) n2);
-    }
-
-    public static double power(int n1, double n2) {
-        return Math.pow((double) n1, n2);
-    }
-
-    public static double power(int n1, long n2) {
-        return Math.pow((double) n1, (double) n2);
-    }
-
-    public static double power(int n1, BigDecimal n2) {
-        return Math.pow((double) n1, n2.doubleValue());
-    }
-
-    public static double power(int n1, int n2) {
-        return Math.pow(n1, n2);
-    }
-
-    // OVERRIDE POINT ends, more power overloads
-
-    // LN
-
-    /** SQL {@code LN(number)} function applied to double values. */
-    public static double ln(double d) {
-        return Math.log(d);
-    }
-
-    /** SQL {@code LN(number)} function applied to long values. */
-    public static double ln(long b0) {
-        return Math.log(b0);
-    }
-
-    /** SQL {@code LN(number)} function applied to BigDecimal values. */
-    public static double ln(BigDecimal d) {
-        return Math.log(d.doubleValue());
-    }
-
-    // LOG10
-
-    /** SQL <code>LOG10(numeric)</code> operator applied to double values. */
-    public static double log10(double b0) {
-        return Math.log10(b0);
-    }
-
-    /** SQL {@code LOG10(number)} function applied to long values. */
-    public static double log10(long b0) {
-        return Math.log10(b0);
-    }
-
-    /** SQL {@code LOG10(number)} function applied to BigDecimal values. */
-    public static double log10(BigDecimal d) {
-        return Math.log10(d.doubleValue());
-    }
-
-    // MOD
-
-    /** SQL <code>MOD</code> operator applied to byte values. */
-    public static byte mod(byte b0, byte b1) {
-        return (byte) (b0 % b1);
-    }
-
-    /** SQL <code>MOD</code> operator applied to short values. */
-    public static short mod(short b0, short b1) {
-        return (short) (b0 % b1);
-    }
-
-    /** SQL <code>MOD</code> operator applied to int values. */
-    public static int mod(int b0, int b1) {
-        return b0 % b1;
-    }
-
-    /** SQL <code>MOD</code> operator applied to long values. */
-    public static long mod(long b0, long b1) {
-        return b0 % b1;
-    }
-
-    // temporary
-    public static BigDecimal mod(BigDecimal b0, int b1) {
-        return mod(b0, BigDecimal.valueOf(b1));
-    }
-
-    // temporary
-    public static int mod(int b0, BigDecimal b1) {
-        return mod(b0, b1.intValue());
-    }
-
-    public static BigDecimal mod(BigDecimal b0, BigDecimal b1) {
-        final BigDecimal[] bigDecimals = b0.divideAndRemainder(b1);
-        return bigDecimals[1];
-    }
-
-    // FLOOR
-
-    public static double floor(double b0) {
-        return Math.floor(b0);
-    }
-
-    public static float floor(float b0) {
-        return (float) Math.floor(b0);
-    }
-
-    public static BigDecimal floor(BigDecimal b0) {
-        return b0.setScale(0, RoundingMode.FLOOR);
-    }
-
-    /** SQL <code>FLOOR</code> operator applied to byte values. */
-    public static byte floor(byte b0, byte b1) {
-        return (byte) floor((int) b0, (int) b1);
-    }
-
-    /** SQL <code>FLOOR</code> operator applied to short values. */
-    public static short floor(short b0, short b1) {
-        return (short) floor((int) b0, (int) b1);
-    }
-
-    /** SQL <code>FLOOR</code> operator applied to int values. */
-    public static int floor(int b0, int b1) {
-        int r = b0 % b1;
-        if (r < 0) {
-            r += b1;
-        }
-        return b0 - r;
-    }
-
-    /** SQL <code>FLOOR</code> operator applied to long values. */
-    public static long floor(long b0, long b1) {
-        long r = b0 % b1;
-        if (r < 0) {
-            r += b1;
-        }
-        return b0 - r;
-    }
-
-    // temporary
-    public static BigDecimal floor(BigDecimal b0, int b1) {
-        return floor(b0, BigDecimal.valueOf(b1));
-    }
-
-    // temporary
-    public static int floor(int b0, BigDecimal b1) {
-        return floor(b0, b1.intValue());
-    }
-
-    public static BigDecimal floor(BigDecimal b0, BigDecimal b1) {
-        final BigDecimal[] bigDecimals = b0.divideAndRemainder(b1);
-        BigDecimal r = bigDecimals[1];
-        if (r.signum() < 0) {
-            r = r.add(b1);
-        }
-        return b0.subtract(r);
-    }
-
-    // CEIL
-
-    public static double ceil(double b0) {
-        return Math.ceil(b0);
-    }
-
-    public static float ceil(float b0) {
-        return (float) Math.ceil(b0);
-    }
-
-    public static BigDecimal ceil(BigDecimal b0) {
-        return b0.setScale(0, RoundingMode.CEILING);
-    }
-
-    /** SQL <code>CEIL</code> operator applied to byte values. */
-    public static byte ceil(byte b0, byte b1) {
-        return floor((byte) (b0 + b1 - 1), b1);
-    }
-
-    /** SQL <code>CEIL</code> operator applied to short values. */
-    public static short ceil(short b0, short b1) {
-        return floor((short) (b0 + b1 - 1), b1);
-    }
-
-    /** SQL <code>CEIL</code> operator applied to int values. */
-    public static int ceil(int b0, int b1) {
-        int r = b0 % b1;
-        if (r > 0) {
-            r -= b1;
-        }
-        return b0 - r;
-    }
-
-    /** SQL <code>CEIL</code> operator applied to long values. */
-    public static long ceil(long b0, long b1) {
-        return floor(b0 + b1 - 1, b1);
-    }
-
-    // temporary
-    public static BigDecimal ceil(BigDecimal b0, int b1) {
-        return ceil(b0, BigDecimal.valueOf(b1));
-    }
-
-    // temporary
-    public static int ceil(int b0, BigDecimal b1) {
-        return ceil(b0, b1.intValue());
-    }
-
-    public static BigDecimal ceil(BigDecimal b0, BigDecimal b1) {
-        final BigDecimal[] bigDecimals = b0.divideAndRemainder(b1);
-        BigDecimal r = bigDecimals[1];
-        if (r.signum() > 0) {
-            r = r.subtract(b1);
-        }
-        return b0.subtract(r);
-    }
-
-    // ABS
-
-    /** SQL <code>ABS</code> operator applied to byte values. */
-    public static byte abs(byte b0) {
-        return (byte) Math.abs(b0);
-    }
-
-    /** SQL <code>ABS</code> operator applied to short values. */
-    public static short abs(short b0) {
-        return (short) Math.abs(b0);
-    }
-
-    /** SQL <code>ABS</code> operator applied to int values. */
-    public static int abs(int b0) {
-        return Math.abs(b0);
-    }
-
-    /** SQL <code>ABS</code> operator applied to long values. */
-    public static long abs(long b0) {
-        return Math.abs(b0);
-    }
-
-    /** SQL <code>ABS</code> operator applied to float values. */
-    public static float abs(float b0) {
-        return Math.abs(b0);
-    }
-
-    /** SQL <code>ABS</code> operator applied to double values. */
-    public static double abs(double b0) {
-        return Math.abs(b0);
-    }
-
-    /** SQL <code>ABS</code> operator applied to BigDecimal values. */
-    public static BigDecimal abs(BigDecimal b0) {
-        return b0.abs();
-    }
-
-    // ACOS
-    /** SQL <code>ACOS</code> operator applied to long values. */
-    public static double acos(long b0) {
-        return Math.acos(b0);
-    }
-
-    /** SQL <code>ACOS</code> operator applied to BigDecimal values. */
-    public static double acos(BigDecimal b0) {
-        return Math.acos(b0.doubleValue());
-    }
-
-    /** SQL <code>ACOS</code> operator applied to double values. */
-    public static double acos(double b0) {
-        return Math.acos(b0);
-    }
-
-    // ASIN
-    /** SQL <code>ASIN</code> operator applied to long values. */
-    public static double asin(long b0) {
-        return Math.asin(b0);
-    }
-
-    /** SQL <code>ASIN</code> operator applied to BigDecimal values. */
-    public static double asin(BigDecimal b0) {
-        return Math.asin(b0.doubleValue());
-    }
-
-    /** SQL <code>ASIN</code> operator applied to double values. */
-    public static double asin(double b0) {
-        return Math.asin(b0);
-    }
-
-    // ATAN
-    /** SQL <code>ATAN</code> operator applied to long values. */
-    public static double atan(long b0) {
-        return Math.atan(b0);
-    }
-
-    /** SQL <code>ATAN</code> operator applied to BigDecimal values. */
-    public static double atan(BigDecimal b0) {
-        return Math.atan(b0.doubleValue());
-    }
-
-    /** SQL <code>ATAN</code> operator applied to double values. */
-    public static double atan(double b0) {
-        return Math.atan(b0);
-    }
-
-    // ATAN2
-    /** SQL <code>ATAN2</code> operator applied to long values. */
-    public static double atan2(long b0, long b1) {
-        return Math.atan2(b0, b1);
-    }
-
-    /** SQL <code>ATAN2</code> operator applied to long/BigDecimal values. */
-    public static double atan2(long b0, BigDecimal b1) {
-        return Math.atan2(b0, b1.doubleValue());
-    }
-
-    /** SQL <code>ATAN2</code> operator applied to BigDecimal values. */
-    public static double atan2(BigDecimal b0, BigDecimal b1) {
-        return Math.atan2(b0.doubleValue(), b1.doubleValue());
-    }
-
-    /** SQL <code>ATAN2</code> operator applied to double values. */
-    public static double atan2(double b0, double b1) {
-        return Math.atan2(b0, b1);
-    }
-
-    // COS
-    /** SQL <code>COS</code> operator applied to long values. */
-    public static double cos(long b0) {
-        return Math.cos(b0);
-    }
-
-    /** SQL <code>COS</code> operator applied to BigDecimal values. */
-    public static double cos(BigDecimal b0) {
-        return Math.cos(b0.doubleValue());
-    }
-
-    /** SQL <code>COS</code> operator applied to double values. */
-    public static double cos(double b0) {
-        return Math.cos(b0);
-    }
-
-    // COT
-    /** SQL <code>COT</code> operator applied to long values. */
-    public static double cot(long b0) {
-        return 1.0d / Math.tan(b0);
-    }
-
-    /** SQL <code>COT</code> operator applied to BigDecimal values. */
-    public static double cot(BigDecimal b0) {
-        return 1.0d / Math.tan(b0.doubleValue());
-    }
-
-    /** SQL <code>COT</code> operator applied to double values. */
-    public static double cot(double b0) {
-        return 1.0d / Math.tan(b0);
-    }
-
-    // DEGREES
-    /** SQL <code>DEGREES</code> operator applied to long values. */
-    public static double degrees(long b0) {
-        return Math.toDegrees(b0);
-    }
-
-    /** SQL <code>DEGREES</code> operator applied to BigDecimal values. */
-    public static double degrees(BigDecimal b0) {
-        return Math.toDegrees(b0.doubleValue());
-    }
-
-    /** SQL <code>DEGREES</code> operator applied to double values. */
-    public static double degrees(double b0) {
-        return Math.toDegrees(b0);
-    }
-
-    // RADIANS
-    /** SQL <code>RADIANS</code> operator applied to long values. */
-    public static double radians(long b0) {
-        return Math.toRadians(b0);
-    }
-
-    /** SQL <code>RADIANS</code> operator applied to BigDecimal values. */
-    public static double radians(BigDecimal b0) {
-        return Math.toRadians(b0.doubleValue());
-    }
-
-    /** SQL <code>RADIANS</code> operator applied to double values. */
-    public static double radians(double b0) {
-        return Math.toRadians(b0);
-    }
-
-    // SQL ROUND
-    /** SQL <code>ROUND</code> operator applied to long values. */
-    public static int sround(int b0, int b1) {
-        return sround(BigDecimal.valueOf(b0), b1).intValue();
-    }
-
-    /** SQL <code>ROUND</code> operator applied to long values. */
-    public static long sround(long b0, int b1) {
-        return sround(BigDecimal.valueOf(b0), b1).longValue();
-    }
-
-    /** SQL <code>ROUND</code> operator applied to BigDecimal values. */
-    public static BigDecimal sround(BigDecimal b0, int b1) {
-        return b0.movePointRight(b1).setScale(0, RoundingMode.HALF_UP).movePointLeft(b1);
-    }
-
-    /** SQL <code>ROUND</code> operator applied to double values. */
-    public static double sround(double b0, int b1) {
-        return sround(BigDecimal.valueOf(b0), b1).doubleValue();
-    }
-
-    // SQL TRUNCATE
-    /** SQL <code>TRUNCATE</code> operator applied to int values. */
-    public static int struncate(int b0, int b1) {
-        return struncate(BigDecimal.valueOf(b0), b1).intValue();
-    }
-
-    /** SQL <code>TRUNCATE</code> operator applied to long values. */
-    public static long struncate(long b0, int b1) {
-        return struncate(BigDecimal.valueOf(b0), b1).longValue();
-    }
-
-    /** SQL <code>TRUNCATE</code> operator applied to BigDecimal values. */
-    public static BigDecimal struncate(BigDecimal b0, int b1) {
-        return b0.movePointRight(b1).setScale(0, RoundingMode.DOWN).movePointLeft(b1);
-    }
-
-    /** SQL <code>TRUNCATE</code> operator applied to double values. */
-    public static double struncate(double b0, int b1) {
-        return struncate(BigDecimal.valueOf(b0), b1).doubleValue();
-    }
-
-    // SIGN
-    /** SQL <code>SIGN</code> operator applied to int values. */
-    public static int sign(int b0) {
-        return Integer.signum(b0);
-    }
-
-    /** SQL <code>SIGN</code> operator applied to long values. */
-    public static long sign(long b0) {
-        return Long.signum(b0);
-    }
-
-    /** SQL <code>SIGN</code> operator applied to BigDecimal values. */
-    public static BigDecimal sign(BigDecimal b0) {
-        return BigDecimal.valueOf(b0.signum());
-    }
-
-    /** SQL <code>SIGN</code> operator applied to double values. */
-    public static double sign(double b0) {
-        return Math.signum(b0);
-    }
-
-    // SIN
-    /** SQL <code>SIN</code> operator applied to long values. */
-    public static double sin(long b0) {
-        return Math.sin(b0);
-    }
-
-    /** SQL <code>SIN</code> operator applied to BigDecimal values. */
-    public static double sin(BigDecimal b0) {
-        return Math.sin(b0.doubleValue());
-    }
-
-    /** SQL <code>SIN</code> operator applied to double values. */
-    public static double sin(double b0) {
-        return Math.sin(b0);
-    }
-
-    // TAN
-    /** SQL <code>TAN</code> operator applied to long values. */
-    public static double tan(long b0) {
-        return Math.tan(b0);
-    }
-
-    /** SQL <code>TAN</code> operator applied to BigDecimal values. */
-    public static double tan(BigDecimal b0) {
-        return Math.tan(b0.doubleValue());
-    }
-
-    /** SQL <code>TAN</code> operator applied to double values. */
-    public static double tan(double b0) {
-        return Math.tan(b0);
-    }
-
-    // Helpers
-
-    /** Helper for implementing MIN. Somewhat similar to LEAST operator. */
-    public static <T extends Comparable<T>> T lesser(T b0, T b1) {
-        return b0 == null || b0.compareTo(b1) > 0 ? b1 : b0;
-    }
-
-    /** LEAST operator. */
-    public static <T extends Comparable<T>> T least(T b0, T b1) {
-        return b0 == null || b1 != null && b0.compareTo(b1) > 0 ? b1 : b0;
-    }
-
-    public static boolean greater(boolean b0, boolean b1) {
-        return b0 || b1;
-    }
-
-    public static boolean lesser(boolean b0, boolean b1) {
-        return b0 && b1;
-    }
-
-    public static byte greater(byte b0, byte b1) {
-        return b0 > b1 ? b0 : b1;
-    }
-
-    public static byte lesser(byte b0, byte b1) {
-        return b0 > b1 ? b1 : b0;
-    }
-
-    public static char greater(char b0, char b1) {
-        return b0 > b1 ? b0 : b1;
-    }
-
-    public static char lesser(char b0, char b1) {
-        return b0 > b1 ? b1 : b0;
-    }
-
-    public static short greater(short b0, short b1) {
-        return b0 > b1 ? b0 : b1;
-    }
-
-    public static short lesser(short b0, short b1) {
-        return b0 > b1 ? b1 : b0;
-    }
-
-    public static int greater(int b0, int b1) {
-        return b0 > b1 ? b0 : b1;
-    }
-
-    public static int lesser(int b0, int b1) {
-        return b0 > b1 ? b1 : b0;
-    }
-
-    public static long greater(long b0, long b1) {
-        return b0 > b1 ? b0 : b1;
-    }
-
-    public static long lesser(long b0, long b1) {
-        return b0 > b1 ? b1 : b0;
-    }
-
-    public static float greater(float b0, float b1) {
-        return b0 > b1 ? b0 : b1;
-    }
-
-    public static float lesser(float b0, float b1) {
-        return b0 > b1 ? b1 : b0;
-    }
-
-    public static double greater(double b0, double b1) {
-        return b0 > b1 ? b0 : b1;
-    }
-
-    public static double lesser(double b0, double b1) {
-        return b0 > b1 ? b1 : b0;
-    }
-
-    /** Helper for implementing MAX. Somewhat similar to GREATEST operator. */
-    public static <T extends Comparable<T>> T greater(T b0, T b1) {
-        return b0 == null || b0.compareTo(b1) < 0 ? b1 : b0;
-    }
-
-    /** GREATEST operator. */
-    public static <T extends Comparable<T>> T greatest(T b0, T b1) {
-        return b0 == null || b1 != null && b0.compareTo(b1) < 0 ? b1 : b0;
-    }
-
-    /** Boolean comparison. */
-    public static int compare(boolean x, boolean y) {
-        return x == y ? 0 : x ? 1 : -1;
-    }
-
-    /** CAST(FLOAT AS VARCHAR). */
-    public static String toString(float x) {
-        if (x == 0) {
-            return "0E0";
-        }
-        BigDecimal bigDecimal = new BigDecimal(x, MathContext.DECIMAL32).stripTrailingZeros();
-        final String s = bigDecimal.toString();
-        return s.replaceAll("0*E", "E").replace("E+", "E");
-    }
-
-    /** CAST(DOUBLE AS VARCHAR). */
-    public static String toString(double x) {
-        if (x == 0) {
-            return "0E0";
-        }
-        BigDecimal bigDecimal = new BigDecimal(x, MathContext.DECIMAL64).stripTrailingZeros();
-        final String s = bigDecimal.toString();
-        return s.replaceAll("0*E", "E").replace("E+", "E");
-    }
-
-    /** CAST(DECIMAL AS VARCHAR). */
-    public static String toString(BigDecimal x) {
-        final String s = x.toString();
-        if (s.startsWith("0")) {
-            // we want ".1" not "0.1"
-            return s.substring(1);
-        } else if (s.startsWith("-0")) {
-            // we want "-.1" not "-0.1"
-            return "-" + s.substring(2);
-        } else {
-            return s;
-        }
-    }
-
-    /** CAST(BOOLEAN AS VARCHAR). */
-    public static String toString(boolean x) {
-        // Boolean.toString returns lower case -- no good.
-        return x ? "TRUE" : "FALSE";
-    }
-
-    @NonDeterministic
-    private static Object cannotConvert(Object o, Class toType) {
-        throw new RuntimeException("Cannot convert " + o + " to " + toType);
-    }
-
-    /** CAST(VARCHAR AS BOOLEAN). */
-    public static boolean toBoolean(String s) {
-        s = trim_(s, true, true, ' ');
-        if (s.equalsIgnoreCase("TRUE")) {
-            return true;
-        } else if (s.equalsIgnoreCase("FALSE")) {
-            return false;
-        } else {
-            throw new RuntimeException("Invalid character for cast");
-        }
-    }
-
-    public static boolean toBoolean(Number number) {
-        return !number.equals(0);
-    }
-
-    public static boolean toBoolean(Object o) {
-        return o instanceof Boolean ? (Boolean) o
-                : o instanceof Number ? toBoolean((Number) o)
-                        : o instanceof String ? toBoolean((String) o) : (Boolean) cannotConvert(o, boolean.class);
-    }
-
-    // Don't need parseByte etc. - Byte.parseByte is sufficient.
-
-    public static byte toByte(Object o) {
-        return o instanceof Byte ? (Byte) o : o instanceof Number ? toByte((Number) o) : Byte.parseByte(o.toString());
-    }
-
-    public static byte toByte(Number number) {
-        return number.byteValue();
-    }
-
-    public static char toChar(String s) {
-        return s.charAt(0);
-    }
-
-    public static Character toCharBoxed(String s) {
-        return s.charAt(0);
-    }
-
-    public static short toShort(String s) {
-        return Short.parseShort(s.trim());
-    }
-
-    public static short toShort(Number number) {
-        return number.shortValue();
-    }
-
-    public static short toShort(Object o) {
-        return o instanceof Short ? (Short) o
-                : o instanceof Number ? toShort((Number) o)
-                        : o instanceof String ? toShort((String) o) : (Short) cannotConvert(o, short.class);
-    }
-
-    /** Converts the Java type used for UDF parameters of SQL DATE type
-     * ({@link java.sql.Date}) to internal representation (int).
-     *
-     * <p>Converse of {@link #internalToDate(int)}. */
-    public static int toInt(java.util.Date v) {
-        return toInt(v, LOCAL_TZ);
-    }
-
-    public static int toInt(java.util.Date v, TimeZone timeZone) {
-        return (int) (toLong(v, timeZone) / DateTimeUtils.MILLIS_PER_DAY);
-    }
-
-    public static Integer toIntOptional(java.util.Date v) {
-        return v == null ? null : toInt(v);
-    }
-
-    public static Integer toIntOptional(java.util.Date v, TimeZone timeZone) {
-        return v == null ? null : toInt(v, timeZone);
-    }
-
-    public static long toLong(Date v) {
-        return toLong(v, LOCAL_TZ);
-    }
-
-    /** Converts the Java type used for UDF parameters of SQL TIME type
-     * ({@link java.sql.Time}) to internal representation (int).
-     *
-     * <p>Converse of {@link #internalToTime(int)}. */
-    public static int toInt(java.sql.Time v) {
-        return (int) (toLong(v) % DateTimeUtils.MILLIS_PER_DAY);
-    }
-
-    public static Integer toIntOptional(java.sql.Time v) {
-        return v == null ? null : toInt(v);
-    }
-
-    public static int toInt(String s) {
-        return Integer.parseInt(s.trim());
-    }
-
-    public static int toInt(Number number) {
-        return number.intValue();
-    }
-
-    public static int toInt(Object o) {
-        return o instanceof Integer ? (Integer) o
-                : o instanceof Number ? toInt((Number) o)
-                        : o instanceof String ? toInt((String) o)
-                                : o instanceof java.util.Date ? toInt((java.util.Date) o)
-                                        : (Integer) cannotConvert(o, int.class);
-    }
-
-    /** Converts the Java type used for UDF parameters of SQL TIMESTAMP type
-     * ({@link java.sql.Timestamp}) to internal representation (long).
-     *
-     * <p>Converse of {@link #internalToTimestamp(long)}. */
-    public static long toLong(Timestamp v) {
-        return toLong(v, LOCAL_TZ);
-    }
-
-    // mainly intended for java.sql.Timestamp but works for other dates also
-    public static long toLong(java.util.Date v, TimeZone timeZone) {
-        final long time = v.getTime();
-        return time + timeZone.getOffset(time);
-    }
-
-    // mainly intended for java.sql.Timestamp but works for other dates also
-    public static Long toLongOptional(java.util.Date v) {
-        return v == null ? null : toLong(v, LOCAL_TZ);
-    }
-
-    public static Long toLongOptional(Timestamp v, TimeZone timeZone) {
-        if (v == null) {
-            return null;
-        }
-        return toLong(v, LOCAL_TZ);
-    }
-
-    public static long toLong(String s) {
-        if (s.startsWith("199") && s.contains(":")) {
-            return Timestamp.valueOf(s).getTime();
-        }
-        return Long.parseLong(s.trim());
-    }
-
-    public static long toLong(Number number) {
-        return number.longValue();
-    }
-
-    public static long toLong(Object o) {
-        return o instanceof Long ? (Long) o
-                : o instanceof Number ? toLong((Number) o)
-                        : o instanceof String ? toLong((String) o) : (Long) cannotConvert(o, long.class);
-    }
-
-    public static float toFloat(String s) {
-        return Float.parseFloat(s.trim());
-    }
-
-    public static float toFloat(Number number) {
-        return number.floatValue();
-    }
-
-    public static float toFloat(Object o) {
-        return o instanceof Float ? (Float) o
-                : o instanceof Number ? toFloat((Number) o)
-                        : o instanceof String ? toFloat((String) o) : (Float) cannotConvert(o, float.class);
-    }
-
-    public static double toDouble(String s) {
-        return Double.parseDouble(s.trim());
-    }
-
-    public static double toDouble(Number number) {
-        return number.doubleValue();
-    }
-
-    public static double toDouble(Object o) {
-        return o instanceof Double ? (Double) o
-                : o instanceof Number ? toDouble((Number) o)
-                        : o instanceof String ? toDouble((String) o) : (Double) cannotConvert(o, double.class);
-    }
-
-    public static BigDecimal toBigDecimal(String s) {
-        return new BigDecimal(s.trim());
-    }
-
-    public static BigDecimal toBigDecimal(Number number) {
-        // There are some values of "long" that cannot be represented as "double".
-        // Not so "int". If it isn't a long, go straight to double.
-        return number instanceof BigDecimal ? (BigDecimal) number
-                : number instanceof BigInteger ? new BigDecimal((BigInteger) number)
-                        : number instanceof Long ? new BigDecimal(number.longValue())
-                                : new BigDecimal(number.doubleValue());
-    }
-
-    public static BigDecimal toBigDecimal(Object o) {
-        return o instanceof Number ? toBigDecimal((Number) o) : toBigDecimal(o.toString());
-    }
-
-    /** Converts the internal representation of a SQL DATE (int) to the Java
-     * type used for UDF parameters ({@link java.sql.Date}). */
-    public static java.sql.Date internalToDate(int v) {
-        final long t = v * DateTimeUtils.MILLIS_PER_DAY;
-        return new java.sql.Date(t - LOCAL_TZ.getOffset(t));
-    }
-
-    /** As {@link #internalToDate(int)} but allows nulls. */
-    public static java.sql.Date internalToDate(Integer v) {
-        return v == null ? null : internalToDate(v.intValue());
-    }
-
-    /** Converts the internal representation of a SQL TIME (int) to the Java
-     * type used for UDF parameters ({@link java.sql.Time}). */
-    public static java.sql.Time internalToTime(int v) {
-        return new java.sql.Time(v - LOCAL_TZ.getOffset(v));
-    }
-
-    public static java.sql.Time internalToTime(Integer v) {
-        return v == null ? null : internalToTime(v.intValue());
-    }
-
-    /** Converts the internal representation of a SQL TIMESTAMP (long) to the Java
-     * type used for UDF parameters ({@link java.sql.Timestamp}). */
-    public static java.sql.Timestamp internalToTimestamp(long v) {
-        return new java.sql.Timestamp(v - LOCAL_TZ.getOffset(v));
-    }
-
-    public static java.sql.Timestamp internalToTimestamp(Long v) {
-        return v == null ? null : internalToTimestamp(v.longValue());
-    }
-
-    // Don't need shortValueOf etc. - Short.valueOf is sufficient.
-
-    /** Helper for CAST(... AS VARCHAR(maxLength)). */
-    public static String truncate(String s, int maxLength) {
-        if (s == null) {
-            return null;
-        } else if (s.length() > maxLength) {
-            return s.substring(0, maxLength);
-        } else {
-            return s;
-        }
-    }
-
-    /** Helper for CAST(... AS CHAR(maxLength)). */
-    public static String truncateOrPad(String s, int maxLength) {
-        if (s == null) {
-            return null;
-        } else {
-            final int length = s.length();
-            if (length > maxLength) {
-                return s.substring(0, maxLength);
-            } else {
-                return length < maxLength ? Spaces.padRight(s, maxLength) : s;
-            }
-        }
-    }
-
-    /** Helper for CAST(... AS VARBINARY(maxLength)). */
-    public static ByteString truncate(ByteString s, int maxLength) {
-        if (s == null) {
-            return null;
-        } else if (s.length() > maxLength) {
-            return s.substring(0, maxLength);
-        } else {
-            return s;
-        }
-    }
-
-    /** Helper for CAST(... AS BINARY(maxLength)). */
-    public static ByteString truncateOrPad(ByteString s, int maxLength) {
-        if (s == null) {
-            return null;
-        } else {
-            final int length = s.length();
-            if (length > maxLength) {
-                return s.substring(0, maxLength);
-            } else if (length < maxLength) {
-                return s.concat(new ByteString(new byte[maxLength - length]));
-            } else {
-                return s;
-            }
-        }
-    }
-
-    /** SQL {@code POSITION(seek IN string)} function. */
-    public static int position(String seek, String s) {
-        return s.indexOf(seek) + 1;
-    }
-
-    /** SQL {@code POSITION(seek IN string)} function for byte strings. */
-    public static int position(ByteString seek, ByteString s) {
-        return s.indexOf(seek) + 1;
-    }
-
-    /** SQL {@code POSITION(seek IN string FROM integer)} function. */
-    public static int position(String seek, String s, int from) {
-        final int from0 = from - 1; // 0-based
-        if (from0 > s.length() || from0 < 0) {
-            return 0;
-        }
-
-        return s.indexOf(seek, from0) + 1;
-    }
-
-    /** SQL {@code POSITION(seek IN string FROM integer)} function for byte
-     * strings. */
-    public static int position(ByteString seek, ByteString s, int from) {
-        final int from0 = from - 1;
-        if (from0 > s.length() || from0 < 0) {
-            return 0;
-        }
-
-        // ByteString doesn't have indexOf(ByteString, int) until avatica-1.9
-        // (see [CALCITE-1423]), so apply substring and find from there.
-        Bug.upgrade("in avatica-1.9, use ByteString.substring(ByteString, int)");
-        final int p = s.substring(from0).indexOf(seek);
-        if (p < 0) {
-            return 0;
-        }
-        return p + from;
-    }
-
-    /** Helper for rounding. Truncate(12345, 1000) returns 12000. */
-    public static long round(long v, long x) {
-        return truncate(v + x / 2, x);
-    }
-
-    /** Helper for rounding. Truncate(12345, 1000) returns 12000. */
-    public static long truncate(long v, long x) {
-        long remainder = v % x;
-        if (remainder < 0) {
-            remainder += x;
-        }
-        return v - remainder;
-    }
-
-    /** Helper for rounding. Truncate(12345, 1000) returns 12000. */
-    public static int round(int v, int x) {
-        return truncate(v + x / 2, x);
-    }
-
-    /** Helper for rounding. Truncate(12345, 1000) returns 12000. */
-    public static int truncate(int v, int x) {
-        int remainder = v % x;
-        if (remainder < 0) {
-            remainder += x;
-        }
-        return v - remainder;
-    }
-
-    /** SQL {@code CURRENT_TIMESTAMP} function. */
-    @NonDeterministic
-    public static long currentTimestamp(DataContext root) {
-        // Cast required for JDK 1.6.
-        return (Long) DataContext.Variable.CURRENT_TIMESTAMP.get(root);
-    }
-
-    /** SQL {@code CURRENT_TIME} function. */
-    @NonDeterministic
-    public static int currentTime(DataContext root) {
-        int time = (int) (currentTimestamp(root) % DateTimeUtils.MILLIS_PER_DAY);
-        if (time < 0) {
-            time += DateTimeUtils.MILLIS_PER_DAY;
-        }
-        return time;
-    }
-
-    /** SQL {@code CURRENT_DATE} function. */
-    @NonDeterministic
-    public static int currentDate(DataContext root) {
-        final long timestamp = currentTimestamp(root);
-        int date = (int) (timestamp / DateTimeUtils.MILLIS_PER_DAY);
-        final int time = (int) (timestamp % DateTimeUtils.MILLIS_PER_DAY);
-        if (time < 0) {
-            --date;
-        }
-        return date;
-    }
-
-    /** SQL {@code LOCAL_TIMESTAMP} function. */
-    @NonDeterministic
-    public static long localTimestamp(DataContext root) {
-        // Cast required for JDK 1.6.
-        return (Long) DataContext.Variable.LOCAL_TIMESTAMP.get(root);
-    }
-
-    /** SQL {@code LOCAL_TIME} function. */
-    @NonDeterministic
-    public static int localTime(DataContext root) {
-        return (int) (localTimestamp(root) % DateTimeUtils.MILLIS_PER_DAY);
-    }
-
-    /** SQL {@code TRANSLATE(string, search_chars, replacement_chars)}
-     * function. */
-    public static String translate3(String s, String search, String replacement) {
-        return org.apache.commons.lang3.StringUtils.replaceChars(s, search, replacement);
-    }
-
-    /** SQL {@code REPLACE(string, search, replacement)} function. */
-    public static String replace(String s, String search, String replacement) {
-        return s.replace(search, replacement);
-    }
-
-    /** Helper for "array element reference". Caller has already ensured that
-     * array and index are not null. Index is 1-based, per SQL. */
-    public static Object arrayItem(List list, int item) {
-        if (item < 1 || item > list.size()) {
-            return null;
-        }
-        return list.get(item - 1);
-    }
-
-    /** Helper for "map element reference". Caller has already ensured that
-     * array and index are not null. Index is 1-based, per SQL. */
-    public static Object mapItem(Map map, Object item) {
-        return map.get(item);
-    }
-
-    /** Implements the {@code [ ... ]} operator on an object whose type is not
-     * known until runtime.
-     */
-    public static Object item(Object object, Object index) {
-        if (object instanceof Map) {
-            return mapItem((Map) object, index);
-        }
-        if (object instanceof List && index instanceof Number) {
-            return arrayItem((List) object, ((Number) index).intValue());
-        }
-        return null;
-    }
-
-    /** As {@link #arrayItem} method, but allows array to be nullable. */
-    public static Object arrayItemOptional(List list, int item) {
-        if (list == null) {
-            return null;
-        }
-        return arrayItem(list, item);
-    }
-
-    /** As {@link #mapItem} method, but allows map to be nullable. */
-    public static Object mapItemOptional(Map map, Object item) {
-        if (map == null) {
-            return null;
-        }
-        return mapItem(map, item);
-    }
-
-    /** As {@link #item} method, but allows object to be nullable. */
-    public static Object itemOptional(Object object, Object index) {
-        if (object == null) {
-            return null;
-        }
-        return item(object, index);
-    }
-
-    /** NULL &rarr; FALSE, FALSE &rarr; FALSE, TRUE &rarr; TRUE. */
-    public static boolean isTrue(Boolean b) {
-        return b != null && b;
-    }
-
-    /** NULL &rarr; FALSE, FALSE &rarr; TRUE, TRUE &rarr; FALSE. */
-    public static boolean isFalse(Boolean b) {
-        return b != null && !b;
-    }
-
-    /** NULL &rarr; TRUE, FALSE &rarr; TRUE, TRUE &rarr; FALSE. */
-    public static boolean isNotTrue(Boolean b) {
-        return b == null || !b;
-    }
-
-    /** NULL &rarr; TRUE, FALSE &rarr; FALSE, TRUE &rarr; TRUE. */
-    public static boolean isNotFalse(Boolean b) {
-        return b == null || b;
-    }
-
-    /** NULL &rarr; NULL, FALSE &rarr; TRUE, TRUE &rarr; FALSE. */
-    public static Boolean not(Boolean b) {
-        return (b == null) ? null : !b;
-    }
-
-    /** Converts a JDBC array to a list. */
-    public static List arrayToList(final java.sql.Array a) {
-        if (a == null) {
-            return null;
-        }
-        try {
-            return Primitive.asList(a.getArray());
-        } catch (SQLException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /** Support the {@code CURRENT VALUE OF sequence} operator. */
-    @NonDeterministic
-    public static long sequenceCurrentValue(String key) {
-        return getAtomicLong(key).get();
-    }
-
-    /** Support the {@code NEXT VALUE OF sequence} operator. */
-    @NonDeterministic
-    public static long sequenceNextValue(String key) {
-        return getAtomicLong(key).incrementAndGet();
-    }
-
-    private static AtomicLong getAtomicLong(String key) {
-        final Map<String, AtomicLong> map = THREAD_SEQUENCES.get();
-        AtomicLong atomic = map.get(key);
-        if (atomic == null) {
-            atomic = new AtomicLong();
-            map.put(key, atomic);
-        }
-        return atomic;
-    }
-
-    /** Support the SLICE function. */
-    public static List slice(List list) {
-        return list;
-    }
-
-    /** Support the ELEMENT function. */
-    public static Object element(List list) {
-        switch (list.size()) {
-        case 0:
-            return null;
-        case 1:
-            return list.get(0);
-        default:
-            throw new RuntimeException("more than one value");
-        }
-    }
-
-    public static Function1<Object, Enumerable<ComparableList<Comparable>>> flatProduct(final int[] fieldCounts,
-            final boolean withOrdinality, final FlatProductInputType[] inputTypes) {
-        if (fieldCounts.length == 1) {
-            if (!withOrdinality && inputTypes[0] == FlatProductInputType.SCALAR) {
-                //noinspection unchecked
-                return (Function1) LIST_AS_ENUMERABLE;
-            } else {
-                return new Function1<Object, Enumerable<ComparableList<Comparable>>>() {
-                    public Enumerable<ComparableList<Comparable>> apply(Object row) {
-                        return p2(new Object[] { row }, fieldCounts, withOrdinality, inputTypes);
-                    }
-                };
-            }
-        }
-        return new Function1<Object, Enumerable<FlatLists.ComparableList<Comparable>>>() {
-            public Enumerable<FlatLists.ComparableList<Comparable>> apply(Object lists) {
-                return p2((Object[]) lists, fieldCounts, withOrdinality, inputTypes);
-            }
-        };
-    }
-
-    private static Enumerable<FlatLists.ComparableList<Comparable>> p2(Object[] lists, int[] fieldCounts,
-            boolean withOrdinality, FlatProductInputType[] inputTypes) {
-        final List<Enumerator<List<Comparable>>> enumerators = new ArrayList<>();
-        int totalFieldCount = 0;
-        for (int i = 0; i < lists.length; i++) {
-            int fieldCount = fieldCounts[i];
-            FlatProductInputType inputType = inputTypes[i];
-            Object inputObject = lists[i];
-            switch (inputType) {
-            case SCALAR:
-                @SuppressWarnings("unchecked")
-                List<Comparable> list = (List<Comparable>) inputObject;
-                enumerators
-                        .add(Linq4j.transform(Linq4j.enumerator(list), new Function1<Comparable, List<Comparable>>() {
-                            public List<Comparable> apply(Comparable a0) {
-                                return FlatLists.of(a0);
-                            }
-                        }));
-                break;
-            case LIST:
-                @SuppressWarnings("unchecked")
-                List<List<Comparable>> listList = (List<List<Comparable>>) inputObject;
-                enumerators.add(Linq4j.enumerator(listList));
-                break;
-            case MAP:
-                @SuppressWarnings("unchecked")
-                Map<Comparable, Comparable> map = (Map<Comparable, Comparable>) inputObject;
-                Enumerator<Entry<Comparable, Comparable>> enumerator = Linq4j.enumerator(map.entrySet());
-
-                Enumerator<List<Comparable>> transformed = Linq4j.transform(enumerator,
-                        new Function1<Entry<Comparable, Comparable>, List<Comparable>>() {
-                            public List<Comparable> apply(Entry<Comparable, Comparable> entry) {
-                                return FlatLists.<Comparable> of(entry.getKey(), entry.getValue());
-                            }
-                        });
-                enumerators.add(transformed);
-                break;
-            default:
-                break;
-            }
-            if (fieldCount < 0) {
-                ++totalFieldCount;
-            } else {
-                totalFieldCount += fieldCount;
-            }
-        }
-        if (withOrdinality) {
-            ++totalFieldCount;
-        }
-        return product(enumerators, totalFieldCount, withOrdinality);
-    }
-
-    public static Object[] array(Object... args) {
-        return args;
-    }
-
-    /** Similar to {@link Linq4j#product(Iterable)} but each resulting list
-     * implements {@link FlatLists.ComparableList}. */
-    public static <E extends Comparable> Enumerable<FlatLists.ComparableList<E>> product(
-            final List<Enumerator<List<E>>> enumerators, final int fieldCount, final boolean withOrdinality) {
-        return new AbstractEnumerable<FlatLists.ComparableList<E>>() {
-            public Enumerator<FlatLists.ComparableList<E>> enumerator() {
-                return new ProductComparableListEnumerator<>(enumerators, fieldCount, withOrdinality);
-            }
-        };
-    }
-
-    /** Adds a given number of months to a timestamp, represented as the number
-     * of milliseconds since the epoch. */
-    public static long addMonths(long timestamp, int m) {
-        final long millis = DateTimeUtils.floorMod(timestamp, DateTimeUtils.MILLIS_PER_DAY);
-        timestamp -= millis;
-        final long x = addMonths((int) (timestamp / DateTimeUtils.MILLIS_PER_DAY), m);
-        return x * DateTimeUtils.MILLIS_PER_DAY + millis;
-    }
-
-    /** Adds a given number of months to a date, represented as the number of
-     * days since the epoch. */
-    //override
-    public static int addMonths(int date, int m) {
-        int y0 = (int) DateTimeUtils.unixDateExtract(TimeUnitRange.YEAR, date);
-        int m0 = (int) DateTimeUtils.unixDateExtract(TimeUnitRange.MONTH, date);
-        int d0 = (int) DateTimeUtils.unixDateExtract(TimeUnitRange.DAY, date);
-        int y = (m + m0) / 12;
-        y0 += y;
-        m0 = m + m0 - y * 12;
-        if (m0 <= 0) {
-            m0 += 12;
-            assert m0 > 0;
-            y0--;
-        }
-        int last = lastDay(y0, m0);
-        if (d0 > last) {
-            d0 = last;
-        }
-        return DateTimeUtils.ymdToUnixDate(y0, m0, d0);
-    }
-
-    private static int lastDay(int y, int m) {
-        switch (m) {
-        case 2:
-            return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0) ? 29 : 28;
-        case 4:
-        case 6:
-        case 9:
-        case 11:
-            return 30;
-        default:
-            return 31;
-        }
-    }
-
-    /** Finds the number of months between two dates, each represented as the
-     * number of days since the epoch. */
-    public static int subtractMonths(int date0, int date1) {
-        if (date0 < date1) {
-            return -subtractMonths(date1, date0);
-        }
-        // Start with an estimate.
-        // Since no month has more than 31 days, the estimate is <= the true value.
-        int m = (date0 - date1) / 31;
-        for (;;) {
-            int date2 = addMonths(date1, m);
-            if (date2 >= date0) {
-                return m;
-            }
-            int date3 = addMonths(date1, m + 1);
-            if (date3 > date0) {
-                return m;
-            }
-            ++m;
-        }
-    }
-
-    public static int subtractMonths(long t0, long t1) {
-        final long millis0 = DateTimeUtils.floorMod(t0, DateTimeUtils.MILLIS_PER_DAY);
-        final int d0 = (int) DateTimeUtils.floorDiv(t0 - millis0, DateTimeUtils.MILLIS_PER_DAY);
-        final long millis1 = DateTimeUtils.floorMod(t1, DateTimeUtils.MILLIS_PER_DAY);
-        final int d1 = (int) DateTimeUtils.floorDiv(t1 - millis1, DateTimeUtils.MILLIS_PER_DAY);
-        int x = subtractMonths(d0, d1);
-        final long d2 = addMonths(d1, x);
-        if (d2 == d0 && millis0 < millis1) {
-            --x;
-        }
-        return x;
-    }
-
-    /** Enumerates over the cartesian product of the given lists, returning
-     * a comparable list for each row. */
-    private static class ProductComparableListEnumerator<E extends Comparable>
-            extends CartesianProductEnumerator<List<E>, FlatLists.ComparableList<E>> {
-        final E[] flatElements;
-        final List<E> list;
-        private final boolean withOrdinality;
-        private int ordinality;
-
-        ProductComparableListEnumerator(List<Enumerator<List<E>>> enumerators, int fieldCount, boolean withOrdinality) {
-            super(enumerators);
-            this.withOrdinality = withOrdinality;
-            flatElements = (E[]) new Comparable[fieldCount];
-            list = Arrays.asList(flatElements);
-        }
-
-        public FlatLists.ComparableList<E> current() {
-            int i = 0;
-            for (Object element : (Object[]) elements) {
-                final List list2 = (List) element;
-                Object[] a = list2.toArray();
-                System.arraycopy(a, 0, flatElements, i, a.length);
-                i += a.length;
-            }
-            if (withOrdinality) {
-                flatElements[i] = (E) Integer.valueOf(++ordinality); // 1-based
-            }
-            return FlatLists.ofComparable(list);
-        }
-    }
-
-    /** Type of argument passed into {@link #flatProduct}. */
-    public enum FlatProductInputType {
-        SCALAR, LIST, MAP
-    }
-
-}
-
-// End SqlFunctions.java
diff --git a/atopcalcite/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java b/atopcalcite/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java
deleted file mode 100644
index 320cd7c..0000000
--- a/atopcalcite/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java
+++ /dev/null
@@ -1,1336 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.calcite.sql.type;
-
-import org.apache.calcite.rel.type.RelDataType;
-import org.apache.calcite.rel.type.RelDataTypeFactory;
-import org.apache.calcite.rel.type.RelDataTypeFamily;
-import org.apache.calcite.rel.type.RelDataTypeField;
-import org.apache.calcite.rel.type.RelDataTypeFieldImpl;
-import org.apache.calcite.sql.SqlCall;
-import org.apache.calcite.sql.SqlCallBinding;
-import org.apache.calcite.sql.SqlCollation;
-import org.apache.calcite.sql.SqlDataTypeSpec;
-import org.apache.calcite.sql.SqlIdentifier;
-import org.apache.calcite.sql.SqlNode;
-import org.apache.calcite.sql.parser.SqlParserPos;
-import org.apache.calcite.sql.validate.SqlValidator;
-import org.apache.calcite.sql.validate.SqlValidatorScope;
-import org.apache.calcite.sql.validate.SqlValidatorUtil;
-import org.apache.calcite.util.NumberUtil;
-import org.apache.calcite.util.Pair;
-import org.apache.calcite.util.Util;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-
-import java.nio.charset.Charset;
-import java.util.AbstractList;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import static org.apache.calcite.util.Static.RESOURCE;
-
-/**
- * Contains utility methods used during SQL validation or type derivation.
- */
-public abstract class SqlTypeUtil {
-    //~ Methods ----------------------------------------------------------------
-
-    /**
-     * Checks whether two types or more are char comparable.
-     *
-     * @return Returns true if all operands are of char type and if they are
-     * comparable, i.e. of the same charset and collation of same charset
-     */
-    public static boolean isCharTypeComparable(List<RelDataType> argTypes) {
-        assert argTypes != null;
-        assert argTypes.size() >= 2;
-
-        // Filter out ANY elements.
-        List<RelDataType> argTypes2 = Lists.newArrayList();
-        for (RelDataType t : argTypes) {
-            if (!isAny(t)) {
-                argTypes2.add(t);
-            }
-        }
-
-        for (Pair<RelDataType, RelDataType> pair : Pair.adjacents(argTypes2)) {
-            RelDataType t0 = pair.left;
-            RelDataType t1 = pair.right;
-
-            if (!inCharFamily(t0) || !inCharFamily(t1)) {
-                return false;
-            }
-
-            if (t0.getCharset() == null) {
-                throw new AssertionError("RelDataType object should have been assigned "
-                        + "a (default) charset when calling deriveType");
-            } else if (!t0.getCharset().equals(t1.getCharset())) {
-                return false;
-            }
-
-            if (t0.getCollation() == null) {
-                throw new AssertionError("RelDataType object should have been assigned "
-                        + "a (default) collation when calling deriveType");
-            } else if (!t0.getCollation().getCharset().equals(
-                    t1.getCollation().getCharset())) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    /**
-     * Returns whether the operands to a call are char type-comparable.
-     *
-     * @param binding        Binding of call to operands
-     * @param operands       Operands to check for compatibility; usually the
-     *                       operands of the bound call, but not always
-     * @param throwOnFailure Whether to throw an exception on failure
-     * @return whether operands are valid
-     */
-    public static boolean isCharTypeComparable(
-            SqlCallBinding binding,
-            List<SqlNode> operands,
-            boolean throwOnFailure) {
-        final SqlValidator validator = binding.getValidator();
-        final SqlValidatorScope scope = binding.getScope();
-        assert operands != null;
-        assert operands.size() >= 2;
-
-        if (!isCharTypeComparable(
-                deriveAndCollectTypes(validator, scope, operands))) {
-            if (throwOnFailure) {
-                String msg = "";
-                for (int i = 0; i < operands.size(); i++) {
-                    if (i > 0) {
-                        msg += ", ";
-                    }
-                    msg += operands.get(i).toString();
-                }
-                throw binding.newError(RESOURCE.operandNotComparable(msg));
-            }
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Iterates over all operands, derives their types, and collects them into
-     * a list.
-     */
-    public static List<RelDataType> deriveAndCollectTypes(
-            SqlValidator validator,
-            SqlValidatorScope scope,
-            List<SqlNode> operands) {
-        // NOTE: Do not use an AbstractList. Don't want to be lazy. We want
-        // errors.
-        List<RelDataType> types = new ArrayList<RelDataType>();
-        for (SqlNode operand : operands) {
-            types.add(validator.deriveType(scope, operand));
-        }
-        return types;
-    }
-
-    /**
-     * Promotes a type to a row type (does nothing if it already is one).
-     *
-     * @param type      type to be promoted
-     * @param fieldName name to give field in row type; null for default of
-     *                  "ROW_VALUE"
-     * @return row type
-     */
-    public static RelDataType promoteToRowType(
-            RelDataTypeFactory typeFactory,
-            RelDataType type,
-            String fieldName) {
-        if (!type.isStruct()) {
-            if (fieldName == null) {
-                fieldName = "ROW_VALUE";
-            }
-            type = typeFactory.builder().add(fieldName, type).build();
-        }
-        return type;
-    }
-
-    /**
-     * Recreates a given RelDataType with nullability iff any of the operands
-     * of a call are nullable.
-     */
-    public static RelDataType makeNullableIfOperandsAre(
-            final SqlValidator validator,
-            final SqlValidatorScope scope,
-            final SqlCall call,
-            RelDataType type) {
-        for (SqlNode operand : call.getOperandList()) {
-            RelDataType operandType = validator.deriveType(scope, operand);
-
-            if (containsNullable(operandType)) {
-                RelDataTypeFactory typeFactory = validator.getTypeFactory();
-                type = typeFactory.createTypeWithNullability(type, true);
-                break;
-            }
-        }
-        return type;
-    }
-
-    /**
-     * Recreates a given RelDataType with nullability iff any of the param
-     * argTypes are nullable.
-     */
-    public static RelDataType makeNullableIfOperandsAre(
-            final RelDataTypeFactory typeFactory,
-            final List<RelDataType> argTypes,
-            RelDataType type) {
-        Preconditions.checkNotNull(type);
-        if (containsNullable(argTypes)) {
-            type = typeFactory.createTypeWithNullability(type, true);
-        }
-        return type;
-    }
-
-    /**
-     * Returns whether all of array of types are nullable.
-     */
-    public static boolean allNullable(List<RelDataType> types) {
-        for (RelDataType type : types) {
-            if (!containsNullable(type)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Returns whether one or more of an array of types is nullable.
-     */
-    public static boolean containsNullable(List<RelDataType> types) {
-        for (RelDataType type : types) {
-            if (containsNullable(type)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Determines whether a type or any of its fields (if a structured type) are
-     * nullable.
-     */
-    public static boolean containsNullable(RelDataType type) {
-        if (type.isNullable()) {
-            return true;
-        }
-        if (!type.isStruct()) {
-            return false;
-        }
-        for (RelDataTypeField field : type.getFieldList()) {
-            if (containsNullable(field.getType())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Returns typeName.equals(type.getSqlTypeName()). If
-     * typeName.equals(SqlTypeName.Any) true is always returned.
-     */
-    public static boolean isOfSameTypeName(
-            SqlTypeName typeName,
-            RelDataType type) {
-        return SqlTypeName.ANY.equals(typeName)
-                || typeName.equals(type.getSqlTypeName());
-    }
-
-    /**
-     * Returns true if any element in <code>typeNames</code> matches
-     * type.getSqlTypeName().
-     *
-     * @see #isOfSameTypeName(SqlTypeName, RelDataType)
-     */
-    public static boolean isOfSameTypeName(
-            Collection<SqlTypeName> typeNames,
-            RelDataType type) {
-        for (SqlTypeName typeName : typeNames) {
-            if (isOfSameTypeName(typeName, type)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * @return true if type is DATE, TIME, or TIMESTAMP
-     */
-    public static boolean isDatetime(RelDataType type) {
-        return SqlTypeFamily.DATETIME.contains(type);
-    }
-
-    /**
-     * @return true if type is some kind of INTERVAL
-     */
-    public static boolean isInterval(RelDataType type) {
-        return SqlTypeFamily.DATETIME_INTERVAL.contains(type);
-    }
-
-    /**
-     * @return true if type is in SqlTypeFamily.Character
-     */
-    public static boolean inCharFamily(RelDataType type) {
-        return type.getFamily() == SqlTypeFamily.CHARACTER;
-    }
-
-    /**
-     * @return true if type is in SqlTypeFamily.Character
-     */
-    public static boolean inCharFamily(SqlTypeName typeName) {
-        return typeName.getFamily() == SqlTypeFamily.CHARACTER;
-    }
-
-    /**
-     * @return true if type is in SqlTypeFamily.Boolean
-     */
-    public static boolean inBooleanFamily(RelDataType type) {
-        return type.getFamily() == SqlTypeFamily.BOOLEAN;
-    }
-
-    /**
-     * @return true if two types are in same type family
-     */
-    public static boolean inSameFamily(RelDataType t1, RelDataType t2) {
-        return t1.getFamily() == t2.getFamily();
-    }
-
-    /**
-     * @return true if two types are in same type family, or one or the other is
-     * of type {@link SqlTypeName#NULL}.
-     */
-    public static boolean inSameFamilyOrNull(RelDataType t1, RelDataType t2) {
-        return (t1.getSqlTypeName() == SqlTypeName.NULL)
-                || (t2.getSqlTypeName() == SqlTypeName.NULL)
-                || (t1.getFamily() == t2.getFamily());
-    }
-
-    /**
-     * @return true if type family is either character or binary
-     */
-    public static boolean inCharOrBinaryFamilies(RelDataType type) {
-        return (type.getFamily() == SqlTypeFamily.CHARACTER)
-                || (type.getFamily() == SqlTypeFamily.BINARY);
-    }
-
-    /**
-     * @return true if type is a LOB of some kind
-     */
-    public static boolean isLob(RelDataType type) {
-        // TODO jvs 9-Dec-2004:  once we support LOB types
-        return false;
-    }
-
-    /**
-     * @return true if type is variable width with bounded precision
-     */
-    public static boolean isBoundedVariableWidth(RelDataType type) {
-        SqlTypeName typeName = type.getSqlTypeName();
-        if (typeName == null) {
-            return false;
-        }
-        switch (typeName) {
-            case VARCHAR:
-            case VARBINARY:
-
-                // TODO angel 8-June-2005: Multiset should be LOB
-            case MULTISET:
-                return true;
-            default:
-                return false;
-        }
-    }
-
-    /**
-     * @return true if type is one of the integer types
-     */
-    public static boolean isIntType(RelDataType type) {
-        SqlTypeName typeName = type.getSqlTypeName();
-        if (typeName == null) {
-            return false;
-        }
-        switch (typeName) {
-            case TINYINT:
-            case SMALLINT:
-            case INTEGER:
-            case BIGINT:
-                return true;
-            default:
-                return false;
-        }
-    }
-
-    /**
-     * @return true if type is decimal
-     */
-    public static boolean isDecimal(RelDataType type) {
-        SqlTypeName typeName = type.getSqlTypeName();
-        if (typeName == null) {
-            return false;
-        }
-        return typeName == SqlTypeName.DECIMAL;
-    }
-
-    /**
-     * @return true if type is bigint
-     */
-    public static boolean isBigint(RelDataType type) {
-        SqlTypeName typeName = type.getSqlTypeName();
-        if (typeName == null) {
-            return false;
-        }
-        return typeName == SqlTypeName.BIGINT;
-    }
-
-    /**
-     * @return true if type is numeric with exact precision
-     */
-    public static boolean isExactNumeric(RelDataType type) {
-        SqlTypeName typeName = type.getSqlTypeName();
-        if (typeName == null) {
-            return false;
-        }
-        switch (typeName) {
-            case TINYINT:
-            case SMALLINT:
-            case INTEGER:
-            case BIGINT:
-            case DECIMAL:
-                return true;
-            default:
-                return false;
-        }
-    }
-
-    /** Returns whether a type's scale is set. */
-    public static boolean hasScale(RelDataType type) {
-        return type.getScale() != Integer.MIN_VALUE;
-    }
-
-    /**
-     * Returns the maximum value of an integral type, as a long value
-     */
-    public static long maxValue(RelDataType type) {
-        assert SqlTypeUtil.isIntType(type);
-        switch (type.getSqlTypeName()) {
-            case TINYINT:
-                return Byte.MAX_VALUE;
-            case SMALLINT:
-                return Short.MAX_VALUE;
-            case INTEGER:
-                return Integer.MAX_VALUE;
-            case BIGINT:
-                return Long.MAX_VALUE;
-            default:
-                throw Util.unexpected(type.getSqlTypeName());
-        }
-    }
-
-    /**
-     * @return true if type is numeric with approximate precision
-     */
-    public static boolean isApproximateNumeric(RelDataType type) {
-        SqlTypeName typeName = type.getSqlTypeName();
-        if (typeName == null) {
-            return false;
-        }
-        switch (typeName) {
-            case FLOAT:
-            case REAL:
-            case DOUBLE:
-                return true;
-            default:
-                return false;
-        }
-    }
-
-    /**
-     * @return true if type is numeric
-     */
-    public static boolean isNumeric(RelDataType type) {
-        return isExactNumeric(type) || isApproximateNumeric(type);
-    }
-
-    /**
-     * Tests whether two types have the same name and structure, possibly with
-     * differing modifiers. For example, VARCHAR(1) and VARCHAR(10) are
-     * considered the same, while VARCHAR(1) and CHAR(1) are considered
-     * different. Likewise, VARCHAR(1) MULTISET and VARCHAR(10) MULTISET are
-     * considered the same.
-     *
-     * @return true if types have same name and structure
-     */
-    public static boolean sameNamedType(RelDataType t1, RelDataType t2) {
-        if (t1.isStruct() || t2.isStruct()) {
-            if (!t1.isStruct() || !t2.isStruct()) {
-                return false;
-            }
-            if (t1.getFieldCount() != t2.getFieldCount()) {
-                return false;
-            }
-            List<RelDataTypeField> fields1 = t1.getFieldList();
-            List<RelDataTypeField> fields2 = t2.getFieldList();
-            for (int i = 0; i < fields1.size(); ++i) {
-                if (!sameNamedType(
-                        fields1.get(i).getType(),
-                        fields2.get(i).getType())) {
-                    return false;
-                }
-            }
-            return true;
-        }
-        RelDataType comp1 = t1.getComponentType();
-        RelDataType comp2 = t2.getComponentType();
-        if ((comp1 != null) || (comp2 != null)) {
-            if ((comp1 == null) || (comp2 == null)) {
-                return false;
-            }
-            if (!sameNamedType(comp1, comp2)) {
-                return false;
-            }
-        }
-        return t1.getSqlTypeName() == t2.getSqlTypeName();
-    }
-
-    /**
-     * Computes the maximum number of bytes required to represent a value of a
-     * type having user-defined precision. This computation assumes no overhead
-     * such as length indicators and NUL-terminators. Complex types for which
-     * multiple representations are possible (e.g. DECIMAL or TIMESTAMP) return
-     * 0.
-     *
-     * @param type type for which to compute storage
-     * @return maximum bytes, or 0 for a fixed-width type or type with unknown
-     * maximum
-     */
-    public static int getMaxByteSize(RelDataType type) {
-        SqlTypeName typeName = type.getSqlTypeName();
-
-        if (typeName == null) {
-            return 0;
-        }
-
-        switch (typeName) {
-            case CHAR:
-            case VARCHAR:
-                return (int) Math.ceil(
-                        ((double) type.getPrecision())
-                                * type.getCharset().newEncoder().maxBytesPerChar());
-
-            case BINARY:
-            case VARBINARY:
-                return type.getPrecision();
-
-            case MULTISET:
-
-                // TODO Wael Jan-24-2005: Need a better way to tell fennel this
-                // number. This a very generic place and implementation details like
-                // this doesnt belong here. Waiting to change this once we have blob
-                // support
-                return 4096;
-
-            default:
-                return 0;
-        }
-    }
-
-    /**
-     * Determines the minimum unscaled value of a numeric type
-     *
-     * @param type a numeric type
-     */
-    public static long getMinValue(RelDataType type) {
-        SqlTypeName typeName = type.getSqlTypeName();
-        switch (typeName) {
-            case TINYINT:
-                return Byte.MIN_VALUE;
-            case SMALLINT:
-                return Short.MIN_VALUE;
-            case INTEGER:
-                return Integer.MIN_VALUE;
-            case BIGINT:
-            case DECIMAL:
-                return NumberUtil.getMinUnscaled(type.getPrecision()).longValue();
-            default:
-                throw new AssertionError("getMinValue(" + typeName + ")");
-        }
-    }
-
-    /**
-     * Determines the maximum unscaled value of a numeric type
-     *
-     * @param type a numeric type
-     */
-    public static long getMaxValue(RelDataType type) {
-        SqlTypeName typeName = type.getSqlTypeName();
-        switch (typeName) {
-            case TINYINT:
-                return Byte.MAX_VALUE;
-            case SMALLINT:
-                return Short.MAX_VALUE;
-            case INTEGER:
-                return Integer.MAX_VALUE;
-            case BIGINT:
-            case DECIMAL:
-                return NumberUtil.getMaxUnscaled(type.getPrecision()).longValue();
-            default:
-                throw new AssertionError("getMaxValue(" + typeName + ")");
-        }
-    }
-
-    /**
-     * @return true if type has a representation as a Java primitive (ignoring
-     * nullability)
-     */
-    @Deprecated // to be removed before 2.0
-    public static boolean isJavaPrimitive(RelDataType type) {
-        SqlTypeName typeName = type.getSqlTypeName();
-        if (typeName == null) {
-            return false;
-        }
-
-        switch (typeName) {
-            case BOOLEAN:
-            case TINYINT:
-            case SMALLINT:
-            case INTEGER:
-            case BIGINT:
-            case FLOAT:
-            case REAL:
-            case DOUBLE:
-            case SYMBOL:
-                return true;
-            default:
-                return false;
-        }
-    }
-
-    /**
-     * @return class name of the wrapper for the primitive data type.
-     */
-    @Deprecated // to be removed before 2.0
-    public static String getPrimitiveWrapperJavaClassName(RelDataType type) {
-        if (type == null) {
-            return null;
-        }
-        SqlTypeName typeName = type.getSqlTypeName();
-        if (typeName == null) {
-            return null;
-        }
-
-        switch (typeName) {
-            case BOOLEAN:
-                return "Boolean";
-            default:
-                //noinspection deprecation
-                return getNumericJavaClassName(type);
-        }
-    }
-
-    /**
-     * @return class name of the numeric data type.
-     */
-    @Deprecated // to be removed before 2.0
-    public static String getNumericJavaClassName(RelDataType type) {
-        if (type == null) {
-            return null;
-        }
-        SqlTypeName typeName = type.getSqlTypeName();
-        if (typeName == null) {
-            return null;
-        }
-
-        switch (typeName) {
-            case TINYINT:
-                return "Byte";
-            case SMALLINT:
-                return "Short";
-            case INTEGER:
-                return "Integer";
-            case BIGINT:
-                return "Long";
-            case REAL:
-                return "Float";
-            case DECIMAL:
-            case FLOAT:
-            case DOUBLE:
-                return "Double";
-            default:
-                return null;
-        }
-    }
-
-    private static boolean isAny(RelDataType t) {
-        return t.getFamily() == SqlTypeFamily.ANY;
-    }
-
-    /**
-     * Tests whether a value can be assigned to a site.
-     *
-     * @param toType   type of the target site
-     * @param fromType type of the source value
-     * @return true iff assignable
-     */
-    public static boolean canAssignFrom(
-            RelDataType toType,
-            RelDataType fromType) {
-        if (isAny(toType) || isAny(fromType)) {
-            return true;
-        }
-
-        // TODO jvs 2-Jan-2005:  handle all the other cases like
-        // rows, collections, UDT's
-        if (fromType.getSqlTypeName() == SqlTypeName.NULL) {
-            // REVIEW jvs 4-Dec-2008: We allow assignment from NULL to any
-            // type, including NOT NULL types, since in the case where no
-            // rows are actually processed, the assignment is legal
-            // (FRG-365).  However, it would be better if the validator's
-            // NULL type inference guaranteed that we had already
-            // assigned a real (nullable) type to every NULL literal.
-            return true;
-        }
-
-        if (fromType.getSqlTypeName() == SqlTypeName.ARRAY) {
-            if (toType.getSqlTypeName() != SqlTypeName.ARRAY) {
-                return false;
-            }
-            return canAssignFrom(toType.getComponentType(), fromType.getComponentType());
-        }
-
-        if (areCharacterSetsMismatched(toType, fromType)) {
-            return false;
-        }
-
-        return toType.getFamily() == fromType.getFamily();
-    }
-
-    /**
-     * Determines whether two types both have different character sets. If one
-     * or the other type has no character set (e.g. in cast from INT to
-     * VARCHAR), that is not a mismatch.
-     *
-     * @param t1 first type
-     * @param t2 second type
-     * @return true iff mismatched
-     */
-    public static boolean areCharacterSetsMismatched(
-            RelDataType t1,
-            RelDataType t2) {
-        if (isAny(t1) || isAny(t2)) {
-            return false;
-        }
-
-        Charset cs1 = t1.getCharset();
-        Charset cs2 = t2.getCharset();
-        if ((cs1 != null) && (cs2 != null)) {
-            if (!cs1.equals(cs2)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Compares two types and returns true if fromType can be cast to toType.
-     *
-     * <p>REVIEW jvs 17-Dec-2004: the coerce param below shouldn't really be
-     * necessary. We're using it as a hack because
-     * {@link SqlTypeFactoryImpl#leastRestrictiveSqlType} isn't complete enough
-     * yet.  Once it is, this param (and the non-coerce rules of
-     * {@link SqlTypeAssignmentRules}) should go away.
-     *
-     * @param toType   target of assignment
-     * @param fromType source of assignment
-     * @param coerce   if true, the SQL rules for CAST are used; if false, the
-     *                 rules are similar to Java; e.g. you can't assign short x =
-     *                 (int) y, and you can't assign int x = (String) z.
-     * @return true iff cast is legal
-     */
-    public static boolean canCastFrom(
-            RelDataType toType,
-            RelDataType fromType,
-            boolean coerce) {
-        if (toType == fromType) {
-            return true;
-        }
-        if (isAny(toType) || isAny(fromType)) {
-            return true;
-        }
-
-        final SqlTypeName fromTypeName = fromType.getSqlTypeName();
-        final SqlTypeName toTypeName = toType.getSqlTypeName();
-        if (toType.isStruct() || fromType.isStruct()) {
-            if (toTypeName == SqlTypeName.DISTINCT) {
-                if (fromTypeName == SqlTypeName.DISTINCT) {
-                    // can't cast between different distinct types
-                    return false;
-                }
-                return canCastFrom(
-                        toType.getFieldList().get(0).getType(), fromType, coerce);
-            } else if (fromTypeName == SqlTypeName.DISTINCT) {
-                return canCastFrom(
-                        toType, fromType.getFieldList().get(0).getType(), coerce);
-            } else if (toTypeName == SqlTypeName.ROW) {
-                if (fromTypeName != SqlTypeName.ROW) {
-                    return false;
-                }
-                int n = toType.getFieldCount();
-                if (fromType.getFieldCount() != n) {
-                    return false;
-                }
-                for (int i = 0; i < n; ++i) {
-                    RelDataTypeField toField = toType.getFieldList().get(i);
-                    RelDataTypeField fromField = fromType.getFieldList().get(i);
-                    if (!canCastFrom(
-                            toField.getType(),
-                            fromField.getType(),
-                            coerce)) {
-                        return false;
-                    }
-                }
-                return true;
-            } else if (toTypeName == SqlTypeName.MULTISET) {
-                if (!fromType.isStruct()) {
-                    return false;
-                }
-                if (fromTypeName != SqlTypeName.MULTISET) {
-                    return false;
-                }
-                return canCastFrom(
-                        toType.getComponentType(),
-                        fromType.getComponentType(),
-                        coerce);
-            } else if (fromTypeName == SqlTypeName.MULTISET) {
-                return false;
-            } else {
-                return toType.getFamily() == fromType.getFamily();
-            }
-        }
-        RelDataType c1 = toType.getComponentType();
-        if (c1 != null) {
-            RelDataType c2 = fromType.getComponentType();
-            if (c2 == null) {
-                return false;
-            }
-            return canCastFrom(c1, c2, coerce);
-        }
-        if ((isInterval(fromType) && isExactNumeric(toType))
-                || (isInterval(toType) && isExactNumeric(fromType))) {
-            IntervalSqlType intervalType =
-                    (IntervalSqlType) (isInterval(fromType) ? fromType : toType);
-            if (!intervalType.getIntervalQualifier().isSingleDatetimeField()) {
-                // Casts between intervals and exact numerics must involve
-                // intervals with a single datetime field.
-                return false;
-            }
-        }
-        if (toTypeName == null || fromTypeName == null) {
-            return false;
-        }
-
-        // REVIEW jvs 9-Feb-2009: we don't impose SQL rules for character sets
-        // here; instead, we do that in SqlCastFunction.  The reason is that
-        // this method is called from at least one place (MedJdbcNameDirectory)
-        // where internally a cast across character repertoires is OK.  Should
-        // probably clean that up.
-
-        SqlTypeAssignmentRules rules = SqlTypeAssignmentRules.instance();
-        return rules.canCastFrom(toTypeName, fromTypeName, coerce);
-    }
-
-    /**
-     * Flattens a record type by recursively expanding any fields which are
-     * themselves record types. For each record type, a representative null
-     * value field is also prepended (with state NULL for a null value and FALSE
-     * for non-null), and all component types are asserted to be nullable, since
-     * SQL doesn't allow NOT NULL to be specified on attributes.
-     *
-     * @param typeFactory   factory which should produced flattened type
-     * @param recordType    type with possible nesting
-     * @param flatteningMap if non-null, receives map from unflattened ordinal
-     *                      to flattened ordinal (must have length at least
-     *                      recordType.getFieldList().size())
-     * @return flattened equivalent
-     */
-    public static RelDataType flattenRecordType(
-            RelDataTypeFactory typeFactory,
-            RelDataType recordType,
-            int[] flatteningMap) {
-        if (!recordType.isStruct()) {
-            return recordType;
-        }
-        List<RelDataTypeField> fieldList = new ArrayList<RelDataTypeField>();
-        boolean nested =
-                flattenFields(
-                        typeFactory,
-                        recordType,
-                        fieldList,
-                        flatteningMap);
-        if (!nested) {
-            return recordType;
-        }
-        List<RelDataType> types = new ArrayList<RelDataType>();
-        List<String> fieldNames = new ArrayList<String>();
-        int i = -1;
-        for (RelDataTypeField field : fieldList) {
-            ++i;
-            types.add(field.getType());
-            fieldNames.add(field.getName() + "_" + i);
-        }
-        return typeFactory.createStructType(types, fieldNames);
-    }
-
-    public static boolean needsNullIndicator(RelDataType recordType) {
-        // NOTE jvs 9-Mar-2005: It would be more storage-efficient to say that
-        // no null indicator is required for structured type columns declared
-        // as NOT NULL.  However, the uniformity of always having a null
-        // indicator makes things cleaner in many places.
-        return recordType.getSqlTypeName() == SqlTypeName.STRUCTURED;
-    }
-
-    private static boolean flattenFields(
-            RelDataTypeFactory typeFactory,
-            RelDataType type,
-            List<RelDataTypeField> list,
-            int[] flatteningMap) {
-        boolean nested = false;
-        if (needsNullIndicator(type)) {
-            // NOTE jvs 9-Mar-2005:  other code
-            // (e.g. RelStructuredTypeFlattener) relies on the
-            // null indicator field coming first.
-            RelDataType indicatorType =
-                    typeFactory.createSqlType(SqlTypeName.BOOLEAN);
-            if (type.isNullable()) {
-                indicatorType =
-                        typeFactory.createTypeWithNullability(
-                                indicatorType,
-                                true);
-            }
-            RelDataTypeField nullIndicatorField =
-                    new RelDataTypeFieldImpl(
-                            "NULL_VALUE",
-                            0,
-                            indicatorType);
-            list.add(nullIndicatorField);
-            nested = true;
-        }
-        for (RelDataTypeField field : type.getFieldList()) {
-            if (flatteningMap != null) {
-                flatteningMap[field.getIndex()] = list.size();
-            }
-            if (field.getType().isStruct()) {
-                nested = true;
-                flattenFields(
-                        typeFactory,
-                        field.getType(),
-                        list,
-                        null);
-            } else if (field.getType().getComponentType() != null) {
-                nested = true;
-
-                // TODO jvs 14-Feb-2005:  generalize to any kind of
-                // collection type
-                RelDataType flattenedCollectionType =
-                        typeFactory.createMultisetType(
-                                flattenRecordType(
-                                        typeFactory,
-                                        field.getType().getComponentType(),
-                                        null),
-                                -1);
-                field =
-                        new RelDataTypeFieldImpl(
-                                field.getName(),
-                                field.getIndex(),
-                                flattenedCollectionType);
-                list.add(field);
-            } else {
-                list.add(field);
-            }
-        }
-        return nested;
-    }
-
-    /**
-     * Converts an instance of RelDataType to an instance of SqlDataTypeSpec.
-     *
-     * @param type type descriptor
-     * @return corresponding parse representation
-     */
-    public static SqlDataTypeSpec convertTypeToSpec(RelDataType type) {
-        SqlTypeName typeName = type.getSqlTypeName();
-
-        // TODO jvs 28-Dec-2004:  support row types, user-defined types,
-        // interval types, multiset types, etc
-        assert typeName != null;
-        SqlIdentifier typeIdentifier =
-                new SqlIdentifier(
-                        typeName.name(),
-                        SqlParserPos.ZERO);
-
-        String charSetName = null;
-
-        if (inCharFamily(type)) {
-            charSetName = type.getCharset().name();
-            // TODO jvs 28-Dec-2004:  collation
-        }
-
-        // REVIEW jvs 28-Dec-2004:  discriminate between precision/scale
-        // zero and unspecified?
-
-        // REVIEW angel 11-Jan-2006:
-        // Use neg numbers to indicate unspecified precision/scale
-
-        if (typeName.allowsScale()) {
-            return new SqlDataTypeSpec(
-                    typeIdentifier,
-                    type.getPrecision(),
-                    type.getScale(),
-                    charSetName,
-                    null,
-                    SqlParserPos.ZERO);
-        } else if (typeName.allowsPrec()) {
-            return new SqlDataTypeSpec(
-                    typeIdentifier,
-                    type.getPrecision(),
-                    -1,
-                    charSetName,
-                    null,
-                    SqlParserPos.ZERO);
-        } else {
-            return new SqlDataTypeSpec(
-                    typeIdentifier,
-                    -1,
-                    -1,
-                    charSetName,
-                    null,
-                    SqlParserPos.ZERO);
-        }
-    }
-
-    public static RelDataType createMultisetType(
-            RelDataTypeFactory typeFactory,
-            RelDataType type,
-            boolean nullable) {
-        RelDataType ret = typeFactory.createMultisetType(type, -1);
-        return typeFactory.createTypeWithNullability(ret, nullable);
-    }
-
-    public static RelDataType createArrayType(
-            RelDataTypeFactory typeFactory,
-            RelDataType type,
-            boolean nullable) {
-        RelDataType ret = typeFactory.createArrayType(type, -1);
-        return typeFactory.createTypeWithNullability(ret, nullable);
-    }
-
-    public static RelDataType createMapType(
-            RelDataTypeFactory typeFactory,
-            RelDataType keyType,
-            RelDataType valueType,
-            boolean nullable) {
-        RelDataType ret = typeFactory.createMapType(keyType, valueType);
-        return typeFactory.createTypeWithNullability(ret, nullable);
-    }
-
-    /**
-     * Adds collation and charset to a character type, returns other types
-     * unchanged.
-     *
-     * @param type        Type
-     * @param typeFactory Type factory
-     * @return Type with added charset and collation, or unchanged type if it is
-     * not a char type.
-     */
-    public static RelDataType addCharsetAndCollation(
-            RelDataType type,
-            RelDataTypeFactory typeFactory) {
-        if (!inCharFamily(type)) {
-            return type;
-        }
-        Charset charset = type.getCharset();
-        if (charset == null) {
-            charset = typeFactory.getDefaultCharset();
-        }
-        SqlCollation collation = type.getCollation();
-        if (collation == null) {
-            collation = SqlCollation.IMPLICIT;
-        }
-
-        // todo: should get the implicit collation from repository
-        //   instead of null
-        type =
-                typeFactory.createTypeWithCharsetAndCollation(
-                        type,
-                        charset,
-                        collation);
-        SqlValidatorUtil.checkCharsetAndCollateConsistentIfCharType(type);
-        return type;
-    }
-
-    /**
-     * Returns whether two types are equal, ignoring nullability.
-     *
-     * <p>They need not come from the same factory.
-     *
-     * @param factory Type factory
-     * @param type1   First type
-     * @param type2   Second type
-     * @return whether types are equal, ignoring nullability
-     */
-    public static boolean equalSansNullability(
-            RelDataTypeFactory factory,
-            RelDataType type1,
-            RelDataType type2) {
-        if (type1.equals(type2)) {
-            return true;
-        }
-
-        if (isAny(type1) || isAny(type2)) {
-            return true;
-        }
-
-        if (type1.isNullable() == type2.isNullable()) {
-            // If types have the same nullability and they weren't equal above,
-            // they must be different.
-            return false;
-        }
-        return type1.equals(
-                factory.createTypeWithNullability(type2, type1.isNullable()));
-    }
-
-    /**
-     * Returns the ordinal of a given field in a record type, or -1 if the field
-     * is not found.
-     *
-     * @param type      Record type
-     * @param fieldName Name of field
-     * @return Ordinal of field
-     */
-    public static int findField(RelDataType type, String fieldName) {
-        List<RelDataTypeField> fields = type.getFieldList();
-        for (int i = 0; i < fields.size(); i++) {
-            RelDataTypeField field = fields.get(i);
-            if (field.getName().equals(fieldName)) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    /**
-     * Selects data types of the specified fields from an input row type.
-     * This is useful when identifying data types of a function that is going
-     * to operate on inputs that are specified as field ordinals (e.g.
-     * aggregate calls).
-     *
-     * @param rowType input row type
-     * @param requiredFields ordinals of the projected fields
-     * @return list of data types that are requested by requiredFields
-     */
-    public static List<RelDataType> projectTypes(final RelDataType rowType,
-                                                 final List<? extends Number> requiredFields) {
-        final List<RelDataTypeField> fields = rowType.getFieldList();
-
-        return new AbstractList<RelDataType>() {
-            @Override public RelDataType get(int index) {
-                return fields.get(requiredFields.get(index).intValue()).getType();
-            }
-
-            @Override public int size() {
-                return requiredFields.size();
-            }
-        };
-    }
-
-    /**
-     * Records a struct type with no fields.
-     *
-     * @param typeFactory Type factory
-     * @return Struct type with no fields
-     */
-    public static RelDataType createEmptyStructType(
-            RelDataTypeFactory typeFactory) {
-        return typeFactory.createStructType(
-                ImmutableList.<RelDataType>of(),
-                ImmutableList.<String>of());
-    }
-
-    /** Returns whether a type is flat. It is not flat if it is a record type that
-     * has one or more fields that are themselves record types. */
-    public static boolean isFlat(RelDataType type) {
-        if (type.isStruct()) {
-            for (RelDataTypeField field : type.getFieldList()) {
-                if (field.getType().isStruct()) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Returns whether two types are comparable. They need to be scalar types of
-     * the same family, or struct types whose fields are pairwise comparable.
-     *
-     * @param type1 First type
-     * @param type2 Second type
-     * @return Whether types are comparable
-     */
-    public static boolean isComparable(RelDataType type1, RelDataType type2) {
-        if (type1.isStruct() != type2.isStruct()) {
-            return false;
-        }
-
-        if (type1.isStruct()) {
-            int n = type1.getFieldCount();
-            if (n != type2.getFieldCount()) {
-                return false;
-            }
-            for (Pair<RelDataTypeField, RelDataTypeField> pair
-                    : Pair.zip(type1.getFieldList(), type2.getFieldList())) {
-                if (!isComparable(pair.left.getType(), pair.right.getType())) {
-                    return false;
-                }
-            }
-            return true;
-        }
-        RelDataTypeFamily family1 = null;
-        RelDataTypeFamily family2 = null;
-
-        // REVIEW jvs 2-June-2005:  This is needed to keep
-        // the Saffron type system happy.
-        if (type1.getSqlTypeName() != null) {
-            family1 = type1.getSqlTypeName().getFamily();
-        }
-        if (type2.getSqlTypeName() != null) {
-            family2 = type2.getSqlTypeName().getFamily();
-        }
-        if (family1 == null) {
-            family1 = type1.getFamily();
-        }
-        if (family2 == null) {
-            family2 = type2.getFamily();
-        }
-        if (family1 == family2) {
-            return true;
-        }
-
-        // If one of the operators is of type 'ANY', return true.
-        if (family1 == SqlTypeFamily.ANY
-                || family2 == SqlTypeFamily.ANY) {
-            return true;
-        }
-
-        // We can implicitly convert from character to date
-        if (family1 == SqlTypeFamily.CHARACTER
-                && canConvertStringInCompare(family2)
-                || family2 == SqlTypeFamily.CHARACTER
-                && canConvertStringInCompare(family1)) {
-            return true;
-        }
-
-        // HACK POINT: allow boolean = integer (integer = boolean)
-        if (type1 instanceof BasicSqlType && type2 instanceof BasicSqlType) {
-            SqlTypeName typeName1 = ((BasicSqlType) type1).typeName;
-            SqlTypeName typeName2 = ((BasicSqlType) type2).typeName;
-            if (typeName1 == SqlTypeName.INTEGER
-                    && typeName2 == SqlTypeName.BOOLEAN
-                    || typeName1 == SqlTypeName.BOOLEAN
-                    && typeName2 == SqlTypeName.INTEGER) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    /** Returns whether a character data type can be implicitly converted to a
-     * given family in a compare operation. */
-    private static boolean canConvertStringInCompare(RelDataTypeFamily family) {
-        if (family instanceof SqlTypeFamily) {
-            SqlTypeFamily sqlTypeFamily = (SqlTypeFamily) family;
-            switch (sqlTypeFamily) {
-                case DATE:
-                case TIME:
-                case TIMESTAMP:
-                case INTERVAL_DAY_TIME:
-                case INTERVAL_YEAR_MONTH:
-                case NUMERIC:
-                case APPROXIMATE_NUMERIC:
-                case EXACT_NUMERIC:
-                case INTEGER:
-                case BOOLEAN:
-                    return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Checks whether a type represents Unicode character data.
-     *
-     * @param type type to test
-     * @return whether type represents Unicode character data
-     */
-    public static boolean isUnicode(RelDataType type) {
-        Charset charset = type.getCharset();
-        if (charset == null) {
-            return false;
-        }
-        return charset.name().startsWith("UTF");
-    }
-
-    /** Returns the larger of two precisions, treating
-     * {@link RelDataType#PRECISION_NOT_SPECIFIED} as infinity. */
-    public static int maxPrecision(int p0, int p1) {
-        return (p0 == RelDataType.PRECISION_NOT_SPECIFIED
-                || p0 >= p1
-                && p1 != RelDataType.PRECISION_NOT_SPECIFIED) ? p0 : p1;
-    }
-
-    /** Returns whether a precision is greater or equal than another,
-     * treating {@link RelDataType#PRECISION_NOT_SPECIFIED} as infinity. */
-    public static int comparePrecision(int p0, int p1) {
-        if (p0 == p1) {
-            return 0;
-        }
-        if (p0 == RelDataType.PRECISION_NOT_SPECIFIED) {
-            return 1;
-        }
-        if (p1 == RelDataType.PRECISION_NOT_SPECIFIED) {
-            return -1;
-        }
-        return Integer.compare(p0, p1);
-    }
-
-    public static boolean isArray(RelDataType type) {
-        return type.getSqlTypeName() == SqlTypeName.ARRAY;
-    }
-}
-
-// End SqlTypeUtil.java
diff --git a/atopcalcite/src/main/java/org/apache/calcite/sql2rel/RelFieldTrimmer.java b/atopcalcite/src/main/java/org/apache/calcite/sql2rel/RelFieldTrimmer.java
deleted file mode 100644
index 70d1b2a..0000000
--- a/atopcalcite/src/main/java/org/apache/calcite/sql2rel/RelFieldTrimmer.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.calcite.sql2rel;
-
-import org.apache.calcite.plan.RelOptCluster;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.core.RelFactories;
-import org.apache.calcite.sql.validate.SqlValidator;
-import org.apache.calcite.tools.RelBuilder;
-import org.apache.calcite.util.ReflectiveVisitor;
-
-/*
- * OVERRIDE POINT:
- * - disable the whole RelFieldTrimmer
- */
-
-public class RelFieldTrimmer implements ReflectiveVisitor {
-
-    public RelFieldTrimmer(SqlValidator validator, RelBuilder relBuilder) {
-    }
-
-    public RelFieldTrimmer(SqlValidator validator, RelOptCluster cluster, RelFactories.ProjectFactory projectFactory, RelFactories.FilterFactory filterFactory, RelFactories.JoinFactory joinFactory, RelFactories.SemiJoinFactory semiJoinFactory, RelFactories.SortFactory sortFactory, RelFactories.AggregateFactory aggregateFactory, RelFactories.SetOpFactory setOpFactory) {
-    }
-
-    public RelNode trim(RelNode rootRel) {
-        return rootRel;
-    }
-
-}
diff --git a/atopcalcite/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java b/atopcalcite/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
deleted file mode 100644
index 519a73b..0000000
--- a/atopcalcite/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
+++ /dev/null
@@ -1,5656 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
-*/
-package org.apache.calcite.sql2rel;
-
-import static org.apache.calcite.sql.SqlUtil.stripAs;
-import static org.apache.calcite.util.Static.RESOURCE;
-
-import java.lang.reflect.Type;
-import java.math.BigDecimal;
-import java.util.AbstractList;
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Deque;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-
-import org.apache.calcite.avatica.util.Spaces;
-import org.apache.calcite.linq4j.Ord;
-import org.apache.calcite.plan.Convention;
-import org.apache.calcite.plan.RelOptCluster;
-import org.apache.calcite.plan.RelOptPlanner;
-import org.apache.calcite.plan.RelOptSamplingParameters;
-import org.apache.calcite.plan.RelOptTable;
-import org.apache.calcite.plan.RelOptUtil;
-import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.prepare.Prepare;
-import org.apache.calcite.prepare.RelOptTableImpl;
-import org.apache.calcite.rel.RelCollation;
-import org.apache.calcite.rel.RelCollationImpl;
-import org.apache.calcite.rel.RelCollationTraitDef;
-import org.apache.calcite.rel.RelCollations;
-import org.apache.calcite.rel.RelFieldCollation;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.RelRoot;
-import org.apache.calcite.rel.SingleRel;
-import org.apache.calcite.rel.core.Aggregate;
-import org.apache.calcite.rel.core.AggregateCall;
-import org.apache.calcite.rel.core.Collect;
-import org.apache.calcite.rel.core.CorrelationId;
-import org.apache.calcite.rel.core.Filter;
-import org.apache.calcite.rel.core.Join;
-import org.apache.calcite.rel.core.JoinInfo;
-import org.apache.calcite.rel.core.JoinRelType;
-import org.apache.calcite.rel.core.Project;
-import org.apache.calcite.rel.core.RelFactories;
-import org.apache.calcite.rel.core.Sample;
-import org.apache.calcite.rel.core.Sort;
-import org.apache.calcite.rel.core.Uncollect;
-import org.apache.calcite.rel.logical.LogicalAggregate;
-import org.apache.calcite.rel.logical.LogicalCorrelate;
-import org.apache.calcite.rel.logical.LogicalFilter;
-import org.apache.calcite.rel.logical.LogicalIntersect;
-import org.apache.calcite.rel.logical.LogicalJoin;
-import org.apache.calcite.rel.logical.LogicalMatch;
-import org.apache.calcite.rel.logical.LogicalMinus;
-import org.apache.calcite.rel.logical.LogicalProject;
-import org.apache.calcite.rel.logical.LogicalSort;
-import org.apache.calcite.rel.logical.LogicalTableFunctionScan;
-import org.apache.calcite.rel.logical.LogicalTableModify;
-import org.apache.calcite.rel.logical.LogicalTableScan;
-import org.apache.calcite.rel.logical.LogicalUnion;
-import org.apache.calcite.rel.logical.LogicalValues;
-import org.apache.calcite.rel.metadata.JaninoRelMetadataProvider;
-import org.apache.calcite.rel.metadata.RelColumnMapping;
-import org.apache.calcite.rel.metadata.RelMetadataQuery;
-import org.apache.calcite.rel.stream.Delta;
-import org.apache.calcite.rel.stream.LogicalDelta;
-import org.apache.calcite.rel.type.RelDataType;
-import org.apache.calcite.rel.type.RelDataTypeFactory;
-import org.apache.calcite.rel.type.RelDataTypeField;
-import org.apache.calcite.rex.RexBuilder;
-import org.apache.calcite.rex.RexCall;
-import org.apache.calcite.rex.RexCallBinding;
-import org.apache.calcite.rex.RexCorrelVariable;
-import org.apache.calcite.rex.RexDynamicParam;
-import org.apache.calcite.rex.RexFieldAccess;
-import org.apache.calcite.rex.RexFieldCollation;
-import org.apache.calcite.rex.RexInputRef;
-import org.apache.calcite.rex.RexLiteral;
-import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.rex.RexPatternFieldRef;
-import org.apache.calcite.rex.RexRangeRef;
-import org.apache.calcite.rex.RexShuttle;
-import org.apache.calcite.rex.RexSubQuery;
-import org.apache.calcite.rex.RexUtil;
-import org.apache.calcite.rex.RexWindowBound;
-import org.apache.calcite.schema.ModifiableTable;
-import org.apache.calcite.schema.ModifiableView;
-import org.apache.calcite.schema.Table;
-import org.apache.calcite.schema.TranslatableTable;
-import org.apache.calcite.schema.Wrapper;
-import org.apache.calcite.sql.JoinConditionType;
-import org.apache.calcite.sql.JoinType;
-import org.apache.calcite.sql.SemiJoinType;
-import org.apache.calcite.sql.SqlAggFunction;
-import org.apache.calcite.sql.SqlBasicCall;
-import org.apache.calcite.sql.SqlCall;
-import org.apache.calcite.sql.SqlCallBinding;
-import org.apache.calcite.sql.SqlDataTypeSpec;
-import org.apache.calcite.sql.SqlDelete;
-import org.apache.calcite.sql.SqlDynamicParam;
-import org.apache.calcite.sql.SqlExplainFormat;
-import org.apache.calcite.sql.SqlExplainLevel;
-import org.apache.calcite.sql.SqlFunction;
-import org.apache.calcite.sql.SqlIdentifier;
-import org.apache.calcite.sql.SqlInsert;
-import org.apache.calcite.sql.SqlIntervalQualifier;
-import org.apache.calcite.sql.SqlJoin;
-import org.apache.calcite.sql.SqlKind;
-import org.apache.calcite.sql.SqlLiteral;
-import org.apache.calcite.sql.SqlMatchRecognize;
-import org.apache.calcite.sql.SqlMerge;
-import org.apache.calcite.sql.SqlNode;
-import org.apache.calcite.sql.SqlNodeList;
-import org.apache.calcite.sql.SqlNumericLiteral;
-import org.apache.calcite.sql.SqlOperator;
-import org.apache.calcite.sql.SqlOperatorTable;
-import org.apache.calcite.sql.SqlOrderBy;
-import org.apache.calcite.sql.SqlSampleSpec;
-import org.apache.calcite.sql.SqlSelect;
-import org.apache.calcite.sql.SqlSelectKeyword;
-import org.apache.calcite.sql.SqlSetOperator;
-import org.apache.calcite.sql.SqlUnnestOperator;
-import org.apache.calcite.sql.SqlUpdate;
-import org.apache.calcite.sql.SqlUtil;
-import org.apache.calcite.sql.SqlValuesOperator;
-import org.apache.calcite.sql.SqlWindow;
-import org.apache.calcite.sql.SqlWith;
-import org.apache.calcite.sql.SqlWithItem;
-import org.apache.calcite.sql.fun.SqlCountAggFunction;
-import org.apache.calcite.sql.fun.SqlInOperator;
-import org.apache.calcite.sql.fun.SqlRowOperator;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
-import org.apache.calcite.sql.parser.SqlParserPos;
-import org.apache.calcite.sql.type.SqlReturnTypeInference;
-import org.apache.calcite.sql.type.SqlTypeName;
-import org.apache.calcite.sql.type.SqlTypeUtil;
-import org.apache.calcite.sql.type.TableFunctionReturnTypeInference;
-import org.apache.calcite.sql.util.SqlBasicVisitor;
-import org.apache.calcite.sql.util.SqlVisitor;
-import org.apache.calcite.sql.validate.AggregatingSelectScope;
-import org.apache.calcite.sql.validate.CollectNamespace;
-import org.apache.calcite.sql.validate.DelegatingScope;
-import org.apache.calcite.sql.validate.ListScope;
-import org.apache.calcite.sql.validate.MatchRecognizeScope;
-import org.apache.calcite.sql.validate.ParameterScope;
-import org.apache.calcite.sql.validate.SelectScope;
-import org.apache.calcite.sql.validate.SqlMonotonicity;
-import org.apache.calcite.sql.validate.SqlNameMatcher;
-import org.apache.calcite.sql.validate.SqlQualified;
-import org.apache.calcite.sql.validate.SqlUserDefinedTableFunction;
-import org.apache.calcite.sql.validate.SqlUserDefinedTableMacro;
-import org.apache.calcite.sql.validate.SqlValidator;
-import org.apache.calcite.sql.validate.SqlValidatorImpl;
-import org.apache.calcite.sql.validate.SqlValidatorNamespace;
-import org.apache.calcite.sql.validate.SqlValidatorScope;
-import org.apache.calcite.sql.validate.SqlValidatorTable;
-import org.apache.calcite.sql.validate.SqlValidatorUtil;
-import org.apache.calcite.tools.RelBuilder;
-import org.apache.calcite.util.ImmutableBitSet;
-import org.apache.calcite.util.ImmutableIntList;
-import org.apache.calcite.util.Litmus;
-import org.apache.calcite.util.NlsString;
-import org.apache.calcite.util.NumberUtil;
-import org.apache.calcite.util.Pair;
-import org.apache.calcite.util.Util;
-import org.apache.calcite.util.trace.CalciteTrace;
-import org.slf4j.Logger;
-
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableList.Builder;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-/*
- * The code has synced with calcite. Hope one day, we could remove the hardcode override point.
- * OVERRIDE POINT:
- * - DEFAULT_IN_SUB_QUERY_THRESHOLD, was `20`, now `Integer.MAX_VALUE`
- * - isTrimUnusedFields(), override to false
- * - AggConverter.translateAgg(...), skip column reading for COUNT(COL), for https://jirap.corp.ebay.com/browse/KYLIN-104
- * - convertQuery(), call hackSelectStar() at the end
- * - createJoin() check cast operation
- */
-
-/**
- * Converts a SQL parse tree (consisting of
- * {@link org.apache.calcite.sql.SqlNode} objects) into a relational algebra
- * expression (consisting of {@link org.apache.calcite.rel.RelNode} objects).
- *
- * <p>The public entry points are: {@link #convertQuery},
- * {@link #convertExpression(SqlNode)}.
- */
-public class SqlToRelConverter {
-  //~ Static fields/initializers ---------------------------------------------
-
-  protected static final Logger SQL2REL_LOGGER =
-      CalciteTrace.getSqlToRelTracer();
-
-  private static final BigDecimal TWO = BigDecimal.valueOf(2L);
-
-  /** Size of the smallest IN list that will be converted to a semijoin to a
-   * static table. */
-  /* OVERRIDE POINT */
-  public static final int DEFAULT_IN_SUB_QUERY_THRESHOLD = Integer.MAX_VALUE;
-
-  @Deprecated // to be removed before 2.0
-  public static final int DEFAULT_IN_SUBQUERY_THRESHOLD =
-      DEFAULT_IN_SUB_QUERY_THRESHOLD;
-
-  //~ Instance fields --------------------------------------------------------
-
-  protected final SqlValidator validator;
-  protected final RexBuilder rexBuilder;
-  protected final Prepare.CatalogReader catalogReader;
-  protected final RelOptCluster cluster;
-  private SubQueryConverter subQueryConverter;
-  protected final List<RelNode> leaves = new ArrayList<>();
-  private final List<SqlDynamicParam> dynamicParamSqlNodes = new ArrayList<>();
-  private final SqlOperatorTable opTab;
-  protected final RelDataTypeFactory typeFactory;
-  private final SqlNodeToRexConverter exprConverter;
-  private int explainParamCount;
-  public final SqlToRelConverter.Config config;
-
-  /**
-   * Fields used in name resolution for correlated sub-queries.
-   */
-  private final Map<CorrelationId, DeferredLookup> mapCorrelToDeferred =
-      new HashMap<>();
-
-  /**
-   * Stack of names of datasets requested by the <code>
-   * TABLE(SAMPLE(&lt;datasetName&gt;, &lt;query&gt;))</code> construct.
-   */
-  private final Deque<String> datasetStack = new ArrayDeque<>();
-
-  /**
-   * Mapping of non-correlated sub-queries that have been converted to their
-   * equivalent constants. Used to avoid re-evaluating the sub-query if it's
-   * already been evaluated.
-   */
-  private final Map<SqlNode, RexNode> mapConvertedNonCorrSubqs =
-      new HashMap<>();
-
-  public final RelOptTable.ViewExpander viewExpander;
-
-  //~ Constructors -----------------------------------------------------------
-  /**
-   * Creates a converter.
-   *
-   * @param viewExpander    Preparing statement
-   * @param validator       Validator
-   * @param catalogReader   Schema
-   * @param planner         Planner
-   * @param rexBuilder      Rex builder
-   * @param convertletTable Expression converter
-   */
-  @Deprecated // to be removed before 2.0
-  public SqlToRelConverter(
-      RelOptTable.ViewExpander viewExpander,
-      SqlValidator validator,
-      Prepare.CatalogReader catalogReader,
-      RelOptPlanner planner,
-      RexBuilder rexBuilder,
-      SqlRexConvertletTable convertletTable) {
-    this(viewExpander, validator, catalogReader,
-        RelOptCluster.create(planner, rexBuilder), convertletTable,
-        Config.DEFAULT);
-  }
-
-  @Deprecated // to be removed before 2.0
-  public SqlToRelConverter(
-      RelOptTable.ViewExpander viewExpander,
-      SqlValidator validator,
-      Prepare.CatalogReader catalogReader,
-      RelOptCluster cluster,
-      SqlRexConvertletTable convertletTable) {
-    this(viewExpander, validator, catalogReader, cluster, convertletTable,
-        Config.DEFAULT);
-  }
-
-  /* Creates a converter. */
-  public SqlToRelConverter(
-      RelOptTable.ViewExpander viewExpander,
-      SqlValidator validator,
-      Prepare.CatalogReader catalogReader,
-      RelOptCluster cluster,
-      SqlRexConvertletTable convertletTable,
-      Config config) {
-    this.viewExpander = viewExpander;
-    this.opTab =
-        (validator
-            == null) ? SqlStdOperatorTable.instance()
-            : validator.getOperatorTable();
-    this.validator = validator;
-    this.catalogReader = catalogReader;
-    this.subQueryConverter = new NoOpSubQueryConverter();
-    this.rexBuilder = cluster.getRexBuilder();
-    this.typeFactory = rexBuilder.getTypeFactory();
-    this.cluster = Preconditions.checkNotNull(cluster);
-    this.exprConverter = new SqlNodeToRexConverterImpl(convertletTable);
-    this.explainParamCount = 0;
-    this.config = new ConfigBuilder().withConfig(config).build();
-  }
-
-  //~ Methods ----------------------------------------------------------------
-
-  /**
-   * @return the RelOptCluster in use.
-   */
-  public RelOptCluster getCluster() {
-    return cluster;
-  }
-
-  /**
-   * Returns the row-expression builder.
-   */
-  public RexBuilder getRexBuilder() {
-    return rexBuilder;
-  }
-
-  /**
-   * Returns the number of dynamic parameters encountered during translation;
-   * this must only be called after {@link #convertQuery}.
-   *
-   * @return number of dynamic parameters
-   */
-  public int getDynamicParamCount() {
-    return dynamicParamSqlNodes.size();
-  }
-
-  /**
-   * Returns the type inferred for a dynamic parameter.
-   *
-   * @param index 0-based index of dynamic parameter
-   * @return inferred type, never null
-   */
-  public RelDataType getDynamicParamType(int index) {
-    SqlNode sqlNode = dynamicParamSqlNodes.get(index);
-    if (sqlNode == null) {
-      throw Util.needToImplement("dynamic param type inference");
-    }
-    return validator.getValidatedNodeType(sqlNode);
-  }
-
-  /**
-   * Returns the current count of the number of dynamic parameters in an
-   * EXPLAIN PLAN statement.
-   *
-   * @param increment if true, increment the count
-   * @return the current count before the optional increment
-   */
-  public int getDynamicParamCountInExplain(boolean increment) {
-    int retVal = explainParamCount;
-    if (increment) {
-      ++explainParamCount;
-    }
-    return retVal;
-  }
-
-  /**
-   * @return mapping of non-correlated sub-queries that have been converted to
-   * the constants that they evaluate to
-   */
-  public Map<SqlNode, RexNode> getMapConvertedNonCorrSubqs() {
-    return mapConvertedNonCorrSubqs;
-  }
-
-  /**
-   * Adds to the current map of non-correlated converted sub-queries the
-   * elements from another map that contains non-correlated sub-queries that
-   * have been converted by another SqlToRelConverter.
-   *
-   * @param alreadyConvertedNonCorrSubqs the other map
-   */
-  public void addConvertedNonCorrSubqs(
-      Map<SqlNode, RexNode> alreadyConvertedNonCorrSubqs) {
-    mapConvertedNonCorrSubqs.putAll(alreadyConvertedNonCorrSubqs);
-  }
-
-  /**
-   * Sets a new SubQueryConverter. To have any effect, this must be called
-   * before any convert method.
-   *
-   * @param converter new SubQueryConverter
-   */
-  public void setSubQueryConverter(SubQueryConverter converter) {
-    subQueryConverter = converter;
-  }
-
-  /**
-   * Sets the number of dynamic parameters in the current EXPLAIN PLAN
-   * statement.
-   *
-   * @param explainParamCount number of dynamic parameters in the statement
-   */
-  public void setDynamicParamCountInExplain(int explainParamCount) {
-    assert config.isExplain();
-    this.explainParamCount = explainParamCount;
-  }
-
-  private void checkConvertedType(SqlNode query, RelNode result) {
-    if (query.isA(SqlKind.DML)) {
-      return;
-    }
-    // Verify that conversion from SQL to relational algebra did
-    // not perturb any type information.  (We can't do this if the
-    // SQL statement is something like an INSERT which has no
-    // validator type information associated with its result,
-    // hence the namespace check above.)
-    final List<RelDataTypeField> validatedFields =
-        validator.getValidatedNodeType(query).getFieldList();
-    final RelDataType validatedRowType =
-        validator.getTypeFactory().createStructType(
-            Pair.right(validatedFields),
-            SqlValidatorUtil.uniquify(Pair.left(validatedFields),
-                catalogReader.nameMatcher().isCaseSensitive()));
-
-    final List<RelDataTypeField> convertedFields =
-        result.getRowType().getFieldList().subList(0, validatedFields.size());
-    final RelDataType convertedRowType =
-        validator.getTypeFactory().createStructType(convertedFields);
-
-    if (!RelOptUtil.equal("validated row type", validatedRowType,
-        "converted row type", convertedRowType, Litmus.IGNORE)) {
-      throw new AssertionError("Conversion to relational algebra failed to "
-          + "preserve datatypes:\n"
-          + "validated type:\n"
-          + validatedRowType.getFullTypeString()
-          + "\nconverted type:\n"
-          + convertedRowType.getFullTypeString()
-          + "\nrel:\n"
-          + RelOptUtil.toString(result));
-    }
-  }
-
-  public RelNode flattenTypes(
-      RelNode rootRel,
-      boolean restructure) {
-    RelStructuredTypeFlattener typeFlattener =
-        new RelStructuredTypeFlattener(rexBuilder, createToRelContext(), restructure);
-    return typeFlattener.rewrite(rootRel);
-  }
-
-  /**
-   * If sub-query is correlated and decorrelation is enabled, performs
-   * decorrelation.
-   *
-   * @param query   Query
-   * @param rootRel Root relational expression
-   * @return New root relational expression after decorrelation
-   */
-  public RelNode decorrelate(SqlNode query, RelNode rootRel) {
-    if (!enableDecorrelation()) {
-      return rootRel;
-    }
-    final RelNode result = decorrelateQuery(rootRel);
-    if (result != rootRel) {
-      checkConvertedType(query, result);
-    }
-    return result;
-  }
-
-  /**
-   * Walks over a tree of relational expressions, replacing each
-   * {@link RelNode} with a 'slimmed down' relational expression that projects
-   * only the fields required by its consumer.
-   *
-   * <p>This may make things easier for the optimizer, by removing crud that
-   * would expand the search space, but is difficult for the optimizer itself
-   * to do it, because optimizer rules must preserve the number and type of
-   * fields. Hence, this transform that operates on the entire tree, similar
-   * to the {@link RelStructuredTypeFlattener type-flattening transform}.
-   *
-   * <p>Currently this functionality is disabled in farrago/luciddb; the
-   * default implementation of this method does nothing.
-   *
-   * @param ordered Whether the relational expression must produce results in
-   * a particular order (typically because it has an ORDER BY at top level)
-   * @param rootRel Relational expression that is at the root of the tree
-   * @return Trimmed relational expression
-   */
-  public RelNode trimUnusedFields(boolean ordered, RelNode rootRel) {
-    // Trim fields that are not used by their consumer.
-    if (isTrimUnusedFields()) {
-      final RelFieldTrimmer trimmer = newFieldTrimmer();
-      final List<RelCollation> collations =
-          rootRel.getTraitSet().getTraits(RelCollationTraitDef.INSTANCE);
-      rootRel = trimmer.trim(rootRel);
-      if (!ordered
-          && collations != null
-          && !collations.isEmpty()
-          && !collations.equals(ImmutableList.of(RelCollations.EMPTY))) {
-        final RelTraitSet traitSet = rootRel.getTraitSet()
-            .replace(RelCollationTraitDef.INSTANCE, collations);
-        rootRel = rootRel.copy(traitSet, rootRel.getInputs());
-      }
-      if (SQL2REL_LOGGER.isDebugEnabled()) {
-        SQL2REL_LOGGER.debug(
-            RelOptUtil.dumpPlan("Plan after trimming unused fields", rootRel,
-                SqlExplainFormat.TEXT, SqlExplainLevel.EXPPLAN_ATTRIBUTES));
-      }
-    }
-    return rootRel;
-  }
-
-  /**
-   * Creates a RelFieldTrimmer.
-   *
-   * @return Field trimmer
-   */
-  protected RelFieldTrimmer newFieldTrimmer() {
-    final RelBuilder relBuilder =
-        RelFactories.LOGICAL_BUILDER.create(cluster, null);
-    return new RelFieldTrimmer(validator, relBuilder);
-  }
-
-  /**
-   * Converts an unvalidated query's parse tree into a relational expression.
-   *
-   * @param query           Query to convert
-   * @param needsValidation Whether to validate the query before converting;
-   *                        <code>false</code> if the query has already been
-   *                        validated.
-   * @param top             Whether the query is top-level, say if its result
-   *                        will become a JDBC result set; <code>false</code> if
-   *                        the query will be part of a view.
-   */
-  public RelRoot convertQuery(
-      SqlNode query,
-      final boolean needsValidation,
-      final boolean top) {
-
-    SqlNode origQuery = query; /* OVERRIDE POINT */
-
-    if (needsValidation) {
-      query = validator.validate(query);
-    }
-
-    RelMetadataQuery.THREAD_PROVIDERS.set(
-        JaninoRelMetadataProvider.of(cluster.getMetadataProvider()));
-    RelNode result = convertQueryRecursive(query, top, null).rel;
-    if (top) {
-      if (isStream(query)) {
-        result = new LogicalDelta(cluster, result.getTraitSet(), result);
-      }
-    }
-    RelCollation collation = RelCollations.EMPTY;
-    if (!query.isA(SqlKind.DML)) {
-      if (isOrdered(query)) {
-        collation = requiredCollation(result);
-      }
-    }
-    checkConvertedType(query, result);
-
-    if (SQL2REL_LOGGER.isDebugEnabled()) {
-      SQL2REL_LOGGER.debug(
-          RelOptUtil.dumpPlan("Plan after converting SqlNode to RelNode",
-              result, SqlExplainFormat.TEXT,
-              SqlExplainLevel.EXPPLAN_ATTRIBUTES));
-    }
-
-    final RelDataType validatedRowType = validator.getValidatedNodeType(query);
-    RelRoot origResult = RelRoot.of(result, validatedRowType, query.getKind())
-            .withCollation(collation);
-    return hackSelectStar(origQuery, origResult);
-  }
-
-  /* OVERRIDE POINT */
-  private RelRoot hackSelectStar(SqlNode query, RelRoot root) {
-    //        /*
-    //         * Rel tree is like:
-    //         *
-    //         *   LogicalSort (optional)
-    //         *    |- LogicalProject
-    //         *        |- LogicalFilter (optional)
-    //         *            |- OLAPTableScan or LogicalJoin
-    //         */
-    LogicalProject rootPrj = null;
-    LogicalSort rootSort = null;
-    if (root.rel instanceof LogicalProject) {
-      rootPrj = (LogicalProject) root.rel;
-    } else if (root.rel instanceof LogicalSort && root.rel.getInput(0) instanceof LogicalProject) {
-      rootPrj = (LogicalProject) root.rel.getInput(0);
-      rootSort = (LogicalSort) root.rel;
-    } else {
-      return root;
-    }
-
-    //
-    RelNode input = rootPrj.getInput();
-    //        if (!(//
-    //                isAmong(input, "OLAPTableScan", "LogicalJoin")//
-    //                || (isAmong(input, "LogicalFilter") && isAmong(input.getInput(0), "OLAPTableScan", "LogicalJoin"))//
-    //             ))
-    //            return root;
-    //
-    //        if (rootPrj.getRowType().getFieldCount() < input.getRowType().getFieldCount())
-    //            return root;
-
-    RelDataType inType = rootPrj.getRowType();
-    List<String> inFields = inType.getFieldNames();
-    List<RexNode> projExp = new ArrayList<>();
-    List<Pair<Integer, String>> projFields = new ArrayList<>();
-    Map<Integer,Integer> projFieldMapping = new HashMap<>();
-    RelDataTypeFactory.FieldInfoBuilder projTypeBuilder = getCluster().getTypeFactory().builder();
-    RelDataTypeFactory.FieldInfoBuilder validTypeBuilder = getCluster().getTypeFactory().builder();
-
-    boolean hiddenColumnExists = false;
-    for (int i = 0; i < root.validatedRowType.getFieldList().size(); i++) {
-      if (root.validatedRowType.getFieldNames().get(i).startsWith("_KY_"))
-        hiddenColumnExists = true;
-    }
-    if(!hiddenColumnExists) {
-      return root;
-    }
-
-    for (int i = 0; i < inFields.size(); i++) {
-      if (!inFields.get(i).startsWith("_KY_")) {
-        projExp.add(rootPrj.getProjects().get(i));
-        projFieldMapping.put(i, projFields.size());
-        projFields.add(Pair.of(projFields.size(), inFields.get(i)));
-        projTypeBuilder.add(inType.getFieldList().get(i));
-
-        if (i < root.validatedRowType.getFieldList().size()) //for cases like kylin-it/src/test/resources/query/sql_verifyCount/query10.sql
-          validTypeBuilder.add(root.validatedRowType.getFieldList().get(i));
-      }
-    }
-
-    RelDataType projRowType = getCluster().getTypeFactory().createStructType(projTypeBuilder);
-    rootPrj = LogicalProject.create(input, projExp, projRowType);
-    if (rootSort != null) {
-      //for cases like kylin-it/src/test/resources/query/sql_verifyCount/query10.sql, original RelCollation is stale, need to fix its fieldIndex
-      RelCollation originalCollation = rootSort.collation;
-      RelCollation newCollation = null;
-      List<RelFieldCollation> fieldCollations = originalCollation.getFieldCollations();
-      ImmutableList.Builder<RelFieldCollation> newFieldCollations = ImmutableList.builder();
-      for (RelFieldCollation fieldCollation : fieldCollations) {
-        if(projFieldMapping.containsKey(fieldCollation.getFieldIndex())) {
-          newFieldCollations.add(fieldCollation.copy(projFieldMapping.get(fieldCollation.getFieldIndex())));
-        } else {
-          newFieldCollations.add(fieldCollation);
-        }
-      }
-      newCollation = RelCollationImpl.of(newFieldCollations.build());
-      rootSort = LogicalSort.create(rootPrj, newCollation, rootSort.offset, rootSort.fetch);
-    }
-
-    RelDataType validRowType = getCluster().getTypeFactory().createStructType(validTypeBuilder);
-    root = new RelRoot(rootSort == null ? rootPrj : rootSort, validRowType, root.kind, projFields, rootSort == null ? root.collation : rootSort.getCollation());
-
-    validator.setValidatedNodeType(query, validRowType);
-
-    return root;
-  }
-
-  private static boolean isStream(SqlNode query) {
-    return query instanceof SqlSelect
-        && ((SqlSelect) query).isKeywordPresent(SqlSelectKeyword.STREAM);
-  }
-
-  public static boolean isOrdered(SqlNode query) {
-    switch (query.getKind()) {
-    case SELECT:
-      return ((SqlSelect) query).getOrderList() != null
-          && ((SqlSelect) query).getOrderList().size() > 0;
-    case WITH:
-      return isOrdered(((SqlWith) query).body);
-    case ORDER_BY:
-      return ((SqlOrderBy) query).orderList.size() > 0;
-    default:
-      return false;
-    }
-  }
-
-  private RelCollation requiredCollation(RelNode r) {
-    if (r instanceof Sort) {
-      return ((Sort) r).collation;
-    }
-    if (r instanceof Project) {
-      return requiredCollation(((Project) r).getInput());
-    }
-    if (r instanceof Delta) {
-      return requiredCollation(((Delta) r).getInput());
-    }
-    throw new AssertionError();
-  }
-
-  /**
-   * Converts a SELECT statement's parse tree into a relational expression.
-   */
-  public RelNode convertSelect(SqlSelect select, boolean top) {
-    final SqlValidatorScope selectScope = validator.getWhereScope(select);
-    final Blackboard bb = createBlackboard(selectScope, null, top);
-    convertSelectImpl(bb, select);
-    return bb.root;
-  }
-
-  /**
-   * Factory method for creating translation workspace.
-   */
-  protected Blackboard createBlackboard(SqlValidatorScope scope,
-                                        Map<String, RexNode> nameToNodeMap, boolean top) {
-    return new Blackboard(scope, nameToNodeMap, top);
-  }
-
-  /**
-   * Implementation of {@link #convertSelect(SqlSelect, boolean)};
-   * derived class may override.
-   */
-  protected void convertSelectImpl(
-      final Blackboard bb,
-      SqlSelect select) {
-    convertFrom(
-        bb,
-        select.getFrom());
-    convertWhere(
-        bb,
-        select.getWhere());
-
-    final List<SqlNode> orderExprList = new ArrayList<>();
-    final List<RelFieldCollation> collationList = new ArrayList<>();
-    gatherOrderExprs(
-        bb,
-        select,
-        select.getOrderList(),
-        orderExprList,
-        collationList);
-    final RelCollation collation =
-        cluster.traitSet().canonize(RelCollations.of(collationList));
-
-    if (validator.isAggregate(select)) {
-      convertAgg(
-          bb,
-          select,
-          orderExprList);
-    } else {
-      convertSelectList(
-          bb,
-          select,
-          orderExprList);
-    }
-
-    if (select.isDistinct()) {
-      distinctify(bb, true);
-    }
-    convertOrder(
-        select, bb, collation, orderExprList, select.getOffset(),
-        select.getFetch());
-    bb.setRoot(bb.root, true);
-  }
-
-  /**
-   * Having translated 'SELECT ... FROM ... [GROUP BY ...] [HAVING ...]', adds
-   * a relational expression to make the results unique.
-   *
-   * <p>If the SELECT clause contains duplicate expressions, adds
-   * {@link org.apache.calcite.rel.logical.LogicalProject}s so that we are
-   * grouping on the minimal set of keys. The performance gain isn't huge, but
-   * it is difficult to detect these duplicate expressions later.
-   *
-   * @param bb               Blackboard
-   * @param checkForDupExprs Check for duplicate expressions
-   */
-  private void distinctify(
-      Blackboard bb,
-      boolean checkForDupExprs) {
-    // Look for duplicate expressions in the project.
-    // Say we have 'select x, y, x, z'.
-    // Then dups will be {[2, 0]}
-    // and oldToNew will be {[0, 0], [1, 1], [2, 0], [3, 2]}
-    RelNode rel = bb.root;
-    if (checkForDupExprs && (rel instanceof LogicalProject)) {
-      LogicalProject project = (LogicalProject) rel;
-      final List<RexNode> projectExprs = project.getProjects();
-      final List<Integer> origins = new ArrayList<>();
-      int dupCount = 0;
-      for (int i = 0; i < projectExprs.size(); i++) {
-        int x = findExpr(projectExprs.get(i), projectExprs, i);
-        if (x >= 0) {
-          origins.add(x);
-          ++dupCount;
-        } else {
-          origins.add(i);
-        }
-      }
-      if (dupCount == 0) {
-        distinctify(bb, false);
-        return;
-      }
-
-      final Map<Integer, Integer> squished = Maps.newHashMap();
-      final List<RelDataTypeField> fields = rel.getRowType().getFieldList();
-      final List<Pair<RexNode, String>> newProjects = Lists.newArrayList();
-      for (int i = 0; i < fields.size(); i++) {
-        if (origins.get(i) == i) {
-          squished.put(i, newProjects.size());
-          newProjects.add(RexInputRef.of2(i, fields));
-        }
-      }
-      rel =
-          LogicalProject.create(rel, Pair.left(newProjects),
-              Pair.right(newProjects));
-      bb.root = rel;
-      distinctify(bb, false);
-      rel = bb.root;
-
-      // Create the expressions to reverse the mapping.
-      // Project($0, $1, $0, $2).
-      final List<Pair<RexNode, String>> undoProjects = Lists.newArrayList();
-      for (int i = 0; i < fields.size(); i++) {
-        final int origin = origins.get(i);
-        RelDataTypeField field = fields.get(i);
-        undoProjects.add(
-            Pair.of(
-                (RexNode) new RexInputRef(
-                    squished.get(origin), field.getType()),
-                field.getName()));
-      }
-
-      rel =
-          LogicalProject.create(rel, Pair.left(undoProjects),
-              Pair.right(undoProjects));
-      bb.setRoot(
-          rel,
-          false);
-
-      return;
-    }
-
-    // Usual case: all of the expressions in the SELECT clause are
-    // different.
-    final ImmutableBitSet groupSet =
-        ImmutableBitSet.range(rel.getRowType().getFieldCount());
-    rel =
-        createAggregate(bb, false, groupSet, ImmutableList.of(groupSet),
-            ImmutableList.<AggregateCall>of());
-
-    bb.setRoot(
-        rel,
-        false);
-  }
-
-  private int findExpr(RexNode seek, List<RexNode> exprs, int count) {
-    for (int i = 0; i < count; i++) {
-      RexNode expr = exprs.get(i);
-      if (expr.toString().equals(seek.toString())) {
-        return i;
-      }
-    }
-    return -1;
-  }
-
-  /**
-   * Converts a query's ORDER BY clause, if any.
-   *
-   * @param select        Query
-   * @param bb            Blackboard
-   * @param collation     Collation list
-   * @param orderExprList Method populates this list with orderBy expressions
-   *                      not present in selectList
-   * @param offset        Expression for number of rows to discard before
-   *                      returning first row
-   * @param fetch         Expression for number of rows to fetch
-   */
-  protected void convertOrder(
-      SqlSelect select,
-      Blackboard bb,
-      RelCollation collation,
-      List<SqlNode> orderExprList,
-      SqlNode offset,
-      SqlNode fetch) {
-    if (select.getOrderList() == null
-        || select.getOrderList().getList().isEmpty()) {
-      assert collation.getFieldCollations().isEmpty();
-      if ((offset == null
-            || ((SqlLiteral) offset).bigDecimalValue().equals(BigDecimal.ZERO))
-          && fetch == null) {
-        return;
-      }
-    }
-
-    // Create a sorter using the previously constructed collations.
-    bb.setRoot(
-        LogicalSort.create(bb.root, collation,
-            offset == null ? null : convertExpression(offset),
-            fetch == null ? null : convertExpression(fetch)),
-        false);
-
-    // If extra expressions were added to the project list for sorting,
-    // add another project to remove them. But make the collation empty, because
-    // we can't represent the real collation.
-    //
-    // If it is the top node, use the real collation, but don't trim fields.
-    if (orderExprList.size() > 0 && !bb.top) {
-      final List<RexNode> exprs = new ArrayList<>();
-      final RelDataType rowType = bb.root.getRowType();
-      final int fieldCount =
-          rowType.getFieldCount() - orderExprList.size();
-      for (int i = 0; i < fieldCount; i++) {
-        exprs.add(rexBuilder.makeInputRef(bb.root, i));
-      }
-      bb.setRoot(
-          LogicalProject.create(bb.root, exprs,
-              rowType.getFieldNames().subList(0, fieldCount)),
-          false);
-    }
-  }
-
-  /**
-   * Returns whether a given node contains a {@link SqlInOperator}.
-   *
-   * @param node a RexNode tree
-   */
-  private static boolean containsInOperator(
-      SqlNode node) {
-    try {
-      SqlVisitor<Void> visitor =
-          new SqlBasicVisitor<Void>() {
-            public Void visit(SqlCall call) {
-              if (call.getOperator() instanceof SqlInOperator) {
-                throw new Util.FoundOne(call);
-              }
-              return super.visit(call);
-            }
-          };
-      node.accept(visitor);
-      return false;
-    } catch (Util.FoundOne e) {
-      Util.swallow(e, null);
-      return true;
-    }
-  }
-
-  /**
-   * Push down all the NOT logical operators into any IN/NOT IN operators.
-   *
-   * @param scope Scope where {@code sqlNode} occurs
-   * @param sqlNode the root node from which to look for NOT operators
-   * @return the transformed SqlNode representation with NOT pushed down.
-   */
-  private static SqlNode pushDownNotForIn(SqlValidatorScope scope,
-                                          SqlNode sqlNode) {
-    if ((sqlNode instanceof SqlCall) && containsInOperator(sqlNode)) {
-      SqlCall sqlCall = (SqlCall) sqlNode;
-      if ((sqlCall.getOperator() == SqlStdOperatorTable.AND)
-          || (sqlCall.getOperator() == SqlStdOperatorTable.OR)) {
-        SqlNode[] sqlOperands = ((SqlBasicCall) sqlCall).operands;
-        for (int i = 0; i < sqlOperands.length; i++) {
-          sqlOperands[i] = pushDownNotForIn(scope, sqlOperands[i]);
-        }
-        return reg(scope, sqlNode);
-      } else if (sqlCall.getOperator() == SqlStdOperatorTable.NOT) {
-        SqlNode childNode = sqlCall.operand(0);
-        assert childNode instanceof SqlCall;
-        SqlBasicCall childSqlCall = (SqlBasicCall) childNode;
-        if (childSqlCall.getOperator() == SqlStdOperatorTable.AND) {
-          SqlNode[] andOperands = childSqlCall.getOperands();
-          SqlNode[] orOperands = new SqlNode[andOperands.length];
-          for (int i = 0; i < orOperands.length; i++) {
-            orOperands[i] = reg(scope,
-                SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO,
-                    andOperands[i]));
-          }
-          for (int i = 0; i < orOperands.length; i++) {
-            orOperands[i] = pushDownNotForIn(scope, orOperands[i]);
-          }
-          return reg(scope,
-              SqlStdOperatorTable.OR.createCall(SqlParserPos.ZERO,
-                  orOperands[0], orOperands[1]));
-        } else if (childSqlCall.getOperator() == SqlStdOperatorTable.OR) {
-          SqlNode[] orOperands = childSqlCall.getOperands();
-          SqlNode[] andOperands = new SqlNode[orOperands.length];
-          for (int i = 0; i < andOperands.length; i++) {
-            andOperands[i] = reg(scope,
-                SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO,
-                    orOperands[i]));
-          }
-          for (int i = 0; i < andOperands.length; i++) {
-            andOperands[i] = pushDownNotForIn(scope, andOperands[i]);
-          }
-          return reg(scope,
-              SqlStdOperatorTable.AND.createCall(SqlParserPos.ZERO,
-                  andOperands[0], andOperands[1]));
-        } else if (childSqlCall.getOperator() == SqlStdOperatorTable.NOT) {
-          SqlNode[] notOperands = childSqlCall.getOperands();
-          assert notOperands.length == 1;
-          return pushDownNotForIn(scope, notOperands[0]);
-        } else if (childSqlCall.getOperator() instanceof SqlInOperator) {
-          SqlNode[] inOperands = childSqlCall.getOperands();
-          SqlInOperator inOp =
-              (SqlInOperator) childSqlCall.getOperator();
-          if (inOp.isNotIn()) {
-            return reg(scope,
-                SqlStdOperatorTable.IN.createCall(SqlParserPos.ZERO,
-                    inOperands[0], inOperands[1]));
-          } else {
-            return reg(scope,
-                SqlStdOperatorTable.NOT_IN.createCall(SqlParserPos.ZERO,
-                    inOperands[0], inOperands[1]));
-          }
-        } else {
-          // childSqlCall is "leaf" node in a logical expression tree
-          // (only considering AND, OR, NOT)
-          return sqlNode;
-        }
-      } else {
-        // sqlNode is "leaf" node in a logical expression tree
-        // (only considering AND, OR, NOT)
-        return sqlNode;
-      }
-    } else {
-      // tree rooted at sqlNode does not contain inOperator
-      return sqlNode;
-    }
-  }
-
-  /** Registers with the validator a {@link SqlNode} that has been created
-   * during the Sql-to-Rel process. */
-  private static SqlNode reg(SqlValidatorScope scope, SqlNode e) {
-    scope.getValidator().deriveType(scope, e);
-    return e;
-  }
-
-  /**
-   * Converts a WHERE clause.
-   *
-   * @param bb    Blackboard
-   * @param where WHERE clause, may be null
-   */
-  private void convertWhere(
-      final Blackboard bb,
-      final SqlNode where) {
-    if (where == null) {
-      return;
-    }
-    SqlNode newWhere = pushDownNotForIn(bb.scope, where);
-    replaceSubQueries(bb, newWhere, RelOptUtil.Logic.UNKNOWN_AS_FALSE);
-    final RexNode convertedWhere = bb.convertExpression(newWhere);
-
-    // only allocate filter if the condition is not TRUE
-    if (convertedWhere.isAlwaysTrue()) {
-      return;
-    }
-
-    final RelFactories.FilterFactory factory =
-        RelFactories.DEFAULT_FILTER_FACTORY;
-    final RelNode filter = factory.createFilter(bb.root, convertedWhere);
-    final RelNode r;
-    final CorrelationUse p = getCorrelationUse(bb, filter);
-    if (p != null) {
-      assert p.r instanceof Filter;
-      Filter f = (Filter) p.r;
-      r = LogicalFilter.create(f.getInput(), f.getCondition(),
-          ImmutableSet.of(p.id));
-    } else {
-      r = filter;
-    }
-
-    bb.setRoot(r, false);
-  }
-
-  private void replaceSubQueries(
-      final Blackboard bb,
-      final SqlNode expr,
-      RelOptUtil.Logic logic) {
-    findSubQueries(bb, expr, logic, false);
-    for (SubQuery node : bb.subQueryList) {
-      substituteSubQuery(bb, node);
-    }
-  }
-
-  private void substituteSubQuery(Blackboard bb, SubQuery subQuery) {
-    final RexNode expr = subQuery.expr;
-    if (expr != null) {
-      // Already done.
-      return;
-    }
-
-    final SqlBasicCall call;
-    final RelNode rel;
-    final SqlNode query;
-    final RelOptUtil.Exists converted;
-    switch (subQuery.node.getKind()) {
-    case CURSOR:
-      convertCursor(bb, subQuery);
-      return;
-
-    case MULTISET_QUERY_CONSTRUCTOR:
-    case MULTISET_VALUE_CONSTRUCTOR:
-    case ARRAY_QUERY_CONSTRUCTOR:
-      rel = convertMultisets(ImmutableList.of(subQuery.node), bb);
-      subQuery.expr = bb.register(rel, JoinRelType.INNER);
-      return;
-
-    case IN:
-      call = (SqlBasicCall) subQuery.node;
-      query = call.operand(1);
-      if (!config.isExpand() && !(query instanceof SqlNodeList)) {
-        return;
-      }
-      final SqlNode leftKeyNode = call.operand(0);
-
-      final List<RexNode> leftKeys;
-      switch (leftKeyNode.getKind()) {
-      case ROW:
-        leftKeys = Lists.newArrayList();
-        for (SqlNode sqlExpr : ((SqlBasicCall) leftKeyNode).getOperandList()) {
-          leftKeys.add(bb.convertExpression(sqlExpr));
-        }
-        break;
-      default:
-        leftKeys = ImmutableList.of(bb.convertExpression(leftKeyNode));
-      }
-
-      final boolean notIn = ((SqlInOperator) call.getOperator()).isNotIn();
-      if (query instanceof SqlNodeList) {
-        SqlNodeList valueList = (SqlNodeList) query;
-        if (!containsNullLiteral(valueList)
-            && valueList.size() < config.getInSubQueryThreshold()) {
-          // We're under the threshold, so convert to OR.
-          subQuery.expr =
-              convertInToOr(
-                  bb,
-                  leftKeys,
-                  valueList,
-                  notIn);
-          return;
-        }
-
-        // Otherwise, let convertExists translate
-        // values list into an inline table for the
-        // reference to Q below.
-      }
-
-      // Project out the search columns from the left side
-
-      // Q1:
-      // "select from emp where emp.deptno in (select col1 from T)"
-      //
-      // is converted to
-      //
-      // "select from
-      //   emp inner join (select distinct col1 from T)) q
-      //   on emp.deptno = q.col1
-      //
-      // Q2:
-      // "select from emp where emp.deptno not in (Q)"
-      //
-      // is converted to
-      //
-      // "select from
-      //   emp left outer join (select distinct col1, TRUE from T) q
-      //   on emp.deptno = q.col1
-      //   where emp.deptno <> null
-      //         and q.indicator <> TRUE"
-      //
-      final RelDataType targetRowType =
-          SqlTypeUtil.promoteToRowType(typeFactory,
-              validator.getValidatedNodeType(leftKeyNode), null);
-      converted =
-          convertExists(query, RelOptUtil.SubQueryType.IN, subQuery.logic,
-              notIn, targetRowType);
-      if (converted.indicator) {
-        // Generate
-        //    emp CROSS JOIN (SELECT COUNT(*) AS c,
-        //                       COUNT(deptno) AS ck FROM dept)
-        final RelDataType longType =
-            typeFactory.createSqlType(SqlTypeName.BIGINT);
-        final RelNode seek = converted.r.getInput(0); // fragile
-        final int keyCount = leftKeys.size();
-        final List<Integer> args = ImmutableIntList.range(0, keyCount);
-        LogicalAggregate aggregate =
-            LogicalAggregate.create(seek, false, ImmutableBitSet.of(), null,
-                ImmutableList.of(
-                    AggregateCall.create(SqlStdOperatorTable.COUNT, false,
-                        ImmutableList.<Integer>of(), -1, longType, null),
-                    AggregateCall.create(SqlStdOperatorTable.COUNT, false,
-                        args, -1, longType, null)));
-        LogicalJoin join =
-            LogicalJoin.create(bb.root, aggregate, rexBuilder.makeLiteral(true),
-                ImmutableSet.<CorrelationId>of(), JoinRelType.INNER);
-        bb.setRoot(join, false);
-      }
-      final RexNode rex =
-          bb.register(converted.r,
-              converted.outerJoin ? JoinRelType.LEFT : JoinRelType.INNER,
-              leftKeys);
-
-      RelOptUtil.Logic logic = subQuery.logic;
-      switch (logic) {
-      case TRUE_FALSE_UNKNOWN:
-      case UNKNOWN_AS_TRUE:
-        if (!converted.indicator) {
-          logic = RelOptUtil.Logic.TRUE_FALSE;
-        }
-      }
-      subQuery.expr = translateIn(logic, bb.root, rex);
-      if (notIn) {
-        subQuery.expr =
-            rexBuilder.makeCall(SqlStdOperatorTable.NOT, subQuery.expr);
-      }
-      return;
-
-    case EXISTS:
-      // "select from emp where exists (select a from T)"
-      //
-      // is converted to the following if the sub-query is correlated:
-      //
-      // "select from emp left outer join (select AGG_TRUE() as indicator
-      // from T group by corr_var) q where q.indicator is true"
-      //
-      // If there is no correlation, the expression is replaced with a
-      // boolean indicating whether the sub-query returned 0 or >= 1 row.
-      call = (SqlBasicCall) subQuery.node;
-      query = call.operand(0);
-      if (!config.isExpand()) {
-        return;
-      }
-      converted = convertExists(query, RelOptUtil.SubQueryType.EXISTS,
-          subQuery.logic, true, null);
-      assert !converted.indicator;
-      if (convertNonCorrelatedSubQuery(subQuery, bb, converted.r, true)) {
-        return;
-      }
-      subQuery.expr = bb.register(converted.r, JoinRelType.LEFT);
-      return;
-
-    case SCALAR_QUERY:
-      // Convert the sub-query.  If it's non-correlated, convert it
-      // to a constant expression.
-      if (!config.isExpand()) {
-        return;
-      }
-      call = (SqlBasicCall) subQuery.node;
-      query = call.operand(0);
-      converted = convertExists(query, RelOptUtil.SubQueryType.SCALAR,
-          subQuery.logic, true, null);
-      assert !converted.indicator;
-      if (convertNonCorrelatedSubQuery(subQuery, bb, converted.r, false)) {
-        return;
-      }
-      rel = convertToSingleValueSubq(query, converted.r);
-      subQuery.expr = bb.register(rel, JoinRelType.LEFT);
-      return;
-
-    case SELECT:
-      // This is used when converting multiset queries:
-      //
-      // select * from unnest(select multiset[deptno] from emps);
-      //
-      converted = convertExists(subQuery.node, RelOptUtil.SubQueryType.SCALAR,
-          subQuery.logic, true, null);
-      assert !converted.indicator;
-      subQuery.expr = bb.register(converted.r, JoinRelType.LEFT);
-      return;
-
-    default:
-      throw new AssertionError("unexpected kind of sub-query: "
-          + subQuery.node);
-    }
-  }
-
-  private RexNode translateIn(RelOptUtil.Logic logic, RelNode root,
-                              final RexNode rex) {
-    switch (logic) {
-    case TRUE:
-      return rexBuilder.makeLiteral(true);
-
-    case TRUE_FALSE:
-    case UNKNOWN_AS_FALSE:
-      assert rex instanceof RexRangeRef;
-      final int fieldCount = rex.getType().getFieldCount();
-      RexNode rexNode = rexBuilder.makeFieldAccess(rex, fieldCount - 1);
-      rexNode = rexBuilder.makeCall(SqlStdOperatorTable.IS_TRUE, rexNode);
-
-      // Then append the IS NOT NULL(leftKeysForIn).
-      //
-      // RexRangeRef contains the following fields:
-      //   leftKeysForIn,
-      //   rightKeysForIn (the original sub-query select list),
-      //   nullIndicator
-      //
-      // The first two lists contain the same number of fields.
-      final int k = (fieldCount - 1) / 2;
-      for (int i = 0; i < k; i++) {
-        rexNode =
-            rexBuilder.makeCall(
-                SqlStdOperatorTable.AND,
-                rexNode,
-                rexBuilder.makeCall(
-                    SqlStdOperatorTable.IS_NOT_NULL,
-                    rexBuilder.makeFieldAccess(rex, i)));
-      }
-      return rexNode;
-
-    case TRUE_FALSE_UNKNOWN:
-    case UNKNOWN_AS_TRUE:
-      // select e.deptno,
-      //   case
-      //   when ct.c = 0 then false
-      //   when dt.i is not null then true
-      //   when e.deptno is null then null
-      //   when ct.ck < ct.c then null
-      //   else false
-      //   end
-      // from e
-      // cross join (select count(*) as c, count(deptno) as ck from v) as ct
-      // left join (select distinct deptno, true as i from v) as dt
-      //   on e.deptno = dt.deptno
-      final Join join = (Join) root;
-      final Project left = (Project) join.getLeft();
-      final RelNode leftLeft = ((Join) left.getInput()).getLeft();
-      final int leftLeftCount = leftLeft.getRowType().getFieldCount();
-      final RelDataType longType =
-          typeFactory.createSqlType(SqlTypeName.BIGINT);
-      final RexNode cRef = rexBuilder.makeInputRef(root, leftLeftCount);
-      final RexNode ckRef = rexBuilder.makeInputRef(root, leftLeftCount + 1);
-      final RexNode iRef =
-          rexBuilder.makeInputRef(root, root.getRowType().getFieldCount() - 1);
-
-      final RexLiteral zero =
-          rexBuilder.makeExactLiteral(BigDecimal.ZERO, longType);
-      final RexLiteral trueLiteral = rexBuilder.makeLiteral(true);
-      final RexLiteral falseLiteral = rexBuilder.makeLiteral(false);
-      final RexNode unknownLiteral =
-          rexBuilder.makeNullLiteral(trueLiteral.getType());
-
-      final ImmutableList.Builder<RexNode> args = ImmutableList.builder();
-      args.add(rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, cRef, zero),
-          falseLiteral,
-          rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, iRef),
-          trueLiteral);
-      final JoinInfo joinInfo = join.analyzeCondition();
-      for (int leftKey : joinInfo.leftKeys) {
-        final RexNode kRef = rexBuilder.makeInputRef(root, leftKey);
-        args.add(rexBuilder.makeCall(SqlStdOperatorTable.IS_NULL, kRef),
-            unknownLiteral);
-      }
-      args.add(rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, ckRef, cRef),
-          unknownLiteral,
-          falseLiteral);
-
-      return rexBuilder.makeCall(SqlStdOperatorTable.CASE, args.build());
-
-    default:
-      throw new AssertionError(logic);
-    }
-  }
-
-  private static boolean containsNullLiteral(SqlNodeList valueList) {
-    for (SqlNode node : valueList.getList()) {
-      if (node instanceof SqlLiteral) {
-        SqlLiteral lit = (SqlLiteral) node;
-        if (lit.getValue() == null) {
-          return true;
-        }
-      }
-    }
-    return false;
-  }
-
-  /**
-   * Determines if a sub-query is non-correlated and if so, converts it to a
-   * constant.
-   *
-   * @param subQuery  the call that references the sub-query
-   * @param bb        blackboard used to convert the sub-query
-   * @param converted RelNode tree corresponding to the sub-query
-   * @param isExists  true if the sub-query is part of an EXISTS expression
-   * @return Whether the sub-query can be converted to a constant
-   */
-  private boolean convertNonCorrelatedSubQuery(
-      SubQuery subQuery,
-      Blackboard bb,
-      RelNode converted,
-      boolean isExists) {
-    SqlCall call = (SqlBasicCall) subQuery.node;
-    if (subQueryConverter.canConvertSubQuery()
-        && isSubQueryNonCorrelated(converted, bb)) {
-      // First check if the sub-query has already been converted
-      // because it's a nested sub-query.  If so, don't re-evaluate
-      // it again.
-      RexNode constExpr = mapConvertedNonCorrSubqs.get(call);
-      if (constExpr == null) {
-        constExpr =
-            subQueryConverter.convertSubQuery(
-                call,
-                this,
-                isExists,
-                config.isExplain());
-      }
-      if (constExpr != null) {
-        subQuery.expr = constExpr;
-        mapConvertedNonCorrSubqs.put(call, constExpr);
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /**
-   * Converts the RelNode tree for a select statement to a select that
-   * produces a single value.
-   *
-   * @param query the query
-   * @param plan   the original RelNode tree corresponding to the statement
-   * @return the converted RelNode tree
-   */
-  public RelNode convertToSingleValueSubq(
-      SqlNode query,
-      RelNode plan) {
-    // Check whether query is guaranteed to produce a single value.
-    if (query instanceof SqlSelect) {
-      SqlSelect select = (SqlSelect) query;
-      SqlNodeList selectList = select.getSelectList();
-      SqlNodeList groupList = select.getGroup();
-
-      if ((selectList.size() == 1)
-          && ((groupList == null) || (groupList.size() == 0))) {
-        SqlNode selectExpr = selectList.get(0);
-        if (selectExpr instanceof SqlCall) {
-          SqlCall selectExprCall = (SqlCall) selectExpr;
-          if (Util.isSingleValue(selectExprCall)) {
-            return plan;
-          }
-        }
-
-        // If there is a limit with 0 or 1,
-        // it is ensured to produce a single value
-        if (select.getFetch() != null
-            && select.getFetch() instanceof SqlNumericLiteral) {
-          SqlNumericLiteral limitNum = (SqlNumericLiteral) select.getFetch();
-          if (((BigDecimal) limitNum.getValue()).intValue() < 2) {
-            return plan;
-          }
-        }
-      }
-    } else if (query instanceof SqlCall) {
-      // If the query is (values ...),
-      // it is necessary to look into the operands to determine
-      // whether SingleValueAgg is necessary
-      SqlCall exprCall = (SqlCall) query;
-      if (exprCall.getOperator()
-          instanceof SqlValuesOperator
-              && Util.isSingleValue(exprCall)) {
-        return plan;
-      }
-    }
-
-    // If not, project SingleValueAgg
-    return RelOptUtil.createSingleValueAggRel(
-        cluster,
-        plan);
-  }
-
-  /**
-   * Converts "x IN (1, 2, ...)" to "x=1 OR x=2 OR ...".
-   *
-   * @param leftKeys   LHS
-   * @param valuesList RHS
-   * @param isNotIn    is this a NOT IN operator
-   * @return converted expression
-   */
-  private RexNode convertInToOr(
-      final Blackboard bb,
-      final List<RexNode> leftKeys,
-      SqlNodeList valuesList,
-      boolean isNotIn) {
-    final List<RexNode> comparisons = new ArrayList<>();
-    for (SqlNode rightVals : valuesList) {
-      RexNode rexComparison;
-      if (leftKeys.size() == 1) {
-        rexComparison =
-            rexBuilder.makeCall(SqlStdOperatorTable.EQUALS,
-                leftKeys.get(0),
-                ensureSqlType(leftKeys.get(0).getType(),
-                    bb.convertExpression(rightVals)));
-      } else {
-        assert rightVals instanceof SqlCall;
-        final SqlBasicCall call = (SqlBasicCall) rightVals;
-        assert (call.getOperator() instanceof SqlRowOperator)
-            && call.operandCount() == leftKeys.size();
-        rexComparison =
-            RexUtil.composeConjunction(
-                rexBuilder,
-                Iterables.transform(
-                    Pair.zip(leftKeys, call.getOperandList()),
-                    new Function<Pair<RexNode, SqlNode>, RexNode>() {
-                      public RexNode apply(Pair<RexNode, SqlNode> pair) {
-                        return rexBuilder.makeCall(SqlStdOperatorTable.EQUALS,
-                            pair.left,
-                            ensureSqlType(pair.left.getType(),
-                                bb.convertExpression(pair.right)));
-                      }
-                    }),
-                false);
-      }
-      comparisons.add(rexComparison);
-    }
-
-    RexNode result =
-        RexUtil.composeDisjunction(rexBuilder, comparisons, true);
-    assert result != null;
-
-    if (isNotIn) {
-      result =
-          rexBuilder.makeCall(
-              SqlStdOperatorTable.NOT,
-              result);
-    }
-
-    return result;
-  }
-
-  /** Ensures that an expression has a given {@link SqlTypeName}, applying a
-   * cast if necessary. If the expression already has the right type family,
-   * returns the expression unchanged. */
-  private RexNode ensureSqlType(RelDataType type, RexNode node) {
-    if (type.getSqlTypeName() == node.getType().getSqlTypeName()
-        || (type.getSqlTypeName() == SqlTypeName.VARCHAR
-            && node.getType().getSqlTypeName() == SqlTypeName.CHAR)) {
-      return node;
-    }
-    return rexBuilder.ensureType(type, node, true);
-  }
-
-  /**
-   * Gets the list size threshold under which {@link #convertInToOr} is used.
-   * Lists of this size or greater will instead be converted to use a join
-   * against an inline table
-   * ({@link org.apache.calcite.rel.logical.LogicalValues}) rather than a
-   * predicate. A threshold of 0 forces usage of an inline table in all cases; a
-   * threshold of Integer.MAX_VALUE forces usage of OR in all cases
-   *
-   * @return threshold, default {@link #DEFAULT_IN_SUB_QUERY_THRESHOLD}
-   */
-  @Deprecated // to be removed before 2.0
-  protected int getInSubqueryThreshold() {
-    return config.getInSubQueryThreshold();
-  }
-
-  /**
-   * Converts an EXISTS or IN predicate into a join. For EXISTS, the sub-query
-   * produces an indicator variable, and the result is a relational expression
-   * which outer joins that indicator to the original query. After performing
-   * the outer join, the condition will be TRUE if the EXISTS condition holds,
-   * NULL otherwise.
-   *
-   * @param seek           A query, for example 'select * from emp' or
-   *                       'values (1,2,3)' or '('Foo', 34)'.
-   * @param subQueryType   Whether sub-query is IN, EXISTS or scalar
-   * @param logic Whether the answer needs to be in full 3-valued logic (TRUE,
-   *     FALSE, UNKNOWN) will be required, or whether we can accept an
-   *     approximation (say representing UNKNOWN as FALSE)
-   * @param notIn Whether the operation is NOT IN
-   * @return join expression
-   */
-  private RelOptUtil.Exists convertExists(
-      SqlNode seek,
-      RelOptUtil.SubQueryType subQueryType,
-      RelOptUtil.Logic logic,
-      boolean notIn,
-      RelDataType targetDataType) {
-    final SqlValidatorScope seekScope =
-        (seek instanceof SqlSelect)
-            ? validator.getSelectScope((SqlSelect) seek)
-            : null;
-    final Blackboard seekBb = createBlackboard(seekScope, null, false);
-    RelNode seekRel = convertQueryOrInList(seekBb, seek, targetDataType);
-
-    return RelOptUtil.createExistsPlan(seekRel, subQueryType, logic, notIn);
-  }
-
-  private RelNode convertQueryOrInList(
-      Blackboard bb,
-      SqlNode seek,
-      RelDataType targetRowType) {
-    // NOTE: Once we start accepting single-row queries as row constructors,
-    // there will be an ambiguity here for a case like X IN ((SELECT Y FROM
-    // Z)).  The SQL standard resolves the ambiguity by saying that a lone
-    // select should be interpreted as a table expression, not a row
-    // expression.  The semantic difference is that a table expression can
-    // return multiple rows.
-    if (seek instanceof SqlNodeList) {
-      return convertRowValues(
-          bb,
-          seek,
-          ((SqlNodeList) seek).getList(),
-          false,
-          targetRowType);
-    } else {
-      return convertQueryRecursive(seek, false, null).project();
-    }
-  }
-
-  private RelNode convertRowValues(
-      Blackboard bb,
-      SqlNode rowList,
-      Collection<SqlNode> rows,
-      boolean allowLiteralsOnly,
-      RelDataType targetRowType) {
-    // NOTE jvs 30-Apr-2006: We combine all rows consisting entirely of
-    // literals into a single LogicalValues; this gives the optimizer a smaller
-    // input tree.  For everything else (computed expressions, row
-    // sub-queries), we union each row in as a projection on top of a
-    // LogicalOneRow.
-
-    final ImmutableList.Builder<ImmutableList<RexLiteral>> tupleList =
-        ImmutableList.builder();
-    final RelDataType rowType;
-    if (targetRowType != null) {
-      rowType = targetRowType;
-    } else {
-      rowType =
-          SqlTypeUtil.promoteToRowType(
-              typeFactory,
-              validator.getValidatedNodeType(rowList),
-              null);
-    }
-
-    final List<RelNode> unionInputs = new ArrayList<>();
-    for (SqlNode node : rows) {
-      SqlBasicCall call;
-      if (isRowConstructor(node)) {
-        call = (SqlBasicCall) node;
-        ImmutableList.Builder<RexLiteral> tuple = ImmutableList.builder();
-        for (Ord<SqlNode> operand : Ord.zip(call.operands)) {
-          RexLiteral rexLiteral =
-              convertLiteralInValuesList(
-                  operand.e,
-                  bb,
-                  rowType,
-                  operand.i);
-          if ((rexLiteral == null) && allowLiteralsOnly) {
-            return null;
-          }
-          if ((rexLiteral == null) || !config.isCreateValuesRel()) {
-            // fallback to convertRowConstructor
-            tuple = null;
-            break;
-          }
-          tuple.add(rexLiteral);
-        }
-        if (tuple != null) {
-          tupleList.add(tuple.build());
-          continue;
-        }
-      } else {
-        RexLiteral rexLiteral =
-            convertLiteralInValuesList(
-                node,
-                bb,
-                rowType,
-                0);
-        if ((rexLiteral != null) && config.isCreateValuesRel()) {
-          tupleList.add(ImmutableList.of(rexLiteral));
-          continue;
-        } else {
-          if ((rexLiteral == null) && allowLiteralsOnly) {
-            return null;
-          }
-        }
-
-        // convert "1" to "row(1)"
-        call =
-            (SqlBasicCall) SqlStdOperatorTable.ROW.createCall(
-                SqlParserPos.ZERO,
-                node);
-      }
-      unionInputs.add(convertRowConstructor(bb, call));
-    }
-    LogicalValues values =
-        LogicalValues.create(cluster, rowType, tupleList.build());
-    RelNode resultRel;
-    if (unionInputs.isEmpty()) {
-      resultRel = values;
-    } else {
-      if (!values.getTuples().isEmpty()) {
-        unionInputs.add(values);
-      }
-      resultRel = LogicalUnion.create(unionInputs, true);
-    }
-    leaves.add(resultRel);
-    return resultRel;
-  }
-
-  private RexLiteral convertLiteralInValuesList(
-      SqlNode sqlNode,
-      Blackboard bb,
-      RelDataType rowType,
-      int iField) {
-    if (!(sqlNode instanceof SqlLiteral)) {
-      return null;
-    }
-    RelDataTypeField field = rowType.getFieldList().get(iField);
-    RelDataType type = field.getType();
-    if (type.isStruct()) {
-      // null literals for weird stuff like UDT's need
-      // special handling during type flattening, so
-      // don't use LogicalValues for those
-      return null;
-    }
-
-    RexNode literalExpr =
-        exprConverter.convertLiteral(
-            bb,
-            (SqlLiteral) sqlNode);
-
-    if (!(literalExpr instanceof RexLiteral)) {
-      assert literalExpr.isA(SqlKind.CAST);
-      RexNode child = ((RexCall) literalExpr).getOperands().get(0);
-      assert RexLiteral.isNullLiteral(child);
-
-      // NOTE jvs 22-Nov-2006:  we preserve type info
-      // in LogicalValues digest, so it's OK to lose it here
-      return (RexLiteral) child;
-    }
-
-    RexLiteral literal = (RexLiteral) literalExpr;
-
-    Comparable value = literal.getValue();
-
-    if (SqlTypeUtil.isExactNumeric(type) && SqlTypeUtil.hasScale(type)) {
-      BigDecimal roundedValue =
-          NumberUtil.rescaleBigDecimal(
-              (BigDecimal) value,
-              type.getScale());
-      return rexBuilder.makeExactLiteral(
-          roundedValue,
-          type);
-    }
-
-    if ((value instanceof NlsString)
-        && (type.getSqlTypeName() == SqlTypeName.CHAR)) {
-      // pad fixed character type
-      NlsString unpadded = (NlsString) value;
-      return rexBuilder.makeCharLiteral(
-          new NlsString(
-              Spaces.padRight(unpadded.getValue(), type.getPrecision()),
-              unpadded.getCharsetName(),
-              unpadded.getCollation()));
-    }
-    return literal;
-  }
-
-  private boolean isRowConstructor(SqlNode node) {
-    if (!(node.getKind() == SqlKind.ROW)) {
-      return false;
-    }
-    SqlCall call = (SqlCall) node;
-    return call.getOperator().getName().equalsIgnoreCase("row");
-  }
-
-  /**
-   * Builds a list of all <code>IN</code> or <code>EXISTS</code> operators
-   * inside SQL parse tree. Does not traverse inside queries.
-   *
-   * @param bb                           blackboard
-   * @param node                         the SQL parse tree
-   * @param logic Whether the answer needs to be in full 3-valued logic (TRUE,
-   *              FALSE, UNKNOWN) will be required, or whether we can accept
-   *              an approximation (say representing UNKNOWN as FALSE)
-   * @param registerOnlyScalarSubQueries if set to true and the parse tree
-   *                                     corresponds to a variation of a select
-   *                                     node, only register it if it's a scalar
-   *                                     sub-query
-   */
-  private void findSubQueries(
-      Blackboard bb,
-      SqlNode node,
-      RelOptUtil.Logic logic,
-      boolean registerOnlyScalarSubQueries) {
-    final SqlKind kind = node.getKind();
-    switch (kind) {
-    case EXISTS:
-    case SELECT:
-    case MULTISET_QUERY_CONSTRUCTOR:
-    case MULTISET_VALUE_CONSTRUCTOR:
-    case ARRAY_QUERY_CONSTRUCTOR:
-    case CURSOR:
-    case SCALAR_QUERY:
-      if (!registerOnlyScalarSubQueries
-          || (kind == SqlKind.SCALAR_QUERY)) {
-        bb.registerSubQuery(node, RelOptUtil.Logic.TRUE_FALSE);
-      }
-      return;
-    case IN:
-      if (((SqlCall) node).getOperator() == SqlStdOperatorTable.NOT_IN) {
-        logic = logic.negate();
-      }
-      break;
-    case NOT:
-      logic = logic.negate();
-      break;
-    }
-    if (node instanceof SqlCall) {
-      for (SqlNode operand : ((SqlCall) node).getOperandList()) {
-        if (operand != null) {
-          // In the case of an IN expression, locate scalar
-          // sub-queries so we can convert them to constants
-          findSubQueries(
-              bb,
-              operand,
-              logic,
-              kind == SqlKind.IN || registerOnlyScalarSubQueries);
-        }
-      }
-    } else if (node instanceof SqlNodeList) {
-      for (SqlNode child : (SqlNodeList) node) {
-        findSubQueries(
-            bb,
-            child,
-            logic,
-            kind == SqlKind.IN || registerOnlyScalarSubQueries);
-      }
-    }
-
-    // Now that we've located any scalar sub-queries inside the IN
-    // expression, register the IN expression itself.  We need to
-    // register the scalar sub-queries first so they can be converted
-    // before the IN expression is converted.
-    if (kind == SqlKind.IN) {
-      switch (logic) {
-      case TRUE_FALSE_UNKNOWN:
-        if (validator.getValidatedNodeType(node).isNullable()) {
-          break;
-        } else if (true) {
-          break;
-        }
-        // fall through
-      case UNKNOWN_AS_FALSE:
-        logic = RelOptUtil.Logic.TRUE;
-      }
-      bb.registerSubQuery(node, logic);
-    }
-  }
-
-  /**
-   * Converts an expression from {@link SqlNode} to {@link RexNode} format.
-   *
-   * @param node Expression to translate
-   * @return Converted expression
-   */
-  public RexNode convertExpression(
-      SqlNode node) {
-    Map<String, RelDataType> nameToTypeMap = Collections.emptyMap();
-    final ParameterScope scope =
-        new ParameterScope((SqlValidatorImpl) validator, nameToTypeMap);
-    final Blackboard bb = createBlackboard(scope, null, false);
-    return bb.convertExpression(node);
-  }
-
-  /**
-   * Converts an expression from {@link SqlNode} to {@link RexNode} format,
-   * mapping identifier references to predefined expressions.
-   *
-   * @param node          Expression to translate
-   * @param nameToNodeMap map from String to {@link RexNode}; when an
-   *                      {@link SqlIdentifier} is encountered, it is used as a
-   *                      key and translated to the corresponding value from
-   *                      this map
-   * @return Converted expression
-   */
-  public RexNode convertExpression(
-      SqlNode node,
-      Map<String, RexNode> nameToNodeMap) {
-    final Map<String, RelDataType> nameToTypeMap = new HashMap<>();
-    for (Map.Entry<String, RexNode> entry : nameToNodeMap.entrySet()) {
-      nameToTypeMap.put(entry.getKey(), entry.getValue().getType());
-    }
-    final ParameterScope scope =
-        new ParameterScope((SqlValidatorImpl) validator, nameToTypeMap);
-    final Blackboard bb = createBlackboard(scope, nameToNodeMap, false);
-    return bb.convertExpression(node);
-  }
-
-  /**
-   * Converts a non-standard expression.
-   *
-   * <p>This method is an extension-point that derived classes can override. If
-   * this method returns a null result, the normal expression translation
-   * process will proceed. The default implementation always returns null.
-   *
-   * @param node Expression
-   * @param bb   Blackboard
-   * @return null to proceed with the usual expression translation process
-   */
-  protected RexNode convertExtendedExpression(
-      SqlNode node,
-      Blackboard bb) {
-    return null;
-  }
-
-  private RexNode convertOver(Blackboard bb, SqlNode node) {
-    SqlCall call = (SqlCall) node;
-    SqlCall aggCall = call.operand(0);
-    SqlNode windowOrRef = call.operand(1);
-    final SqlWindow window =
-        validator.resolveWindow(windowOrRef, bb.scope, true);
-
-    // ROW_NUMBER() expects specific kind of framing.
-    if (aggCall.getKind() == SqlKind.ROW_NUMBER) {
-      window.setLowerBound(SqlWindow.createUnboundedPreceding(SqlParserPos.ZERO));
-      window.setUpperBound(SqlWindow.createCurrentRow(SqlParserPos.ZERO));
-      window.setRows(SqlLiteral.createBoolean(true, SqlParserPos.ZERO));
-    }
-    final SqlNodeList partitionList = window.getPartitionList();
-    final ImmutableList.Builder<RexNode> partitionKeys =
-        ImmutableList.builder();
-    for (SqlNode partition : partitionList) {
-      partitionKeys.add(bb.convertExpression(partition));
-    }
-    RexNode lowerBound = bb.convertExpression(window.getLowerBound());
-    RexNode upperBound = bb.convertExpression(window.getUpperBound());
-    SqlNodeList orderList = window.getOrderList();
-    if ((orderList.size() == 0) && !window.isRows()) {
-      // A logical range requires an ORDER BY clause. Use the implicit
-      // ordering of this relation. There must be one, otherwise it would
-      // have failed validation.
-      orderList = bb.scope.getOrderList();
-      if (orderList == null) {
-        throw new AssertionError(
-            "Relation should have sort key for implicit ORDER BY");
-      }
-    }
-    final ImmutableList.Builder<RexFieldCollation> orderKeys =
-        ImmutableList.builder();
-    final Set<SqlKind> flags = EnumSet.noneOf(SqlKind.class);
-    for (SqlNode order : orderList) {
-      flags.clear();
-      RexNode e = bb.convertSortExpression(order, flags);
-      orderKeys.add(new RexFieldCollation(e, flags));
-    }
-    try {
-      Preconditions.checkArgument(bb.window == null,
-          "already in window agg mode");
-      bb.window = window;
-      RexNode rexAgg = exprConverter.convertCall(bb, aggCall);
-      rexAgg =
-          rexBuilder.ensureType(
-              validator.getValidatedNodeType(call), rexAgg, false);
-
-      // Walk over the tree and apply 'over' to all agg functions. This is
-      // necessary because the returned expression is not necessarily a call
-      // to an agg function. For example, AVG(x) becomes SUM(x) / COUNT(x).
-
-      boolean isDistinct = false;
-      if (aggCall.getFunctionQuantifier() != null
-        && aggCall.getFunctionQuantifier().getValue().equals(SqlSelectKeyword.DISTINCT)) {
-        isDistinct = true;
-      }
-
-      final RexShuttle visitor =
-          new HistogramShuttle(
-              partitionKeys.build(), orderKeys.build(),
-              RexWindowBound.create(window.getLowerBound(), lowerBound),
-              RexWindowBound.create(window.getUpperBound(), upperBound),
-              window,
-              isDistinct);
-      RexNode overNode = rexAgg.accept(visitor);
-
-      return overNode;
-    } finally {
-      bb.window = null;
-    }
-  }
-
-  /**
-   * Converts a FROM clause into a relational expression.
-   *
-   * @param bb   Scope within which to resolve identifiers
-   * @param from FROM clause of a query. Examples include:
-   *
-   *             <ul>
-   *             <li>a single table ("SALES.EMP"),
-   *             <li>an aliased table ("EMP AS E"),
-   *             <li>a list of tables ("EMP, DEPT"),
-   *             <li>an ANSI Join expression ("EMP JOIN DEPT ON EMP.DEPTNO =
-   *             DEPT.DEPTNO"),
-   *             <li>a VALUES clause ("VALUES ('Fred', 20)"),
-   *             <li>a query ("(SELECT * FROM EMP WHERE GENDER = 'F')"),
-   *             <li>or any combination of the above.
-   *             </ul>
-   */
-  protected void convertFrom(
-      Blackboard bb,
-      SqlNode from) {
-    if (from == null) {
-      bb.setRoot(LogicalValues.createOneRow(cluster), false);
-      return;
-    }
-
-    final SqlCall call;
-    final SqlNode[] operands;
-    switch (from.getKind()) {
-    case MATCH_RECOGNIZE:
-      convertMatchRecognize(bb, (SqlCall) from);
-      return;
-
-    case AS:
-      convertFrom(bb, ((SqlCall) from).operand(0));
-      return;
-
-    case WITH_ITEM:
-      convertFrom(bb, ((SqlWithItem) from).query);
-      return;
-
-    case WITH:
-      convertFrom(bb, ((SqlWith) from).body);
-      return;
-
-    case TABLESAMPLE:
-      operands = ((SqlBasicCall) from).getOperands();
-      SqlSampleSpec sampleSpec = SqlLiteral.sampleValue(operands[1]);
-      if (sampleSpec instanceof SqlSampleSpec.SqlSubstitutionSampleSpec) {
-        String sampleName =
-            ((SqlSampleSpec.SqlSubstitutionSampleSpec) sampleSpec)
-                .getName();
-        datasetStack.push(sampleName);
-        convertFrom(bb, operands[0]);
-        datasetStack.pop();
-      } else if (sampleSpec instanceof SqlSampleSpec.SqlTableSampleSpec) {
-        SqlSampleSpec.SqlTableSampleSpec tableSampleSpec =
-            (SqlSampleSpec.SqlTableSampleSpec) sampleSpec;
-        convertFrom(bb, operands[0]);
-        RelOptSamplingParameters params =
-            new RelOptSamplingParameters(
-                tableSampleSpec.isBernoulli(),
-                tableSampleSpec.getSamplePercentage(),
-                tableSampleSpec.isRepeatable(),
-                tableSampleSpec.getRepeatableSeed());
-        bb.setRoot(new Sample(cluster, bb.root, params), false);
-      } else {
-        throw new AssertionError("unknown TABLESAMPLE type: " + sampleSpec);
-      }
-      return;
-
-    case IDENTIFIER:
-      convertIdentifier(bb, (SqlIdentifier) from, null);
-      return;
-
-    case EXTEND:
-      call = (SqlCall) from;
-      SqlIdentifier id = (SqlIdentifier) call.getOperandList().get(0);
-      SqlNodeList extendedColumns = (SqlNodeList) call.getOperandList().get(1);
-      convertIdentifier(bb, id, extendedColumns);
-      return;
-
-    case JOIN:
-      final SqlJoin join = (SqlJoin) from;
-      final SqlValidatorScope scope = validator.getJoinScope(from);
-      final Blackboard fromBlackboard = createBlackboard(scope, null, false);
-      SqlNode left = join.getLeft();
-      SqlNode right = join.getRight();
-      final boolean isNatural = join.isNatural();
-      final JoinType joinType = join.getJoinType();
-      final SqlValidatorScope leftScope =
-          Util.first(validator.getJoinScope(left),
-              ((DelegatingScope) bb.scope).getParent());
-      final Blackboard leftBlackboard =
-          createBlackboard(leftScope, null, false);
-      final SqlValidatorScope rightScope =
-          Util.first(validator.getJoinScope(right),
-              ((DelegatingScope) bb.scope).getParent());
-      final Blackboard rightBlackboard =
-          createBlackboard(rightScope, null, false);
-      convertFrom(leftBlackboard, left);
-      RelNode leftRel = leftBlackboard.root;
-      convertFrom(rightBlackboard, right);
-      RelNode rightRel = rightBlackboard.root;
-      JoinRelType convertedJoinType = convertJoinType(joinType);
-      RexNode conditionExp;
-      final SqlValidatorNamespace leftNamespace = validator.getNamespace(left);
-      final SqlValidatorNamespace rightNamespace = validator.getNamespace(right);
-      if (isNatural) {
-        final RelDataType leftRowType = leftNamespace.getRowType();
-        final RelDataType rightRowType = rightNamespace.getRowType();
-        final List<String> columnList =
-            SqlValidatorUtil.deriveNaturalJoinColumnList(leftRowType,
-                rightRowType);
-        conditionExp = convertUsing(leftNamespace, rightNamespace,
-            columnList);
-      } else {
-        conditionExp =
-            convertJoinCondition(
-                fromBlackboard,
-                leftNamespace,
-                rightNamespace,
-                join.getCondition(),
-                join.getConditionType(),
-                leftRel,
-                rightRel);
-      }
-
-      final RelNode joinRel =
-          createJoin(
-              fromBlackboard,
-              leftRel,
-              rightRel,
-              conditionExp,
-              convertedJoinType);
-      bb.setRoot(joinRel, false);
-      return;
-
-    case SELECT:
-    case INTERSECT:
-    case EXCEPT:
-    case UNION:
-      final RelNode rel = convertQueryRecursive(from, false, null).project();
-      bb.setRoot(rel, true);
-      return;
-
-    case VALUES:
-      convertValuesImpl(bb, (SqlCall) from, null);
-      return;
-
-    case UNNEST:
-      call = (SqlCall) from;
-      final List<SqlNode> nodes = call.getOperandList();
-      final SqlUnnestOperator operator = (SqlUnnestOperator) call.getOperator();
-      for (SqlNode node : nodes) {
-        replaceSubQueries(bb, node, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
-      }
-      final List<RexNode> exprs = new ArrayList<>();
-      final List<String> fieldNames = new ArrayList<>();
-      for (Ord<SqlNode> node : Ord.zip(nodes)) {
-        exprs.add(bb.convertExpression(node.e));
-        fieldNames.add(validator.deriveAlias(node.e, node.i));
-      }
-      final RelNode input =
-          RelOptUtil.createProject(
-              (null != bb.root) ? bb.root : LogicalValues.createOneRow(cluster),
-              exprs, fieldNames, true);
-
-      Uncollect uncollect =
-          new Uncollect(cluster, cluster.traitSetOf(Convention.NONE),
-              input, operator.withOrdinality);
-      bb.setRoot(uncollect, true);
-      return;
-
-    case COLLECTION_TABLE:
-      call = (SqlCall) from;
-
-      // Dig out real call; TABLE() wrapper is just syntactic.
-      assert call.getOperandList().size() == 1;
-      final SqlCall call2 = call.operand(0);
-      convertCollectionTable(bb, call2);
-      return;
-
-    default:
-      throw new AssertionError("not a join operator " + from);
-    }
-  }
-
-  protected void convertMatchRecognize(Blackboard bb, SqlCall call) {
-    final SqlMatchRecognize matchRecognize = (SqlMatchRecognize) call;
-    final SqlValidatorNamespace ns = validator.getNamespace(matchRecognize);
-    final SqlValidatorScope scope = validator.getMatchRecognizeScope(matchRecognize);
-
-    final Blackboard matchBb = createBlackboard(scope, null, false);
-    final RelDataType rowType = ns.getRowType();
-    // convert inner query, could be a table name or a derived table
-    SqlNode expr = matchRecognize.getTableRef();
-    convertFrom(matchBb, expr);
-    final RelNode input = matchBb.root;
-
-    // PARTITION BY
-    final SqlNodeList partitionList = matchRecognize.getPartitionList();
-    final List<RexNode> partitionKeys = new ArrayList<>();
-    for (SqlNode partition : partitionList) {
-      RexNode e = matchBb.convertExpression(partition);
-      partitionKeys.add(e);
-    }
-
-    // ORDER BY
-    final SqlNodeList orderList = matchRecognize.getOrderList();
-    final List<RelFieldCollation> orderKeys = new ArrayList<>();
-    for (SqlNode order : orderList) {
-      final RelFieldCollation.Direction direction;
-      switch (order.getKind()) {
-      case DESCENDING:
-        direction = RelFieldCollation.Direction.DESCENDING;
-        order = ((SqlCall) order).operand(0);
-        break;
-      case NULLS_FIRST:
-      case NULLS_LAST:
-        throw new AssertionError();
-      default:
-        direction = RelFieldCollation.Direction.ASCENDING;
-        break;
-      }
-      final RelFieldCollation.NullDirection nullDirection =
-          validator.getDefaultNullCollation().last(desc(direction))
-              ? RelFieldCollation.NullDirection.LAST
-              : RelFieldCollation.NullDirection.FIRST;
-      RexNode e = matchBb.convertExpression(order);
-      orderKeys.add(
-          new RelFieldCollation(((RexInputRef) e).getIndex(), direction,
-              nullDirection));
-    }
-    final RelCollation orders = cluster.traitSet().canonize(RelCollations.of(orderKeys));
-
-    // convert pattern
-    final Set<String> patternVarsSet = new HashSet<>();
-    SqlNode pattern = matchRecognize.getPattern();
-    final SqlBasicVisitor<RexNode> patternVarVisitor =
-      new SqlBasicVisitor<RexNode>() {
-        @Override public RexNode visit(SqlCall call) {
-          List<SqlNode> operands = call.getOperandList();
-          List<RexNode> newOperands = Lists.newArrayList();
-          for (SqlNode node : operands) {
-            newOperands.add(node.accept(this));
-          }
-          return rexBuilder.makeCall(
-            validator.getUnknownType(), call.getOperator(), newOperands);
-        }
-
-        @Override public RexNode visit(SqlIdentifier id) {
-          assert id.isSimple();
-          patternVarsSet.add(id.getSimple());
-          return rexBuilder.makeLiteral(id.getSimple());
-        }
-
-        @Override public RexNode visit(SqlLiteral literal) {
-          if (literal instanceof SqlNumericLiteral) {
-            return rexBuilder.makeExactLiteral(BigDecimal.valueOf(literal.intValue(true)));
-          } else {
-            return rexBuilder.makeLiteral(literal.booleanValue());
-          }
-        }
-      };
-    final RexNode patternNode = pattern.accept(patternVarVisitor);
-
-    // convert subset
-    final SqlNodeList subsets = matchRecognize.getSubsetList();
-    final Map<String, TreeSet<String>> subsetMap = Maps.newHashMap();
-    for (SqlNode node : subsets) {
-      List<SqlNode> operands = ((SqlCall) node).getOperandList();
-      SqlIdentifier left = (SqlIdentifier) operands.get(0);
-      patternVarsSet.add(left.getSimple());
-      SqlNodeList rights = (SqlNodeList) operands.get(1);
-      final TreeSet<String> list = new TreeSet<String>();
-      for (SqlNode right : rights) {
-        assert right instanceof SqlIdentifier;
-        list.add(((SqlIdentifier) right).getSimple());
-      }
-      subsetMap.put(left.getSimple(), list);
-    }
-
-    SqlNode afterMatch = matchRecognize.getAfter();
-    if (afterMatch == null) {
-      afterMatch =
-          SqlMatchRecognize.AfterOption.SKIP_TO_NEXT_ROW.symbol(SqlParserPos.ZERO);
-    }
-
-    final RexNode after;
-    if (afterMatch instanceof SqlCall) {
-      List<SqlNode> operands = ((SqlCall) afterMatch).getOperandList();
-      SqlOperator operator = ((SqlCall) afterMatch).getOperator();
-      assert operands.size() == 1;
-      SqlIdentifier id = (SqlIdentifier) operands.get(0);
-      assert patternVarsSet.contains(id.getSimple())
-          : id.getSimple() + " not defined in pattern";
-      RexNode rex = rexBuilder.makeLiteral(id.getSimple());
-      after =
-          rexBuilder.makeCall(validator.getUnknownType(), operator,
-              ImmutableList.of(rex));
-    } else {
-      after = matchBb.convertExpression(afterMatch);
-    }
-
-    matchBb.setPatternVarRef(true);
-
-    // convert measures
-    final ImmutableMap.Builder<String, RexNode> measureNodes =
-        ImmutableMap.builder();
-    for (SqlNode measure : matchRecognize.getMeasureList()) {
-      List<SqlNode> operands = ((SqlCall) measure).getOperandList();
-      String alias = ((SqlIdentifier) operands.get(1)).getSimple();
-      RexNode rex = matchBb.convertExpression(operands.get(0));
-      measureNodes.put(alias, rex);
-    }
-
-    // convert definitions
-    final ImmutableMap.Builder<String, RexNode> definitionNodes =
-        ImmutableMap.builder();
-    for (SqlNode def : matchRecognize.getPatternDefList()) {
-      List<SqlNode> operands = ((SqlCall) def).getOperandList();
-      String alias = ((SqlIdentifier) operands.get(1)).getSimple();
-      RexNode rex = matchBb.convertExpression(operands.get(0));
-      definitionNodes.put(alias, rex);
-    }
-
-    final SqlLiteral rowsPerMatch = matchRecognize.getRowsPerMatch();
-    final boolean allRows = rowsPerMatch != null
-        && rowsPerMatch.getValue() == SqlMatchRecognize.RowsPerMatchOption.ALL_ROWS;
-
-    matchBb.setPatternVarRef(false);
-
-    final RelFactories.MatchFactory factory =
-        RelFactories.DEFAULT_MATCH_FACTORY;
-    final RelNode rel =
-        factory.createMatchRecognize(input, patternNode,
-            matchRecognize.getStrictStart().booleanValue(),
-            matchRecognize.getStrictEnd().booleanValue(),
-            definitionNodes.build(), measureNodes.build(), after,
-            subsetMap, allRows, partitionKeys, orders, rowType);
-    bb.setRoot(rel, false);
-  }
-
-  private void convertIdentifier(Blackboard bb, SqlIdentifier id,
-      SqlNodeList extendedColumns) {
-    final SqlValidatorNamespace fromNamespace =
-        validator.getNamespace(id).resolve();
-    if (fromNamespace.getNode() != null) {
-      convertFrom(bb, fromNamespace.getNode());
-      return;
-    }
-    final String datasetName =
-        datasetStack.isEmpty() ? null : datasetStack.peek();
-    final boolean[] usedDataset = {false};
-    RelOptTable table =
-        SqlValidatorUtil.getRelOptTable(fromNamespace, catalogReader,
-            datasetName, usedDataset);
-    if (extendedColumns != null && extendedColumns.size() > 0) {
-      assert table != null;
-      final SqlValidatorTable validatorTable =
-          table.unwrap(SqlValidatorTable.class);
-      final List<RelDataTypeField> extendedFields =
-          SqlValidatorUtil.getExtendedColumns(validator.getTypeFactory(), validatorTable,
-              extendedColumns);
-      table = table.extend(extendedFields);
-    }
-    final RelNode tableRel;
-    if (config.isConvertTableAccess()) {
-      tableRel = toRel(table);
-    } else {
-      tableRel = LogicalTableScan.create(cluster, table);
-    }
-    bb.setRoot(tableRel, true);
-    if (usedDataset[0]) {
-      bb.setDataset(datasetName);
-    }
-  }
-
-  protected void convertCollectionTable(
-      Blackboard bb,
-      SqlCall call) {
-    final SqlOperator operator = call.getOperator();
-    if (operator == SqlStdOperatorTable.TABLESAMPLE) {
-      final String sampleName = (String) SqlLiteral.value(call.operand(0));
-      datasetStack.push(sampleName);
-      SqlCall cursorCall = call.operand(1);
-      SqlNode query = cursorCall.operand(0);
-      RelNode converted = convertQuery(query, false, false).rel;
-      bb.setRoot(converted, false);
-      datasetStack.pop();
-      return;
-    }
-    replaceSubQueries(bb, call, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
-
-    // Expand table macro if possible. It's more efficient than
-    // LogicalTableFunctionScan.
-    final SqlCallBinding callBinding =
-        new SqlCallBinding(bb.scope.getValidator(), bb.scope, call);
-    if (operator instanceof SqlUserDefinedTableMacro) {
-      final SqlUserDefinedTableMacro udf =
-          (SqlUserDefinedTableMacro) operator;
-      final TranslatableTable table =
-          udf.getTable(typeFactory, callBinding.operands());
-      final RelDataType rowType = table.getRowType(typeFactory);
-      RelOptTable relOptTable = RelOptTableImpl.create(null, rowType, table,
-          udf.getNameAsId().names);
-      RelNode converted = toRel(relOptTable);
-      bb.setRoot(converted, true);
-      return;
-    }
-
-    Type elementType;
-    if (operator instanceof SqlUserDefinedTableFunction) {
-      SqlUserDefinedTableFunction udtf = (SqlUserDefinedTableFunction) operator;
-      elementType = udtf.getElementType(typeFactory, callBinding.operands());
-    } else {
-      elementType = null;
-    }
-
-    RexNode rexCall = bb.convertExpression(call);
-    final List<RelNode> inputs = bb.retrieveCursors();
-    Set<RelColumnMapping> columnMappings =
-        getColumnMappings(operator);
-    LogicalTableFunctionScan callRel =
-        LogicalTableFunctionScan.create(
-            cluster,
-            inputs,
-            rexCall,
-            elementType,
-            validator.getValidatedNodeType(call),
-            columnMappings);
-    bb.setRoot(callRel, true);
-    afterTableFunction(bb, call, callRel);
-  }
-
-  protected void afterTableFunction(
-      SqlToRelConverter.Blackboard bb,
-      SqlCall call,
-      LogicalTableFunctionScan callRel) {
-  }
-
-  private Set<RelColumnMapping> getColumnMappings(SqlOperator op) {
-    SqlReturnTypeInference rti = op.getReturnTypeInference();
-    if (rti == null) {
-      return null;
-    }
-    if (rti instanceof TableFunctionReturnTypeInference) {
-      TableFunctionReturnTypeInference tfrti =
-          (TableFunctionReturnTypeInference) rti;
-      return tfrti.getColumnMappings();
-    } else {
-      return null;
-    }
-  }
-
-  protected RelNode createJoin(
-      Blackboard bb,
-      RelNode leftRel,
-      RelNode rightRel,
-      RexNode joinCond,
-      JoinRelType joinType) {
-    assert joinCond != null;
-
-    final CorrelationUse p = getCorrelationUse(bb, rightRel);
-    if (p != null) {
-      LogicalCorrelate corr = LogicalCorrelate.create(leftRel, p.r,
-          p.id, p.requiredColumns, SemiJoinType.of(joinType));
-      if (!joinCond.isAlwaysTrue()) {
-        final RelFactories.FilterFactory factory =
-            RelFactories.DEFAULT_FILTER_FACTORY;
-        return factory.createFilter(corr, joinCond);
-      }
-      return corr;
-    }
-
-    // OVERRIDE POINT
-    if (containOnlyCast(joinCond)) {
-      joinCond = convertCastCondition(joinCond);
-    }
-
-    final Join originalJoin =
-        (Join) RelFactories.DEFAULT_JOIN_FACTORY.createJoin(leftRel, rightRel,
-            joinCond, ImmutableSet.<CorrelationId>of(), joinType, false);
-
-    return RelOptUtil.pushDownJoinConditions(originalJoin);
-  }
-
-  // OVERRIDE POINT
-  private boolean containOnlyCast(RexNode node) {
-    boolean result = true;
-    switch (node.getKind()) {
-      case AND:
-      case EQUALS:
-        final RexCall call = (RexCall) node;
-        List<RexNode> operands = Lists.newArrayList(call.getOperands());
-        for (int i = 0; i < operands.size(); i++) {
-          RexNode operand = operands.get(i);
-          result &= containOnlyCast(operand);
-        }
-        break;
-      case OR:
-      case INPUT_REF:
-      case LITERAL:
-      case CAST:
-        return true;
-      default:
-        return false;
-    }
-    return result;
-  }
-
-  // OVERRIDE POINT
-  private static RexNode convertCastCondition(RexNode node) {
-    switch (node.getKind()) {
-      case IS_NULL:
-      case IS_NOT_NULL:
-      case OR:
-      case AND:
-      case EQUALS:
-        RexCall call = (RexCall) node;
-        List<RexNode> list = Lists.newArrayList();
-        List<RexNode> operands = Lists.newArrayList(call.getOperands());
-        for (int i = 0; i < operands.size(); i++) {
-          RexNode operand = operands.get(i);
-          final RexNode e =
-                  convertCastCondition(
-                          operand);
-          list.add(e);
-        }
-        if (!list.equals(call.getOperands())) {
-          return call.clone(call.getType(), list);
-        }
-        return call;
-      case CAST:
-        call = (RexCall) node;
-        operands = Lists.newArrayList(call.getOperands());
-        return operands.get(0);
-      default:
-        return node;
-    }
-  }
-
-  private CorrelationUse getCorrelationUse(Blackboard bb, final RelNode r0) {
-    final Set<CorrelationId> correlatedVariables =
-        RelOptUtil.getVariablesUsed(r0);
-    if (correlatedVariables.isEmpty()) {
-      return null;
-    }
-    final ImmutableBitSet.Builder requiredColumns = ImmutableBitSet.builder();
-    final List<CorrelationId> correlNames = Lists.newArrayList();
-
-    // All correlations must refer the same namespace since correlation
-    // produces exactly one correlation source.
-    // The same source might be referenced by different variables since
-    // DeferredLookups are not de-duplicated at create time.
-    SqlValidatorNamespace prevNs = null;
-
-    for (CorrelationId correlName : correlatedVariables) {
-      DeferredLookup lookup =
-          mapCorrelToDeferred.get(correlName);
-      RexFieldAccess fieldAccess = lookup.getFieldAccess(correlName);
-      String originalRelName = lookup.getOriginalRelName();
-      String originalFieldName = fieldAccess.getField().getName();
-
-      final SqlNameMatcher nameMatcher =
-          lookup.bb.scope.getValidator().getCatalogReader().nameMatcher();
-      final SqlValidatorScope.ResolvedImpl resolved =
-          new SqlValidatorScope.ResolvedImpl();
-      lookup.bb.scope.resolve(ImmutableList.of(originalRelName),
-          nameMatcher, false, resolved);
-      assert resolved.count() == 1;
-      final SqlValidatorScope.Resolve resolve = resolved.only();
-      final SqlValidatorNamespace foundNs = resolve.namespace;
-      final RelDataType rowType = resolve.rowType();
-      final int childNamespaceIndex = resolve.path.steps().get(0).i;
-      final SqlValidatorScope ancestorScope = resolve.scope;
-      boolean correlInCurrentScope = ancestorScope == bb.scope;
-
-      if (!correlInCurrentScope) {
-        continue;
-      }
-
-      if (prevNs == null) {
-        prevNs = foundNs;
-      } else {
-        assert prevNs == foundNs : "All correlation variables should resolve"
-            + " to the same namespace."
-            + " Prev ns=" + prevNs
-            + ", new ns=" + foundNs;
-      }
-
-      int namespaceOffset = 0;
-      if (childNamespaceIndex > 0) {
-        // If not the first child, need to figure out the width
-        // of output types from all the preceding namespaces
-        assert ancestorScope instanceof ListScope;
-        List<SqlValidatorNamespace> children =
-            ((ListScope) ancestorScope).getChildren();
-
-        for (int i = 0; i < childNamespaceIndex; i++) {
-          SqlValidatorNamespace child = children.get(i);
-          namespaceOffset +=
-              child.getRowType().getFieldCount();
-        }
-      }
-
-      RexFieldAccess topLevelFieldAccess = fieldAccess;
-      while (topLevelFieldAccess.getReferenceExpr() instanceof RexFieldAccess) {
-        topLevelFieldAccess = (RexFieldAccess) topLevelFieldAccess.getReferenceExpr();
-      }
-      final RelDataTypeField field = rowType.getFieldList()
-          .get(topLevelFieldAccess.getField().getIndex() - namespaceOffset);
-      int pos = namespaceOffset + field.getIndex();
-
-      assert field.getType()
-          == topLevelFieldAccess.getField().getType();
-
-      assert pos != -1;
-
-      if (bb.mapRootRelToFieldProjection.containsKey(bb.root)) {
-        // bb.root is an aggregate and only projects group by
-        // keys.
-        Map<Integer, Integer> exprProjection =
-            bb.mapRootRelToFieldProjection.get(bb.root);
-
-        // sub-query can reference group by keys projected from
-        // the root of the outer relation.
-        if (exprProjection.containsKey(pos)) {
-          pos = exprProjection.get(pos);
-        } else {
-          // correl not grouped
-          throw new AssertionError("Identifier '" + originalRelName + "."
-              + originalFieldName + "' is not a group expr");
-        }
-      }
-
-      requiredColumns.set(pos);
-      correlNames.add(correlName);
-    }
-
-    if (correlNames.isEmpty()) {
-      // None of the correlating variables originated in this scope.
-      return null;
-    }
-
-    RelNode r = r0;
-    if (correlNames.size() > 1) {
-      // The same table was referenced more than once.
-      // So we deduplicate.
-      r = DeduplicateCorrelateVariables.go(rexBuilder, correlNames.get(0),
-          Util.skip(correlNames), r0);
-      // Add new node to leaves.
-      leaves.add(r);
-    }
-    return new CorrelationUse(correlNames.get(0), requiredColumns.build(), r);
-  }
-
-  /**
-   * Determines whether a sub-query is non-correlated. Note that a
-   * non-correlated sub-query can contain correlated references, provided those
-   * references do not reference select statements that are parents of the
-   * sub-query.
-   *
-   * @param subq the sub-query
-   * @param bb   blackboard used while converting the sub-query, i.e., the
-   *             blackboard of the parent query of this sub-query
-   * @return true if the sub-query is non-correlated
-   */
-  private boolean isSubQueryNonCorrelated(RelNode subq, Blackboard bb) {
-    Set<CorrelationId> correlatedVariables = RelOptUtil.getVariablesUsed(subq);
-    for (CorrelationId correlName : correlatedVariables) {
-      DeferredLookup lookup = mapCorrelToDeferred.get(correlName);
-      String originalRelName = lookup.getOriginalRelName();
-
-      final SqlNameMatcher nameMatcher =
-          lookup.bb.scope.getValidator().getCatalogReader().nameMatcher();
-      final SqlValidatorScope.ResolvedImpl resolved =
-          new SqlValidatorScope.ResolvedImpl();
-      lookup.bb.scope.resolve(ImmutableList.of(originalRelName), nameMatcher,
-          false, resolved);
-
-      SqlValidatorScope ancestorScope = resolved.only().scope;
-
-      // If the correlated reference is in a scope that's "above" the
-      // sub-query, then this is a correlated sub-query.
-      SqlValidatorScope parentScope = bb.scope;
-      do {
-        if (ancestorScope == parentScope) {
-          return false;
-        }
-        if (parentScope instanceof DelegatingScope) {
-          parentScope = ((DelegatingScope) parentScope).getParent();
-        } else {
-          break;
-        }
-      } while (parentScope != null);
-    }
-    return true;
-  }
-
-  /**
-   * Returns a list of fields to be prefixed to each relational expression.
-   *
-   * @return List of system fields
-   */
-  protected List<RelDataTypeField> getSystemFields() {
-    return Collections.emptyList();
-  }
-
-  private RexNode convertJoinCondition(Blackboard bb,
-                                       SqlValidatorNamespace leftNamespace,
-                                       SqlValidatorNamespace rightNamespace,
-                                       SqlNode condition,
-                                       JoinConditionType conditionType,
-                                       RelNode leftRel,
-                                       RelNode rightRel) {
-    if (condition == null) {
-      return rexBuilder.makeLiteral(true);
-    }
-    bb.setRoot(ImmutableList.of(leftRel, rightRel));
-    replaceSubQueries(bb, condition, RelOptUtil.Logic.UNKNOWN_AS_FALSE);
-    switch (conditionType) {
-    case ON:
-      bb.setRoot(ImmutableList.of(leftRel, rightRel));
-      return bb.convertExpression(condition);
-    case USING:
-      final SqlNodeList list = (SqlNodeList) condition;
-      final List<String> nameList = new ArrayList<>();
-      for (SqlNode columnName : list) {
-        final SqlIdentifier id = (SqlIdentifier) columnName;
-        String name = id.getSimple();
-        nameList.add(name);
-      }
-      return convertUsing(leftNamespace, rightNamespace, nameList);
-    default:
-      throw Util.unexpected(conditionType);
-    }
-  }
-
-  /**
-   * Returns an expression for matching columns of a USING clause or inferred
-   * from NATURAL JOIN. "a JOIN b USING (x, y)" becomes "a.x = b.x AND a.y =
-   * b.y". Returns null if the column list is empty.
-   *
-   * @param leftNamespace Namespace of left input to join
-   * @param rightNamespace Namespace of right input to join
-   * @param nameList List of column names to join on
-   * @return Expression to match columns from name list, or true if name list
-   * is empty
-   */
-  private RexNode convertUsing(SqlValidatorNamespace leftNamespace,
-                               SqlValidatorNamespace rightNamespace,
-                               List<String> nameList) {
-    final SqlNameMatcher nameMatcher = catalogReader.nameMatcher();
-    final List<RexNode> list = Lists.newArrayList();
-    for (String name : nameList) {
-      List<RexNode> operands = new ArrayList<>();
-      int offset = 0;
-      for (SqlValidatorNamespace n : ImmutableList.of(leftNamespace,
-          rightNamespace)) {
-        final RelDataType rowType = n.getRowType();
-        final RelDataTypeField field = nameMatcher.field(rowType, name);
-        operands.add(
-            rexBuilder.makeInputRef(field.getType(),
-                offset + field.getIndex()));
-        offset += rowType.getFieldList().size();
-      }
-      list.add(rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, operands));
-    }
-    return RexUtil.composeConjunction(rexBuilder, list, false);
-  }
-
-  private static JoinRelType convertJoinType(JoinType joinType) {
-    switch (joinType) {
-    case COMMA:
-    case INNER:
-    case CROSS:
-      return JoinRelType.INNER;
-    case FULL:
-      return JoinRelType.FULL;
-    case LEFT:
-      return JoinRelType.LEFT;
-    case RIGHT:
-      return JoinRelType.RIGHT;
-    default:
-      throw Util.unexpected(joinType);
-    }
-  }
-
-  /**
-   * Converts the SELECT, GROUP BY and HAVING clauses of an aggregate query.
-   *
-   * <p>This method extracts SELECT, GROUP BY and HAVING clauses, and creates
-   * an {@link AggConverter}, then delegates to {@link #createAggImpl}.
-   * Derived class may override this method to change any of those clauses or
-   * specify a different {@link AggConverter}.
-   *
-   * @param bb            Scope within which to resolve identifiers
-   * @param select        Query
-   * @param orderExprList Additional expressions needed to implement ORDER BY
-   */
-  protected void convertAgg(
-      Blackboard bb,
-      SqlSelect select,
-      List<SqlNode> orderExprList) {
-    assert bb.root != null : "precondition: child != null";
-    SqlNodeList groupList = select.getGroup();
-    SqlNodeList selectList = select.getSelectList();
-    SqlNode having = select.getHaving();
-
-    final AggConverter aggConverter = new AggConverter(bb, select);
-    createAggImpl(
-        bb,
-        aggConverter,
-        selectList,
-        groupList,
-        having,
-        orderExprList);
-  }
-
-  protected final void createAggImpl(
-      Blackboard bb,
-      final AggConverter aggConverter,
-      SqlNodeList selectList,
-      SqlNodeList groupList,
-      SqlNode having,
-      List<SqlNode> orderExprList) {
-    // Find aggregate functions in SELECT and HAVING clause
-    final AggregateFinder aggregateFinder = new AggregateFinder();
-    selectList.accept(aggregateFinder);
-    if (having != null) {
-      having.accept(aggregateFinder);
-    }
-
-    // first replace the sub-queries inside the aggregates
-    // because they will provide input rows to the aggregates.
-    replaceSubQueries(bb, aggregateFinder.list,
-        RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
-
-    // If group-by clause is missing, pretend that it has zero elements.
-    if (groupList == null) {
-      groupList = SqlNodeList.EMPTY;
-    }
-
-    replaceSubQueries(bb, groupList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
-
-    // register the group exprs
-
-    // build a map to remember the projections from the top scope to the
-    // output of the current root.
-    //
-    // Calcite allows expressions, not just column references in
-    // group by list. This is not SQL 2003 compliant, but hey.
-
-    final AggregatingSelectScope scope = aggConverter.aggregatingSelectScope;
-    final AggregatingSelectScope.Resolved r = scope.resolved.get();
-    for (SqlNode groupExpr : r.groupExprList) {
-      aggConverter.addGroupExpr(groupExpr);
-    }
-
-    RexNode havingExpr = null;
-    final List<Pair<RexNode, String>> projects = Lists.newArrayList();
-
-    try {
-      Preconditions.checkArgument(bb.agg == null, "already in agg mode");
-      bb.agg = aggConverter;
-
-      // convert the select and having expressions, so that the
-      // agg converter knows which aggregations are required
-
-      selectList.accept(aggConverter);
-      // Assert we don't have dangling items left in the stack
-      assert !aggConverter.inOver;
-      for (SqlNode expr : orderExprList) {
-        expr.accept(aggConverter);
-        assert !aggConverter.inOver;
-      }
-      if (having != null) {
-        having.accept(aggConverter);
-        assert !aggConverter.inOver;
-      }
-
-      // compute inputs to the aggregator
-      List<Pair<RexNode, String>> preExprs = aggConverter.getPreExprs();
-
-      if (preExprs.size() == 0) {
-        // Special case for COUNT(*), where we can end up with no inputs
-        // at all.  The rest of the system doesn't like 0-tuples, so we
-        // select a dummy constant here.
-        final RexNode zero = rexBuilder.makeExactLiteral(BigDecimal.ZERO);
-        preExprs = ImmutableList.of(Pair.of(zero, (String) null));
-      }
-
-      final RelNode inputRel = bb.root;
-
-      // Project the expressions required by agg and having.
-      bb.setRoot(
-          RelOptUtil.createProject(
-              inputRel,
-              preExprs,
-              true),
-          false);
-      bb.mapRootRelToFieldProjection.put(bb.root, r.groupExprProjection);
-
-      // REVIEW jvs 31-Oct-2007:  doesn't the declaration of
-      // monotonicity here assume sort-based aggregation at
-      // the physical level?
-
-      // Tell bb which of group columns are sorted.
-      bb.columnMonotonicities.clear();
-      for (SqlNode groupItem : groupList) {
-        bb.columnMonotonicities.add(
-            bb.scope.getMonotonicity(groupItem));
-      }
-
-      // Add the aggregator
-      bb.setRoot(
-          createAggregate(bb, r.indicator, r.groupSet, r.groupSets,
-              aggConverter.getAggCalls()),
-          false);
-
-      // Generate NULL values for rolled-up not-null fields.
-      final Aggregate aggregate = (Aggregate) bb.root;
-      if (aggregate.getGroupType() != Aggregate.Group.SIMPLE) {
-        assert aggregate.indicator;
-        List<Pair<RexNode, String>> projects2 = Lists.newArrayList();
-        int converted = 0;
-        final int groupCount = aggregate.getGroupSet().cardinality();
-        for (RelDataTypeField field : aggregate.getRowType().getFieldList()) {
-          final int i = field.getIndex();
-          final RexNode rex;
-          if (i < groupCount && r.isNullable(i)) {
-            ++converted;
-
-            rex = rexBuilder.makeCall(SqlStdOperatorTable.CASE,
-                rexBuilder.makeInputRef(aggregate, groupCount + i),
-                rexBuilder.makeCast(
-                    typeFactory.createTypeWithNullability(
-                        field.getType(), true),
-                    rexBuilder.constantNull()),
-                rexBuilder.makeInputRef(aggregate, i));
-          } else {
-            rex = rexBuilder.makeInputRef(aggregate, i);
-          }
-          projects2.add(Pair.of(rex, field.getName()));
-        }
-        if (converted > 0) {
-          bb.setRoot(
-              RelOptUtil.createProject(bb.root, projects2, true),
-              false);
-        }
-      }
-
-      bb.mapRootRelToFieldProjection.put(bb.root, r.groupExprProjection);
-
-      // Replace sub-queries in having here and modify having to use
-      // the replaced expressions
-      if (having != null) {
-        SqlNode newHaving = pushDownNotForIn(bb.scope, having);
-        replaceSubQueries(bb, newHaving, RelOptUtil.Logic.UNKNOWN_AS_FALSE);
-        havingExpr = bb.convertExpression(newHaving);
-        if (havingExpr.isAlwaysTrue()) {
-          havingExpr = null;
-        }
-      }
-
-      // Now convert the other sub-queries in the select list.
-      // This needs to be done separately from the sub-query inside
-      // any aggregate in the select list, and after the aggregate rel
-      // is allocated.
-      replaceSubQueries(bb, selectList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
-
-      // Now sub-queries in the entire select list have been converted.
-      // Convert the select expressions to get the final list to be
-      // projected.
-      int k = 0;
-
-      // For select expressions, use the field names previously assigned
-      // by the validator. If we derive afresh, we might generate names
-      // like "EXPR$2" that don't match the names generated by the
-      // validator. This is especially the case when there are system
-      // fields; system fields appear in the relnode's rowtype but do not
-      // (yet) appear in the validator type.
-      final SelectScope selectScope =
-          SqlValidatorUtil.getEnclosingSelectScope(bb.scope);
-      assert selectScope != null;
-      final SqlValidatorNamespace selectNamespace =
-          validator.getNamespace(selectScope.getNode());
-      final List<String> names =
-          selectNamespace.getRowType().getFieldNames();
-      int sysFieldCount = selectList.size() - names.size();
-      for (SqlNode expr : selectList) {
-        projects.add(
-            Pair.of(bb.convertExpression(expr),
-                k < sysFieldCount
-                    ? validator.deriveAlias(expr, k++)
-                    : names.get(k++ - sysFieldCount)));
-      }
-
-      for (SqlNode expr : orderExprList) {
-        projects.add(
-            Pair.of(bb.convertExpression(expr),
-                validator.deriveAlias(expr, k++)));
-      }
-    } finally {
-      bb.agg = null;
-    }
-
-    // implement HAVING (we have already checked that it is non-trivial)
-    if (havingExpr != null) {
-      final RelFactories.FilterFactory factory =
-          RelFactories.DEFAULT_FILTER_FACTORY;
-      bb.setRoot(factory.createFilter(bb.root, havingExpr), false);
-    }
-
-    // implement the SELECT list
-    bb.setRoot(
-        RelOptUtil.createProject(
-            bb.root,
-            projects,
-            true),
-        false);
-
-    // Tell bb which of group columns are sorted.
-    bb.columnMonotonicities.clear();
-    for (SqlNode selectItem : selectList) {
-      bb.columnMonotonicities.add(
-          bb.scope.getMonotonicity(selectItem));
-    }
-  }
-
-  /**
-   * Creates an Aggregate.
-   *
-   * <p>In case the aggregate rel changes the order in which it projects
-   * fields, the <code>groupExprProjection</code> parameter is provided, and
-   * the implementation of this method may modify it.
-   *
-   * <p>The <code>sortedCount</code> parameter is the number of expressions
-   * known to be monotonic. These expressions must be on the leading edge of
-   * the grouping keys. The default implementation of this method ignores this
-   * parameter.
-   *
-   * @param bb       Blackboard
-   * @param indicator Whether to output fields indicating grouping sets
-   * @param groupSet Bit set of ordinals of grouping columns
-   * @param groupSets Grouping sets
-   * @param aggCalls Array of calls to aggregate functions
-   * @return LogicalAggregate
-   */
-  protected RelNode createAggregate(Blackboard bb, boolean indicator,
-                                    ImmutableBitSet groupSet, ImmutableList<ImmutableBitSet> groupSets,
-                                    List<AggregateCall> aggCalls) {
-    return LogicalAggregate.create(
-        bb.root, indicator, groupSet, groupSets, aggCalls);
-  }
-
-  public RexDynamicParam convertDynamicParam(
-      final SqlDynamicParam dynamicParam) {
-    // REVIEW jvs 8-Jan-2005:  dynamic params may be encountered out of
-    // order.  Should probably cross-check with the count from the parser
-    // at the end and make sure they all got filled in.  Why doesn't List
-    // have a resize() method?!?  Make this a utility.
-    while (dynamicParam.getIndex() >= dynamicParamSqlNodes.size()) {
-      dynamicParamSqlNodes.add(null);
-    }
-
-    dynamicParamSqlNodes.set(
-        dynamicParam.getIndex(),
-        dynamicParam);
-    return rexBuilder.makeDynamicParam(
-        getDynamicParamType(dynamicParam.getIndex()),
-        dynamicParam.getIndex());
-  }
-
-  /**
-   * Creates a list of collations required to implement the ORDER BY clause,
-   * if there is one. Populates <code>extraOrderExprs</code> with any sort
-   * expressions which are not in the select clause.
-   *
-   * @param bb              Scope within which to resolve identifiers
-   * @param select          Select clause. Never null, because we invent a
-   *                        dummy SELECT if ORDER BY is applied to a set
-   *                        operation (UNION etc.)
-   * @param orderList       Order by clause, may be null
-   * @param extraOrderExprs Sort expressions which are not in the select
-   *                        clause (output)
-   * @param collationList   List of collations (output)
-   */
-  protected void gatherOrderExprs(
-      Blackboard bb,
-      SqlSelect select,
-      SqlNodeList orderList,
-      List<SqlNode> extraOrderExprs,
-      List<RelFieldCollation> collationList) {
-    // TODO:  add validation rules to SqlValidator also
-    assert bb.root != null : "precondition: child != null";
-    assert select != null;
-    if (orderList == null) {
-      return;
-    }
-    for (SqlNode orderItem : orderList) {
-      collationList.add(
-          convertOrderItem(
-              select,
-              orderItem,
-              extraOrderExprs,
-              RelFieldCollation.Direction.ASCENDING,
-              RelFieldCollation.NullDirection.UNSPECIFIED));
-    }
-  }
-
-  protected RelFieldCollation convertOrderItem(
-          SqlSelect select,
-          SqlNode orderItem, List<SqlNode> extraExprs,
-          RelFieldCollation.Direction direction,
-          RelFieldCollation.NullDirection nullDirection) {
-    assert select != null;
-    // Handle DESC keyword, e.g. 'select a, b from t order by a desc'.
-    switch (orderItem.getKind()) {
-    case DESCENDING:
-      return convertOrderItem(
-          select,
-          ((SqlCall) orderItem).operand(0),
-          extraExprs,
-          RelFieldCollation.Direction.DESCENDING,
-          nullDirection);
-    case NULLS_FIRST:
-      return convertOrderItem(
-          select,
-          ((SqlCall) orderItem).operand(0),
-          extraExprs,
-          direction,
-          RelFieldCollation.NullDirection.FIRST);
-    case NULLS_LAST:
-      return convertOrderItem(
-          select,
-          ((SqlCall) orderItem).operand(0),
-          extraExprs,
-          direction,
-          RelFieldCollation.NullDirection.LAST);
-    }
-
-    SqlNode converted = validator.expandOrderExpr(select, orderItem);
-
-    switch (nullDirection) {
-    case UNSPECIFIED:
-      nullDirection = validator.getDefaultNullCollation().last(desc(direction))
-          ? RelFieldCollation.NullDirection.LAST
-          : RelFieldCollation.NullDirection.FIRST;
-    }
-
-    // Scan the select list and order exprs for an identical expression.
-    final SelectScope selectScope = validator.getRawSelectScope(select);
-    int ordinal = -1;
-    for (SqlNode selectItem : selectScope.getExpandedSelectList()) {
-      ++ordinal;
-      if (converted.equalsDeep(stripAs(selectItem), Litmus.IGNORE)) {
-        return new RelFieldCollation(ordinal, direction, nullDirection);
-      }
-    }
-
-    for (SqlNode extraExpr : extraExprs) {
-      ++ordinal;
-      if (converted.equalsDeep(extraExpr, Litmus.IGNORE)) {
-        return new RelFieldCollation(ordinal, direction, nullDirection);
-      }
-    }
-
-    // TODO:  handle collation sequence
-    // TODO: flag expressions as non-standard
-
-    extraExprs.add(converted);
-    return new RelFieldCollation(ordinal + 1, direction, nullDirection);
-  }
-
-  private static boolean desc(RelFieldCollation.Direction direction) {
-    switch (direction) {
-    case DESCENDING:
-    case STRICTLY_DESCENDING:
-      return true;
-    default:
-      return false;
-    }
-  }
-
-  @Deprecated // to be removed before 2.0
-  protected boolean enableDecorrelation() {
-    // disable sub-query decorrelation when needed.
-    // e.g. if outer joins are not supported.
-    return config.isDecorrelationEnabled();
-  }
-
-  protected RelNode decorrelateQuery(RelNode rootRel) {
-    return RelDecorrelator.decorrelateQuery(rootRel);
-  }
-
-  /**
-   * Returns whether to trim unused fields as part of the conversion process.
-   *
-   * @return Whether to trim unused fields
-   */
-  @Deprecated // to be removed before 2.0
-  public boolean isTrimUnusedFields() {
-//    return config.isTrimUnusedFields();
-    /* OVERRIDE POINT */
-    return false;
-  }
-
-  /**
-   * Recursively converts a query to a relational expression.
-   *
-   * @param query         Query
-   * @param top           Whether this query is the top-level query of the
-   *                      statement
-   * @param targetRowType Target row type, or null
-   * @return Relational expression
-   */
-  protected RelRoot convertQueryRecursive(SqlNode query, boolean top,
-                                          RelDataType targetRowType) {
-    final SqlKind kind = query.getKind();
-    switch (kind) {
-    case SELECT:
-      return RelRoot.of(convertSelect((SqlSelect) query, top), kind);
-    case INSERT:
-      return RelRoot.of(convertInsert((SqlInsert) query), kind);
-    case DELETE:
-      return RelRoot.of(convertDelete((SqlDelete) query), kind);
-    case UPDATE:
-      return RelRoot.of(convertUpdate((SqlUpdate) query), kind);
-    case MERGE:
-      return RelRoot.of(convertMerge((SqlMerge) query), kind);
-    case UNION:
-    case INTERSECT:
-    case EXCEPT:
-      return RelRoot.of(convertSetOp((SqlCall) query), kind);
-    case WITH:
-      return convertWith((SqlWith) query, top);
-    case VALUES:
-      return RelRoot.of(convertValues((SqlCall) query, targetRowType), kind);
-    default:
-      throw new AssertionError("not a query: " + query);
-    }
-  }
-
-  /**
-   * Converts a set operation (UNION, INTERSECT, MINUS) into relational
-   * expressions.
-   *
-   * @param call Call to set operator
-   * @return Relational expression
-   */
-  protected RelNode convertSetOp(SqlCall call) {
-    final RelNode left =
-        convertQueryRecursive(call.operand(0), false, null).project();
-    final RelNode right =
-        convertQueryRecursive(call.operand(1), false, null).project();
-    switch (call.getKind()) {
-    case UNION:
-      return LogicalUnion.create(ImmutableList.of(left, right), all(call));
-
-    case INTERSECT:
-      return LogicalIntersect.create(ImmutableList.of(left, right), all(call));
-
-    case EXCEPT:
-      return LogicalMinus.create(ImmutableList.of(left, right), all(call));
-
-    default:
-      throw Util.unexpected(call.getKind());
-    }
-  }
-
-  private boolean all(SqlCall call) {
-    return ((SqlSetOperator) call.getOperator()).isAll();
-  }
-
-  protected RelNode convertInsert(SqlInsert call) {
-    RelOptTable targetTable = getTargetTable(call);
-
-    final RelDataType targetRowType =
-        validator.getValidatedNodeType(call);
-    assert targetRowType != null;
-    RelNode sourceRel =
-        convertQueryRecursive(call.getSource(), false, targetRowType).project();
-    RelNode massagedRel = convertColumnList(call, sourceRel);
-
-    return createModify(targetTable, massagedRel);
-  }
-
-  /** Creates a relational expression to modify a table or modifiable view. */
-  private RelNode createModify(RelOptTable targetTable, RelNode source) {
-    final ModifiableTable modifiableTable =
-        targetTable.unwrap(ModifiableTable.class);
-    if (modifiableTable != null) {
-      return modifiableTable.toModificationRel(cluster, targetTable,
-          catalogReader, source, LogicalTableModify.Operation.INSERT, null,
-          null, false);
-    }
-    final ModifiableView modifiableView =
-        targetTable.unwrap(ModifiableView.class);
-    if (modifiableView != null) {
-      final Table delegateTable = modifiableView.getTable();
-      final RelDataType delegateRowType = delegateTable.getRowType(typeFactory);
-      final RelOptTable delegateRelOptTable =
-          RelOptTableImpl.create(null, delegateRowType, delegateTable,
-              modifiableView.getTablePath());
-      final RelNode newSource =
-          createSource(targetTable, source, modifiableView, delegateRowType);
-      return createModify(delegateRelOptTable, newSource);
-    }
-    return LogicalTableModify.create(targetTable, catalogReader, source,
-        LogicalTableModify.Operation.INSERT, null, null, false);
-  }
-
-  /** Wraps a relational expression in the projects and filters implied by
-   * a {@link ModifiableView}.
-   *
-   * <p>The input relational expression is suitable for inserting into the view,
-   * and the returned relational expression is suitable for inserting into its
-   * delegate table.
-   *
-   * <p>In principle, the delegate table of a view might be another modifiable
-   * view, and if so, the process can be repeated. */
-  private RelNode createSource(RelOptTable targetTable, RelNode source,
-                               ModifiableView modifiableView, RelDataType delegateRowType) {
-    final ImmutableIntList mapping = modifiableView.getColumnMapping();
-    assert mapping.size() == targetTable.getRowType().getFieldCount();
-
-    // For columns represented in the mapping, the expression is just a field
-    // reference.
-    final Map<Integer, RexNode> projectMap = new HashMap<>();
-    final List<RexNode> filters = new ArrayList<>();
-    for (int i = 0; i < mapping.size(); i++) {
-      int target = mapping.get(i);
-      if (target >= 0) {
-        projectMap.put(target, RexInputRef.of(i, source.getRowType()));
-      }
-    }
-
-    // For columns that are not in the mapping, and have a constraint of the
-    // form "column = value", the expression is the literal "value".
-    //
-    // If a column has multiple constraints, the extra ones will become a
-    // filter.
-    final RexNode constraint =
-        modifiableView.getConstraint(rexBuilder, delegateRowType);
-    RelOptUtil.inferViewPredicates(projectMap, filters, constraint);
-    final List<Pair<RexNode, String>> projects = new ArrayList<>();
-    for (RelDataTypeField field : delegateRowType.getFieldList()) {
-      RexNode node = projectMap.get(field.getIndex());
-      if (node == null) {
-        node = rexBuilder.makeNullLiteral(field.getType());
-      }
-      projects.add(
-          Pair.of(rexBuilder.ensureType(field.getType(), node, false),
-              field.getName()));
-    }
-
-    source = RelOptUtil.createProject(source, projects, true);
-    if (filters.size() > 0) {
-      source = RelOptUtil.createFilter(source, filters);
-    }
-    return source;
-  }
-
-  private RelOptTable.ToRelContext createToRelContext() {
-    return new RelOptTable.ToRelContext() {
-      public RelOptCluster getCluster() {
-        return cluster;
-      }
-
-      @Override public RelRoot expandView(
-          RelDataType rowType,
-          String queryString,
-          List<String> schemaPath,
-          List<String> viewPath) {
-        return viewExpander.expandView(rowType, queryString, schemaPath, viewPath);
-      }
-
-    };
-  }
-
-  public RelNode toRel(RelOptTable table) {
-    return table.toRel(createToRelContext());
-  }
-
-  protected RelOptTable getTargetTable(SqlNode call) {
-    final SqlValidatorNamespace targetNs = validator.getNamespace(call);
-    if (targetNs.isWrapperFor(SqlValidatorImpl.DmlNamespace.class)) {
-      final SqlValidatorImpl.DmlNamespace dmlNamespace =
-          targetNs.unwrap(SqlValidatorImpl.DmlNamespace.class);
-      return SqlValidatorUtil.getRelOptTable(dmlNamespace, catalogReader, null, null);
-    }
-    final SqlValidatorNamespace resolvedNamespace = targetNs.resolve();
-    return SqlValidatorUtil.getRelOptTable(resolvedNamespace, catalogReader, null, null);
-  }
-
-  /**
-   * Creates a source for an INSERT statement.
-   *
-   * <p>If the column list is not specified, source expressions match target
-   * columns in order.
-   *
-   * <p>If the column list is specified, Source expressions are mapped to
-   * target columns by name via targetColumnList, and may not cover the entire
-   * target table. So, we'll make up a full row, using a combination of
-   * default values and the source expressions provided.
-   *
-   * @param call      Insert expression
-   * @param sourceRel Source relational expression
-   * @return Converted INSERT statement
-   */
-  protected RelNode convertColumnList(
-      SqlInsert call,
-      RelNode sourceRel) {
-    RelDataType sourceRowType = sourceRel.getRowType();
-    final RexNode sourceRef =
-        rexBuilder.makeRangeReference(sourceRowType, 0, false);
-    final List<String> targetColumnNames = new ArrayList<>();
-    final List<RexNode> columnExprs = new ArrayList<>();
-    collectInsertTargets(call, sourceRef, targetColumnNames, columnExprs);
-
-    final RelOptTable targetTable = getTargetTable(call);
-    final RelDataType targetRowType = targetTable.getRowType();
-    final List<RelDataTypeField> targetFields =
-        targetRowType.getFieldList();
-    final List<RexNode> sourceExps =
-        new ArrayList<>(
-            Collections.<RexNode>nCopies(targetFields.size(), null));
-    final List<String> fieldNames =
-        new ArrayList<>(
-            Collections.<String>nCopies(targetFields.size(), null));
-
-    final InitializerExpressionFactory initializerFactory =
-        getInitializerFactory(validator.getNamespace(call).getTable());
-
-    // Walk the name list and place the associated value in the
-    // expression list according to the ordinal value returned from
-    // the table construct, leaving nulls in the list for columns
-    // that are not referenced.
-    final SqlNameMatcher nameMatcher = catalogReader.nameMatcher();
-    for (Pair<String, RexNode> p : Pair.zip(targetColumnNames, columnExprs)) {
-      RelDataTypeField field = nameMatcher.field(targetRowType, p.left);
-      assert field != null : "column " + p.left + " not found";
-      sourceExps.set(field.getIndex(), p.right);
-    }
-
-    // Walk the expression list and get default values for any columns
-    // that were not supplied in the statement. Get field names too.
-    for (int i = 0; i < targetFields.size(); ++i) {
-      final RelDataTypeField field = targetFields.get(i);
-      final String fieldName = field.getName();
-      fieldNames.set(i, fieldName);
-      if (sourceExps.get(i) != null) {
-        if (initializerFactory.isGeneratedAlways(targetTable, i)) {
-          throw RESOURCE.insertIntoAlwaysGenerated(fieldName).ex();
-        }
-        continue;
-      }
-      sourceExps.set(i,
-          initializerFactory.newColumnDefaultValue(targetTable, i,
-              new InitializerContext() {
-                public RexBuilder getRexBuilder() {
-                  return rexBuilder;
-                }
-              }));
-
-      // bare nulls are dangerous in the wrong hands
-      sourceExps.set(i,
-          castNullLiteralIfNeeded(sourceExps.get(i), field.getType()));
-    }
-
-    return RelOptUtil.createProject(sourceRel, sourceExps, fieldNames, true);
-  }
-
-  private InitializerExpressionFactory getInitializerFactory(
-      SqlValidatorTable validatorTable) {
-    // We might unwrap a null instead of a InitializerExpressionFactory.
-    final Table table = unwrap(validatorTable, Table.class);
-    if (table != null) {
-      InitializerExpressionFactory f =
-          unwrap(table, InitializerExpressionFactory.class);
-      if (f != null) {
-        return f;
-      }
-    }
-    return new NullInitializerExpressionFactory();
-  }
-
-  private static <T> T unwrap(Object o, Class<T> clazz) {
-    if (o instanceof Wrapper) {
-      return ((Wrapper) o).unwrap(clazz);
-    }
-    return null;
-  }
-
-  private RexNode castNullLiteralIfNeeded(RexNode node, RelDataType type) {
-    if (!RexLiteral.isNullLiteral(node)) {
-      return node;
-    }
-    return rexBuilder.makeCast(type, node);
-  }
-
-  /**
-   * Given an INSERT statement, collects the list of names to be populated and
-   * the expressions to put in them.
-   *
-   * @param call              Insert statement
-   * @param sourceRef         Expression representing a row from the source
-   *                          relational expression
-   * @param targetColumnNames List of target column names, to be populated
-   * @param columnExprs       List of expressions, to be populated
-   */
-  protected void collectInsertTargets(
-      SqlInsert call,
-      final RexNode sourceRef,
-      final List<String> targetColumnNames,
-      List<RexNode> columnExprs) {
-    final RelOptTable targetTable = getTargetTable(call);
-    final RelDataType tableRowType = targetTable.getRowType();
-    SqlNodeList targetColumnList = call.getTargetColumnList();
... 2953 lines suppressed ...