use remdb::config::{DbConfig, DefaultMemoryAllocator, LogMode, WALConfig};
use remdb::platform::{init_platform, FileHandle, FileMode, FileResult, Platform, SeekWhence};
use remdb::sql::{execute_query, parse_sql_query};
use remdb::RemDb;
struct TestPlatform;
impl Platform for TestPlatform {
fn get_timestamp(&self) -> u64 {
1234567890
}
fn get_timestamp_us(&self) -> u64 {
1234567890123
}
fn spin_lock(&self, lock: &mut u32) {
while unsafe {
core::sync::atomic::AtomicU32::from_ptr(lock as *mut u32)
.compare_exchange(
0,
1,
core::sync::atomic::Ordering::Acquire,
core::sync::atomic::Ordering::Relaxed,
)
.is_err()
} {
core::hint::spin_loop();
}
}
fn spin_unlock(&self, lock: &mut u32) {
unsafe {
core::sync::atomic::AtomicU32::from_ptr(lock as *mut u32)
.store(0, core::sync::atomic::Ordering::Release);
}
}
fn compiler_barrier(&self) {
core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
}
fn full_memory_barrier(&self) {
core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst);
}
fn memcpy(&self, dest: *mut u8, src: *const u8, size: usize) {
unsafe {
core::ptr::copy_nonoverlapping(src, dest, size);
}
}
fn memset(&self, dest: *mut u8, value: u8, size: usize) {
unsafe {
core::ptr::write_bytes(dest, value, size);
}
}
fn delay_ms(&self, ms: u32) {
std::thread::sleep(std::time::Duration::from_millis(ms as u64));
}
fn delay_us(&self, us: u32) {
std::thread::sleep(std::time::Duration::from_micros(us as u64));
}
fn file_open(&self, _path: &str, _mode: FileMode) -> FileResult<FileHandle> {
Err(())
}
fn file_close(&self, _handle: FileHandle) -> FileResult<()> {
Err(())
}
fn file_write(
&self,
_handle: FileHandle,
_buffer: *const u8,
_size: usize,
) -> FileResult<usize> {
Err(())
}
fn file_read(&self, _handle: FileHandle, _buffer: *mut u8, _size: usize) -> FileResult<usize> {
Err(())
}
fn file_seek(&self, _handle: FileHandle, _offset: i64, _whence: SeekWhence) -> FileResult<u64> {
Err(())
}
fn file_remove(&self, _path: &str) -> FileResult<()> {
Err(())
}
fn file_size(&self, _path: &str) -> FileResult<usize> {
Err(())
}
fn crc32(&self, _data: *const u8, _size: usize) -> u32 {
0
}
}
fn main() {
static TEST_PLATFORM: TestPlatform = TestPlatform;
init_platform(&TEST_PLATFORM);
let memory_size = 1024 * 1024 * 500; let mut memory = vec![0u8; memory_size];
let memory_ptr = memory.as_mut_ptr();
if let Err(e) = remdb::memory::allocator::init_global_allocator(memory_ptr, memory_size) {
println!("Failed to initialize memory allocator: {:?}", e);
return;
}
std::mem::forget(memory);
static MEMORY_ALLOCATOR: DefaultMemoryAllocator = DefaultMemoryAllocator;
static DB_CONFIG: DbConfig = DbConfig {
tables: vec![],
total_memory: 1024 * 1024 * 500, low_power_mode_supported: false,
low_power_max_records: None,
default_max_records: 100000,
memory_allocator: &MEMORY_ALLOCATOR,
wal_config: WALConfig {
log_path: "./wal",
log_mode: LogMode::Async,
checkpoint_interval_ms: 60000,
log_file_size_limit: 16 * 1024 * 1024,
log_prealloc_size: 0,
log_segment_size: 16 * 1024 * 1024,
retained_checkpoints: 2,
max_consecutive_invalid: 100,
skip_threshold: 1000,
skip_block_size: 1024 * 1024,
max_skip_attempts: 3,
compression_type: remdb::config::WALCompressionType::None,
compression_level: 3,
},
time_series_defaults: remdb::time_series::TimeSeriesConfig {
partition_duration_secs: 3600, retention_period_secs: 30 * 24 * 3600, compression: remdb::time_series::CompressionType::None,
max_partitions: 1000,
},
#[cfg(feature = "pubsub")]
pubsub_config: None,
#[cfg(feature = "ha")]
ha_config: None,
model_worker_config: remdb::config::ModelWorkerConfig::DEFAULT,
};
let mut db = RemDb::new(&DB_CONFIG);
let create_table_sql = "CREATE TABLE test_null_values (
id INTEGER PRIMARY KEY,
int_val INTEGER,
real_val REAL,
text_val TEXT,
bool_val BOOLEAN,
ts_val TIMESTAMP
)";
match parse_sql_query(create_table_sql) {
Ok(query) => match execute_query(&mut db, &query) {
Ok(_) => println!("Create table result: Success"),
Err(e) => println!("Create table error: {:?}", e),
},
Err(e) => {
println!("Parse error: {:?}", e);
}
}
let insert_sql = "INSERT INTO test_null_values (id, int_val, text_val, bool_val)
VALUES (2, 100, 'test', TRUE)";
match parse_sql_query(insert_sql) {
Ok(query) => match execute_query(&mut db, &query) {
Ok(_) => println!("Insert result: Success"),
Err(e) => println!("Insert error: {:?}", e),
},
Err(e) => {
println!("Parse error: {:?}", e);
}
}
let select_sql = "SELECT int_val IS NULL as int_null, text_val IS NULL as text_null FROM test_null_values ORDER BY id";
match parse_sql_query(select_sql) {
Ok(query) => match execute_query(&mut db, &query) {
Ok(_) => println!("Select IS NULL result: Success"),
Err(e) => println!("Select IS NULL error: {:?}", e),
},
Err(e) => {
println!("Parse error: {:?}", e);
}
}
let select_not_null_sql = "SELECT int_val IS NOT NULL as int_not_null, text_val IS NOT NULL as text_not_null FROM test_null_values ORDER BY id";
match parse_sql_query(select_not_null_sql) {
Ok(query) => match execute_query(&mut db, &query) {
Ok(_) => println!("Select IS NOT NULL result: Success"),
Err(e) => println!("Select IS NOT NULL error: {:?}", e),
},
Err(e) => {
println!("Parse error: {:?}", e);
}
}
println!("Test completed successfully!");
}