You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tajo.apache.org by hy...@apache.org on 2014/04/18 11:20:10 UTC
[48/51] [partial] TAJO-752: Escalate sub modules in tajo-core into
the top-level modules. (hyunsik)
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4 b/tajo-core/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
new file mode 100644
index 0000000..f6385eb
--- /dev/null
+++ b/tajo-core/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
@@ -0,0 +1,1398 @@
+/**
+ * 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.
+ */
+
+parser grammar SQLParser;
+
+options {
+ language=Java;
+ tokenVocab=SQLLexer;
+}
+
+@header {
+}
+
+@members {
+}
+
+/*
+===============================================================================
+ SQL statement (Start Symbol)
+===============================================================================
+*/
+sql
+ : (explain_clause)? statement (SEMI_COLON)? EOF
+ ;
+
+explain_clause
+ : EXPLAIN
+ ;
+
+statement
+ : data_statement
+ | data_change_statement
+ | schema_statement
+ | index_statement
+ ;
+
+data_statement
+ : query_expression
+ ;
+
+data_change_statement
+ : insert_statement
+ ;
+
+schema_statement
+ : database_definition
+ | drop_database_statement
+ | create_table_statement
+ | drop_table_statement
+ | alter_tablespace_statement
+ | alter_table_statement
+ ;
+
+index_statement
+ : CREATE (u=UNIQUE)? INDEX n=identifier ON t=table_name (m=method_specifier)?
+ LEFT_PAREN s=sort_specifier_list RIGHT_PAREN p=param_clause?
+ ;
+
+database_definition
+ : CREATE DATABASE (if_not_exists)? dbname = identifier
+ ;
+
+if_not_exists
+ : IF NOT EXISTS
+ ;
+
+drop_database_statement
+ : DROP DATABASE (if_exists)? dbname = identifier
+ ;
+
+if_exists
+ : IF EXISTS
+ ;
+
+create_table_statement
+ : CREATE EXTERNAL TABLE (if_not_exists)? table_name table_elements USING file_type=identifier
+ (param_clause)? (table_partitioning_clauses)? (LOCATION path=Character_String_Literal)
+ | CREATE TABLE (if_not_exists)? table_name table_elements (USING file_type=identifier)?
+ (param_clause)? (table_partitioning_clauses)? (AS query_expression)?
+ | CREATE TABLE (if_not_exists)? table_name (USING file_type=identifier)?
+ (param_clause)? (table_partitioning_clauses)? AS query_expression
+ ;
+
+table_elements
+ : LEFT_PAREN field_element (COMMA field_element)* RIGHT_PAREN
+ ;
+
+field_element
+ : name=identifier field_type
+ ;
+
+field_type
+ : data_type
+ ;
+
+param_clause
+ : WITH LEFT_PAREN param (COMMA param)* RIGHT_PAREN
+ ;
+
+param
+ : key=Character_String_Literal EQUAL value=numeric_value_expression
+ ;
+
+method_specifier
+ : USING m=identifier
+ ;
+
+table_space_specifier
+ : TABLESPACE table_space_name
+ ;
+
+table_space_name
+ : identifier
+ ;
+
+table_partitioning_clauses
+ : range_partitions
+ | hash_partitions
+ | list_partitions
+ | column_partitions
+ ;
+
+range_partitions
+ : PARTITION BY RANGE LEFT_PAREN column_reference_list RIGHT_PAREN
+ LEFT_PAREN range_value_clause_list RIGHT_PAREN
+ ;
+
+range_value_clause_list
+ : range_value_clause (COMMA range_value_clause)*
+ ;
+
+range_value_clause
+ : PARTITION partition_name VALUES LESS THAN (LEFT_PAREN value_expression RIGHT_PAREN | LEFT_PAREN? MAXVALUE RIGHT_PAREN?)
+ ;
+
+hash_partitions
+ : PARTITION BY HASH LEFT_PAREN column_reference_list RIGHT_PAREN
+ (LEFT_PAREN individual_hash_partitions RIGHT_PAREN | hash_partitions_by_quantity)
+ ;
+
+individual_hash_partitions
+ : individual_hash_partition (COMMA individual_hash_partition)*
+ ;
+
+individual_hash_partition
+ : PARTITION partition_name
+ ;
+
+hash_partitions_by_quantity
+ : PARTITIONS quantity = numeric_value_expression
+ ;
+
+list_partitions
+ : PARTITION BY LIST LEFT_PAREN column_reference_list RIGHT_PAREN LEFT_PAREN list_value_clause_list RIGHT_PAREN
+ ;
+
+list_value_clause_list
+ : list_value_partition (COMMA list_value_partition)*
+ ;
+
+list_value_partition
+ : PARTITION partition_name VALUES (IN)? LEFT_PAREN in_value_list RIGHT_PAREN
+ ;
+
+column_partitions
+ : PARTITION BY COLUMN table_elements
+ ;
+
+partition_name
+ : identifier
+ ;
+
+/*
+===============================================================================
+ 11.21 <data types>
+===============================================================================
+*/
+
+drop_table_statement
+ : DROP TABLE (if_exists)? table_name (PURGE)?
+ ;
+
+/*
+===============================================================================
+ 5.2 <token and separator>
+
+ Specifying lexical units (tokens and separators) that participate in SQL language
+===============================================================================
+*/
+
+identifier
+ : Regular_Identifier
+ | nonreserved_keywords
+ | Quoted_Identifier
+ ;
+
+nonreserved_keywords
+ : ADD
+ | AVG
+ | ALTER
+ | BETWEEN
+ | BY
+ | CENTURY
+ | CHARACTER
+ | COALESCE
+ | COLLECT
+ | COLUMN
+ | COUNT
+ | CUBE
+ | DAY
+ | DEC
+ | DECADE
+ | DOW
+ | DOY
+ | DROP
+ | EPOCH
+ | EVERY
+ | EXISTS
+ | EXPLAIN
+ | EXTERNAL
+ | EXTRACT
+ | FILTER
+ | FIRST
+ | FORMAT
+ | FUSION
+ | GROUPING
+ | HASH
+ | INDEX
+ | INSERT
+ | INTERSECTION
+ | ISODOW
+ | ISOYEAR
+ | LAST
+ | LESS
+ | LIST
+ | LOCATION
+ | MAX
+ | MAXVALUE
+ | MICROSECONDS
+ | MILLENNIUM
+ | MILLISECONDS
+ | MIN
+ | MINUTE
+ | MONTH
+ | NATIONAL
+ | NULLIF
+ | OVERWRITE
+ | PARTITION
+ | PARTITIONS
+ | PRECISION
+ | PURGE
+ | QUARTER
+ | RANGE
+ | REGEXP
+ | RENAME
+ | RLIKE
+ | ROLLUP
+ | SECOND
+ | SET
+ | SIMILAR
+ | STDDEV_POP
+ | STDDEV_SAMP
+ | SUBPARTITION
+ | SUM
+ | TABLESPACE
+ | THAN
+ | TIMEZONE
+ | TIMEZONE_HOUR
+ | TIMEZONE_MINUTE
+ | TRIM
+ | TO
+ | UNKNOWN
+ | VALUES
+ | VAR_POP
+ | VAR_SAMP
+ | VARYING
+ | WEEK
+ | YEAR
+ | ZONE
+
+ | BIGINT
+ | BIT
+ | BLOB
+ | BOOL
+ | BOOLEAN
+ | BYTEA
+ | CHAR
+ | DATE
+ | DECIMAL
+ | DOUBLE
+ | FLOAT
+ | FLOAT4
+ | FLOAT8
+ | INET4
+ | INT
+ | INT1
+ | INT2
+ | INT4
+ | INT8
+ | INTEGER
+ | NCHAR
+ | NUMERIC
+ | NVARCHAR
+ | REAL
+ | SMALLINT
+ | TEXT
+ | TIME
+ | TIMESTAMP
+ | TIMESTAMPTZ
+ | TIMETZ
+ | TINYINT
+ | VARBINARY
+ | VARBIT
+ | VARCHAR
+ ;
+
+/*
+===============================================================================
+ 5.3 <literal>
+===============================================================================
+*/
+
+unsigned_literal
+ : unsigned_numeric_literal
+ | general_literal
+ ;
+
+general_literal
+ : Character_String_Literal
+ | datetime_literal
+ | boolean_literal
+ ;
+
+datetime_literal
+ : timestamp_literal
+ | time_literal
+ | date_literal
+ ;
+
+time_literal
+ : TIME time_string=Character_String_Literal
+ ;
+
+timestamp_literal
+ : TIMESTAMP timestamp_string=Character_String_Literal
+ ;
+
+date_literal
+ : DATE date_string=Character_String_Literal
+ ;
+
+boolean_literal
+ : TRUE | FALSE | UNKNOWN
+ ;
+
+/*
+===============================================================================
+ 6.1 <data types>
+===============================================================================
+*/
+
+data_type
+ : predefined_type
+ ;
+
+predefined_type
+ : character_string_type
+ | national_character_string_type
+ | binary_large_object_string_type
+ | numeric_type
+ | boolean_type
+ | datetime_type
+ | bit_type
+ | binary_type
+ | network_type
+ ;
+
+network_type
+ : INET4
+ ;
+
+character_string_type
+ : CHARACTER type_length?
+ | CHAR type_length?
+ | CHARACTER VARYING type_length?
+ | CHAR VARYING type_length?
+ | VARCHAR type_length?
+ | TEXT
+ ;
+
+type_length
+ : LEFT_PAREN NUMBER RIGHT_PAREN
+ ;
+
+national_character_string_type
+ : NATIONAL CHARACTER type_length?
+ | NATIONAL CHAR type_length?
+ | NCHAR type_length?
+ | NATIONAL CHARACTER VARYING type_length?
+ | NATIONAL CHAR VARYING type_length?
+ | NCHAR VARYING type_length?
+ | NVARCHAR type_length?
+ ;
+
+binary_large_object_string_type
+ : BLOB type_length?
+ | BYTEA type_length?
+ ;
+
+numeric_type
+ : exact_numeric_type | approximate_numeric_type
+ ;
+
+exact_numeric_type
+ : NUMERIC (precision_param)?
+ | DECIMAL (precision_param)?
+ | DEC (precision_param)?
+ | INT1
+ | TINYINT
+ | INT2
+ | SMALLINT
+ | INT4
+ | INT
+ | INTEGER
+ | INT8
+ | BIGINT
+ ;
+
+approximate_numeric_type
+ : FLOAT (precision_param)?
+ | FLOAT4
+ | REAL
+ | FLOAT8
+ | DOUBLE
+ | DOUBLE PRECISION
+ ;
+
+precision_param
+ : LEFT_PAREN precision=NUMBER RIGHT_PAREN
+ | LEFT_PAREN precision=NUMBER COMMA scale=NUMBER RIGHT_PAREN
+ ;
+
+boolean_type
+ : BOOLEAN
+ | BOOL
+ ;
+
+datetime_type
+ : DATE
+ | TIME
+ | TIME WITH TIME ZONE
+ | TIMETZ
+ | TIMESTAMP
+ | TIMESTAMP WITH TIME ZONE
+ | TIMESTAMPTZ
+ ;
+
+bit_type
+ : BIT type_length?
+ | VARBIT type_length?
+ | BIT VARYING type_length?
+ ;
+
+binary_type
+ : BINARY type_length?
+ | BINARY VARYING type_length?
+ | VARBINARY type_length?
+ ;
+
+/*
+===============================================================================
+ 6.3 <value_expression_primary>
+===============================================================================
+*/
+value_expression_primary
+ : parenthesized_value_expression
+ | nonparenthesized_value_expression_primary
+ ;
+
+parenthesized_value_expression
+ : LEFT_PAREN value_expression RIGHT_PAREN
+ ;
+
+nonparenthesized_value_expression_primary
+ : unsigned_value_specification
+ | column_reference
+ | set_function_specification
+ | scalar_subquery
+ | case_expression
+ | cast_specification
+ | routine_invocation
+ ;
+
+/*
+===============================================================================
+ 6.4 <unsigned value specification>
+===============================================================================
+*/
+
+unsigned_value_specification
+ : unsigned_literal
+ ;
+
+unsigned_numeric_literal
+ : NUMBER
+ | REAL_NUMBER
+ ;
+
+signed_numerical_literal
+ : sign? unsigned_numeric_literal
+ ;
+
+/*
+===============================================================================
+ 6.9 <set function specification>
+
+ Invoke an SQL-invoked routine.
+===============================================================================
+*/
+set_function_specification
+ : aggregate_function
+ ;
+
+aggregate_function
+ : COUNT LEFT_PAREN MULTIPLY RIGHT_PAREN
+ | general_set_function filter_clause?
+ ;
+
+general_set_function
+ : set_function_type LEFT_PAREN set_qualifier? value_expression RIGHT_PAREN
+ ;
+
+set_function_type
+ : AVG
+ | MAX
+ | MIN
+ | SUM
+ | EVERY
+ | ANY
+ | SOME
+ | COUNT
+ | STDDEV_POP
+ | STDDEV_SAMP
+ | VAR_SAMP
+ | VAR_POP
+ | COLLECT
+ | FUSION
+ | INTERSECTION
+ ;
+
+filter_clause
+ : FILTER LEFT_PAREN WHERE search_condition RIGHT_PAREN
+ ;
+
+grouping_operation
+ : GROUPING LEFT_PAREN column_reference_list RIGHT_PAREN
+ ;
+
+/*
+===============================================================================
+ 6.11 <case expression>
+===============================================================================
+*/
+
+case_expression
+ : case_specification
+ ;
+
+case_abbreviation
+ : NULLIF LEFT_PAREN numeric_value_expression COMMA boolean_value_expression RIGHT_PAREN
+ | COALESCE LEFT_PAREN numeric_value_expression ( COMMA boolean_value_expression )+ RIGHT_PAREN
+ ;
+
+case_specification
+ : simple_case
+ | searched_case
+ ;
+
+simple_case
+ : CASE boolean_value_expression ( simple_when_clause )+ ( else_clause )? END
+ ;
+
+searched_case
+ : CASE (searched_when_clause)+ (else_clause)? END
+ ;
+
+simple_when_clause : WHEN search_condition THEN result ;
+
+searched_when_clause
+ : WHEN c=search_condition THEN r=result
+ ;
+
+else_clause
+ : ELSE r=result
+ ;
+
+result
+ : value_expression | NULL
+ ;
+
+/*
+===============================================================================
+ 6.12 <cast specification>
+===============================================================================
+*/
+
+cast_specification
+ : CAST LEFT_PAREN cast_operand AS cast_target RIGHT_PAREN
+ ;
+
+cast_operand
+ : value_expression
+ ;
+
+cast_target
+ : data_type
+ ;
+
+/*
+===============================================================================
+ 6.25 <value expression>
+===============================================================================
+*/
+value_expression
+ : common_value_expression
+ | row_value_expression
+ | boolean_value_expression
+ ;
+
+common_value_expression
+ : numeric_value_expression
+ | string_value_expression
+ | NULL
+ ;
+
+/*
+===============================================================================
+ 6.26 <numeric value expression>
+
+ Specify a comparison of two row values.
+===============================================================================
+*/
+
+numeric_value_expression
+ : left=term ((PLUS|MINUS) right=term)*
+ ;
+
+term
+ : left=factor ((MULTIPLY|DIVIDE|MODULAR) right=factor)*
+ ;
+
+factor
+ : (sign)? numeric_primary
+ ;
+
+array
+ : LEFT_PAREN numeric_value_expression (COMMA numeric_value_expression )* RIGHT_PAREN
+ ;
+
+numeric_primary
+ : value_expression_primary (CAST_EXPRESSION cast_target)*
+ | numeric_value_function
+ ;
+
+sign
+ : PLUS | MINUS
+ ;
+
+/*
+===============================================================================
+ 6.27 <numeric value function>
+===============================================================================
+*/
+
+numeric_value_function
+ : extract_expression
+ ;
+
+extract_expression
+ : EXTRACT LEFT_PAREN extract_field_string=extract_field FROM extract_source RIGHT_PAREN
+ ;
+
+extract_field
+ : primary_datetime_field
+ | time_zone_field
+ | extended_datetime_field
+ ;
+
+time_zone_field
+ : TIMEZONE | TIMEZONE_HOUR | TIMEZONE_MINUTE
+ ;
+
+extract_source
+ : column_reference
+ | datetime_literal
+ ;
+
+/*
+===============================================================================
+ 6.28 <string value expression>
+===============================================================================
+*/
+
+string_value_expression
+ : character_value_expression
+ ;
+
+character_value_expression
+ : character_factor (CONCATENATION_OPERATOR character_factor)*
+ ;
+
+character_factor
+ : character_primary
+ ;
+
+character_primary
+ : value_expression_primary
+ | string_value_function
+ ;
+
+/*
+===============================================================================
+ 6.29 <string value function>
+===============================================================================
+*/
+
+string_value_function
+ : trim_function
+ ;
+
+trim_function
+ : TRIM LEFT_PAREN trim_operands RIGHT_PAREN
+ ;
+
+trim_operands
+ : ((trim_specification)? (trim_character=character_value_expression)? FROM)? trim_source=character_value_expression
+ | trim_source=character_value_expression COMMA trim_character=character_value_expression
+ ;
+
+trim_specification
+ : LEADING | TRAILING | BOTH
+ ;
+
+/*
+===============================================================================
+ 6.34 <boolean value expression>
+===============================================================================
+*/
+
+boolean_value_expression
+ : or_predicate
+ ;
+
+or_predicate
+ : and_predicate (OR or_predicate)*
+ ;
+
+and_predicate
+ : boolean_factor (AND and_predicate)*
+ ;
+
+boolean_factor
+ : boolean_test
+ | NOT boolean_test
+ ;
+
+boolean_test
+ : boolean_primary is_clause?
+ ;
+
+is_clause
+ : IS NOT? t=truth_value
+ ;
+
+truth_value
+ : TRUE | FALSE | UNKNOWN
+ ;
+
+boolean_primary
+ : predicate
+ | boolean_predicand
+ ;
+
+boolean_predicand
+ : parenthesized_boolean_value_expression
+ | nonparenthesized_value_expression_primary
+ ;
+
+parenthesized_boolean_value_expression
+ : LEFT_PAREN boolean_value_expression RIGHT_PAREN
+ ;
+
+/*
+===============================================================================
+ 7.2 <row value expression>
+===============================================================================
+*/
+row_value_expression
+ : row_value_special_case
+ | explicit_row_value_constructor
+ ;
+
+row_value_special_case
+ : nonparenthesized_value_expression_primary
+ ;
+
+explicit_row_value_constructor
+ : NULL
+ ;
+
+row_value_predicand
+ : row_value_special_case
+ | row_value_constructor_predicand
+ ;
+
+row_value_constructor_predicand
+ : common_value_expression
+ | boolean_predicand
+// | explicit_row_value_constructor
+ ;
+
+/*
+===============================================================================
+ 7.4 <table expression>
+===============================================================================
+*/
+
+table_expression
+ : from_clause
+ where_clause?
+ groupby_clause?
+ having_clause?
+ orderby_clause?
+ limit_clause?
+ ;
+
+/*
+===============================================================================
+ 7.5 <from clause>
+===============================================================================
+*/
+
+from_clause
+ : FROM table_reference_list
+ ;
+
+table_reference_list
+ :table_reference (COMMA table_reference)*
+ ;
+
+/*
+===============================================================================
+ 7.6 <table reference>
+===============================================================================
+*/
+
+table_reference
+ : joined_table
+ | table_primary
+ ;
+
+/*
+===============================================================================
+ 7.7 <joined table>
+===============================================================================
+*/
+
+joined_table
+ : table_primary joined_table_primary+
+ ;
+
+joined_table_primary
+ : CROSS JOIN right=table_primary
+ | (t=join_type)? JOIN right=table_primary s=join_specification
+ | NATURAL (t=join_type)? JOIN right=table_primary
+ | UNION JOIN right=table_primary
+ ;
+
+cross_join
+ : CROSS JOIN r=table_primary
+ ;
+
+qualified_join
+ : (t=join_type)? JOIN r=table_primary s=join_specification
+ ;
+
+natural_join
+ : NATURAL (t=join_type)? JOIN r=table_primary
+ ;
+
+union_join
+ : UNION JOIN r=table_primary
+ ;
+
+join_type
+ : INNER
+ | t=outer_join_type
+ ;
+
+outer_join_type
+ : outer_join_type_part2 OUTER?
+ ;
+
+outer_join_type_part2
+ : LEFT
+ | RIGHT
+ | FULL
+ ;
+
+join_specification
+ : join_condition
+ | named_columns_join
+ ;
+
+join_condition
+ : ON search_condition
+ ;
+
+named_columns_join
+ : USING LEFT_PAREN f=column_reference_list RIGHT_PAREN
+ ;
+
+table_primary
+ : table_or_query_name ((AS)? alias=identifier)? (LEFT_PAREN column_name_list RIGHT_PAREN)?
+ | derived_table (AS)? name=identifier (LEFT_PAREN column_name_list RIGHT_PAREN)?
+ ;
+
+column_name_list
+ : identifier ( COMMA identifier )*
+ ;
+
+derived_table
+ : table_subquery
+ ;
+
+/*
+===============================================================================
+ 7.8 <where clause>
+===============================================================================
+*/
+where_clause
+ : WHERE search_condition
+ ;
+
+search_condition
+ : value_expression // instead of boolean_value_expression, we use value_expression for more flexibility.
+ ;
+
+/*
+===============================================================================
+ 7.9 <group by clause>
+===============================================================================
+*/
+groupby_clause
+ : GROUP BY g=grouping_element_list
+ ;
+
+grouping_element_list
+ : grouping_element (COMMA grouping_element)*
+ ;
+
+grouping_element
+ : rollup_list
+ | cube_list
+ | empty_grouping_set
+ | ordinary_grouping_set
+ ;
+
+ordinary_grouping_set
+ : row_value_predicand
+ | LEFT_PAREN row_value_predicand_list RIGHT_PAREN
+ ;
+
+ordinary_grouping_set_list
+ : ordinary_grouping_set (COMMA ordinary_grouping_set)*
+ ;
+
+rollup_list
+ : ROLLUP LEFT_PAREN c=ordinary_grouping_set_list RIGHT_PAREN
+ ;
+
+cube_list
+ : CUBE LEFT_PAREN c=ordinary_grouping_set_list RIGHT_PAREN
+ ;
+
+empty_grouping_set
+ : LEFT_PAREN RIGHT_PAREN
+ ;
+
+having_clause
+ : HAVING boolean_value_expression
+ ;
+
+row_value_predicand_list
+ : row_value_predicand (COMMA row_value_predicand)*
+ ;
+
+/*
+===============================================================================
+ 7.13 <query expression>
+===============================================================================
+*/
+query_expression
+ : query_expression_body
+ ;
+
+query_expression_body
+ : non_join_query_expression
+ | joined_table
+ ;
+
+non_join_query_expression
+ : (non_join_query_term
+ | joined_table (UNION | EXCEPT) (ALL|DISTINCT)? query_term)
+ ((UNION | EXCEPT) (ALL|DISTINCT)? query_term)*
+ ;
+
+query_term
+ : non_join_query_term
+ | joined_table
+ ;
+
+non_join_query_term
+ : ( non_join_query_primary
+ | joined_table INTERSECT (ALL|DISTINCT)? query_primary)
+ (INTERSECT (ALL|DISTINCT)? query_primary)*
+ ;
+
+query_primary
+ : non_join_query_primary
+ | joined_table
+ ;
+
+non_join_query_primary
+ : simple_table
+ | LEFT_PAREN non_join_query_expression RIGHT_PAREN
+ ;
+
+simple_table
+ : query_specification
+ | explicit_table
+ ;
+
+explicit_table
+ : TABLE table_or_query_name
+ ;
+
+table_or_query_name
+ : table_name
+ | identifier
+ ;
+
+table_name
+ : identifier (DOT identifier ( DOT identifier)? )?
+ ;
+
+column_name
+ : identifier
+ ;
+
+query_specification
+ : SELECT set_qualifier? select_list table_expression?
+ ;
+
+select_list
+ : select_sublist (COMMA select_sublist)*
+ ;
+
+select_sublist
+ : derived_column
+ | qualified_asterisk
+ ;
+
+derived_column
+ : value_expression as_clause?
+ ;
+
+qualified_asterisk
+ : (tb_name=identifier DOT)? MULTIPLY
+ ;
+
+set_qualifier
+ : DISTINCT
+ | ALL
+ ;
+
+column_reference
+ : ((db_name = identifier DOT)? (tb_name=identifier DOT))? name=identifier
+ ;
+
+as_clause
+ : (AS)? identifier
+ ;
+
+column_reference_list
+ : column_reference (COMMA column_reference)*
+ ;
+
+/*
+==============================================================================================
+ 7.15 <subquery>
+
+ Specify a scalar value, a row, or a table derived from a query_expression .
+==============================================================================================
+*/
+
+scalar_subquery
+ : subquery
+ ;
+
+row_subquery
+ : subquery
+ ;
+
+table_subquery
+ : subquery
+ ;
+
+subquery
+ : LEFT_PAREN query_expression RIGHT_PAREN
+ ;
+
+/*
+===============================================================================
+ 8.1 <predicate>
+===============================================================================
+*/
+
+predicate
+ : comparison_predicate
+ | between_predicate
+ | in_predicate
+ | pattern_matching_predicate // like predicate and other similar predicates
+ | null_predicate
+ | exists_predicate
+ ;
+
+/*
+===============================================================================
+ 8.2 <comparison predicate>
+
+ Specify a comparison of two row values.
+===============================================================================
+*/
+comparison_predicate
+ : left=row_value_predicand c=comp_op right=row_value_predicand
+ ;
+
+comp_op
+ : EQUAL
+ | NOT_EQUAL
+ | LTH
+ | LEQ
+ | GTH
+ | GEQ
+ ;
+
+/*
+===============================================================================
+ 8.3 <between predicate>
+===============================================================================
+*/
+
+between_predicate
+ : predicand=row_value_predicand between_predicate_part_2
+ ;
+
+between_predicate_part_2
+ : (NOT)? BETWEEN (ASYMMETRIC | SYMMETRIC)? begin=row_value_predicand AND end=row_value_predicand
+ ;
+
+
+/*
+===============================================================================
+ 8.4 <in predicate>
+===============================================================================
+*/
+
+in_predicate
+ : predicand=numeric_value_expression NOT? IN in_predicate_value
+ ;
+
+in_predicate_value
+ : table_subquery
+ | LEFT_PAREN in_value_list RIGHT_PAREN
+ ;
+
+in_value_list
+ : row_value_predicand ( COMMA row_value_predicand )*
+ ;
+
+/*
+===============================================================================
+ 8.5, 8.6 <pattern matching predicate>
+
+ Specify a pattern-matching comparison.
+===============================================================================
+*/
+
+pattern_matching_predicate
+ : f=row_value_predicand pattern_matcher s=Character_String_Literal
+ ;
+
+pattern_matcher
+ : NOT? negativable_matcher
+ | regex_matcher
+ ;
+
+negativable_matcher
+ : LIKE
+ | ILIKE
+ | SIMILAR TO
+ | REGEXP
+ | RLIKE
+ ;
+
+regex_matcher
+ : Similar_To
+ | Not_Similar_To
+ | Similar_To_Case_Insensitive
+ | Not_Similar_To_Case_Insensitive
+ ;
+
+/*
+===============================================================================
+ 8.7 <null predicate>
+
+ Specify a test for a null value.
+===============================================================================
+*/
+
+null_predicate
+ : predicand=row_value_predicand IS (n=NOT)? NULL
+ ;
+
+/*
+==============================================================================================
+ 8.8 <quantified comparison predicate>
+
+ Specify a quantified comparison.
+==============================================================================================
+*/
+
+quantified_comparison_predicate
+ : l=numeric_value_expression c=comp_op q=quantifier s=table_subquery
+ ;
+
+quantifier : all | some ;
+
+all : ALL;
+
+some : SOME | ANY;
+
+/*
+==============================================================================================
+ 8.9 <exists predicate>
+
+ Specify a test for a non_empty set.
+==============================================================================================
+*/
+
+exists_predicate
+ : NOT? EXISTS s=table_subquery
+ ;
+
+
+/*
+==============================================================================================
+ 8.10 <unique predicate>
+
+ Specify a test for the absence of duplicate rows
+==============================================================================================
+*/
+
+unique_predicate
+ : UNIQUE s=table_subquery
+ ;
+
+/*
+===============================================================================
+ 10.1 <interval qualifier>
+
+ Specify the precision of an interval data type.
+===============================================================================
+*/
+
+primary_datetime_field
+ : non_second_primary_datetime_field
+ | SECOND
+ ;
+
+non_second_primary_datetime_field
+ : YEAR | MONTH | DAY | HOUR | MINUTE
+ ;
+
+extended_datetime_field
+ : CENTURY | DECADE | DOW | DOY | EPOCH | ISODOW | ISOYEAR | MICROSECONDS | MILLENNIUM | MILLISECONDS | QUARTER | WEEK
+ ;
+
+/*
+===============================================================================
+ 10.4 <routine invocation>
+
+ Invoke an SQL-invoked routine.
+===============================================================================
+*/
+
+routine_invocation
+ : function_name LEFT_PAREN sql_argument_list? RIGHT_PAREN
+ ;
+
+function_names_for_reserved_words
+ : LEFT
+ | RIGHT
+ ;
+
+function_name
+ : identifier
+ | function_names_for_reserved_words
+ ;
+
+sql_argument_list
+ : value_expression (COMMA value_expression)*
+ ;
+
+/*
+===============================================================================
+ 14.1 <declare cursor>
+===============================================================================
+*/
+
+orderby_clause
+ : ORDER BY sort_specifier_list
+ ;
+
+sort_specifier_list
+ : sort_specifier (COMMA sort_specifier)*
+ ;
+
+sort_specifier
+ : key=row_value_predicand order=order_specification? null_order=null_ordering?
+ ;
+
+order_specification
+ : ASC
+ | DESC
+ ;
+
+limit_clause
+ : LIMIT e=numeric_value_expression
+ ;
+
+null_ordering
+ : NULL FIRST
+ | NULL LAST
+ ;
+
+/*
+===============================================================================
+ 14.8 <insert statement>
+===============================================================================
+*/
+
+insert_statement
+ : INSERT (OVERWRITE)? INTO table_name (LEFT_PAREN column_name_list RIGHT_PAREN)? query_expression
+ | INSERT (OVERWRITE)? INTO LOCATION path=Character_String_Literal (USING file_type=identifier (param_clause)?)? query_expression
+ ;
+
+/*
+===============================================================================
+ <alter table>
+===============================================================================
+*/
+
+alter_tablespace_statement
+ : ALTER TABLESPACE space_name=identifier LOCATION uri=Character_String_Literal
+ ;
+
+alter_table_statement
+ : ALTER TABLE table_name RENAME TO table_name
+ | ALTER TABLE table_name RENAME COLUMN column_name TO column_name
+ | ALTER TABLE table_name ADD COLUMN field_element
+ ;
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/log4j.properties
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/log4j.properties b/tajo-core/src/main/java/log4j.properties
new file mode 100644
index 0000000..15e5778
--- /dev/null
+++ b/tajo-core/src/main/java/log4j.properties
@@ -0,0 +1,30 @@
+##
+# 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.
+#
+
+# log4j configuration used during build and unit tests
+
+log4j.rootLogger=info,stdout,EventCounter
+log4j.threshhold=ALL
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p %c{2} (%F:%M(%L)) - %m%n
+
+log4j.logger.org.apache.hadoop=WARN
+log4j.logger.org.apache.hadoop.conf=ERROR
+
+log4j.appender.EventCounter=org.apache.tajo.util.metrics.TajoLogEventCounter
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/benchmark/BenchmarkSet.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/benchmark/BenchmarkSet.java b/tajo-core/src/main/java/org/apache/tajo/benchmark/BenchmarkSet.java
new file mode 100644
index 0000000..91dcea1
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/benchmark/BenchmarkSet.java
@@ -0,0 +1,120 @@
+/**
+ * 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.tajo.benchmark;
+
+import com.google.protobuf.ServiceException;
+import org.apache.hadoop.net.NetUtils;
+import org.apache.tajo.catalog.CatalogConstants;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.catalog.store.MemStore;
+import org.apache.tajo.client.TajoClient;
+import org.apache.tajo.conf.TajoConf;
+import org.apache.tajo.conf.TajoConf.ConfVars;
+import org.apache.tajo.util.FileUtil;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public abstract class BenchmarkSet {
+ protected TajoClient tajo;
+ protected Map<String, Schema> schemas = new HashMap<String, Schema>();
+ protected Map<String, Schema> outSchemas = new HashMap<String, Schema>();
+ protected Map<String, String> queries = new HashMap<String, String>();
+ protected String dataDir;
+
+ public void init(TajoConf conf, String dataDir) throws IOException {
+ this.dataDir = dataDir;
+ if (System.getProperty(ConfVars.WORKER_PEER_RPC_ADDRESS.varname) != null) {
+ tajo = new TajoClient(NetUtils.createSocketAddr(
+ System.getProperty(ConfVars.WORKER_PEER_RPC_ADDRESS.varname)));
+ } else {
+ conf.set(CatalogConstants.STORE_CLASS, MemStore.class.getCanonicalName());
+ tajo = new TajoClient(conf);
+ }
+ }
+
+ protected void loadQueries(String dir) throws IOException {
+ // TODO - this code dead??
+ File queryDir = new File(dir);
+
+ if(!queryDir.exists()) {
+ queryDir = new File(System.getProperty("user.dir") + "/tajo-core/" + dir);
+ }
+
+ if(!queryDir.exists())
+ {
+ return;
+ }
+ int last;
+ String name, query;
+ for (String file : queryDir.list()) {
+ if (file.endsWith(".sql")) {
+ last = file.indexOf(".sql");
+ name = file.substring(0, last);
+ query = FileUtil.readTextFile(new File(queryDir + "/" + file));
+ }
+ }
+ }
+
+ public abstract void loadSchemas();
+
+ public abstract void loadOutSchema();
+
+ public abstract void loadQueries() throws IOException;
+
+ public abstract void loadTables() throws ServiceException;
+
+ public String [] getTableNames() {
+ return schemas.keySet().toArray(new String[schemas.size()]);
+ }
+
+ public String getQuery(String queryName) {
+ return queries.get(queryName);
+ }
+
+ public Schema getSchema(String name) {
+ return schemas.get(name);
+ }
+
+ public Iterable<Schema> getSchemas() {
+ return schemas.values();
+ }
+
+ public Schema getOutSchema(String name) {
+ return outSchemas.get(name);
+ }
+
+ public void perform(String queryName) throws IOException, ServiceException {
+ String query = getQuery(queryName);
+ if (query == null) {
+ throw new IllegalArgumentException("#{queryName} does not exists");
+ }
+ long start = System.currentTimeMillis();
+ tajo.executeQuery(query);
+ long end = System.currentTimeMillis();
+
+ System.out.println("====================================");
+ System.out.println("QueryName: " + queryName);
+ System.out.println("Query: " + query);
+ System.out.println("Processing Time: " + (end - start));
+ System.out.println("====================================");
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/benchmark/Driver.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/benchmark/Driver.java b/tajo-core/src/main/java/org/apache/tajo/benchmark/Driver.java
new file mode 100644
index 0000000..99b9a99
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/benchmark/Driver.java
@@ -0,0 +1,46 @@
+/**
+ * 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.tajo.benchmark;
+
+import org.apache.tajo.conf.TajoConf;
+
+public class Driver {
+ private static void printUsage() {
+ System.out.println("benchmark BenchmarkClass datadir query");
+ }
+
+ public static void main(String [] args) throws Exception {
+
+ if (args.length < 3) {
+ printUsage();
+ System.exit(-1);
+ }
+
+ TajoConf conf = new TajoConf();
+ Class clazz = Class.forName(args[0]);
+ BenchmarkSet benchmark = (BenchmarkSet) clazz.newInstance();
+
+ benchmark.init(conf, args[1]);
+ benchmark.loadSchemas();
+ benchmark.loadQueries();
+ benchmark.loadTables();
+ benchmark.perform(args[2]);
+ System.exit(0);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/benchmark/SimpleQuery.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/benchmark/SimpleQuery.java b/tajo-core/src/main/java/org/apache/tajo/benchmark/SimpleQuery.java
new file mode 100644
index 0000000..af6af8d
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/benchmark/SimpleQuery.java
@@ -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.tajo.benchmark;
+
+import java.io.IOException;
+
+public class SimpleQuery extends TPCH {
+ private static final String BENCHMARK_DIR = "benchmark/simple";
+
+ public void loadQueries() throws IOException {
+ loadQueries(BENCHMARK_DIR);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/benchmark/TPCH.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/benchmark/TPCH.java b/tajo-core/src/main/java/org/apache/tajo/benchmark/TPCH.java
new file mode 100644
index 0000000..abd9e7f
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/benchmark/TPCH.java
@@ -0,0 +1,200 @@
+/**
+ * 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.tajo.benchmark;
+
+import com.google.common.collect.Maps;
+import com.google.protobuf.ServiceException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.fs.Path;
+import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.catalog.TableMeta;
+import org.apache.tajo.catalog.proto.CatalogProtos.StoreType;
+import org.apache.tajo.common.TajoDataTypes.Type;
+import org.apache.tajo.storage.StorageConstants;
+
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.Map;
+
+public class TPCH extends BenchmarkSet {
+ private final Log LOG = LogFactory.getLog(TPCH.class);
+ private final String BENCHMARK_DIR = "benchmark/tpch";
+
+ public static final String LINEITEM = "lineitem";
+ public static final String CUSTOMER = "customer";
+ public static final String NATION = "nation";
+ public static final String PART = "part";
+ public static final String REGION = "region";
+ public static final String ORDERS = "orders";
+ public static final String PARTSUPP = "partsupp";
+ public static final String SUPPLIER = "supplier";
+ public static final String EMPTY_ORDERS = "empty_orders";
+
+
+ public static final Map<String, Long> tableVolumes = Maps.newHashMap();
+
+ static {
+ tableVolumes.put(LINEITEM, 759863287L);
+ tableVolumes.put(CUSTOMER, 24346144L);
+ tableVolumes.put(NATION, 2224L);
+ tableVolumes.put(PART, 24135125L);
+ tableVolumes.put(REGION, 389L);
+ tableVolumes.put(ORDERS, 171952161L);
+ tableVolumes.put(PARTSUPP, 118984616L);
+ tableVolumes.put(SUPPLIER, 1409184L);
+ tableVolumes.put(EMPTY_ORDERS, 0L);
+
+ }
+
+ @Override
+ public void loadSchemas() {
+ Schema lineitem = new Schema()
+ .addColumn("l_orderkey", Type.INT4) // 0
+ .addColumn("l_partkey", Type.INT4) // 1
+ .addColumn("l_suppkey", Type.INT4) // 2
+ .addColumn("l_linenumber", Type.INT4) // 3
+ .addColumn("l_quantity", Type.FLOAT8) // 4
+ .addColumn("l_extendedprice", Type.FLOAT8) // 5
+ .addColumn("l_discount", Type.FLOAT8) // 6
+ .addColumn("l_tax", Type.FLOAT8) // 7
+ // TODO - This is temporal solution. 8 and 9 are actually Char type.
+ .addColumn("l_returnflag", Type.TEXT) // 8
+ .addColumn("l_linestatus", Type.TEXT) // 9
+ // TODO - This is temporal solution. 10,11, and 12 are actually Date type.
+ .addColumn("l_shipdate", Type.TEXT) // 10
+ .addColumn("l_commitdate", Type.TEXT) // 11
+ .addColumn("l_receiptdate", Type.TEXT) // 12
+ .addColumn("l_shipinstruct", Type.TEXT) // 13
+ .addColumn("l_shipmode", Type.TEXT) // 14
+ .addColumn("l_comment", Type.TEXT); // 15
+ schemas.put(LINEITEM, lineitem);
+
+ Schema customer = new Schema()
+ .addColumn("c_custkey", Type.INT4) // 0
+ .addColumn("c_name", Type.TEXT) // 1
+ .addColumn("c_address", Type.TEXT) // 2
+ .addColumn("c_nationkey", Type.INT4) // 3
+ .addColumn("c_phone", Type.TEXT) // 4
+ .addColumn("c_acctbal", Type.FLOAT8) // 5
+ .addColumn("c_mktsegment", Type.TEXT) // 6
+ .addColumn("c_comment", Type.TEXT); // 7
+ schemas.put(CUSTOMER, customer);
+
+ Schema nation = new Schema()
+ .addColumn("n_nationkey", Type.INT4) // 0
+ .addColumn("n_name", Type.TEXT) // 1
+ .addColumn("n_regionkey", Type.INT4) // 2
+ .addColumn("n_comment", Type.TEXT); // 3
+ schemas.put(NATION, nation);
+
+ Schema part = new Schema()
+ .addColumn("p_partkey", Type.INT4) // 0
+ .addColumn("p_name", Type.TEXT) // 1
+ .addColumn("p_mfgr", Type.TEXT) // 2
+ .addColumn("p_brand", Type.TEXT) // 3
+ .addColumn("p_type", Type.TEXT) // 4
+ .addColumn("p_size", Type.INT4) // 5
+ .addColumn("p_container", Type.TEXT) // 6
+ .addColumn("p_retailprice", Type.FLOAT8) // 7
+ .addColumn("p_comment", Type.TEXT); // 8
+ schemas.put(PART, part);
+
+ Schema region = new Schema()
+ .addColumn("r_regionkey", Type.INT4) // 0
+ .addColumn("r_name", Type.TEXT) // 1
+ .addColumn("r_comment", Type.TEXT); // 2
+ schemas.put(REGION, region);
+
+ Schema orders = new Schema()
+ .addColumn("o_orderkey", Type.INT4) // 0
+ .addColumn("o_custkey", Type.INT4) // 1
+ .addColumn("o_orderstatus", Type.TEXT) // 2
+ .addColumn("o_totalprice", Type.FLOAT8) // 3
+ // TODO - This is temporal solution. o_orderdate is actually Date type.
+ .addColumn("o_orderdate", Type.TEXT) // 4
+ .addColumn("o_orderpriority", Type.TEXT) // 5
+ .addColumn("o_clerk", Type.TEXT) // 6
+ .addColumn("o_shippriority", Type.INT4) // 7
+ .addColumn("o_comment", Type.TEXT); // 8
+ schemas.put(ORDERS, orders);
+ schemas.put(EMPTY_ORDERS, orders);
+
+
+ Schema partsupp = new Schema()
+ .addColumn("ps_partkey", Type.INT4) // 0
+ .addColumn("ps_suppkey", Type.INT4) // 1
+ .addColumn("ps_availqty", Type.INT4) // 2
+ .addColumn("ps_supplycost", Type.FLOAT8) // 3
+ .addColumn("ps_comment", Type.TEXT); // 4
+ schemas.put(PARTSUPP, partsupp);
+
+ Schema supplier = new Schema()
+ .addColumn("s_suppkey", Type.INT4) // 0
+ .addColumn("s_name", Type.TEXT) // 1
+ .addColumn("s_address", Type.TEXT) // 2
+ .addColumn("s_nationkey", Type.INT4) // 3
+ .addColumn("s_phone", Type.TEXT) // 4
+ .addColumn("s_acctbal", Type.FLOAT8) // 5
+ .addColumn("s_comment", Type.TEXT); // 6
+ schemas.put(SUPPLIER, supplier);
+ }
+
+ public void loadOutSchema() {
+ Schema q2 = new Schema()
+ .addColumn("s_acctbal", Type.FLOAT8)
+ .addColumn("s_name", Type.TEXT)
+ .addColumn("n_name", Type.TEXT)
+ .addColumn("p_partkey", Type.INT4)
+ .addColumn("p_mfgr", Type.TEXT)
+ .addColumn("s_address", Type.TEXT)
+ .addColumn("s_phone", Type.TEXT)
+ .addColumn("s_comment", Type.TEXT);
+ outSchemas.put("q2", q2);
+ }
+
+ public void loadQueries() throws IOException {
+ loadQueries(BENCHMARK_DIR);
+ }
+
+ public void loadTables() throws ServiceException {
+ loadTable(LINEITEM);
+ loadTable(CUSTOMER);
+ loadTable(NATION);
+ loadTable(PART);
+ loadTable(REGION);
+ loadTable(ORDERS);
+ loadTable(PARTSUPP) ;
+ loadTable(SUPPLIER);
+ loadTable(EMPTY_ORDERS);
+
+ }
+
+ private void loadTable(String tableName) throws ServiceException {
+ TableMeta meta = CatalogUtil.newTableMeta(StoreType.CSV);
+ meta.putOption(StorageConstants.CSVFILE_DELIMITER, StorageConstants.DEFAULT_FIELD_DELIMITER);
+
+ try {
+ tajo.createExternalTable(tableName, getSchema(tableName), new Path(dataDir, tableName), meta);
+ } catch (SQLException s) {
+ throw new ServiceException(s);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/AggregationFunctionCallEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/AggregationFunctionCallEval.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/AggregationFunctionCallEval.java
new file mode 100644
index 0000000..10eadce
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/AggregationFunctionCallEval.java
@@ -0,0 +1,92 @@
+/**
+ * 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.tajo.engine.eval;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.FunctionDesc;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.common.TajoDataTypes.DataType;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.engine.function.AggFunction;
+import org.apache.tajo.engine.function.FunctionContext;
+import org.apache.tajo.storage.Tuple;
+import org.apache.tajo.storage.VTuple;
+
+public class AggregationFunctionCallEval extends FunctionEval implements Cloneable {
+ @Expose protected AggFunction instance;
+ @Expose boolean firstPhase = false;
+ private Tuple params;
+
+ public AggregationFunctionCallEval(FunctionDesc desc, AggFunction instance, EvalNode[] givenArgs) {
+ super(EvalType.AGG_FUNCTION, desc, givenArgs);
+ this.instance = instance;
+ }
+
+ public FunctionContext newContext() {
+ return instance.newContext();
+ }
+
+ public void merge(FunctionContext context, Schema schema, Tuple tuple) {
+ if (params == null) {
+ this.params = new VTuple(argEvals.length);
+ }
+
+ if (argEvals != null) {
+ for (int i = 0; i < argEvals.length; i++) {
+ params.put(i, argEvals[i].eval(schema, tuple));
+ }
+ }
+
+ if (firstPhase) {
+ instance.eval(context, params);
+ } else {
+ instance.merge(context, params);
+ }
+ }
+
+ @Override
+ public Datum eval(Schema schema, Tuple tuple) {
+ throw new UnsupportedOperationException("Cannot execute eval() of aggregation function");
+ }
+
+ public Datum terminate(FunctionContext context) {
+ if (firstPhase) {
+ return instance.getPartialResult(context);
+ } else {
+ return instance.terminate(context);
+ }
+ }
+
+ @Override
+ public DataType getValueType() {
+ if (firstPhase) {
+ return instance.getPartialResultType();
+ } else {
+ return funcDesc.getReturnType();
+ }
+ }
+
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+ public void setFirstPhase() {
+ this.firstPhase = true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/AlgebraicException.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/AlgebraicException.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/AlgebraicException.java
new file mode 100644
index 0000000..9dba6df
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/AlgebraicException.java
@@ -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.tajo.engine.eval;
+
+public class AlgebraicException extends RuntimeException {
+ private static final long serialVersionUID = -1813125460274622006L;
+
+ public AlgebraicException() {
+ }
+
+ public AlgebraicException(String message) {
+ super(message);
+ }
+
+ public AlgebraicException(Throwable cause) {
+ super(cause);
+ }
+
+ public AlgebraicException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/AlgebraicUtil.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/AlgebraicUtil.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/AlgebraicUtil.java
new file mode 100644
index 0000000..6bb0160
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/AlgebraicUtil.java
@@ -0,0 +1,398 @@
+/**
+ * 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.tajo.engine.eval;
+
+import org.apache.tajo.catalog.Column;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class AlgebraicUtil {
+
+ /**
+ * Transpose a given comparison expression into the expression
+ * where the variable corresponding to the target is placed
+ * on the left-hand side.
+ *
+ * @param expr
+ * @param target
+ * @return Transposed expression
+ */
+ public static EvalNode transpose(EvalNode expr, Column target) {
+ EvalNode commutated = null;
+ // If the variable is in the right term, inverse the expr.
+ if (!EvalTreeUtil.containColumnRef(expr.getLeftExpr(), target)) {
+ // the commutate method works with a copy of the expr
+ commutated = commutate(expr);
+ } else {
+ try {
+ commutated = (EvalNode) expr.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new AlgebraicException(e);
+ }
+ }
+
+ return _transpose(commutated, target);
+ }
+
+ private static EvalNode _transpose(EvalNode _expr, Column target) {
+ EvalNode expr = eliminateConstantExprs(_expr);
+
+ if (isSingleVar(expr.getLeftExpr())) {
+ return expr;
+ }
+
+ EvalNode left = expr.getLeftExpr();
+ EvalNode lTerm = null;
+ EvalNode rTerm = null;
+
+ if (left.getType() == EvalType.PLUS
+ || left.getType() == EvalType.MINUS
+ || left.getType() == EvalType.MULTIPLY
+ || left.getType() == EvalType.DIVIDE) {
+
+ // If the left-left term is a variable, the left-right term is transposed.
+ if(EvalTreeUtil.containColumnRef(left.getLeftExpr(), target)) {
+ PartialBinaryExpr tmpTerm = splitRightTerm(left);
+ tmpTerm.type = inverseOperator(tmpTerm.type);
+ tmpTerm.setLeftExpr(expr.getRightExpr());
+ lTerm = left.getLeftExpr();
+ rTerm = new BinaryEval(tmpTerm);
+ } else {
+ // Otherwise, the left-right term is transposed into the left-left term.
+ PartialBinaryExpr tmpTerm = splitLeftTerm(left);
+ tmpTerm.type = inverseOperator(tmpTerm.type);
+ tmpTerm.setLeftExpr(expr.getRightExpr());
+ lTerm = left.getRightExpr();
+ rTerm = new BinaryEval(tmpTerm);
+ }
+ }
+
+ return _transpose(new BinaryEval(expr.getType(), lTerm, rTerm), target);
+ }
+
+ /**
+ * Inverse a given operator (+, -, *, /)
+ *
+ * @param type
+ * @return inversed operator type
+ */
+ public static EvalType inverseOperator(EvalType type) {
+ switch (type) {
+ case PLUS:
+ return EvalType.MINUS;
+ case MINUS:
+ return EvalType.PLUS;
+ case MULTIPLY:
+ return EvalType.DIVIDE;
+ case DIVIDE:
+ return EvalType.MULTIPLY;
+ default : throw new AlgebraicException("ERROR: cannot inverse the operator: "
+ + type);
+ }
+ }
+
+ /**
+ * Examine if a given expr is a variable.
+ *
+ * @param node
+ * @return true if a given expr is a variable.
+ */
+ private static boolean isSingleVar(EvalNode node) {
+ if (node.getType() == EvalType.FIELD) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Simplify the given expr. That is, all subexprs consisting of only constants
+ * are calculated immediately.
+ *
+ * @param expr to be simplified
+ * @return the simplified expr
+ */
+ public static EvalNode eliminateConstantExprs(EvalNode expr) {
+
+ if (expr.getType() == EvalType.FIELD) {
+ return expr;
+ }
+
+ EvalNode left = expr.getLeftExpr();
+ EvalNode right = expr.getRightExpr();
+
+ switch (expr.getType()) {
+ case AND:
+ case OR:
+ case EQUAL:
+ case NOT_EQUAL:
+ case LTH:
+ case LEQ:
+ case GTH:
+ case GEQ:
+ case PLUS:
+ case MINUS:
+ case MULTIPLY:
+ case DIVIDE:
+ case MODULAR:
+ left = eliminateConstantExprs(left);
+ right = eliminateConstantExprs(right);
+
+ if (left.getType() == EvalType.CONST && right.getType() == EvalType.CONST) {
+ return new ConstEval(expr.eval(null, null));
+ } else {
+ return new BinaryEval(expr.getType(), left, right);
+ }
+
+ case CONST:
+ return expr;
+
+ default: new AlgebraicException("Wrong expression: " + expr);
+ }
+ return expr;
+ }
+
+ /**
+ * @param expr to be evaluated if the expr includes one variable
+ * @return true if expr has only one field
+ */
+ public static boolean containSingleVar(EvalNode expr) {
+ Map<EvalType, Integer> counter = EvalTreeUtil.getExprCounters(expr);
+
+ int sum = 0;
+ for (Integer cnt : counter.values()) {
+ sum += cnt;
+ }
+
+ if (sum == 1 && counter.get(EvalType.FIELD) == 1) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Split the left term and transform it into the right deep expression.
+ *
+ * @param expr - notice the left term of this expr will be eliminated
+ * after done.
+ * @return the separated expression changed into the right deep expression.
+ * For example, the expr 'x * y' is transformed into '* x'.
+ *
+ */
+ public static PartialBinaryExpr splitLeftTerm(EvalNode expr) {
+
+ if (!(expr.getType() == EvalType.PLUS
+ || expr.getType() == EvalType.MINUS
+ || expr.getType() == EvalType.MULTIPLY
+ || expr.getType() == EvalType.DIVIDE)) {
+ throw new AlgebraicException("Invalid algebraic operation: " + expr);
+ }
+
+ if (expr.getLeftExpr().getType() != EvalType.CONST) {
+ return splitLeftTerm(expr.getLeftExpr());
+ }
+
+ PartialBinaryExpr splitted =
+ new PartialBinaryExpr(expr.getType(), null, expr.getLeftExpr());
+ expr.setLeftExpr(null);
+ return splitted;
+ }
+
+ /**
+ * Split the left term and transform it into the right deep expression.
+ *
+ * @param expr - to be splited
+ * @return the separated expression changed into the right deep expression.
+ * For example, the expr 'x * y' is transformed into '* y'.
+ *
+ * @throws CloneNotSupportedException
+ */
+ public static PartialBinaryExpr splitRightTerm(EvalNode expr) {
+
+ if (!(expr.getType() == EvalType.PLUS
+ || expr.getType() == EvalType.MINUS
+ || expr.getType() == EvalType.MULTIPLY
+ || expr.getType() == EvalType.DIVIDE)) {
+ throw new AlgebraicException("Invalid algebraic operation: " + expr);
+ }
+
+ if (expr.getRightExpr().getType() != EvalType.CONST) {
+ return splitRightTerm(expr.getRightExpr());
+ }
+
+ PartialBinaryExpr splitted =
+ new PartialBinaryExpr(expr.getType(), null, expr.getRightExpr());
+ expr.setRightExpr(null);
+ return splitted;
+ }
+
+ /**
+ * Commutate two terms which are added, subtracted and multiplied.
+ *
+ * @param inputExpr
+ * @return
+ */
+ public static EvalNode commutate(EvalNode inputExpr) {
+ EvalNode expr;
+ switch (inputExpr.getType()) {
+ case AND:
+ case OR:
+ case EQUAL:
+ case PLUS:
+ case MINUS:
+ case MULTIPLY: // these types can be commutated w/o any change
+ expr = EvalTreeFactory.create(inputExpr.getType(),
+ inputExpr.getRightExpr(), inputExpr.getLeftExpr());
+ break;
+
+ case GTH:
+ expr = EvalTreeFactory.create(EvalType.LTH,
+ inputExpr.getRightExpr(), inputExpr.getLeftExpr());
+ break;
+ case GEQ:
+ expr = EvalTreeFactory.create(EvalType.LEQ,
+ inputExpr.getRightExpr(), inputExpr.getLeftExpr());
+ break;
+ case LTH:
+ expr = EvalTreeFactory.create(EvalType.GTH,
+ inputExpr.getRightExpr(), inputExpr.getLeftExpr());
+ break;
+ case LEQ:
+ expr = EvalTreeFactory.create(EvalType.GEQ,
+ inputExpr.getRightExpr(), inputExpr.getLeftExpr());
+ break;
+
+ default :
+ throw new AlgebraicException("Cannot commutate the expr: " + inputExpr);
+ }
+
+ return expr;
+ }
+
+ public static boolean isComparisonOperator(EvalNode expr) {
+ return expr.getType() == EvalType.EQUAL ||
+ expr.getType() == EvalType.LEQ ||
+ expr.getType() == EvalType.LTH ||
+ expr.getType() == EvalType.GEQ ||
+ expr.getType() == EvalType.GTH ||
+ expr.getType() == EvalType.BETWEEN;
+ }
+
+ public static boolean isIndexableOperator(EvalNode expr) {
+ return expr.getType() == EvalType.EQUAL ||
+ expr.getType() == EvalType.LEQ ||
+ expr.getType() == EvalType.LTH ||
+ expr.getType() == EvalType.GEQ ||
+ expr.getType() == EvalType.GTH ||
+ expr.getType() == EvalType.BETWEEN ||
+ expr.getType() == EvalType.IN ||
+ (expr.getType() == EvalType.LIKE && !((LikePredicateEval)expr).isLeadingWildCard());
+ }
+
+ /**
+ * Convert a list of conjunctive normal forms into a singleton expression.
+ *
+ * @param cnfExprs
+ * @return The EvalNode object that merges all CNF-formed expressions.
+ */
+ public static EvalNode createSingletonExprFromCNF(EvalNode... cnfExprs) {
+ if (cnfExprs.length == 1) {
+ return cnfExprs[0];
+ }
+
+ return createSingletonExprFromCNFRecursive(cnfExprs, 0);
+ }
+
+ private static EvalNode createSingletonExprFromCNFRecursive(EvalNode[] evalNode, int idx) {
+ if (idx == evalNode.length - 2) {
+ return new BinaryEval(EvalType.AND, evalNode[idx], evalNode[idx + 1]);
+ } else {
+ return new BinaryEval(EvalType.AND, evalNode[idx], createSingletonExprFromCNFRecursive(evalNode, idx + 1));
+ }
+ }
+
+ /**
+ * Transforms a expression to an array of conjunctive normal formed expressions.
+ *
+ * @param expr The expression to be transformed to an array of CNF-formed expressions.
+ * @return An array of CNF-formed expressions
+ */
+ public static EvalNode [] toConjunctiveNormalFormArray(EvalNode expr) {
+ List<EvalNode> list = new ArrayList<EvalNode>();
+ toConjunctiveNormalFormArrayRecursive(expr, list);
+ return list.toArray(new EvalNode[list.size()]);
+ }
+
+ private static void toConjunctiveNormalFormArrayRecursive(EvalNode node, List<EvalNode> found) {
+ if (node.getType() == EvalType.AND) {
+ toConjunctiveNormalFormArrayRecursive(node.getLeftExpr(), found);
+ toConjunctiveNormalFormArrayRecursive(node.getRightExpr(), found);
+ } else {
+ found.add(node);
+ }
+ }
+
+ /**
+ * Convert a list of conjunctive normal forms into a singleton expression.
+ *
+ * @param cnfExprs
+ * @return The EvalNode object that merges all CNF-formed expressions.
+ */
+ public static EvalNode createSingletonExprFromDNF(EvalNode... cnfExprs) {
+ if (cnfExprs.length == 1) {
+ return cnfExprs[0];
+ }
+
+ return createSingletonExprFromDNFRecursive(cnfExprs, 0);
+ }
+
+ private static EvalNode createSingletonExprFromDNFRecursive(EvalNode[] evalNode, int idx) {
+ if (idx == evalNode.length - 2) {
+ return new BinaryEval(EvalType.OR, evalNode[idx], evalNode[idx + 1]);
+ } else {
+ return new BinaryEval(EvalType.OR, evalNode[idx], createSingletonExprFromDNFRecursive(evalNode, idx + 1));
+ }
+ }
+
+ /**
+ * Transforms a expression to an array of disjunctive normal formed expressions.
+ *
+ * @param exprs The expressions to be transformed to an array of CNF-formed expressions.
+ * @return An array of CNF-formed expressions
+ */
+ public static EvalNode [] toDisjunctiveNormalFormArray(EvalNode...exprs) {
+ List<EvalNode> list = new ArrayList<EvalNode>();
+ for (EvalNode expr : exprs) {
+ toDisjunctiveNormalFormArrayRecursive(expr, list);
+ }
+ return list.toArray(new EvalNode[list.size()]);
+ }
+
+ private static void toDisjunctiveNormalFormArrayRecursive(EvalNode node, List<EvalNode> found) {
+ if (node.getType() == EvalType.OR) {
+ toDisjunctiveNormalFormArrayRecursive(node.getLeftExpr(), found);
+ toDisjunctiveNormalFormArrayRecursive(node.getRightExpr(), found);
+ } else {
+ found.add(node);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/BasicEvalNodeVisitor.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/BasicEvalNodeVisitor.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/BasicEvalNodeVisitor.java
new file mode 100644
index 0000000..2208119
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/BasicEvalNodeVisitor.java
@@ -0,0 +1,341 @@
+/**
+ * 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.tajo.engine.eval;
+
+import java.util.Stack;
+
+public class BasicEvalNodeVisitor<CONTEXT, RESULT> implements EvalNodeVisitor2<CONTEXT, RESULT> {
+
+ @Override
+ public RESULT visitChild(CONTEXT context, EvalNode evalNode, Stack<EvalNode> stack) {
+ RESULT result;
+ switch (evalNode.getType()) {
+ // Column and Value reference expressions
+ case CONST:
+ result = visitConst(context, (ConstEval) evalNode, stack);
+ break;
+ case ROW_CONSTANT:
+ result = visitRowConstant(context, (RowConstantEval) evalNode, stack);
+ break;
+ case FIELD:
+ result = visitField(context, stack, (FieldEval) evalNode);
+ break;
+
+ // Arithmetic expression
+ case PLUS:
+ result = visitPlus(context, (BinaryEval) evalNode, stack);
+ break;
+ case MINUS:
+ result = visitMinus(context, (BinaryEval) evalNode, stack);
+ break;
+ case MULTIPLY:
+ result = visitMultiply(context, (BinaryEval) evalNode, stack);
+ break;
+ case DIVIDE:
+ result = visitDivide(context, (BinaryEval) evalNode, stack);
+ break;
+ case MODULAR:
+ result = visitModular(context, (BinaryEval) evalNode, stack);
+ break;
+
+ // Logical Predicates
+ case AND:
+ result = visitAnd(context, (BinaryEval) evalNode, stack);
+ break;
+ case OR:
+ result = visitOr(context, (BinaryEval) evalNode, stack);
+ break;
+ case NOT:
+ result = visitNot(context, (NotEval) evalNode, stack);
+ break;
+
+ // Comparison Predicates
+ case EQUAL:
+ result = visitEqual(context, (BinaryEval) evalNode, stack);
+ break;
+ case NOT_EQUAL:
+ result = visitNotEqual(context, (BinaryEval) evalNode, stack);
+ break;
+ case LTH:
+ result = visitLessThan(context, (BinaryEval) evalNode, stack);
+ break;
+ case LEQ:
+ result = visitLessThanOrEqual(context, (BinaryEval) evalNode, stack);
+ break;
+ case GTH:
+ result = visitGreaterThan(context, (BinaryEval) evalNode, stack);
+ break;
+ case GEQ:
+ result = visitGreaterThanOrEqual(context, (BinaryEval) evalNode, stack);
+ break;
+
+ // SQL standard predicates
+ case IS_NULL:
+ result = visitIsNull(context, (IsNullEval) evalNode, stack);
+ break;
+ case BETWEEN:
+ result = visitBetween(context, (BetweenPredicateEval) evalNode, stack);
+ break;
+ case CASE:
+ result = visitCaseWhen(context, (CaseWhenEval) evalNode, stack);
+ break;
+ case IF_THEN:
+ result = visitIfThen(context, (CaseWhenEval.IfThenEval) evalNode, stack);
+ break;
+ case IN:
+ result = visitInPredicate(context, (InEval) evalNode, stack);
+ break;
+
+ // String operators and Pattern match predicates
+ case LIKE:
+ result = visitLike(context, (LikePredicateEval) evalNode, stack);
+ break;
+ case SIMILAR_TO:
+ result = visitSimilarTo(context, (SimilarToPredicateEval) evalNode, stack);
+ break;
+ case REGEX:
+ result = visitRegex(context, (RegexPredicateEval) evalNode, stack);
+ break;
+ case CONCATENATE:
+ result = visitConcatenate(context, (BinaryEval) evalNode, stack);
+ break;
+
+ // Functions
+ case FUNCTION:
+ result = visitFuncCall(context, (GeneralFunctionEval) evalNode, stack);
+ break;
+ case AGG_FUNCTION:
+ result = visitAggrFuncCall(context, (AggregationFunctionCallEval) evalNode, stack);
+ break;
+
+ case SIGNED:
+ result = visitSigned(context, (SignedEval) evalNode, stack);
+ break;
+ case CAST:
+ result = visitCast(context, (CastEval) evalNode, stack);
+ break;
+
+ default:
+ throw new InvalidEvalException("Unknown EvalNode: " + evalNode);
+ }
+
+ return result;
+ }
+
+ private RESULT visitDefaultBinaryEval(CONTEXT context, Stack<EvalNode> stack, BinaryEval binaryEval) {
+ stack.push(binaryEval);
+ RESULT result = visitChild(context, binaryEval.getLeftExpr(), stack);
+ visitChild(context, binaryEval.getRightExpr(), stack);
+ stack.pop();
+ return result;
+ }
+
+ private RESULT visitDefaultFunctionEval(CONTEXT context, Stack<EvalNode> stack, FunctionEval functionEval) {
+ RESULT result = null;
+ stack.push(functionEval);
+ if (functionEval.getArgs() != null) {
+ for (EvalNode arg : functionEval.getArgs()) {
+ result = visitChild(context, arg, stack);
+ }
+ }
+ stack.pop();
+ return result;
+ }
+
+ @Override
+ public RESULT visitConst(CONTEXT context, ConstEval evalNode, Stack<EvalNode> stack) {
+ return null;
+ }
+
+ @Override
+ public RESULT visitRowConstant(CONTEXT context, RowConstantEval evalNode, Stack<EvalNode> stack) {
+ return null;
+ }
+
+ @Override
+ public RESULT visitField(CONTEXT context, Stack<EvalNode> stack, FieldEval evalNode) {
+ return null;
+ }
+
+ @Override
+ public RESULT visitPlus(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitMinus(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitMultiply(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitDivide(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitModular(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitAnd(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitOr(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitNot(CONTEXT context, NotEval evalNode, Stack<EvalNode> stack) {
+ RESULT result;
+ stack.push(evalNode);
+ result = visitChild(context, evalNode.getChild(), stack);
+ stack.pop();
+
+ return result;
+ }
+
+ @Override
+ public RESULT visitEqual(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitNotEqual(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitLessThan(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitLessThanOrEqual(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitGreaterThan(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitGreaterThanOrEqual(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitIsNull(CONTEXT context, IsNullEval evalNode, Stack<EvalNode> stack) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitBetween(CONTEXT context, BetweenPredicateEval evalNode, Stack<EvalNode> stack) {
+ stack.push(evalNode);
+ RESULT result = visitChild(context, evalNode.getPredicand(), stack);
+ visitChild(context, evalNode.getBegin(), stack);
+ visitChild(context, evalNode.getEnd(), stack);
+ return result;
+ }
+
+ @Override
+ public RESULT visitCaseWhen(CONTEXT context, CaseWhenEval evalNode, Stack<EvalNode> stack) {
+ RESULT result = null;
+ stack.push(evalNode);
+ for (CaseWhenEval.IfThenEval ifThenEval : evalNode.getIfThenEvals()) {
+ result = visitIfThen(context, ifThenEval, stack);
+ }
+ if (evalNode.hasElse()) {
+ result = visitChild(context, evalNode.getElse(), stack);
+ }
+ stack.pop();
+ return result;
+ }
+
+ @Override
+ public RESULT visitIfThen(CONTEXT context, CaseWhenEval.IfThenEval evalNode, Stack<EvalNode> stack) {
+ RESULT result;
+ stack.push(evalNode);
+ result = visitChild(context, evalNode.getConditionExpr(), stack);
+ visitChild(context, evalNode.getResultExpr(), stack);
+ stack.pop();
+ return result;
+ }
+
+ @Override
+ public RESULT visitInPredicate(CONTEXT context, InEval evalNode, Stack<EvalNode> stack) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitLike(CONTEXT context, LikePredicateEval evalNode, Stack<EvalNode> stack) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitSimilarTo(CONTEXT context, SimilarToPredicateEval evalNode, Stack<EvalNode> stack) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitRegex(CONTEXT context, RegexPredicateEval evalNode, Stack<EvalNode> stack) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitConcatenate(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack) {
+ return visitDefaultBinaryEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitFuncCall(CONTEXT context, GeneralFunctionEval evalNode, Stack<EvalNode> stack) {
+ return visitDefaultFunctionEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitAggrFuncCall(CONTEXT context, AggregationFunctionCallEval evalNode, Stack<EvalNode> stack) {
+ return visitDefaultFunctionEval(context, stack, evalNode);
+ }
+
+ @Override
+ public RESULT visitSigned(CONTEXT context, SignedEval signedEval, Stack<EvalNode> stack) {
+ RESULT result;
+ stack.push(signedEval);
+ result = visitChild(context, signedEval.getChild(), stack);
+ stack.pop();
+ return result;
+ }
+
+ @Override
+ public RESULT visitCast(CONTEXT context, CastEval signedEval, Stack<EvalNode> stack) {
+ RESULT result;
+ stack.push(signedEval);
+ result = visitChild(context, signedEval.getOperand(), stack);
+ stack.pop();
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/BetweenPredicateEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/BetweenPredicateEval.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/BetweenPredicateEval.java
new file mode 100644
index 0000000..0f30ac9
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/BetweenPredicateEval.java
@@ -0,0 +1,219 @@
+/**
+ * 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.tajo.engine.eval;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.datum.DatumFactory;
+import org.apache.tajo.datum.NullDatum;
+import org.apache.tajo.storage.Tuple;
+
+public class BetweenPredicateEval extends EvalNode {
+ private static final TajoDataTypes.DataType RES_TYPE = CatalogUtil.newSimpleDataType(TajoDataTypes.Type.BOOLEAN);
+ @Expose private boolean not;
+ @Expose private boolean symmetric;
+ @Expose private EvalNode predicand;
+ @Expose private EvalNode begin;
+ @Expose private EvalNode end;
+
+ private Checker checker;
+
+ public BetweenPredicateEval(boolean not, boolean symmetric, EvalNode predicand, EvalNode begin, EvalNode end) {
+ super(EvalType.BETWEEN);
+ this.not = not;
+ this.symmetric = symmetric;
+ this.predicand = predicand;
+ this.begin = begin;
+ this.end = end;
+ }
+
+ public EvalNode getPredicand() {
+ return predicand;
+ }
+
+ public EvalNode getBegin() {
+ return begin;
+ }
+
+ public EvalNode getEnd() {
+ return end;
+ }
+
+ private static interface Checker {
+ Datum eval(Schema schema, Tuple param);
+ }
+
+ private static class ConstantChecker implements Checker {
+ EvalNode predicand;
+ Datum begin;
+ Datum end;
+ private boolean not;
+
+ private ConstantChecker(boolean not, EvalNode predicand, Datum begin, Datum end) {
+ this.predicand = predicand;
+ this.not = not;
+ if (begin.compareTo(end) > 0) {
+ this.begin = end;
+ this.end = begin;
+ } else {
+ this.begin = begin;
+ this.end = end;
+ }
+ }
+
+ @Override
+ public Datum eval(Schema schema, Tuple param) {
+ Datum predicandValue = predicand.eval(schema, param);
+
+ if (!predicandValue.isNull()) {
+ return DatumFactory.createBool(not ^ (predicandValue.greaterThanEqual(begin).asBool()
+ && predicandValue.lessThanEqual(end).asBool()));
+ } else {
+ return NullDatum.get();
+ }
+ }
+ }
+
+ private static class AsymmetricChecker implements Checker {
+ EvalNode predicand;
+ EvalNode begin;
+ EvalNode end;
+ private boolean not;
+
+ private AsymmetricChecker(boolean not, EvalNode predicand, EvalNode begin, EvalNode end) {
+ this.not = not;
+ this.predicand = predicand;
+ this.begin = begin;
+ this.end = end;
+ }
+
+ @Override
+ public Datum eval(Schema schema, Tuple param) {
+ Datum predicandValue = predicand.eval(schema, param);
+ Datum beginValue = begin.eval(schema, param);
+ Datum endValue = end.eval(schema, param);
+
+ if (!(predicandValue.isNull() || beginValue.isNull() || endValue.isNull())) {
+ return
+ DatumFactory.createBool(not ^ (predicandValue.greaterThanEqual(beginValue).asBool()
+ && predicandValue.lessThanEqual(endValue).asBool()));
+ } else {
+ return NullDatum.get();
+ }
+ }
+ }
+
+ private static class SymmetricChecker implements Checker {
+ boolean not;
+ EvalNode predicand;
+ EvalNode begin;
+ EvalNode end;
+
+ SymmetricChecker(boolean not, EvalNode predicand, EvalNode begin, EvalNode end) {
+ this.not = not;
+ this.predicand = predicand;
+ this.begin = begin;
+ this.end = end;
+ }
+
+ @Override
+ public Datum eval(Schema schema, Tuple param) {
+ Datum predicandValue = predicand.eval(schema, param);
+ Datum beginValue = begin.eval(schema, param);
+ Datum endValue = end.eval(schema, param);
+
+ if (!(predicandValue.isNull()|| beginValue.isNull() || endValue.isNull())) {
+ return DatumFactory.createBool( not ^
+ (predicandValue.greaterThanEqual(beginValue).asBool() && predicandValue.lessThanEqual(endValue).asBool()) ||
+ (predicandValue.lessThanEqual(beginValue).asBool() && predicandValue.greaterThanEqual(endValue).asBool())
+ );
+ } else {
+ return NullDatum.get();
+ }
+ }
+ }
+
+ @Override
+ public TajoDataTypes.DataType getValueType() {
+ return RES_TYPE;
+ }
+
+ @Override
+ public String getName() {
+ return "between";
+ }
+
+ @Override
+ public String toString() {
+ return predicand + " BETWEEN " + (symmetric ? "SYMMETRIC" : "ASYMMETRIC") + " " + begin + " AND " + end;
+ }
+
+ @Override
+ public Datum eval(Schema schema, Tuple tuple) {
+ if (checker == null) {
+ if (begin.getType() == EvalType.CONST && end.getType() == EvalType.CONST) {
+ Datum beginValue = ((ConstEval)begin).getValue();
+ Datum endValue = ((ConstEval)end).getValue();
+
+ if (symmetric || beginValue.compareTo(endValue) <= 0) {
+ checker = new ConstantChecker(not, predicand, beginValue, endValue);
+ } else {
+ checker = new AsymmetricChecker(not, predicand, begin, end);
+ }
+ } else {
+ if (symmetric) {
+ checker = new SymmetricChecker(not, predicand, begin, end);
+ } else {
+ checker = new AsymmetricChecker(not, predicand, begin, end);
+ }
+ }
+ }
+
+ return checker.eval(schema, tuple);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof BetweenPredicateEval) {
+ BetweenPredicateEval another = (BetweenPredicateEval) obj;
+ return not == another.not && symmetric == another.symmetric && predicand.equals(another.predicand) &&
+ begin.equals(another.begin) && end.equals(another.end);
+ }
+ return false;
+ }
+
+ @Deprecated
+ public void preOrder(EvalNodeVisitor visitor) {
+ visitor.visit(this);
+ predicand.preOrder(visitor);
+ begin.preOrder(visitor);
+ end.preOrder(visitor);
+ }
+
+ @Deprecated
+ public void postOrder(EvalNodeVisitor visitor) {
+ predicand.postOrder(visitor);
+ begin.postOrder(visitor);
+ end.postOrder(visitor);
+ visitor.visit(this);
+ }
+}
\ No newline at end of file