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 13:44:51 UTC

[48/57] [abbrv] [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