internally hidden column forgotten
This commit is contained in:
@@ -46,6 +46,12 @@ pub const ACCOUNT_REFERENCE_COLUMN: &str = "account_id";
|
||||
pub const ACCOUNT_API_COLUMN: &str = "account";
|
||||
/// Internal version of a managed row. It is never exposed as editable data.
|
||||
pub const ROW_VERSION_COLUMN: &str = "version";
|
||||
/// Records the user who closed an accounting journal. It is exposed only by
|
||||
/// the dedicated accounting API, never by the generic table API.
|
||||
pub const CLOSED_BY_USER_ID_COLUMN: &str = "closed_by_user_id";
|
||||
|
||||
/// Fixed server-owned columns that generic table APIs must omit entirely.
|
||||
pub const INTERNAL_COLUMN_NAMES: [&str; 2] = [ROW_VERSION_COLUMN, CLOSED_BY_USER_ID_COLUMN];
|
||||
|
||||
/// The longest name any system column carries physically.
|
||||
///
|
||||
@@ -71,17 +77,33 @@ const fn longest_system_column_name() -> usize {
|
||||
longest
|
||||
}
|
||||
|
||||
let longest = longest_of(
|
||||
&LEADING_SYSTEM_COLUMNS,
|
||||
if ACCOUNT_REFERENCE_COLUMN.len() > ROW_VERSION_COLUMN.len() {
|
||||
ACCOUNT_REFERENCE_COLUMN.len()
|
||||
} else {
|
||||
ROW_VERSION_COLUMN.len()
|
||||
},
|
||||
);
|
||||
const fn longest_name(names: &[&str], mut longest: usize) -> usize {
|
||||
let mut index = 0;
|
||||
while index < names.len() {
|
||||
let length = names[index].len();
|
||||
if length > longest {
|
||||
longest = length;
|
||||
}
|
||||
index += 1;
|
||||
}
|
||||
longest
|
||||
}
|
||||
|
||||
let longest = longest_name(&INTERNAL_COLUMN_NAMES, ACCOUNT_REFERENCE_COLUMN.len());
|
||||
let longest = longest_of(&LEADING_SYSTEM_COLUMNS, longest);
|
||||
longest_of(&TRAILING_SYSTEM_COLUMNS, longest)
|
||||
}
|
||||
|
||||
/// Fixed internal column names. Link-version columns are also internal, but
|
||||
/// their generated names are loaded from table metadata at runtime.
|
||||
pub fn internal_column_names() -> impl Iterator<Item = &'static str> {
|
||||
INTERNAL_COLUMN_NAMES.into_iter()
|
||||
}
|
||||
|
||||
pub fn is_internal_column(name: &str) -> bool {
|
||||
internal_column_names().any(|internal_name| internal_name == name)
|
||||
}
|
||||
|
||||
/// Every system column name, whether or not the column is on a given table.
|
||||
///
|
||||
/// A name is reserved for all tables even when only some tables carry the
|
||||
@@ -92,12 +114,13 @@ pub fn system_column_names() -> impl Iterator<Item = &'static str> {
|
||||
.chain(TRAILING_SYSTEM_COLUMNS.iter())
|
||||
.map(|column| column.name)
|
||||
.chain(std::iter::once(ACCOUNT_REFERENCE_COLUMN))
|
||||
.chain(std::iter::once(ROW_VERSION_COLUMN))
|
||||
.chain(internal_column_names())
|
||||
}
|
||||
|
||||
/// Whether `name` belongs to the system column vocabulary and is safe to show
|
||||
/// to a client as-is. Whether a user may claim a virtual API name as an alias
|
||||
/// is decided with the table's capabilities in scope.
|
||||
/// Whether `name` belongs to the reserved system column vocabulary. Internal
|
||||
/// columns must still be removed before a row or structure reaches a client.
|
||||
/// Whether a user may claim a virtual API name as an alias is decided with the
|
||||
/// table's capabilities in scope.
|
||||
pub fn is_system_column(name: &str) -> bool {
|
||||
name == ACCOUNT_API_COLUMN || system_column_names().any(|system_name| system_name == name)
|
||||
}
|
||||
@@ -114,7 +137,8 @@ pub fn system_column_name_list() -> String {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
ACCOUNT_API_COLUMN, ACCOUNT_REFERENCE_COLUMN, LONGEST_SYSTEM_COLUMN_NAME, is_system_column,
|
||||
ACCOUNT_API_COLUMN, ACCOUNT_REFERENCE_COLUMN, CLOSED_BY_USER_ID_COLUMN,
|
||||
LONGEST_SYSTEM_COLUMN_NAME, ROW_VERSION_COLUMN, is_internal_column, is_system_column,
|
||||
system_column_name_list, system_column_names,
|
||||
};
|
||||
|
||||
@@ -131,6 +155,15 @@ mod tests {
|
||||
assert!(is_system_column(ACCOUNT_API_COLUMN));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn internal_columns_are_reserved_but_not_public() {
|
||||
for name in [ROW_VERSION_COLUMN, CLOSED_BY_USER_ID_COLUMN] {
|
||||
assert!(is_system_column(name));
|
||||
assert!(is_internal_column(name));
|
||||
}
|
||||
assert!(!is_internal_column(ACCOUNT_REFERENCE_COLUMN));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_ordinal_is_not_a_system_column() {
|
||||
assert!(!is_system_column("1"));
|
||||
@@ -155,7 +188,7 @@ mod tests {
|
||||
fn the_name_list_reads_as_a_sentence_fragment() {
|
||||
assert_eq!(
|
||||
system_column_name_list(),
|
||||
"'id', 'deleted', 'row_revision', 'created_at', 'account_id', 'version', 'account'"
|
||||
"'id', 'deleted', 'row_revision', 'created_at', 'account_id', 'version', 'closed_by_user_id', 'account'"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user