mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-25 00:52:02 +00:00
84 lines
1.9 KiB
Python
84 lines
1.9 KiB
Python
#!/usr/bin/env python3
|
|
import os
|
|
from random import randint, choices
|
|
import sys
|
|
|
|
CURDIR = os.path.dirname(os.path.realpath(__file__))
|
|
sys.path.insert(0, os.path.join(CURDIR, "helpers"))
|
|
|
|
from pure_http_client import ClickHouseClient
|
|
|
|
client = ClickHouseClient()
|
|
|
|
N = 10
|
|
create_query = (
|
|
"CREATE TABLE t_cnf_fuzz("
|
|
+ ", ".join([f"c{i} UInt8" for i in range(N)])
|
|
+ ") ENGINE = Memory"
|
|
)
|
|
|
|
client.query("DROP TABLE IF EXISTS t_cnf_fuzz")
|
|
client.query(create_query)
|
|
|
|
# Insert all possible combinations of bool columns.
|
|
insert_query = "INSERT INTO t_cnf_fuzz VALUES "
|
|
for i in range(2**N):
|
|
values = []
|
|
cur = i
|
|
for _ in range(N):
|
|
values.append(cur % 2)
|
|
cur //= 2
|
|
|
|
insert_query += "(" + ", ".join(map(lambda x: str(x), values)) + ")"
|
|
|
|
client.query(insert_query)
|
|
|
|
# Let's try to covert DNF to CNF,
|
|
# because it's a worst case in a sense.
|
|
|
|
MAX_CLAUSES = 10
|
|
MAX_ATOMS = 5
|
|
|
|
|
|
def generate_dnf():
|
|
clauses = []
|
|
num_clauses = randint(1, MAX_CLAUSES)
|
|
for _ in range(num_clauses):
|
|
num_atoms = randint(1, MAX_ATOMS)
|
|
atom_ids = choices(range(N), k=num_atoms)
|
|
negates = choices([0, 1], k=num_atoms)
|
|
atoms = [
|
|
f"(NOT c{i})" if neg else f"c{i}" for (i, neg) in zip(atom_ids, negates)
|
|
]
|
|
clauses.append("(" + " AND ".join(atoms) + ")")
|
|
|
|
return " OR ".join(clauses)
|
|
|
|
|
|
select_query = (
|
|
"SELECT count() FROM t_cnf_fuzz WHERE {} SETTINGS convert_query_to_cnf = {}"
|
|
)
|
|
|
|
fail_report = """
|
|
Failed query: '{}'.
|
|
Result without optimization: {}.
|
|
Result with optimization: {}.
|
|
"""
|
|
|
|
T = 500
|
|
for _ in range(T):
|
|
condition = generate_dnf()
|
|
|
|
query = select_query.format(condition, 0)
|
|
res = client.query(query).strip()
|
|
|
|
query_cnf = select_query.format(condition, 1)
|
|
res_cnf = client.query(query_cnf).strip()
|
|
|
|
if res != res_cnf:
|
|
print(fail_report.format(query_cnf, res, res_cnf))
|
|
exit(1)
|
|
|
|
client.query("DROP TABLE t_cnf_fuzz")
|
|
print("OK")
|