Skip to content

Commit

Permalink
Merge pull request #563 from mabel-dev/FIX/#561
Browse files Browse the repository at this point in the history
FEATURE/524
  • Loading branch information
joocer authored Oct 1, 2022
2 parents ceddbad + 32ae11d commit 781e15c
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,41 @@
Type: Heuristic
Goal: Reduce rows
"""
from opteryx import operators
from opteryx.managers.expression import NodeType


def unique_id():
import random

return hex(random.getrandbits(16))


def _inner_split(plan, nid, operator):

selection = operator.filter
if selection.token_type != NodeType.AND:
return plan

# get the left and right filters
left_node = operators.SelectionNode(
filter=selection.left, properties=operator.properties
)
right_node = operators.SelectionNode(
filter=selection.right, properties=operator.properties
)
# insert them into the plan and remove the old node
# we're chaining the new operators
uid = unique_id() # avoid collisions
plan.insert_operator_before(f"{nid}-{uid}-right", right_node, nid)
plan.insert_operator_before(f"{nid}-{uid}-left", left_node, f"{nid}-{uid}-right")
plan.remove_operator(nid)

# recurse until we get to a non-AND condition
plan = _inner_split(plan, f"{nid}-{uid}-right", right_node)
plan = _inner_split(plan, f"{nid}-{uid}-left", left_node)

return plan


def split_conjunctive_predicates(plan):
Expand All @@ -33,9 +68,6 @@ def split_conjunctive_predicates(plan):
result, balancing the selectivity (get rid of more records faster) vs cost of
the check (a numeric check is faster than a string check)
"""
from opteryx import operators
from opteryx.managers.expression import NodeType

# find the in-scope nodes
selection_nodes = plan.get_nodes_of_type(operators.SelectionNode)

Expand All @@ -47,19 +79,6 @@ def split_conjunctive_predicates(plan):
for nid in selection_nodes:
# get the node from the node_id
operator = plan.get_operator(nid)
selection = operator.filter
if selection.token_type == NodeType.AND:
# get the left and right filters
left_node = operators.SelectionNode(
filter=selection.left, properties=operator.properties
)
right_node = operators.SelectionNode(
filter=selection.right, properties=operator.properties
)
# insert them into the plan and remove the old node
# we're chaining the new operators
plan.insert_operator_before(f"{nid}-right", right_node, nid)
plan.insert_operator_before(f"{nid}-left", left_node, f"{nid}-right")
plan.remove_operator(nid)
plan = _inner_split(plan, nid, operator)

return plan
1 change: 1 addition & 0 deletions tests/sql_battery/test_battery.py
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,7 @@
("SET enable_optimizer = true;\nSET enable_page_management = true;\nSELECT COUNT(*) FROM $planets WHERE id > 3 AND name ILIKE '%e%'", 1, 1),
("SET enable_optimizer = true;\nSET enable_page_management = false;\nSELECT COUNT(*) FROM $planets WHERE id > 3 AND name ILIKE '%e%'", 1, 1),
("SET enable_optimizer = false;\nSET enable_page_management = false;\nSELECT COUNT(*) FROM $planets WHERE id > 3 AND name ILIKE '%e%'", 1, 1),
("SELECT COUNT(*) FROM $planets WHERE id > 3 AND name ILIKE '%e%' AND id > 1 AND id > 0 AND id > 2 AND name ILIKE '%e%'", 1, 1),

# These are queries which have been found to return the wrong result or not run correctly
# FILTERING ON FUNCTIONS
Expand Down

0 comments on commit 781e15c

Please sign in to comment.