我是Rust的新手,我想和postgres的箱子一起玩。我可以通过对表名进行硬编码来创建表,但是当试图从变量中传递表名时,总是会出现代码崩溃的情况。
rustc --version 1.36.0
cargo --version 1.36.0
postgres = "0.15"
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");
thread 'main' panicked at 'Table message creation failed', src/libcore/option.rs:1036:5
stack backtrace:
0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
at src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:39
1: std::sys_common::backtrace::_print
at src/libstd/sys_common/backtrace.rs:71
2: std::panicking::default_hook::{{closure}}
at src/libstd/sys_common/backtrace.rs:59
at src/libstd/panicking.rs:197
3: std::panicking::default_hook
at src/libstd/panicking.rs:211
4: std::panicking::rust_panic_with_hook
at src/libstd/panicking.rs:474
5: std::panicking::continue_panic_fmt
at src/libstd/panicking.rs:381
6: rust_begin_unwind
at src/libstd/panicking.rs:308
7: core::panicking::panic_fmt
at src/libcore/panicking.rs:85
8: core::option::expect_failed
at src/libcore/option.rs:1036
9: core::option::Option<T>::expect
at /rustc/a53f9df32fbb0b5f4382caaad8f1a46f36ea887c/src/libcore/option.rs:314
10: rustdb::main
at ./main.rs:27
11: std::rt::lang_start::{{closure}}
at /rustc/a53f9df32fbb0b5f4382caaad8f1a46f36ea887c/src/libstd/rt.rs:64
12: std::panicking::try::do_call
at src/libstd/rt.rs:49
at src/libstd/panicking.rs:293
13: __rust_maybe_catch_panic
at src/libpanic_unwind/lib.rs:85
14: std::rt::lang_start_internal
at src/libstd/panicking.rs:272
at src/libstd/panic.rs:394
at src/libstd/rt.rs:48
15: std::rt::lang_start
at /rustc/a53f9df32fbb0b5f4382caaad8f1a46f36ea887c/src/libstd/rt.rs:64
16: main
17: __libc_start_main
18: _start
答案 0 :(得分:1)
您不能使用占位符(例如$1
)将表名替换为查询。
占位符的功能之一是允许查询准备一次,然后多次执行。这样可以节省每次使用查询时计划查询的开销,这可能会很大。但是,如果数据库甚至都不知道要查询哪个表,就不可能计划查询。
如果需要在运行时动态插入表名,则需要在rust中进行,然后再将SQL传递给数据库:
let sql = format!("CREATE TABLE IF NOT EXISTS {} (
id SERIAL PRIMARY KEY,
title VARCHAR NOT NULL,
body VARCHAR,
)", tname);
如果表名是从用户输入传递过来的,请不要忘记事先验证表名以防SQL注入。
还请注意,出现恐慌是由于使用了.ok().expect(....)
。
ok()
将获得执行SQL的结果,并将其转换为Option
。如果结果是错误,它将被丢弃,因此您永远不会看到错误消息,它可能会帮助您诊断问题。 Result
直接实现expect
,其优点是它不会丢弃错误,而是将其显示为Panic的一部分。因此,您最好使用:
conn.execute(sql, &[] as &[String]).expect("Failed creating table");
但是,如果现实情况中SQL语句将失败,则最好检查结果并更优雅地处理它,而不是使程序崩溃。