如何使用 postgres crate 将表名作为变量传递给execute()?

Seb*_*and 3 postgresql rust

我是 Rust 新手,我正在尝试使用 postgres 板条箱。我能够通过对表名称进行硬编码来创建表,但在尝试从变量传递表名称时,代码总是会出现恐慌。

rustc --version 1.36.0
cargo --version 1.36.0
postgres = "0.15"
Run Code Online (Sandbox Code Playgroud)
fn main() {
  let conn = Connection::connect("postgresql://postgres:postgres@localhost/db1",
                                    TlsMode::None).unwrap();

  let tname = "message";
  conn.execute("CREATE TABLE IF NOT EXISTS $1 (
                    id              SERIAL PRIMARY KEY,
                    title           VARCHAR NOT NULL,
                    body            VARCHAR,
                )", &[&tname]).ok().expect("Table message creation failed");
Run Code Online (Sandbox Code Playgroud)
fn main() {
  let conn = Connection::connect("postgresql://postgres:postgres@localhost/db1",
                                    TlsMode::None).unwrap();

  let tname = "message";
  conn.execute("CREATE TABLE IF NOT EXISTS $1 (
                    id              SERIAL PRIMARY KEY,
                    title           VARCHAR NOT NULL,
                    body            VARCHAR,
                )", &[&tname]).ok().expect("Table message creation failed");
Run Code Online (Sandbox Code Playgroud)

har*_*mic 6

您不能使用占位符(例如$1)将表名替换为查询。

占位符的功能之一是允许查询准备一次,然后执行多次。这节省了每次要使用查询时规划查询的开销,这可能是巨大的。但是,如果数据库甚至不知道正在查询哪个表,则不可能计划查询。

如果需要在运行时动态插入表名,则需要在将 SQL 传递到数据库之前在 Rust 中执行此操作:

let sql = format!("CREATE TABLE IF NOT EXISTS {} (
                    id              SERIAL PRIMARY KEY,
                    title           VARCHAR NOT NULL,
                    body            VARCHAR,
                )", tname);
Run Code Online (Sandbox Code Playgroud)

如果表名是从用户输入传入的,请不要忘记通过事先验证来防止 SQL 注入。

另请注意,恐慌是由于使用.ok().expect(....).

ok()将获取执行 SQL 的结果并将其转换为Option. 如果结果是错误,它将被丢弃,因此您永远看不到可能有助于您诊断问题的错误消息。Result直接实现expect,其优点是不会丢弃错误,而是将其显示为 Panic 的一部分。所以,你会更好:

conn.execute(sql, &[] as &[String]).expect("Failed creating table");
Run Code Online (Sandbox Code Playgroud)

但是,如果 SQL 语句很可能会失败,那么您最好检查结果并更优雅地处理它,而不是使程序崩溃。