diff --git a/scratch/audit_postgres.py b/scratch/audit_postgres.py new file mode 100644 index 00000000..f780d9b8 --- /dev/null +++ b/scratch/audit_postgres.py @@ -0,0 +1,59 @@ +import os +import re + +# Directories to scan +DIRS = ['./app', './Modules', './database'] + +# Patterns to search for +# 1. MySQL specific functions +PATTERNS = { + 'MONTHNAME': r'MONTHNAME\(', + 'DATE_FUNCTION': r'DATE\((?!\s*[\'"])', # Avoid matching strings like DATE('2023-01-01') + 'YEAR_FUNCTION': r'YEAR\(', + 'MONTH_FUNCTION': r'MONTH\(', + 'DAY_FUNCTION': r'DAY\(', + 'IFNULL': r'IFNULL\(', +} + +# 2. Unquoted camelCase identifiers in raw SQL +# This is tricky, but we can look for selectRaw, DB::raw, sum(DB::raw), etc. +RAW_SQL_PATTERN = r'(?:selectRaw|DB::raw|sum\(DB::raw)\(([\'"])(.*?)\1\)' + +def is_mixed_case(s): + return any(c.islower() for c in s) and any(c.isupper() for c in s) + +def audit(): + results = [] + for root_dir in DIRS: + for root, dirs, files in os.walk(root_dir): + for file in files: + if file.endswith('.php'): + path = os.path.join(root, file) + with open(path, 'r', encoding='utf-8', errors='ignore') as f: + lines = f.readlines() + for i, line in enumerate(lines): + # Check for function patterns + for name, pattern in PATTERNS.items(): + if re.search(pattern, line): + results.append(f"{path}:{i+1} - Found {name}: {line.strip()}") + + # Check for unquoted mixed case in raw SQL + matches = re.finditer(RAW_SQL_PATTERN, line) + for match in matches: + sql = match.group(2) + # Simple check for mixed case words not in quotes + words = re.findall(r'\b\w+\b', sql) + for word in words: + if is_mixed_case(word): + # Check if it's already double-quoted + if f'"{word}"' not in sql: + results.append(f"{path}:{i+1} - Unquoted mixed-case '{word}' in SQL: {line.strip()}") + + return results + +if __name__ == "__main__": + findings = audit() + if findings: + print("\n".join(findings)) + else: + print("No PostgreSQL incompatibilities found.")