러스트에서 PostgreSQL 을 연결하기 위한 모듈? crate?을 찾아봤는데 이 녀석만 나온다. 읽다 보니 그냥 postgres 와 tokio-postgres 가 있는데, tokio 가 붙은 녀석은 asynchronous를 지원한다고 한다. 비동기가 왠지 좋아 보여서 살펴 보았으나 tokio 는 뭔가 더 심오한 느낌이라 일단 synchronous 버전인 postgres 로 일단 해봐야겠다.
간단하게 테스트를 위한 데이터베이스와 테이블을 만들었다.
postgres=# create database portfolio_test;
CREATE DATABASE
postgres=# \c portfolio_test
You are now connected to database "portfolio_test" as user "postgres".
portfolio_test=# CREATE TABLE tb_user (
portfolio_test(# id SERIAL PRIMARY KEY,
portfolio_test(# name VARCHAR(64)
portfolio_test(# );
CREATE TABLE
backend 프로젝트의 Cargo.toml 파일에 postgres 도 추가 해 주자.
...
[dependencies]
rocket = "0.5.0-rc.2"
postgres = "0.19.4"
이번에도 main.rs 에 샘플 코드를 붙여 넣자.
extern crate postgres;
use postgres::{Client, NoTls};
fn test_db() {
let mut client = Client::connect("host=localhost user=postgres password=hello!1234 database=portfolio_test", NoTls)?;
for row in client.query("SELECT id, name FROM user", &[])? {
let id: i32 = row.get(0);
let name: &str = row.get(1);
println!("found user: {} {}", id, name);
}
}
#[get("/")]
fn index() -> &'static str {
test_db();
return "Hello, world!"
}
그리고 cargo run 을 했는데...
에라가 난다
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> backend/src/main.rs:7:120
|
6 | / fn test_db() {
7 | | let mut client = Client::connect("host=localhost user=postgres password=hello!1234 dbname=portfolio_test", NoTls)?;
| | ^ cannot use the `?` operator in a function that returns `()`
무언가 ? 에 신비한 기능이 있나보다.
공식 문서를 살펴보니 Rust 는 리턴값에 결과와 오류를 선택해서 전달할 수 있는 type 인 Result 가 있는데, 오류가 있는 경우 오류를 리턴하고 없는 경우 result 를 취하는 기능인가보다.
뭔가 좀 알흠다운 방법을 찾고 싶지만, 간단하게 이렇게 처치 했다.
extern crate postgres;
use postgres::{Client, NoTls};
use std::option::{Option};
fn test_db() -> Option<postgres::Error> {
let mut client = Client::connect("host=localhost user=postgres password=hello!1234 database=portfolio_test", NoTls).ok()?;
for row in client.query("SELECT id, name FROM user", &[]).ok()? {
ok 를 붙이는 건 rust 컴파일러가 알려주었는데 똑똑한 것 같다.
error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option`
--> backend/src/main.rs:8:120
|
7 | / fn test_db() -> Option<postgres::Error> {
8 | | let mut client = Client::connect("host=localhost user=postgres password=hello!1234 database=portfolio_test", NoTls)?;
| | ^ use `.ok()?` if you want to discard the `Result<Infallible, postgres::Error>` error information
다시 실행 해 보자!
는 에라가 났다.
thread 'rocket-worker-thread' panicked at 'Cannot start a runtime from within a runtime. This happens because a function (like `block_on`) attempted to block the current thread while the thread is being used to drive asynchronous tasks.', /Users/galaxy/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.21.2/src/runtime/scheduler/current_thread.rs:516:26
_-_ rocket 이 기본으로 비동기인가보다 + postgres 가 동기라고 해놓고 내부적으로 비동기를 쓰나보다. 갑자기 피곤해진다. 내일 이어서 하자.