修 GitHub App 安装在 Postgres 上崩:适配层译 INSERT OR IGNORE,安装后增减仓库同步
This commit is contained in:
1 parent
f07b3ccc7c
commit
9fa80bef89
3 files changed
+101
-8
No files matched your search
+25
-3
@@ -310,9 +310,10 @@ def _load_postgres_driver():
|
||||
# 不重构所有 store 的前提:现有代码到处用 ``?`` 占位符、
|
||||
# ``row["col"]``、``conn.execute().fetchall()``、``commit`` /
|
||||
# ``rollback`` / ``close``、``cursor.lastrowid``、``cursor.rowcount``,
|
||||
# 以及少量 SQLite 方言(``INSERT OR REPLACE``、``PRAGMA
|
||||
# table_info``、``AUTOINCREMENT``、FTS5 虚拟表)。适配层在
|
||||
# 执行前做最小翻译,翻译不了的方言明确报错,绝不静默改语义:
|
||||
# 以及少量 SQLite 方言(``INSERT OR REPLACE``、``INSERT OR
|
||||
# IGNORE``、``PRAGMA table_info``、``AUTOINCREMENT``、FTS5 虚拟表)。
|
||||
# 适配层在执行前做最小翻译,翻译不了的方言明确报错,绝不静默
|
||||
# 改语义:
|
||||
# - ``?`` -> ``%s``:只转换单引号字符串字面量之外的 ``?``
|
||||
# (扫描时跟踪单引号与 ``''`` 转义,字面量里的 ``?`` 不动);
|
||||
# SQL 里已有的 ``%s``(例如调用方自己拼的 ``IN (%s)`` 占位串
|
||||
@@ -322,6 +323,8 @@ def _load_postgres_driver():
|
||||
# _OR_REPLACE_PK;未知表退化为 ``ON CONFLICT DO NOTHING``
|
||||
# (语义弱于 REPLACE,调用点只有 project_members 与
|
||||
# slack_users 两张已知主键表,不会走到退化分支)。
|
||||
# - ``INSERT OR IGNORE`` -> ``ON CONFLICT DO NOTHING``:无冲突
|
||||
# 目标,任何唯一冲突都跳过,不改已有行。
|
||||
# - ``PRAGMA table_info(<表>)`` -> information_schema 查询,
|
||||
# 返回 (cid, name, type, notnull, dflt_value, pk) 六元组,
|
||||
# 与 sqlite 的 PRAGMA table_info 行形状一致,调用方取 row[1]
|
||||
@@ -411,6 +414,7 @@ def _convert_placeholders(sql):
|
||||
_OR_REPLACE_PK = {
|
||||
"project_members": ("project_id", "user_id"),
|
||||
"slack_users": ("slack_id",),
|
||||
"github_app_config": ("id",),
|
||||
}
|
||||
|
||||
_IDENTITY_TABLES = frozenset(
|
||||
@@ -422,6 +426,10 @@ _OR_REPLACE_RE = _re.compile(
|
||||
r"^\s*INSERT\s+OR\s+REPLACE\s+INTO\s+(\w+)\s*\(([^)]+)\)\s*"
|
||||
r"VALUES\s*\((.*)\)\s*$",
|
||||
_re.IGNORECASE | _re.DOTALL)
|
||||
_OR_IGNORE_RE = _re.compile(
|
||||
r"^\s*INSERT\s+OR\s+IGNORE\s+INTO\s+(\w+)\s*\(([^)]+)\)\s*"
|
||||
r"VALUES\s*\((.*)\)\s*$",
|
||||
_re.IGNORECASE | _re.DOTALL)
|
||||
_INSERT_TABLE_RE = _re.compile(
|
||||
r"^\s*INSERT\s+INTO\s+(?:\w+\.)?(\w+)", _re.IGNORECASE)
|
||||
_PRAGMA_INFO_RE = _re.compile(
|
||||
@@ -477,6 +485,20 @@ def _translate_sql(sql):
|
||||
"INSERT INTO %s (%s) VALUES (%s) ON CONFLICT DO NOTHING"
|
||||
% (table, ", ".join(cols), values))
|
||||
return _convert_placeholders(translated), "normal"
|
||||
m = _OR_IGNORE_RE.match(stripped)
|
||||
if m:
|
||||
# INSERT OR IGNORE(SQLite 方言)-> ON CONFLICT DO NOTHING:
|
||||
# 无冲突目标即可,任何唯一冲突都跳过,不改已有行。2026-10-26
|
||||
# 实弹教训:GitHub App 安装事件在生产 Postgres 上因这句未
|
||||
# 翻译直接报语法错,安装记录丢了(delivery 已认领,重试会
|
||||
# 判 duplicate,事件无法靠重发恢复,只能卸载重装)。
|
||||
table = m.group(1)
|
||||
cols = m.group(2)
|
||||
values = m.group(3)
|
||||
translated = (
|
||||
"INSERT INTO %s (%s) VALUES (%s) ON CONFLICT DO NOTHING"
|
||||
% (table, cols, values))
|
||||
return _convert_placeholders(translated), "normal"
|
||||
translated = _AUTOINCREMENT_RE.sub(
|
||||
"BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY", sql)
|
||||
translated = _convert_placeholders(translated)
|
||||
|
||||
Reference in new issue
Block a user