Skip to content

Commit c232429

Browse files
authored
Merge pull request #89 from roc-lang/improve-sqlite-again
Add improved Sqlite again
2 parents a2308d9 + dd55259 commit c232429

File tree

16 files changed

+1049
-817
lines changed

16 files changed

+1049
-817
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ examples/file
3636
examples/dir
3737
examples/env
3838
examples/command
39+
examples/sqlite
3940
examples/sqlite3
4041
examples/hello-web
4142
examples/file-upload-form
@@ -50,3 +51,6 @@ crates/roc_std
5051

5152
# build script artifacts
5253
build
54+
55+
# sqlite database temp file
56+
*.db-shm

Cargo.lock

Lines changed: 47 additions & 39 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/roc_host/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ roc_io_error = { git = "https://github.com/roc-lang/basic-cli.git" }
2020
roc_stdio = { git = "https://github.com/roc-lang/basic-cli.git" }
2121
roc_file = { git = "https://github.com/roc-lang/basic-cli.git" }
2222
roc_http = { git = "https://github.com/roc-lang/basic-cli.git" }
23+
roc_sqlite = { git = "https://github.com/roc-lang/basic-cli.git" }
2324
libc = "0.2"
2425
hyper = { version = "0.14", features = [
2526
"http1",
@@ -39,4 +40,3 @@ tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] }
3940
futures = "0.3"
4041
backtrace = "0.3.68"
4142
bytes = "1.0"
42-
sqlite = { version = "0.33.0", features = ["bundled"] }

crates/roc_host/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
mod http_server;
22
mod roc;
3-
mod roc_sql;
43

54
#[no_mangle]
65
pub extern "C" fn rust_main() -> i32 {

crates/roc_host/src/roc.rs

Lines changed: 47 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use crate::roc_sql;
21
use roc_io_error::IOErr;
32
use roc_std::{RocBox, RocList, RocResult, RocStr};
43
use std::cell::RefCell;
@@ -324,83 +323,6 @@ pub extern "C" fn roc_fx_dir_list(
324323
roc_file::dir_list(roc_path)
325324
}
326325

327-
#[no_mangle]
328-
pub extern "C" fn roc_fx_sqlite_execute(
329-
db_path: &roc_std::RocStr,
330-
query: &roc_std::RocStr,
331-
bindings: &RocList<roc_sql::SQLiteBindings>,
332-
) -> RocResult<RocList<RocList<roc_sql::SQLiteValue>>, roc_sql::SQLiteError> {
333-
// Get the connection
334-
let connection = {
335-
match roc_sql::get_connection(db_path.as_str()) {
336-
Ok(c) => c,
337-
Err(err) => {
338-
return RocResult::err(roc_sql::SQLiteError {
339-
code: err.code.unwrap_or_default() as i64,
340-
message: RocStr::from(err.message.unwrap_or_default().as_str()),
341-
});
342-
}
343-
}
344-
};
345-
346-
// Prepare the query
347-
let mut statement = {
348-
match connection.prepare(query.as_str()) {
349-
Ok(c) => c,
350-
Err(err) => {
351-
return RocResult::err(roc_sql::SQLiteError {
352-
code: err.code.unwrap_or_default() as i64,
353-
message: RocStr::from(err.message.unwrap_or_default().as_str()),
354-
});
355-
}
356-
}
357-
};
358-
359-
// Add bindings for the query
360-
for binding in bindings {
361-
match statement.bind(binding) {
362-
Ok(()) => {}
363-
Err(err) => {
364-
return RocResult::err(roc_sql::SQLiteError {
365-
code: err.code.unwrap_or_default() as i64,
366-
message: RocStr::from(err.message.unwrap_or_default().as_str()),
367-
});
368-
}
369-
}
370-
}
371-
372-
let mut cursor = statement.iter();
373-
let column_count = cursor.column_count();
374-
375-
// Save space for 1000 rows without allocating
376-
let mut roc_values: RocList<RocList<roc_sql::SQLiteValue>> = RocList::with_capacity(1000);
377-
378-
while let Ok(Some(row_values)) = cursor.try_next() {
379-
let mut row = RocList::with_capacity(column_count);
380-
381-
// For each column in the row
382-
for value in row_values {
383-
row.push(roc_sql_from_sqlite_value(value));
384-
}
385-
386-
roc_values.push(row);
387-
}
388-
389-
RocResult::ok(roc_values)
390-
}
391-
392-
fn roc_sql_from_sqlite_value(value: sqlite::Value) -> roc_sql::SQLiteValue {
393-
match value {
394-
sqlite::Value::Binary(bytes) => {
395-
roc_sql::SQLiteValue::bytes(RocList::from_slice(&bytes[..]))
396-
}
397-
sqlite::Value::Float(f64) => roc_sql::SQLiteValue::real(f64),
398-
sqlite::Value::Integer(i64) => roc_sql::SQLiteValue::integer(i64),
399-
sqlite::Value::String(str) => roc_sql::SQLiteValue::string(RocStr::from(str.as_str())),
400-
sqlite::Value::Null => roc_sql::SQLiteValue::null(),
401-
}
402-
}
403-
404326
#[no_mangle]
405327
pub extern "C" fn roc_fx_temp_dir() -> RocList<u8> {
406328
roc_env::temp_dir()
@@ -418,6 +340,12 @@ impl Model {
418340
let rc_ptr = data_ptr.offset(-1);
419341
let max_refcount = 0;
420342
*rc_ptr = max_refcount;
343+
344+
// Ensure all sqlite stmts that escapes init has an zero (constant) refcount.
345+
// This ensures it is safe to share between threads and is never freed.
346+
let heap = roc_sqlite::heap();
347+
heap.promote_all_to_constant();
348+
421349
Self {
422350
model: std::mem::transmute::<*mut usize, roc_std::RocBox<()>>(data_ptr),
423351
}
@@ -523,3 +451,44 @@ pub extern "C" fn roc_fx_getLocales() -> RocList<RocStr> {
523451
pub extern "C" fn roc_fx_currentArchOS() -> roc_env::ReturnArchOS {
524452
roc_env::current_arch_os()
525453
}
454+
455+
#[no_mangle]
456+
pub extern "C" fn roc_fx_sqlite_bind(
457+
stmt: RocBox<()>,
458+
bindings: &RocList<roc_sqlite::SqliteBindings>,
459+
) -> RocResult<(), roc_sqlite::SqliteError> {
460+
roc_sqlite::bind(stmt, bindings)
461+
}
462+
463+
#[no_mangle]
464+
pub extern "C" fn roc_fx_sqlite_prepare(
465+
db_path: &roc_std::RocStr,
466+
query: &roc_std::RocStr,
467+
) -> roc_std::RocResult<RocBox<()>, roc_sqlite::SqliteError> {
468+
roc_sqlite::prepare(db_path, query)
469+
}
470+
471+
#[no_mangle]
472+
pub extern "C" fn roc_fx_sqlite_columns(stmt: RocBox<()>) -> RocList<RocStr> {
473+
roc_sqlite::columns(stmt)
474+
}
475+
476+
#[no_mangle]
477+
pub extern "C" fn roc_fx_sqlite_column_value(
478+
stmt: RocBox<()>,
479+
i: u64,
480+
) -> RocResult<roc_sqlite::SqliteValue, roc_sqlite::SqliteError> {
481+
roc_sqlite::column_value(stmt, i)
482+
}
483+
484+
#[no_mangle]
485+
pub extern "C" fn roc_fx_sqlite_step(
486+
stmt: RocBox<()>,
487+
) -> RocResult<roc_sqlite::SqliteState, roc_sqlite::SqliteError> {
488+
roc_sqlite::step(stmt)
489+
}
490+
491+
#[no_mangle]
492+
pub extern "C" fn roc_fx_sqlite_reset(stmt: RocBox<()>) -> RocResult<(), roc_sqlite::SqliteError> {
493+
roc_sqlite::reset(stmt)
494+
}

0 commit comments

Comments
 (0)