代码之家  ›  专栏  ›  技术社区  ›  kdgregory

PG8000或Postgres客户端服务器协议是否不支持DDL语句中的绑定参数?

  •  0
  • kdgregory  · 技术社区  · 3 年前

    我正在尝试用PG8000创建一个新用户。这段代码有效,但它将密码放在服务器日志中,这是不可取的(我不关心这个用例的SQL注入):

    with pg8000.dbapi.connect(**CONNECTION_INFO) as conn:
        csr = conn.cursor()
        csr.execute("create user example password 'password-123'")
        conn.commit()
    

    然后,我可以通过使用绑定参数的查询来选择有关该用户的信息:

    with pg8000.dbapi.connect(**CONNECTION_INFO) as conn:
        csr = conn.cursor()
        csr.execute("select * from pg_user where usename = %s", ("example",))
        result = csr.fetchall()
    

    但是,如果我尝试使用绑定参数创建用户:

    with pg8000.dbapi.connect(**CONNECTION_INFO) as conn:
        csr = conn.cursor()
        csr.execute("create user example password %s", ("password-123",))
        conn.commit()
    

    请求失败,出现以下客户端错误:

    DatabaseError: {'S': 'ERROR', 'V': 'ERROR', 'C': '42601', 'M': 'syntax error at or near "$1"', 'P': '30', 'F': 'scan.l', 'L': '1145', 'R': 'scanner_yyerror'}
    

    这个服务器端错误:

    2022-08-26 12:30:02.029 UTC [205] LOG:  statement: begin transaction
    2022-08-26 12:30:02.029 UTC [205] ERROR:  syntax error at or near "$1" at character 30
    2022-08-26 12:30:02.029 UTC [205] STATEMENT:  create user example password $1
    

    如果我使用PG8000“本机”接口,也会发生同样的情况。

    如果我切换到psycopg2,我可以执行用参数编写的create命令,但服务器日志表明客户端进行了参数替换,并发送了一条文字SQL语句:

    2022-08-26 12:30:55.317 UTC [206] LOG:  statement: BEGIN
    2022-08-26 12:30:55.317 UTC [206] LOG:  statement: create user example2 password 'password-123'
    2022-08-26 12:30:55.317 UTC [206] LOG:  statement: COMMIT
    
    0 回复  |  直到 3 年前
        1
  •  0
  •   kdgregory    3 年前

    Postgres作为一个整体似乎不支持从准备好的语句中调用DDL。我找不到任何关于这方面的权威文档:不在 PREPARE ,不在 Overview of PostgreSQL Internals ,而不是在 description of the client-server protocol 然而,很容易证明:

    postgres=# prepare ddl_example ( varchar(255) ) as
    postgres-# create user example password '$1';
    ERROR:  syntax error at or near "create"
    LINE 2: create user example password '$1';
            ^
    

    在谷歌搜索的一些页面中,人们评论说DDL没有经过计划器,而计划器是应用绑定变量的地方。这是有道理的,如果有人引用了Postgres的官方文档,请用这个链接回答。

    推荐文章