Skip to content

Commit 5346432

Browse files
authored
feat: add tag DDL support (CREATE/DROP/SHOW only) (#19109)
* feat: add tag DDL support (CREATE/DROP/SHOW only) * fix conversation * add tag <-> object ref * refactor * rename some struct * extract TagError * fix conversation * add reserved TagMeta::drop_on * split TagError, TagMetaError; add some comments * retry set_object_tags and drop concurrent tag error - set_object_tags now perform an optimistic retry with txn_backoff to keep allowed_values consistent with the latest tag meta. - remove the TagMetaConcurrentModification errors and corresponding exception code, instead retry logic processing. * meta: add explicit tag allowed_values enforcement flag - Proto3 `repeated` fields can’t distinguish `None` from `Some(Vec::new())`, so extending TagMeta with a dedicated `enforce_allowed_values` flag lets us tell whether a tag declared `ALLOWED_VALUES` even when the list is empty. - Split the semantics in Rust too: keep `allowed_values: Vec<String>` strictly for ordered values, and use the boolean to record if the constraint is active instead of overloading `Option<Vec<_>>`. - Update CREATE TAG interpreter, tag validation, error text, and system.tags display to respect the new structure, and refresh the proto conversion tests. * optimize - represent tag allowed_values as Option<Vec<String>> without an enforce flag - update tag.proto + conversions to the new AllowedValues message - simplify validation/error paths and keep system.tags display consistent
1 parent 119f87d commit 5346432

File tree

49 files changed

+2162
-21
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+2162
-21
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/common/exception/src/exception_code.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,18 @@ build_exceptions! {
373373
IndexColumnIdNotFound(2726),
374374
}
375375

376+
// Tag Errors [2750-2753]
377+
build_exceptions! {
378+
/// Tag already exists
379+
TagAlreadyExists(2750),
380+
/// Unknown tag
381+
UnknownTag(2751),
382+
/// Invalid value for tag
383+
NotAllowedTagValue(2752),
384+
/// Tag still has references
385+
TagHasReferences(2753),
386+
}
387+
376388
// Cloud and Integration Errors [1701-1703]
377389
build_exceptions! {
378390
/// Cloud control connect error

src/meta/api/src/catalog_api.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,9 @@ where
128128
let name_id_values = self.list_id_value(&dir).await?;
129129

130130
let catalog_infos = name_id_values
131-
.map(|(name, id, seq_meta)| Arc::new(CatalogInfo::new(name, id, seq_meta.data)))
131+
.map(|(name, id_seqv, seq_meta)| {
132+
Arc::new(CatalogInfo::new(name, id_seqv.data, seq_meta.data))
133+
})
132134
.collect::<Vec<_>>();
133135

134136
Ok(catalog_infos)

src/meta/api/src/index_api.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,10 +217,10 @@ where
217217
let index_metas = name_id_metas
218218
// table_id is not specified
219219
// or table_id is specified and equals to the given table_id.
220-
.filter(|(_k, _id, seq_meta)| {
220+
.filter(|(_k, _seq_id, seq_meta)| {
221221
req.table_id.is_none() || req.table_id == Some(seq_meta.table_id)
222222
})
223-
.map(|(k, id, seq_meta)| (k.index_name().to_string(), id, seq_meta.data))
223+
.map(|(k, id_seqv, seq_meta)| (k.index_name().to_string(), id_seqv.data, seq_meta.data))
224224
.collect::<Vec<_>>();
225225

226226
Ok(index_metas)

src/meta/api/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ pub mod security_api;
4545
mod sequence_api;
4646
pub mod serialization_util;
4747
pub mod table_api;
48+
pub mod tag_api;
4849
pub(crate) mod testing;
4950
pub mod txn_backoff;
5051
pub mod txn_condition_util;
@@ -72,6 +73,7 @@ pub use data_mask_api::DatamaskApi;
7273
pub use data_retention_util::get_retention_boundary;
7374
pub use data_retention_util::is_drop_time_retainable;
7475
pub use database_api::DatabaseApi;
76+
pub use databend_common_meta_app::schema::TagError;
7577
pub use dictionary_api::DictionaryApi;
7678
// Re-export from new error_util module for backward compatibility
7779
pub use error_util::assert_table_exist;
@@ -102,6 +104,7 @@ pub use serialization_util::{
102104
deserialize_struct, deserialize_u64, serialize_struct, serialize_u64,
103105
};
104106
pub use table_api::TableApi;
107+
pub use tag_api::TagApi;
105108
// Re-export from new txn_condition_util module for backward compatibility
106109
pub use txn_condition_util::txn_cond_eq_seq;
107110
pub use txn_condition_util::txn_cond_seq;

src/meta/api/src/name_id_value_api.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -274,9 +274,9 @@ where
274274
self.get_id_and_value(key).await
275275
}
276276

277-
/// list by name prefix, returns a list of `(name, id, value)`
277+
/// list by name prefix, returns a list of `(name, SeqV<id>, SeqV<value>)`
278278
///
279-
/// Returns an iterator of `(name, id, SeqV<value>)` tuples.
279+
/// Returns an iterator of `(name, SeqV<id>, SeqV<value>)` tuples.
280280
/// This function list all the ids by a name prefix,
281281
/// then get the `id->value` mapping and finally zip these two together.
282282
// Using `async fn` does not allow using `impl Iterator` in the return type.
@@ -286,7 +286,7 @@ where
286286
prefix: &DirName<K>,
287287
) -> impl Future<
288288
Output = Result<
289-
impl Iterator<Item = (K, DataId<IdRsc>, SeqV<IdRsc::ValueType>)>,
289+
impl Iterator<Item = (K, SeqV<DataId<IdRsc>>, SeqV<IdRsc::ValueType>)>,
290290
MetaError,
291291
>,
292292
> + Send {
@@ -295,10 +295,9 @@ where
295295
let strm = self.list_pb(prefix).await?;
296296
let name_ids = strm.try_collect::<Vec<_>>().await?;
297297

298-
let id_idents = name_ids.iter().map(|itm| {
299-
let id = itm.seqv.data;
300-
id.into_t_ident(tenant)
301-
});
298+
let id_idents = name_ids
299+
.iter()
300+
.map(|itm| itm.seqv.data.into_t_ident(tenant));
302301

303302
let strm = self.get_pb_values(id_idents).await?;
304303
let seq_metas = strm.try_collect::<Vec<_>>().await?;
@@ -308,7 +307,7 @@ where
308307
.into_iter()
309308
.zip(seq_metas)
310309
.filter_map(|(itm, opt_seq_meta)| {
311-
opt_seq_meta.map(|seq_meta| (itm.key, itm.seqv.data, seq_meta))
310+
opt_seq_meta.map(|seq_meta| (itm.key, itm.seqv, seq_meta))
312311
});
313312

314313
Ok(name_id_values)

0 commit comments

Comments
 (0)