61 lines
1.6 KiB
Python
Executable File
61 lines
1.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""One-line SQL guard for the pyspark-sql-guardrails skill.
|
|
|
|
Usage:
|
|
# Pipe SQL via stdin (preferred for multi-line SQL)
|
|
echo "SELECT ..." | python3 validate_sql.py
|
|
cat query.sql | python3 validate_sql.py
|
|
|
|
# Or pass SQL as the first argument (single-line, quoting-friendly)
|
|
python3 validate_sql.py "SELECT 1"
|
|
|
|
Exit code:
|
|
0 -> PASS (SQL is allowed)
|
|
1 -> FAIL (SQL violates the allowlist; reason printed to stdout)
|
|
|
|
This script is the ONLY sanctioned way to validate a generated SQL
|
|
string before showing it to the user. It is intentionally short so it
|
|
can be invoked in a single Bash call from the assistant.
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
|
|
# Allow running from anywhere; resolve bundled sql_guard.py.
|
|
# The skill layout is:
|
|
# .claude/skills/pyspark-sql-guardrails/
|
|
# ├── SKILL.md
|
|
# └── scripts/
|
|
# ├── sql_guard.py (this script's sibling)
|
|
# ├── validate_sql.py
|
|
# └── test_sql_guard.py
|
|
SCRIPTS_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
sys.path.insert(0, SCRIPTS_DIR)
|
|
|
|
from sql_guard import assert_select_or_insert # noqa: E402
|
|
|
|
|
|
def read_sql() -> str:
|
|
if len(sys.argv) > 1:
|
|
return sys.argv[1]
|
|
if not sys.stdin.isatty():
|
|
return sys.stdin.read()
|
|
print(__doc__, file=sys.stderr)
|
|
sys.exit(2)
|
|
|
|
|
|
def main() -> int:
|
|
sql = read_sql()
|
|
try:
|
|
body = assert_select_or_insert(sql)
|
|
except ValueError as e:
|
|
print(f"FAIL - {e}")
|
|
return 1
|
|
first = body.split(None, 1)[0].lower()
|
|
print(f"PASS - first keyword: {first}, body length: {len(body)}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|