使用 Psycopg2 SQL 模块时,为什么我的查询在引用标识符时仍然有效?

When using the Psycopg2 SQL module, why does my query still work when the identifiers are quoted?

提问人:Florian 提问时间:8/30/2020 最后编辑:LaurelFlorian 更新时间:10/30/2023 访问量:666

问:

由于莫里斯·迈耶(Maurice Meyer)让我知道的语法错误而编辑了问题

我需要保护应用程序免受 SQL 注入,因此使用 Psycopg2sql 模块。这将生成一个工作查询:

conn = get_db()
cur = conn.cursor()
with open(fp, 'r') as f:
    query = sql.SQL("COPY parts ({fields}) FROM STDIN WITH (FORMAT CSV, DELIMITER ';', ENCODING UTF8)").format(
        fields = sql.SQL(',').join(sql.Identifier(col) for col in cols))
    cur.copy_expert(query, f)

但是,我想知道这是否是正确的解决方案。由于生成的查询是:

print(query.as_string(conn))
>>> COPY parts ("asin","name","t_id","supp_pid","acq_price","deposit","ean","m_pid") FROM STDIN WITH (FORMAT CSV, DELIMITER ';', ENCODING UTF8)

但是根据 Postgresql 文档,标识符应该不加引号。 为什么它仍然有效?

蟒蛇 psycopg2 sql 注入

评论


答:

0赞 Cyril Jouve 8/30/2020 #1

你有一个错别字:

sql.SQL("xxx".format(...))

而不是:

sql.SQL("xxx").format(...)
             ^ this (

所以:

query = sql.SQL("COPY parts ({fields}) FROM STDIN WITH (FORMAT CSV, DELIMITER ';', ENCODING UTF8)").format(
        fields = sql.SQL(',').join(sql.Identifier(col) for col in cols))
1赞 Maurice Meyer 8/30/2020 #2

支架未正确闭合。您正在对字符串使用,而不是在 SQL 对象上使用:format

with open(fp, 'r') as f:
    _sql = "COPY parts ({}) FROM STDIN WITH (FORMAT CSV, DELIMITER ';', ENCODING UTF8)"
    query = sql.SQL(_sql).format(
        sql.SQL(',').join(sql.Identifier(col) for col in cols)
    )
    print(query.as_string(conn))
    cur.copy_expert(query, f)

输出:

COPY parts ("firstname","lastname") FROM STDIN WITH (FORMAT CSV, DELIMITER ';', ENCODING UTF8)
Traceback (most recent call last):
  File "pg2.py", line 14, in <module>
    cur.copy_expert(query, f)
psycopg2.errors.UndefinedTable: relation "parts" does not exist

请注意,关于带引号的标识符:

想象一下,你有一个包含空格的列名,那么你需要用引号来引用它们才能使用它们。因此,允许使用引号,相同的行为适用于 postgres 控制台。

>>> cur.execute("""select firstname, "desc ription" from users2 where lastname = 'bar'""")
>>> print(cur.fetchone())
RealDictRow([('firstname', 'fo'), ('desc ription', 'baz')])

评论

0赞 Florian 8/30/2020
感谢!那部分线超出了我的编辑视口,因此我错过了它。但是,返回的查询仍然具有带引号的标识符,根据 Postgresql 文档,这些标识符的格式不正确 - 但它有效。我不明白。