37 lines
1.8 KiB
Python
37 lines
1.8 KiB
Python
# 2026-03-21 — pg-search: полнотекстовый поиск по title через ILIKE + LIMIT/OFFSET.
|
|
# Тестирует: пагинацию, спецсимволы в input (XSS, SQL injection attempt → безопасно через параметры).
|
|
import os, psycopg2, psycopg2.extras
|
|
|
|
def search(event):
|
|
# «query» — основной параметр (user-friendly), «q» — алиас для совместимости.
|
|
query = str(event.get("query") or event.get("q") or "")[:200]
|
|
# int() может упасть если юзер прислал строку — защищаем try/except.
|
|
try:
|
|
limit = max(1, min(int(event.get("limit", 20)), 100))
|
|
except (TypeError, ValueError):
|
|
limit = 20
|
|
try:
|
|
offset = max(0, int(event.get("offset", 0)))
|
|
except (TypeError, ValueError):
|
|
offset = 0
|
|
|
|
conn = psycopg2.connect(
|
|
host=os.environ["PGHOST"], port=int(os.environ.get("PGPORT", 5432)),
|
|
dbname=os.environ["PGDATABASE"], user=os.environ["PGUSER"],
|
|
password=os.environ["PGPASSWORD"], sslmode=os.environ.get("PGSSLMODE", "require"),
|
|
)
|
|
try:
|
|
with conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as cur:
|
|
pattern = f"%{query}%" if query else "%"
|
|
cur.execute(
|
|
"SELECT id, title, created_at::text FROM terraform_demo_table "
|
|
"WHERE title ILIKE %s ORDER BY id DESC LIMIT %s OFFSET %s",
|
|
(pattern, limit, offset),
|
|
)
|
|
rows = [dict(r) for r in cur.fetchall()]
|
|
cur.execute("SELECT COUNT(*) FROM terraform_demo_table WHERE title ILIKE %s", (pattern,))
|
|
total = cur.fetchone()["count"]
|
|
return {"rows": rows, "count": len(rows), "total": total, "q": query, "limit": limit, "offset": offset}
|
|
finally:
|
|
conn.close()
|