37 lines
1.7 KiB
Python
37 lines
1.7 KiB
Python
# 2026-03-21 — pg-upsert: INSERT ... ON CONFLICT (title) DO UPDATE.
|
|
# Тестирует: идемпотентность вставки — один и тот же title можно вызывать 100 раз подряд.
|
|
# Требует уникального индекса на title — создаётся при первом вызове (CREATE UNIQUE INDEX IF NOT EXISTS).
|
|
import os, psycopg2
|
|
|
|
def upsert(event):
|
|
title = str(event.get("title", "upsert-default"))[:255]
|
|
payload = str(event.get("payload", ""))[:500]
|
|
|
|
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() as cur:
|
|
# Создаём уникальный индекс если нет — для поддержки ON CONFLICT
|
|
cur.execute(
|
|
"CREATE UNIQUE INDEX IF NOT EXISTS terraform_demo_table_title_uniq "
|
|
"ON terraform_demo_table (title)"
|
|
)
|
|
cur.execute(
|
|
"INSERT INTO terraform_demo_table (title) VALUES (%s) "
|
|
"ON CONFLICT (title) DO UPDATE SET created_at = now() "
|
|
"RETURNING id, title, created_at::text, xmax",
|
|
(title,),
|
|
)
|
|
row = cur.fetchone()
|
|
was_insert = row[3] == 0 # xmax=0 означает INSERT, иначе UPDATE
|
|
conn.commit()
|
|
return {
|
|
"id": row[0], "title": row[1], "created_at": row[2],
|
|
"action": "inserted" if was_insert else "updated",
|
|
}
|
|
finally:
|
|
conn.close()
|