1pub mod cdc_type_compatibility;
16mod column;
17mod external_table;
18mod internal_table;
19mod physical_table;
20mod schema;
21pub mod test_utils;
22
23use std::fmt::Binary;
24use std::sync::Arc;
25
26pub use column::*;
27pub use external_table::*;
28use futures::stream::BoxStream;
29pub use internal_table::*;
30use parse_display::Display;
31pub use physical_table::*;
32use risingwave_pb::catalog::table::PbEngine;
33use risingwave_pb::catalog::{
34 CreateType as PbCreateType, HandleConflictBehavior as PbHandleConflictBehavior,
35 StreamJobStatus as PbStreamJobStatus,
36};
37use risingwave_pb::plan_common::ColumnDescVersion;
38pub use schema::{Field, FieldDisplay, FieldLike, Schema, test_utils as schema_test_utils};
39
40use crate::array::DataChunk;
41pub use crate::constants::hummock;
42use crate::error::BoxedError;
43pub use crate::id::*;
44
45pub type CatalogVersion = u64;
47
48pub type TableVersionId = u64;
50pub const INITIAL_TABLE_VERSION_ID: u64 = 0;
52pub type SourceVersionId = u64;
54pub const INITIAL_SOURCE_VERSION_ID: u64 = 0;
56
57pub const DEFAULT_DATABASE_NAME: &str = "dev";
58pub const DEFAULT_SCHEMA_NAME: &str = "public";
59pub const PG_CATALOG_SCHEMA_NAME: &str = "pg_catalog";
60pub const INFORMATION_SCHEMA_SCHEMA_NAME: &str = "information_schema";
61pub const RW_CATALOG_SCHEMA_NAME: &str = "rw_catalog";
62pub const RESERVED_PG_SCHEMA_PREFIX: &str = "pg_";
63pub const DEFAULT_SUPER_USER: &str = "root";
64pub const DEFAULT_SUPER_USER_ID: UserId = UserId::new(1);
65pub const DEFAULT_SUPER_USER_FOR_PG: &str = "postgres";
67pub const DEFAULT_SUPER_USER_FOR_PG_ID: u32 = 2;
68
69pub const DEFAULT_SUPER_USER_FOR_ADMIN: &str = "rwadmin";
71pub const DEFAULT_SUPER_USER_FOR_ADMIN_ID: UserId = UserId::new(3);
72
73pub const NON_RESERVED_USER_ID: UserId = UserId::new(11);
74
75pub const MAX_SYS_CATALOG_NUM: i32 = 5000;
76pub const SYS_CATALOG_START_ID: i32 = i32::MAX - MAX_SYS_CATALOG_NUM;
77
78pub use risingwave_pb::id::OBJECT_ID_PLACEHOLDER;
79
80pub const SYSTEM_SCHEMAS: [&str; 3] = [
81 PG_CATALOG_SCHEMA_NAME,
82 INFORMATION_SCHEMA_SCHEMA_NAME,
83 RW_CATALOG_SCHEMA_NAME,
84];
85pub fn is_system_schema(schema_name: &str) -> bool {
86 SYSTEM_SCHEMAS.contains(&schema_name)
87}
88
89pub fn is_reserved_admin_user(user_name: &str) -> bool {
90 user_name == DEFAULT_SUPER_USER_FOR_ADMIN
91}
92
93pub const RW_RESERVED_COLUMN_NAME_PREFIX: &str = "_rw_";
94
95pub const DEFAULT_KEY_COLUMN_NAME: &str = "_rw_key";
99
100pub fn default_key_column_name_version_mapping(version: &ColumnDescVersion) -> &str {
101 match version {
102 ColumnDescVersion::Unspecified => DEFAULT_KEY_COLUMN_NAME,
103 _ => DEFAULT_KEY_COLUMN_NAME,
104 }
105}
106
107pub const KAFKA_TIMESTAMP_COLUMN_NAME: &str = "_rw_kafka_timestamp";
112
113pub const RISINGWAVE_ICEBERG_ROW_ID: &str = "_risingwave_iceberg_row_id";
118
119pub const ROW_ID_COLUMN_NAME: &str = "_row_id";
120pub const ROW_ID_COLUMN_ID: ColumnId = ColumnId::new(0);
122
123pub const USER_COLUMN_ID_OFFSET: i32 = ROW_ID_COLUMN_ID.next().get_id();
127
128pub const RW_TIMESTAMP_COLUMN_NAME: &str = "_rw_timestamp";
129pub const RW_TIMESTAMP_COLUMN_ID: ColumnId = ColumnId::new(-1);
130
131pub const PROJECTED_ROW_ID_COLUMN_NAME: &str = "_rw_projected_row_id";
134
135pub const ICEBERG_SEQUENCE_NUM_COLUMN_NAME: &str = "_iceberg_sequence_number";
136pub const ICEBERG_FILE_PATH_COLUMN_NAME: &str = "_iceberg_file_path";
137pub const ICEBERG_FILE_POS_COLUMN_NAME: &str = "_iceberg_file_pos";
138
139pub const CDC_OFFSET_COLUMN_NAME: &str = "_rw_offset";
140pub const CDC_SOURCE_COLUMN_NUM: u32 = 3;
143pub const CDC_TABLE_NAME_COLUMN_NAME: &str = "_rw_table_name";
144
145pub const ICEBERG_SOURCE_PREFIX: &str = "__iceberg_source_";
146pub const ICEBERG_SINK_PREFIX: &str = "__iceberg_sink_";
147
148pub trait SysCatalogReader: Sync + Send + 'static {
150 fn read_table(&self, table_id: TableId) -> BoxStream<'_, Result<DataChunk, BoxedError>>;
152}
153
154pub type SysCatalogReaderRef = Arc<dyn SysCatalogReader>;
155
156#[derive(Clone, Debug, PartialEq, Default, Copy)]
157pub struct TableOption {
158 pub retention_seconds: Option<u32>, }
160
161impl From<&risingwave_pb::hummock::TableOption> for TableOption {
162 fn from(table_option: &risingwave_pb::hummock::TableOption) -> Self {
163 Self {
164 retention_seconds: table_option.retention_seconds,
165 }
166 }
167}
168
169impl From<&TableOption> for risingwave_pb::hummock::TableOption {
170 fn from(table_option: &TableOption) -> Self {
171 Self {
172 retention_seconds: table_option.retention_seconds,
173 }
174 }
175}
176
177impl TableOption {
178 pub fn new(retention_seconds: Option<u32>) -> Self {
179 TableOption { retention_seconds }
181 }
182}
183
184#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
185pub enum ConflictBehavior {
186 #[default]
187 NoCheck,
188 Overwrite,
189 IgnoreConflict,
190 DoUpdateIfNotNull,
191}
192
193#[macro_export]
194macro_rules! _checked_conflict_behaviors {
195 () => {
196 ConflictBehavior::Overwrite
197 | ConflictBehavior::IgnoreConflict
198 | ConflictBehavior::DoUpdateIfNotNull
199 };
200}
201pub use _checked_conflict_behaviors as checked_conflict_behaviors;
202
203impl ConflictBehavior {
204 pub fn from_protobuf(tb_conflict_behavior: &PbHandleConflictBehavior) -> Self {
205 match tb_conflict_behavior {
206 PbHandleConflictBehavior::Overwrite => ConflictBehavior::Overwrite,
207 PbHandleConflictBehavior::Ignore => ConflictBehavior::IgnoreConflict,
208 PbHandleConflictBehavior::DoUpdateIfNotNull => ConflictBehavior::DoUpdateIfNotNull,
209 PbHandleConflictBehavior::NoCheck | PbHandleConflictBehavior::Unspecified => {
212 ConflictBehavior::NoCheck
213 }
214 }
215 }
216
217 pub fn to_protobuf(self) -> PbHandleConflictBehavior {
218 match self {
219 ConflictBehavior::NoCheck => PbHandleConflictBehavior::NoCheck,
220 ConflictBehavior::Overwrite => PbHandleConflictBehavior::Overwrite,
221 ConflictBehavior::IgnoreConflict => PbHandleConflictBehavior::Ignore,
222 ConflictBehavior::DoUpdateIfNotNull => PbHandleConflictBehavior::DoUpdateIfNotNull,
223 }
224 }
225
226 pub fn debug_to_string(self) -> String {
227 match self {
228 ConflictBehavior::NoCheck => "NoCheck".to_owned(),
229 ConflictBehavior::Overwrite => "Overwrite".to_owned(),
230 ConflictBehavior::IgnoreConflict => "IgnoreConflict".to_owned(),
231 ConflictBehavior::DoUpdateIfNotNull => "DoUpdateIfNotNull".to_owned(),
232 }
233 }
234}
235
236#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
237pub enum Engine {
238 #[default]
239 Hummock,
240 Iceberg,
241}
242
243impl Engine {
244 pub fn from_protobuf(engine: &PbEngine) -> Self {
245 match engine {
246 PbEngine::Hummock | PbEngine::Unspecified => Engine::Hummock,
247 PbEngine::Iceberg => Engine::Iceberg,
248 }
249 }
250
251 pub fn to_protobuf(self) -> PbEngine {
252 match self {
253 Engine::Hummock => PbEngine::Hummock,
254 Engine::Iceberg => PbEngine::Iceberg,
255 }
256 }
257
258 pub fn debug_to_string(self) -> String {
259 match self {
260 Engine::Hummock => "Hummock".to_owned(),
261 Engine::Iceberg => "Iceberg".to_owned(),
262 }
263 }
264}
265
266#[derive(Clone, Copy, Debug, Default, Display, Hash, PartialOrd, PartialEq, Eq, Ord)]
267pub enum StreamJobStatus {
268 #[default]
269 Creating,
270 Created,
271}
272
273impl StreamJobStatus {
274 pub fn from_proto(stream_job_status: PbStreamJobStatus) -> Self {
275 match stream_job_status {
276 PbStreamJobStatus::Creating => StreamJobStatus::Creating,
277 PbStreamJobStatus::Created | PbStreamJobStatus::Unspecified => StreamJobStatus::Created,
278 }
279 }
280
281 pub fn to_proto(self) -> PbStreamJobStatus {
282 match self {
283 StreamJobStatus::Creating => PbStreamJobStatus::Creating,
284 StreamJobStatus::Created => PbStreamJobStatus::Created,
285 }
286 }
287}
288
289#[derive(Clone, Copy, Debug, Display, Hash, PartialOrd, PartialEq, Eq, Ord, Default)]
290pub enum CreateType {
291 #[default]
292 Foreground,
293 Background,
294}
295
296impl CreateType {
297 pub fn from_proto(pb_create_type: PbCreateType) -> Self {
298 match pb_create_type {
299 PbCreateType::Foreground | PbCreateType::Unspecified => CreateType::Foreground,
300 PbCreateType::Background => CreateType::Background,
301 }
302 }
303
304 pub fn to_proto(self) -> PbCreateType {
305 match self {
306 CreateType::Foreground => PbCreateType::Foreground,
307 CreateType::Background => PbCreateType::Background,
308 }
309 }
310}
311
312#[derive(Clone, Debug)]
313pub enum AlterDatabaseParam {
314 BarrierIntervalMs(Option<u32>),
317 CheckpointFrequency(Option<u64>),
318}
319
320macro_rules! for_all_fragment_type_flags {
321 () => {
322 for_all_fragment_type_flags! {
323 {
324 Source,
325 Mview,
326 Sink,
327 Now,
328 StreamScan,
329 BarrierRecv,
330 Values,
331 Dml,
332 CdcFilter,
333 Skipped1,
334 SourceScan,
335 SnapshotBackfillStreamScan,
336 FsFetch,
337 CrossDbSnapshotBackfillStreamScan,
338 StreamCdcScan,
339 VectorIndexWrite,
340 UpstreamSinkUnion,
341 LocalityProvider
342 },
343 {},
344 0
345 }
346 };
347 (
348 {},
349 {
350 $(
351 {$flag:ident, $index:expr}
352 ),*
353 },
354 $next_index:expr
355 ) => {
356 #[derive(Clone, Copy, Debug, Display, Hash, PartialOrd, PartialEq, Eq)]
357 #[repr(u32)]
358 pub enum FragmentTypeFlag {
359 $(
360 $flag = (1 << $index),
361 )*
362 }
363
364 pub const FRAGMENT_TYPE_FLAG_LIST: [FragmentTypeFlag; $next_index] = [
365 $(
366 FragmentTypeFlag::$flag,
367 )*
368 ];
369
370 impl TryFrom<u32> for FragmentTypeFlag {
371 type Error = String;
372
373 fn try_from(value: u32) -> Result<Self, Self::Error> {
374 match value {
375 $(
376 value if value == (FragmentTypeFlag::$flag as u32) => Ok(FragmentTypeFlag::$flag),
377 )*
378 _ => Err(format!("Invalid FragmentTypeFlag value: {}", value)),
379 }
380 }
381 }
382
383 impl FragmentTypeFlag {
384 pub fn as_str_name(&self) -> &'static str {
385 match self {
386 $(
387 FragmentTypeFlag::$flag => paste::paste!{stringify!( [< $flag:snake:upper >] )},
388 )*
389 }
390 }
391 }
392 };
393 (
394 {$first:ident $(, $rest:ident)*},
395 {
396 $(
397 {$flag:ident, $index:expr}
398 ),*
399 },
400 $next_index:expr
401 ) => {
402 for_all_fragment_type_flags! {
403 {$($rest),*},
404 {
405 $({$flag, $index},)*
406 {$first, $next_index}
407 },
408 $next_index + 1
409 }
410 };
411}
412
413for_all_fragment_type_flags!();
414
415impl FragmentTypeFlag {
416 pub fn raw_flag(flags: impl IntoIterator<Item = FragmentTypeFlag>) -> u32 {
417 flags.into_iter().fold(0, |acc, flag| acc | (flag as u32))
418 }
419
420 pub fn backfill_rate_limit_fragments() -> impl Iterator<Item = FragmentTypeFlag> {
422 [FragmentTypeFlag::SourceScan, FragmentTypeFlag::StreamScan].into_iter()
423 }
424
425 pub fn source_rate_limit_fragments() -> impl Iterator<Item = FragmentTypeFlag> {
428 [FragmentTypeFlag::Source, FragmentTypeFlag::FsFetch].into_iter()
429 }
430
431 pub fn sink_rate_limit_fragments() -> impl Iterator<Item = FragmentTypeFlag> {
433 [FragmentTypeFlag::Sink].into_iter()
434 }
435
436 pub fn rate_limit_fragments() -> impl Iterator<Item = FragmentTypeFlag> {
438 Self::backfill_rate_limit_fragments()
439 .chain(Self::source_rate_limit_fragments())
440 .chain(Self::sink_rate_limit_fragments())
441 }
442
443 pub fn dml_rate_limit_fragments() -> impl Iterator<Item = FragmentTypeFlag> {
444 [FragmentTypeFlag::Dml].into_iter()
445 }
446}
447
448#[derive(Clone, Copy, Debug, Hash, PartialOrd, PartialEq, Eq, Default)]
449pub struct FragmentTypeMask(u32);
450
451impl Binary for FragmentTypeMask {
452 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
453 write!(f, "{:b}", self.0)
454 }
455}
456
457impl From<i32> for FragmentTypeMask {
458 fn from(value: i32) -> Self {
459 Self(value as u32)
460 }
461}
462
463impl From<u32> for FragmentTypeMask {
464 fn from(value: u32) -> Self {
465 Self(value)
466 }
467}
468
469impl From<FragmentTypeMask> for u32 {
470 fn from(value: FragmentTypeMask) -> Self {
471 value.0
472 }
473}
474
475impl From<FragmentTypeMask> for i32 {
476 fn from(value: FragmentTypeMask) -> Self {
477 value.0 as _
478 }
479}
480
481impl FragmentTypeMask {
482 pub fn empty() -> Self {
483 FragmentTypeMask(0)
484 }
485
486 pub fn add(&mut self, flag: FragmentTypeFlag) {
487 self.0 |= flag as u32;
488 }
489
490 pub fn contains_any(&self, flags: impl IntoIterator<Item = FragmentTypeFlag>) -> bool {
491 let flag = FragmentTypeFlag::raw_flag(flags);
492 (self.0 & flag) != 0
493 }
494
495 pub fn contains(&self, flag: FragmentTypeFlag) -> bool {
496 self.contains_any([flag])
497 }
498}
499
500#[cfg(test)]
501mod tests {
502 use itertools::Itertools;
503 use risingwave_common::catalog::FRAGMENT_TYPE_FLAG_LIST;
504
505 use crate::catalog::FragmentTypeFlag;
506
507 #[test]
508 fn test_all_fragment_type_flag() {
509 expect_test::expect![[r#"
510 [
511 (
512 Source,
513 1,
514 "SOURCE",
515 ),
516 (
517 Mview,
518 2,
519 "MVIEW",
520 ),
521 (
522 Sink,
523 4,
524 "SINK",
525 ),
526 (
527 Now,
528 8,
529 "NOW",
530 ),
531 (
532 StreamScan,
533 16,
534 "STREAM_SCAN",
535 ),
536 (
537 BarrierRecv,
538 32,
539 "BARRIER_RECV",
540 ),
541 (
542 Values,
543 64,
544 "VALUES",
545 ),
546 (
547 Dml,
548 128,
549 "DML",
550 ),
551 (
552 CdcFilter,
553 256,
554 "CDC_FILTER",
555 ),
556 (
557 Skipped1,
558 512,
559 "SKIPPED1",
560 ),
561 (
562 SourceScan,
563 1024,
564 "SOURCE_SCAN",
565 ),
566 (
567 SnapshotBackfillStreamScan,
568 2048,
569 "SNAPSHOT_BACKFILL_STREAM_SCAN",
570 ),
571 (
572 FsFetch,
573 4096,
574 "FS_FETCH",
575 ),
576 (
577 CrossDbSnapshotBackfillStreamScan,
578 8192,
579 "CROSS_DB_SNAPSHOT_BACKFILL_STREAM_SCAN",
580 ),
581 (
582 StreamCdcScan,
583 16384,
584 "STREAM_CDC_SCAN",
585 ),
586 (
587 VectorIndexWrite,
588 32768,
589 "VECTOR_INDEX_WRITE",
590 ),
591 (
592 UpstreamSinkUnion,
593 65536,
594 "UPSTREAM_SINK_UNION",
595 ),
596 (
597 LocalityProvider,
598 131072,
599 "LOCALITY_PROVIDER",
600 ),
601 ]
602 "#]]
603 .assert_debug_eq(
604 &FRAGMENT_TYPE_FLAG_LIST
605 .into_iter()
606 .map(|flag| (flag, flag as u32, flag.as_str_name()))
607 .collect_vec(),
608 );
609 for flag in FRAGMENT_TYPE_FLAG_LIST {
610 assert_eq!(FragmentTypeFlag::try_from(flag as u32).unwrap(), flag);
611 }
612 }
613}