系统表统一命名与迁移

This commit is contained in:
LIm1tZz7 committed 2026-10-03 17:16:26 +08:00
1 parent 4c030e6181
commit 29529444a1
7 files changed
+178 -15

No files matched your search

+17
View File
@@ -202,6 +202,23 @@ impl Catalog {
Ok(())
}
/// 表改名到指定名字
pub fn rename_table(&mut self, from: &str, to: &str) -> io::Result<bool> {
let Some(entry) = self.tables.remove(from) else {
return Ok(false);
};
if self.tables.contains_key(to) {
self.tables.insert(from.to_string(), entry);
return Err(io::Error::new(
io::ErrorKind::AlreadyExists,
format!("table already exists: {}", to),
));
}
self.seen.remove(from);
self.tables.insert(to.to_string(), entry);
Ok(true)
}
/// ALTER:整列定义换成新的,并清掉二级索引与统计
pub fn set_columns(&mut self, table: &str, columns: Vec<SchemaColumn>) -> io::Result<()> {
let entry = self
+13
View File
@@ -229,6 +229,19 @@ pub fn reserved_table(table: &str) -> bool {
table.to_ascii_lowercase().starts_with("__system_")
}
/// 服务自己的角色与授权表名
pub const PRIVILEGE_TABLES: [&str; 3] = ["__system_roles", "__system_grants", "__system_members"];
/// 是不是服务自己经请求通道读写的系统表
pub fn internal_table(table: &str) -> bool {
PRIVILEGE_TABLES.contains(&table.to_ascii_lowercase().as_str())
}
/// 是不是请求通道要拒绝的系统表
pub fn blocked_table(table: &str) -> bool {
reserved_table(table) && !internal_table(table)
}
/// 没写 column 时按 `id` 算
fn default_id_column() -> String {
"id".to_string()
+60 -7
View File
@@ -8,8 +8,8 @@ use crate::config::{self, Config, Loaded};
use crate::heap::{scalar_int, HeapTable};
use crate::log;
use crate::protocol::{
reserved_table, Account, ColumnStatWire, IndexWire, Request, Response, Row, SchemaColumn, StorageOp,
TableSchemaWire, USERS_TABLE,
blocked_table, reserved_table, Account, ColumnStatWire, IndexWire, Request, Response, Row,
SchemaColumn, StorageOp, TableSchemaWire, USERS_TABLE,
};
use crate::wal::{committed_ops, Wal, WalOp};
use crate::{log_debug, log_error, log_info, log_warn};
@@ -386,7 +386,7 @@ impl Server {
| StorageOp::Delete { table, .. }
| StorageOp::Replace { table, .. } => table,
};
if reserved_table(table) {
if blocked_table(table) {
return Err(std::io::Error::other("reserved system table"));
}
if table.is_empty() || !table.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') {
@@ -604,6 +604,7 @@ impl Server {
/// 老数据迁移:类型名规范、缺列补 null
fn migrate_data(&self) -> std::io::Result<()> {
self.migrate_table_names()?;
let names: Vec<String> = self
.catalog
.lock()
@@ -649,6 +650,51 @@ impl Server {
Ok(())
}
/// 老目录里的角色与授权表改到内部前缀
fn migrate_table_names(&self) -> std::io::Result<()> {
for (from, to) in LEGACY_TABLE_RENAMES {
let indexes = {
let c = self
.catalog
.lock()
.map_err(|_| std::io::Error::other("catalog lock poisoned"))?;
match c.describe(from) {
Some(schema) if c.describe(to).is_none() => {
schema.indexes.iter().map(|i| i.column.clone()).collect::<Vec<String>>()
}
_ => continue,
}
};
self.rename_table_files(from, to, &indexes);
{
let mut c = self
.catalog
.lock()
.map_err(|_| std::io::Error::other("catalog lock poisoned"))?;
if !c.rename_table(from, to)? {
continue;
}
c.save(self.catalog_path())?;
}
if let Ok(mut tables) = self.tables.lock() {
tables.remove(from);
}
log_info!(core, "renamed system table {} to {}", from, to);
}
Ok(())
}
/// 把一张表的数据文件与索引文件改名
fn rename_table_files(&self, from: &str, to: &str, indexes: &[String]) {
if !self.table_path(from).exists() {
return;
}
let _ = std::fs::rename(self.table_path(from), self.table_path(to));
for column in std::iter::once("id").chain(indexes.iter().map(String::as_str)) {
let _ = std::fs::rename(self.index_path(from, column), self.index_path(to, column));
}
}
/// 建索引前的检查:内置列、未知表列、重复索引
fn check_create_index(&self, table: &str, column: &str) -> std::io::Result<()> {
if column == "id" {
@@ -963,7 +1009,7 @@ impl Server {
return Response::Error { message: "invalid column name".into() };
}
if let Some(table) = req.table() {
if reserved_table(table) {
if blocked_table(table) {
return Response::Error { message: "reserved system table".into() };
}
if table.is_empty() || !table.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') {
@@ -1192,7 +1238,7 @@ impl Server {
let schemas: Vec<TableSchemaWire> = c
.all_tables()
.into_iter()
.filter(|(name, _)| !reserved_table(name))
.filter(|(name, _)| !blocked_table(name))
.map(|(name, ts)| TableSchemaWire {
table: name.to_string(),
columns: ts.columns.clone(),
@@ -1364,10 +1410,10 @@ impl Server {
}
}
/// 只列出数据字典中的业务表
/// 列出业务表与授权服务用的三张系统表
fn list_tables(&self) -> std::io::Result<Vec<String>> {
let c = self.catalog.lock().map_err(|_| std::io::Error::other("catalog lock poisoned"))?;
Ok(c.table_names().into_iter().filter(|t| !reserved_table(t)).collect())
Ok(c.table_names().into_iter().filter(|t| !blocked_table(t)).collect())
}
/// 查一张表的 schema
@@ -1567,6 +1613,13 @@ impl Drop for Server {
/// 别的库一律要显式建(没有默认工作库)。
const SYSTEM_DATABASE: &str = "system";
/// 老目录里角色与授权表的旧名对照
const LEGACY_TABLE_RENAMES: [(&str, &str); 3] = [
("sys_roles", "__system_roles"),
("sys_grants", "__system_grants"),
("sys_members", "__system_members"),
];
/// 保留库:不能建、不能删。
fn reserved_database(name: &str) -> bool {
name == SYSTEM_DATABASE