diff --git a/opteryx/__version__.py b/opteryx/__version__.py index ad5fe7b2..e4bd6646 100644 --- a/opteryx/__version__.py +++ b/opteryx/__version__.py @@ -27,9 +27,9 @@ class VersionStatus(Enum): _major = 0 -_minor = 17 -_revision = 2 -_status = VersionStatus.ALPHA +_minor = 18 +_revision = 0 +_status = VersionStatus.RELEASE __author__ = "@joocer" __version__ = f"{_major}.{_minor}.{_revision}" + ( diff --git a/opteryx/operators/exit_node.py b/opteryx/operators/exit_node.py index 219b2b61..2de2271d 100644 --- a/opteryx/operators/exit_node.py +++ b/opteryx/operators/exit_node.py @@ -68,6 +68,7 @@ def name(self): # pragma: no cover def execute(self) -> Generator: start = time.monotonic_ns() morsels = self._producers[0] # type:ignore + at_least_one = False final_columns = [] final_names = [] @@ -110,4 +111,10 @@ def execute(self) -> Generator: self.statistics.time_exiting += time.monotonic_ns() - start yield morsel + at_least_one = True start = time.monotonic_ns() + + if not at_least_one: + from orso import DataFrame + + yield DataFrame(schema=final_names).arrow() diff --git a/tests/fuzzing/test_sql_fuzzer_join.py b/tests/fuzzing/test_sql_fuzzer_join.py index d579de95..1418ccbe 100644 --- a/tests/fuzzing/test_sql_fuzzer_join.py +++ b/tests/fuzzing/test_sql_fuzzer_join.py @@ -31,7 +31,7 @@ def random_value(t): return random_int() / 1000 -def generate_condition(columns): +def generate_condition(table, columns): where_column = columns[random.choice(range(len(columns)))] while where_column.type in (OrsoTypes.ARRAY, OrsoTypes.STRUCT): where_column = columns[random.choice(range(len(columns)))] @@ -48,10 +48,10 @@ def generate_condition(columns): else: where_operator = random.choice(["=", "!=", "<", "<=", ">", ">="]) where_value = f"{str(random_value(where_column.type))}" - return f"{where_column.name} {where_operator} {where_value}" + return f"{table}.{where_column.name} {where_operator} {where_value}" def generate_random_sql_join(columns1, table1, columns2, table2) -> str: - join_type = random.choice(["INNER JOIN", "LEFT JOIN", "RIGHT JOIN", "FULL OUTER JOIN"]) + join_type = random.choice(["JOIN", "INNER JOIN", "LEFT JOIN", "RIGHT JOIN", "FULL OUTER JOIN"]) last_value = -1 this_value = random.random() @@ -75,7 +75,29 @@ def generate_random_sql_join(columns1, table1, columns2, table2) -> str: selected_columns = ["*"] select_clause = "SELECT " + ", ".join(selected_columns) - query = f"{select_clause} FROM {table1} {join_type} {table2} ON {join_condition}" + where_clause = "--" + # Generate a WHERE clause with 70% chance + if random.random() < 0.3: + if where_clause == "--": + where_clause = " WHERE " + where_clause += generate_condition(table1, columns1) + # add an abitrary number of additional conditions + while random.random() < 0.1: + linking_condition = random.choice(["AND", "OR", "AND NOT"]) + where_clause += f" {linking_condition} {generate_condition(table1, columns1)}" + + if random.random() < 0.3: + if where_clause == "--": + where_clause = " WHERE " + else: + where_clause += f' {random.choice(["AND", "OR", "AND NOT"])} ' + where_clause += generate_condition(table2, columns2) + # add an abitrary number of additional conditions + while random.random() < 0.1: + linking_condition = random.choice(["AND", "OR", "AND NOT"]) + where_clause += f" {linking_condition} {generate_condition(table2, columns2)}" + + query = f"{select_clause} FROM {table1} {join_type} {table2} ON {join_condition} {where_clause}" return query diff --git a/tests/fuzzing/test_sql_fuzzer_single_table_select.py b/tests/fuzzing/test_sql_fuzzer_single_table_select.py index a26f7760..ec586a0b 100644 --- a/tests/fuzzing/test_sql_fuzzer_single_table_select.py +++ b/tests/fuzzing/test_sql_fuzzer_single_table_select.py @@ -89,12 +89,11 @@ def generate_random_sql_select(columns, table): # Generate a WHERE clause with 70% chance if random.random() < 0.7: where_clause = generate_condition(columns) - select_clause = f"{select_clause} WHERE {where_clause}" # add an abitrary number of additional conditions while random.random() < 0.3: linking_condition = random.choice(["AND", "OR", "AND NOT"]) - where_clause = generate_condition(columns) - select_clause = f"{select_clause} {linking_condition} {where_clause}" + where_clause += f" {linking_condition} {generate_condition(columns)} " + select_clause = f"{select_clause} WHERE {where_clause}" # Add GROUP BY clause with 40% chance if agg_column and random.random() < 0.4: column_list = [c.name for c in column_list]