You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@kylin.apache.org by GitBox <gi...@apache.org> on 2018/11/15 12:57:08 UTC

[GitHub] shaofengshi closed pull request #346: KYLIN-3676 Update customized Calctie

shaofengshi closed pull request #346: KYLIN-3676 Update customized Calctie
URL: https://github.com/apache/kylin/pull/346
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/atopcalcite/.settings/org.eclipse.core.resources.prefs b/atopcalcite/.settings/org.eclipse.core.resources.prefs
deleted file mode 100644
index 29abf99956..0000000000
--- 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 500de29f7f..0000000000
--- 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 d521bab91b..0000000000
--- 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 58e40ef822..0000000000
--- 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 13a33e3059..0000000000
--- 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 b63beeeb49..0000000000
--- 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 849348432f..0000000000
--- 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 f758b40735..0000000000
--- 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 35f2ae6752..0000000000
--- 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 a769cbdac3..0000000000
--- 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 38bd223e05..0000000000
--- 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 320cd7c329..0000000000
--- 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 70d1b2abdf..0000000000
--- 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 519a73b647..0000000000
--- 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();
-    if (targetColumnList == null) {
-      if (validator.getConformance().isInsertSubsetColumnsAllowed()) {
-        final RelDataType targetRowType =
-            typeFactory.createStructType(
-                tableRowType.getFieldList()
-                    .subList(0, sourceRef.getType().getFieldCount()));
-        targetColumnNames.addAll(targetRowType.getFieldNames());
-      } else {
-        targetColumnNames.addAll(tableRowType.getFieldNames());
-      }
-    } else {
-      for (int i = 0; i < targetColumnList.size(); i++) {
-        SqlIdentifier id = (SqlIdentifier) targetColumnList.get(i);
-        RelDataTypeField field =
-            SqlValidatorUtil.getTargetField(
-                tableRowType, typeFactory, id, catalogReader, targetTable);
-        assert field != null : "column " + id.toString() + " not found";
-        targetColumnNames.add(field.getName());
-      }
-    }
-
-    for (int i = 0; i < targetColumnNames.size(); i++) {
-      final RexNode expr = rexBuilder.makeFieldAccess(sourceRef, i);
-      columnExprs.add(expr);
-    }
-  }
-
-  private RelNode convertDelete(SqlDelete call) {
-    RelOptTable targetTable = getTargetTable(call);
-    RelNode sourceRel = convertSelect(call.getSourceSelect(), false);
-    return LogicalTableModify.create(targetTable, catalogReader, sourceRel,
-        LogicalTableModify.Operation.DELETE, null, null, false);
-  }
-
-  private RelNode convertUpdate(SqlUpdate call) {
-    final SqlValidatorScope scope = validator.getWhereScope(call.getSourceSelect());
-    Blackboard bb = createBlackboard(scope, null, false);
-
-    Builder<RexNode> rexNodeSourceExpressionListBuilder = ImmutableList.builder();
-    for (SqlNode n : call.getSourceExpressionList()) {
-      RexNode rn = bb.convertExpression(n);
-      rexNodeSourceExpressionListBuilder.add(rn);
-    }
-
-    RelOptTable targetTable = getTargetTable(call);
-
-    // convert update column list from SqlIdentifier to String
-    final List<String> targetColumnNameList = new ArrayList<>();
-    final RelDataType targetRowType = targetTable.getRowType();
-    for (SqlNode node : call.getTargetColumnList()) {
-      SqlIdentifier id = (SqlIdentifier) node;
-      RelDataTypeField field =
-          SqlValidatorUtil.getTargetField(
-              targetRowType, typeFactory, id, catalogReader, targetTable);
-      assert field != null : "column " + id.toString() + " not found";
-      targetColumnNameList.add(field.getName());
-    }
-
-    RelNode sourceRel = convertSelect(call.getSourceSelect(), false);
-
-    return LogicalTableModify.create(targetTable, catalogReader, sourceRel,
-        LogicalTableModify.Operation.UPDATE, targetColumnNameList,
-        rexNodeSourceExpressionListBuilder.build(), false);
-  }
-
-  private RelNode convertMerge(SqlMerge call) {
-    RelOptTable targetTable = getTargetTable(call);
-
-    // convert update column list from SqlIdentifier to String
-    final List<String> targetColumnNameList = new ArrayList<>();
-    final RelDataType targetRowType = targetTable.getRowType();
-    SqlUpdate updateCall = call.getUpdateCall();
-    if (updateCall != null) {
-      for (SqlNode targetColumn : updateCall.getTargetColumnList()) {
-        SqlIdentifier id = (SqlIdentifier) targetColumn;
-        RelDataTypeField field =
-            SqlValidatorUtil.getTargetField(
-                targetRowType, typeFactory, id, catalogReader, targetTable);
-        assert field != null : "column " + id.toString() + " not found";
-        targetColumnNameList.add(field.getName());
-      }
-    }
-
-    // replace the projection of the source select with a
-    // projection that contains the following:
-    // 1) the expressions corresponding to the new insert row (if there is
-    //    an insert)
-    // 2) all columns from the target table (if there is an update)
-    // 3) the set expressions in the update call (if there is an update)
-
-    // first, convert the merge's source select to construct the columns
-    // from the target table and the set expressions in the update call
-    RelNode mergeSourceRel = convertSelect(call.getSourceSelect(), false);
-
-    // then, convert the insert statement so we can get the insert
-    // values expressions
-    SqlInsert insertCall = call.getInsertCall();
-    int nLevel1Exprs = 0;
-    List<RexNode> level1InsertExprs = null;
-    List<RexNode> level2InsertExprs = null;
-    if (insertCall != null) {
-      RelNode insertRel = convertInsert(insertCall);
-
-      // if there are 2 level of projections in the insert source, combine
-      // them into a single project; level1 refers to the topmost project;
-      // the level1 projection contains references to the level2
-      // expressions, except in the case where no target expression was
-      // provided, in which case, the expression is the default value for
-      // the column; or if the expressions directly map to the source
-      // table
-      level1InsertExprs =
-          ((LogicalProject) insertRel.getInput(0)).getProjects();
-      if (insertRel.getInput(0).getInput(0) instanceof LogicalProject) {
-        level2InsertExprs =
-            ((LogicalProject) insertRel.getInput(0).getInput(0))
-                .getProjects();
-      }
-      nLevel1Exprs = level1InsertExprs.size();
-    }
-
-    LogicalJoin join = (LogicalJoin) mergeSourceRel.getInput(0);
-    int nSourceFields = join.getLeft().getRowType().getFieldCount();
-    final List<RexNode> projects = new ArrayList<>();
-    for (int level1Idx = 0; level1Idx < nLevel1Exprs; level1Idx++) {
-      if ((level2InsertExprs != null)
-          && (level1InsertExprs.get(level1Idx) instanceof RexInputRef)) {
-        int level2Idx =
-            ((RexInputRef) level1InsertExprs.get(level1Idx)).getIndex();
-        projects.add(level2InsertExprs.get(level2Idx));
-      } else {
-        projects.add(level1InsertExprs.get(level1Idx));
-      }
-    }
-    if (updateCall != null) {
-      final LogicalProject project = (LogicalProject) mergeSourceRel;
-      projects.addAll(
-          Util.skip(project.getProjects(), nSourceFields));
-    }
-
-    RelNode massagedRel =
-        RelOptUtil.createProject(join, projects, null, true);
-
-    return LogicalTableModify.create(targetTable, catalogReader, massagedRel,
-        LogicalTableModify.Operation.MERGE, targetColumnNameList, null, false);
-  }
-
-  /**
-   * Converts an identifier into an expression in a given scope. For example,
-   * the "empno" in "select empno from emp join dept" becomes "emp.empno".
-   */
-  private RexNode convertIdentifier(
-      Blackboard bb,
-      SqlIdentifier identifier) {
-    // first check for reserved identifiers like CURRENT_USER
-    final SqlCall call = SqlUtil.makeCall(opTab, identifier);
-    if (call != null) {
-      return bb.convertExpression(call);
-    }
-
-    String pv = null;
-    if (bb.isPatternVarRef && identifier.names.size() > 1) {
-      pv = identifier.names.get(0);
-    }
-
-    final SqlQualified qualified;
-    if (bb.scope != null) {
-      qualified = bb.scope.fullyQualify(identifier);
-    } else {
-      qualified = SqlQualified.create(null, 1, null, identifier);
-    }
-    final Pair<RexNode, Map<String, Integer>> e0 = bb.lookupExp(qualified);
-    RexNode e = e0.left;
-    for (String name : qualified.suffixTranslated()) {
-      if (e == e0.left && e0.right != null) {
-        int i = e0.right.get(name);
-        e = rexBuilder.makeFieldAccess(e, i);
-      } else {
-        final boolean caseSensitive = true; // name already fully-qualified
-        if (identifier.isStar() && bb.scope instanceof MatchRecognizeScope) {
-          e = rexBuilder.makeFieldAccess(e, 0);
-        } else {
-          e = rexBuilder.makeFieldAccess(e, name, caseSensitive);
-        }
-      }
-    }
-    if (e instanceof RexInputRef) {
-      // adjust the type to account for nulls introduced by outer joins
-      e = adjustInputRef(bb, (RexInputRef) e);
-      if (pv != null) {
-        e = RexPatternFieldRef.of(pv, (RexInputRef) e);
-      }
-    }
-
-    if (e0.left instanceof RexCorrelVariable) {
-      assert e instanceof RexFieldAccess;
-      final RexNode prev =
-          bb.mapCorrelateToRex.put(((RexCorrelVariable) e0.left).id,
-              (RexFieldAccess) e);
-      assert prev == null;
-    }
-    return e;
-  }
-
-  /**
-   * Adjusts the type of a reference to an input field to account for nulls
-   * introduced by outer joins; and adjusts the offset to match the physical
-   * implementation.
-   *
-   * @param bb       Blackboard
-   * @param inputRef Input ref
-   * @return Adjusted input ref
-   */
-  protected RexNode adjustInputRef(
-      Blackboard bb,
-      RexInputRef inputRef) {
-    RelDataTypeField field = bb.getRootField(inputRef);
-    if (field != null) {
-      return rexBuilder.makeInputRef(
-          field.getType(),
-          inputRef.getIndex());
-    }
-    return inputRef;
-  }
-
-  /**
-   * Converts a row constructor into a relational expression.
-   *
-   * @param bb             Blackboard
-   * @param rowConstructor Row constructor expression
-   * @return Relational expression which returns a single row.
-   */
-  private RelNode convertRowConstructor(
-      Blackboard bb,
-      SqlCall rowConstructor) {
-    Preconditions.checkArgument(isRowConstructor(rowConstructor));
-    final List<SqlNode> operands = rowConstructor.getOperandList();
-    return convertMultisets(operands, bb);
-  }
-
-  private RelNode convertCursor(Blackboard bb, SubQuery subQuery) {
-    final SqlCall cursorCall = (SqlCall) subQuery.node;
-    assert cursorCall.operandCount() == 1;
-    SqlNode query = cursorCall.operand(0);
-    RelNode converted = convertQuery(query, false, false).rel;
-    int iCursor = bb.cursors.size();
-    bb.cursors.add(converted);
-    subQuery.expr =
-        new RexInputRef(
-            iCursor,
-            converted.getRowType());
-    return converted;
-  }
-
-  private RelNode convertMultisets(final List<SqlNode> operands,
-                                   Blackboard bb) {
-    // NOTE: Wael 2/04/05: this implementation is not the most efficient in
-    // terms of planning since it generates XOs that can be reduced.
-    final List<Object> joinList = new ArrayList<>();
-    List<SqlNode> lastList = new ArrayList<>();
-    for (int i = 0; i < operands.size(); i++) {
-      SqlNode operand = operands.get(i);
-      if (!(operand instanceof SqlCall)) {
-        lastList.add(operand);
-        continue;
-      }
-
-      final SqlCall call = (SqlCall) operand;
-      final RelNode input;
-      switch (call.getKind()) {
-      case MULTISET_VALUE_CONSTRUCTOR:
-      case ARRAY_VALUE_CONSTRUCTOR:
-        final SqlNodeList list =
-            new SqlNodeList(call.getOperandList(), call.getParserPosition());
-        CollectNamespace nss =
-            (CollectNamespace) validator.getNamespace(call);
-        Blackboard usedBb;
-        if (null != nss) {
-          usedBb = createBlackboard(nss.getScope(), null, false);
-        } else {
-          usedBb =
-              createBlackboard(new ListScope(bb.scope) {
-                public SqlNode getNode() {
-                  return call;
-                }
-              }, null, false);
-        }
-        RelDataType multisetType = validator.getValidatedNodeType(call);
-        ((SqlValidatorImpl) validator).setValidatedNodeType(list,
-            multisetType.getComponentType());
-        input = convertQueryOrInList(usedBb, list, null);
-        break;
-      case MULTISET_QUERY_CONSTRUCTOR:
-      case ARRAY_QUERY_CONSTRUCTOR:
-        final RelRoot root = convertQuery(call.operand(0), false, true);
-        input = root.rel;
-        break;
-      default:
-        lastList.add(operand);
-        continue;
-      }
-
-      if (lastList.size() > 0) {
-        joinList.add(lastList);
-      }
-      lastList = new ArrayList<>();
-      Collect collect =
-          new Collect(
-              cluster,
-              cluster.traitSetOf(Convention.NONE),
-              input,
-              validator.deriveAlias(call, i));
-      joinList.add(collect);
-    }
-
-    if (joinList.size() == 0) {
-      joinList.add(lastList);
-    }
-
-    for (int i = 0; i < joinList.size(); i++) {
-      Object o = joinList.get(i);
-      if (o instanceof List) {
-        @SuppressWarnings("unchecked")
-        List<SqlNode> projectList = (List<SqlNode>) o;
-        final List<RexNode> selectList = new ArrayList<>();
-        final List<String> fieldNameList = new ArrayList<>();
-        for (int j = 0; j < projectList.size(); j++) {
-          SqlNode operand = projectList.get(j);
-          selectList.add(bb.convertExpression(operand));
-
-          // REVIEW angel 5-June-2005: Use deriveAliasFromOrdinal
-          // instead of deriveAlias to match field names from
-          // SqlRowOperator. Otherwise, get error   Type
-          // 'RecordType(INTEGER EMPNO)' has no field 'EXPR$0' when
-          // doing   select * from unnest(     select multiset[empno]
-          // from sales.emps);
-
-          fieldNameList.add(SqlUtil.deriveAliasFromOrdinal(j));
-        }
-
-        RelNode projRel =
-            RelOptUtil.createProject(
-                LogicalValues.createOneRow(cluster),
-                selectList,
-                fieldNameList);
-
-        joinList.set(i, projRel);
-      }
-    }
-
-    RelNode ret = (RelNode) joinList.get(0);
-    for (int i = 1; i < joinList.size(); i++) {
-      RelNode relNode = (RelNode) joinList.get(i);
-      ret =
-          RelFactories.DEFAULT_JOIN_FACTORY.createJoin(
-              ret,
-              relNode,
-              rexBuilder.makeLiteral(true),
-              ImmutableSet.<CorrelationId>of(),
-              JoinRelType.INNER,
-              false);
-    }
-    return ret;
-  }
-
-  private void convertSelectList(
-      Blackboard bb,
-      SqlSelect select,
-      List<SqlNode> orderList) {
-    SqlNodeList selectList = select.getSelectList();
-    selectList = validator.expandStar(selectList, select, false);
-
-    replaceSubQueries(bb, selectList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
-
-    List<String> fieldNames = new ArrayList<>();
-    final List<RexNode> exprs = new ArrayList<>();
-    final Collection<String> aliases = new TreeSet<>();
-
-    // Project any system fields. (Must be done before regular select items,
-    // because offsets may be affected.)
-    final List<SqlMonotonicity> columnMonotonicityList = new ArrayList<>();
-    extraSelectItems(
-        bb,
-        select,
-        exprs,
-        fieldNames,
-        aliases,
-        columnMonotonicityList);
-
-    // Project select clause.
-    int i = -1;
-    for (SqlNode expr : selectList) {
-      ++i;
-      exprs.add(bb.convertExpression(expr));
-      fieldNames.add(deriveAlias(expr, aliases, i));
-    }
-
-    // Project extra fields for sorting.
-    for (SqlNode expr : orderList) {
-      ++i;
-      SqlNode expr2 = validator.expandOrderExpr(select, expr);
-      exprs.add(bb.convertExpression(expr2));
-      fieldNames.add(deriveAlias(expr, aliases, i));
-    }
-
-    fieldNames = SqlValidatorUtil.uniquify(fieldNames,
-        catalogReader.nameMatcher().isCaseSensitive());
-
-    bb.setRoot(
-        RelOptUtil.createProject(bb.root, exprs, fieldNames),
-        false);
-
-    assert bb.columnMonotonicities.isEmpty();
-    bb.columnMonotonicities.addAll(columnMonotonicityList);
-    for (SqlNode selectItem : selectList) {
-      bb.columnMonotonicities.add(
-          selectItem.getMonotonicity(bb.scope));
-    }
-  }
-
-  /**
-   * Adds extra select items. The default implementation adds nothing; derived
-   * classes may add columns to exprList, nameList, aliasList and
-   * columnMonotonicityList.
-   *
-   * @param bb                     Blackboard
-   * @param select                 Select statement being translated
-   * @param exprList               List of expressions in select clause
-   * @param nameList               List of names, one per column
-   * @param aliasList              Collection of aliases that have been used
-   *                               already
-   * @param columnMonotonicityList List of monotonicity, one per column
-   */
-  protected void extraSelectItems(
-      Blackboard bb,
-      SqlSelect select,
-      List<RexNode> exprList,
-      List<String> nameList,
-      Collection<String> aliasList,
-      List<SqlMonotonicity> columnMonotonicityList) {
-  }
-
-  private String deriveAlias(
-      final SqlNode node,
-      Collection<String> aliases,
-      final int ordinal) {
-    String alias = validator.deriveAlias(node, ordinal);
-    if ((alias == null) || aliases.contains(alias)) {
-      String aliasBase = (alias == null) ? "EXPR$" : alias;
-      for (int j = 0;; j++) {
-        alias = aliasBase + j;
-        if (!aliases.contains(alias)) {
-          break;
-        }
-      }
-    }
-    aliases.add(alias);
-    return alias;
-  }
-
-  /**
-   * Converts a WITH sub-query into a relational expression.
-   */
-  public RelRoot convertWith(SqlWith with, boolean top) {
-    return convertQuery(with.body, false, top);
-  }
-
-  /**
-   * Converts a SELECT statement's parse tree into a relational expression.
-   */
-  public RelNode convertValues(
-      SqlCall values,
-      RelDataType targetRowType) {
-    final SqlValidatorScope scope = validator.getOverScope(values);
-    assert scope != null;
-    final Blackboard bb = createBlackboard(scope, null, false);
-    convertValuesImpl(bb, values, targetRowType);
-    return bb.root;
-  }
-
-  /**
-   * Converts a values clause (as in "INSERT INTO T(x,y) VALUES (1,2)") into a
-   * relational expression.
-   *
-   * @param bb            Blackboard
-   * @param values        Call to SQL VALUES operator
-   * @param targetRowType Target row type
-   */
-  private void convertValuesImpl(
-      Blackboard bb,
-      SqlCall values,
-      RelDataType targetRowType) {
-    // Attempt direct conversion to LogicalValues; if that fails, deal with
-    // fancy stuff like sub-queries below.
-    RelNode valuesRel =
-        convertRowValues(
-            bb,
-            values,
-            values.getOperandList(),
-            true,
-            targetRowType);
-    if (valuesRel != null) {
-      bb.setRoot(valuesRel, true);
-      return;
-    }
-
-    final List<RelNode> unionRels = new ArrayList<>();
-    for (SqlNode rowConstructor1 : values.getOperandList()) {
-      SqlCall rowConstructor = (SqlCall) rowConstructor1;
-      Blackboard tmpBb = createBlackboard(bb.scope, null, false);
-      replaceSubQueries(tmpBb, rowConstructor,
-          RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
-      final List<Pair<RexNode, String>> exps = new ArrayList<>();
-      for (Ord<SqlNode> operand : Ord.zip(rowConstructor.getOperandList())) {
-        exps.add(
-            Pair.of(
-                tmpBb.convertExpression(operand.e),
-                validator.deriveAlias(operand.e, operand.i)));
-      }
-      RelNode in =
-          (null == tmpBb.root)
-              ? LogicalValues.createOneRow(cluster)
-              : tmpBb.root;
-      unionRels.add(
-          RelOptUtil.createProject(
-              in,
-              Pair.left(exps),
-              Pair.right(exps),
-              true));
-    }
-
-    if (unionRels.size() == 0) {
-      throw new AssertionError("empty values clause");
-    } else if (unionRels.size() == 1) {
-      bb.setRoot(
-          unionRels.get(0),
-          true);
-    } else {
-      bb.setRoot(
-          LogicalUnion.create(unionRels, true),
-          true);
-    }
-
-    // REVIEW jvs 22-Jan-2004:  should I add
-    // mapScopeToLux.put(validator.getScope(values),bb.root);
-    // ?
-  }
-
-  //~ Inner Classes ----------------------------------------------------------
-
-  /**
-   * Workspace for translating an individual SELECT statement (or sub-SELECT).
-   */
-  protected class Blackboard implements SqlRexContext, SqlVisitor<RexNode> {
-    /**
-     * Collection of {@link RelNode} objects which correspond to a SELECT
-     * statement.
-     */
-    public final SqlValidatorScope scope;
-    private final Map<String, RexNode> nameToNodeMap;
-    public RelNode root;
-    private List<RelNode> inputs;
-    private final Map<CorrelationId, RexFieldAccess> mapCorrelateToRex =
-        new HashMap<>();
-
-    private boolean isPatternVarRef = false;
-
-    final List<RelNode> cursors = new ArrayList<>();
-
-    /**
-     * List of <code>IN</code> and <code>EXISTS</code> nodes inside this
-     * <code>SELECT</code> statement (but not inside sub-queries).
-     */
-    private final Set<SubQuery> subQueryList = new LinkedHashSet<>();
-
-    /**
-     * Workspace for building aggregates.
-     */
-    AggConverter agg;
-
-    /**
-     * When converting window aggregate, we need to know if the window is
-     * guaranteed to be non-empty.
-     */
-    SqlWindow window;
-
-    /**
-     * Project the groupby expressions out of the root of this sub-select.
-     * Sub-queries can reference group by expressions projected from the
-     * "right" to the sub-query.
-     */
-    private final Map<RelNode, Map<Integer, Integer>>
-    mapRootRelToFieldProjection = new HashMap<>();
-
-    private final List<SqlMonotonicity> columnMonotonicities =
-        new ArrayList<>();
-
-    private final List<RelDataTypeField> systemFieldList = new ArrayList<>();
-    final boolean top;
-
-    private final InitializerExpressionFactory initializerExpressionFactory =
-        new NullInitializerExpressionFactory();
-
-    /**
-     * Creates a Blackboard.
-     *
-     * @param scope         Name-resolution scope for expressions validated
-     *                      within this query. Can be null if this Blackboard is
-     *                      for a leaf node, say
-     * @param nameToNodeMap Map which translates the expression to map a
-     *                      given parameter into, if translating expressions;
-     *                      null otherwise
-     * @param top           Whether this is the root of the query
-     */
-    protected Blackboard(SqlValidatorScope scope,
-                         Map<String, RexNode> nameToNodeMap, boolean top) {
-      this.scope = scope;
-      this.nameToNodeMap = nameToNodeMap;
-      this.top = top;
-    }
-
-    public void setPatternVarRef(boolean isVarRef) {
-      this.isPatternVarRef = isVarRef;
-    }
-
-    public RexNode register(
-        RelNode rel,
-        JoinRelType joinType) {
-      return register(rel, joinType, null);
-    }
-
-    /**
-     * Registers a relational expression.
-     *
-     * @param rel               Relational expression
-     * @param joinType          Join type
-     * @param leftKeys LHS of IN clause, or null for expressions
-     *                          other than IN
-     * @return Expression with which to refer to the row (or partial row)
-     * coming from this relational expression's side of the join
-     */
-    public RexNode register(
-        RelNode rel,
-        JoinRelType joinType,
-        List<RexNode> leftKeys) {
-      assert joinType != null;
-      if (root == null) {
-        assert leftKeys == null;
-        setRoot(rel, false);
-        return rexBuilder.makeRangeReference(
-            root.getRowType(),
-            0,
-            false);
-      }
-
-      final RexNode joinCond;
-      final int origLeftInputCount = root.getRowType().getFieldCount();
-      if (leftKeys != null) {
-        List<RexNode> newLeftInputExpr = Lists.newArrayList();
-        for (int i = 0; i < origLeftInputCount; i++) {
-          newLeftInputExpr.add(rexBuilder.makeInputRef(root, i));
-        }
-
-        final List<Integer> leftJoinKeys = Lists.newArrayList();
-        for (RexNode leftKey : leftKeys) {
-          int index = newLeftInputExpr.indexOf(leftKey);
-          if (index < 0 || joinType == JoinRelType.LEFT) {
-            index = newLeftInputExpr.size();
-            newLeftInputExpr.add(leftKey);
-          }
-          leftJoinKeys.add(index);
-        }
-
-        RelNode newLeftInput =
-            RelOptUtil.createProject(
-                root,
-                newLeftInputExpr,
-                null,
-                true);
-
-        // maintain the group by mapping in the new LogicalProject
-        if (mapRootRelToFieldProjection.containsKey(root)) {
-          mapRootRelToFieldProjection.put(
-              newLeftInput,
-              mapRootRelToFieldProjection.get(root));
-        }
-
-        setRoot(newLeftInput, false);
-
-        // right fields appear after the LHS fields.
-        final int rightOffset = root.getRowType().getFieldCount()
-            - newLeftInput.getRowType().getFieldCount();
-        final List<Integer> rightKeys =
-            Util.range(rightOffset, rightOffset + leftKeys.size());
-
-        joinCond =
-            RelOptUtil.createEquiJoinCondition(newLeftInput, leftJoinKeys,
-                rel, rightKeys, rexBuilder);
-      } else {
-        joinCond = rexBuilder.makeLiteral(true);
-      }
-
-      int leftFieldCount = root.getRowType().getFieldCount();
-      final RelNode join =
-          createJoin(
-              this,
-              root,
-              rel,
-              joinCond,
-              joinType);
-
-      setRoot(join, false);
-
-      if (leftKeys != null
-          && joinType == JoinRelType.LEFT) {
-        final int leftKeyCount = leftKeys.size();
-        int rightFieldLength = rel.getRowType().getFieldCount();
-        assert leftKeyCount == rightFieldLength - 1;
-
-        final int rexRangeRefLength = leftKeyCount + rightFieldLength;
-        RelDataType returnType =
-            typeFactory.createStructType(
-                new AbstractList<Map.Entry<String, RelDataType>>() {
-                  public Map.Entry<String, RelDataType> get(
-                      int index) {
-                    return join.getRowType().getFieldList()
-                        .get(origLeftInputCount + index);
-                  }
-
-                  public int size() {
-                    return rexRangeRefLength;
-                  }
-                });
-
-        return rexBuilder.makeRangeReference(
-            returnType,
-            origLeftInputCount,
-            false);
-      } else {
-        return rexBuilder.makeRangeReference(
-            rel.getRowType(),
-            leftFieldCount,
-            joinType.generatesNullsOnRight());
-      }
-    }
-
-    /**
-     * Sets a new root relational expression, as the translation process
-     * backs its way further up the tree.
-     *
-     * @param root New root relational expression
-     * @param leaf Whether the relational expression is a leaf, that is,
-     *             derived from an atomic relational expression such as a table
-     *             name in the from clause, or the projection on top of a
-     *             select-sub-query. In particular, relational expressions
-     *             derived from JOIN operators are not leaves, but set
-     *             expressions are.
-     */
-    public void setRoot(RelNode root, boolean leaf) {
-      setRoot(
-          Collections.singletonList(root), root, root instanceof LogicalJoin);
-      if (leaf) {
-        leaves.add(root);
-      }
-      this.columnMonotonicities.clear();
-    }
-
-    private void setRoot(
-        List<RelNode> inputs,
-        RelNode root,
-        boolean hasSystemFields) {
-      this.inputs = inputs;
-      this.root = root;
-      this.systemFieldList.clear();
-      if (hasSystemFields) {
-        this.systemFieldList.addAll(getSystemFields());
-      }
-    }
-
-    /**
-     * Notifies this Blackboard that the root just set using
-     * {@link #setRoot(RelNode, boolean)} was derived using dataset
-     * substitution.
-     *
-     * <p>The default implementation is not interested in such
-     * notifications, and does nothing.
-     *
-     * @param datasetName Dataset name
-     */
-    public void setDataset(String datasetName) {
-    }
-
-    void setRoot(List<RelNode> inputs) {
-      setRoot(inputs, null, false);
-    }
-
-    /**
-     * Returns an expression with which to reference a from-list item.
-     *
-     * @param qualified the alias of the from item
-     * @return a {@link RexFieldAccess} or {@link RexRangeRef}, or null if
-     * not found
-     */
-    Pair<RexNode, Map<String, Integer>> lookupExp(SqlQualified qualified) {
-      if (nameToNodeMap != null && qualified.prefixLength == 1) {
-        RexNode node = nameToNodeMap.get(qualified.identifier.names.get(0));
-        if (node == null) {
-          throw new AssertionError("Unknown identifier '" + qualified.identifier
-              + "' encountered while expanding expression");
-        }
-        return Pair.of(node, null);
-      }
-      final SqlNameMatcher nameMatcher =
-          scope.getValidator().getCatalogReader().nameMatcher();
-      final SqlValidatorScope.ResolvedImpl resolved =
-          new SqlValidatorScope.ResolvedImpl();
-      scope.resolve(qualified.prefix(), nameMatcher, false, resolved);
-      if (!(resolved.count() == 1)) {
-        return null;
-      }
-      final SqlValidatorScope.Resolve resolve = resolved.only();
-      final RelDataType rowType = resolve.rowType();
-
-      // Found in current query's from list.  Find which from item.
-      // We assume that the order of the from clause items has been
-      // preserved.
-      final SqlValidatorScope ancestorScope = resolve.scope;
-      boolean isParent = ancestorScope != scope;
-      if ((inputs != null) && !isParent) {
-        final LookupContext rels =
-            new LookupContext(this, inputs, systemFieldList.size());
-        final RexNode node = lookup(resolve.path.steps().get(0).i, rels);
-        if (node == null) {
-          return null;
-        } else {
-          return Pair.of(node, null);
-        }
-      } else {
-        // We're referencing a relational expression which has not been
-        // converted yet. This occurs when from items are correlated,
-        // e.g. "select from emp as emp join emp.getDepts() as dept".
-        // Create a temporary expression.
-        DeferredLookup lookup =
-            new DeferredLookup(this, qualified.identifier.names.get(0));
-        final CorrelationId correlId = cluster.createCorrel();
-        mapCorrelToDeferred.put(correlId, lookup);
-        if (resolve.path.steps().get(0).i < 0) {
-          return Pair.of(rexBuilder.makeCorrel(rowType, correlId), null);
-        } else {
-          final RelDataTypeFactory.FieldInfoBuilder builder =
-              typeFactory.builder();
-          final ListScope ancestorScope1 = (ListScope) resolve.scope;
-          final ImmutableMap.Builder<String, Integer> fields =
-              ImmutableMap.builder();
-          int i = 0;
-          int offset = 0;
-          for (SqlValidatorNamespace c : ancestorScope1.getChildren()) {
-            builder.addAll(c.getRowType().getFieldList());
-            if (i == resolve.path.steps().get(0).i) {
-              for (RelDataTypeField field : c.getRowType().getFieldList()) {
-                fields.put(c.translate(field.getName()),
-                    field.getIndex() + offset);
-              }
-            }
-            ++i;
-            offset += c.getRowType().getFieldCount();
-          }
-          final RexNode c =
-              rexBuilder.makeCorrel(builder.uniquify().build(), correlId);
-          return Pair.<RexNode, Map<String, Integer>>of(c, fields.build());
-        }
-      }
-    }
-
-    /**
-     * Creates an expression with which to reference the expression whose
-     * offset in its from-list is {@code offset}.
-     */
-    RexNode lookup(
-        int offset,
-        LookupContext lookupContext) {
-      Pair<RelNode, Integer> pair = lookupContext.findRel(offset);
-      return rexBuilder.makeRangeReference(
-          pair.left.getRowType(),
-          pair.right,
-          false);
-    }
-
-    RelDataTypeField getRootField(RexInputRef inputRef) {
-      int fieldOffset = inputRef.getIndex();
-      for (RelNode input : inputs) {
-        RelDataType rowType = input.getRowType();
-        if (rowType == null) {
-          // TODO:  remove this once leastRestrictive
-          // is correctly implemented
-          return null;
-        }
-        if (fieldOffset < rowType.getFieldCount()) {
-          return rowType.getFieldList().get(fieldOffset);
-        }
-        fieldOffset -= rowType.getFieldCount();
-      }
-      throw new AssertionError();
-    }
-
-    public void flatten(
-        List<RelNode> rels,
-        int systemFieldCount,
-        int[] start,
-        List<Pair<RelNode, Integer>> relOffsetList) {
-      for (RelNode rel : rels) {
-        if (leaves.contains(rel) || rel instanceof LogicalMatch) {
-          relOffsetList.add(
-              Pair.of(rel, start[0]));
-          start[0] += rel.getRowType().getFieldCount();
-        } else {
-          if (rel instanceof LogicalJoin
-              || rel instanceof LogicalAggregate) {
-            start[0] += systemFieldCount;
-          }
-          flatten(
-              rel.getInputs(),
-              systemFieldCount,
-              start,
-              relOffsetList);
-        }
-      }
-    }
-
-    void registerSubQuery(SqlNode node, RelOptUtil.Logic logic) {
-      for (SubQuery subQuery : subQueryList) {
-        if (node.equalsDeep(subQuery.node, Litmus.IGNORE)) {
-          return;
-        }
-      }
-      subQueryList.add(new SubQuery(node, logic));
-    }
-
-    SubQuery getSubQuery(SqlNode expr) {
-      for (SubQuery subQuery : subQueryList) {
-        if (expr.equalsDeep(subQuery.node, Litmus.IGNORE)) {
-          return subQuery;
-        }
-      }
-
-      return null;
-    }
-
-    ImmutableList<RelNode> retrieveCursors() {
-      try {
-        return ImmutableList.copyOf(cursors);
-      } finally {
-        cursors.clear();
-      }
-    }
-
-    public RexNode convertExpression(SqlNode expr) {
-      // If we're in aggregation mode and this is an expression in the
-      // GROUP BY clause, return a reference to the field.
-      if (agg != null) {
-        final SqlNode expandedGroupExpr = validator.expand(expr, scope);
-        final int ref = agg.lookupGroupExpr(expandedGroupExpr);
-        if (ref >= 0) {
-          return rexBuilder.makeInputRef(root, ref);
-        }
-        if (expr instanceof SqlCall) {
-          final RexNode rex = agg.lookupAggregates((SqlCall) expr);
-          if (rex != null) {
-            return rex;
-          }
-        }
-      }
-
-      // Allow the derived class chance to override the standard
-      // behavior for special kinds of expressions.
-      RexNode rex = convertExtendedExpression(expr, this);
-      if (rex != null) {
-        return rex;
-      }
-
-      // Sub-queries and OVER expressions are not like ordinary
-      // expressions.
-      final SqlKind kind = expr.getKind();
-      final SubQuery subQuery;
-      if (!config.isExpand()) {
-        final SqlCall call;
-        final SqlNode query;
-        final RelRoot root;
-        switch (kind) {
-        case IN:
-          call = (SqlCall) expr;
-          query = call.operand(1);
-          if (!(query instanceof SqlNodeList)) {
-            final SqlInOperator op = (SqlInOperator) call.getOperator();
-            root = convertQueryRecursive(query, false, null);
-            final SqlNode operand = call.operand(0);
-            List<SqlNode> nodes;
-            switch (operand.getKind()) {
-            case ROW:
-              nodes = ((SqlCall) operand).getOperandList();
-              break;
-            default:
-              nodes = ImmutableList.of(operand);
-            }
-            final ImmutableList.Builder<RexNode> builder =
-                ImmutableList.builder();
-            for (SqlNode node : nodes) {
-              builder.add(convertExpression(node));
-            }
-            final RexSubQuery in = RexSubQuery.in(root.rel, builder.build());
-            return op.isNotIn()
-                ? rexBuilder.makeCall(SqlStdOperatorTable.NOT, in)
-                : in;
-          }
-          break;
-
-        case EXISTS:
-          call = (SqlCall) expr;
-          query = Iterables.getOnlyElement(call.getOperandList());
-          root = convertQueryRecursive(query, false, null);
-          RelNode rel = root.rel;
-          while (rel instanceof Project
-              || rel instanceof Sort
-              && ((Sort) rel).fetch == null
-              && ((Sort) rel).offset == null) {
-            rel = ((SingleRel) rel).getInput();
-          }
-          return RexSubQuery.exists(rel);
-
-        case SCALAR_QUERY:
-          call = (SqlCall) expr;
-          query = Iterables.getOnlyElement(call.getOperandList());
-          root = convertQueryRecursive(query, false, null);
-          return RexSubQuery.scalar(root.rel);
-        }
-      }
-
-      switch (kind) {
-      case CURSOR:
-      case IN:
-        subQuery = Preconditions.checkNotNull(getSubQuery(expr));
-        rex = Preconditions.checkNotNull(subQuery.expr);
-        return StandardConvertletTable.castToValidatedType(expr, rex,
-            validator, rexBuilder);
-
-      case SELECT:
-      case EXISTS:
-      case SCALAR_QUERY:
-        subQuery = getSubQuery(expr);
-        assert subQuery != null;
-        rex = subQuery.expr;
-        assert rex != null : "rex != null";
-
-        if (((kind == SqlKind.SCALAR_QUERY)
-            || (kind == SqlKind.EXISTS))
-            && isConvertedSubq(rex)) {
-          // scalar sub-query or EXISTS has been converted to a
-          // constant
-          return rex;
-        }
-
-        // The indicator column is the last field of the sub-query.
-        RexNode fieldAccess =
-            rexBuilder.makeFieldAccess(
-                rex,
-                rex.getType().getFieldCount() - 1);
-
-        // The indicator column will be nullable if it comes from
-        // the null-generating side of the join. For EXISTS, add an
-        // "IS TRUE" check so that the result is "BOOLEAN NOT NULL".
-        if (fieldAccess.getType().isNullable()
-            && kind == SqlKind.EXISTS) {
-          fieldAccess =
-              rexBuilder.makeCall(
-                  SqlStdOperatorTable.IS_NOT_NULL,
-                  fieldAccess);
-        }
-        return fieldAccess;
-
-      case OVER:
-        return convertOver(this, expr);
-
-      default:
-        // fall through
-      }
-
-      // Apply standard conversions.
-      rex = expr.accept(this);
-      return Preconditions.checkNotNull(rex);
-    }
-
-    /**
-     * Converts an item in an ORDER BY clause, extracting DESC, NULLS LAST
-     * and NULLS FIRST flags first.
-     */
-    public RexNode convertSortExpression(SqlNode expr, Set<SqlKind> flags) {
-      switch (expr.getKind()) {
-      case DESCENDING:
-      case NULLS_LAST:
-      case NULLS_FIRST:
-        flags.add(expr.getKind());
-        final SqlNode operand = ((SqlCall) expr).operand(0);
-        return convertSortExpression(operand, flags);
-      default:
-        return convertExpression(expr);
-      }
-    }
-
-    /**
-     * Determines whether a RexNode corresponds to a sub-query that's been
-     * converted to a constant.
-     *
-     * @param rex the expression to be examined
-     * @return true if the expression is a dynamic parameter, a literal, or
-     * a literal that is being cast
-     */
-    private boolean isConvertedSubq(RexNode rex) {
-      if ((rex instanceof RexLiteral)
-          || (rex instanceof RexDynamicParam)) {
-        return true;
-      }
-      if (rex instanceof RexCall) {
-        RexCall call = (RexCall) rex;
-        if (call.getOperator() == SqlStdOperatorTable.CAST) {
-          RexNode operand = call.getOperands().get(0);
-          if (operand instanceof RexLiteral) {
-            return true;
-          }
-        }
-      }
-      return false;
-    }
-
-    public int getGroupCount() {
-      if (agg != null) {
-        return agg.groupExprs.size();
-      }
-      if (window != null) {
-        return window.isAlwaysNonEmpty() ? 1 : 0;
-      }
-      return -1;
-    }
-
-    public RexBuilder getRexBuilder() {
-      return rexBuilder;
-    }
-
-    public RexRangeRef getSubQueryExpr(SqlCall call) {
-      final SubQuery subQuery = getSubQuery(call);
-      assert subQuery != null;
-      return (RexRangeRef) subQuery.expr;
-    }
-
-    public RelDataTypeFactory getTypeFactory() {
-      return typeFactory;
-    }
-
-    public InitializerExpressionFactory getInitializerExpressionFactory() {
-      return initializerExpressionFactory;
-    }
-
-    public SqlValidator getValidator() {
-      return validator;
-    }
-
-    public RexNode convertLiteral(SqlLiteral literal) {
-      return exprConverter.convertLiteral(this, literal);
-    }
-
-    public RexNode convertInterval(SqlIntervalQualifier intervalQualifier) {
-      return exprConverter.convertInterval(this, intervalQualifier);
-    }
-
-    public RexNode visit(SqlLiteral literal) {
-      return exprConverter.convertLiteral(this, literal);
-    }
-
-    public RexNode visit(SqlCall call) {
-      if (agg != null) {
-        final SqlOperator op = call.getOperator();
-        if (window == null
-            && (op.isAggregator() || op.getKind() == SqlKind.FILTER)) {
-          return agg.lookupAggregates(call);
-        }
-      }
-      return exprConverter.convertCall(this,
-          new SqlCallBinding(validator, scope, call).permutedCall());
-    }
-
-    public RexNode visit(SqlNodeList nodeList) {
-      throw new UnsupportedOperationException();
-    }
-
-    public RexNode visit(SqlIdentifier id) {
-      return convertIdentifier(this, id);
-    }
-
-    public RexNode visit(SqlDataTypeSpec type) {
-      throw new UnsupportedOperationException();
-    }
-
-    public RexNode visit(SqlDynamicParam param) {
-      return convertDynamicParam(param);
-    }
-
-    public RexNode visit(SqlIntervalQualifier intervalQualifier) {
-      return convertInterval(intervalQualifier);
-    }
-
-    public List<SqlMonotonicity> getColumnMonotonicities() {
-      return columnMonotonicities;
-    }
-
-  }
-
-  /** Deferred lookup. */
-  private static class DeferredLookup {
-    Blackboard bb;
-    String originalRelName;
-
-    DeferredLookup(
-        Blackboard bb,
-        String originalRelName) {
-      this.bb = bb;
-      this.originalRelName = originalRelName;
-    }
-
-    public RexFieldAccess getFieldAccess(CorrelationId name) {
-      return (RexFieldAccess) bb.mapCorrelateToRex.get(name);
-    }
-
-    public String getOriginalRelName() {
-      return originalRelName;
-    }
-  }
-
-  /**
-   * A default implementation of SubQueryConverter that does no conversion.
-   */
-  private class NoOpSubQueryConverter implements SubQueryConverter {
-    public boolean canConvertSubQuery() {
-      return false;
-    }
-
-    public RexNode convertSubQuery(
-        SqlCall subQuery,
-        SqlToRelConverter parentConverter,
-        boolean isExists,
-        boolean isExplain) {
-      throw new IllegalArgumentException();
-    }
-  }
-
-  /**
-   * Converts expressions to aggregates.
-   *
-   * <p>Consider the expression
-   *
-   * <blockquote>
-   * {@code SELECT deptno, SUM(2 * sal) FROM emp GROUP BY deptno}
-   * </blockquote>
-   *
-   * <p>Then:
-   *
-   * <ul>
-   * <li>groupExprs = {SqlIdentifier(deptno)}</li>
-   * <li>convertedInputExprs = {RexInputRef(deptno), 2 *
-   * RefInputRef(sal)}</li>
-   * <li>inputRefs = {RefInputRef(#0), RexInputRef(#1)}</li>
-   * <li>aggCalls = {AggCall(SUM, {1})}</li>
-   * </ul>
-   */
-  protected class AggConverter implements SqlVisitor<Void> {
-    private final Blackboard bb;
-    public final AggregatingSelectScope aggregatingSelectScope;
-
-    private final Map<String, String> nameMap = Maps.newHashMap();
-
-    /**
-     * The group-by expressions, in {@link SqlNode} format.
-     */
-    private final SqlNodeList groupExprs =
-        new SqlNodeList(SqlParserPos.ZERO);
-
-    /**
-     * The auxiliary group-by expressions.
-     */
-    private final Map<SqlNode, Ord<AuxiliaryConverter>> auxiliaryGroupExprs =
-        new HashMap<>();
-
-    /**
-     * Input expressions for the group columns and aggregates, in
-     * {@link RexNode} format. The first elements of the list correspond to the
-     * elements in {@link #groupExprs}; the remaining elements are for
-     * aggregates. The right field of each pair is the name of the expression,
-     * where the expressions are simple mappings to input fields.
-     */
-    private final List<Pair<RexNode, String>> convertedInputExprs =
-        new ArrayList<>();
-
-    /** Expressions to be evaluated as rows are being placed into the
-     * aggregate's hash table. This is when group functions such as TUMBLE
-     * cause rows to be expanded. */
-    private final List<RexNode> midExprs = new ArrayList<>();
-
-    private final List<AggregateCall> aggCalls = new ArrayList<>();
-    private final Map<SqlNode, RexNode> aggMapping = new HashMap<>();
-    private final Map<AggregateCall, RexNode> aggCallMapping =
-        new HashMap<>();
-
-    /** Are we directly inside a windowed aggregate? */
-    private boolean inOver = false;
-
-    /**
-     * Creates an AggConverter.
-     *
-     * <p>The <code>select</code> parameter provides enough context to name
-     * aggregate calls which are top-level select list items.
-     *
-     * @param bb     Blackboard
-     * @param select Query being translated; provides context to give
-     */
-    public AggConverter(Blackboard bb, SqlSelect select) {
-      this.bb = bb;
-      this.aggregatingSelectScope =
-          (AggregatingSelectScope) bb.getValidator().getSelectScope(select);
-
-      // Collect all expressions used in the select list so that aggregate
-      // calls can be named correctly.
-      final SqlNodeList selectList = select.getSelectList();
-      for (int i = 0; i < selectList.size(); i++) {
-        SqlNode selectItem = selectList.get(i);
-        String name = null;
-        if (SqlUtil.isCallTo(
-            selectItem,
-            SqlStdOperatorTable.AS)) {
-          final SqlCall call = (SqlCall) selectItem;
-          selectItem = call.operand(0);
-          name = call.operand(1).toString();
-        }
-        if (name == null) {
-          name = validator.deriveAlias(selectItem, i);
-        }
-        nameMap.put(selectItem.toString(), name);
-      }
-    }
-
-    public int addGroupExpr(SqlNode expr) {
-      int ref = lookupGroupExpr(expr);
-      if (ref >= 0) {
-        return ref;
-      }
-      final int index = groupExprs.size();
-      groupExprs.add(expr);
-      String name = nameMap.get(expr.toString());
-      RexNode convExpr = bb.convertExpression(expr);
-      addExpr(convExpr, name);
-
-      if (expr instanceof SqlCall) {
-        SqlCall call = (SqlCall) expr;
-        for (Pair<SqlNode, AuxiliaryConverter> p
-            : SqlStdOperatorTable.convertGroupToAuxiliaryCalls(call)) {
-          addAuxiliaryGroupExpr(p.left, index, p.right);
-        }
-      }
-
-      return index;
-    }
-
-    void addAuxiliaryGroupExpr(SqlNode node, int index,
-                               AuxiliaryConverter converter) {
-      for (SqlNode node2 : auxiliaryGroupExprs.keySet()) {
-        if (node2.equalsDeep(node, Litmus.IGNORE)) {
-          return;
-        }
-      }
-      auxiliaryGroupExprs.put(node, Ord.of(index, converter));
-    }
-
-    /**
-     * Adds an expression, deducing an appropriate name if possible.
-     *
-     * @param expr Expression
-     * @param name Suggested name
-     */
-    private void addExpr(RexNode expr, String name) {
-      if ((name == null) && (expr instanceof RexInputRef)) {
-        final int i = ((RexInputRef) expr).getIndex();
-        name = bb.root.getRowType().getFieldList().get(i).getName();
-      }
-      if (Pair.right(convertedInputExprs).contains(name)) {
-        // In case like 'SELECT ... GROUP BY x, y, x', don't add
-        // name 'x' twice.
-        name = null;
-      }
-      convertedInputExprs.add(Pair.of(expr, name));
-    }
-
-    public Void visit(SqlIdentifier id) {
-      return null;
-    }
-
-    public Void visit(SqlNodeList nodeList) {
-      for (int i = 0; i < nodeList.size(); i++) {
-        nodeList.get(i).accept(this);
-      }
-      return null;
-    }
-
-    public Void visit(SqlLiteral lit) {
-      return null;
-    }
-
-    public Void visit(SqlDataTypeSpec type) {
-      return null;
-    }
-
-    public Void visit(SqlDynamicParam param) {
-      return null;
-    }
-
-    public Void visit(SqlIntervalQualifier intervalQualifier) {
-      return null;
-    }
-
-    public Void visit(SqlCall call) {
-      switch (call.getKind()) {
-      case FILTER:
-        translateAgg((SqlCall) call.operand(0), call.operand(1), call);
-        return null;
-      case SELECT:
-        // rchen 2006-10-17:
-        // for now do not detect aggregates in sub-queries.
-        return null;
-      }
-      final boolean prevInOver = inOver;
-      // Ignore window aggregates and ranking functions (associated with OVER
-      // operator). However, do not ignore nested window aggregates.
-      if (call.getOperator().getKind() == SqlKind.OVER) {
-        // Track aggregate nesting levels only within an OVER operator.
-        inOver = true;
-      }
-
-      // Do not translate the top level window aggregate. Only do so for
-      // nested aggregates, if present
-      if (call.getOperator().isAggregator()) {
-        if (inOver) {
-          // Add the parent aggregate level before visiting its children
-          inOver = false;
-        } else {
-          // We're beyond the one ignored level
-          translateAgg(call, null, call);
-          return null;
-        }
-      }
-      for (SqlNode operand : call.getOperandList()) {
-        // Operands are occasionally null, e.g. switched CASE arg 0.
-        if (operand != null) {
-          operand.accept(this);
-        }
-      }
-      // Remove the parent aggregate level after visiting its children
-      inOver = prevInOver;
-      return null;
-    }
-
-    private void translateAgg(SqlCall call, SqlNode filter, SqlCall outerCall) {
-      assert bb.agg == this;
-      final List<Integer> args = new ArrayList<>();
-      int filterArg = -1;
-      final List<RelDataType> argTypes =
-          call.getOperator() instanceof SqlCountAggFunction
-              ? new ArrayList<RelDataType>(call.getOperandList().size())
-              : null;
-      try {
-        // switch out of agg mode
-        bb.agg = null;
-        for (SqlNode operand : call.getOperandList()) {
-
-          // special case for COUNT(*):  delete the *
-          if (operand instanceof SqlIdentifier) {
-            SqlIdentifier id = (SqlIdentifier) operand;
-            if (id.isStar()) {
-              assert call.operandCount() == 1;
-              assert args.isEmpty();
-              break;
-            }
-          }
-          RexNode convertedExpr = bb.convertExpression(operand);
-          assert convertedExpr != null;
-          if (argTypes != null) {
-            argTypes.add(convertedExpr.getType());
-          }
-          args.add(lookupOrCreateGroupExpr(convertedExpr));
-        }
-
-        if (filter != null) {
-          RexNode convertedExpr = bb.convertExpression(filter);
-          assert convertedExpr != null;
-          if (convertedExpr.getType().isNullable()) {
-            convertedExpr =
-                rexBuilder.makeCall(SqlStdOperatorTable.IS_TRUE, convertedExpr);
-          }
-          filterArg = lookupOrCreateGroupExpr(convertedExpr);
-        }
-      } finally {
-        // switch back into agg mode
-        bb.agg = this;
-      }
-
-      final SqlAggFunction aggFunction =
-          (SqlAggFunction) call.getOperator();
-      RelDataType type = validator.deriveType(bb.scope, call);
-      boolean distinct = false;
-      SqlLiteral quantifier = call.getFunctionQuantifier();
-      if ((null != quantifier)
-          && (quantifier.getValue() == SqlSelectKeyword.DISTINCT)) {
-        distinct = true;
-      }
-      final AggregateCall aggCall =
-          AggregateCall.create(
-              aggFunction,
-              distinct,
-              args,
-              filterArg,
-              type,
-              nameMap.get(outerCall.toString()));
-      final AggregatingSelectScope.Resolved r =
-          aggregatingSelectScope.resolved.get();
-      RexNode rex =
-          rexBuilder.addAggCall(
-              aggCall,
-              groupExprs.size(),
-              r.indicator,
-              aggCalls,
-              aggCallMapping,
-              argTypes);
-      aggMapping.put(outerCall, rex);
-    }
-
-    /* OVERRIDE POINT */
-    private boolean isSimpleCount(SqlCall call) {
-      if (call.getOperator().isName("COUNT") && call.operandCount() == 1) {
-        final SqlNode parm = call.operand(0);
-        if ((parm instanceof SqlIdentifier || parm instanceof SqlNumericLiteral) //
-                && call.getFunctionQuantifier() == null) {
-          return true;
-        }
-      }
-      return false;
-    }
-
-    private int lookupOrCreateGroupExpr(RexNode expr) {
-      int index = 0;
-      for (RexNode convertedInputExpr : Pair.left(convertedInputExprs)) {
-        if (expr.toString().equals(convertedInputExpr.toString())) {
-          return index;
-        }
-        ++index;
-      }
-
-      // not found -- add it
-      addExpr(expr, null);
-      return index;
-    }
-
-    /**
-     * If an expression is structurally identical to one of the group-by
-     * expressions, returns a reference to the expression, otherwise returns
-     * null.
-     */
-    public int lookupGroupExpr(SqlNode expr) {
-      for (int i = 0; i < groupExprs.size(); i++) {
-        SqlNode groupExpr = groupExprs.get(i);
-        if (expr.equalsDeep(groupExpr, Litmus.IGNORE)) {
-          return i;
-        }
-      }
-      return -1;
-    }
-
-    public RexNode lookupAggregates(SqlCall call) {
-      // assert call.getOperator().isAggregator();
-      assert bb.agg == this;
-
-      switch (call.getKind()) {
-      case GROUPING:
-      case GROUP_ID:
-        final RelDataType type = validator.getValidatedNodeType(call);
-        if (!aggregatingSelectScope.resolved.get().indicator) {
-          return rexBuilder.makeExactLiteral(
-              TWO.pow(effectiveArgCount(call)).subtract(BigDecimal.ONE), type);
-        } else {
-          final List<Integer> operands;
-          switch (call.getKind()) {
-          case GROUP_ID:
-            operands = ImmutableIntList.range(0, groupExprs.size());
-            break;
-          default:
-            operands = Lists.newArrayList();
-            for (SqlNode operand : call.getOperandList()) {
-              final int x = lookupGroupExpr(operand);
-              assert x >= 0;
-              operands.add(x);
-            }
-          }
-          RexNode node = null;
-          int shift = operands.size();
-          for (int operand : operands) {
-            node = bitValue(node, type, operand, --shift);
-          }
-          return node;
-        }
-      }
-
-      for (Map.Entry<SqlNode, Ord<AuxiliaryConverter>> e
-          : auxiliaryGroupExprs.entrySet()) {
-        if (call.equalsDeep(e.getKey(), Litmus.IGNORE)) {
-          AuxiliaryConverter converter = e.getValue().e;
-          final int groupOrdinal = e.getValue().i;
-          return converter.convert(rexBuilder,
-              convertedInputExprs.get(groupOrdinal).left,
-              rexBuilder.makeInputRef(bb.root, groupOrdinal));
-        }
-      }
-
-      return aggMapping.get(call);
-    }
-
-    private int effectiveArgCount(SqlCall call) {
-      switch (call.getKind()) {
-      case GROUPING:
-        return call.operandCount();
-      case GROUP_ID:
-        return groupExprs.size();
-      default:
-        throw new AssertionError(call.getKind());
-      }
-    }
-
-    private RexNode bitValue(RexNode previous, RelDataType type, int x,
-                             int shift) {
-      final AggregatingSelectScope.Resolved r =
-          aggregatingSelectScope.resolved.get();
-      RexNode node = rexBuilder.makeCall(SqlStdOperatorTable.CASE,
-          rexBuilder.makeInputRef(bb.root, r.groupExprList.size() + x),
-          rexBuilder.makeExactLiteral(BigDecimal.ONE, type),
-          rexBuilder.makeExactLiteral(BigDecimal.ZERO, type));
-      if (shift > 0) {
-        node = rexBuilder.makeCall(SqlStdOperatorTable.MULTIPLY, node,
-            rexBuilder.makeExactLiteral(TWO.pow(shift), type));
-      }
-      if (previous != null) {
-        node = rexBuilder.makeCall(SqlStdOperatorTable.PLUS, previous, node);
-      }
-      return node;
-    }
-
-    public List<Pair<RexNode, String>> getPreExprs() {
-      return convertedInputExprs;
-    }
-
-    public List<AggregateCall> getAggCalls() {
-      return aggCalls;
-    }
-
-    public RelDataTypeFactory getTypeFactory() {
-      return typeFactory;
-    }
-  }
-
-  /**
-   * Context to find a relational expression to a field offset.
-   */
-  private static class LookupContext {
-    private final List<Pair<RelNode, Integer>> relOffsetList =
-        new ArrayList<>();
-
-    /**
-     * Creates a LookupContext with multiple input relational expressions.
-     *
-     * @param bb               Context for translating this sub-query
-     * @param rels             Relational expressions
-     * @param systemFieldCount Number of system fields
-     */
-    LookupContext(Blackboard bb, List<RelNode> rels, int systemFieldCount) {
-      bb.flatten(rels, systemFieldCount, new int[]{0}, relOffsetList);
-    }
-
-    /**
-     * Returns the relational expression with a given offset, and the
-     * ordinal in the combined row of its first field.
-     *
-     * <p>For example, in {@code Emp JOIN Dept}, findRel(1) returns the
-     * relational expression for {@code Dept} and offset 6 (because
-     * {@code Emp} has 6 fields, therefore the first field of {@code Dept}
-     * is field 6.
-     *
-     * @param offset Offset of relational expression in FROM clause
-     * @return Relational expression and the ordinal of its first field
-     */
-    Pair<RelNode, Integer> findRel(int offset) {
-      return relOffsetList.get(offset);
-    }
-  }
-
-  /**
-   * Shuttle which walks over a tree of {@link RexNode}s and applies 'over' to
-   * all agg functions.
-   *
-   * <p>This is necessary because the returned expression is not necessarily a
-   * call to an agg function. For example,
-   *
-   * <blockquote><code>AVG(x)</code></blockquote>
-   *
-   * <p>becomes
-   *
-   * <blockquote><code>SUM(x) / COUNT(x)</code></blockquote>
-   *
-   * <p>Any aggregate functions are converted to calls to the internal <code>
-   * $Histogram</code> aggregation function and accessors such as <code>
-   * $HistogramMin</code>; for example,
-   *
-   * <blockquote><code>MIN(x), MAX(x)</code></blockquote>
-   *
-   * <p>are converted to
-   *
-   * <blockquote><code>$HistogramMin($Histogram(x)),
-   * $HistogramMax($Histogram(x))</code></blockquote>
-   *
-   * <p>Common sub-expression elimination will ensure that only one histogram is
-   * computed.
-   */
-  private class HistogramShuttle extends RexShuttle {
-    /**
-     * Whether to convert calls to MIN(x) to HISTOGRAM_MIN(HISTOGRAM(x)).
-     * Histograms allow rolling computation, but require more space.
-     */
-    static final boolean ENABLE_HISTOGRAM_AGG = false;
-
-    private final List<RexNode> partitionKeys;
-    private final ImmutableList<RexFieldCollation> orderKeys;
-    private final RexWindowBound lowerBound;
-    private final RexWindowBound upperBound;
-    private final SqlWindow window;
-    private final boolean distinct;
-
-    HistogramShuttle(
-            List<RexNode> partitionKeys,
-            ImmutableList<RexFieldCollation> orderKeys,
-            RexWindowBound lowerBound, RexWindowBound upperBound,
-            SqlWindow window,
-            boolean distinct) {
-      this.partitionKeys = partitionKeys;
-      this.orderKeys = orderKeys;
-      this.lowerBound = lowerBound;
-      this.upperBound = upperBound;
-      this.window = window;
-      this.distinct = distinct;
-    }
-
-    public RexNode visitCall(RexCall call) {
-      final SqlOperator op = call.getOperator();
-      if (!(op instanceof SqlAggFunction)) {
-        return super.visitCall(call);
-      }
-      final SqlAggFunction aggOp = (SqlAggFunction) op;
-      final RelDataType type = call.getType();
-      List<RexNode> exprs = call.getOperands();
-
-      SqlFunction histogramOp = !ENABLE_HISTOGRAM_AGG
-          ? null
-          : getHistogramOp(aggOp);
-
-      if (histogramOp != null) {
-        final RelDataType histogramType = computeHistogramType(type);
-
-        // For DECIMAL, since it's already represented as a bigint we
-        // want to do a reinterpretCast instead of a cast to avoid
-        // losing any precision.
-        boolean reinterpretCast =
-            type.getSqlTypeName() == SqlTypeName.DECIMAL;
-
-        // Replace original expression with CAST of not one
-        // of the supported types
-        if (histogramType != type) {
-          exprs = new ArrayList<>(exprs);
-          exprs.set(
-              0,
-              reinterpretCast
-              ? rexBuilder.makeReinterpretCast(histogramType, exprs.get(0),
-                  rexBuilder.makeLiteral(false))
-              : rexBuilder.makeCast(histogramType, exprs.get(0)));
-        }
-
-        RexCallBinding bind =
-            new RexCallBinding(
-                rexBuilder.getTypeFactory(),
-                SqlStdOperatorTable.HISTOGRAM_AGG,
-                exprs,
-                ImmutableList.<RelCollation>of());
-
-        RexNode over =
-            rexBuilder.makeOver(
-                SqlStdOperatorTable.HISTOGRAM_AGG
-                    .inferReturnType(bind),
-                SqlStdOperatorTable.HISTOGRAM_AGG,
-                exprs,
-                partitionKeys,
-                orderKeys,
-                lowerBound,
-                upperBound,
-                window.isRows(),
-                window.isAllowPartial(),
-                false,
-                distinct);
-
-        RexNode histogramCall =
-            rexBuilder.makeCall(
-                histogramType,
-                histogramOp,
-                ImmutableList.of(over));
-
-        // If needed, post Cast result back to original
-        // type.
-        if (histogramType != type) {
-          if (reinterpretCast) {
-            histogramCall =
-                rexBuilder.makeReinterpretCast(
-                    type,
-                    histogramCall,
-                    rexBuilder.makeLiteral(false));
-          } else {
-            histogramCall =
-                rexBuilder.makeCast(type, histogramCall);
-          }
-        }
-
-        return histogramCall;
-      } else {
-        boolean needSum0 = aggOp == SqlStdOperatorTable.SUM
-            && type.isNullable();
-        SqlAggFunction aggOpToUse =
-            needSum0 ? SqlStdOperatorTable.SUM0
-                : aggOp;
-        return rexBuilder.makeOver(
-            type,
-            aggOpToUse,
-            exprs,
-            partitionKeys,
-            orderKeys,
-            lowerBound,
-            upperBound,
-            window.isRows(),
-            window.isAllowPartial(),
-            needSum0,
-            distinct);
-      }
-    }
-
-    /**
-     * Returns the histogram operator corresponding to a given aggregate
-     * function.
-     *
-     * <p>For example, <code>getHistogramOp
-     *({@link SqlStdOperatorTable#MIN}}</code> returns
-     * {@link SqlStdOperatorTable#HISTOGRAM_MIN}.
-     *
-     * @param aggFunction An aggregate function
-     * @return Its histogram function, or null
-     */
-    SqlFunction getHistogramOp(SqlAggFunction aggFunction) {
-      if (aggFunction == SqlStdOperatorTable.MIN) {
-        return SqlStdOperatorTable.HISTOGRAM_MIN;
-      } else if (aggFunction == SqlStdOperatorTable.MAX) {
-        return SqlStdOperatorTable.HISTOGRAM_MAX;
-      } else if (aggFunction == SqlStdOperatorTable.FIRST_VALUE) {
-        return SqlStdOperatorTable.HISTOGRAM_FIRST_VALUE;
-      } else if (aggFunction == SqlStdOperatorTable.LAST_VALUE) {
-        return SqlStdOperatorTable.HISTOGRAM_LAST_VALUE;
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Returns the type for a histogram function. It is either the actual
-     * type or an an approximation to it.
-     */
-    private RelDataType computeHistogramType(RelDataType type) {
-      if (SqlTypeUtil.isExactNumeric(type)
-          && type.getSqlTypeName() != SqlTypeName.BIGINT) {
-        return typeFactory.createSqlType(SqlTypeName.BIGINT);
-      } else if (SqlTypeUtil.isApproximateNumeric(type)
-          && type.getSqlTypeName() != SqlTypeName.DOUBLE) {
-        return typeFactory.createSqlType(SqlTypeName.DOUBLE);
-      } else {
-        return type;
-      }
-    }
-  }
-
-  /** A sub-query, whether it needs to be translated using 2- or 3-valued
-   * logic. */
-  private static class SubQuery {
-    final SqlNode node;
-    final RelOptUtil.Logic logic;
-    RexNode expr;
-
-    private SubQuery(SqlNode node, RelOptUtil.Logic logic) {
-      this.node = node;
-      this.logic = logic;
-    }
-  }
-
-  /**
-   * Visitor that collects all aggregate functions in a {@link SqlNode} tree.
-   */
-  private static class AggregateFinder extends SqlBasicVisitor<Void> {
-    final SqlNodeList list = new SqlNodeList(SqlParserPos.ZERO);
-
-    @Override public Void visit(SqlCall call) {
-      // ignore window aggregates and ranking functions (associated with OVER operator)
-      if (call.getOperator().getKind() == SqlKind.OVER) {
-        return null;
-      }
-      if (call.getOperator().isAggregator()) {
-        list.add(call);
-        return null;
-      }
-
-      // Don't traverse into sub-queries, even if they contain aggregate
-      // functions.
-      if (call instanceof SqlSelect) {
-        return null;
-      }
-
-      return call.getOperator().acceptCall(this, call);
-    }
-  }
-
-  /** Use of a row as a correlating variable by a given relational
-   * expression. */
-  private static class CorrelationUse {
-    private final CorrelationId id;
-    private final ImmutableBitSet requiredColumns;
-    private final RelNode r;
-
-    CorrelationUse(CorrelationId id, ImmutableBitSet requiredColumns,
-                   RelNode r) {
-      this.id = id;
-      this.requiredColumns = requiredColumns;
-      this.r = r;
-    }
-  }
-
-  /** Creates a builder for a {@link Config}. */
-  public static ConfigBuilder configBuilder() {
-    return new ConfigBuilder();
-  }
-
-  /**
-   * Interface to define the configuration for a SqlToRelConverter.
-   * Provides methods to set each configuration option.
-   *
-   * @see ConfigBuilder
-   * @see SqlToRelConverter#configBuilder()
-   */
-  public interface Config {
-    /** Default configuration. */
-    Config DEFAULT = configBuilder().build();
-
-    /** Returns the {@code convertTableAccess} option. Controls whether table
-     * access references are converted to physical rels immediately. The
-     * optimizer doesn't like leaf rels to have {@link Convention#NONE}.
-     * However, if we are doing further conversion passes (e.g.
-     * {@link RelStructuredTypeFlattener}), then we may need to defer
-     * conversion. */
-    boolean isConvertTableAccess();
-
-    /** Returns the {@code decorrelationEnabled} option. Controls whether to
-     * disable sub-query decorrelation when needed. e.g. if outer joins are not
-     * supported. */
-    boolean isDecorrelationEnabled();
-
-    /** Returns the {@code trimUnusedFields} option. Controls whether to trim
-     * unused fields as part of the conversion process. */
-    boolean isTrimUnusedFields();
-
-    /** Returns the {@code createValuesRel} option. Controls whether instances
-     * of {@link org.apache.calcite.rel.logical.LogicalValues} are generated.
-     * These may not be supported by all physical implementations. */
-    boolean isCreateValuesRel();
-
-    /** Returns the {@code explain} option. Describes whether the current
-     * statement is part of an EXPLAIN PLAN statement. */
-    boolean isExplain();
-
-    /** Returns the {@code expand} option. Controls whether to expand
-     * sub-queries. If false, each sub-query becomes a
-     * {@link org.apache.calcite.rex.RexSubQuery}. */
-    boolean isExpand();
-
-    /** Returns the {@code inSubQueryThreshold} option,
-     * default {@link #DEFAULT_IN_SUB_QUERY_THRESHOLD}. Controls 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 {@link Integer#MAX_VALUE} forces usage of OR in all
-     * cases. */
-    int getInSubQueryThreshold();
-  }
-
-  /** Builder for a {@link Config}. */
-  public static class ConfigBuilder {
-    private boolean convertTableAccess = true;
-    private boolean decorrelationEnabled = true;
-    private boolean trimUnusedFields = false;
-    private boolean createValuesRel = true;
-    private boolean explain;
-    private boolean expand = true;
-    private int inSubQueryThreshold = DEFAULT_IN_SUB_QUERY_THRESHOLD;
-
-    private ConfigBuilder() {}
-
-    /** Sets configuration identical to a given {@link Config}. */
-    public ConfigBuilder withConfig(Config config) {
-      this.convertTableAccess = config.isConvertTableAccess();
-      this.decorrelationEnabled = config.isDecorrelationEnabled();
-      this.trimUnusedFields = config.isTrimUnusedFields();
-      this.createValuesRel = config.isCreateValuesRel();
-      this.explain = config.isExplain();
-      this.expand = config.isExpand();
-      this.inSubQueryThreshold = config.getInSubQueryThreshold();
-      return this;
-    }
-
-    public ConfigBuilder withConvertTableAccess(boolean convertTableAccess) {
-      this.convertTableAccess = convertTableAccess;
-      return this;
-    }
-
-    public ConfigBuilder withDecorrelationEnabled(boolean enabled) {
-      this.decorrelationEnabled = enabled;
-      return this;
-    }
-
-    public ConfigBuilder withTrimUnusedFields(boolean trimUnusedFields) {
-      this.trimUnusedFields = trimUnusedFields;
-      return this;
-    }
-
-    public ConfigBuilder withCreateValuesRel(boolean createValuesRel) {
-      this.createValuesRel = createValuesRel;
-      return this;
-    }
-
-    public ConfigBuilder withExplain(boolean explain) {
-      this.explain = explain;
-      return this;
-    }
-
-    public ConfigBuilder withExpand(boolean expand) {
-      this.expand = expand;
-      return this;
-    }
-
-    @Deprecated // to be removed before 2.0
-    public ConfigBuilder withInSubqueryThreshold(int inSubQueryThreshold) {
-      return withInSubQueryThreshold(inSubQueryThreshold);
-    }
-
-    public ConfigBuilder withInSubQueryThreshold(int inSubQueryThreshold) {
-      this.inSubQueryThreshold = inSubQueryThreshold;
-      return this;
-    }
-
-    /** Builds a {@link Config}. */
-    public Config build() {
-      return new ConfigImpl(convertTableAccess, decorrelationEnabled,
-          trimUnusedFields, createValuesRel, explain, expand,
-          inSubQueryThreshold);
-    }
-  }
-
-  /** Implementation of {@link Config}.
-   * Called by builder; all values are in private final fields. */
-  private static class ConfigImpl implements Config {
-    private final boolean convertTableAccess;
-    private final boolean decorrelationEnabled;
-    private final boolean trimUnusedFields;
-    private final boolean createValuesRel;
-    private final boolean explain;
-    private final int inSubQueryThreshold;
-    private final boolean expand;
-
-    private ConfigImpl(boolean convertTableAccess, boolean decorrelationEnabled,
-        boolean trimUnusedFields, boolean createValuesRel, boolean explain,
-        boolean expand, int inSubQueryThreshold) {
-      this.convertTableAccess = convertTableAccess;
-      this.decorrelationEnabled = decorrelationEnabled;
-      this.trimUnusedFields = trimUnusedFields;
-      this.createValuesRel = createValuesRel;
-      this.explain = explain;
-      this.expand = expand;
-      this.inSubQueryThreshold = inSubQueryThreshold;
-    }
-
-    public boolean isConvertTableAccess() {
-      return convertTableAccess;
-    }
-
-    public boolean isDecorrelationEnabled() {
-      return decorrelationEnabled;
-    }
-
-    public boolean isTrimUnusedFields() {
-      return trimUnusedFields;
-    }
-
-    public boolean isCreateValuesRel() {
-      return createValuesRel;
-    }
-
-    public boolean isExplain() {
-      return explain;
-    }
-
-    public boolean isExpand() {
-      return expand;
-    }
-
-    public int getInSubQueryThreshold() {
-      return inSubQueryThreshold;
-    }
-  }
-}
-
-// End SqlToRelConverter.java
diff --git a/atopcalcite/src/main/java/org/apache/calcite/tools/Programs.java b/atopcalcite/src/main/java/org/apache/calcite/tools/Programs.java
deleted file mode 100644
index 663a82cdcd..0000000000
--- a/atopcalcite/src/main/java/org/apache/calcite/tools/Programs.java
+++ /dev/null
@@ -1,438 +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.tools;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.apache.calcite.adapter.enumerable.EnumerableRules;
-import org.apache.calcite.config.CalciteConnectionConfig;
-import org.apache.calcite.interpreter.NoneToBindableConverterRule;
-import org.apache.calcite.plan.RelOptCostImpl;
-import org.apache.calcite.plan.RelOptLattice;
-import org.apache.calcite.plan.RelOptMaterialization;
-import org.apache.calcite.plan.RelOptPlanner;
-import org.apache.calcite.plan.RelOptRule;
-import org.apache.calcite.plan.RelOptUtil;
-import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.plan.hep.HepMatchOrder;
-import org.apache.calcite.plan.hep.HepPlanner;
-import org.apache.calcite.plan.hep.HepProgram;
-import org.apache.calcite.plan.hep.HepProgramBuilder;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.core.Calc;
-import org.apache.calcite.rel.core.RelFactories;
-import org.apache.calcite.rel.metadata.ChainedRelMetadataProvider;
-import org.apache.calcite.rel.metadata.DefaultRelMetadataProvider;
-import org.apache.calcite.rel.metadata.RelMetadataProvider;
-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.CalcMergeRule;
-import org.apache.calcite.rel.rules.FilterAggregateTransposeRule;
-import org.apache.calcite.rel.rules.FilterCalcMergeRule;
-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.FilterToCalcRule;
-import org.apache.calcite.rel.rules.JoinAssociateRule;
-import org.apache.calcite.rel.rules.JoinCommuteRule;
-import org.apache.calcite.rel.rules.JoinPushThroughJoinRule;
-import org.apache.calcite.rel.rules.JoinToMultiJoinRule;
-import org.apache.calcite.rel.rules.LoptOptimizeJoinRule;
-import org.apache.calcite.rel.rules.MultiJoinOptimizeBushyRule;
-import org.apache.calcite.rel.rules.OLAPJoinPushThroughJoinRule;
-import org.apache.calcite.rel.rules.OLAPJoinPushThroughJoinRule2;
-import org.apache.calcite.rel.rules.ProjectCalcMergeRule;
-import org.apache.calcite.rel.rules.ProjectMergeRule;
-import org.apache.calcite.rel.rules.ProjectToCalcRule;
-import org.apache.calcite.rel.rules.SemiJoinRule;
-import org.apache.calcite.rel.rules.SortProjectTransposeRule;
-import org.apache.calcite.rel.rules.SubQueryRemoveRule;
-import org.apache.calcite.rel.rules.TableScanRule;
-import org.apache.calcite.sql2rel.RelDecorrelator;
-import org.apache.calcite.sql2rel.RelFieldTrimmer;
-import org.apache.calcite.sql2rel.SqlToRelConverter;
-
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-
-/*
- * The code has synced with calcite. Hope one day, we could remove the hardcode override point.
- * OVERRIDE POINT:
- * - add OLAPJoinPushThroughJoinRule OLAPJoinPushThroughJoinRule2 to org.apache.calcite.tools.Programs#subQuery
- */
-
-/**
- * Utilities for creating {@link Program}s.
- */
-public class Programs {
-  private static final Function<RuleSet, Program> RULE_SET_TO_PROGRAM =
-      new Function<RuleSet, Program>() {
-        public Program apply(RuleSet ruleSet) {
-          return of(ruleSet);
-        }
-      };
-
-  public static final ImmutableList<RelOptRule> CALC_RULES =
-      ImmutableList.of(
-          NoneToBindableConverterRule.INSTANCE,
-          EnumerableRules.ENUMERABLE_CALC_RULE,
-          EnumerableRules.ENUMERABLE_FILTER_TO_CALC_RULE,
-          EnumerableRules.ENUMERABLE_PROJECT_TO_CALC_RULE,
-          CalcMergeRule.INSTANCE,
-          FilterCalcMergeRule.INSTANCE,
-          ProjectCalcMergeRule.INSTANCE,
-          FilterToCalcRule.INSTANCE,
-          ProjectToCalcRule.INSTANCE,
-          CalcMergeRule.INSTANCE,
-
-          // REVIEW jvs 9-Apr-2006: Do we still need these two?  Doesn't the
-          // combination of CalcMergeRule, FilterToCalcRule, and
-          // ProjectToCalcRule have the same effect?
-          FilterCalcMergeRule.INSTANCE,
-          ProjectCalcMergeRule.INSTANCE);
-
-  /** Program that converts filters and projects to {@link Calc}s. */
-  public static final Program CALC_PROGRAM =
-      calc(DefaultRelMetadataProvider.INSTANCE);
-
-  /** Program that expands sub-queries. */
-  public static final Program SUB_QUERY_PROGRAM =
-      subQuery(DefaultRelMetadataProvider.INSTANCE);
-
-  public static final ImmutableSet<RelOptRule> RULE_SET =
-      ImmutableSet.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_UNION_RULE,
-          EnumerableRules.ENUMERABLE_INTERSECT_RULE,
-          EnumerableRules.ENUMERABLE_MINUS_RULE,
-          EnumerableRules.ENUMERABLE_TABLE_MODIFICATION_RULE,
-          EnumerableRules.ENUMERABLE_VALUES_RULE,
-          EnumerableRules.ENUMERABLE_WINDOW_RULE,
-          SemiJoinRule.PROJECT,
-          SemiJoinRule.JOIN,
-          TableScanRule.INSTANCE,
-          CalcitePrepareImpl.COMMUTE
-              ? JoinAssociateRule.INSTANCE
-              : ProjectMergeRule.INSTANCE,
-          AggregateStarTableRule.INSTANCE,
-          AggregateStarTableRule.INSTANCE2,
-          FilterTableScanRule.INSTANCE,
-          FilterProjectTransposeRule.INSTANCE,
-          FilterJoinRule.FILTER_ON_JOIN,
-          AggregateExpandDistinctAggregatesRule.INSTANCE,
-          AggregateReduceFunctionsRule.INSTANCE,
-          FilterAggregateTransposeRule.INSTANCE,
-          JoinCommuteRule.INSTANCE,
-          JoinPushThroughJoinRule.RIGHT,
-          JoinPushThroughJoinRule.LEFT,
-          SortProjectTransposeRule.INSTANCE);
-
-  // private constructor for utility class
-  private Programs() {}
-
-  /** Creates a program that executes a rule set. */
-  public static Program of(RuleSet ruleSet) {
-    return new RuleSetProgram(ruleSet);
-  }
-
-  /** Creates a list of programs based on an array of rule sets. */
-  public static List<Program> listOf(RuleSet... ruleSets) {
-    return Lists.transform(Arrays.asList(ruleSets), RULE_SET_TO_PROGRAM);
-  }
-
-  /** Creates a list of programs based on a list of rule sets. */
-  public static List<Program> listOf(List<RuleSet> ruleSets) {
-    return Lists.transform(ruleSets, RULE_SET_TO_PROGRAM);
-  }
-
-  /** Creates a program from a list of rules. */
-  public static Program ofRules(RelOptRule... rules) {
-    return of(RuleSets.ofList(rules));
-  }
-
-  /** Creates a program from a list of rules. */
-  public static Program ofRules(Iterable<? extends RelOptRule> rules) {
-    return of(RuleSets.ofList(rules));
-  }
-
-  /** Creates a program that executes a sequence of programs. */
-  public static Program sequence(Program... programs) {
-    return new SequenceProgram(ImmutableList.copyOf(programs));
-  }
-
-  /** Creates a program that executes a list of rules in a HEP planner. */
-  public static Program hep(Iterable<? extends RelOptRule> rules,
-                            boolean noDag, RelMetadataProvider metadataProvider) {
-    final HepProgramBuilder builder = HepProgram.builder();
-    for (RelOptRule rule : rules) {
-      builder.addRuleInstance(rule);
-    }
-    return of(builder.build(), noDag, metadataProvider);
-  }
-
-  /** Creates a program that executes a {@link HepProgram}. */
-  public static Program of(final HepProgram hepProgram, final boolean noDag,
-                           final RelMetadataProvider metadataProvider) {
-    return new Program() {
-      public RelNode run(RelOptPlanner planner, RelNode rel,
-                         RelTraitSet requiredOutputTraits,
-                         List<RelOptMaterialization> materializations,
-                         List<RelOptLattice> lattices) {
-        final HepPlanner hepPlanner = new HepPlanner(hepProgram,
-            null, noDag, null, RelOptCostImpl.FACTORY);
-
-        List<RelMetadataProvider> list = Lists.newArrayList();
-        if (metadataProvider != null) {
-          list.add(metadataProvider);
-        }
-        hepPlanner.registerMetadataProviders(list);
-        RelMetadataProvider plannerChain =
-            ChainedRelMetadataProvider.of(list);
-        rel.getCluster().setMetadataProvider(plannerChain);
-
-        hepPlanner.setRoot(rel);
-        return hepPlanner.findBestExp();
-      }
-    };
-  }
-
-  /** Creates a program that invokes heuristic join-order optimization
-   * (via {@link org.apache.calcite.rel.rules.JoinToMultiJoinRule},
-   * {@link org.apache.calcite.rel.rules.MultiJoin} and
-   * {@link org.apache.calcite.rel.rules.LoptOptimizeJoinRule})
-   * if there are 6 or more joins (7 or more relations). */
-  public static Program heuristicJoinOrder(
-      final Iterable<? extends RelOptRule> rules,
-      final boolean bushy, final int minJoinCount) {
-    return new Program() {
-      public RelNode run(RelOptPlanner planner, RelNode rel,
-                         RelTraitSet requiredOutputTraits,
-                         List<RelOptMaterialization> materializations,
-                         List<RelOptLattice> lattices) {
-        final int joinCount = RelOptUtil.countJoins(rel);
-        final Program program;
-        if (joinCount < minJoinCount) {
-          program = ofRules(rules);
-        } else {
-          // Create a program that gathers together joins as a MultiJoin.
-          final HepProgram hep = new HepProgramBuilder()
-              .addRuleInstance(FilterJoinRule.FILTER_ON_JOIN)
-              .addMatchOrder(HepMatchOrder.BOTTOM_UP)
-              .addRuleInstance(JoinToMultiJoinRule.INSTANCE)
-              .build();
-          final Program program1 =
-              of(hep, false, DefaultRelMetadataProvider.INSTANCE);
-
-          // Create a program that contains a rule to expand a MultiJoin
-          // into heuristically ordered joins.
-          // We use the rule set passed in, but remove JoinCommuteRule and
-          // JoinPushThroughJoinRule, because they cause exhaustive search.
-          final List<RelOptRule> list = Lists.newArrayList(rules);
-          list.removeAll(
-              ImmutableList.of(JoinCommuteRule.INSTANCE,
-                  JoinAssociateRule.INSTANCE,
-                  JoinPushThroughJoinRule.LEFT,
-                  JoinPushThroughJoinRule.RIGHT));
-          list.add(bushy
-              ? MultiJoinOptimizeBushyRule.INSTANCE
-              : LoptOptimizeJoinRule.INSTANCE);
-          final Program program2 = ofRules(list);
-
-          program = sequence(program1, program2);
-        }
-        return program.run(
-            planner, rel, requiredOutputTraits, materializations, lattices);
-      }
-    };
-  }
-
-  public static Program calc(RelMetadataProvider metadataProvider) {
-    return hep(CALC_RULES, true, metadataProvider);
-  }
-
-  @Deprecated // to be removed before 2.0
-  public static Program subquery(RelMetadataProvider metadataProvider) {
-    return subQuery(metadataProvider);
-  }
-
-  public static Program subQuery(RelMetadataProvider metadataProvider) {
-    return hep(
-        ImmutableList.of((RelOptRule) SubQueryRemoveRule.FILTER,
-            SubQueryRemoveRule.PROJECT,
-            SubQueryRemoveRule.JOIN, OLAPJoinPushThroughJoinRule.INSTANCE,
-            OLAPJoinPushThroughJoinRule2.INSTANCE), true, metadataProvider);
-  }
-
-  public static Program getProgram() {
-    return new Program() {
-      public RelNode run(RelOptPlanner planner, RelNode rel,
-                         RelTraitSet requiredOutputTraits,
-                         List<RelOptMaterialization> materializations,
-                         List<RelOptLattice> lattices) {
-        return null;
-      }
-    };
-  }
-
-  /** Returns the standard program used by Prepare. */
-  public static Program standard() {
-    return standard(DefaultRelMetadataProvider.INSTANCE);
-  }
-
-  /** Returns the standard program with user metadata provider. */
-  public static Program standard(RelMetadataProvider metadataProvider) {
-
-    final Program program1 =
-        new Program() {
-          public RelNode run(RelOptPlanner planner, RelNode rel,
-                             RelTraitSet requiredOutputTraits,
-                             List<RelOptMaterialization> materializations,
-                             List<RelOptLattice> lattices) {
-            planner.setRoot(rel);
-
-            for (RelOptMaterialization materialization : materializations) {
-              planner.addMaterialization(materialization);
-            }
-            for (RelOptLattice lattice : lattices) {
-              planner.addLattice(lattice);
-            }
-
-            final RelNode rootRel2 =
-                rel.getTraitSet().equals(requiredOutputTraits)
-                ? rel
-                : planner.changeTraits(rel, requiredOutputTraits);
-            assert rootRel2 != null;
-
-            planner.setRoot(rootRel2);
-            final RelOptPlanner planner2 = planner.chooseDelegate();
-            final RelNode rootRel3 = planner2.findBestExp();
-            assert rootRel3 != null : "could not implement exp";
-            return rootRel3;
-          }
-        };
-
-    return sequence(subQuery(metadataProvider),
-        new DecorrelateProgram(),
-        new TrimFieldsProgram(),
-        program1,
-
-        // Second planner pass to do physical "tweaks". This the first time that
-        // EnumerableCalcRel is introduced.
-        calc(metadataProvider));
-  }
-
-  /** Program backed by a {@link RuleSet}. */
-  static class RuleSetProgram implements Program {
-    final RuleSet ruleSet;
-
-    private RuleSetProgram(RuleSet ruleSet) {
-      this.ruleSet = ruleSet;
-    }
-
-    public RelNode run(RelOptPlanner planner, RelNode rel,
-                       RelTraitSet requiredOutputTraits,
-                       List<RelOptMaterialization> materializations,
-                       List<RelOptLattice> lattices) {
-      planner.clear();
-      for (RelOptRule rule : ruleSet) {
-        planner.addRule(rule);
-      }
-      for (RelOptMaterialization materialization : materializations) {
-        planner.addMaterialization(materialization);
-      }
-      for (RelOptLattice lattice : lattices) {
-        planner.addLattice(lattice);
-      }
-      if (!rel.getTraitSet().equals(requiredOutputTraits)) {
-        rel = planner.changeTraits(rel, requiredOutputTraits);
-      }
-      planner.setRoot(rel);
-      return planner.findBestExp();
-
-    }
-  }
-
-  /** Program that runs sub-programs, sending the output of the previous as
-   * input to the next. */
-  private static class SequenceProgram implements Program {
-    private final ImmutableList<Program> programs;
-
-    SequenceProgram(ImmutableList<Program> programs) {
-      this.programs = programs;
-    }
-
-    public RelNode run(RelOptPlanner planner, RelNode rel,
-                       RelTraitSet requiredOutputTraits,
-                       List<RelOptMaterialization> materializations,
-                       List<RelOptLattice> lattices) {
-      for (Program program : programs) {
-        rel = program.run(
-            planner, rel, requiredOutputTraits, materializations, lattices);
-      }
-      return rel;
-    }
-  }
-
-  /** Program that de-correlates a query.
-   *
-   * <p>To work around
-   * <a href="https://issues.apache.org/jira/browse/CALCITE-842">[CALCITE-842]
-   * Decorrelator gets field offsets confused if fields have been trimmed</a>,
-   * disable field-trimming in {@link SqlToRelConverter}, and run
-   * {@link TrimFieldsProgram} after this program. */
-  private static class DecorrelateProgram implements Program {
-    public RelNode run(RelOptPlanner planner, RelNode rel,
-                       RelTraitSet requiredOutputTraits,
-                       List<RelOptMaterialization> materializations,
-                       List<RelOptLattice> lattices) {
-      final CalciteConnectionConfig config =
-          planner.getContext().unwrap(CalciteConnectionConfig.class);
-      if (config != null && config.forceDecorrelate()) {
-        return RelDecorrelator.decorrelateQuery(rel);
-      }
-      return rel;
-    }
-  }
-
-  /** Program that trims fields. */
-  private static class TrimFieldsProgram implements Program {
-    public RelNode run(RelOptPlanner planner, RelNode rel,
-                       RelTraitSet requiredOutputTraits,
-                       List<RelOptMaterialization> materializations,
-                       List<RelOptLattice> lattices) {
-      final RelBuilder relBuilder =
-          RelFactories.LOGICAL_BUILDER.create(rel.getCluster(), null);
-      return new RelFieldTrimmer(null, relBuilder).trim(rel);
-    }
-  }
-}
-
-// End Programs.java
diff --git a/atopcalcite/src/main/java/org/apache/calcite/tools/RelUtils.java b/atopcalcite/src/main/java/org/apache/calcite/tools/RelUtils.java
deleted file mode 100644
index 68ad5cd1a4..0000000000
--- a/atopcalcite/src/main/java/org/apache/calcite/tools/RelUtils.java
+++ /dev/null
@@ -1,71 +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.tools;
-
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rex.RexCall;
-import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.rex.RexVisitor;
-import org.apache.calcite.rex.RexVisitorImpl;
-import org.apache.calcite.sql.SqlOperator;
-
-import com.google.common.collect.Lists;
-
-public class RelUtils {
-    public static boolean findOLAPRel(RelNode rel) {
-        Class aClass;
-        try {
-            aClass = Thread.currentThread().getContextClassLoader().loadClass("org.apache.kylin.query.relnode.OLAPRel");
-        } catch (ClassNotFoundException e) {
-            return false;
-        }
-        return findRel(rel, Lists.newArrayList(aClass)) != null;
-    }
-
-    private static RelNode findRel(RelNode rel, List<Class> candidate) {
-        for (Class clazz : candidate) {
-            if (clazz.isInstance(rel)) {
-                return rel;
-            }
-        }
-
-        if (rel.getInputs().size() < 1) {
-            return null;
-        }
-
-        return findRel(rel.getInput(0), candidate);
-    }
-
-    public static int countOperatorCall(final SqlOperator operator, RexNode node) {
-        final AtomicInteger atomicInteger = new AtomicInteger(0);
-        RexVisitor<Void> visitor = new RexVisitorImpl<Void>(true) {
-            public Void visitCall(RexCall call) {
-                if (call.getOperator().equals(operator)) {
-                    atomicInteger.incrementAndGet();
-                }
-                return super.visitCall(call);
-            }
-        };
-        node.accept(visitor);
-        return atomicInteger.get();
-    }
-}
diff --git a/atopcalcite/src/test/java/org/apache/calcite/runtime/SqlFunctionsTest.java b/atopcalcite/src/test/java/org/apache/calcite/runtime/SqlFunctionsTest.java
deleted file mode 100644
index 07e54df161..0000000000
--- a/atopcalcite/src/test/java/org/apache/calcite/runtime/SqlFunctionsTest.java
+++ /dev/null
@@ -1,38 +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 static org.apache.calcite.avatica.util.DateTimeUtils.ymdToUnixDate;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-public class SqlFunctionsTest {
-    @Test
-    public void testAddMonth() {
-        // normal add
-        Assert.assertEquals(ymdToUnixDate(2011, 5, 10), SqlFunctions.addMonths(ymdToUnixDate(2011, 4, 10), 1));
-        Assert.assertEquals(ymdToUnixDate(2013, 5, 10), SqlFunctions.addMonths(ymdToUnixDate(2011, 4, 10), 25));
-
-        // special case
-        Assert.assertEquals(ymdToUnixDate(2011, 2, 28), SqlFunctions.addMonths(ymdToUnixDate(2011, 1, 31), 1));
-        Assert.assertEquals(ymdToUnixDate(2012, 2, 29), SqlFunctions.addMonths(ymdToUnixDate(2012, 1, 31), 1));
-        Assert.assertEquals(ymdToUnixDate(2014, 2, 28), SqlFunctions.addMonths(ymdToUnixDate(2012, 3, 31), 23));
-    }
-}
diff --git a/core-cube/src/main/java/org/apache/kylin/cube/CubeCapabilityChecker.java b/core-cube/src/main/java/org/apache/kylin/cube/CubeCapabilityChecker.java
index 49ce4f502f..d05a7a3a19 100644
--- a/core-cube/src/main/java/org/apache/kylin/cube/CubeCapabilityChecker.java
+++ b/core-cube/src/main/java/org/apache/kylin/cube/CubeCapabilityChecker.java
@@ -24,6 +24,7 @@
 import java.util.List;
 import java.util.Set;
 
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.kylin.cube.model.CubeDesc;
 import org.apache.kylin.measure.MeasureType;
@@ -71,6 +72,7 @@ public static CapabilityResult check(CubeInstance cube, SQLDigest digest) {
             //1. dimension as measure
 
             if (!unmatchedAggregations.isEmpty()) {
+                removeUnmatchedGroupingAgg(unmatchedAggregations);
                 tryDimensionAsMeasures(unmatchedAggregations, result,
                         cube.getDescriptor().listDimensionColumnsIncludingDerived());
             }
@@ -264,4 +266,15 @@ private static void tryCustomMeasureTypes(Collection<TblColRef> unmatchedDimensi
                     StringUtils.join(influencingMeasures, ","));
     }
 
+    private static void removeUnmatchedGroupingAgg(Collection<FunctionDesc> unmatchedAggregations) {
+        if (CollectionUtils.isEmpty(unmatchedAggregations))
+            return;
+        Iterator<FunctionDesc> iterator = unmatchedAggregations.iterator();
+        while (iterator.hasNext()) {
+            if (FunctionDesc.FUNC_GROUPING.equalsIgnoreCase(iterator.next().getExpression())) {
+                iterator.remove();
+            }
+        }
+    }
+
 }
diff --git a/core-metadata/pom.xml b/core-metadata/pom.xml
index 6accda35b9..6ba698c129 100644
--- a/core-metadata/pom.xml
+++ b/core-metadata/pom.xml
@@ -60,8 +60,19 @@
             <artifactId>jsr305</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.apache.kylin</groupId>
-            <artifactId>atopcalcite</artifactId>
+            <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>
             <exclusions>
                 <exclusion>
                     <groupId>org.apache.calcite.avatica</groupId>
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/FunctionDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/FunctionDesc.java
index c0d54ae913..72d956a359 100644
--- a/core-metadata/src/main/java/org/apache/kylin/metadata/model/FunctionDesc.java
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/FunctionDesc.java
@@ -60,6 +60,7 @@ public static FunctionDesc newInstance(String expression, ParameterDesc param, S
     public static final String FUNC_MAX = "MAX";
     public static final String FUNC_COUNT = "COUNT";
     public static final String FUNC_COUNT_DISTINCT = "COUNT_DISTINCT";
+    public static final String FUNC_GROUPING = "GROUPING";
     public static final String FUNC_PERCENTILE = "PERCENTILE_APPROX";
     public static final Set<String> BUILT_IN_AGGREGATIONS = Sets.newHashSet();
 
diff --git a/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/GTCubeStorageQueryBase.java b/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/GTCubeStorageQueryBase.java
index 07d241fe23..68c4113793 100644
--- a/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/GTCubeStorageQueryBase.java
+++ b/core-storage/src/main/java/org/apache/kylin/storage/gtrecord/GTCubeStorageQueryBase.java
@@ -209,7 +209,7 @@ protected ITupleConverter newCubeTupleConverter(CubeSegment cubeSeg, Cuboid cubo
     protected void buildDimensionsAndMetrics(SQLDigest sqlDigest, Collection<TblColRef> dimensions,
             Collection<FunctionDesc> metrics) {
         for (FunctionDesc func : sqlDigest.aggregations) {
-            if (!func.isDimensionAsMetric()) {
+            if (!func.isDimensionAsMetric() && !FunctionDesc.FUNC_GROUPING.equalsIgnoreCase(func.getExpression())) {
                 // use the FunctionDesc from cube desc as much as possible, that has more info such as HLLC precision
                 metrics.add(findAggrFuncFromCubeDesc(func));
             }
diff --git a/kylin-it/pom.xml b/kylin-it/pom.xml
index cce101949a..15ee8467a8 100644
--- a/kylin-it/pom.xml
+++ b/kylin-it/pom.xml
@@ -42,12 +42,23 @@
     <!-- Dependencies. -->
     <dependencies>
         <dependency>
-            <groupId>org.apache.kylin</groupId>
-            <artifactId>atopcalcite</artifactId>
+            <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>
+            <exclusions>
+                <exclusion>
                     <groupId>org.apache.calcite.avatica</groupId>
+                    <artifactId>avatica-core</artifactId>
                 </exclusion>
             </exclusions>
         </dependency>
diff --git a/pom.xml b/pom.xml
index aa0ca0c79e..f0ee6489d6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -72,7 +72,7 @@
     <!-- <reflections.version>0.9.10</reflections.version> -->
 
     <!-- Calcite Version -->
-    <calcite.version>1.13.0-kylin-r4</calcite.version>
+    <calcite.version>1.16.0-kylin-r2-SNAPSHOT</calcite.version>
     <avatica.version>1.10.0</avatica.version>
 
     <!-- Hadoop Common deps, keep compatible with hadoop2.version -->
@@ -641,6 +641,11 @@
         <artifactId>jackson-annotations</artifactId>
         <version>${jackson.version}</version>
       </dependency>
+      <dependency>
+        <groupId>com.fasterxml.jackson.dataformat</groupId>
+        <artifactId>jackson-dataformat-xml</artifactId>
+        <version>${jackson.version}</version>
+      </dependency>
 
       <!-- Spark dependency -->
       <dependency>
@@ -1238,7 +1243,6 @@
   </build>
 
   <modules>
-    <module>atopcalcite</module>
     <module>core-common</module>
     <module>core-metadata</module>
     <module>core-dictionary</module>
diff --git a/query/pom.xml b/query/pom.xml
index 94999ef3c0..03c2014dce 100644
--- a/query/pom.xml
+++ b/query/pom.xml
@@ -33,8 +33,19 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.kylin</groupId>
-            <artifactId>atopcalcite</artifactId>
+            <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>
             <exclusions>
                 <exclusion>
                     <groupId>org.apache.calcite.avatica</groupId>
diff --git a/query/src/main/java/org/apache/kylin/query/optrule/AggregateMultipleExpandRule.java b/query/src/main/java/org/apache/kylin/query/optrule/AggregateMultipleExpandRule.java
index 39c90e8674..7dedcf7553 100644
--- a/query/src/main/java/org/apache/kylin/query/optrule/AggregateMultipleExpandRule.java
+++ b/query/src/main/java/org/apache/kylin/query/optrule/AggregateMultipleExpandRule.java
@@ -106,23 +106,6 @@ public void onMatch(RelOptRuleCall call) {
                 }
             }
 
-            // fill indicators if need, false when key is present and true if key is rolled up
-            if (aggr.indicator) {
-                groupSetIter = aggr.getGroupSet().iterator();
-                groupKeyIter = groupSet.iterator();
-                groupKey = groupKeyIter.next();
-                while (groupSetIter.hasNext()) {
-                    Integer aggrGroupKey = groupSetIter.next();
-                    RelDataType type = typeIterator.next().getType();
-                    if (groupKey == aggrGroupKey) {
-                        rexNodes.add(rexBuilder.makeLiteral(false, type, true));
-                        groupKey = groupKeyIter.next();
-                    } else {
-                        rexNodes.add(rexBuilder.makeLiteral(true, type, true));
-                    }
-                }
-            }
-
             // fill aggr calls input ref
             while (typeIterator.hasNext()) {
                 RelDataType type = typeIterator.next().getType();
diff --git a/query/src/main/java/org/apache/kylin/query/relnode/OLAPAggregateRel.java b/query/src/main/java/org/apache/kylin/query/relnode/OLAPAggregateRel.java
index ab8be1b8f1..fb64c565d7 100644
--- a/query/src/main/java/org/apache/kylin/query/relnode/OLAPAggregateRel.java
+++ b/query/src/main/java/org/apache/kylin/query/relnode/OLAPAggregateRel.java
@@ -99,6 +99,7 @@
         AGGR_FUNC_MAP.put("COUNT_DISTINCT", "COUNT_DISTINCT");
         AGGR_FUNC_MAP.put("MAX", "MAX");
         AGGR_FUNC_MAP.put("MIN", "MIN");
+        AGGR_FUNC_MAP.put("GROUPING", "GROUPING");
 
         Map<String, MeasureTypeFactory> udafFactories = MeasureTypeFactory.getUDAFFactories();
         for (Map.Entry<String, MeasureTypeFactory> entry : udafFactories.entrySet()) {
@@ -410,6 +411,11 @@ public void implementRewrite(RewriteImplementor implementor) {
             for (int i = 0; i < this.aggCalls.size(); i++) {
                 AggregateCall aggCall = this.hackAggCalls.get(i) != null ? this.hackAggCalls.get(i)
                         : this.aggCalls.get(i);
+                if (SqlStdOperatorTable.GROUPING == aggCall.getAggregation()) {
+                    this.rewriteAggCalls.add(aggCall);
+                    continue;
+                }
+
                 FunctionDesc cubeFunc = this.context.aggregations.get(i);
                 // filter needn,t rewrite aggfunc
                 // if it's not a cube, then the "needRewriteField func" should not resort to any rewrite fields,
@@ -593,7 +599,8 @@ SqlAggFunction createCustomAggFunction(String funcName, RelDataType returnType,
             typeFamilies.add(Util.first(type.getSqlTypeName().getFamily(), SqlTypeFamily.ANY));
         }
         return new SqlUserDefinedAggFunction(sqlIdentifier, ReturnTypes.explicit(returnType),
-                InferTypes.explicit(argTypes), OperandTypes.family(typeFamilies), aggFunction, false, false);
+                InferTypes.explicit(argTypes), OperandTypes.family(typeFamilies), aggFunction, false, false,
+                typeFactory);
     }
 
     @Override
diff --git a/query/src/main/java/org/apache/kylin/query/relnode/visitor/TupleExpressionVisitor.java b/query/src/main/java/org/apache/kylin/query/relnode/visitor/TupleExpressionVisitor.java
index d0ad23aac7..03b58dc9b1 100644
--- a/query/src/main/java/org/apache/kylin/query/relnode/visitor/TupleExpressionVisitor.java
+++ b/query/src/main/java/org/apache/kylin/query/relnode/visitor/TupleExpressionVisitor.java
@@ -28,7 +28,6 @@
 import org.apache.calcite.rex.RexVisitorImpl;
 import org.apache.calcite.sql.SqlOperator;
 import org.apache.calcite.sql.fun.SqlCastFunction;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.validate.SqlUserDefinedFunction;
 import org.apache.calcite.util.NlsString;
 import org.apache.kylin.common.util.Pair;
@@ -61,9 +60,7 @@ public TupleExpressionVisitor(ColumnRowType inputRowType, boolean ifVerify) {
     @Override
     public TupleExpression visitCall(RexCall call) {
         SqlOperator op = call.getOperator();
-        if (op == SqlStdOperatorTable.EXTRACT_DATE) {
-            return visitFirstRexInputRef(call);
-        } else if (op instanceof SqlCastFunction) {
+        if (op instanceof SqlCastFunction) {
             return call.getOperands().get(0).accept(this);
         } else if (op instanceof SqlUserDefinedFunction) {
             if (op.getName().equals("QUARTER")) {


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services