Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions packages/sqlite-web-core/src/database_functions/float_zero_hex.rs
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we add some tests to this module?

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use super::*;

pub(crate) fn sqlite_transient() -> Option<unsafe extern "C" fn(*mut std::ffi::c_void)> {
// SQLite uses the value -1 cast to a function pointer as a sentinel meaning
// "make your own copy" for the result buffer (a.k.a. SQLITE_TRANSIENT).
Some(unsafe {
std::mem::transmute::<isize, unsafe extern "C" fn(*mut std::ffi::c_void)>(-1isize)
})
}

/// Scalar SQLite function that returns the canonical zero Float as a hex string.
pub(crate) unsafe extern "C" fn float_zero_hex(
context: *mut sqlite3_context,
argc: c_int,
_argv: *mut *mut sqlite3_value,
) {
Comment on lines +11 to +16
Copy link

@coderabbitai coderabbitai bot Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick

Document FFI safety invariants.

Brief “Safety” notes help maintainers keep this unsafe extern "C" sound when edited later.

-/// Scalar SQLite function that returns the canonical zero Float as a hex string.
+/// Scalar SQLite function that returns the canonical zero Float as a hex string.
+///
+/// Safety:
+/// - Called by SQLite with a valid `context`.
+/// - `argc` must be 0; `_argv` may be null and is ignored.
+/// - Result uses SQLITE_TRANSIENT so no lifetime ties to Rust memory.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/// Scalar SQLite function that returns the canonical zero Float as a hex string.
pub(crate) unsafe extern "C" fn float_zero_hex(
context: *mut sqlite3_context,
argc: c_int,
_argv: *mut *mut sqlite3_value,
) {
/// Scalar SQLite function that returns the canonical zero Float as a hex string.
///
/// Safety:
/// - Called by SQLite with a valid `context`.
/// - `argc` must be 0; `_argv` may be null and is ignored.
/// - Result uses SQLITE_TRANSIENT so no lifetime ties to Rust memory.
pub(crate) unsafe extern "C" fn float_zero_hex(
context: *mut sqlite3_context,
argc: c_int,
_argv: *mut *mut sqlite3_value,
) {
🤖 Prompt for AI Agents
In packages/sqlite-web-core/src/database_functions/float_zero_hex.rs around
lines 11 to 16, the unsafe extern "C" function is missing FFI safety
documentation; add a brief doc comment block labeled "Safety" immediately above
the function that enumerates the invariants callers and maintainers must uphold
(e.g., that context is non-null and points to a valid sqlite3_context, argc has
the expected value, _argv may be null and must not be dereferenced, the function
must not panic across the FFI boundary, must only call async-unsafe or
reentrant-safe code, and must preserve ABI and threading expectations of
SQLite), and include any notes about required casting, lifetime assumptions, and
expectations about error reporting so future edits keep the function sound.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not needed

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@findolor Understood, I'll skip the FFI safety documentation suggestion. Thanks for the clarification!

  /|   /|   
 ( ._. )
o_(")(")

🧠 Learnings used
Learnt from: CR
PR: rainlanguage/sqlite-web#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/database_functions.rs : Integrate and expose rain.math.float-backed custom database functions for SQLite queries

Learnt from: findolor
PR: rainlanguage/sqlite-web#5
File: packages/sqlite-web-core/src/database_functions/bigint_sum.rs:76-93
Timestamp: 2025-08-27T05:55:40.481Z
Learning: In the sqlite-web-core codebase, for SQLite aggregate function context initialization, the maintainer prefers using byte-scanning to detect zero-initialized memory rather than using explicit initialization flags or Option wrappers.

if argc != 0 {
sqlite3_result_error(
context,
c"FLOAT_ZERO_HEX() does not take any arguments".as_ptr(),
-1,
);
sqlite3_result_error_code(context, SQLITE_MISUSE);
return;
}

let zero_hex = Float::default().as_hex();
let zero_hex_ptr = zero_hex.as_ptr() as *const c_char;
let zero_hex_len = zero_hex.len() as c_int;

sqlite3_result_text(context, zero_hex_ptr, zero_hex_len, sqlite_transient());
}
22 changes: 22 additions & 0 deletions packages/sqlite-web-core/src/database_functions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ use std::str::FromStr;
mod bigint_sum;
mod float_negate;
mod float_sum;
mod float_zero_hex;
mod rain_math;

use bigint_sum::*;
use float_negate::*;
use float_sum::*;
use float_zero_hex::*;

pub use rain_math::*;

Expand Down Expand Up @@ -80,6 +82,26 @@ pub fn register_custom_functions(db: *mut sqlite3) -> Result<(), String> {
return Err("Failed to register FLOAT_SUM function".to_string());
}

// Register FLOAT_ZERO_HEX scalar function
let float_zero_hex_name = CString::new("FLOAT_ZERO_HEX").unwrap();
let ret = unsafe {
sqlite3_create_function_v2(
db,
float_zero_hex_name.as_ptr(),
0, // 0 arguments
SQLITE_UTF8 | SQLITE_DETERMINISTIC | SQLITE_INNOCUOUS,
std::ptr::null_mut(),
Some(float_zero_hex), // Scalar function
None,
None,
None,
)
};

if ret != SQLITE_OK {
return Err("Failed to register FLOAT_ZERO_HEX function".to_string());
}

// Register FLOAT_NEGATE scalar function
let float_negate_name = CString::new("FLOAT_NEGATE").unwrap();
let ret = unsafe {
Expand Down
2 changes: 1 addition & 1 deletion pkg/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@
"sideEffects": [
"./snippets/*"
]
}
}
Loading