use crate::platform::{memcpy, memset};
use crate::types::{RemDbError, Result, Value};
pub const SYSTEM_CONFIG_TABLE: &str = "__remdb_system_config";
pub const SYSTEM_ROLES_TABLE: &str = "__remdb_system_roles";
pub const SYSTEM_ROLE_PERMISSIONS_TABLE: &str = "__remdb_system_role_permissions";
pub const SYSTEM_USERS_TABLE: &str = "__remdb_system_users";
pub const SYSTEM_USER_ROLES_TABLE: &str = "__remdb_system_user_roles";
static mut CONFIG_CACHE: Option<ConfigCache> = None;
#[derive(Clone)]
pub struct ConfigCache {
pub vector_compression_enabled: bool,
pub vector_compression_scheme: u8,
pub vector_compression_level: u8,
pub max_query_memory_mb: u32,
pub query_timeout_ms: u32,
}
pub const COMPRESSION_NONE: u8 = 0;
pub const COMPRESSION_FLOAT16: u8 = 1;
pub const COMPRESSION_ZSTD: u8 = 2;
pub unsafe fn init_system_tables(db: &mut crate::RemDb) -> Result<bool> {
let system_config_table_exists = db.tables.iter().any(|table_opt| {
table_opt
.as_ref()
.map(|table| table.def.name == SYSTEM_CONFIG_TABLE)
.unwrap_or(false)
});
let mut tables_created = false;
if !system_config_table_exists {
create_system_config_table(db)?;
insert_default_configs(db)?;
tables_created = true;
}
let roles_table_exists = db.tables.iter().any(|table_opt| {
table_opt
.as_ref()
.map(|table| table.def.name == SYSTEM_ROLES_TABLE)
.unwrap_or(false)
});
if !roles_table_exists {
create_system_roles_table(db)?;
create_system_role_permissions_table(db)?;
create_system_users_table(db)?;
create_system_user_roles_table(db)?;
insert_default_rbac_data(db)?;
tables_created = true;
}
load_config_cache(db)?;
Ok(tables_created)
}
unsafe fn create_system_config_table(db: &mut crate::RemDb) -> Result<()> {
let now = crate::platform::get_timestamp_us();
let _offset = 0;
let record_size = 64 + 256 + 128 + 8 + 8;
let fields = vec![
crate::types::FieldDef {
name: "config_key".to_string(),
data_type: crate::types::DataType::VarChar,
size: 64,
string_length: Some(64),
offset: 0,
primary_key: true,
not_null: true,
unique: true,
auto_increment: false,
default_value: None,
vector_metadata: None,
json_metadata: None,
},
crate::types::FieldDef {
name: "config_value".to_string(),
data_type: crate::types::DataType::VarChar,
size: 256,
string_length: Some(256),
offset: 64,
primary_key: false,
not_null: false,
unique: false,
auto_increment: false,
default_value: None,
vector_metadata: None,
json_metadata: None,
},
crate::types::FieldDef {
name: "description".to_string(),
data_type: crate::types::DataType::VarChar,
size: 128,
string_length: Some(128),
offset: 64 + 256,
primary_key: false,
not_null: false,
unique: false,
auto_increment: false,
default_value: None,
vector_metadata: None,
json_metadata: None,
},
crate::types::FieldDef {
name: "updated_at".to_string(),
data_type: crate::types::DataType::Timestamp,
size: 8,
string_length: None,
offset: 64 + 256 + 128,
primary_key: false,
not_null: false,
unique: false,
auto_increment: false,
default_value: None,
vector_metadata: None,
json_metadata: None,
},
crate::types::FieldDef {
name: "created_at".to_string(),
data_type: crate::types::DataType::Timestamp,
size: 8,
string_length: None,
offset: 64 + 256 + 128 + 8,
primary_key: false,
not_null: false,
unique: false,
auto_increment: false,
default_value: None,
vector_metadata: None,
json_metadata: None,
},
];
let table_def = crate::types::TableDef {
id: (db.tables.len() + 1) as u8, name: SYSTEM_CONFIG_TABLE.to_string(),
fields,
primary_key: vec![0], secondary_index: None,
secondary_index_type: crate::types::IndexType::SortedArray,
record_size,
max_records: 512, version: 1,
created_at: now,
updated_at: now,
};
let table = crate::table::MemoryTable::new(alloc::sync::Arc::new(table_def))?;
db.tables.push(Some(table));
db.primary_indices.push(None);
db.secondary_indices.push(None);
Ok(())
}
unsafe fn create_system_roles_table(db: &mut crate::RemDb) -> Result<()> {
let now = crate::platform::get_timestamp_us();
let record_size = 64 + 256 + 8 + 8;
let fields = vec![
crate::types::FieldDef {
name: "role_name".to_string(),
data_type: crate::types::DataType::VarChar,
size: 64,
string_length: Some(64),
offset: 0,
primary_key: true,
not_null: true,
unique: true,
auto_increment: false,
default_value: None,
vector_metadata: None,
json_metadata: None,
},
crate::types::FieldDef {
name: "description".to_string(),
data_type: crate::types::DataType::VarChar,
size: 256,
string_length: Some(256),
offset: 64,
primary_key: false,
not_null: false,
unique: false,
auto_increment: false,
default_value: None,
vector_metadata: None,
json_metadata: None,
},
crate::types::FieldDef {
name: "created_at".to_string(),
data_type: crate::types::DataType::Timestamp,
size: 8,
string_length: None,
offset: 64 + 256,
primary_key: false,
not_null: false,
unique: false,
auto_increment: false,
default_value: None,
vector_metadata: None,
json_metadata: None,
},
crate::types::FieldDef {
name: "updated_at".to_string(),
data_type: crate::types::DataType::Timestamp,
size: 8,
string_length: None,
offset: 64 + 256 + 8,
primary_key: false,
not_null: false,
unique: false,
auto_increment: false,
default_value: None,
vector_metadata: None,
json_metadata: None,
},
];
let table_def = crate::types::TableDef {
id: (db.tables.len() + 1) as u8, name: SYSTEM_ROLES_TABLE.to_string(),
fields,
primary_key: vec![0], secondary_index: None,
secondary_index_type: crate::types::IndexType::SortedArray,
record_size,
max_records: 512, version: 1,
created_at: now,
updated_at: now,
};
let table = crate::table::MemoryTable::new(alloc::sync::Arc::new(table_def))?;
db.tables.push(Some(table));
db.primary_indices.push(None);
db.secondary_indices.push(None);
Ok(())
}
unsafe fn create_system_role_permissions_table(db: &mut crate::RemDb) -> Result<()> {
let now = crate::platform::get_timestamp_us();
let record_size = 64 + 64 + 256 + 8;
let fields = vec![
crate::types::FieldDef {
name: "role_name".to_string(),
data_type: crate::types::DataType::VarChar,
size: 64,
string_length: Some(64),
offset: 0,
primary_key: true,
not_null: true,
unique: false,
auto_increment: false,
default_value: None,
vector_metadata: None,
json_metadata: None,
},
crate::types::FieldDef {
name: "permission".to_string(),
data_type: crate::types::DataType::VarChar,
size: 64,
string_length: Some(64),
offset: 64,
primary_key: true,
not_null: true,
unique: false,
auto_increment: false,
default_value: None,
vector_metadata: None,
json_metadata: None,
},
crate::types::FieldDef {
name: "table_name".to_string(),
data_type: crate::types::DataType::VarChar,
size: 256,
string_length: Some(256),
offset: 64 + 64,
primary_key: false,
not_null: false,
unique: false,
auto_increment: false,
default_value: None,
vector_metadata: None,
json_metadata: None,
},
crate::types::FieldDef {
name: "created_at".to_string(),
data_type: crate::types::DataType::Timestamp,
size: 8,
string_length: None,
offset: 64 + 64 + 256,
primary_key: false,
not_null: false,
unique: false,
auto_increment: false,
default_value: None,
vector_metadata: None,
json_metadata: None,
},
];
let table_def = crate::types::TableDef {
id: (db.tables.len() + 1) as u8, name: SYSTEM_ROLE_PERMISSIONS_TABLE.to_string(),
fields,
primary_key: vec![0, 1], secondary_index: None,
secondary_index_type: crate::types::IndexType::SortedArray,
record_size,
max_records: 512, version: 1,
created_at: now,
updated_at: now,
};
let table = crate::table::MemoryTable::new(alloc::sync::Arc::new(table_def))?;
db.tables.push(Some(table));
db.primary_indices.push(None);
db.secondary_indices.push(None);
Ok(())
}
unsafe fn create_system_users_table(db: &mut crate::RemDb) -> Result<()> {
let now = crate::platform::get_timestamp_us();
let record_size = 64 + 256 + 8 + 8;
let fields = vec![
crate::types::FieldDef {
name: "username".to_string(),
data_type: crate::types::DataType::VarChar,
size: 64,
string_length: Some(64),
offset: 0,
primary_key: true,
not_null: true,
unique: true,
auto_increment: false,
default_value: None,
vector_metadata: None,
json_metadata: None,
},
crate::types::FieldDef {
name: "description".to_string(),
data_type: crate::types::DataType::VarChar,
size: 256,
string_length: Some(256),
offset: 64,
primary_key: false,
not_null: false,
unique: false,
auto_increment: false,
default_value: None,
vector_metadata: None,
json_metadata: None,
},
crate::types::FieldDef {
name: "created_at".to_string(),
data_type: crate::types::DataType::Timestamp,
size: 8,
string_length: None,
offset: 64 + 256,
primary_key: false,
not_null: false,
unique: false,
auto_increment: false,
default_value: None,
vector_metadata: None,
json_metadata: None,
},
crate::types::FieldDef {
name: "updated_at".to_string(),
data_type: crate::types::DataType::Timestamp,
size: 8,
string_length: None,
offset: 64 + 256 + 8,
primary_key: false,
not_null: false,
unique: false,
auto_increment: false,
default_value: None,
vector_metadata: None,
json_metadata: None,
},
];
let table_def = crate::types::TableDef {
id: (db.tables.len() + 1) as u8, name: SYSTEM_USERS_TABLE.to_string(),
fields,
primary_key: vec![0], secondary_index: None,
secondary_index_type: crate::types::IndexType::SortedArray,
record_size,
max_records: 512, version: 1,
created_at: now,
updated_at: now,
};
let table = crate::table::MemoryTable::new(alloc::sync::Arc::new(table_def))?;
db.tables.push(Some(table));
db.primary_indices.push(None);
db.secondary_indices.push(None);
Ok(())
}
unsafe fn create_system_user_roles_table(db: &mut crate::RemDb) -> Result<()> {
let now = crate::platform::get_timestamp_us();
let record_size = 64 + 64 + 8;
let fields = vec![
crate::types::FieldDef {
name: "username".to_string(),
data_type: crate::types::DataType::VarChar,
size: 64,
string_length: Some(64),
offset: 0,
primary_key: true,
not_null: true,
unique: false,
auto_increment: false,
default_value: None,
vector_metadata: None,
json_metadata: None,
},
crate::types::FieldDef {
name: "role_name".to_string(),
data_type: crate::types::DataType::VarChar,
size: 64,
string_length: Some(64),
offset: 64,
primary_key: true,
not_null: true,
unique: false,
auto_increment: false,
default_value: None,
vector_metadata: None,
json_metadata: None,
},
crate::types::FieldDef {
name: "created_at".to_string(),
data_type: crate::types::DataType::Timestamp,
size: 8,
string_length: None,
offset: 64 + 64,
primary_key: false,
not_null: false,
unique: false,
auto_increment: false,
default_value: None,
vector_metadata: None,
json_metadata: None,
},
];
let table_def = crate::types::TableDef {
id: (db.tables.len() + 1) as u8, name: SYSTEM_USER_ROLES_TABLE.to_string(),
fields,
primary_key: vec![0, 1], secondary_index: None,
secondary_index_type: crate::types::IndexType::SortedArray,
record_size,
max_records: 512, version: 1,
created_at: now,
updated_at: now,
};
let table = crate::table::MemoryTable::new(alloc::sync::Arc::new(table_def))?;
db.tables.push(Some(table));
db.primary_indices.push(None);
db.secondary_indices.push(None);
Ok(())
}
unsafe fn insert_default_configs(db: &mut crate::RemDb) -> Result<()> {
let table_id = db
.tables
.iter()
.position(|table_opt| {
table_opt
.as_ref()
.map(|table| table.def.name == SYSTEM_CONFIG_TABLE)
.unwrap_or(false)
})
.ok_or(RemDbError::TableNotFound)?;
let table = db.get_table_mut(table_id)?;
let now = crate::platform::get_timestamp_us();
let _timestamp_value = Value {
time: crate::types::db_timestamp {
value: now as i64,
tz_offset: 0,
precision: 6, flags: 0,
},
};
let default_configs = [
("vector_compression_enabled", "false", "全局向量压缩开关"),
(
"vector_compression_scheme",
"none",
"向量压缩方案:none=不压缩, float16=float16, zstd=ZSTD",
),
("vector_compression_level", "3", "压缩级别(1-9)"),
("max_query_memory_mb", "512", "查询内存限制(MB)"),
("query_timeout_ms", "30000", "查询超时时间(毫秒)"),
];
for (key, value, desc) in default_configs {
let mut record_data = [0u8; 64 + 256 + 128 + 8 + 8]; let mut offset = 0;
memset(record_data.as_mut_ptr().add(offset), 0, 64);
let key_bytes = key.as_bytes();
memcpy(
record_data.as_mut_ptr().add(offset),
key_bytes.as_ptr(),
key_bytes.len(),
);
offset += 64;
memset(record_data.as_mut_ptr().add(offset), 0, 256);
let value_bytes = value.as_bytes();
memcpy(
record_data.as_mut_ptr().add(offset),
value_bytes.as_ptr(),
value_bytes.len(),
);
offset += 256;
memset(record_data.as_mut_ptr().add(offset), 0, 128);
let desc_bytes = desc.as_bytes();
memcpy(
record_data.as_mut_ptr().add(offset),
desc_bytes.as_ptr(),
desc_bytes.len(),
);
offset += 128;
memcpy(
record_data.as_mut_ptr().add(offset),
&now as *const u64 as *const u8,
8,
);
offset += 8;
memcpy(
record_data.as_mut_ptr().add(offset),
&now as *const u64 as *const u8,
8,
);
table.insert(record_data.as_ptr())?;
}
Ok(())
}
unsafe fn insert_default_rbac_data(db: &mut crate::RemDb) -> Result<()> {
let now = crate::platform::get_timestamp_us();
let roles_table_id = db
.tables
.iter()
.position(|table_opt| {
table_opt
.as_ref()
.map(|table| table.def.name == SYSTEM_ROLES_TABLE)
.unwrap_or(false)
})
.ok_or(RemDbError::TableNotFound)?;
let roles_table = db.get_table_mut(roles_table_id)?;
{
let mut record_data = [0u8; 64 + 256 + 8 + 8];
let mut offset = 0;
memset(record_data.as_mut_ptr().add(offset), 0, 64);
let role_name = "admin";
let role_name_bytes = role_name.as_bytes();
memcpy(
record_data.as_mut_ptr().add(offset),
role_name_bytes.as_ptr(),
role_name_bytes.len(),
);
offset += 64;
memset(record_data.as_mut_ptr().add(offset), 0, 256);
let description = "超级管理员角色,拥有所有权限";
let desc_bytes = description.as_bytes();
memcpy(
record_data.as_mut_ptr().add(offset),
desc_bytes.as_ptr(),
desc_bytes.len(),
);
offset += 256;
memcpy(
record_data.as_mut_ptr().add(offset),
&now as *const u64 as *const u8,
8,
);
offset += 8;
memcpy(
record_data.as_mut_ptr().add(offset),
&now as *const u64 as *const u8,
8,
);
roles_table.insert(record_data.as_ptr())?;
}
let role_permissions_table_id = db
.tables
.iter()
.position(|table_opt| {
table_opt
.as_ref()
.map(|table| table.def.name == SYSTEM_ROLE_PERMISSIONS_TABLE)
.unwrap_or(false)
})
.ok_or(RemDbError::TableNotFound)?;
let role_permissions_table = db.get_table_mut(role_permissions_table_id)?;
let permissions = [
"ADMIN", "SELECT", "INSERT", "UPDATE", "DELETE", "CREATE", "DROP",
];
for permission in permissions {
let mut record_data = [0u8; 64 + 64 + 256 + 8];
let mut offset = 0;
memset(record_data.as_mut_ptr().add(offset), 0, 64);
let role_name = "admin";
let role_name_bytes = role_name.as_bytes();
memcpy(
record_data.as_mut_ptr().add(offset),
role_name_bytes.as_ptr(),
role_name_bytes.len(),
);
offset += 64;
memset(record_data.as_mut_ptr().add(offset), 0, 64);
let perm_bytes = permission.as_bytes();
memcpy(
record_data.as_mut_ptr().add(offset),
perm_bytes.as_ptr(),
perm_bytes.len(),
);
offset += 64;
memset(record_data.as_mut_ptr().add(offset), 0, 256);
offset += 256;
memcpy(
record_data.as_mut_ptr().add(offset),
&now as *const u64 as *const u8,
8,
);
role_permissions_table.insert(record_data.as_ptr())?;
}
let users_table_id = db
.tables
.iter()
.position(|table_opt| {
table_opt
.as_ref()
.map(|table| table.def.name == SYSTEM_USERS_TABLE)
.unwrap_or(false)
})
.ok_or(RemDbError::TableNotFound)?;
let users_table = db.get_table_mut(users_table_id)?;
{
let mut record_data = [0u8; 64 + 256 + 8 + 8];
let mut offset = 0;
memset(record_data.as_mut_ptr().add(offset), 0, 64);
let username = "root";
let username_bytes = username.as_bytes();
memcpy(
record_data.as_mut_ptr().add(offset),
username_bytes.as_ptr(),
username_bytes.len(),
);
offset += 64;
memset(record_data.as_mut_ptr().add(offset), 0, 256);
let description = "超级管理员用户";
let desc_bytes = description.as_bytes();
memcpy(
record_data.as_mut_ptr().add(offset),
desc_bytes.as_ptr(),
desc_bytes.len(),
);
offset += 256;
memcpy(
record_data.as_mut_ptr().add(offset),
&now as *const u64 as *const u8,
8,
);
offset += 8;
memcpy(
record_data.as_mut_ptr().add(offset),
&now as *const u64 as *const u8,
8,
);
users_table.insert(record_data.as_ptr())?;
}
let user_roles_table_id = db
.tables
.iter()
.position(|table_opt| {
table_opt
.as_ref()
.map(|table| table.def.name == SYSTEM_USER_ROLES_TABLE)
.unwrap_or(false)
})
.ok_or(RemDbError::TableNotFound)?;
let user_roles_table = db.get_table_mut(user_roles_table_id)?;
{
let mut record_data = [0u8; 64 + 64 + 8];
let mut offset = 0;
memset(record_data.as_mut_ptr().add(offset), 0, 64);
let username = "root";
let username_bytes = username.as_bytes();
memcpy(
record_data.as_mut_ptr().add(offset),
username_bytes.as_ptr(),
username_bytes.len(),
);
offset += 64;
memset(record_data.as_mut_ptr().add(offset), 0, 64);
let role_name = "admin";
let role_name_bytes = role_name.as_bytes();
memcpy(
record_data.as_mut_ptr().add(offset),
role_name_bytes.as_ptr(),
role_name_bytes.len(),
);
offset += 64;
memcpy(
record_data.as_mut_ptr().add(offset),
&now as *const u64 as *const u8,
8,
);
user_roles_table.insert(record_data.as_ptr())?;
}
Ok(())
}
pub unsafe fn load_config_cache(db: &crate::RemDb) -> Result<()> {
let table_id = db
.tables
.iter()
.position(|table_opt| {
table_opt
.as_ref()
.map(|table| table.def.name == SYSTEM_CONFIG_TABLE)
.unwrap_or(false)
})
.ok_or(RemDbError::TableNotFound)?;
let table = db.get_table(table_id)?;
let mut enabled = false;
let mut scheme = COMPRESSION_NONE;
let mut level = 3u8;
let mut max_query_memory_mb = 512u32;
let mut query_timeout_ms = 30000u32;
let mut cursor = table.scan_ref();
while let Some(record) = cursor.next() {
let config_key = record.get_str(0).unwrap_or("");
match config_key {
"vector_compression_enabled" => {
let value = record.get_str(1).unwrap_or("false");
enabled = value == "true";
}
"vector_compression_scheme" => {
let value = record.get_str(1).unwrap_or("none");
scheme = match value {
"none" => COMPRESSION_NONE,
"float16" => COMPRESSION_FLOAT16,
"zstd" => COMPRESSION_ZSTD,
_ => COMPRESSION_NONE,
};
}
"vector_compression_level" => {
let value = record.get_str(1).unwrap_or("3");
level = value.parse().unwrap_or(3);
}
"max_query_memory_mb" => {
let value = record.get_str(1).unwrap_or("512");
max_query_memory_mb = value.parse().unwrap_or(512);
}
"query_timeout_ms" => {
let value = record.get_str(1).unwrap_or("30000");
query_timeout_ms = value.parse().unwrap_or(30000);
}
_ => {}
}
}
CONFIG_CACHE = Some(ConfigCache {
vector_compression_enabled: enabled,
vector_compression_scheme: scheme,
vector_compression_level: level,
max_query_memory_mb,
query_timeout_ms,
});
Ok(())
}
pub fn get_vector_compression_config() -> ConfigCache {
unsafe {
CONFIG_CACHE.as_ref().cloned().unwrap_or_else(|| {
ConfigCache {
vector_compression_enabled: false,
vector_compression_scheme: COMPRESSION_NONE,
vector_compression_level: 3,
max_query_memory_mb: 512,
query_timeout_ms: 30000,
}
})
}
}
pub fn get_query_resource_config() -> (u32, u32) {
unsafe {
let config = CONFIG_CACHE.as_ref().cloned().unwrap_or_else(|| {
ConfigCache {
vector_compression_enabled: false,
vector_compression_scheme: COMPRESSION_NONE,
vector_compression_level: 3,
max_query_memory_mb: 512,
query_timeout_ms: 30000,
}
});
(config.max_query_memory_mb, config.query_timeout_ms)
}
}
pub unsafe fn refresh_config_cache() -> Result<()> {
if let Some(db) = crate::get_global_db() {
load_config_cache(db)?;
}
Ok(())
}
pub fn is_system_table(table_name: &str) -> bool {
table_name.starts_with("__remdb_system")
}
pub fn get_vector_field_size(dimension: u16) -> usize {
let config = get_vector_compression_config();
match config.vector_compression_scheme {
COMPRESSION_NONE => dimension as usize * 4, COMPRESSION_FLOAT16 => dimension as usize * 2, COMPRESSION_ZSTD => dimension as usize * 4 + 4, _ => dimension as usize * 4, }
}