Warning
This post was published 38 days ago. The information described in this article may have changed.
Hello, I have backend like this :
use ntex::{web, web::types::State};
use serde_json::{Map, Value as JsonValue};
use limbo::{Builder, Connection, value::Value, Error as LimboError};
use std::{future::Future, env::set_var};
use bb8::{ManageConnection, Pool};
use log::error;
struct LimboConnectionManager {
db: limbo::Database,
}
impl LimboConnectionManager {
async fn new(path: &str) -> Self {
let db = Builder::new_local(path).build().await.unwrap();
Self { db }
}
}
impl ManageConnection for LimboConnectionManager {
type Connection = Connection;
type Error = LimboError;
fn connect(&self) -> impl Future<Output = Result<Self::Connection, Self::Error>> + Send {
let db = self.db.clone();
async move { db.connect() }
}
fn is_valid(&self, conn: &mut Self::Connection) -> impl Future<Output = Result<(), Self::Error>> + Send {
async move {
conn.execute("SELECT 1", ()).await.map(|_| ())
}
}
fn has_broken(&self, _conn: &mut Self::Connection) -> bool {
false
}
}
async fn row_to_json(row: &limbo::Row, columns: &[&str]) -> serde_json::Value {
let mut map = Map::new();
for (i, &col_name) in columns.iter().enumerate() {
match row.get_value(i) {
Ok(Value::Text(t)) => {
map.insert(col_name.to_string(), JsonValue::String(t));
}
Ok(Value::Integer(i)) => {
map.insert(col_name.to_string(), JsonValue::Number(i.into()));
}
Ok(Value::Null) => {
map.insert(col_name.to_string(), JsonValue::Null);
}
Ok(val) => {
map.insert(col_name.to_string(), JsonValue::String(format!("{:?}", val)));
}
Err(_) => continue,
}
}
JsonValue::Object(map)
}
async fn test(pool: State<Pool<LimboConnectionManager>>) -> impl web::Responder {
let conn = match pool.get().await {
Ok(c) => c,
Err(e) => {
error!("Failed to get DB connection: {}", e);
return web::HttpResponse::InternalServerError().finish();
}
};
if let Err(e) = conn.execute("create table if not exists tes(nama text);", ()).await {
error!("Failed to create table: {}", e);
return web::HttpResponse::InternalServerError().finish();
}
if let Err(e) = conn.execute("insert into tes(nama) values('fuji');", ()).await {
error!("Failed to insert data: {}", e);
return web::HttpResponse::InternalServerError().finish();
}
let mut hasil = match conn.query("SELECT * FROM tes;", ()).await {
Ok(q) => q,
Err(e) => {
error!("Query failed: {}", e);
return web::HttpResponse::InternalServerError().finish();
}
};
let mut rows_json = Vec::new();
while let Some(row_result) = hasil.next().await.transpose() {
match row_result {
Ok(row) => {
let json = row_to_json(&row, &["nama"]).await;
rows_json.push(json);
}
Err(e) => {
error!("Error reading row: {}", e);
return web::HttpResponse::InternalServerError().finish();
}
}
}
match serde_json::to_string(&rows_json) {
Ok(json_str) => web::HttpResponse::Ok()
.content_type("application/json")
.body(json_str),
Err(e) => {
error!("JSON serialization error: {}", e);
web::HttpResponse::InternalServerError().finish()
}
}
}
#[ntex::main]
async fn main() -> std::io::Result<()> {
unsafe {
set_var("RUST_LOG", "info");
set_var("RUST_BACKTRACE", "1");
}
env_logger::init();
let manager = LimboConnectionManager::new("database.db").await;
let pool = Pool::builder()
.max_size(50)
.build(manager)
.await
.unwrap();
web::HttpServer::new(move || {
let logger = web::middleware::Logger::default();
web::App::new()
.wrap(logger)
.state(pool.clone())
.route("/", web::get().to(test))
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
I place table creation and data insertion queries before select *
to test it. It works
{"nama":"fuji"}
When I revisit the endpoint, it successfully add and fetch new data
[{"nama":"fuji"},{"nama":"fuji"}]
But if I stop the app, comment the table creattion and data insertion queries, and rerun the app. it doesn't work saying there is no table tes
[2025-05-22T06:38:35Z ERROR svr] Query failed: SQL execution failure: `Parse error: Table tes not found`
The table and data are not saved to database.db file because when I stop and rerun the app, they are lost. It seems that it is saved in memory only, but I didn't use ":memory:"
when opening the database, but I use "database.db"
Does anyone know how to solve this?
1 post - 1 participant
🏷️ rust_feed