shilpisingh-oracle/SQL-Optimization
0
1"""Utility helpers: safety checks, SQL normalization, result hashing."""2import re3import hashlib4import sqlparse5 6DANGEROUS_PATTERNS = [7 r"\bDROP\b",8 r"\bTRUNCATE\b",9 r"\bDELETE\b\s+FROM\b.*\bWHERE\b.*", # allow DELETE with WHERE10 r"\bALTER\b.*DROP\b",11]12 13 14def is_sql_safe(sql: str) -> bool:15 """Return True if SQL appears safe to run (basic checks).16 17 Blocks DROP, TRUNCATE, ALTER ... DROP and DELETE without WHERE.18 This is a heuristic and not a guarantee.19 """20 up = sql.upper()21 # block plain DELETE without WHERE22 if re.search(r"\bDELETE\b\s+FROM\s+[\w\.]+\s*(;|$)", up):23 return False24 for pat in DANGEROUS_PATTERNS:25 if re.search(pat, up, flags=re.IGNORECASE):26 # allow DELETE with WHERE27 if re.search(r"\bDELETE\b.*\bWHERE\b", up, flags=re.IGNORECASE):28 continue29 return False30 return True31 32 33def normalize_sql(sql: str) -> str:34 """Normalize SQL for comparison/hashing (whitespace, casing, remove comments)."""35 # remove SQL comments36 parsed = sqlparse.format(sql, strip_comments=True)37 # remove extra whitespace and lowercase38 normalized = " ".join(parsed.split())39 return normalized.lower()40 41 42def hash_result(rows) -> str:43 """Create a stable hash for query result rows (list of tuples or pandas DataFrame)."""44 m = hashlib.sha256()45 if hasattr(rows, 'to_csv'):46 s = rows.to_csv(index=False)47 m.update(s.encode('utf-8'))48 else:49 # assume iterable of rows50 for r in rows:51 m.update(repr(r).encode('utf-8'))52 return m.hexdigest()53 