Skip to content

Commit

Permalink
Support SELECT expr;
Browse files Browse the repository at this point in the history
  • Loading branch information
xzdandy committed Sep 10, 2023
1 parent 2671059 commit 79dd6f3
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 30 deletions.
6 changes: 4 additions & 2 deletions evadb/binder/statement_binder.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,9 @@ def _bind_create_index_statement(self, node: CreateIndexStatement):

@bind.register(SelectStatement)
def _bind_select_statement(self, node: SelectStatement):
self.bind(node.from_table)
if node.from_table:
self.bind(node.from_table)

if node.where_clause:
self.bind(node.where_clause)
if node.where_clause.etype == ExpressionType.COMPARE_LIKE:
Expand Down Expand Up @@ -180,7 +182,7 @@ def _bind_select_statement(self, node: SelectStatement):
self._binder_context = current_context

# chunk_params only supported for DOCUMENT TYPE
if node.from_table.chunk_params:
if node.from_table and node.from_table.chunk_params:
assert is_document_table(
node.from_table.table.table_obj
), "CHUNK related parameters only supported for DOCUMENT tables."
Expand Down
2 changes: 1 addition & 1 deletion evadb/executor/executor_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class ExecutorError(Exception):
def apply_project(
batch: Batch, project_list: List[AbstractExpression], catalog: "CatalogManager"
):
if not batch.empty() and project_list:
if batch is None or (not batch.empty() and project_list):
batches = [expr.evaluate(batch) for expr in project_list]
batch = Batch.merge_column_wise(batches)

Expand Down
17 changes: 12 additions & 5 deletions evadb/executor/project_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

from evadb.database import EvaDBDatabase
from evadb.executor.abstract_executor import AbstractExecutor
from evadb.executor.executor_utils import apply_project
from evadb.executor.executor_utils import ExecutorError, apply_project
from evadb.models.storage.batch import Batch
from evadb.plan_nodes.project_plan import ProjectPlan

Expand All @@ -29,9 +29,16 @@ def __init__(self, db: EvaDBDatabase, node: ProjectPlan):
self.target_list = node.target_list

def exec(self, *args, **kwargs) -> Iterator[Batch]:
child_executor = self.children[0]
for batch in child_executor.exec(**kwargs):
batch = apply_project(batch, self.target_list, self.catalog())

# SELECT FORECAST(12);
if len(self.children) == 0:
batch = apply_project(None, self.target_list, self.catalog())
if not batch.empty():
yield batch
elif len(self.children) == 1:
child_executor = self.children[0]
for batch in child_executor.exec(**kwargs):
batch = apply_project(batch, self.target_list, self.catalog())
if not batch.empty():
yield batch
else:
raise ExecutorError("ProjectExecutor has more than 1 children.")
8 changes: 7 additions & 1 deletion evadb/expression/constant_value_expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,13 @@ def __init__(self, value: Any, v_type: ColumnType = ColumnType.INTEGER):
self._v_type = v_type

def evaluate(self, batch: Batch, **kwargs):
batch = Batch(pd.DataFrame({0: [self._value] * len(batch)}))
repeated = 0
# SELECT expr;
if batch is None:
repeated = 1
else:
repeated = len(batch)
batch = Batch(pd.DataFrame({0: [self._value] * repeated}))
return batch

def signature(self) -> str:
Expand Down
7 changes: 6 additions & 1 deletion evadb/expression/function_expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,11 @@ def evaluate(self, batch: Batch, **kwargs) -> Batch:
outcomes.modify_column_alias(self.alias)

# record the number of function calls
self._stats.num_calls += len(batch)
# TODO: should get from the function abstract class.
if batch is not None:
self._stats.num_calls += len(batch)
else:
self._stats.num_calls += 1

# try persisting the stats to catalog and do not crash if we fail in doing so
try:
Expand Down Expand Up @@ -187,6 +191,7 @@ def _apply_function_expression(self, func: Callable, batch: Batch, **kwargs):
if not self._cache:
return func_args.apply_function_expression(func)

# TODO: the following cache code does not work for `SELECT func(1);`
output_cols = [obj.name for obj in self.function_obj.outputs]

# 1. check cache
Expand Down
16 changes: 16 additions & 0 deletions evadb/optimizer/rules/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -1176,6 +1176,22 @@ def apply(self, before: LogicalProject, context: OptimizerContext):
yield after


class LogicalProjectNoTableToPhysical(Rule):
def __init__(self):
pattern = Pattern(OperatorType.LOGICALPROJECT)
super().__init__(RuleType.LOGICAL_PROJECT_NO_TABLE_TO_PHYSICAL, pattern)

def promise(self):
return Promise.LOGICAL_PROJECT_NO_TABLE_TO_PHYSICAL

def check(self, grp_id: int, context: OptimizerContext):
return True

def apply(self, before: LogicalProject, context: OptimizerContext):
after = ProjectPlan(before.target_list)
yield after


class LogicalShowToPhysical(Rule):
def __init__(self):
pattern = Pattern(OperatorType.LOGICAL_SHOW)
Expand Down
2 changes: 2 additions & 0 deletions evadb/optimizer/rules/rules_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class RuleType(Flag):
LOGICAL_FUNCTION_SCAN_TO_PHYSICAL = auto()
LOGICAL_FILTER_TO_PHYSICAL = auto()
LOGICAL_PROJECT_TO_PHYSICAL = auto()
LOGICAL_PROJECT_NO_TABLE_TO_PHYSICAL = auto()
LOGICAL_SHOW_TO_PHYSICAL = auto()
LOGICAL_EXPLAIN_TO_PHYSICAL = auto()
LOGICAL_CREATE_INDEX_TO_VECTOR_INDEX = auto()
Expand Down Expand Up @@ -121,6 +122,7 @@ class Promise(IntEnum):
LOGICAL_FUNCTION_SCAN_TO_PHYSICAL = auto()
LOGICAL_FILTER_TO_PHYSICAL = auto()
LOGICAL_PROJECT_TO_PHYSICAL = auto()
LOGICAL_PROJECT_NO_TABLE_TO_PHYSICAL = auto()
LOGICAL_SHOW_TO_PHYSICAL = auto()
LOGICAL_EXPLAIN_TO_PHYSICAL = auto()
LOGICAL_CREATE_INDEX_TO_VECTOR_INDEX = auto()
Expand Down
2 changes: 2 additions & 0 deletions evadb/optimizer/rules/rules_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
LogicalLimitToPhysical,
LogicalLoadToPhysical,
LogicalOrderByToPhysical,
LogicalProjectNoTableToPhysical,
LogicalProjectToPhysical,
LogicalProjectToRayPhysical,
LogicalRenameToPhysical,
Expand Down Expand Up @@ -114,6 +115,7 @@ def __init__(self, config: ConfigurationManager):
LogicalExplainToPhysical(),
LogicalCreateIndexToVectorIndex(),
LogicalVectorIndexScanToPhysical(),
LogicalProjectNoTableToPhysical(),
]

# These rules are enabled only if
Expand Down
37 changes: 18 additions & 19 deletions evadb/optimizer/statement_to_opr_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,30 +120,28 @@ def visit_select(self, statement: SelectStatement):
"""

table_ref = statement.from_table
if table_ref is None:
logger.error("From entry missing in select statement")
return None
if table_ref is not None:
self.visit_table_ref(table_ref)

self.visit_table_ref(table_ref)
# Filter Operator
predicate = statement.where_clause
if predicate is not None:
self._visit_select_predicate(predicate)

# Filter Operator
predicate = statement.where_clause
if predicate is not None:
self._visit_select_predicate(predicate)
# TODO ACTION: Group By

# union
if statement.union_link is not None:
self._visit_union(statement.union_link, statement.union_all)
if statement.groupby_clause is not None:
self._visit_groupby(statement.groupby_clause)

# TODO ACTION: Group By
if statement.groupby_clause is not None:
self._visit_groupby(statement.groupby_clause)
if statement.orderby_list is not None:
self._visit_orderby(statement.orderby_list)

if statement.orderby_list is not None:
self._visit_orderby(statement.orderby_list)
if statement.limit_count is not None:
self._visit_limit(statement.limit_count)

if statement.limit_count is not None:
self._visit_limit(statement.limit_count)
# union
if statement.union_link is not None:
self._visit_union(statement.union_link, statement.union_all)

# Projection operator
select_columns = statement.target_list
Expand Down Expand Up @@ -182,7 +180,8 @@ def _visit_union(self, target, all):

def _visit_projection(self, select_columns):
projection_opr = LogicalProject(select_columns)
projection_opr.append_child(self._plan)
if self._plan is not None:
projection_opr.append_child(self._plan)
self._plan = projection_opr

def _visit_select_predicate(self, predicate: AbstractExpression):
Expand Down
2 changes: 1 addition & 1 deletion evadb/parser/evadb.lark
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ alias_clause: AS? uid "(" uid_list ")" | AS? uid

query_expression: "(" query_specification ")" | "(" query_expression ")"

query_specification: SELECT select_elements from_clause order_by_clause? limit_clause?
query_specification: SELECT select_elements from_clause? order_by_clause? limit_clause?

select_elements: (STAR | select_element ) ("," select_element)*

Expand Down

0 comments on commit 79dd6f3

Please sign in to comment.