[Enhancement][Refactor](Nereids) generate pattern by operator and refactor Plan and NODE_TYPE generic type (#10019)

This pr support
1. remove the generic type from operator, remove some NODE_TYPE from plan and expression
2. refactor Plan and NODE_TYPE generic type
3. support child class matching by TypePattern
4. analyze the code of operator and generate pattern makes it easy to create rules.


e.g. 
```java
class LogicalJoin extends LogicalBinaryOperator;
class PhysicalFilter extends PhysicalUnaryOperator;
```

will generate the code
```java
interface GeneratedPatterns extends Patterns {
  default PatternDescriptor<LogicalBinaryPlan<LogicalJoin, Plan, Plan>, Plan> logicalJoin() {
      return new PatternDescriptor<LogicalBinaryPlan<LogicalJoin, Plan, Plan>, Plan>(
          new TypePattern(LogicalJoin.class, Pattern.FIXED, Pattern.FIXED),
          defaultPromise()
      );
  }
  
  default <C1 extends Plan, C2 extends Plan>
  PatternDescriptor<LogicalBinaryPlan<LogicalJoin, C1, C2>, Plan>
          logicalJoin(PatternDescriptor<C1, Plan> child1, PatternDescriptor<C2, Plan> child2) {
      return new PatternDescriptor<LogicalBinaryPlan<LogicalJoin, C1, C2>, Plan>(
          new TypePattern(LogicalJoin.class, child1.pattern, child2.pattern),
          defaultPromise()
      );
  }

  default PatternDescriptor<PhysicalUnaryPlan<PhysicalFilter, Plan>, Plan> physicalFilter() {
      return new PatternDescriptor<PhysicalUnaryPlan<PhysicalFilter, Plan>, Plan>(
          new TypePattern(PhysicalFilter.class, Pattern.FIXED),
          defaultPromise()
      );
  }
  
  default <C1 extends Plan>
  PatternDescriptor<PhysicalUnaryPlan<PhysicalFilter, C1>, Plan>
          physicalFilter(PatternDescriptor<C1, Plan> child1) {
      return new PatternDescriptor<PhysicalUnaryPlan<PhysicalFilter, C1>, Plan>(
          new TypePattern(PhysicalFilter.class, child1.pattern),
          defaultPromise()
      );
  }
}
```
and then we don't have to add pattern for new operators.

this function utilizing jsr269 to do something in compile time, and utilizing antlr4 to analyze the code of `Operator`, then we can generate corresponding pattern.


pattern generate steps:
1. maven-compiler-plugin in the pom.xml will compile fe-core three terms. first term will compile `PatternDescribable.java` and `PatternDescribableProcessor.java`
2. second compile term will compile `PatternDescribableProcessPoint.java`, and enable annotation process `PatternDescribableProcessor`, PatternDescribableProcessor will receive the event and know that `PatternDescribableProcessPoint` class contains the `PatternDescribable` annotation.
3. `PatternDescribableProcessor` will not process `PatternDescribableProcessPoint`, but find all java file exists in `operatorPath` that specify in pom.xml, and then parse to Java AST(abstract syntax tree).
5. PatternDescribableProcessor collect java AST and use `PatternGeneratorAnalyzer` to analyze AST, find the child class file for `PlanOperator` then generate `GeneratedPatterns.java` by the AST.
6. third compile term will compile `GeneratedPatterns.java` and other java file.
This commit is contained in:
924060929
2022-06-15 11:44:54 +08:00
committed by GitHub
parent c9f33fa051
commit 76a968d1dd
134 changed files with 4369 additions and 720 deletions

View File

@ -0,0 +1,241 @@
/*
[The "BSD licence"]
Copyright (c) 2013 Terence Parr, Sam Harwell
Copyright (c) 2017 Ivan Kochurkin (upgrade to Java 8)
Copyright (c) 2021 Michał Lorek (upgrade to Java 11)
Copyright (c) 2022 Michał Lorek (upgrade to Java 17)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
lexer grammar JavaLexer;
// Keywords
ABSTRACT: 'abstract';
ASSERT: 'assert';
BOOLEAN: 'boolean';
BREAK: 'break';
BYTE: 'byte';
CASE: 'case';
CATCH: 'catch';
CHAR: 'char';
CLASS: 'class';
CONST: 'const';
CONTINUE: 'continue';
DEFAULT: 'default';
DO: 'do';
DOUBLE: 'double';
ELSE: 'else';
ENUM: 'enum';
EXTENDS: 'extends';
FINAL: 'final';
FINALLY: 'finally';
FLOAT: 'float';
FOR: 'for';
IF: 'if';
GOTO: 'goto';
IMPLEMENTS: 'implements';
IMPORT: 'import';
INSTANCEOF: 'instanceof';
INT: 'int';
INTERFACE: 'interface';
LONG: 'long';
NATIVE: 'native';
NEW: 'new';
PACKAGE: 'package';
PRIVATE: 'private';
PROTECTED: 'protected';
PUBLIC: 'public';
RETURN: 'return';
SHORT: 'short';
STATIC: 'static';
STRICTFP: 'strictfp';
SUPER: 'super';
SWITCH: 'switch';
SYNCHRONIZED: 'synchronized';
THIS: 'this';
THROW: 'throw';
THROWS: 'throws';
TRANSIENT: 'transient';
TRY: 'try';
VOID: 'void';
VOLATILE: 'volatile';
WHILE: 'while';
// Module related keywords
MODULE: 'module';
OPEN: 'open';
REQUIRES: 'requires';
EXPORTS: 'exports';
OPENS: 'opens';
TO: 'to';
USES: 'uses';
PROVIDES: 'provides';
WITH: 'with';
TRANSITIVE: 'transitive';
// Local Variable Type Inference
VAR: 'var'; // reserved type name
// Switch Expressions
YIELD: 'yield';
// Records
RECORD: 'record';
// Sealed Classes
SEALED: 'sealed';
PERMITS: 'permits';
NON_SEALED: 'non-sealed';
// Literals
DECIMAL_LITERAL: ('0' | [1-9] (Digits? | '_'+ Digits)) [lL]?;
HEX_LITERAL: '0' [xX] [0-9a-fA-F] ([0-9a-fA-F_]* [0-9a-fA-F])? [lL]?;
OCT_LITERAL: '0' '_'* [0-7] ([0-7_]* [0-7])? [lL]?;
BINARY_LITERAL: '0' [bB] [01] ([01_]* [01])? [lL]?;
FLOAT_LITERAL: (Digits '.' Digits? | '.' Digits) ExponentPart? [fFdD]?
| Digits (ExponentPart [fFdD]? | [fFdD])
;
HEX_FLOAT_LITERAL: '0' [xX] (HexDigits '.'? | HexDigits? '.' HexDigits) [pP] [+-]? Digits [fFdD]?;
BOOL_LITERAL: 'true'
| 'false'
;
CHAR_LITERAL: '\'' (~['\\\r\n] | EscapeSequence) '\'';
STRING_LITERAL: '"' (~["\\\r\n] | EscapeSequence)* '"';
TEXT_BLOCK: '"""' [ \t]* [\r\n] (. | EscapeSequence)*? '"""';
NULL_LITERAL: 'null';
// Separators
LPAREN: '(';
RPAREN: ')';
LBRACE: '{';
RBRACE: '}';
LBRACK: '[';
RBRACK: ']';
SEMI: ';';
COMMA: ',';
DOT: '.';
// Operators
ASSIGN: '=';
GT: '>';
LT: '<';
BANG: '!';
TILDE: '~';
QUESTION: '?';
COLON: ':';
EQUAL: '==';
LE: '<=';
GE: '>=';
NOTEQUAL: '!=';
AND: '&&';
OR: '||';
INC: '++';
DEC: '--';
ADD: '+';
SUB: '-';
MUL: '*';
DIV: '/';
BITAND: '&';
BITOR: '|';
CARET: '^';
MOD: '%';
ADD_ASSIGN: '+=';
SUB_ASSIGN: '-=';
MUL_ASSIGN: '*=';
DIV_ASSIGN: '/=';
AND_ASSIGN: '&=';
OR_ASSIGN: '|=';
XOR_ASSIGN: '^=';
MOD_ASSIGN: '%=';
LSHIFT_ASSIGN: '<<=';
RSHIFT_ASSIGN: '>>=';
URSHIFT_ASSIGN: '>>>=';
// Java 8 tokens
ARROW: '->';
COLONCOLON: '::';
// Additional symbols not defined in the lexical specification
AT: '@';
ELLIPSIS: '...';
// Whitespace and comments
WS: [ \t\r\n\u000C]+ -> channel(HIDDEN);
COMMENT: '/*' .*? '*/' -> channel(HIDDEN);
LINE_COMMENT: '//' ~[\r\n]* -> channel(HIDDEN);
// Identifiers
IDENTIFIER: Letter LetterOrDigit*;
// Fragment rules
fragment ExponentPart
: [eE] [+-]? Digits
;
fragment EscapeSequence
: '\\' [btnfr"'\\]
| '\\' ([0-3]? [0-7])? [0-7]
| '\\' 'u'+ HexDigit HexDigit HexDigit HexDigit
;
fragment HexDigits
: HexDigit ((HexDigit | '_')* HexDigit)?
;
fragment HexDigit
: [0-9a-fA-F]
;
fragment Digits
: [0-9] ([0-9_]* [0-9])?
;
fragment LetterOrDigit
: Letter
| [0-9]
;
fragment Letter
: [a-zA-Z$_] // these are the "java letters" below 0x7F
| ~[\u0000-\u007F\uD800-\uDBFF] // covers all characters above 0x7F which are not a surrogate
| [\uD800-\uDBFF] [\uDC00-\uDFFF] // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
;

View File

@ -0,0 +1,762 @@
/*
[The "BSD licence"]
Copyright (c) 2013 Terence Parr, Sam Harwell
Copyright (c) 2017 Ivan Kochurkin (upgrade to Java 8)
Copyright (c) 2021 Michał Lorek (upgrade to Java 11)
Copyright (c) 2022 Michał Lorek (upgrade to Java 17)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
parser grammar JavaParser;
options { tokenVocab=JavaLexer; }
compilationUnit
: packageDeclaration? importDeclaration* typeDeclaration*
| moduleDeclaration EOF
;
packageDeclaration
: annotation* PACKAGE qualifiedName ';'
;
importDeclaration
: IMPORT STATIC? qualifiedName importStar? ';'
;
importStar
: '.' '*'
;
typeDeclaration
: classOrInterfaceModifier*
(classDeclaration | enumDeclaration | interfaceDeclaration | annotationTypeDeclaration | recordDeclaration)
| ';'
;
modifier
: classOrInterfaceModifier
| NATIVE
| SYNCHRONIZED
| TRANSIENT
| VOLATILE
;
classOrInterfaceModifier
: annotation
| PUBLIC
| PROTECTED
| PRIVATE
| STATIC
| ABSTRACT
| FINAL // FINAL for class only -- does not apply to interfaces
| STRICTFP
| SEALED // Java17
| NON_SEALED // Java17
;
variableModifier
: FINAL
| annotation
;
classDeclaration
: CLASS identifier typeParameters?
(EXTENDS typeType)?
(IMPLEMENTS typeList)?
(PERMITS typeList)? // Java17
classBody
;
typeParameters
: '<' typeParameter (',' typeParameter)* '>'
;
typeParameter
: annotation* identifier (EXTENDS annotation* typeBound)?
;
typeBound
: typeType ('&' typeType)*
;
enumDeclaration
: ENUM identifier (IMPLEMENTS typeList)? '{' enumConstants? ','? enumBodyDeclarations? '}'
;
enumConstants
: enumConstant (',' enumConstant)*
;
enumConstant
: annotation* identifier arguments? classBody?
;
enumBodyDeclarations
: ';' classBodyDeclaration*
;
interfaceDeclaration
: INTERFACE identifier typeParameters? (EXTENDS typeList)? (PERMITS typeList)? interfaceBody
;
classBody
: '{' classBodyDeclaration* '}'
;
interfaceBody
: '{' interfaceBodyDeclaration* '}'
;
classBodyDeclaration
: ';'
| STATIC? block
| modifier* memberDeclaration
;
memberDeclaration
: methodDeclaration
| genericMethodDeclaration
| fieldDeclaration
| constructorDeclaration
| genericConstructorDeclaration
| interfaceDeclaration
| annotationTypeDeclaration
| classDeclaration
| enumDeclaration
| recordDeclaration //Java17
;
/* We use rule this even for void methods which cannot have [] after parameters.
This simplifies grammar and we can consider void to be a type, which
renders the [] matching as a context-sensitive issue or a semantic check
for invalid return type after parsing.
*/
methodDeclaration
: typeTypeOrVoid identifier formalParameters ('[' ']')*
(THROWS qualifiedNameList)?
methodBody
;
methodBody
: block
| ';'
;
typeTypeOrVoid
: typeType
| VOID
;
genericMethodDeclaration
: typeParameters methodDeclaration
;
genericConstructorDeclaration
: typeParameters constructorDeclaration
;
constructorDeclaration
: identifier formalParameters (THROWS qualifiedNameList)? constructorBody=block
;
fieldDeclaration
: typeType variableDeclarators ';'
;
interfaceBodyDeclaration
: modifier* interfaceMemberDeclaration
| ';'
;
interfaceMemberDeclaration
: constDeclaration
| interfaceMethodDeclaration
| genericInterfaceMethodDeclaration
| interfaceDeclaration
| annotationTypeDeclaration
| classDeclaration
| enumDeclaration
| recordDeclaration // Java17
;
constDeclaration
: typeType constantDeclarator (',' constantDeclarator)* ';'
;
constantDeclarator
: identifier ('[' ']')* '=' variableInitializer
;
// Early versions of Java allows brackets after the method name, eg.
// public int[] return2DArray() [] { ... }
// is the same as
// public int[][] return2DArray() { ... }
interfaceMethodDeclaration
: interfaceMethodModifier* interfaceCommonBodyDeclaration
;
// Java8
interfaceMethodModifier
: annotation
| PUBLIC
| ABSTRACT
| DEFAULT
| STATIC
| STRICTFP
;
genericInterfaceMethodDeclaration
: interfaceMethodModifier* typeParameters interfaceCommonBodyDeclaration
;
interfaceCommonBodyDeclaration
: annotation* typeTypeOrVoid identifier formalParameters ('[' ']')* (THROWS qualifiedNameList)? methodBody
;
variableDeclarators
: variableDeclarator (',' variableDeclarator)*
;
variableDeclarator
: variableDeclaratorId ('=' variableInitializer)?
;
variableDeclaratorId
: identifier arrayDeclarator*
;
arrayDeclarator
: '[' ']'
;
variableInitializer
: arrayInitializer
| expression
;
arrayInitializer
: '{' (variableInitializer (',' variableInitializer)* (',')? )? '}'
;
classOrInterfaceType
: identifierAndTypeArguments ('.' identifierAndTypeArguments)*
;
identifierAndTypeArguments
: identifier typeArguments?
;
typeArgument
: typeType
| annotation* '?' ((EXTENDS | SUPER) typeType)?
;
qualifiedNameList
: qualifiedName (',' qualifiedName)*
;
formalParameters
: '(' ( receiverParameter?
| receiverParameter (',' formalParameterList)?
| formalParameterList?
) ')'
;
receiverParameter
: typeType (identifier '.')* THIS
;
formalParameterList
: formalParameter (',' formalParameter)* (',' lastFormalParameter)?
| lastFormalParameter
;
formalParameter
: variableModifier* typeType variableDeclaratorId
;
lastFormalParameter
: variableModifier* typeType annotation* '...' variableDeclaratorId
;
// local variable type inference
lambdaLVTIList
: lambdaLVTIParameter (',' lambdaLVTIParameter)*
;
lambdaLVTIParameter
: variableModifier* VAR identifier
;
qualifiedName
: identifier ('.' identifier)*
;
literal
: integerLiteral
| floatLiteral
| CHAR_LITERAL
| STRING_LITERAL
| BOOL_LITERAL
| NULL_LITERAL
| TEXT_BLOCK // Java17
;
integerLiteral
: DECIMAL_LITERAL
| HEX_LITERAL
| OCT_LITERAL
| BINARY_LITERAL
;
floatLiteral
: FLOAT_LITERAL
| HEX_FLOAT_LITERAL
;
// ANNOTATIONS
altAnnotationQualifiedName
: (identifier DOT)* '@' identifier
;
annotation
: ('@' qualifiedName | altAnnotationQualifiedName) ('(' ( elementValuePairs | elementValue )? ')')?
;
elementValuePairs
: elementValuePair (',' elementValuePair)*
;
elementValuePair
: identifier '=' elementValue
;
elementValue
: expression
| annotation
| elementValueArrayInitializer
;
elementValueArrayInitializer
: '{' (elementValue (',' elementValue)*)? (',')? '}'
;
annotationTypeDeclaration
: '@' INTERFACE identifier annotationTypeBody
;
annotationTypeBody
: '{' (annotationTypeElementDeclaration)* '}'
;
annotationTypeElementDeclaration
: modifier* annotationTypeElementRest
| ';' // this is not allowed by the grammar, but apparently allowed by the actual compiler
;
annotationTypeElementRest
: typeType annotationMethodOrConstantRest ';'
| classDeclaration ';'?
| interfaceDeclaration ';'?
| enumDeclaration ';'?
| annotationTypeDeclaration ';'?
| recordDeclaration ';'? // Java17
;
annotationMethodOrConstantRest
: annotationMethodRest
| annotationConstantRest
;
annotationMethodRest
: identifier '(' ')' defaultValue?
;
annotationConstantRest
: variableDeclarators
;
defaultValue
: DEFAULT elementValue
;
// MODULES - Java9
moduleDeclaration
: OPEN? MODULE qualifiedName moduleBody
;
moduleBody
: '{' moduleDirective* '}'
;
moduleDirective
: REQUIRES requiresModifier* qualifiedName ';'
| EXPORTS qualifiedName (TO qualifiedName)? ';'
| OPENS qualifiedName (TO qualifiedName)? ';'
| USES qualifiedName ';'
| PROVIDES qualifiedName WITH qualifiedName ';'
;
requiresModifier
: TRANSITIVE
| STATIC
;
// RECORDS - Java 17
recordDeclaration
: RECORD identifier typeParameters? recordHeader
(IMPLEMENTS typeList)?
recordBody
;
recordHeader
: '(' recordComponentList? ')'
;
recordComponentList
: recordComponent (',' recordComponent)*
;
recordComponent
: typeType identifier
;
recordBody
: '{' classBodyDeclaration* '}'
;
// STATEMENTS / BLOCKS
block
: '{' blockStatement* '}'
;
blockStatement
: localVariableDeclaration ';'
| statement
| localTypeDeclaration
;
localVariableDeclaration
: variableModifier* (typeType variableDeclarators | VAR identifier '=' expression)
;
identifier
: IDENTIFIER
| MODULE
| OPEN
| REQUIRES
| EXPORTS
| OPENS
| TO
| USES
| PROVIDES
| WITH
| TRANSITIVE
| YIELD
| SEALED
| PERMITS
| RECORD
| VAR
;
localTypeDeclaration
: classOrInterfaceModifier*
(classDeclaration | interfaceDeclaration | recordDeclaration)
| ';'
;
statement
: blockLabel=block
| ASSERT expression (':' expression)? ';'
| IF parExpression statement (ELSE statement)?
| FOR '(' forControl ')' statement
| WHILE parExpression statement
| DO statement WHILE parExpression ';'
| TRY block (catchClause+ finallyBlock? | finallyBlock)
| TRY resourceSpecification block catchClause* finallyBlock?
| SWITCH parExpression '{' switchBlockStatementGroup* switchLabel* '}'
| SYNCHRONIZED parExpression block
| RETURN expression? ';'
| THROW expression ';'
| BREAK identifier? ';'
| CONTINUE identifier? ';'
| YIELD expression ';' // Java17
| SEMI
| statementExpression=expression ';'
| switchExpression ';'? // Java17
| identifierLabel=identifier ':' statement
;
catchClause
: CATCH '(' variableModifier* catchType identifier ')' block
;
catchType
: qualifiedName ('|' qualifiedName)*
;
finallyBlock
: FINALLY block
;
resourceSpecification
: '(' resources ';'? ')'
;
resources
: resource (';' resource)*
;
resource
: variableModifier* ( classOrInterfaceType variableDeclaratorId | VAR identifier ) '=' expression
| identifier
;
/** Matches cases then statements, both of which are mandatory.
* To handle empty cases at the end, we add switchLabel* to statement.
*/
switchBlockStatementGroup
: switchLabel+ blockStatement+
;
switchLabel
: CASE (constantExpression=expression | enumConstantName=IDENTIFIER | typeType varName=identifier) ':'
| DEFAULT ':'
;
forControl
: enhancedForControl
| forInit? ';' expression? ';' forUpdate=expressionList?
;
forInit
: localVariableDeclaration
| expressionList
;
enhancedForControl
: variableModifier* (typeType | VAR) variableDeclaratorId ':' expression
;
// EXPRESSIONS
parExpression
: '(' expression ')'
;
expressionList
: expression (',' expression)*
;
methodCall
: identifier '(' expressionList? ')'
| THIS '(' expressionList? ')'
| SUPER '(' expressionList? ')'
;
expression
: primary
| expression bop='.'
(
identifier
| methodCall
| THIS
| NEW nonWildcardTypeArguments? innerCreator
| SUPER superSuffix
| explicitGenericInvocation
)
| expression '[' expression ']'
| methodCall
| NEW creator
| '(' annotation* typeType ('&' typeType)* ')' expression
| expression postfix=('++' | '--')
| prefix=('+'|'-'|'++'|'--') expression
| prefix=('~'|'!') expression
| expression bop=('*'|'/'|'%') expression
| expression bop=('+'|'-') expression
| expression ('<' '<' | '>' '>' '>' | '>' '>') expression
| expression bop=('<=' | '>=' | '>' | '<') expression
| expression bop=INSTANCEOF (typeType | pattern)
| expression bop=('==' | '!=') expression
| expression bop='&' expression
| expression bop='^' expression
| expression bop='|' expression
| expression bop='&&' expression
| expression bop='||' expression
| <assoc=right> expression bop='?' expression ':' expression
| <assoc=right> expression
bop=('=' | '+=' | '-=' | '*=' | '/=' | '&=' | '|=' | '^=' | '>>=' | '>>>=' | '<<=' | '%=')
expression
| lambdaExpression // Java8
| switchExpression // Java17
// Java 8 methodReference
| expression '::' typeArguments? identifier
| typeType '::' (typeArguments? identifier | NEW)
| classType '::' typeArguments? NEW
;
// Java17
pattern
: variableModifier* typeType annotation* identifier
;
// Java8
lambdaExpression
: lambdaParameters '->' lambdaBody
;
// Java8
lambdaParameters
: identifier
| '(' formalParameterList? ')'
| '(' identifier (',' identifier)* ')'
| '(' lambdaLVTIList? ')'
;
// Java8
lambdaBody
: expression
| block
;
primary
: '(' expression ')'
| THIS
| SUPER
| literal
| identifier
| typeTypeOrVoid '.' CLASS
| nonWildcardTypeArguments (explicitGenericInvocationSuffix | THIS arguments)
;
// Java17
switchExpression
: SWITCH parExpression '{' switchLabeledRule* '}'
;
// Java17
switchLabeledRule
: CASE (expressionList | NULL_LITERAL | guardedPattern) (ARROW | COLON) switchRuleOutcome
| DEFAULT (ARROW | COLON) switchRuleOutcome
;
// Java17
guardedPattern
: '(' guardedPattern ')'
| variableModifier* typeType annotation* identifier ('&&' expression)*
| guardedPattern '&&' expression
;
// Java17
switchRuleOutcome
: block
| blockStatement*
;
classType
: (classOrInterfaceType '.')? annotation* identifier typeArguments?
;
creator
: nonWildcardTypeArguments createdName classCreatorRest
| createdName (arrayCreatorRest | classCreatorRest)
;
createdName
: identifier typeArgumentsOrDiamond? ('.' identifier typeArgumentsOrDiamond?)*
| primitiveType
;
innerCreator
: identifier nonWildcardTypeArgumentsOrDiamond? classCreatorRest
;
arrayCreatorRest
: '[' (']' ('[' ']')* arrayInitializer | expression ']' ('[' expression ']')* ('[' ']')*)
;
classCreatorRest
: arguments classBody?
;
explicitGenericInvocation
: nonWildcardTypeArguments explicitGenericInvocationSuffix
;
typeArgumentsOrDiamond
: '<' '>'
| typeArguments
;
nonWildcardTypeArgumentsOrDiamond
: '<' '>'
| nonWildcardTypeArguments
;
nonWildcardTypeArguments
: '<' typeList '>'
;
typeList
: typeType (',' typeType)*
;
typeType
: annotation* (classOrInterfaceType | primitiveType) (annotation* '[' ']')*
;
primitiveType
: BOOLEAN
| CHAR
| BYTE
| SHORT
| INT
| LONG
| FLOAT
| DOUBLE
;
typeArguments
: '<' typeArgument (',' typeArgument)* '>'
;
superSuffix
: arguments
| '.' typeArguments? identifier arguments?
;
explicitGenericInvocationSuffix
: SUPER superSuffix
| identifier arguments
;
arguments
: '(' expressionList? ')'
;

View File

@ -29,7 +29,7 @@ import org.apache.doris.nereids.trees.TreeNode;
/**
* Context used in memo.
*/
public class OptimizerContext<NODE_TYPE extends TreeNode> {
public class OptimizerContext<NODE_TYPE extends TreeNode<NODE_TYPE>> {
private final Memo<NODE_TYPE> memo;
private RuleSet ruleSet;
private JobPool jobPool;

View File

@ -17,7 +17,6 @@
package org.apache.doris.nereids;
import org.apache.doris.nereids.operators.Operator;
import org.apache.doris.nereids.operators.plans.physical.PhysicalAggregation;
import org.apache.doris.nereids.operators.plans.physical.PhysicalFilter;
import org.apache.doris.nereids.operators.plans.physical.PhysicalHashJoin;
@ -25,7 +24,9 @@ import org.apache.doris.nereids.operators.plans.physical.PhysicalOlapScan;
import org.apache.doris.nereids.operators.plans.physical.PhysicalProject;
import org.apache.doris.nereids.operators.plans.physical.PhysicalSort;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalPlan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalBinaryPlan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalLeafPlan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalUnaryPlan;
/**
* Base class for the processing of logical and physical plan.
@ -36,35 +37,29 @@ import org.apache.doris.nereids.trees.plans.physical.PhysicalPlan;
@SuppressWarnings("rawtypes")
public abstract class PlanOperatorVisitor<R, C> {
public abstract R visit(Plan<? extends Plan, ? extends Operator> plan, C context);
public abstract R visit(Plan plan, C context);
public R visitPhysicalAggregationPlan(PhysicalPlan<? extends PhysicalPlan, PhysicalAggregation> aggPlan,
C context) {
public R visitPhysicalAggregationPlan(PhysicalUnaryPlan<PhysicalAggregation, Plan> aggPlan, C context) {
return null;
}
public R visitPhysicalOlapScanPlan(PhysicalPlan<? extends PhysicalPlan, PhysicalOlapScan> olapScanPlan,
C context) {
public R visitPhysicalOlapScanPlan(PhysicalLeafPlan<PhysicalOlapScan> olapScanPlan, C context) {
return null;
}
public R visitPhysicalSortPlan(PhysicalPlan<? extends PhysicalPlan, PhysicalSort> sortPlan,
C context) {
public R visitPhysicalSortPlan(PhysicalUnaryPlan<PhysicalSort, Plan> sortPlan, C context) {
return null;
}
public R visitPhysicalHashJoinPlan(PhysicalPlan<? extends PhysicalPlan, PhysicalHashJoin> hashJoinPlan,
C context) {
public R visitPhysicalHashJoinPlan(PhysicalBinaryPlan<PhysicalHashJoin, Plan, Plan> hashJoinPlan, C context) {
return null;
}
public R visitPhysicalProject(PhysicalPlan<? extends PhysicalPlan, PhysicalProject> projectPlan,
C context) {
public R visitPhysicalProject(PhysicalUnaryPlan<PhysicalProject, Plan> projectPlan, C context) {
return null;
}
public R visitPhysicalFilter(PhysicalPlan<? extends PhysicalPlan, PhysicalFilter> filterPlan,
C context) {
public R visitPhysicalFilter(PhysicalUnaryPlan<PhysicalFilter, Plan> filterPlan, C context) {
return null;
}

View File

@ -29,8 +29,9 @@ import java.util.List;
/**
* Expression for unbound alias.
*/
public class UnboundAlias<CHILD_TYPE extends Expression> extends NamedExpression<UnboundAlias<CHILD_TYPE>>
implements UnaryExpression<UnboundAlias<CHILD_TYPE>, CHILD_TYPE> {
public class UnboundAlias<CHILD_TYPE extends Expression>
extends NamedExpression
implements UnaryExpression<CHILD_TYPE> {
public UnboundAlias(CHILD_TYPE child) {
super(NodeType.UNBOUND_ALIAS, child);

View File

@ -32,7 +32,7 @@ import java.util.List;
/**
* Represent a relation plan node that has not been bound.
*/
public class UnboundRelation extends LogicalLeafOperator<UnboundRelation> {
public class UnboundRelation extends LogicalLeafOperator {
private final List<String> nameParts;
public UnboundRelation(List<String> nameParts) {

View File

@ -28,7 +28,7 @@ import java.util.List;
/**
* Slot has not been bound.
*/
public class UnboundSlot extends Slot<UnboundSlot> {
public class UnboundSlot extends Slot {
private final List<String> nameParts;
public UnboundSlot(List<String> nameParts) {

View File

@ -29,7 +29,7 @@ import java.util.List;
/**
* Star expression.
*/
public class UnboundStar extends NamedExpression<UnboundStar> implements LeafExpression<UnboundStar> {
public class UnboundStar extends NamedExpression implements LeafExpression {
private final List<String> target;
public UnboundStar(List<String> target) {

View File

@ -30,7 +30,7 @@ import java.util.stream.Collectors;
/**
* Abstract class for all job using for analyze and optimize query plan in Nereids.
*/
public abstract class Job<NODE_TYPE extends TreeNode> {
public abstract class Job<NODE_TYPE extends TreeNode<NODE_TYPE>> {
protected JobType type;
protected PlannerContext context;

View File

@ -35,7 +35,7 @@ import java.util.Objects;
/**
* Bottom up job for rewrite, use pattern match.
*/
public class RewriteBottomUpJob<NODE_TYPE extends TreeNode> extends Job<NODE_TYPE> {
public class RewriteBottomUpJob<NODE_TYPE extends TreeNode<NODE_TYPE>> extends Job<NODE_TYPE> {
private final Group group;
private final List<Rule<NODE_TYPE>> rules;
private final boolean childrenOptimized;

View File

@ -34,7 +34,7 @@ import java.util.Objects;
/**
* Top down job for rewrite, use pattern match.
*/
public class RewriteTopDownJob<NODE_TYPE extends TreeNode> extends Job<NODE_TYPE> {
public class RewriteTopDownJob<NODE_TYPE extends TreeNode<NODE_TYPE>> extends Job<NODE_TYPE> {
private final Group group;
private final List<Rule<NODE_TYPE>> rules;

View File

@ -33,7 +33,7 @@ import java.util.Map;
*
* @param <NODE_TYPE> should be {@link Plan} or {@link Expression}
*/
public class Memo<NODE_TYPE extends TreeNode> {
public class Memo<NODE_TYPE extends TreeNode<NODE_TYPE>> {
private final List<Group> groups = Lists.newArrayList();
// we could not use Set, because Set has no get method.
private final Map<GroupExpression, GroupExpression> groupExpressions = Maps.newHashMap();
@ -59,12 +59,11 @@ public class Memo<NODE_TYPE extends TreeNode> {
public GroupExpression copyIn(NODE_TYPE node, Group target, boolean rewrite) {
Preconditions.checkArgument(!rewrite || target != null);
List<Group> childrenGroups = Lists.newArrayList();
for (Object object : node.children()) {
NODE_TYPE child = (NODE_TYPE) object;
for (NODE_TYPE child : node.children()) {
childrenGroups.add(copyIn(child, null, rewrite).getParent());
}
if (node.getGroupExpression() != null && groupExpressions.containsKey(node.getGroupExpression())) {
return node.getGroupExpression();
if (node.getGroupExpression().isPresent() && groupExpressions.containsKey(node.getGroupExpression().get())) {
return node.getGroupExpression().get();
}
GroupExpression newGroupExpression = new GroupExpression(node.getOperator());
newGroupExpression.setChildren(childrenGroups);

View File

@ -25,7 +25,7 @@ import java.util.Objects;
/**
* Abstract class for all concrete operator.
*/
public abstract class AbstractOperator<TYPE extends AbstractOperator<TYPE>> implements Operator<TYPE> {
public abstract class AbstractOperator implements Operator {
protected final OperatorType type;
protected final long limited;
@ -52,7 +52,7 @@ public abstract class AbstractOperator<TYPE extends AbstractOperator<TYPE>> impl
* (PhysicalPlan<? extends PhysicalPlan, PhysicalOlapScan>) plan, context);
* </code>
*/
public <R, C> R accept(PlanOperatorVisitor<R, C> visitor, Plan<?, ?> plan, C context) {
public <R, C> R accept(PlanOperatorVisitor<R, C> visitor, Plan plan, C context) {
return null;
}

View File

@ -25,11 +25,11 @@ import org.apache.doris.nereids.trees.plans.Plan;
/**
* interface for all concrete operator.
*/
public interface Operator<TYPE extends Operator<TYPE>> {
public interface Operator {
OperatorType getType();
<NODE_TYPE extends TreeNode> NODE_TYPE toTreeNode(GroupExpression groupExpression);
<NODE_TYPE extends TreeNode<NODE_TYPE>> NODE_TYPE toTreeNode(GroupExpression groupExpression);
public <R, C> R accept(PlanOperatorVisitor<R, C> visitor, Plan<?, ?> plan, C context);
<R, C> R accept(PlanOperatorVisitor<R, C> visitor, Plan plan, C context);
}

View File

@ -46,6 +46,7 @@ public enum OperatorType {
PHYSICAL_EXCHANGE,
// pattern
NORMAL_PATTERN,
ANY,
MULTI,
FIXED,

View File

@ -17,13 +17,8 @@
package org.apache.doris.nereids.operators.plans;
import org.apache.doris.nereids.trees.plans.Plan;
/**
* interface for all concrete binary plan operator.
*/
public interface BinaryPlanOperator<
TYPE extends BinaryPlanOperator<TYPE, LEFT_INPUT_TYPE, RIGHT_INPUT_TYPE>,
LEFT_INPUT_TYPE extends Plan,
RIGHT_INPUT_TYPE extends Plan> extends PlanOperator<TYPE> {
public interface BinaryPlanOperator extends PlanOperator {
}

View File

@ -20,5 +20,5 @@ package org.apache.doris.nereids.operators.plans;
/**
* interface for all concrete leaf plan operator.
*/
public interface LeafPlanOperator<TYPE extends LeafPlanOperator<TYPE>> extends PlanOperator<TYPE> {
public interface LeafPlanOperator extends PlanOperator {
}

View File

@ -22,5 +22,5 @@ import org.apache.doris.nereids.operators.Operator;
/**
* interface for all concrete plan operator.
*/
public interface PlanOperator<TYPE extends PlanOperator<TYPE>> extends Operator<TYPE> {
public interface PlanOperator extends Operator {
}

View File

@ -17,12 +17,8 @@
package org.apache.doris.nereids.operators.plans;
import org.apache.doris.nereids.trees.plans.Plan;
/**
* interface for all concrete unary plan operator.
*/
public interface UnaryPlanOperator<
TYPE extends UnaryPlanOperator<TYPE, INPUT_TYPE>,
INPUT_TYPE extends Plan> extends PlanOperator<TYPE> {
public interface UnaryPlanOperator extends PlanOperator {
}

View File

@ -25,19 +25,15 @@ import org.apache.doris.nereids.properties.LogicalProperties;
import org.apache.doris.nereids.trees.expressions.Slot;
import org.apache.doris.nereids.trees.plans.PlaceHolderPlan;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.logical.LogicalBinary;
import org.apache.doris.nereids.trees.plans.logical.LogicalBinaryPlan;
import java.util.List;
/**
* Abstract class for all logical binary operator that have two inputs.
*/
public abstract class LogicalBinaryOperator<
TYPE extends LogicalBinaryOperator<TYPE, LEFT_INPUT_TYPE, RIGHT_INPUT_TYPE>,
LEFT_INPUT_TYPE extends Plan,
RIGHT_INPUT_TYPE extends Plan>
extends AbstractOperator<TYPE>
implements LogicalOperator<TYPE>, BinaryPlanOperator<TYPE, LEFT_INPUT_TYPE, RIGHT_INPUT_TYPE> {
public abstract class LogicalBinaryOperator extends AbstractOperator
implements LogicalOperator, BinaryPlanOperator {
public LogicalBinaryOperator(OperatorType type) {
super(type);
@ -45,15 +41,15 @@ public abstract class LogicalBinaryOperator<
@Override
public final List<Slot> computeOutput(Plan... inputs) {
return doComputeOutput((LEFT_INPUT_TYPE) inputs[0], (RIGHT_INPUT_TYPE) inputs[1]);
return doComputeOutput(inputs[0], inputs[1]);
}
public abstract List<Slot> doComputeOutput(LEFT_INPUT_TYPE left, RIGHT_INPUT_TYPE right);
public abstract List<Slot> doComputeOutput(Plan left, Plan right);
@Override
public LogicalBinary toTreeNode(GroupExpression groupExpression) {
public LogicalBinaryPlan toTreeNode(GroupExpression groupExpression) {
LogicalProperties logicalProperties = groupExpression.getParent().getLogicalProperties();
return new LogicalBinary(this, groupExpression, logicalProperties,
return new LogicalBinaryPlan(this, groupExpression, logicalProperties,
new PlaceHolderPlan(), new PlaceHolderPlan());
}
}

View File

@ -28,8 +28,7 @@ import java.util.Objects;
/**
* Logical filter plan operator.
*/
public class LogicalFilter<INPUT_TYPE extends Plan>
extends LogicalUnaryOperator<LogicalFilter<INPUT_TYPE>, INPUT_TYPE> {
public class LogicalFilter extends LogicalUnaryOperator {
private final Expression predicates;
@ -44,7 +43,7 @@ public class LogicalFilter<INPUT_TYPE extends Plan>
@Override
public List<Slot> doComputeOutput(INPUT_TYPE input) {
public List<Slot> doComputeOutput(Plan input) {
return input.getOutput();
}

View File

@ -33,9 +33,7 @@ import java.util.Optional;
/**
* Logical join plan operator.
*/
public class LogicalJoin<LEFT_INPUT_TYPE extends Plan, RIGHT_INPUT_TYPE extends Plan>
extends LogicalBinaryOperator<LogicalJoin<LEFT_INPUT_TYPE, RIGHT_INPUT_TYPE>,
LEFT_INPUT_TYPE, RIGHT_INPUT_TYPE> {
public class LogicalJoin extends LogicalBinaryOperator {
private final JoinType joinType;
private final Optional<Expression> onClause;
@ -73,7 +71,7 @@ public class LogicalJoin<LEFT_INPUT_TYPE extends Plan, RIGHT_INPUT_TYPE extends
}
@Override
public List<Slot> doComputeOutput(LEFT_INPUT_TYPE leftInput, RIGHT_INPUT_TYPE rightInput) {
public List<Slot> doComputeOutput(Plan leftInput, Plan rightInput) {
switch (joinType) {
case LEFT_SEMI_JOIN:
return ImmutableList.copyOf(leftInput.getOutput());

View File

@ -23,16 +23,15 @@ import org.apache.doris.nereids.operators.OperatorType;
import org.apache.doris.nereids.operators.plans.LeafPlanOperator;
import org.apache.doris.nereids.trees.expressions.Slot;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.logical.LogicalLeaf;
import org.apache.doris.nereids.trees.plans.logical.LogicalLeafPlan;
import java.util.List;
/**
* Abstract class for all logical operator that have no input.
*/
public abstract class LogicalLeafOperator<TYPE extends LogicalLeafOperator<TYPE>>
extends AbstractOperator<TYPE>
implements LogicalOperator<TYPE>, LeafPlanOperator<TYPE> {
public abstract class LogicalLeafOperator extends AbstractOperator
implements LogicalOperator, LeafPlanOperator {
public LogicalLeafOperator(OperatorType type) {
super(type);
@ -46,7 +45,7 @@ public abstract class LogicalLeafOperator<TYPE extends LogicalLeafOperator<TYPE>
public abstract List<Slot> doComputeOutput();
@Override
public LogicalLeaf toTreeNode(GroupExpression groupExpression) {
return new LogicalLeaf(this, groupExpression, groupExpression.getParent().getLogicalProperties());
public LogicalLeafPlan toTreeNode(GroupExpression groupExpression) {
return new LogicalLeafPlan(this, groupExpression, groupExpression.getParent().getLogicalProperties());
}
}

View File

@ -26,6 +26,6 @@ import java.util.List;
/**
* interface for all concrete logical plan operator.
*/
public interface LogicalOperator<TYPE extends LogicalOperator<TYPE>> extends PlanOperator<TYPE> {
public interface LogicalOperator extends PlanOperator {
List<Slot> computeOutput(Plan... inputs);
}

View File

@ -32,8 +32,7 @@ import java.util.Objects;
/**
* Logical project plan operator.
*/
public class LogicalProject<INPUT_TYPE extends Plan>
extends LogicalUnaryOperator<LogicalProject<INPUT_TYPE>, INPUT_TYPE> {
public class LogicalProject extends LogicalUnaryOperator {
private final List<? extends NamedExpression> projects;
@ -57,7 +56,7 @@ public class LogicalProject<INPUT_TYPE extends Plan>
}
@Override
public List<Slot> doComputeOutput(INPUT_TYPE input) {
public List<Slot> doComputeOutput(Plan input) {
// fixme: not throw a checked exception
return projects.stream()
.map(namedExpr -> {

View File

@ -31,7 +31,7 @@ import java.util.Objects;
/**
* Logical relation plan operator.
*/
public class LogicalRelation extends LogicalLeafOperator<LogicalRelation> {
public class LogicalRelation extends LogicalLeafOperator {
private final Table table;
private final List<String> qualifier;

View File

@ -25,18 +25,15 @@ import org.apache.doris.nereids.properties.LogicalProperties;
import org.apache.doris.nereids.trees.expressions.Slot;
import org.apache.doris.nereids.trees.plans.PlaceHolderPlan;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.logical.LogicalUnary;
import org.apache.doris.nereids.trees.plans.logical.LogicalUnaryPlan;
import java.util.List;
/**
* Abstract class for all logical operator that have one input.
*/
public abstract class LogicalUnaryOperator<
TYPE extends LogicalUnaryOperator<TYPE, INPUT_TYPE>,
INPUT_TYPE extends Plan>
extends AbstractOperator<TYPE>
implements LogicalOperator<TYPE>, UnaryPlanOperator<TYPE, INPUT_TYPE> {
public abstract class LogicalUnaryOperator extends AbstractOperator
implements LogicalOperator, UnaryPlanOperator {
public LogicalUnaryOperator(OperatorType type) {
super(type);
@ -44,14 +41,14 @@ public abstract class LogicalUnaryOperator<
@Override
public final List<Slot> computeOutput(Plan... inputs) {
return doComputeOutput((INPUT_TYPE) inputs[0]);
return doComputeOutput(inputs[0]);
}
public abstract List<Slot> doComputeOutput(INPUT_TYPE input);
public abstract List<Slot> doComputeOutput(Plan input);
@Override
public LogicalUnary toTreeNode(GroupExpression groupExpression) {
public LogicalUnaryPlan toTreeNode(GroupExpression groupExpression) {
LogicalProperties logicalProperties = groupExpression.getParent().getLogicalProperties();
return new LogicalUnary(this, groupExpression, logicalProperties, new PlaceHolderPlan());
return new LogicalUnaryPlan(this, groupExpression, logicalProperties, new PlaceHolderPlan());
}
}

View File

@ -22,14 +22,14 @@ import org.apache.doris.nereids.operators.OperatorType;
import org.apache.doris.nereids.operators.plans.AggPhase;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalPlan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalUnaryPlan;
import java.util.List;
/**
* Physical aggregation plan operator.
*/
public class PhysicalAggregation extends PhysicalUnaryOperator<PhysicalAggregation, PhysicalPlan> {
public class PhysicalAggregation extends PhysicalUnaryOperator {
private final List<Expression> groupByExprList;
@ -80,8 +80,7 @@ public class PhysicalAggregation extends PhysicalUnaryOperator<PhysicalAggregati
}
@Override
public <R, C> R accept(PlanOperatorVisitor<R, C> visitor, Plan<?, ?> plan, C context) {
return visitor.visitPhysicalAggregationPlan(
(PhysicalPlan<? extends PhysicalPlan, PhysicalAggregation>) plan, context);
public <R, C> R accept(PlanOperatorVisitor<R, C> visitor, Plan plan, C context) {
return visitor.visitPhysicalAggregationPlan((PhysicalUnaryPlan<PhysicalAggregation, Plan>) plan, context);
}
}

View File

@ -25,19 +25,15 @@ import org.apache.doris.nereids.properties.LogicalProperties;
import org.apache.doris.nereids.trees.expressions.Slot;
import org.apache.doris.nereids.trees.plans.PlaceHolderPlan;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalBinary;
import org.apache.doris.nereids.trees.plans.physical.PhysicalBinaryPlan;
import java.util.List;
/**
* Abstract class for all physical operator that have two inputs.
*/
public abstract class PhysicalBinaryOperator<
TYPE extends PhysicalBinaryOperator<TYPE, LEFT_INPUT_TYPE, RIGHT_INPUT_TYPE>,
LEFT_INPUT_TYPE extends Plan,
RIGHT_INPUT_TYPE extends Plan>
extends AbstractOperator<TYPE>
implements PhysicalOperator<TYPE>, BinaryPlanOperator<TYPE, LEFT_INPUT_TYPE, RIGHT_INPUT_TYPE> {
public abstract class PhysicalBinaryOperator extends AbstractOperator
implements PhysicalOperator, BinaryPlanOperator {
public PhysicalBinaryOperator(OperatorType type) {
super(type);
@ -45,18 +41,17 @@ public abstract class PhysicalBinaryOperator<
@Override
public final List<Slot> computeOutputs(LogicalProperties logicalProperties, Plan... inputs) {
return doComputeOutput(logicalProperties, (LEFT_INPUT_TYPE) inputs[0], (RIGHT_INPUT_TYPE) inputs[1]);
return doComputeOutput(logicalProperties, inputs[0], inputs[1]);
}
public List<Slot> doComputeOutput(LogicalProperties logicalProperties,
LEFT_INPUT_TYPE left, RIGHT_INPUT_TYPE right) {
public List<Slot> doComputeOutput(LogicalProperties logicalProperties, Plan left, Plan right) {
return logicalProperties.getOutput();
}
@Override
public PhysicalBinary toTreeNode(GroupExpression groupExpression) {
public PhysicalBinaryPlan toTreeNode(GroupExpression groupExpression) {
LogicalProperties logicalProperties = groupExpression.getParent().getLogicalProperties();
return new PhysicalBinary(this, groupExpression, logicalProperties,
return new PhysicalBinaryPlan(this, groupExpression, logicalProperties,
new PlaceHolderPlan(), new PlaceHolderPlan());
}
}

View File

@ -28,9 +28,7 @@ import java.util.Optional;
/**
* Physical operator represents broadcast hash join.
*/
public class PhysicalBroadcastHashJoin<LEFT_INPUT_TYPE extends Plan, RIGHT_INPUT_TYPE extends Plan>
extends PhysicalBinaryOperator<PhysicalBroadcastHashJoin<LEFT_INPUT_TYPE, RIGHT_INPUT_TYPE>,
LEFT_INPUT_TYPE, RIGHT_INPUT_TYPE> {
public class PhysicalBroadcastHashJoin extends PhysicalBinaryOperator {
private final JoinType joinType;
private final Optional<Expression> onClause;

View File

@ -21,15 +21,14 @@ import org.apache.doris.nereids.PlanOperatorVisitor;
import org.apache.doris.nereids.operators.OperatorType;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalPlan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalUnaryPlan;
import java.util.Objects;
/**
* Physical filter plan operator.
*/
public class PhysicalFilter<INPUT_TYPE extends Plan>
extends PhysicalUnaryOperator<PhysicalFilter<INPUT_TYPE>, INPUT_TYPE> {
public class PhysicalFilter extends PhysicalUnaryOperator {
private final Expression predicates;
@ -54,8 +53,7 @@ public class PhysicalFilter<INPUT_TYPE extends Plan>
}
@Override
public <R, C> R accept(PlanOperatorVisitor<R, C> visitor, Plan<?, ?> plan, C context) {
return visitor.visitPhysicalFilter((PhysicalPlan<? extends PhysicalPlan, PhysicalFilter>) plan,
context);
public <R, C> R accept(PlanOperatorVisitor<R, C> visitor, Plan plan, C context) {
return visitor.visitPhysicalFilter((PhysicalUnaryPlan<PhysicalFilter, Plan>) plan, context);
}
}

View File

@ -22,12 +22,12 @@ import org.apache.doris.nereids.operators.OperatorType;
import org.apache.doris.nereids.operators.plans.JoinType;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalPlan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalBinaryPlan;
/**
* Physical hash join plan operator.
*/
public class PhysicalHashJoin extends PhysicalBinaryOperator<PhysicalHashJoin, PhysicalPlan, PhysicalPlan> {
public class PhysicalHashJoin extends PhysicalBinaryOperator {
private final JoinType joinType;
@ -54,9 +54,8 @@ public class PhysicalHashJoin extends PhysicalBinaryOperator<PhysicalHashJoin, P
}
@Override
public <R, C> R accept(PlanOperatorVisitor<R, C> visitor, Plan<?, ?> plan, C context) {
return visitor.visitPhysicalHashJoinPlan(
(PhysicalPlan<? extends PhysicalPlan, PhysicalHashJoin>) plan, context);
public <R, C> R accept(PlanOperatorVisitor<R, C> visitor, Plan plan, C context) {
return visitor.visitPhysicalHashJoinPlan((PhysicalBinaryPlan<PhysicalHashJoin, Plan, Plan>) plan, context);
}
}

View File

@ -24,16 +24,15 @@ import org.apache.doris.nereids.operators.plans.LeafPlanOperator;
import org.apache.doris.nereids.properties.LogicalProperties;
import org.apache.doris.nereids.trees.expressions.Slot;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalLeaf;
import org.apache.doris.nereids.trees.plans.physical.PhysicalLeafPlan;
import java.util.List;
/**
* Abstract class for all physical operator that have no input.
*/
public abstract class PhysicalLeafOperator<TYPE extends PhysicalLeafOperator<TYPE>>
extends AbstractOperator<TYPE>
implements PhysicalOperator<TYPE>, LeafPlanOperator<TYPE> {
public abstract class PhysicalLeafOperator extends AbstractOperator
implements PhysicalOperator, LeafPlanOperator {
public PhysicalLeafOperator(OperatorType type) {
super(type);
@ -49,7 +48,7 @@ public abstract class PhysicalLeafOperator<TYPE extends PhysicalLeafOperator<TYP
}
@Override
public PhysicalLeaf toTreeNode(GroupExpression groupExpression) {
return new PhysicalLeaf(this, groupExpression, groupExpression.getParent().getLogicalProperties());
public PhysicalLeafPlan toTreeNode(GroupExpression groupExpression) {
return new PhysicalLeafPlan(this, groupExpression, groupExpression.getParent().getLogicalProperties());
}
}

View File

@ -22,7 +22,7 @@ import org.apache.doris.catalog.Partition;
import org.apache.doris.nereids.PlanOperatorVisitor;
import org.apache.doris.nereids.operators.OperatorType;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalPlan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalLeafPlan;
import com.clearspring.analytics.util.Lists;
import org.apache.commons.lang3.StringUtils;
@ -32,7 +32,7 @@ import java.util.List;
/**
* Physical olap scan plan operator.
*/
public class PhysicalOlapScan extends PhysicalScan<PhysicalOlapScan> {
public class PhysicalOlapScan extends PhysicalScan {
private final long selectedIndexId;
private final List<Long> selectedTabletId;
private final List<Long> selectedPartitionId;
@ -80,9 +80,8 @@ public class PhysicalOlapScan extends PhysicalScan<PhysicalOlapScan> {
}
@Override
public <R, C> R accept(PlanOperatorVisitor<R, C> visitor, Plan<?, ?> plan, C context) {
return visitor.visitPhysicalOlapScanPlan(
(PhysicalPlan<? extends PhysicalPlan, PhysicalOlapScan>) plan, context);
public <R, C> R accept(PlanOperatorVisitor<R, C> visitor, Plan plan, C context) {
return visitor.visitPhysicalOlapScanPlan((PhysicalLeafPlan<PhysicalOlapScan>) plan, context);
}
}

View File

@ -27,7 +27,7 @@ import java.util.List;
/**
* interface for all concrete physical operator.
*/
public interface PhysicalOperator<TYPE extends PhysicalOperator<TYPE>> extends PlanOperator<TYPE> {
public interface PhysicalOperator extends PlanOperator {
List<Slot> computeOutputs(LogicalProperties logicalProperties, Plan... inputs);

View File

@ -21,7 +21,7 @@ import org.apache.doris.nereids.PlanOperatorVisitor;
import org.apache.doris.nereids.operators.OperatorType;
import org.apache.doris.nereids.trees.expressions.NamedExpression;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalPlan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalUnaryPlan;
import org.apache.commons.lang3.StringUtils;
@ -31,8 +31,7 @@ import java.util.Objects;
/**
* Physical project plan operator.
*/
public class PhysicalProject<INPUT_TYPE extends Plan>
extends PhysicalUnaryOperator<PhysicalProject<INPUT_TYPE>, INPUT_TYPE> {
public class PhysicalProject extends PhysicalUnaryOperator {
private final List<? extends NamedExpression> projects;
@ -51,8 +50,7 @@ public class PhysicalProject<INPUT_TYPE extends Plan>
}
@Override
public <R, C> R accept(PlanOperatorVisitor<R, C> visitor, Plan<?, ?> plan, C context) {
return visitor.visitPhysicalProject(
(PhysicalPlan<? extends PhysicalPlan, PhysicalProject>) plan, context);
public <R, C> R accept(PlanOperatorVisitor<R, C> visitor, Plan plan, C context) {
return visitor.visitPhysicalProject(((PhysicalUnaryPlan<PhysicalProject, Plan>) plan), context);
}
}

View File

@ -25,7 +25,7 @@ import java.util.Objects;
/**
* Abstract class for all physical scan operator.
*/
public abstract class PhysicalScan<TYPE extends PhysicalScan<TYPE>> extends PhysicalLeafOperator<TYPE> {
public abstract class PhysicalScan extends PhysicalLeafOperator {
protected final List<String> qualifier;

View File

@ -21,14 +21,14 @@ import org.apache.doris.nereids.PlanOperatorVisitor;
import org.apache.doris.nereids.operators.OperatorType;
import org.apache.doris.nereids.properties.OrderKey;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalPlan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalUnaryPlan;
import java.util.List;
/**
* Physical sort plan operator.
*/
public class PhysicalSort extends PhysicalUnaryOperator<PhysicalSort, PhysicalPlan> {
public class PhysicalSort extends PhysicalUnaryOperator {
private final int offset;
@ -70,8 +70,7 @@ public class PhysicalSort extends PhysicalUnaryOperator<PhysicalSort, PhysicalPl
}
@Override
public <R, C> R accept(PlanOperatorVisitor<R, C> visitor, Plan<?, ?> plan, C context) {
return visitor.visitPhysicalSortPlan((PhysicalPlan<? extends PhysicalPlan, PhysicalSort>) plan,
context);
public <R, C> R accept(PlanOperatorVisitor<R, C> visitor, Plan plan, C context) {
return visitor.visitPhysicalSortPlan((PhysicalUnaryPlan<PhysicalSort, Plan>) plan, context);
}
}

View File

@ -25,18 +25,15 @@ import org.apache.doris.nereids.properties.LogicalProperties;
import org.apache.doris.nereids.trees.expressions.Slot;
import org.apache.doris.nereids.trees.plans.PlaceHolderPlan;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalUnary;
import org.apache.doris.nereids.trees.plans.physical.PhysicalUnaryPlan;
import java.util.List;
/**
* Abstract class for all physical operator that have one input.
*/
public abstract class PhysicalUnaryOperator<
TYPE extends PhysicalUnaryOperator<TYPE, INPUT_TYPE>,
INPUT_TYPE extends Plan>
extends AbstractOperator<TYPE>
implements PhysicalOperator<TYPE>, UnaryPlanOperator<TYPE, INPUT_TYPE> {
public abstract class PhysicalUnaryOperator extends AbstractOperator
implements PhysicalOperator, UnaryPlanOperator {
public PhysicalUnaryOperator(OperatorType type) {
super(type);
@ -44,16 +41,16 @@ public abstract class PhysicalUnaryOperator<
@Override
public final List<Slot> computeOutputs(LogicalProperties logicalProperties, Plan... inputs) {
return doComputeOutput(logicalProperties, (INPUT_TYPE) inputs[0]);
return doComputeOutput(logicalProperties, inputs[0]);
}
public List<Slot> doComputeOutput(LogicalProperties logicalProperties, INPUT_TYPE input) {
public List<Slot> doComputeOutput(LogicalProperties logicalProperties, Plan input) {
return logicalProperties.getOutput();
}
@Override
public PhysicalUnary toTreeNode(GroupExpression groupExpression) {
public PhysicalUnaryPlan toTreeNode(GroupExpression groupExpression) {
LogicalProperties logicalProperties = groupExpression.getParent().getLogicalProperties();
return new PhysicalUnary(this, groupExpression, logicalProperties, new PlaceHolderPlan());
return new PhysicalUnaryPlan(this, groupExpression, logicalProperties, new PlaceHolderPlan());
}
}

View File

@ -66,10 +66,10 @@ import org.apache.doris.nereids.trees.expressions.Literal;
import org.apache.doris.nereids.trees.expressions.NamedExpression;
import org.apache.doris.nereids.trees.expressions.Not;
import org.apache.doris.nereids.trees.expressions.NullSafeEqual;
import org.apache.doris.nereids.trees.plans.logical.LogicalBinary;
import org.apache.doris.nereids.trees.plans.logical.LogicalLeaf;
import org.apache.doris.nereids.trees.plans.logical.LogicalBinaryPlan;
import org.apache.doris.nereids.trees.plans.logical.LogicalLeafPlan;
import org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
import org.apache.doris.nereids.trees.plans.logical.LogicalUnary;
import org.apache.doris.nereids.trees.plans.logical.LogicalUnaryPlan;
import com.google.common.collect.Lists;
import org.antlr.v4.runtime.ParserRuleContext;
@ -95,7 +95,7 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> {
*/
private final BiFunction<WhereClauseContext, LogicalPlan, LogicalPlan> withWhereClause =
(WhereClauseContext ctx, LogicalPlan plan)
-> new LogicalUnary(new LogicalFilter(expression((ctx.booleanExpression()))), plan);
-> new LogicalUnaryPlan(new LogicalFilter(expression((ctx.booleanExpression()))), plan);
protected <T> T typedVisit(ParseTree ctx) {
return (T) ctx.accept(this);
@ -213,7 +213,7 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> {
LogicalPlan withProject;
if (CollectionUtils.isNotEmpty(namedExpressions)) {
withProject = new LogicalUnary(new LogicalProject(namedExpressions), withFilter);
withProject = new LogicalUnaryPlan(new LogicalProject(namedExpressions), withFilter);
} else {
withProject = withFilter;
}
@ -229,7 +229,7 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> {
if (left == null) {
left = right;
} else {
left = new LogicalBinary(new LogicalJoin(JoinType.INNER_JOIN, null), left, right);
left = new LogicalBinaryPlan(new LogicalJoin(JoinType.INNER_JOIN, null), left, right);
}
left = withJoinRelations(left, relation);
}
@ -269,7 +269,7 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> {
condition = expression(joinCriteria.booleanExpression());
}
last = new LogicalBinary(
last = new LogicalBinaryPlan(
new LogicalJoin(joinType, Optional.ofNullable(condition)),
last, plan(join.relationPrimary())
);
@ -285,7 +285,7 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> {
List<String> tableId = visitMultipartIdentifier(ctx.multipartIdentifier());
UnboundRelation relation = new UnboundRelation(tableId);
// TODO: sample and time travel, alias, sub query
return new LogicalLeaf(relation);
return new LogicalLeafPlan(relation);
}
/**

View File

@ -32,11 +32,11 @@ import java.util.Objects;
* TODO: adapt ANY and MULTI
* TODO: add ut
*/
public class GroupExpressionMatching<NODE_TYPE extends TreeNode> implements Iterable<NODE_TYPE> {
private final Pattern pattern;
public class GroupExpressionMatching<NODE_TYPE extends TreeNode<NODE_TYPE>> implements Iterable<NODE_TYPE> {
private final Pattern<? extends NODE_TYPE, NODE_TYPE> pattern;
private final GroupExpression groupExpression;
public GroupExpressionMatching(Pattern pattern, GroupExpression groupExpression) {
public GroupExpressionMatching(Pattern<? extends NODE_TYPE, NODE_TYPE> pattern, GroupExpression groupExpression) {
this.pattern = Objects.requireNonNull(pattern);
this.groupExpression = Objects.requireNonNull(groupExpression);
}
@ -49,7 +49,7 @@ public class GroupExpressionMatching<NODE_TYPE extends TreeNode> implements Iter
/**
* Iterator to get all subtrees.
*/
public static class GroupExpressionIterator<NODE_TYPE extends TreeNode> implements Iterator<NODE_TYPE> {
public static class GroupExpressionIterator<NODE_TYPE extends TreeNode<NODE_TYPE>> implements Iterator<NODE_TYPE> {
private final List<NODE_TYPE> results;
private int resultIndex = 0;
@ -59,7 +59,8 @@ public class GroupExpressionMatching<NODE_TYPE extends TreeNode> implements Iter
* @param pattern pattern to match
* @param groupExpression group expression to be matched
*/
public GroupExpressionIterator(Pattern pattern, GroupExpression groupExpression) {
public GroupExpressionIterator(Pattern<? extends NODE_TYPE, NODE_TYPE> pattern,
GroupExpression groupExpression) {
results = Lists.newArrayList();
if (!pattern.matchOperator(groupExpression.getOperator())) {
@ -74,7 +75,7 @@ public class GroupExpressionMatching<NODE_TYPE extends TreeNode> implements Iter
return;
}
NODE_TYPE root = (NODE_TYPE) groupExpression.getOperator().toTreeNode(groupExpression);
NODE_TYPE root = groupExpression.getOperator().toTreeNode(groupExpression);
List<List<NODE_TYPE>> childrenResults = Lists.newArrayListWithCapacity(groupExpression.arity());
for (int i = 0; i < groupExpression.arity(); ++i) {
@ -96,7 +97,7 @@ public class GroupExpressionMatching<NODE_TYPE extends TreeNode> implements Iter
for (int i = 0; i < childrenResults.size(); i++) {
children.add(childrenResults.get(i).get(childrenResultsIndex[i]));
}
NODE_TYPE result = (NODE_TYPE) root.newChildren(children);
NODE_TYPE result = root.newChildren(children);
results.add(result);
offset = 0;
while (true) {

View File

@ -48,7 +48,7 @@ public class GroupMatching<NODE_TYPE extends TreeNode> implements Iterable<NODE_
/**
* Iterator to get all subtrees from a group.
*/
public static class GroupIterator<NODE_TYPE extends TreeNode> implements Iterator<NODE_TYPE> {
public static class GroupIterator<NODE_TYPE extends TreeNode<NODE_TYPE>> implements Iterator<NODE_TYPE> {
private final Pattern pattern;
private final List<Iterator<NODE_TYPE>> iterator;
private int iteratorIndex = 0;
@ -59,19 +59,19 @@ public class GroupMatching<NODE_TYPE extends TreeNode> implements Iterable<NODE_
* @param pattern pattern to match
* @param group group to be matched
*/
public GroupIterator(Pattern pattern, Group group) {
public GroupIterator(Pattern<? extends NODE_TYPE, NODE_TYPE> pattern, Group group) {
this.pattern = pattern;
this.iterator = Lists.newArrayList();
for (GroupExpression groupExpression : group.getLogicalExpressions()) {
GroupExpressionMatching.GroupExpressionIterator<NODE_TYPE> groupExpressionIterator =
new GroupExpressionMatching<NODE_TYPE>(pattern, groupExpression).iterator();
new GroupExpressionMatching(pattern, groupExpression).iterator();
if (groupExpressionIterator.hasNext()) {
this.iterator.add(groupExpressionIterator);
}
}
for (GroupExpression groupExpression : group.getPhysicalExpressions()) {
GroupExpressionMatching.GroupExpressionIterator<NODE_TYPE> groupExpressionIterator =
new GroupExpressionMatching<NODE_TYPE>(pattern, groupExpression).iterator();
new GroupExpressionMatching(pattern, groupExpression).iterator();
if (groupExpressionIterator.hasNext()) {
this.iterator.add(groupExpressionIterator);
}

View File

@ -23,6 +23,10 @@ import org.apache.doris.nereids.trees.TreeNode;
* Define an callback action when match a pattern, usually implement as a rule body.
* e.g. exchange join children for JoinCommutative Rule
*/
public interface MatchedAction<INPUT_TYPE extends TreeNode, OUTPUT_TYPE extends TreeNode> {
OUTPUT_TYPE apply(MatchingContext<INPUT_TYPE> ctx);
public interface MatchedAction<
INPUT_TYPE extends RULE_TYPE,
OUTPUT_TYPE extends RULE_TYPE,
RULE_TYPE extends TreeNode<RULE_TYPE>> {
OUTPUT_TYPE apply(MatchingContext<INPUT_TYPE, RULE_TYPE> ctx);
}

View File

@ -23,9 +23,9 @@ import org.apache.doris.nereids.trees.TreeNode;
/**
* Define a context when match a pattern pass through a MatchedAction.
*/
public class MatchingContext<T extends TreeNode> {
public final T root;
public final Pattern<T> pattern;
public class MatchingContext<TYPE extends RULE_TYPE, RULE_TYPE extends TreeNode<RULE_TYPE>> {
public final TYPE root;
public final Pattern<TYPE, RULE_TYPE> pattern;
public final PlannerContext plannerContext;
/**
@ -35,7 +35,7 @@ public class MatchingContext<T extends TreeNode> {
* @param pattern the defined pattern
* @param plannerContext the planner context
*/
public MatchingContext(T root, Pattern<T> pattern, PlannerContext plannerContext) {
public MatchingContext(TYPE root, Pattern<TYPE, RULE_TYPE> pattern, PlannerContext plannerContext) {
this.root = root;
this.pattern = pattern;
this.plannerContext = plannerContext;

View File

@ -28,20 +28,21 @@ import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Predicate;
/**
* Pattern node used in pattern matching.
*/
public class Pattern<T extends TreeNode> extends AbstractTreeNode<Pattern<T>> {
public class Pattern<TYPE extends NODE_TYPE, NODE_TYPE extends TreeNode<NODE_TYPE>>
extends AbstractTreeNode<Pattern<? extends NODE_TYPE, NODE_TYPE>> {
public static final Pattern ANY = new Pattern(OperatorType.ANY);
public static final Pattern MULTI = new Pattern(OperatorType.MULTI);
public static final Pattern FIXED = new Pattern(OperatorType.FIXED);
public static final Pattern MULTI_FIXED = new Pattern(OperatorType.MULTI_FIXED);
private final List<Predicate<T>> predicates;
private final OperatorType operatorType;
protected final List<Predicate<TYPE>> predicates;
protected final OperatorType operatorType;
/**
* Constructor for Pattern.
@ -62,7 +63,7 @@ public class Pattern<T extends TreeNode> extends AbstractTreeNode<Pattern<T>> {
* @param predicates custom matching predicate
* @param children sub pattern
*/
public Pattern(OperatorType operatorType, List<Predicate<T>> predicates, Pattern... children) {
public Pattern(OperatorType operatorType, List<Predicate<TYPE>> predicates, Pattern... children) {
super(NodeType.PATTERN, children);
this.operatorType = operatorType;
this.predicates = ImmutableList.copyOf(predicates);
@ -112,7 +113,7 @@ public class Pattern<T extends TreeNode> extends AbstractTreeNode<Pattern<T>> {
* @param root wait to match
* @return ture if current Pattern match Plan in params
*/
public boolean matchRoot(T root) {
public boolean matchRoot(TYPE root) {
if (root == null) {
return false;
}
@ -125,6 +126,10 @@ public class Pattern<T extends TreeNode> extends AbstractTreeNode<Pattern<T>> {
return true;
}
return doMatchRoot(root);
}
protected boolean doMatchRoot(TYPE root) {
return getOperatorType().equals(root.getOperator().getType())
&& predicates.stream().allMatch(predicate -> predicate.test(root));
}
@ -135,9 +140,10 @@ public class Pattern<T extends TreeNode> extends AbstractTreeNode<Pattern<T>> {
* @param root wait to match
* @return ture if children Patterns match root's children in params
*/
public boolean matchChildren(T root) {
public boolean matchChildren(TYPE root) {
for (int i = 0; i < arity(); i++) {
if (!child(i).match(root.child(i))) {
Pattern child = child(i);
if (!child.match(root.child(i))) {
return false;
}
}
@ -150,18 +156,22 @@ public class Pattern<T extends TreeNode> extends AbstractTreeNode<Pattern<T>> {
* @param root wait to match
* @return ture if current pattern and children patterns match root in params
*/
public boolean match(T root) {
public boolean match(TYPE root) {
return matchRoot(root) && matchChildren(root);
}
@Override
public Pattern<T> newChildren(List<TreeNode> children) {
public Pattern<? extends NODE_TYPE, NODE_TYPE> newChildren(List<Pattern<? extends NODE_TYPE, NODE_TYPE>> children) {
throw new RuntimeException();
}
public Pattern<TYPE, NODE_TYPE> withPredicates(List<Predicate<TYPE>> predicates) {
return new Pattern(operatorType, predicates, children.toArray(new Pattern[0]));
}
@Override
public GroupExpression getGroupExpression() {
throw new RuntimeException();
public Optional<GroupExpression> getGroupExpression() {
return Optional.empty();
}
@Override
@ -180,14 +190,4 @@ public class Pattern<T extends TreeNode> extends AbstractTreeNode<Pattern<T>> {
public int hashCode() {
return Objects.hash(operatorType);
}
@Override
public List<Pattern> children() {
return (List) children;
}
@Override
public Pattern child(int index) {
return (Pattern) children.get(index);
}
}

View File

@ -30,12 +30,12 @@ import java.util.function.Predicate;
* Define a descriptor to wrap a pattern tree to define a pattern shape.
* It can support pattern generic type to MatchedAction.
*/
public class PatternDescriptor<INPUT_TYPE extends RULE_TYPE, RULE_TYPE extends TreeNode> {
public final Pattern<INPUT_TYPE> pattern;
public class PatternDescriptor<INPUT_TYPE extends RULE_TYPE, RULE_TYPE extends TreeNode<RULE_TYPE>> {
public final Pattern<INPUT_TYPE, RULE_TYPE> pattern;
public final RulePromise defaultPromise;
public final List<Predicate<INPUT_TYPE>> predicates = new ArrayList<>();
public PatternDescriptor(Pattern<INPUT_TYPE> pattern, RulePromise defaultPromise) {
public PatternDescriptor(Pattern<INPUT_TYPE, RULE_TYPE> pattern, RulePromise defaultPromise) {
this.pattern = Objects.requireNonNull(pattern, "pattern can not be null");
this.defaultPromise = Objects.requireNonNull(defaultPromise, "defaultPromise can not be null");
}
@ -47,16 +47,12 @@ public class PatternDescriptor<INPUT_TYPE extends RULE_TYPE, RULE_TYPE extends T
public <OUTPUT_TYPE extends RULE_TYPE> PatternMatcher<INPUT_TYPE, OUTPUT_TYPE, RULE_TYPE> then(
Function<INPUT_TYPE, OUTPUT_TYPE> matchedAction) {
return new PatternMatcher<>(patternWithPredicates(), defaultPromise, ctx -> matchedAction.apply(ctx.root));
return new PatternMatcher<>(
pattern.withPredicates(predicates), defaultPromise, ctx -> matchedAction.apply(ctx.root));
}
public <OUTPUT_TYPE extends RULE_TYPE> PatternMatcher<INPUT_TYPE, OUTPUT_TYPE, RULE_TYPE> thenApply(
MatchedAction<INPUT_TYPE, OUTPUT_TYPE> matchedAction) {
return new PatternMatcher<>(patternWithPredicates(), defaultPromise, matchedAction);
}
public Pattern<INPUT_TYPE> patternWithPredicates() {
Pattern[] children = pattern.children().toArray(new Pattern[0]);
return new Pattern<>(pattern.getOperatorType(), predicates, children);
MatchedAction<INPUT_TYPE, OUTPUT_TYPE, RULE_TYPE> matchedAction) {
return new PatternMatcher<>(pattern.withPredicates(predicates), defaultPromise, matchedAction);
}
}

View File

@ -35,11 +35,11 @@ import java.util.Objects;
public class PatternMatcher<
INPUT_TYPE extends RULE_TYPE,
OUTPUT_TYPE extends RULE_TYPE,
RULE_TYPE extends TreeNode> {
RULE_TYPE extends TreeNode<RULE_TYPE>> {
public final Pattern<INPUT_TYPE> pattern;
public final Pattern<INPUT_TYPE, RULE_TYPE> pattern;
public final RulePromise defaultRulePromise;
public final MatchedAction<INPUT_TYPE, OUTPUT_TYPE> matchedAction;
public final MatchedAction<INPUT_TYPE, OUTPUT_TYPE, RULE_TYPE> matchedAction;
/**
* PatternMatcher wrap a pattern, defaultRulePromise and matchedAction.
@ -48,8 +48,8 @@ public class PatternMatcher<
* @param defaultRulePromise defaultRulePromise
* @param matchedAction matched callback function
*/
public PatternMatcher(Pattern<INPUT_TYPE> pattern, RulePromise defaultRulePromise,
MatchedAction<INPUT_TYPE, OUTPUT_TYPE> matchedAction) {
public PatternMatcher(Pattern<INPUT_TYPE, RULE_TYPE> pattern, RulePromise defaultRulePromise,
MatchedAction<INPUT_TYPE, OUTPUT_TYPE, RULE_TYPE> matchedAction) {
this.pattern = Objects.requireNonNull(pattern, "pattern can not be null");
this.defaultRulePromise = Objects.requireNonNull(
defaultRulePromise, "defaultRulePromise can not be null");
@ -71,7 +71,7 @@ public class PatternMatcher<
return new Rule<RULE_TYPE>(ruleType, pattern, rulePromise) {
@Override
public List<RULE_TYPE> transform(RULE_TYPE originPlan, PlannerContext context) {
MatchingContext<INPUT_TYPE> matchingContext =
MatchingContext<INPUT_TYPE, RULE_TYPE> matchingContext =
new MatchingContext<>((INPUT_TYPE) originPlan, pattern, context);
OUTPUT_TYPE replacePlan = matchedAction.apply(matchingContext);
return ImmutableList.of(replacePlan == null ? originPlan : replacePlan);

View File

@ -17,26 +17,28 @@
package org.apache.doris.nereids.pattern;
import org.apache.doris.nereids.analyzer.UnboundRelation;
import org.apache.doris.nereids.operators.OperatorType;
import org.apache.doris.nereids.operators.plans.JoinType;
import org.apache.doris.nereids.operators.plans.logical.LogicalFilter;
import org.apache.doris.nereids.operators.plans.logical.LogicalJoin;
import org.apache.doris.nereids.operators.plans.logical.LogicalProject;
import org.apache.doris.nereids.operators.plans.logical.LogicalRelation;
import org.apache.doris.nereids.operators.plans.physical.PhysicalBroadcastHashJoin;
import org.apache.doris.nereids.operators.plans.physical.PhysicalFilter;
import org.apache.doris.nereids.operators.plans.physical.PhysicalOlapScan;
import org.apache.doris.nereids.operators.plans.physical.PhysicalProject;
import org.apache.doris.nereids.operators.plans.BinaryPlanOperator;
import org.apache.doris.nereids.operators.plans.LeafPlanOperator;
import org.apache.doris.nereids.operators.plans.UnaryPlanOperator;
import org.apache.doris.nereids.operators.plans.logical.LogicalBinaryOperator;
import org.apache.doris.nereids.operators.plans.logical.LogicalLeafOperator;
import org.apache.doris.nereids.operators.plans.logical.LogicalUnaryOperator;
import org.apache.doris.nereids.operators.plans.physical.PhysicalBinaryOperator;
import org.apache.doris.nereids.operators.plans.physical.PhysicalLeafOperator;
import org.apache.doris.nereids.operators.plans.physical.PhysicalScan;
import org.apache.doris.nereids.operators.plans.physical.PhysicalUnaryOperator;
import org.apache.doris.nereids.rules.RulePromise;
import org.apache.doris.nereids.trees.TreeNode;
import org.apache.doris.nereids.trees.plans.BinaryPlan;
import org.apache.doris.nereids.trees.plans.LeafPlan;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.logical.LogicalBinary;
import org.apache.doris.nereids.trees.plans.logical.LogicalLeaf;
import org.apache.doris.nereids.trees.plans.logical.LogicalUnary;
import org.apache.doris.nereids.trees.plans.physical.PhysicalBinary;
import org.apache.doris.nereids.trees.plans.physical.PhysicalLeaf;
import org.apache.doris.nereids.trees.plans.physical.PhysicalUnary;
import org.apache.doris.nereids.trees.plans.UnaryPlan;
import org.apache.doris.nereids.trees.plans.logical.LogicalBinaryPlan;
import org.apache.doris.nereids.trees.plans.logical.LogicalLeafPlan;
import org.apache.doris.nereids.trees.plans.logical.LogicalUnaryPlan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalBinaryPlan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalLeafPlan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalUnaryPlan;
/**
* An interface provided some PatternDescriptor.
@ -47,231 +49,171 @@ public interface Patterns {
// need implement
RulePromise defaultPromise();
// logical pattern descriptors
/* special pattern descriptors */
default <T extends RULE_TYPE, RULE_TYPE extends TreeNode> PatternDescriptor<T, RULE_TYPE> any() {
default <T extends RULE_TYPE, RULE_TYPE extends TreeNode<RULE_TYPE>> PatternDescriptor<T, RULE_TYPE> any() {
return new PatternDescriptor<>(Pattern.ANY, defaultPromise());
}
default <T extends RULE_TYPE, RULE_TYPE extends TreeNode> PatternDescriptor<T, RULE_TYPE> multi() {
default <T extends RULE_TYPE, RULE_TYPE extends TreeNode<RULE_TYPE>> PatternDescriptor<T, RULE_TYPE> multi() {
return new PatternDescriptor<>(Pattern.MULTI, defaultPromise());
}
default <T extends RULE_TYPE, RULE_TYPE extends TreeNode> PatternDescriptor<T, RULE_TYPE> fixed() {
default <T extends RULE_TYPE, RULE_TYPE extends TreeNode<RULE_TYPE>> PatternDescriptor<T, RULE_TYPE> fixed() {
return new PatternDescriptor<>(Pattern.FIXED, defaultPromise());
}
default <T extends RULE_TYPE, RULE_TYPE extends TreeNode<RULE_TYPE>> PatternDescriptor<T, RULE_TYPE> multiFixed() {
return new PatternDescriptor<>(Pattern.MULTI_FIXED, defaultPromise());
}
/* abstract plan operator patterns */
/**
* create a unboundRelation pattern.
* create a leafPlan pattern.
*/
default PatternDescriptor<LogicalLeaf<UnboundRelation>, Plan> unboundRelation() {
return new PatternDescriptor<>(
new Pattern<>(OperatorType.LOGICAL_UNBOUND_RELATION),
default PatternDescriptor<LeafPlan, Plan> leafPlan() {
return new PatternDescriptor(new TypePattern(LeafPlanOperator.class), defaultPromise());
}
/**
* create a unaryPlan pattern.
*/
default PatternDescriptor<UnaryPlan<Plan>, Plan> unaryPlan() {
return new PatternDescriptor(new TypePattern(UnaryPlanOperator.class, Pattern.FIXED), defaultPromise());
}
/**
* create a unaryPlan pattern.
*/
default <C extends Plan> PatternDescriptor<UnaryPlan<C>, Plan>
unaryPlan(PatternDescriptor<C, Plan> child) {
return new PatternDescriptor(new TypePattern(UnaryPlanOperator.class, child.pattern), defaultPromise());
}
/**
* create a binaryPlan pattern.
*/
default PatternDescriptor<BinaryPlan<Plan, Plan>, Plan> binaryPlan() {
return new PatternDescriptor(
new TypePattern(BinaryPlanOperator.class, Pattern.FIXED, Pattern.FIXED),
defaultPromise()
);
}
/**
* create a logicalFilter pattern.
* create a binaryPlan pattern.
*/
default PatternDescriptor<LogicalUnary<LogicalFilter, Plan>, Plan> logicalFilter() {
return new PatternDescriptor<>(
new Pattern<>(OperatorType.LOGICAL_FILTER, new Pattern<>(OperatorType.FIXED)),
default <LEFT_CHILD_TYPE extends Plan, RIGHT_CHILD_TYPE extends Plan>
PatternDescriptor<BinaryPlan<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE>, Plan> binaryPlan(
PatternDescriptor<LEFT_CHILD_TYPE, Plan> leftChild,
PatternDescriptor<RIGHT_CHILD_TYPE, Plan> rightChild) {
return new PatternDescriptor(
new TypePattern(BinaryPlanOperator.class, leftChild.pattern, rightChild.pattern),
defaultPromise()
);
}
/* abstract logical operator patterns */
/**
* create a logicalLeaf pattern.
*/
default PatternDescriptor<LogicalLeafPlan<LogicalLeafOperator>, Plan> logicalLeaf() {
return new PatternDescriptor(new TypePattern(LogicalLeafPlan.class), defaultPromise());
}
/**
* create a logicalUnary pattern.
*/
default PatternDescriptor<LogicalUnaryPlan<LogicalUnaryOperator, Plan>, Plan> logicalUnary() {
return new PatternDescriptor(new TypePattern(LogicalUnaryPlan.class, Pattern.FIXED), defaultPromise());
}
/**
* create a logicalUnary pattern.
*/
default <C extends Plan> PatternDescriptor<LogicalUnaryPlan<LogicalUnaryOperator, C>, Plan>
logicalUnary(PatternDescriptor<C, Plan> child) {
return new PatternDescriptor(new TypePattern(LogicalUnaryPlan.class, child.pattern), defaultPromise());
}
/**
* create a logicalBinary pattern.
*/
default PatternDescriptor<LogicalBinaryPlan<LogicalBinaryOperator, Plan, Plan>, Plan> logicalBinary() {
return new PatternDescriptor(
new TypePattern(LogicalBinaryPlan.class, Pattern.FIXED, Pattern.FIXED),
defaultPromise()
);
}
/**
* create a logicalFilter pattern with child pattern.
* create a logicalBinary pattern.
*/
default <T extends Plan> PatternDescriptor<LogicalUnary<LogicalFilter, T>, Plan>
logicalFilter(PatternDescriptor<T, Plan> childPattern) {
return new PatternDescriptor<>(
new Pattern<>(OperatorType.LOGICAL_FILTER, childPattern.pattern),
default <LEFT_CHILD_TYPE extends Plan, RIGHT_CHILD_TYPE extends Plan>
PatternDescriptor<LogicalBinaryPlan<LogicalBinaryOperator, LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE>, Plan>
logicalBinary(
PatternDescriptor<LEFT_CHILD_TYPE, Plan> leftChild,
PatternDescriptor<RIGHT_CHILD_TYPE, Plan> rightChild) {
return new PatternDescriptor(
new TypePattern(LogicalBinaryPlan.class, leftChild.pattern, rightChild.pattern),
defaultPromise()
);
}
/* abstract physical operator patterns */
/**
* create a physicalLeaf pattern.
*/
default PatternDescriptor<PhysicalLeafPlan<PhysicalLeafOperator>, Plan> physicalLeaf() {
return new PatternDescriptor(new TypePattern(PhysicalLeafPlan.class), defaultPromise());
}
/**
* create a physicalUnary pattern.
*/
default PatternDescriptor<PhysicalUnaryPlan<PhysicalUnaryOperator, Plan>, Plan> physicalUnary() {
return new PatternDescriptor(new TypePattern(PhysicalUnaryPlan.class, Pattern.FIXED), defaultPromise());
}
/**
* create a physicalUnary pattern.
*/
default <C extends Plan> PatternDescriptor<PhysicalUnaryPlan<PhysicalUnaryOperator, C>, Plan>
physicalUnary(PatternDescriptor<C, Plan> child) {
return new PatternDescriptor(new TypePattern(PhysicalUnaryPlan.class, child.pattern), defaultPromise());
}
/**
* create a physicalBinary pattern.
*/
default PatternDescriptor<PhysicalBinaryPlan<PhysicalBinaryOperator, Plan, Plan>, Plan> physicalBinary() {
return new PatternDescriptor(
new TypePattern(PhysicalBinaryPlan.class, Pattern.FIXED, Pattern.FIXED),
defaultPromise()
);
}
/**
* create a logicalProject pattern.
* create a physicalBinary pattern.
*/
default PatternDescriptor<LogicalUnary<LogicalProject, Plan>, Plan> logicalProject() {
return new PatternDescriptor<>(
new Pattern<>(OperatorType.LOGICAL_PROJECT, new Pattern<>(OperatorType.FIXED)),
default <LEFT_CHILD_TYPE extends Plan, RIGHT_CHILD_TYPE extends Plan>
PatternDescriptor<PhysicalBinaryPlan<PhysicalBinaryOperator, LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE>, Plan>
physicalBinary(
PatternDescriptor<LEFT_CHILD_TYPE, Plan> leftChild,
PatternDescriptor<RIGHT_CHILD_TYPE, Plan> rightChild) {
return new PatternDescriptor(
new TypePattern(PhysicalBinaryPlan.class, leftChild.pattern, rightChild.pattern),
defaultPromise()
);
}
/**
* create a logicalProject pattern.
* create a physicalScan pattern.
*/
default <T extends Plan> PatternDescriptor<LogicalUnary<LogicalProject, T>, Plan>
logicalProject(PatternDescriptor<T, Plan> childPattern) {
return new PatternDescriptor<>(
new Pattern<>(OperatorType.LOGICAL_PROJECT, childPattern.pattern),
defaultPromise()
);
}
/**
* create a logicalJoin pattern.
*/
default PatternDescriptor<LogicalBinary<LogicalJoin, Plan, Plan>, Plan> logicalJoin() {
return new PatternDescriptor<>(
new Pattern<>(OperatorType.LOGICAL_JOIN,
new Pattern<>(OperatorType.FIXED), new Pattern<>(OperatorType.FIXED)),
defaultPromise()
);
}
/**
* create a logicalJoin pattern with join type.
*/
default PatternDescriptor<LogicalBinary<LogicalJoin, Plan, Plan>, Plan> logicalJoin(JoinType joinType) {
return new PatternDescriptor<LogicalBinary<LogicalJoin, Plan, Plan>, Plan>(
new Pattern<>(OperatorType.LOGICAL_JOIN,
new Pattern<>(OperatorType.FIXED), new Pattern<>(OperatorType.FIXED)),
defaultPromise()
).when(j -> j.operator.getJoinType() == joinType);
}
/**
* create a logicalJoin pattern with joinType and children patterns.
*/
default <C1 extends Plan, C2 extends Plan>
PatternDescriptor<LogicalBinary<LogicalJoin, C1, C2>, Plan> logicalJoin(
JoinType joinType, PatternDescriptor<C1, Plan> leftChildPattern,
PatternDescriptor<C2, Plan> rightChildPattern) {
return new PatternDescriptor<LogicalBinary<LogicalJoin, C1, C2>, Plan>(
new Pattern<>(OperatorType.LOGICAL_JOIN, leftChildPattern.pattern, rightChildPattern.pattern),
defaultPromise()
).when(j -> j.operator.getJoinType() == joinType);
}
/**
* create a logicalJoin pattern with children patterns.
*/
default <C1 extends Plan, C2 extends Plan>
PatternDescriptor<LogicalBinary<LogicalJoin, C1, C2>, Plan> logicalJoin(
PatternDescriptor<C1, Plan> leftChildPattern, PatternDescriptor<C2, Plan> rightChildPattern) {
return new PatternDescriptor<>(
new Pattern<>(OperatorType.LOGICAL_JOIN, leftChildPattern.pattern, rightChildPattern.pattern),
defaultPromise()
);
}
/**
* create a logicalJoin pattern with joinType is inner.
*/
default PatternDescriptor<LogicalBinary<LogicalJoin, Plan, Plan>, Plan> innerLogicalJoin() {
return new PatternDescriptor<LogicalBinary<LogicalJoin, Plan, Plan>, Plan>(
new Pattern<>(OperatorType.LOGICAL_JOIN,
new Pattern<>(OperatorType.FIXED), new Pattern<>(OperatorType.FIXED)),
defaultPromise()
).when(j -> j.operator.getJoinType() == JoinType.INNER_JOIN);
}
/**
* create a logical join pattern with join type is inner and children patterns.
*/
default <C1 extends Plan, C2 extends Plan>
PatternDescriptor<LogicalBinary<LogicalJoin, C1, C2>, Plan> innerLogicalJoin(
PatternDescriptor<C1, Plan> leftChildPattern, PatternDescriptor<C2, Plan> rightChildPattern) {
return new PatternDescriptor<LogicalBinary<LogicalJoin, C1, C2>, Plan>(
new Pattern<>(OperatorType.LOGICAL_JOIN, leftChildPattern.pattern, rightChildPattern.pattern),
defaultPromise()
).when(j -> j.operator.getJoinType() == JoinType.INNER_JOIN);
}
/**
* create a logicalRelation pattern.
*/
default PatternDescriptor<LogicalLeaf<LogicalRelation>, Plan> logicalRelation() {
return new PatternDescriptor<>(
new Pattern<>(OperatorType.LOGICAL_BOUND_RELATION),
defaultPromise()
);
}
// physical pattern descriptors
/**
* create a physicalFilter pattern.
*/
default PatternDescriptor<PhysicalUnary<PhysicalFilter, Plan>, Plan> physicalFilter() {
return new PatternDescriptor<>(
new Pattern<>(OperatorType.PHYSICAL_FILTER, new Pattern<>(OperatorType.FIXED)),
defaultPromise()
);
}
/**
* create a physicalFilter pattern with child pattern.
*/
default <T extends Plan> PatternDescriptor<PhysicalUnary<PhysicalFilter, T>, Plan>
physicalFilter(PatternDescriptor<T, Plan> childPattern) {
return new PatternDescriptor<>(
new Pattern<>(OperatorType.PHYSICAL_FILTER, childPattern.pattern),
defaultPromise()
);
}
/**
* create a physicalProject pattern.
*/
default PatternDescriptor<PhysicalUnary<PhysicalProject, Plan>, Plan> physicalProject() {
return new PatternDescriptor<>(
new Pattern<>(OperatorType.PHYSICAL_PROJECT, new Pattern<>(OperatorType.FIXED)),
defaultPromise()
);
}
/**
* create a physicalProject pattern with child pattern.
*/
default <T extends Plan> PatternDescriptor<PhysicalUnary<PhysicalProject, T>, Plan>
physicalProject(PatternDescriptor<T, Plan> childPattern) {
return new PatternDescriptor<>(
new Pattern<>(OperatorType.PHYSICAL_PROJECT, childPattern.pattern),
defaultPromise()
);
}
/**
* create a physicalBroadcastHashJoin pattern.
*/
default PatternDescriptor<PhysicalBinary<PhysicalBroadcastHashJoin, Plan, Plan>, Plan>
physicalBroadcastHashJoin() {
return new PatternDescriptor<>(
new Pattern<>(OperatorType.PHYSICAL_BROADCAST_HASH_JOIN,
new Pattern<>(OperatorType.FIXED), new Pattern<>(OperatorType.FIXED)),
defaultPromise()
);
}
/**
* create a physicalBroadcastHashJoin pattern with children patterns.
*/
default <C1 extends Plan, C2 extends Plan>
PatternDescriptor<PhysicalBinary<PhysicalBroadcastHashJoin, C1, C2>, Plan>
physicalBroadcastHashJoin(PatternDescriptor<C1, Plan> leftChildPattern,
PatternDescriptor<C2, Plan> rightChildPattern) {
return new PatternDescriptor<>(
new Pattern<>(OperatorType.PHYSICAL_BROADCAST_HASH_JOIN,
leftChildPattern.pattern,
rightChildPattern.pattern
),
defaultPromise()
);
}
/**
* create a physicalOlapScan pattern.
*/
default PatternDescriptor<PhysicalLeaf<PhysicalOlapScan>, Plan> physicalOlapScan() {
return new PatternDescriptor<>(
new Pattern<>(OperatorType.PHYSICAL_OLAP_SCAN),
defaultPromise()
);
default PatternDescriptor<PhysicalLeafPlan<PhysicalScan>, Plan> physicalScan() {
return new PatternDescriptor(new TypePattern(PhysicalScan.class), defaultPromise());
}
}

View File

@ -0,0 +1,57 @@
// 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.doris.nereids.pattern;
import org.apache.doris.nereids.operators.Operator;
import org.apache.doris.nereids.operators.OperatorType;
import org.apache.doris.nereids.trees.TreeNode;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
/** pattern that used to match class type. */
public class TypePattern<TYPE extends NODE_TYPE, NODE_TYPE extends TreeNode<NODE_TYPE>>
extends Pattern<TYPE, NODE_TYPE> {
protected final Class<TYPE> type;
public TypePattern(Class<TYPE> clazz, Pattern... children) {
super(OperatorType.NORMAL_PATTERN, children);
this.type = Objects.requireNonNull(clazz, "class can not be null");
}
public TypePattern(Class<TYPE> clazz, List<Predicate<TYPE>> predicates, Pattern... children) {
super(OperatorType.NORMAL_PATTERN, predicates, children);
this.type = Objects.requireNonNull(clazz, "class can not be null");
}
@Override
protected boolean doMatchRoot(TYPE root) {
return type.isInstance(root) && predicates.stream().allMatch(predicate -> predicate.test(root));
}
@Override
public TypePattern<TYPE, NODE_TYPE> withPredicates(List<Predicate<TYPE>> predicates) {
return new TypePattern(type, predicates, children.toArray(new Pattern[0]));
}
@Override
public boolean matchOperator(Operator operator) {
return type.isInstance(operator);
}
}

View File

@ -0,0 +1,445 @@
// 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.doris.nereids.pattern.generator;
import org.apache.doris.nereids.JavaParser.ClassBodyDeclarationContext;
import org.apache.doris.nereids.JavaParser.ClassDeclarationContext;
import org.apache.doris.nereids.JavaParser.ClassOrInterfaceModifierContext;
import org.apache.doris.nereids.JavaParser.ClassOrInterfaceTypeContext;
import org.apache.doris.nereids.JavaParser.EnumConstantContext;
import org.apache.doris.nereids.JavaParser.EnumDeclarationContext;
import org.apache.doris.nereids.JavaParser.FieldDeclarationContext;
import org.apache.doris.nereids.JavaParser.FormalParameterListContext;
import org.apache.doris.nereids.JavaParser.IdentifierAndTypeArgumentsContext;
import org.apache.doris.nereids.JavaParser.IdentifierContext;
import org.apache.doris.nereids.JavaParser.ImportDeclarationContext;
import org.apache.doris.nereids.JavaParser.InterfaceDeclarationContext;
import org.apache.doris.nereids.JavaParser.MemberDeclarationContext;
import org.apache.doris.nereids.JavaParser.MethodDeclarationContext;
import org.apache.doris.nereids.JavaParser.PackageDeclarationContext;
import org.apache.doris.nereids.JavaParser.PrimitiveTypeContext;
import org.apache.doris.nereids.JavaParser.QualifiedNameContext;
import org.apache.doris.nereids.JavaParser.TypeArgumentContext;
import org.apache.doris.nereids.JavaParser.TypeArgumentsContext;
import org.apache.doris.nereids.JavaParser.TypeBoundContext;
import org.apache.doris.nereids.JavaParser.TypeDeclarationContext;
import org.apache.doris.nereids.JavaParser.TypeListContext;
import org.apache.doris.nereids.JavaParser.TypeParameterContext;
import org.apache.doris.nereids.JavaParser.TypeParametersContext;
import org.apache.doris.nereids.JavaParser.TypeTypeContext;
import org.apache.doris.nereids.JavaParser.TypeTypeOrVoidContext;
import org.apache.doris.nereids.JavaParser.VariableDeclaratorContext;
import org.apache.doris.nereids.JavaParser.VariableDeclaratorIdContext;
import org.apache.doris.nereids.JavaParser.VariableDeclaratorsContext;
import org.apache.doris.nereids.JavaParserBaseVisitor;
import org.apache.doris.nereids.pattern.generator.javaast.ClassDeclaration;
import org.apache.doris.nereids.pattern.generator.javaast.ClassOrInterfaceModifier;
import org.apache.doris.nereids.pattern.generator.javaast.ClassOrInterfaceType;
import org.apache.doris.nereids.pattern.generator.javaast.EnumConstant;
import org.apache.doris.nereids.pattern.generator.javaast.EnumDeclaration;
import org.apache.doris.nereids.pattern.generator.javaast.FieldDeclaration;
import org.apache.doris.nereids.pattern.generator.javaast.IdentifyTypeArgumentsPair;
import org.apache.doris.nereids.pattern.generator.javaast.ImportDeclaration;
import org.apache.doris.nereids.pattern.generator.javaast.InterfaceDeclaration;
import org.apache.doris.nereids.pattern.generator.javaast.JavaAstNode;
import org.apache.doris.nereids.pattern.generator.javaast.MethodDeclaration;
import org.apache.doris.nereids.pattern.generator.javaast.QualifiedName;
import org.apache.doris.nereids.pattern.generator.javaast.TypeArgument;
import org.apache.doris.nereids.pattern.generator.javaast.TypeArgument.ArgType;
import org.apache.doris.nereids.pattern.generator.javaast.TypeArguments;
import org.apache.doris.nereids.pattern.generator.javaast.TypeBound;
import org.apache.doris.nereids.pattern.generator.javaast.TypeDeclaration;
import org.apache.doris.nereids.pattern.generator.javaast.TypeParameter;
import org.apache.doris.nereids.pattern.generator.javaast.TypeParameters;
import org.apache.doris.nereids.pattern.generator.javaast.TypeType;
import org.apache.doris.nereids.pattern.generator.javaast.TypeTypeOrVoid;
import org.apache.doris.nereids.pattern.generator.javaast.VariableDeclarator;
import org.apache.doris.nereids.pattern.generator.javaast.VariableDeclaratorId;
import org.apache.doris.nereids.pattern.generator.javaast.VariableDeclarators;
import org.antlr.v4.runtime.ParserRuleContext;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Stack;
/**
* Used to build a copy from antlr ast.
*/
public class JavaAstBuilder extends JavaParserBaseVisitor<JavaAstNode> {
Optional<QualifiedName> packageName = Optional.empty();
List<ImportDeclaration> importDeclarations = new ArrayList<>();
List<TypeDeclaration> rootTypeDeclarations = new ArrayList<>();
Stack<List<TypeDeclaration>> childrenStack = new Stack<>();
public List<TypeDeclaration> build(ParserRuleContext tree) {
visit(tree);
return rootTypeDeclarations;
}
@Override
public JavaAstNode visitPackageDeclaration(PackageDeclarationContext ctx) {
packageName = Optional.of(visitQualifiedName(ctx.qualifiedName()));
return null;
}
@Override
public ImportDeclaration visitImportDeclaration(ImportDeclarationContext ctx) {
ImportDeclaration importDeclaration = new ImportDeclaration(ctx.STATIC() != null,
visitQualifiedName(ctx.qualifiedName()), ctx.importStar() != null);
importDeclarations.add(importDeclaration);
return importDeclaration;
}
@Override
public JavaAstNode visitTypeDeclaration(TypeDeclarationContext ctx) {
ClassOrInterfaceModifier modifier = mergeModifiers(ctx.classOrInterfaceModifier());
if (ctx.classDeclaration() != null) {
return visitClassDeclaration(ctx.classDeclaration(), modifier);
} else if (ctx.interfaceDeclaration() != null) {
return visitInterfaceDeclaration(ctx.interfaceDeclaration(), modifier);
} else if (ctx.enumDeclaration() != null) {
return visitEnumDeclaration(ctx.enumDeclaration(), modifier);
} else {
return null;
}
}
/** create enum declaration. */
public EnumDeclaration visitEnumDeclaration(EnumDeclarationContext ctx, ClassOrInterfaceModifier modifier) {
List<TypeType> implementTypes = new ArrayList<>();
if (ctx.IMPLEMENTS() != null) {
implementTypes = getTypes(ctx.typeList());
}
List<EnumConstant> enumConstants = new ArrayList<>();
if (ctx.enumConstants() != null) {
enumConstants = visit(EnumConstant.class, ctx.enumConstants().enumConstant());
}
childrenStack.add(new ArrayList<>());
if (ctx.enumBodyDeclarations() != null) {
// find inner class
ctx.enumBodyDeclarations().accept(this);
}
String enumName = getText(ctx.identifier());
EnumDeclaration enumDeclaration = new EnumDeclaration(packageName.orElse(null),
importDeclarations, modifier, enumName, implementTypes, enumConstants, childrenStack.pop());
addTypeDeclaration(enumDeclaration);
return enumDeclaration;
}
@Override
public EnumConstant visitEnumConstant(EnumConstantContext ctx) {
return new EnumConstant(getText(ctx.identifier()));
}
/** create interface declaration. */
public InterfaceDeclaration visitInterfaceDeclaration(
InterfaceDeclarationContext ctx, ClassOrInterfaceModifier modifier) {
TypeParameters typeParameters = null;
if (ctx.typeParameters() != null) {
typeParameters = visitTypeParameters(ctx.typeParameters());
}
List<TypeType> extendsTypes = new ArrayList<>();
if (ctx.EXTENDS() != null) {
extendsTypes = getTypes(ctx.typeList().get(0));
}
childrenStack.add(new ArrayList<>());
// find inner class
ctx.interfaceBody().accept(this);
String interfaceName = getText(ctx.identifier());
InterfaceDeclaration interfaceDeclaration = new InterfaceDeclaration(packageName.orElse(null),
importDeclarations, modifier, interfaceName, typeParameters, extendsTypes, childrenStack.pop());
addTypeDeclaration(interfaceDeclaration);
return interfaceDeclaration;
}
/** create class declaration. */
public ClassDeclaration visitClassDeclaration(ClassDeclarationContext ctx, ClassOrInterfaceModifier modifier) {
TypeParameters typeParameters = null;
if (ctx.typeParameters() != null) {
typeParameters = visitTypeParameters(ctx.typeParameters());
}
TypeType extendsType = null;
if (ctx.EXTENDS() != null) {
extendsType = visitTypeType(ctx.typeType());
}
List<TypeType> implementTypes = new ArrayList<>();
if (ctx.IMPLEMENTS() != null) {
implementTypes = getTypes(ctx.typeList().get(0));
}
childrenStack.add(new ArrayList<>());
List<FieldDeclaration> fieldDeclarations = new ArrayList<>();
List<MethodDeclaration> methodDeclarations = new ArrayList<>();
for (ClassBodyDeclarationContext classBodyCtx : ctx.classBody().classBodyDeclaration()) {
MemberDeclarationContext memberCtx = classBodyCtx.memberDeclaration();
if (memberCtx != null) {
if (memberCtx.fieldDeclaration() != null) {
fieldDeclarations.add(visitFieldDeclaration(memberCtx.fieldDeclaration()));
continue;
} else if (memberCtx.methodDeclaration() != null) {
methodDeclarations.add(visitMethodDeclaration(memberCtx.methodDeclaration()));
}
}
// find inner class
memberCtx.accept(this);
}
String className = getText(ctx.identifier());
ClassDeclaration classDeclaration = new ClassDeclaration(
packageName.orElse(null), importDeclarations,
modifier, className, typeParameters, extendsType, implementTypes,
fieldDeclarations, methodDeclarations, childrenStack.pop());
addTypeDeclaration(classDeclaration);
return classDeclaration;
}
@Override
public ClassOrInterfaceModifier visitClassOrInterfaceModifier(ClassOrInterfaceModifierContext ctx) {
int mod = 0;
if (ctx.PUBLIC() != null) {
mod |= Modifier.PUBLIC;
} else if (ctx.PROTECTED() != null) {
mod |= Modifier.PROTECTED;
} else if (ctx.PRIVATE() != null) {
mod |= Modifier.PRIVATE;
} else if (ctx.STATIC() != null) {
mod |= Modifier.STATIC;
} else if (ctx.ABSTRACT() != null) {
mod |= Modifier.ABSTRACT;
} else if (ctx.ABSTRACT() != null) {
mod |= Modifier.FINAL;
}
return new ClassOrInterfaceModifier(mod);
}
@Override
public FieldDeclaration visitFieldDeclaration(FieldDeclarationContext ctx) {
TypeType typeType = visitTypeType(ctx.typeType());
VariableDeclarators variableDeclarators = visitVariableDeclarators(ctx.variableDeclarators());
return new FieldDeclaration(typeType, variableDeclarators);
}
@Override
public MethodDeclaration visitMethodDeclaration(MethodDeclarationContext ctx) {
TypeTypeOrVoid typeTypeOrVoid = visitTypeTypeOrVoid(ctx.typeTypeOrVoid());
String identifier = getText(ctx.identifier());
int paramNum = 0;
FormalParameterListContext paramListCtx = ctx.formalParameters().formalParameterList();
if (paramListCtx != null && paramListCtx.formalParameter() != null) {
paramNum = paramListCtx.formalParameter().size() + 1; // + lastFormalParameter
}
return new MethodDeclaration(typeTypeOrVoid, identifier, paramNum);
}
@Override
public TypeTypeOrVoid visitTypeTypeOrVoid(TypeTypeOrVoidContext ctx) {
TypeType typeType = null;
if (ctx.typeType() != null) {
typeType = visitTypeType(ctx.typeType());
}
return new TypeTypeOrVoid(typeType, ctx.VOID() != null);
}
@Override
public VariableDeclarators visitVariableDeclarators(VariableDeclaratorsContext ctx) {
List<VariableDeclarator> vars = visit(VariableDeclarator.class, ctx.variableDeclarator());
return new VariableDeclarators(vars);
}
@Override
public VariableDeclarator visitVariableDeclarator(VariableDeclaratorContext ctx) {
VariableDeclaratorId id = visitVariableDeclaratorId(ctx.variableDeclaratorId());
return new VariableDeclarator(id);
}
@Override
public VariableDeclaratorId visitVariableDeclaratorId(VariableDeclaratorIdContext ctx) {
String text = getText(ctx.identifier());
int arrayDimension = ctx.arrayDeclarator().size();
return new VariableDeclaratorId(text, arrayDimension);
}
@Override
public ClassOrInterfaceType visitClassOrInterfaceType(ClassOrInterfaceTypeContext ctx) {
List<IdentifyTypeArgumentsPair> pairs = new ArrayList<>();
for (IdentifierAndTypeArgumentsContext identifierAndTypeArgument : ctx.identifierAndTypeArguments()) {
String identifier = getText(identifierAndTypeArgument.identifier());
TypeArguments typeArguments = null;
if (identifierAndTypeArgument.typeArguments() != null) {
typeArguments = visitTypeArguments(identifierAndTypeArgument.typeArguments());
}
pairs.add(new IdentifyTypeArgumentsPair(identifier, typeArguments));
}
return new ClassOrInterfaceType(pairs);
}
@Override
public TypeParameters visitTypeParameters(TypeParametersContext ctx) {
List<TypeParameter> typeParameters = new ArrayList<>();
for (TypeParameterContext typeParameterContext : ctx.typeParameter()) {
typeParameters.add(visitTypeParameter(typeParameterContext));
}
return new TypeParameters(typeParameters);
}
@Override
public TypeParameter visitTypeParameter(TypeParameterContext ctx) {
String identifier = getText(ctx.identifier());
TypeBound typeBound = null;
if (ctx.typeBound() != null) {
typeBound = visitTypeBound(ctx.typeBound());
}
return new TypeParameter(identifier, typeBound);
}
@Override
public TypeBound visitTypeBound(TypeBoundContext ctx) {
List<TypeType> typeParameters = new ArrayList<>();
for (TypeTypeContext typeTypeContext : ctx.typeType()) {
typeParameters.add(visitTypeType(typeTypeContext));
}
return new TypeBound(typeParameters);
}
@Override
public TypeArguments visitTypeArguments(TypeArgumentsContext ctx) {
List<TypeArgument> typeArguments = new ArrayList<>();
for (TypeArgumentContext typeArgumentContext : ctx.typeArgument()) {
typeArguments.add(visitTypeArgument(typeArgumentContext));
}
return new TypeArguments(typeArguments);
}
@Override
public TypeArgument visitTypeArgument(TypeArgumentContext ctx) {
TypeType typeType = null;
ArgType argType = ArgType.UNKNOWN;
if (ctx.typeType() != null) {
typeType = visitTypeType(ctx.typeType());
if (ctx.EXTENDS() != null) {
argType = ArgType.EXTENDS;
} else if (ctx.SUPER() != null) {
argType = ArgType.SUPER;
} else {
argType = ArgType.NORMAL;
}
}
return new TypeArgument(argType, typeType);
}
@Override
public TypeType visitTypeType(TypeTypeContext ctx) {
ClassOrInterfaceType classOrInterfaceType = null;
if (ctx.classOrInterfaceType() != null) {
classOrInterfaceType = visitClassOrInterfaceType(ctx.classOrInterfaceType());
}
String primitiveType = null;
if (ctx.primitiveType() != null) {
primitiveType = getText(ctx.primitiveType());
}
return new TypeType(classOrInterfaceType, primitiveType);
}
@Override
public QualifiedName visitQualifiedName(QualifiedNameContext ctx) {
List<String> identifiers = new ArrayList<>();
for (IdentifierContext identifierContext : ctx.identifier()) {
identifiers.add(getText(identifierContext));
}
return new QualifiedName(identifiers);
}
/** merge modifiers, e.g public + static + final. */
public ClassOrInterfaceModifier mergeModifiers(List<ClassOrInterfaceModifierContext> contexts) {
int mod = 0;
for (ClassOrInterfaceModifierContext context : contexts) {
ClassOrInterfaceModifier modifier = visitClassOrInterfaceModifier(context);
mod |= modifier.mod;
}
return new ClassOrInterfaceModifier(mod);
}
/** create a type list. */
public List<TypeType> getTypes(TypeListContext typeListContext) {
List<TypeType> types = new ArrayList<>();
for (TypeTypeContext typeTypeContext : typeListContext.typeType()) {
types.add(visitTypeType(typeTypeContext));
}
return types;
}
/** create a List by class and contexts. */
public <T extends JavaAstNode, C extends ParserRuleContext> List<T> visit(Class<T> clazz, List<C> contexts) {
List<T> list = new ArrayList<>();
for (C ctx : contexts) {
list.add((T) ctx.accept(this));
}
return list;
}
public String getText(IdentifierContext ctx) {
return ctx.getText();
}
public String getText(PrimitiveTypeContext ctx) {
return ctx.getText();
}
private void addTypeDeclaration(TypeDeclaration typeDeclaration) {
if (!childrenStack.isEmpty()) {
childrenStack.peek().add(typeDeclaration);
} else {
rootTypeDeclarations.add(typeDeclaration);
}
}
/** get full qualified name, e.g. OuterClassName.InnerClassName. */
public static String getFullQualifiedName(Stack<String> outerClassStack,
Optional<QualifiedName> packageName, String name) {
if (!outerClassStack.isEmpty()) {
return outerClassStack.peek() + "." + name;
}
return TypeDeclaration.getFullQualifiedName(packageName, name);
}
class OuterClass {
public final Optional<QualifiedName> packageName;
public final String name;
public OuterClass(Optional<QualifiedName> packageName, String name) {
this.packageName = packageName;
this.name = name;
}
}
}

View File

@ -0,0 +1,65 @@
// 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.doris.nereids.pattern.generator;
import org.apache.doris.nereids.pattern.generator.javaast.ClassDeclaration;
import java.util.Set;
import java.util.TreeSet;
/** used to generate pattern for LogicalBinaryOperator. */
public class LogicalBinaryPatternGenerator extends PatternGenerator {
public LogicalBinaryPatternGenerator(PatternGeneratorAnalyzer analyzer,
ClassDeclaration opType, Set<String> parentClass) {
super(analyzer, opType, parentClass);
}
@Override
public String genericType() {
return "<LogicalBinaryPlan<" + opType.name + ", Plan, Plan>, Plan>";
}
@Override
public String genericTypeWithChildren() {
return "<LogicalBinaryPlan<" + opType.name + ", C1, C2>, Plan>";
}
@Override
public Set<String> getImports() {
Set<String> imports = new TreeSet<>();
imports.add(opType.getFullQualifiedName());
imports.add("org.apache.doris.nereids.operators.OperatorType");
imports.add("org.apache.doris.nereids.trees.plans.Plan");
imports.add("org.apache.doris.nereids.trees.plans.logical.LogicalBinaryPlan");
enumFieldPatternInfos.stream()
.map(info -> info.enumFullName)
.forEach(imports::add);
return imports;
}
@Override
public boolean isLogical() {
return true;
}
@Override
public int childrenNum() {
return 2;
}
}

View File

@ -0,0 +1,82 @@
// 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.doris.nereids.pattern.generator;
import org.apache.doris.nereids.pattern.generator.javaast.ClassDeclaration;
import java.util.Set;
import java.util.TreeSet;
/** used to generate pattern for LogicalLeafOperator. */
public class LogicalLeafPatternGenerator extends PatternGenerator {
public LogicalLeafPatternGenerator(PatternGeneratorAnalyzer analyzer,
ClassDeclaration opType, Set<String> parentClass) {
super(analyzer, opType, parentClass);
}
@Override
public String generate() {
String opClassName = opType.name;
String methodName = getPatternMethodName();
String patternParam = "<LogicalLeafPlan<" + opClassName + ">, Plan>";
generateTypePattern(methodName, opClassName, patternParam, "", false);
for (EnumFieldPatternInfo info : enumFieldPatternInfos) {
String predicate = ".when(p -> p.operator." + info.enumInstanceGetter + "() == "
+ info.enumType + "." + info.enumInstance + ")";
generateTypePattern(info.patternName, opClassName, patternParam, predicate, false);
}
return generatePatterns();
}
@Override
public String genericType() {
return "<LogicalLeafPlan<" + opType.name + ">, Plan>";
}
@Override
public String genericTypeWithChildren() {
throw new IllegalStateException("Can not get children generic type by LogicalLeafPlan");
}
@Override
public Set<String> getImports() {
Set<String> imports = new TreeSet<>();
imports.add(opType.getFullQualifiedName());
imports.add("org.apache.doris.nereids.trees.plans.Plan");
imports.add("org.apache.doris.nereids.trees.plans.logical.LogicalLeafPlan");
enumFieldPatternInfos.stream()
.map(info -> info.enumFullName)
.forEach(imports::add);
return imports;
}
@Override
public boolean isLogical() {
return true;
}
@Override
public int childrenNum() {
return 0;
}
}

View File

@ -0,0 +1,65 @@
// 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.doris.nereids.pattern.generator;
import org.apache.doris.nereids.pattern.generator.javaast.ClassDeclaration;
import java.util.Set;
import java.util.TreeSet;
/** used to generate pattern for LogicalUnaryOperator. */
public class LogicalUnaryPatternGenerator extends PatternGenerator {
public LogicalUnaryPatternGenerator(PatternGeneratorAnalyzer analyzer,
ClassDeclaration opType, Set<String> parentClass) {
super(analyzer, opType, parentClass);
}
@Override
public String genericType() {
return "<LogicalUnaryPlan<" + opType.name + ", Plan>, Plan>";
}
@Override
public String genericTypeWithChildren() {
return "<LogicalUnaryPlan<" + opType.name + ", C1>, Plan>";
}
@Override
public Set<String> getImports() {
Set<String> imports = new TreeSet<>();
imports.add(opType.getFullQualifiedName());
imports.add("org.apache.doris.nereids.operators.OperatorType");
imports.add("org.apache.doris.nereids.trees.plans.Plan");
imports.add("org.apache.doris.nereids.trees.plans.logical.LogicalUnaryPlan");
enumFieldPatternInfos.stream()
.map(info -> info.enumFullName)
.forEach(imports::add);
return imports;
}
@Override
public boolean isLogical() {
return true;
}
@Override
public int childrenNum() {
return 1;
}
}

View File

@ -0,0 +1,29 @@
// 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.doris.nereids.pattern.generator;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** used to trigger PatternDescribableProcessor. */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface PatternDescribable {
}

View File

@ -0,0 +1,23 @@
// 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.doris.nereids.pattern.generator;
/** just for process entry point. */
@PatternDescribable
public class PatternDescribableProcessPoint {
}

View File

@ -0,0 +1,157 @@
// 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.doris.nereids.pattern.generator;
import org.apache.doris.nereids.JavaLexer;
import org.apache.doris.nereids.JavaParser;
import org.apache.doris.nereids.pattern.generator.javaast.TypeDeclaration;
import com.google.common.base.Throwables;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.DefaultErrorStrategy;
import org.antlr.v4.runtime.InputMismatchException;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.atn.PredictionMode;
import org.antlr.v4.runtime.misc.ParseCancellationException;
import org.apache.commons.io.FileUtils;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;
import javax.tools.StandardLocation;
/**
* annotation processor for generate GeneratedPattern.java.
*/
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes("org.apache.doris.nereids.pattern.generator.PatternDescribable")
public class PatternDescribableProcessor extends AbstractProcessor {
private List<File> operatorPaths;
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
this.operatorPaths = Arrays.stream(processingEnv.getOptions().get("operatorPath").split(","))
.map(path -> path.trim())
.filter(path -> !path.isEmpty())
.collect(Collectors.toSet())
.stream()
.map(path -> new File(path))
.collect(Collectors.toList());
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (annotations.isEmpty()) {
return false;
}
try {
List<File> operatorFiles = findJavaFiles(operatorPaths);
PatternGeneratorAnalyzer patternGeneratorAnalyzer = new PatternGeneratorAnalyzer();
for (File file : operatorFiles) {
List<TypeDeclaration> asts = parseJavaFile(file);
patternGeneratorAnalyzer.addAsts(asts);
}
String generatePatternCode = patternGeneratorAnalyzer.generatePatterns();
File generatePatternFile = new File(processingEnv.getFiler()
.getResource(StandardLocation.SOURCE_OUTPUT, "org.apache.doris.nereids.pattern",
"GeneratedPatterns.java").toUri());
if (generatePatternFile.exists()) {
generatePatternFile.delete();
}
if (!generatePatternFile.getParentFile().exists()) {
generatePatternFile.getParentFile().mkdirs();
}
// bypass create file for processingEnv.getFiler(), compile GeneratePatterns in next compile term
try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(generatePatternFile))) {
bufferedWriter.write(generatePatternCode);
}
} catch (Throwable t) {
String exceptionMsg = Throwables.getStackTraceAsString(t);
processingEnv.getMessager().printMessage(Kind.ERROR,
"Analyze and generate patterns failed:\n" + exceptionMsg);
}
return false;
}
private List<File> findJavaFiles(List<File> dirs) {
List<File> files = new ArrayList<>();
for (File dir : dirs) {
files.addAll(FileUtils.listFiles(dir, new String[] {"java"}, true));
}
return files;
}
private List<TypeDeclaration> parseJavaFile(File javaFile) throws IOException {
String javaCodeString = FileUtils.readFileToString(javaFile, StandardCharsets.UTF_8);
JavaLexer lexer = new JavaLexer(CharStreams.fromString(javaCodeString));
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
JavaParser parser = new JavaParser(tokenStream);
parser.setErrorHandler(new DefaultErrorStrategy() {
@Override
public Token recoverInline(Parser recognizer) throws RecognitionException {
if (nextTokensContext == null) {
throw new InputMismatchException(recognizer);
} else {
throw new InputMismatchException(recognizer, nextTokensState, nextTokensContext);
}
}
});
// parser.addParseListener(PostProcessor)
// parser.removeErrorListeners()
// parser.addErrorListener(ParseErrorListener)
ParserRuleContext tree;
try {
// first, try parsing with potentially faster SLL mode
parser.getInterpreter().setPredictionMode(PredictionMode.SLL);
tree = parser.compilationUnit();
} catch (ParseCancellationException ex) {
// if we fail, parse with LL mode
tokenStream.seek(0); // rewind input stream
parser.reset();
parser.getInterpreter().setPredictionMode(PredictionMode.LL);
tree = parser.compilationUnit();
}
return new JavaAstBuilder().build(tree);
}
}

View File

@ -0,0 +1,325 @@
// 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.doris.nereids.pattern.generator;
import org.apache.doris.nereids.pattern.generator.javaast.ClassDeclaration;
import org.apache.doris.nereids.pattern.generator.javaast.EnumConstant;
import org.apache.doris.nereids.pattern.generator.javaast.EnumDeclaration;
import org.apache.doris.nereids.pattern.generator.javaast.FieldDeclaration;
import org.apache.doris.nereids.pattern.generator.javaast.MethodDeclaration;
import org.apache.doris.nereids.pattern.generator.javaast.VariableDeclarator;
import com.google.common.base.Joiner;
import org.apache.commons.lang.math.IntRange;
import org.apache.commons.lang3.StringUtils;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/** used to generate pattern by operator. */
public abstract class PatternGenerator {
protected final PatternGeneratorAnalyzer analyzer;
protected final ClassDeclaration opType;
protected final Set<String> parentClass;
protected final List<EnumFieldPatternInfo> enumFieldPatternInfos;
protected final List<String> generatePatterns = new ArrayList<>();
/** constructor. */
public PatternGenerator(PatternGeneratorAnalyzer analyzer, ClassDeclaration opType, Set<String> parentClass) {
this.analyzer = analyzer;
this.opType = opType;
this.parentClass = parentClass;
this.enumFieldPatternInfos = getEnumFieldPatternInfos();
}
public abstract String genericType();
public abstract String genericTypeWithChildren();
public abstract Set<String> getImports();
public abstract boolean isLogical();
public abstract int childrenNum();
public String getPatternMethodName() {
return opType.name.substring(0, 1).toLowerCase(Locale.ENGLISH) + opType.name.substring(1);
}
/** generate code by generators and analyzer. */
public static String generateCode(List<PatternGenerator> generators, PatternGeneratorAnalyzer analyzer) {
String generateCode
= "// Licensed to the Apache Software Foundation (ASF) under one\n"
+ "// or more contributor license agreements. See the NOTICE file\n"
+ "// distributed with this work for additional information\n"
+ "// regarding copyright ownership. The ASF licenses this file\n"
+ "// to you under the Apache License, Version 2.0 (the\n"
+ "// \"License\"); you may not use this file except in compliance\n"
+ "// with the License. You may obtain a copy of the License at\n"
+ "//\n"
+ "// http://www.apache.org/licenses/LICENSE-2.0\n"
+ "//\n"
+ "// Unless required by applicable law or agreed to in writing,\n"
+ "// software distributed under the License is distributed on an\n"
+ "// \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n"
+ "// KIND, either express or implied. See the License for the\n"
+ "// specific language governing permissions and limitations\n"
+ "// under the License.\n"
+ "\n"
+ "package org.apache.doris.nereids.pattern;\n"
+ "\n"
+ generateImports(generators)
+ "\n";
generateCode += "public interface GeneratedPatterns extends Patterns {\n";
generateCode += generators.stream()
.map(generator -> {
String patternMethods = generator.generate();
// add indent
return Arrays.stream(patternMethods.split("\n"))
.map(line -> " " + line + "\n")
.collect(Collectors.joining(""));
}).collect(Collectors.joining("\n"));
return generateCode + "}\n";
}
protected List<EnumFieldPatternInfo> getEnumFieldPatternInfos() {
List<EnumFieldPatternInfo> enumFieldInfos = new ArrayList<>();
for (Entry<FieldDeclaration, EnumDeclaration> pair : findEnumFieldType()) {
FieldDeclaration fieldDecl = pair.getKey();
EnumDeclaration enumDecl = pair.getValue();
Set<String> enumClassNameParts = splitCase(enumDecl.name)
.stream()
.map(part -> part.toLowerCase(Locale.ENGLISH))
.collect(Collectors.toSet());
for (VariableDeclarator varDecl : fieldDecl.variableDeclarators.variableDeclarators) {
String enumFieldName = varDecl.variableDeclaratorId.identifier;
Optional<String> getter = findGetter(enumDecl.name, enumFieldName);
if (getter.isPresent()) {
for (EnumConstant constant : enumDecl.constants) {
String enumInstance = constant.identifier;
String enumPatternName = getEnumPatternName(enumInstance, enumClassNameParts) + opType.name;
enumFieldInfos.add(new EnumFieldPatternInfo(enumPatternName,
enumDecl.getFullQualifiedName(), enumDecl.name, enumInstance, getter.get()));
}
}
}
}
return enumFieldInfos;
}
protected Optional<String> findGetter(String type, String name) {
String getterName = "get" + name.substring(0, 1).toUpperCase(Locale.ENGLISH) + name.substring(1);
for (MethodDeclaration methodDecl : opType.methodDeclarations) {
if (methodDecl.typeTypeOrVoid.isVoid) {
continue;
}
if (methodDecl.typeTypeOrVoid.typeType.isPresent()
&& methodDecl.typeTypeOrVoid.typeType.get().toString().equals(type)) {
if (methodDecl.identifier.equals(getterName) && methodDecl.paramNum == 0) {
return Optional.of(getterName);
}
}
}
return Optional.empty();
}
protected String getEnumPatternName(String enumInstance, Set<String> enumClassNameParts) {
String[] instanceNameParts = enumInstance.split("_+");
List<String> newParts = new ArrayList<>();
boolean isFirst = true;
for (int i = 0; i < instanceNameParts.length; i++) {
String part = instanceNameParts[i].toLowerCase(Locale.ENGLISH);
// skip instanceNameParts, e.g. INNER_JOIN has two part: [inner and Join].
// because 'Join' is the part of the 'JoinType' enum className, so skip 'Join' and return 'inner'
if (part.isEmpty() || enumClassNameParts.contains(part)) {
continue;
}
if (!isFirst) {
newParts.add(part.substring(0, 1).toUpperCase(Locale.ENGLISH) + part.substring(1));
} else {
newParts.add(part.substring(0, 1).toLowerCase(Locale.ENGLISH) + part.substring(1));
}
isFirst = false;
}
return Joiner.on("").join(newParts);
}
protected List<Map.Entry<FieldDeclaration, EnumDeclaration>> findEnumFieldType() {
return opType.fieldDeclarations
.stream()
.map(f -> new SimpleEntry<>(f, analyzer.getType(opType, f.type)))
.filter(pair -> pair.getValue().isPresent() && pair.getValue().get() instanceof EnumDeclaration)
.map(pair -> new SimpleEntry<>(pair.getKey(), (EnumDeclaration) (pair.getValue().get())))
.collect(Collectors.toList());
}
// e.g. split PhysicalBroadcastHashJoin to [Physical, Broadcast, Hash, Join]
// e.g. split JoinType to [Join, Type]
protected List<String> splitCase(String name) {
Pattern pattern = Pattern.compile("([A-Z]+[^A-Z]*)");
Matcher matcher = pattern.matcher(name);
List<String> parts = new ArrayList<>();
while (matcher.find()) {
parts.add(matcher.group(0));
}
return parts;
}
/** create generator by operator's type. */
public static Optional<PatternGenerator> create(PatternGeneratorAnalyzer analyzer,
ClassDeclaration opType, Set<String> parentClass) {
if (parentClass.contains("org.apache.doris.nereids.operators.plans.logical.LogicalLeafOperator")) {
return Optional.of(new LogicalLeafPatternGenerator(analyzer, opType, parentClass));
} else if (parentClass.contains("org.apache.doris.nereids.operators.plans.logical.LogicalUnaryOperator")) {
return Optional.of(new LogicalUnaryPatternGenerator(analyzer, opType, parentClass));
} else if (parentClass.contains("org.apache.doris.nereids.operators.plans.logical.LogicalBinaryOperator")) {
return Optional.of(new LogicalBinaryPatternGenerator(analyzer, opType, parentClass));
} else if (parentClass.contains("org.apache.doris.nereids.operators.plans.physical.PhysicalLeafOperator")) {
return Optional.of(new PhysicalLeafPatternGenerator(analyzer, opType, parentClass));
} else if (parentClass.contains("org.apache.doris.nereids.operators.plans.physical.PhysicalUnaryOperator")) {
return Optional.of(new PhysicalUnaryPatternGenerator(analyzer, opType, parentClass));
} else if (parentClass.contains("org.apache.doris.nereids.operators.plans.physical.PhysicalBinaryOperator")) {
return Optional.of(new PhysicalBinaryPatternGenerator(analyzer, opType, parentClass));
} else {
return Optional.empty();
}
}
private static String generateImports(List<PatternGenerator> generators) {
Set<String> imports = new HashSet<>();
for (PatternGenerator generator : generators) {
imports.addAll(generator.getImports());
}
List<String> sortedImports = new ArrayList<>(imports);
sortedImports.sort(Comparator.naturalOrder());
return sortedImports.stream()
.map(it -> "import " + it + ";\n")
.collect(Collectors.joining(""));
}
/** generate some pattern method code. */
public String generate() {
String opClassName = opType.name;
String methodName = getPatternMethodName();
generateTypePattern(methodName, opClassName, genericType(), "", false);
if (childrenNum() > 0) {
generateTypePattern(methodName, opClassName, genericTypeWithChildren(), "", true);
}
for (EnumFieldPatternInfo info : enumFieldPatternInfos) {
String predicate = ".when(p -> p.operator." + info.enumInstanceGetter + "() == "
+ info.enumType + "." + info.enumInstance + ")";
generateTypePattern(info.patternName, opClassName, genericType(), predicate, false);
if (childrenNum() > 0) {
generateTypePattern(info.patternName, opClassName, genericTypeWithChildren(), predicate, true);
}
}
return generatePatterns();
}
/** generate a pattern method code. */
public String generateTypePattern(String patterName, String className,
String genericParam, String predicate, boolean specifyChildren) {
int childrenNum = childrenNum();
if (specifyChildren) {
String methodGeneric = Arrays.stream(new IntRange(1, childrenNum).toArray())
.mapToObj(i -> "C" + i + " extends Plan")
.collect(Collectors.joining(", ", "<", ">"));
String methodParam = Arrays.stream(new IntRange(1, childrenNum).toArray())
.mapToObj(i -> "PatternDescriptor<C" + i + ", Plan> child" + i)
.collect(Collectors.joining(", "));
String childrenPattern = Arrays.stream(new IntRange(1, childrenNum).toArray())
.mapToObj(i -> "child" + i + ".pattern")
.collect(Collectors.joining(", "));
if (childrenNum > 0) {
childrenPattern = ", " + childrenPattern;
}
String pattern = "default " + methodGeneric + "\n"
+ "PatternDescriptor" + genericParam + "\n"
+ " " + patterName + "(" + methodParam + ") {\n"
+ " return new PatternDescriptor" + genericParam + "(\n"
+ " new TypePattern(" + className + ".class" + childrenPattern + "),\n"
+ " defaultPromise()\n"
+ " )" + predicate + ";\n"
+ "}\n";
generatePatterns.add(pattern);
return pattern;
} else {
String childrenPattern = StringUtils.repeat("Pattern.FIXED", ", ", childrenNum);
if (childrenNum > 0) {
childrenPattern = ", " + childrenPattern;
}
String pattern = "default PatternDescriptor" + genericParam + " " + patterName + "() {\n"
+ " return new PatternDescriptor" + genericParam + "(\n"
+ " new TypePattern(" + className + ".class" + childrenPattern + "),\n"
+ " defaultPromise()\n"
+ " )" + predicate + ";\n"
+ "}\n";
generatePatterns.add(pattern);
return pattern;
}
}
public String generatePatterns() {
return generatePatterns.stream().collect(Collectors.joining("\n"));
}
static class EnumFieldPatternInfo {
public final String patternName;
public final String enumFullName;
public final String enumType;
public final String enumInstance;
public final String enumInstanceGetter;
public EnumFieldPatternInfo(String patternName, String enumFullName, String enumType,
String enumInstance, String enumInstanceGetter) {
this.patternName = patternName;
this.enumFullName = enumFullName;
this.enumType = enumType;
this.enumInstance = enumInstance;
this.enumInstanceGetter = enumInstanceGetter;
}
}
}

View File

@ -0,0 +1,226 @@
// 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.doris.nereids.pattern.generator;
import org.apache.doris.nereids.pattern.generator.javaast.ClassDeclaration;
import org.apache.doris.nereids.pattern.generator.javaast.ClassOrInterfaceType;
import org.apache.doris.nereids.pattern.generator.javaast.EnumDeclaration;
import org.apache.doris.nereids.pattern.generator.javaast.IdentifyTypeArgumentsPair;
import org.apache.doris.nereids.pattern.generator.javaast.ImportDeclaration;
import org.apache.doris.nereids.pattern.generator.javaast.InterfaceDeclaration;
import org.apache.doris.nereids.pattern.generator.javaast.QualifiedName;
import org.apache.doris.nereids.pattern.generator.javaast.TypeDeclaration;
import org.apache.doris.nereids.pattern.generator.javaast.TypeType;
import com.google.common.base.Joiner;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
/**
* used to analyze operator class extends hierarchy and then generated pattern builder methods.
*/
public class PatternGeneratorAnalyzer {
private final Map<String, TypeDeclaration> name2Ast = new LinkedHashMap<>();
private final IdentityHashMap<TypeDeclaration, String> ast2Name = new IdentityHashMap<>();
private final IdentityHashMap<TypeDeclaration, Map<String, String>> ast2Import = new IdentityHashMap<>();
private final IdentityHashMap<TypeDeclaration, Set<String>> parentClassMap = new IdentityHashMap<>();
/** add java AST. */
public void addAsts(List<TypeDeclaration> typeDeclarations) {
for (TypeDeclaration typeDeclaration : typeDeclarations) {
addAst(Optional.empty(), typeDeclaration);
}
}
/** generate pattern methods. */
public String generatePatterns() {
analyzeImport();
analyzeParentClass();
return doGenerate();
}
Optional<TypeDeclaration> getType(TypeDeclaration typeDeclaration, TypeType type) {
String typeName = analyzeClass(new LinkedHashSet<>(), typeDeclaration, type);
if (typeName != null) {
TypeDeclaration ast = name2Ast.get(typeName);
return Optional.ofNullable(ast);
}
return Optional.empty();
}
private String doGenerate() {
Map<ClassDeclaration, Set<String>> planOpClassMap = parentClassMap.entrySet().stream()
.filter(kv -> kv.getValue().contains("org.apache.doris.nereids.operators.plans.PlanOperator"))
.filter(kv -> !Modifier.isAbstract(kv.getKey().modifiers.mod)
&& kv.getKey() instanceof ClassDeclaration)
.collect(Collectors.toMap(kv -> (ClassDeclaration) kv.getKey(), kv -> kv.getValue()));
List<PatternGenerator> generators = planOpClassMap.entrySet()
.stream()
.map(kv -> PatternGenerator.create(this, kv.getKey(), kv.getValue()))
.filter(generator -> generator.isPresent())
.map(Optional::get)
.sorted((g1, g2) -> {
// logical first
if (g1.isLogical() != g2.isLogical()) {
return g1.isLogical() ? -1 : 1;
}
// leaf first
if (g1.childrenNum() != g2.childrenNum()) {
return g1.childrenNum() - g2.childrenNum();
}
// string dict sort
return g1.opType.name.compareTo(g2.opType.name);
})
.collect(Collectors.toList());
return PatternGenerator.generateCode(generators, this);
}
private void analyzeImport() {
for (TypeDeclaration typeDeclaration : name2Ast.values()) {
Map<String, String> imports = new LinkedHashMap<>();
for (ImportDeclaration importDeclaration : typeDeclaration.imports) {
QualifiedName name = importDeclaration.name;
if (!importDeclaration.isStatic && !importDeclaration.importAll
&& name.suffix().isPresent()) {
String importName = Joiner.on(".").join(name.identifiers);
imports.put(name.suffix().get(), importName);
}
}
ast2Import.put(typeDeclaration, imports);
}
}
private void analyzeParentClass() {
for (TypeDeclaration typeDeclaration : name2Ast.values()) {
analyzeParentClass(new LinkedHashSet<>(), typeDeclaration);
}
}
private void analyzeParentClass(Set<String> parentClasses, TypeDeclaration typeDeclaration) {
Set<String> currentParentClasses = new LinkedHashSet<>();
if (typeDeclaration instanceof InterfaceDeclaration) {
for (TypeType extendsType : ((InterfaceDeclaration) typeDeclaration).extendsTypes) {
analyzeClass(currentParentClasses, typeDeclaration, extendsType);
}
} else if (typeDeclaration instanceof EnumDeclaration) {
for (TypeType implementType : ((EnumDeclaration) typeDeclaration).implementTypes) {
analyzeClass(currentParentClasses, typeDeclaration, implementType);
}
} else if (typeDeclaration instanceof ClassDeclaration) {
ClassDeclaration classDeclaration = (ClassDeclaration) typeDeclaration;
if (classDeclaration.extendsType.isPresent()) {
analyzeClass(currentParentClasses, typeDeclaration, classDeclaration.extendsType.get());
}
if (!classDeclaration.implementTypes.isEmpty()) {
for (TypeType implementType : classDeclaration.implementTypes) {
analyzeClass(currentParentClasses, typeDeclaration, implementType);
}
}
}
parentClassMap.put(typeDeclaration, currentParentClasses);
parentClasses.addAll(currentParentClasses);
}
String analyzeClass(Set<String> parentClasses, TypeDeclaration typeDeclaration, TypeType type) {
if (type.classOrInterfaceType.isPresent()) {
List<String> identifiers = new ArrayList<>();
ClassOrInterfaceType classOrInterfaceType = type.classOrInterfaceType.get();
for (IdentifyTypeArgumentsPair identifyTypeArgument : classOrInterfaceType.identifyTypeArguments) {
identifiers.add(identifyTypeArgument.identifier);
}
String className = Joiner.on(".").join(identifiers);
if (analyzeIfExist(parentClasses, className)) {
parentClasses.add(className);
return className;
}
Optional<String> importName = findFullImportName(typeDeclaration, className);
if (importName.isPresent() && analyzeIfExist(parentClasses, importName.get())) {
parentClasses.add(importName.get());
return importName.get();
}
if (typeDeclaration.packageName.isPresent()) {
String currentPackageClass = Joiner.on(".")
.join(typeDeclaration.packageName.get().identifiers) + "." + className;
if (analyzeIfExist(parentClasses, currentPackageClass)) {
parentClasses.add(currentPackageClass);
return currentPackageClass;
}
}
parentClasses.add(className);
return className;
} else if (type.primitiveType.isPresent()) {
parentClasses.add(type.primitiveType.get());
return type.primitiveType.get();
} else {
return null;
}
}
private boolean analyzeIfExist(Set<String> parentClasses, String name) {
if (name2Ast.get(name) != null) {
analyzeParentClass(parentClasses, name2Ast.get(name));
return true;
} else {
return false;
}
}
private Optional<String> findFullImportName(TypeDeclaration typeDeclaration, String name) {
Map<String, String> name2FullName = ast2Import.get(typeDeclaration);
if (name2FullName != null && name2FullName.get(name) != null) {
return Optional.of(name2FullName.get(name));
}
return Optional.empty();
}
private void addAst(Optional<String> outerClassName, TypeDeclaration typeDeclaration) {
String nameWithOuterClass;
if (!outerClassName.isPresent()) {
nameWithOuterClass = typeDeclaration.name;
String fullQualifiedName = typeDeclaration.getFullQualifiedName();
name2Ast.put(fullQualifiedName, typeDeclaration);
ast2Name.put(typeDeclaration, fullQualifiedName);
} else if (typeDeclaration.packageName.isPresent()) {
nameWithOuterClass = outerClassName.get() + "." + typeDeclaration.name;
String fullName = typeDeclaration.packageName.get() + "." + nameWithOuterClass;
name2Ast.put(fullName, typeDeclaration);
ast2Name.put(typeDeclaration, fullName);
} else {
nameWithOuterClass = outerClassName.get() + "." + typeDeclaration.name;
name2Ast.put(nameWithOuterClass, typeDeclaration);
ast2Name.put(typeDeclaration, nameWithOuterClass);
}
for (TypeDeclaration child : typeDeclaration.children) {
addAst(Optional.of(nameWithOuterClass), child);
}
}
}

View File

@ -0,0 +1,66 @@
// 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.doris.nereids.pattern.generator;
import org.apache.doris.nereids.pattern.generator.javaast.ClassDeclaration;
import java.util.Set;
import java.util.TreeSet;
/** used to generate pattern for PhysicalBinaryOperator. */
public class PhysicalBinaryPatternGenerator extends PatternGenerator {
public PhysicalBinaryPatternGenerator(PatternGeneratorAnalyzer analyzer,
ClassDeclaration opType, Set<String> parentClass) {
super(analyzer, opType, parentClass);
}
@Override
public String genericType() {
return "<PhysicalBinaryPlan<" + opType.name + ", Plan, Plan>, Plan>";
}
@Override
public String genericTypeWithChildren() {
return "<PhysicalBinaryPlan<" + opType.name + ", C1, C2>, Plan>";
}
@Override
public Set<String> getImports() {
Set<String> imports = new TreeSet<>();
imports.add(opType.getFullQualifiedName());
imports.add("org.apache.doris.nereids.operators.OperatorType");
imports.add("org.apache.doris.nereids.trees.plans.Plan");
imports.add("org.apache.doris.nereids.trees.plans.physical.PhysicalBinaryPlan");
enumFieldPatternInfos.stream()
.map(info -> info.enumFullName)
.forEach(imports::add);
return imports;
}
@Override
public boolean isLogical() {
return false;
}
@Override
public int childrenNum() {
return 2;
}
}

View File

@ -0,0 +1,64 @@
// 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.doris.nereids.pattern.generator;
import org.apache.doris.nereids.pattern.generator.javaast.ClassDeclaration;
import java.util.Set;
import java.util.TreeSet;
/** used to generate pattern for PhysicalLeafOperator. */
public class PhysicalLeafPatternGenerator extends PatternGenerator {
public PhysicalLeafPatternGenerator(PatternGeneratorAnalyzer analyzer,
ClassDeclaration opType, Set<String> parentClass) {
super(analyzer, opType, parentClass);
}
@Override
public String genericType() {
return "<PhysicalLeafPlan<" + opType.name + ">, Plan>";
}
@Override
public String genericTypeWithChildren() {
throw new IllegalStateException("Can not get children generic type by PhysicalLeafPlan");
}
@Override
public Set<String> getImports() {
Set<String> imports = new TreeSet<>();
imports.add(opType.getFullQualifiedName());
imports.add("org.apache.doris.nereids.trees.plans.Plan");
imports.add("org.apache.doris.nereids.trees.plans.physical.PhysicalLeafPlan");
enumFieldPatternInfos.stream()
.map(info -> info.enumFullName)
.forEach(imports::add);
return imports;
}
@Override
public boolean isLogical() {
return false;
}
@Override
public int childrenNum() {
return 0;
}
}

View File

@ -0,0 +1,65 @@
// 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.doris.nereids.pattern.generator;
import org.apache.doris.nereids.pattern.generator.javaast.ClassDeclaration;
import java.util.Set;
import java.util.TreeSet;
/** used to generate pattern for PhysicalUnaryOperator. */
public class PhysicalUnaryPatternGenerator extends PatternGenerator {
public PhysicalUnaryPatternGenerator(PatternGeneratorAnalyzer analyzer,
ClassDeclaration opType, Set<String> parentClass) {
super(analyzer, opType, parentClass);
}
@Override
public String genericType() {
return "<PhysicalUnaryPlan<" + opType.name + ", Plan>, Plan>";
}
@Override
public String genericTypeWithChildren() {
return "<PhysicalUnaryPlan<" + opType.name + ", C1>, Plan>";
}
@Override
public Set<String> getImports() {
Set<String> imports = new TreeSet<>();
imports.add(opType.getFullQualifiedName());
imports.add("org.apache.doris.nereids.operators.OperatorType");
imports.add("org.apache.doris.nereids.trees.plans.Plan");
imports.add("org.apache.doris.nereids.trees.plans.physical.PhysicalUnaryPlan");
enumFieldPatternInfos.stream()
.map(info -> info.enumFullName)
.forEach(imports::add);
return imports;
}
@Override
public boolean isLogical() {
return false;
}
@Override
public int childrenNum() {
return 1;
}
}

View File

@ -0,0 +1,88 @@
// 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.doris.nereids.pattern.generator.javaast;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.Optional;
/** java's class declaration. */
public class ClassDeclaration extends TypeDeclaration {
public final Optional<TypeType> extendsType;
public final Optional<TypeParameters> typeParameters;
public final List<TypeType> implementTypes;
public final List<FieldDeclaration> fieldDeclarations;
public final List<MethodDeclaration> methodDeclarations;
/** constructor. */
public ClassDeclaration(QualifiedName packageName, List<ImportDeclaration> imports,
ClassOrInterfaceModifier modifier, String name, TypeParameters typeParameters,
TypeType extendsType, List<TypeType> implementTypes,
List<FieldDeclaration> fieldDeclarations, List<MethodDeclaration> methodDeclarations,
List<TypeDeclaration> children) {
super(packageName, imports, modifier, name, children);
this.typeParameters = Optional.ofNullable(typeParameters);
this.extendsType = Optional.ofNullable(extendsType);
this.implementTypes = ImmutableList.copyOf(implementTypes);
this.fieldDeclarations = ImmutableList.copyOf(fieldDeclarations);
this.methodDeclarations = ImmutableList.copyOf(methodDeclarations);
}
@Override
public String toString() {
StringBuilder buffer = new StringBuilder();
if (packageName.isPresent()) {
buffer.append("package ").append(packageName.get()).append(";\n\n");
}
if (!imports.isEmpty()) {
for (ImportDeclaration importDeclaration : imports) {
buffer.append(importDeclaration).append("\n");
}
buffer.append("\n");
}
String mod = modifiers.toString();
if (!mod.isEmpty()) {
mod += " ";
}
buffer.append(mod).append("class ").append(name);
if (typeParameters.isPresent()) {
buffer.append(typeParameters.get());
}
buffer.append(" ");
if (extendsType.isPresent()) {
buffer.append("extends ").append(extendsType.get()).append(" ");
}
if (!implementTypes.isEmpty()) {
buffer.append("implements ").append(Joiner.on(", ").join(implementTypes)).append(" ");
}
buffer.append("{\n");
for (FieldDeclaration fieldDeclaration : fieldDeclarations) {
buffer.append(" ").append(fieldDeclaration).append("\n");
}
for (MethodDeclaration methodDeclaration : methodDeclarations) {
buffer.append(" ").append(methodDeclaration).append("\n");
}
buffer.append("}\n");
return buffer.toString();
}
}

View File

@ -0,0 +1,57 @@
// 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.doris.nereids.pattern.generator.javaast;
import com.google.common.base.Joiner;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
/** java's class or interface's modifiers. */
public class ClassOrInterfaceModifier implements JavaAstNode {
public final int mod;
public ClassOrInterfaceModifier(int mod) {
this.mod = mod;
}
@Override
public String toString() {
List<String> modifiers = new ArrayList<>(3);
if (Modifier.isPublic(mod)) {
modifiers.add("public");
} else if (Modifier.isProtected(mod)) {
modifiers.add("protected");
} else if (Modifier.isPrivate(mod)) {
modifiers.add("private");
}
if (Modifier.isStatic(mod)) {
modifiers.add("static");
}
if (Modifier.isAbstract(mod)) {
modifiers.add("abstract");
} else if (Modifier.isFinal(mod)) {
modifiers.add("final");
}
return Joiner.on(" ").join(modifiers);
}
}

View File

@ -0,0 +1,38 @@
// 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.doris.nereids.pattern.generator.javaast;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import java.util.List;
/** java class or interface's type. */
public class ClassOrInterfaceType implements JavaAstNode {
public final List<IdentifyTypeArgumentsPair> identifyTypeArguments;
public ClassOrInterfaceType(List<IdentifyTypeArgumentsPair> identifyTypeArguments) {
this.identifyTypeArguments = ImmutableList.copyOf(identifyTypeArguments);
}
@Override
public String toString() {
return Joiner.on(".").join(identifyTypeArguments);
}
}

View File

@ -0,0 +1,33 @@
// 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.doris.nereids.pattern.generator.javaast;
/** java enum instance. */
public class EnumConstant implements JavaAstNode {
public final String identifier;
public EnumConstant(String identifier) {
this.identifier = identifier;
}
@Override
public String toString() {
return identifier;
}
}

View File

@ -0,0 +1,67 @@
// 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.doris.nereids.pattern.generator.javaast;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import java.util.List;
/** java's enum declaration. */
public class EnumDeclaration extends TypeDeclaration {
public final List<TypeType> implementTypes;
public final List<EnumConstant> constants;
/** constructor. */
public EnumDeclaration(QualifiedName packageName, List<ImportDeclaration> imports,
ClassOrInterfaceModifier modifier, String name, List<TypeType> implementTypes,
List<EnumConstant> constants, List<TypeDeclaration> children) {
super(packageName, imports, modifier, name, children);
this.implementTypes = ImmutableList.copyOf(implementTypes);
this.constants = ImmutableList.copyOf(constants);
}
@Override
public String toString() {
StringBuilder buffer = new StringBuilder();
if (packageName.isPresent()) {
buffer.append("package ").append(packageName.get()).append(";\n\n");
}
if (!imports.isEmpty()) {
for (ImportDeclaration importDeclaration : imports) {
buffer.append(importDeclaration).append("\n");
}
buffer.append("\n");
}
String mod = modifiers.toString();
if (!mod.isEmpty()) {
mod += " ";
}
buffer.append(mod).append("enum ").append(name).append(" ");
if (!implementTypes.isEmpty()) {
buffer.append("implements ").append(Joiner.on(", ").join(implementTypes)).append(" ");
}
buffer.append("{\n");
if (!constants.isEmpty()) {
buffer.append(" ").append(Joiner.on(", ").join(constants)).append(";\n");
}
buffer.append("}\n");
return buffer.toString();
}
}

View File

@ -0,0 +1,34 @@
// 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.doris.nereids.pattern.generator.javaast;
/** java class field declaration. */
public class FieldDeclaration extends MemberDeclaration {
public final TypeType type;
public final VariableDeclarators variableDeclarators;
public FieldDeclaration(TypeType type, VariableDeclarators variableDeclarators) {
this.type = type;
this.variableDeclarators = variableDeclarators;
}
@Override
public String toString() {
return type + " " + variableDeclarators + ";";
}
}

View File

@ -0,0 +1,41 @@
// 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.doris.nereids.pattern.generator.javaast;
import java.util.Optional;
/** java's identify type and type arguments. */
public class IdentifyTypeArgumentsPair implements JavaAstNode {
public final String identifier;
public final Optional<TypeArguments> typeArguments;
public IdentifyTypeArgumentsPair(String identifier, TypeArguments typeArguments) {
this.identifier = identifier;
this.typeArguments = Optional.ofNullable(typeArguments);
}
@Override
public String toString() {
if (typeArguments.isPresent()) {
return identifier + typeArguments.get();
} else {
return identifier;
}
}
}

View File

@ -0,0 +1,38 @@
// 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.doris.nereids.pattern.generator.javaast;
/** java import declaration. */
public class ImportDeclaration implements JavaAstNode {
public final boolean isStatic;
public final QualifiedName name;
public final boolean importAll;
/** import declaration constructor. */
public ImportDeclaration(boolean isStatic, QualifiedName name, boolean importAll) {
this.isStatic = isStatic;
this.name = name;
this.importAll = importAll;
}
@Override
public String toString() {
return "import " + (isStatic ? "static " : "") + name + (importAll ? ".*" : "") + ";";
}
}

View File

@ -0,0 +1,68 @@
// 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.doris.nereids.pattern.generator.javaast;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.Optional;
/** java's interface declaration. */
public class InterfaceDeclaration extends TypeDeclaration {
public final Optional<TypeParameters> typeParameters;
public final List<TypeType> extendsTypes;
/** constructor. */
public InterfaceDeclaration(QualifiedName packageName, List<ImportDeclaration> imports,
ClassOrInterfaceModifier modifier, String name, TypeParameters typeParameters,
List<TypeType> extendsTypes, List<TypeDeclaration> children) {
super(packageName, imports, modifier, name, children);
this.typeParameters = Optional.ofNullable(typeParameters);
this.extendsTypes = ImmutableList.copyOf(extendsTypes);
}
@Override
public String toString() {
StringBuilder buffer = new StringBuilder();
if (packageName.isPresent()) {
buffer.append("package ").append(packageName.get()).append(";\n\n");
}
if (!imports.isEmpty()) {
for (ImportDeclaration importDeclaration : imports) {
buffer.append(importDeclaration).append("\n");
}
buffer.append("\n");
}
String mod = modifiers.toString();
if (!mod.isEmpty()) {
mod += " ";
}
buffer.append(mod).append("interface ").append(name);
if (typeParameters.isPresent()) {
buffer.append(typeParameters.get());
}
buffer.append(" ");
if (!extendsTypes.isEmpty()) {
buffer.append("extends ").append(Joiner.on(", ").join(extendsTypes)).append(" ");
}
buffer.append("{}");
return buffer.toString();
}
}

View File

@ -0,0 +1,23 @@
// 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.doris.nereids.pattern.generator.javaast;
/** java ast base interface. */
public interface JavaAstNode {
}

View File

@ -0,0 +1,21 @@
// 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.doris.nereids.pattern.generator.javaast;
/** java's member declaration. */
public class MemberDeclaration implements JavaAstNode {}

View File

@ -0,0 +1,37 @@
// 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.doris.nereids.pattern.generator.javaast;
/** java's method declaration. */
public class MethodDeclaration extends MemberDeclaration {
public final TypeTypeOrVoid typeTypeOrVoid;
public final String identifier;
public final int paramNum;
/** constructor. */
public MethodDeclaration(TypeTypeOrVoid typeTypeOrVoid, String identifier, int paramNum) {
this.typeTypeOrVoid = typeTypeOrVoid;
this.identifier = identifier;
this.paramNum = paramNum;
}
@Override
public String toString() {
return typeTypeOrVoid.toString() + " " + identifier + "();";
}
}

View File

@ -0,0 +1,52 @@
// 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.doris.nereids.pattern.generator.javaast;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.Optional;
/** java's qualified name. */
public class QualifiedName implements JavaAstNode {
public final List<String> identifiers;
public QualifiedName(List<String> identifiers) {
this.identifiers = ImmutableList.copyOf(identifiers);
}
public boolean suffixIs(String name) {
return !identifiers.isEmpty() && identifiers.get(identifiers.size() - 1).equals(name);
}
/** get suffix name. */
public Optional<String> suffix() {
if (identifiers.isEmpty()) {
return Optional.empty();
} else {
return Optional.of(identifiers.get(identifiers.size() - 1));
}
}
@Override
public String toString() {
return Joiner.on(".").join(identifiers);
}
}

View File

@ -0,0 +1,53 @@
// 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.doris.nereids.pattern.generator.javaast;
import java.util.Optional;
/** java generic type argument. */
public class TypeArgument implements JavaAstNode {
/** generic type. */
public enum ArgType {
NORMAL, EXTENDS, SUPER, UNKNOWN
}
private final ArgType argType;
private final Optional<TypeType> typeType;
public TypeArgument(ArgType argType, TypeType typeType) {
this.argType = argType;
this.typeType = Optional.ofNullable(typeType);
}
@Override
public String toString() {
switch (argType) {
case NORMAL:
return typeType.get().toString();
case EXTENDS:
return "? extends " + typeType.get();
case SUPER:
return "? super " + typeType.get();
case UNKNOWN:
return "?";
default:
throw new UnsupportedOperationException("Unknown argument type: " + argType);
}
}
}

View File

@ -0,0 +1,38 @@
// 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.doris.nereids.pattern.generator.javaast;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import java.util.List;
/** java's type arguments. */
public class TypeArguments implements JavaAstNode {
public final List<TypeArgument> typeArguments;
public TypeArguments(List<TypeArgument> typeArguments) {
this.typeArguments = ImmutableList.copyOf(typeArguments);
}
@Override
public String toString() {
return "<" + Joiner.on(", ").join(typeArguments) + ">";
}
}

View File

@ -0,0 +1,38 @@
// 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.doris.nereids.pattern.generator.javaast;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import java.util.List;
/** java's type bound. */
public class TypeBound implements JavaAstNode {
public final List<TypeType> types;
public TypeBound(List<TypeType> types) {
this.types = ImmutableList.copyOf(types);
}
@Override
public String toString() {
return Joiner.on(" & ").join(types);
}
}

View File

@ -0,0 +1,56 @@
// 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.doris.nereids.pattern.generator.javaast;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.Optional;
/** java's type declaration. */
public abstract class TypeDeclaration implements JavaAstNode {
public final Optional<QualifiedName> packageName;
public final List<ImportDeclaration> imports;
public final ClassOrInterfaceModifier modifiers;
public final String name;
public final List<TypeDeclaration> children;
/** type declaration's constructor. */
public TypeDeclaration(QualifiedName packageName, List<ImportDeclaration> imports,
ClassOrInterfaceModifier modifiers, String name, List<TypeDeclaration> children) {
this.packageName = Optional.ofNullable(packageName);
this.imports = ImmutableList.copyOf(imports);
this.modifiers = modifiers;
this.name = name;
this.children = ImmutableList.copyOf(children);
}
public String getFullQualifiedName() {
return getFullQualifiedName(packageName, name);
}
/** function to concat package name and type name. */
public static String getFullQualifiedName(Optional<QualifiedName> packageName, String name) {
if (packageName.isPresent()) {
return Joiner.on(".").join(packageName.get().identifiers) + "." + name;
}
return name;
}
}

View File

@ -0,0 +1,41 @@
// 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.doris.nereids.pattern.generator.javaast;
import java.util.Optional;
/** java's type. */
public class TypeParameter implements JavaAstNode {
public final String identifier;
public final Optional<TypeBound> typeBound;
public TypeParameter(String identifier, TypeBound typeBound) {
this.identifier = identifier;
this.typeBound = Optional.ofNullable(typeBound);
}
@Override
public String toString() {
if (typeBound.isPresent()) {
return identifier + " extends " + typeBound.get();
} else {
return identifier;
}
}
}

View File

@ -0,0 +1,38 @@
// 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.doris.nereids.pattern.generator.javaast;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import java.util.List;
/** java's types. */
public class TypeParameters implements JavaAstNode {
public final List<TypeParameter> typeParameters;
public TypeParameters(List<TypeParameter> typeParameters) {
this.typeParameters = ImmutableList.copyOf(typeParameters);
}
@Override
public String toString() {
return "<" + Joiner.on(", ").join(typeParameters) + ">";
}
}

View File

@ -0,0 +1,40 @@
// 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.doris.nereids.pattern.generator.javaast;
import java.util.Optional;
/** java's type. */
public class TypeType implements JavaAstNode {
public final Optional<ClassOrInterfaceType> classOrInterfaceType;
public final Optional<String> primitiveType;
public TypeType(ClassOrInterfaceType classOrInterfaceType, String primitiveType) {
this.classOrInterfaceType = Optional.ofNullable(classOrInterfaceType);
this.primitiveType = Optional.ofNullable(primitiveType);
}
@Override
public String toString() {
if (primitiveType.isPresent()) {
return primitiveType.get();
} else {
return classOrInterfaceType.get().toString();
}
}
}

View File

@ -0,0 +1,37 @@
// 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.doris.nereids.pattern.generator.javaast;
import java.util.Optional;
/** java's type or void. */
public class TypeTypeOrVoid implements JavaAstNode {
public final Optional<TypeType> typeType;
public final boolean isVoid;
public TypeTypeOrVoid(TypeType typeType, boolean isVoid) {
this.typeType = Optional.ofNullable(typeType);
this.isVoid = isVoid;
}
@Override
public String toString() {
return isVoid ? "void" : typeType.get().toString();
}
}

View File

@ -0,0 +1,33 @@
// 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.doris.nereids.pattern.generator.javaast;
/** java variable's declarator. */
public class VariableDeclarator implements JavaAstNode {
public final VariableDeclaratorId variableDeclaratorId;
public VariableDeclarator(VariableDeclaratorId variableDeclaratorId) {
this.variableDeclaratorId = variableDeclaratorId;
}
@Override
public String toString() {
return variableDeclaratorId.toString();
}
}

View File

@ -0,0 +1,37 @@
// 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.doris.nereids.pattern.generator.javaast;
import org.apache.commons.lang3.StringUtils;
/** java's variable. */
public class VariableDeclaratorId implements JavaAstNode {
public final String identifier;
public final int arrayDimension;
public VariableDeclaratorId(String identifier, int arrayDimension) {
this.identifier = identifier;
this.arrayDimension = arrayDimension;
}
@Override
public String toString() {
return identifier + StringUtils.repeat("[]", arrayDimension);
}
}

View File

@ -0,0 +1,38 @@
// 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.doris.nereids.pattern.generator.javaast;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import java.util.List;
/** java's variable declarators. */
public class VariableDeclarators implements JavaAstNode {
public final List<VariableDeclarator> variableDeclarators;
public VariableDeclarators(List<VariableDeclarator> variableDeclarators) {
this.variableDeclarators = ImmutableList.copyOf(variableDeclarators);
}
@Override
public String toString() {
return Joiner.on(", ").join(variableDeclarators);
}
}

View File

@ -26,7 +26,7 @@ import java.util.List;
/**
* abstract class for all rule factories build one rule.
*/
public abstract class OneRuleFactory<TYPE extends TreeNode> implements RuleFactory<TYPE> {
public abstract class OneRuleFactory<TYPE extends TreeNode<TYPE>> implements RuleFactory<TYPE> {
@Override
public final List<Rule<TYPE>> buildRules() {
return ImmutableList.of(build());

View File

@ -28,9 +28,9 @@ import java.util.List;
/**
* Abstract class for all rules.
*/
public abstract class Rule<TYPE extends TreeNode> {
public abstract class Rule<TYPE extends TreeNode<TYPE>> {
private final RuleType ruleType;
private final Pattern pattern;
private final Pattern<? extends TYPE, TYPE> pattern;
private final RulePromise rulePromise;
/**
@ -40,7 +40,7 @@ public abstract class Rule<TYPE extends TreeNode> {
* @param pattern target pattern of rule
* @param rulePromise rule promise
*/
public Rule(RuleType ruleType, Pattern pattern, RulePromise rulePromise) {
public Rule(RuleType ruleType, Pattern<? extends TYPE, TYPE> pattern, RulePromise rulePromise) {
this.ruleType = ruleType;
this.pattern = pattern;
this.rulePromise = rulePromise;
@ -54,7 +54,7 @@ public abstract class Rule<TYPE extends TreeNode> {
return rulePromise;
}
public Pattern getPattern() {
public Pattern<? extends TYPE, TYPE> getPattern() {
return pattern;
}

View File

@ -17,7 +17,7 @@
package org.apache.doris.nereids.rules;
import org.apache.doris.nereids.pattern.Patterns;
import org.apache.doris.nereids.pattern.GeneratedPatterns;
import org.apache.doris.nereids.trees.TreeNode;
import java.util.List;
@ -25,7 +25,7 @@ import java.util.List;
/**
* interface for all rule factories for build some rules.
*/
public interface RuleFactory<TYPE extends TreeNode> extends Patterns {
public interface RuleFactory<TYPE extends TreeNode<TYPE>> extends GeneratedPatterns {
// need implement
List<Rule<TYPE>> buildRules();

View File

@ -62,7 +62,7 @@ public class RuleSet {
return new RuleFactories();
}
private static class RuleFactories<TYPE extends TreeNode> {
private static class RuleFactories<TYPE extends TreeNode<TYPE>> {
final Builder<Rule<TYPE>> rules = ImmutableList.builder();
public RuleFactories<TYPE> add(RuleFactory<TYPE> ruleFactory) {

View File

@ -22,7 +22,7 @@ import org.apache.doris.nereids.rules.Rule;
import org.apache.doris.nereids.rules.RuleType;
import org.apache.doris.nereids.rules.exploration.OneExplorationRuleFactory;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.logical.LogicalBinary;
import org.apache.doris.nereids.trees.plans.logical.LogicalBinaryPlan;
/**
@ -39,8 +39,8 @@ public class JoinExchange extends OneExplorationRuleFactory {
@Override
public Rule<Plan> build() {
return innerLogicalJoin(innerLogicalJoin(), innerLogicalJoin()).then(topJoin -> {
LogicalBinary<LogicalJoin, Plan, Plan> leftJoin = topJoin.left();
LogicalBinary<LogicalJoin, Plan, Plan> rightJoin = topJoin.right();
LogicalBinaryPlan<LogicalJoin, Plan, Plan> leftJoin = topJoin.left();
LogicalBinaryPlan<LogicalJoin, Plan, Plan> rightJoin = topJoin.right();
Plan a = leftJoin.left();
Plan b = leftJoin.right();

View File

@ -22,7 +22,7 @@ import org.apache.doris.nereids.rules.Rule;
import org.apache.doris.nereids.rules.RuleType;
import org.apache.doris.nereids.rules.exploration.OneExplorationRuleFactory;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.logical.LogicalBinary;
import org.apache.doris.nereids.trees.plans.logical.LogicalBinaryPlan;
/**
* Rule for change inner join left associative to right.
@ -38,7 +38,7 @@ public class JoinLAsscom extends OneExplorationRuleFactory {
@Override
public Rule<Plan> build() {
return innerLogicalJoin(innerLogicalJoin(), any()).then(topJoin -> {
LogicalBinary<LogicalJoin, Plan, Plan> bottomJoin = topJoin.left();
LogicalBinaryPlan<LogicalJoin, Plan, Plan> bottomJoin = topJoin.left();
Plan a = bottomJoin.left();
Plan b = bottomJoin.right();

View File

@ -24,6 +24,7 @@ import org.apache.doris.nereids.operators.Operator;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.Optional;
/**
* Abstract class for plan node in Nereids, include plan node and expression.
@ -31,17 +32,17 @@ import java.util.List;
* @param <NODE_TYPE> either {@link org.apache.doris.nereids.trees.plans.Plan}
* or {@link org.apache.doris.nereids.trees.expressions.Expression}
*/
public abstract class AbstractTreeNode<NODE_TYPE extends AbstractTreeNode<NODE_TYPE>>
public abstract class AbstractTreeNode<NODE_TYPE extends TreeNode<NODE_TYPE>>
implements TreeNode<NODE_TYPE> {
protected final NodeType type;
protected final List<TreeNode> children;
protected final List<NODE_TYPE> children;
// TODO: Maybe we should use a GroupPlan to avoid TreeNode hold the GroupExpression.
// https://github.com/apache/incubator-doris/pull/9807#discussion_r884829067
protected final GroupExpression groupExpression;
protected final Optional<GroupExpression> groupExpression;
public AbstractTreeNode(NodeType type, TreeNode... children) {
public AbstractTreeNode(NodeType type, NODE_TYPE... children) {
this(type, null, children);
}
@ -52,10 +53,10 @@ public abstract class AbstractTreeNode<NODE_TYPE extends AbstractTreeNode<NODE_T
* @param groupExpression group expression related to the operator of this node
* @param children children of this node
*/
public AbstractTreeNode(NodeType type, GroupExpression groupExpression, TreeNode... children) {
public AbstractTreeNode(NodeType type, GroupExpression groupExpression, NODE_TYPE... children) {
this.type = type;
this.children = ImmutableList.copyOf(children);
this.groupExpression = groupExpression;
this.groupExpression = Optional.ofNullable(groupExpression);
}
@Override
@ -64,13 +65,18 @@ public abstract class AbstractTreeNode<NODE_TYPE extends AbstractTreeNode<NODE_T
}
@Override
public GroupExpression getGroupExpression() {
public Optional<GroupExpression> getGroupExpression() {
return groupExpression;
}
@Override
public NODE_TYPE newChildren(List<TreeNode> children) {
throw new RuntimeException();
public NODE_TYPE child(int index) {
return children.get(index);
}
@Override
public List<NODE_TYPE> children() {
return children;
}
@Override
@ -78,16 +84,6 @@ public abstract class AbstractTreeNode<NODE_TYPE extends AbstractTreeNode<NODE_T
return type;
}
@Override
public <CHILD_TYPE extends TreeNode> List<CHILD_TYPE> children() {
return (List) children;
}
@Override
public <CHILD_TYPE extends TreeNode> CHILD_TYPE child(int index) {
return (CHILD_TYPE) children.get(index);
}
public int arity() {
return children.size();
}

View File

@ -21,17 +21,17 @@ package org.apache.doris.nereids.trees;
* interface for all tree node that have two children.
*/
public interface BinaryNode<
NODE_TYPE extends BinaryNode<NODE_TYPE, LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE>,
NODE_TYPE extends TreeNode<NODE_TYPE>,
LEFT_CHILD_TYPE extends TreeNode,
RIGHT_CHILD_TYPE extends TreeNode>
extends TreeNode<NODE_TYPE> {
default LEFT_CHILD_TYPE left() {
return child(0);
return (LEFT_CHILD_TYPE) child(0);
}
default RIGHT_CHILD_TYPE right() {
return child(1);
return (RIGHT_CHILD_TYPE) child(1);
}
@Override

View File

@ -20,7 +20,7 @@ package org.apache.doris.nereids.trees;
/**
* Abstract class for all tree node that have no child.
*/
public interface LeafNode<NODE_TYPE extends LeafNode<NODE_TYPE>> extends TreeNode<NODE_TYPE> {
public interface LeafNode<NODE_TYPE extends TreeNode<NODE_TYPE>> extends TreeNode<NODE_TYPE> {
@Override
default int arity() {
return 0;

View File

@ -21,6 +21,7 @@ import org.apache.doris.nereids.memo.GroupExpression;
import org.apache.doris.nereids.operators.Operator;
import java.util.List;
import java.util.Optional;
/**
* interface for all node in Nereids, include plan node and expression.
@ -32,15 +33,16 @@ public interface TreeNode<NODE_TYPE extends TreeNode<NODE_TYPE>> {
Operator getOperator();
GroupExpression getGroupExpression();
// cache GroupExpression for fast exit from Memo.copyIn.
Optional<GroupExpression> getGroupExpression();
NodeType getType();
<CHILD_TYPE extends TreeNode> List<CHILD_TYPE> children();
List<NODE_TYPE> children();
<CHILD_TYPE extends TreeNode> CHILD_TYPE child(int index);
NODE_TYPE child(int index);
int arity();
NODE_TYPE newChildren(List<TreeNode> children);
NODE_TYPE newChildren(List<NODE_TYPE> children);
}

View File

@ -20,13 +20,11 @@ package org.apache.doris.nereids.trees;
/**
* interface for all tree node that have one child.
*/
public interface UnaryNode<
NODE_TYPE extends UnaryNode<NODE_TYPE, CHILD_TYPE>,
CHILD_TYPE extends TreeNode>
public interface UnaryNode<NODE_TYPE extends TreeNode<NODE_TYPE>, CHILD_TYPE extends TreeNode>
extends TreeNode<NODE_TYPE> {
default CHILD_TYPE child() {
return child(0);
return (CHILD_TYPE) child(0);
}
@Override

View File

@ -27,8 +27,8 @@ import java.util.List;
/**
* Expression for alias, such as col1 as c1.
*/
public class Alias<CHILD_TYPE extends Expression> extends NamedExpression<Alias<CHILD_TYPE>>
implements UnaryExpression<Alias<CHILD_TYPE>, CHILD_TYPE> {
public class Alias<CHILD_TYPE extends Expression> extends NamedExpression
implements UnaryExpression<CHILD_TYPE> {
private final ExprId exprId;
private final String name;

View File

@ -23,19 +23,18 @@ import org.apache.doris.nereids.trees.BinaryNode;
* Interface for all expression that have two children.
*/
public interface BinaryExpression<
EXPR_TYPE extends BinaryExpression<EXPR_TYPE, LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE>,
LEFT_CHILD_TYPE extends Expression,
RIGHT_CHILD_TYPE extends Expression>
extends BinaryNode<EXPR_TYPE, LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> {
extends BinaryNode<Expression, LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> {
@Override
default LEFT_CHILD_TYPE left() {
return child(0);
return (LEFT_CHILD_TYPE) child(0);
}
@Override
default RIGHT_CHILD_TYPE right() {
return child(1);
return (RIGHT_CHILD_TYPE) child(1);
}
}

View File

@ -30,8 +30,7 @@ import java.util.Objects;
* Such as: "=", "<", "<=", ">", ">=", "<=>"
*/
public class ComparisonPredicate<LEFT_CHILD_TYPE extends Expression, RIGHT_CHILD_TYPE extends Expression>
extends Expression<ComparisonPredicate<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE>> implements
BinaryExpression<ComparisonPredicate<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE>, LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> {
extends Expression implements BinaryExpression<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> {
/**
* Constructor of ComparisonPredicate.

View File

@ -19,7 +19,6 @@ package org.apache.doris.nereids.trees.expressions;
import org.apache.doris.nereids.exceptions.UnboundException;
import org.apache.doris.nereids.trees.NodeType;
import org.apache.doris.nereids.trees.TreeNode;
import com.google.common.base.Preconditions;
@ -46,8 +45,8 @@ public class EqualTo<LEFT_CHILD_TYPE extends Expression, RIGHT_CHILD_TYPE extend
}
@Override
public EqualTo newChildren(List<TreeNode> children) {
public EqualTo<Expression, Expression> newChildren(List<Expression> children) {
Preconditions.checkArgument(children.size() == 2);
return new EqualTo((Expression) children.get(0), (Expression) children.get(1));
return new EqualTo<>(children.get(0), children.get(1));
}
}

Some files were not shown because too many files have changed in this diff Show More