2014-12-18 2 views
4

가 지금 내가 이렇게 내 응용 프로그램에서 DB 작업의 무리를 DB를 연결을 열고 수행 할 rusqlite sqlite bindings를 사용하는 코드가 : 준비된 명령문은 지역 변수에 살고 있기 때문에나중에 SQLite prepared statements를 저장하는 방법은 무엇입니까?

extern crate rusqlite; 

use rusqlite::SqliteConnection; 

struct MyAppState { 
    db: SqliteConnection, 
    // ... pretend there's other fields here ... 
} 

impl MyAppState { 
    fn new() -> MyAppState { 
     let db = SqliteConnection::open(":memory:").unwrap(); 
     MyAppState { 
      db: db 
     } 
    } 

    fn query_some_info(&mut self, arg: i64) -> i64 { 
     let mut stmt = self.db.prepare("SELECT ? + 1").unwrap(); 
     let mut result_iter = stmt.query(&[&arg]).unwrap(); 
     let result = result_iter.next().unwrap().unwrap().get(0); 

     result 
    } 
} 

fn main() { 
    let mut app = MyAppState::new(); 
    for i in range(0, 100) { 
     let result = app.query_some_info(i); 
     println!("{}", result); 
    } 
} 

을,이 그리워 보인다 함수가 호출되고 지역 변수가 생길 때마다 다시 준비해야하기 때문에 어느 정도까지 준비된 문장의 요점. 이상적으로, 나는 모든 내 문장을 최대 한 번 준비하고 db 연결 기간 동안 MyAppState 구조체에 숨 깁니다.

그러나, SqliteStatement type is parameterized over the lifetime of the db connection 때문에 연결을 차용하고 확장하여 구조체가 사는 곳과 값으로 구조체를 반환하거나에 &mut self 메소드를 호출처럼 나는 query_some_info하지 않는 (더 이상 구조체와 아무것도 할 수 없습니다 여기에 &mut self을 가져갈 필요가 있지만, 실제 프로그램의 일부 코드는 모두가 RefCell에 머물러 있지 않는 이상 않습니다. 최악은 아니지만 여전히 그렇습니다).

보통 차용 증서가 저를 배반 할 때, 내 의무는 스택 규율을 포기하고 모든 것이 작동 할 때까지 여기저기서 Rc<RefCell< >>을 넣는 것입니다. 그러나이 경우에는 어떤 유형의 수명도 있습니다. 차용 증인을 달랠 수있는 방법으로 단어를 쓰는 법을 모릅니다.

이상하게도 DB를 열 때 문을 준비하는 코드를 작성하거나 처음 사용했을 때 단 한 번만 준비한 다음 db 연결 기간 동안 다시 prepare을 호출하지 마십시오. 대부분 rusqlite 바인딩의 안전성을 유지하면서 sqlite3 C API에 대한 코드를 작성하거나 추상화를 파기합니다. 내가 어떻게 할?

답변

4

사실 형제 자매는 녹이 서툴기 만합니다. 좋은 이유가 있습니다. 소유권 시스템에 의해 쉽게 모델링되지 않습니다.

이 특별한 경우

, 나는 구조를 분할 할 수 권합니다 : 당신은 예를 들어 db의 수명에 매개 변수화 전용 캐시도 에 준비된 문을 유지할 수 있습니다; db은 프로그램 상단에서 인스턴스화되어야하며 의존성 삽입을 고려하여 전달되므로 의존하는 캐시가 프로그램 주 기능보다 오래 지속될 수 있습니다.

이것은 분명히 db이 계속 빌릴 것임을 의미합니다.

+0

이 아이디어에 대한 예를 제공해 주시겠습니까? –

관련 문제