mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-20 23:45:18 +01:00
Merge 'translate: disallow creating/dropping internal tables' from Jussi Saurio
edit: we can't disallow 'turso_' prefix though, because turso-sync- engine uses it Closes #3313 Reviewed-by: Nikita Sivukhin (@sivukhin) Closes #3338
This commit is contained in:
@@ -48,6 +48,9 @@ pub const DBSP_TABLE_PREFIX: &str = "__turso_internal_dbsp_state_v";
|
||||
/// Used to refer to the implicit rowid column in tables without an alias during UPDATE
|
||||
pub const ROWID_SENTINEL: usize = usize::MAX;
|
||||
|
||||
/// Internal table prefixes that should be protected from CREATE/DROP
|
||||
pub const RESERVED_TABLE_PREFIXES: [&str; 2] = ["sqlite_", "__turso_internal_"];
|
||||
|
||||
/// Check if a table name refers to a system table that should be protected from direct writes
|
||||
pub fn is_system_table(table_name: &str) -> bool {
|
||||
let normalized = table_name.to_lowercase();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::schema::Table;
|
||||
use crate::schema::{Table, RESERVED_TABLE_PREFIXES};
|
||||
use crate::translate::emitter::{
|
||||
emit_cdc_full_record, emit_cdc_insns, prepare_cdc_if_necessary, OperationMode, Resolver,
|
||||
};
|
||||
@@ -11,7 +11,7 @@ use crate::translate::plan::{
|
||||
use crate::vdbe::builder::CursorKey;
|
||||
use crate::vdbe::insn::{CmpInsFlags, Cookie};
|
||||
use crate::vdbe::BranchOffset;
|
||||
use crate::SymbolTable;
|
||||
use crate::{bail_parse_error, SymbolTable};
|
||||
use crate::{
|
||||
schema::{BTreeTable, Column, Index, IndexColumn, PseudoCursorType, Schema},
|
||||
storage::pager::CreateBTreeFlags,
|
||||
@@ -49,6 +49,21 @@ pub fn translate_create_index(
|
||||
let original_tbl_name = tbl_name;
|
||||
let idx_name = normalize_ident(idx_name);
|
||||
let tbl_name = normalize_ident(tbl_name);
|
||||
if RESERVED_TABLE_PREFIXES
|
||||
.iter()
|
||||
.any(|prefix| idx_name.starts_with(prefix))
|
||||
{
|
||||
bail_parse_error!(
|
||||
"Object name reserved for internal use: {}",
|
||||
original_idx_name
|
||||
);
|
||||
}
|
||||
if RESERVED_TABLE_PREFIXES
|
||||
.iter()
|
||||
.any(|prefix| tbl_name.starts_with(prefix))
|
||||
{
|
||||
bail_parse_error!("Object name reserved for internal use: {}", tbl_name);
|
||||
}
|
||||
let opts = crate::vdbe::builder::ProgramBuilderOpts {
|
||||
num_cursors: 5,
|
||||
approx_num_insns: 40,
|
||||
|
||||
@@ -8,6 +8,7 @@ use crate::schema::Column;
|
||||
use crate::schema::Schema;
|
||||
use crate::schema::Table;
|
||||
use crate::schema::Type;
|
||||
use crate::schema::RESERVED_TABLE_PREFIXES;
|
||||
use crate::storage::pager::CreateBTreeFlags;
|
||||
use crate::translate::emitter::emit_cdc_full_record;
|
||||
use crate::translate::emitter::emit_cdc_insns;
|
||||
@@ -58,6 +59,17 @@ pub fn translate_create_table(
|
||||
approx_num_labels: 1,
|
||||
};
|
||||
program.extend(&opts);
|
||||
|
||||
if RESERVED_TABLE_PREFIXES
|
||||
.iter()
|
||||
.any(|prefix| normalized_tbl_name.starts_with(prefix))
|
||||
{
|
||||
bail_parse_error!(
|
||||
"Object name reserved for internal use: {}",
|
||||
tbl_name.name.as_str()
|
||||
);
|
||||
}
|
||||
|
||||
if schema.get_table(&normalized_tbl_name).is_some() {
|
||||
if if_not_exists {
|
||||
return Ok(program);
|
||||
@@ -601,6 +613,13 @@ pub fn translate_drop_table(
|
||||
bail_parse_error!("No such table: {}", tbl_name.name.as_str());
|
||||
}
|
||||
|
||||
if RESERVED_TABLE_PREFIXES
|
||||
.iter()
|
||||
.any(|prefix| tbl_name.name.as_str().starts_with(prefix))
|
||||
{
|
||||
bail_parse_error!("table {} may not be dropped", tbl_name.name.as_str());
|
||||
}
|
||||
|
||||
let table = table.unwrap(); // safe since we just checked for None
|
||||
|
||||
// Check if this is a materialized view - if so, refuse to drop it with DROP TABLE
|
||||
|
||||
Reference in New Issue
Block a user