Skip to main content

risingwave_frontend/catalog/
schema_catalog.rs

1// Copyright 2022 RisingWave Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::collections::hash_map::Entry::{Occupied, Vacant};
16use std::collections::{HashMap, HashSet};
17use std::sync::Arc;
18
19use itertools::Itertools;
20use risingwave_common::catalog::{FunctionId, IndexId, ObjectId, StreamJobStatus, TableId};
21use risingwave_common::types::DataType;
22use risingwave_connector::sink::catalog::SinkCatalog;
23pub use risingwave_expr::sig::*;
24use risingwave_pb::catalog::{
25    PbConnection, PbFunction, PbIndex, PbSchema, PbSecret, PbSink, PbSource, PbSubscription,
26    PbTable, PbView,
27};
28use risingwave_pb::user::grant_privilege::Object;
29
30use super::subscription_catalog::SubscriptionCatalog;
31use super::{OwnedByUserCatalog, OwnedGrantObject, SubscriptionId};
32use crate::catalog::connection_catalog::ConnectionCatalog;
33use crate::catalog::function_catalog::FunctionCatalog;
34use crate::catalog::index_catalog::IndexCatalog;
35use crate::catalog::secret_catalog::SecretCatalog;
36use crate::catalog::source_catalog::SourceCatalog;
37use crate::catalog::system_catalog::SystemTableCatalog;
38use crate::catalog::table_catalog::TableCatalog;
39use crate::catalog::view_catalog::ViewCatalog;
40use crate::catalog::{ConnectionId, DatabaseId, SchemaId, SecretId, SinkId, SourceId, ViewId};
41use crate::expr::{Expr, ExprImpl, infer_type_name, infer_type_with_sigmap};
42use crate::user::user_catalog::UserCatalog;
43use crate::user::{UserId, has_access_to_object};
44
45#[derive(Clone, Debug)]
46pub struct SchemaCatalog {
47    id: SchemaId,
48    pub name: String,
49    pub database_id: DatabaseId,
50    /// Contains [all types of "tables"](super::table_catalog::TableType), not only user tables.
51    table_by_name: HashMap<String, Arc<TableCatalog>>,
52    /// Contains [all types of "tables"](super::table_catalog::TableType), not only user tables.
53    table_by_id: HashMap<TableId, Arc<TableCatalog>>,
54    source_by_name: HashMap<String, Arc<SourceCatalog>>,
55    source_by_id: HashMap<SourceId, Arc<SourceCatalog>>,
56    sink_by_name: HashMap<String, Arc<SinkCatalog>>,
57    sink_by_id: HashMap<SinkId, Arc<SinkCatalog>>,
58    /// reverted index of (`sink.target_table` -> `sink_id`s)
59    table_incoming_sinks: HashMap<TableId, HashSet<SinkId>>,
60    subscription_by_name: HashMap<String, Arc<SubscriptionCatalog>>,
61    subscription_by_id: HashMap<SubscriptionId, Arc<SubscriptionCatalog>>,
62    index_by_name: HashMap<String, Arc<IndexCatalog>>,
63    index_by_id: HashMap<IndexId, Arc<IndexCatalog>>,
64    indexes_by_table_id: HashMap<TableId, Vec<Arc<IndexCatalog>>>,
65    view_by_name: HashMap<String, Arc<ViewCatalog>>,
66    view_by_id: HashMap<ViewId, Arc<ViewCatalog>>,
67    function_registry: FunctionRegistry,
68    function_by_name: HashMap<String, HashMap<Vec<DataType>, Arc<FunctionCatalog>>>,
69    function_by_id: HashMap<FunctionId, Arc<FunctionCatalog>>,
70    connection_by_name: HashMap<String, Arc<ConnectionCatalog>>,
71    connection_by_id: HashMap<ConnectionId, Arc<ConnectionCatalog>>,
72    secret_by_name: HashMap<String, Arc<SecretCatalog>>,
73    secret_by_id: HashMap<SecretId, Arc<SecretCatalog>>,
74
75    _secret_source_ref: HashMap<SecretId, Vec<SourceId>>,
76    _secret_sink_ref: HashMap<SecretId, Vec<SinkId>>,
77
78    // This field is currently used only for `show connections`
79    connection_source_ref: HashMap<ConnectionId, Vec<SourceId>>,
80    // This field is currently used only for `show connections`
81    connection_sink_ref: HashMap<ConnectionId, Vec<SinkId>>,
82    // This field only available when schema is "pg_catalog". Meanwhile, others will be empty.
83    system_table_by_name: HashMap<String, Arc<SystemTableCatalog>>,
84    pub owner: UserId,
85}
86
87impl SchemaCatalog {
88    pub fn create_table(&mut self, prost: &PbTable) -> Arc<TableCatalog> {
89        let name = prost.name.clone();
90        let id = prost.id;
91        let table: TableCatalog = prost.into();
92        let table_ref = Arc::new(table);
93
94        self.table_by_name
95            .try_insert(name, table_ref.clone())
96            .unwrap();
97        self.table_by_id.try_insert(id, table_ref.clone()).unwrap();
98        table_ref
99    }
100
101    pub fn create_sys_table(&mut self, sys_table: Arc<SystemTableCatalog>) {
102        self.system_table_by_name
103            .try_insert(sys_table.name.clone(), sys_table)
104            .unwrap();
105    }
106
107    pub fn create_sys_view(&mut self, sys_view: Arc<ViewCatalog>) {
108        self.view_by_name
109            .try_insert(sys_view.name().to_owned(), sys_view.clone())
110            .unwrap();
111        self.view_by_id
112            .try_insert(sys_view.id, sys_view.clone())
113            .unwrap();
114    }
115
116    pub fn update_table(&mut self, prost: &PbTable) -> Arc<TableCatalog> {
117        let name = prost.name.clone();
118        let id = prost.id;
119        let table: TableCatalog = prost.into();
120        let table_ref = Arc::new(table);
121
122        let old_table = self.table_by_id.get(&id).unwrap();
123        // check if the table name gets updated.
124        if old_table.name() != name
125            && let Some(t) = self.table_by_name.get(old_table.name())
126            && t.id == id
127        {
128            self.table_by_name.remove(old_table.name());
129        }
130
131        self.table_by_name.insert(name, table_ref.clone());
132        self.table_by_id.insert(id, table_ref.clone());
133        table_ref
134    }
135
136    pub fn update_index(&mut self, prost: &PbIndex) {
137        let name = prost.name.clone();
138        let id = prost.id;
139        let old_index = self.index_by_id.get(&id).unwrap();
140        let index_table = self.get_created_table_by_id(prost.index_table_id).unwrap();
141        let primary_table = self
142            .get_created_table_by_id(prost.primary_table_id)
143            .unwrap();
144        let index: IndexCatalog = IndexCatalog::build_from(prost, index_table, primary_table);
145        let index_ref = Arc::new(index);
146
147        // check if the index name gets updated.
148        if old_index.name != name
149            && let Some(idx) = self.index_by_name.get(&old_index.name)
150            && idx.id == id
151        {
152            self.index_by_name.remove(&old_index.name);
153        }
154        self.index_by_name.insert(name, index_ref.clone());
155        self.index_by_id.insert(id, index_ref.clone());
156
157        match self.indexes_by_table_id.entry(index_ref.primary_table.id) {
158            Occupied(mut entry) => {
159                let pos = entry
160                    .get()
161                    .iter()
162                    .position(|x| x.id == index_ref.id)
163                    .unwrap();
164                *entry.get_mut().get_mut(pos).unwrap() = index_ref;
165            }
166            Vacant(_entry) => {
167                unreachable!()
168            }
169        };
170    }
171
172    pub fn drop_table(&mut self, id: TableId) {
173        if let Some(table_ref) = self.table_by_id.remove(&id) {
174            self.table_by_name.remove(&table_ref.name).unwrap();
175            self.indexes_by_table_id.remove(&table_ref.id);
176        } else {
177            tracing::warn!(
178                %id,
179                "table not found when dropping, frontend might not be notified yet"
180            );
181        }
182    }
183
184    pub fn create_index(&mut self, prost: &PbIndex) {
185        let name = prost.name.clone();
186        let id = prost.id;
187        let index_table = self.get_table_by_id(prost.index_table_id).unwrap();
188        let primary_table = self
189            .get_created_table_by_id(prost.primary_table_id)
190            .unwrap();
191        let index: IndexCatalog = IndexCatalog::build_from(prost, index_table, primary_table);
192        let index_ref = Arc::new(index);
193
194        self.index_by_name
195            .try_insert(name, index_ref.clone())
196            .unwrap();
197        self.index_by_id.try_insert(id, index_ref.clone()).unwrap();
198        match self.indexes_by_table_id.entry(index_ref.primary_table.id) {
199            Occupied(mut entry) => {
200                entry.get_mut().push(index_ref);
201            }
202            Vacant(entry) => {
203                entry.insert(vec![index_ref]);
204            }
205        };
206    }
207
208    pub fn drop_index(&mut self, id: IndexId) {
209        let Some(index_ref) = self.index_by_id.remove(&id) else {
210            tracing::warn!(
211                %id,
212                "index not found when dropping, frontend might not be notified yet"
213            );
214            return;
215        };
216        self.index_by_name.remove(&index_ref.name).unwrap();
217        match self.indexes_by_table_id.entry(index_ref.primary_table.id) {
218            Occupied(mut entry) => {
219                let pos = entry
220                    .get_mut()
221                    .iter()
222                    .position(|x| x.id == index_ref.id)
223                    .unwrap();
224                entry.get_mut().remove(pos);
225            }
226            Vacant(_entry) => (),
227        };
228    }
229
230    pub fn create_source(&mut self, prost: &PbSource) {
231        let name = prost.name.clone();
232        let id = prost.id;
233        let source = SourceCatalog::from(prost);
234        let source_ref = Arc::new(source);
235
236        if let Some(connection_id) = source_ref.connection_id {
237            self.connection_source_ref
238                .entry(connection_id)
239                .and_modify(|sources| sources.push(source_ref.id))
240                .or_insert(vec![source_ref.id]);
241        }
242
243        self.source_by_name
244            .try_insert(name, source_ref.clone())
245            .unwrap();
246        self.source_by_id.try_insert(id, source_ref).unwrap();
247    }
248
249    pub fn drop_source(&mut self, id: SourceId) {
250        let Some(source_ref) = self.source_by_id.remove(&id) else {
251            tracing::warn!(
252                %id,
253                "source not found when dropping, frontend might not be notified yet"
254            );
255            return;
256        };
257        self.source_by_name.remove(&source_ref.name).unwrap();
258        if let Some(connection_id) = source_ref.connection_id
259            && let Occupied(mut e) = self.connection_source_ref.entry(connection_id)
260        {
261            let source_ids = e.get_mut();
262            source_ids.retain_mut(|sid| *sid != id);
263            if source_ids.is_empty() {
264                e.remove_entry();
265            }
266        }
267    }
268
269    pub fn update_source(&mut self, prost: &PbSource) {
270        let name = prost.name.clone();
271        let id = prost.id;
272        let source = SourceCatalog::from(prost);
273        let source_ref = Arc::new(source);
274
275        let old_source = self.source_by_id.get(&id).unwrap();
276        // check if the source name gets updated.
277        if old_source.name != name
278            && let Some(src) = self.source_by_name.get(&old_source.name)
279            && src.id == id
280        {
281            self.source_by_name.remove(&old_source.name);
282        }
283
284        self.source_by_name.insert(name, source_ref.clone());
285        self.source_by_id.insert(id, source_ref);
286    }
287
288    pub fn create_sink(&mut self, prost: &PbSink) {
289        let name = prost.name.clone();
290        let id = prost.id;
291        let sink = SinkCatalog::from(prost);
292        let sink_ref = Arc::new(sink);
293
294        if let Some(connection_id) = sink_ref.connection_id {
295            self.connection_sink_ref
296                .entry(connection_id)
297                .and_modify(|sinks| sinks.push(id))
298                .or_insert(vec![id]);
299        }
300
301        if let Some(target_table) = sink_ref.target_table {
302            assert!(
303                self.table_incoming_sinks
304                    .entry(target_table)
305                    .or_default()
306                    .insert(sink_ref.id)
307            );
308        }
309
310        self.sink_by_name
311            .try_insert(name, sink_ref.clone())
312            .unwrap();
313        self.sink_by_id.try_insert(id, sink_ref).unwrap();
314    }
315
316    pub fn drop_sink(&mut self, id: SinkId) {
317        if let Some(sink_ref) = self.sink_by_id.remove(&id) {
318            self.sink_by_name.remove(&sink_ref.name).unwrap();
319            if let Some(connection_id) = sink_ref.connection_id
320                && let Occupied(mut e) = self.connection_sink_ref.entry(connection_id)
321            {
322                let sink_ids = e.get_mut();
323                sink_ids.retain_mut(|sid| *sid != id);
324                if sink_ids.is_empty() {
325                    e.remove_entry();
326                }
327            }
328            if let Some(target_table) = sink_ref.target_table {
329                let incoming_sinks = self
330                    .table_incoming_sinks
331                    .get_mut(&target_table)
332                    .expect("should exists");
333                assert!(incoming_sinks.remove(&sink_ref.id));
334                if incoming_sinks.is_empty() {
335                    self.table_incoming_sinks.remove(&target_table);
336                }
337            }
338        } else {
339            tracing::warn!(
340                %id,
341                "sink not found when dropping, frontend might not be notified yet"
342            );
343        }
344    }
345
346    pub fn update_sink(&mut self, prost: &PbSink) {
347        let name = prost.name.clone();
348        let id = prost.id;
349        let sink = SinkCatalog::from(prost);
350        let sink_ref = Arc::new(sink);
351
352        let old_sink = self.sink_by_id.get(&id).unwrap();
353        assert_eq!(sink_ref.target_table, old_sink.target_table);
354        // check if the sink name gets updated.
355        if old_sink.name != name
356            && let Some(s) = self.sink_by_name.get(&old_sink.name)
357            && s.id == id
358        {
359            self.sink_by_name.remove(&old_sink.name);
360        }
361
362        self.sink_by_name.insert(name, sink_ref.clone());
363        self.sink_by_id.insert(id, sink_ref);
364    }
365
366    pub fn table_incoming_sinks(&self, table_id: TableId) -> Option<&HashSet<SinkId>> {
367        self.table_incoming_sinks.get(&table_id)
368    }
369
370    pub fn create_subscription(&mut self, prost: &PbSubscription) {
371        let name = prost.name.clone();
372        let id = prost.id;
373        let subscription_catalog = SubscriptionCatalog::from(prost);
374        let subscription_ref = Arc::new(subscription_catalog);
375
376        self.subscription_by_name
377            .try_insert(name, subscription_ref.clone())
378            .unwrap();
379        self.subscription_by_id
380            .try_insert(id, subscription_ref)
381            .unwrap();
382    }
383
384    pub fn drop_subscription(&mut self, id: SubscriptionId) {
385        let subscription_ref = self.subscription_by_id.remove(&id);
386        if let Some(subscription_ref) = subscription_ref {
387            self.subscription_by_name.remove(&subscription_ref.name);
388        }
389    }
390
391    pub fn update_subscription(&mut self, prost: &PbSubscription) {
392        let name = prost.name.clone();
393        let id = prost.id;
394        let subscription = SubscriptionCatalog::from(prost);
395        let subscription_ref = Arc::new(subscription);
396
397        let old_subscription = self.subscription_by_id.get(&id).unwrap();
398        // check if the subscription name gets updated.
399        if old_subscription.name != name
400            && let Some(s) = self.subscription_by_name.get(&old_subscription.name)
401            && s.id == id
402        {
403            self.subscription_by_name.remove(&old_subscription.name);
404        }
405
406        self.subscription_by_name
407            .insert(name, subscription_ref.clone());
408        self.subscription_by_id.insert(id, subscription_ref);
409    }
410
411    pub fn create_view(&mut self, prost: &PbView) {
412        let name = prost.name.clone();
413        let id = prost.id;
414        let view = ViewCatalog::from(prost);
415        let view_ref = Arc::new(view);
416
417        self.view_by_name
418            .try_insert(name, view_ref.clone())
419            .unwrap();
420        self.view_by_id.try_insert(id, view_ref).unwrap();
421    }
422
423    pub fn drop_view(&mut self, id: ViewId) {
424        let view_ref = self.view_by_id.remove(&id).unwrap();
425        self.view_by_name.remove(&view_ref.name).unwrap();
426    }
427
428    pub fn update_view(&mut self, prost: &PbView) {
429        let name = prost.name.clone();
430        let id = prost.id;
431        let view = ViewCatalog::from(prost);
432        let view_ref = Arc::new(view);
433
434        let old_view = self.view_by_id.get(&id).unwrap();
435        // check if the view name gets updated.
436        if old_view.name != name
437            && let Some(v) = self.view_by_name.get(old_view.name())
438            && v.id == id
439        {
440            self.view_by_name.remove(&old_view.name);
441        }
442
443        self.view_by_name.insert(name, view_ref.clone());
444        self.view_by_id.insert(id, view_ref);
445    }
446
447    pub fn get_func_sign(func: &FunctionCatalog) -> FuncSign {
448        FuncSign {
449            name: FuncName::Udf(func.name.clone()),
450            inputs_type: func
451                .arg_types
452                .iter()
453                .map(|t| t.clone().into())
454                .collect_vec(),
455            variadic: false,
456            ret_type: func.return_type.clone().into(),
457            build: FuncBuilder::Udf,
458            // dummy type infer, will not use this result
459            type_infer: |_| Ok(DataType::Boolean),
460            deprecated: false,
461        }
462    }
463
464    pub fn create_function(&mut self, prost: &PbFunction) {
465        let name = prost.name.clone();
466        let id = prost.id;
467        let function = FunctionCatalog::from(prost);
468        let args = function.arg_types.clone();
469        let function_ref = Arc::new(function);
470
471        self.function_registry
472            .insert(Self::get_func_sign(&function_ref));
473        self.function_by_name
474            .entry(name)
475            .or_default()
476            .try_insert(args, function_ref.clone())
477            .expect("function already exists with same argument types");
478        self.function_by_id
479            .try_insert(id, function_ref)
480            .expect("function id exists");
481    }
482
483    pub fn drop_function(&mut self, id: FunctionId) {
484        let function_ref = self
485            .function_by_id
486            .remove(&id)
487            .expect("function not found by id");
488
489        self.function_registry
490            .remove(Self::get_func_sign(&function_ref))
491            .expect("function not found in registry");
492
493        self.function_by_name
494            .get_mut(&function_ref.name)
495            .expect("function not found by name")
496            .remove(&function_ref.arg_types)
497            .expect("function not found by argument types");
498    }
499
500    pub fn update_function(&mut self, prost: &PbFunction) {
501        let name = prost.name.clone();
502        let id = prost.id;
503        let function = FunctionCatalog::from(prost);
504        let function_ref = Arc::new(function);
505
506        let old_function_by_id = self.function_by_id.get(&id).unwrap();
507        let old_function_by_name = self
508            .function_by_name
509            .get_mut(&old_function_by_id.name)
510            .unwrap();
511        // check if the function name gets updated.
512        if old_function_by_id.name != name
513            && let Some(f) = old_function_by_name.get(&old_function_by_id.arg_types)
514            && f.id == id
515        {
516            old_function_by_name.remove(&old_function_by_id.arg_types);
517            if old_function_by_name.is_empty() {
518                self.function_by_name.remove(&old_function_by_id.name);
519            }
520        }
521
522        self.function_by_name
523            .entry(name)
524            .or_default()
525            .insert(old_function_by_id.arg_types.clone(), function_ref.clone());
526        self.function_by_id.insert(id, function_ref);
527    }
528
529    pub fn create_connection(&mut self, prost: &PbConnection) {
530        let name = prost.name.clone();
531        let id = prost.id;
532        let connection = ConnectionCatalog::from(prost);
533        let connection_ref = Arc::new(connection);
534        self.connection_by_name
535            .try_insert(name, connection_ref.clone())
536            .unwrap();
537        self.connection_by_id
538            .try_insert(id, connection_ref)
539            .unwrap();
540    }
541
542    pub fn update_connection(&mut self, prost: &PbConnection) {
543        let name = prost.name.clone();
544        let id = prost.id;
545        let connection = ConnectionCatalog::from(prost);
546        let connection_ref = Arc::new(connection);
547
548        let old_connection = self.connection_by_id.get(&id).unwrap();
549        // check if the connection name gets updated.
550        if old_connection.name != name
551            && let Some(conn) = self.connection_by_name.get(&old_connection.name)
552            && conn.id == id
553        {
554            self.connection_by_name.remove(&old_connection.name);
555        }
556
557        self.connection_by_name.insert(name, connection_ref.clone());
558        self.connection_by_id.insert(id, connection_ref);
559    }
560
561    pub fn drop_connection(&mut self, connection_id: ConnectionId) {
562        let connection_ref = self
563            .connection_by_id
564            .remove(&connection_id)
565            .expect("connection not found by id");
566        self.connection_by_name
567            .remove(&connection_ref.name)
568            .expect("connection not found by name");
569    }
570
571    pub fn create_secret(&mut self, prost: &PbSecret) {
572        let name = prost.name.clone();
573        let id = prost.id;
574        let secret = SecretCatalog::from(prost);
575        let secret_ref = Arc::new(secret);
576
577        self.secret_by_id
578            .try_insert(id, secret_ref.clone())
579            .unwrap();
580        self.secret_by_name.try_insert(name, secret_ref).unwrap();
581    }
582
583    pub fn update_secret(&mut self, prost: &PbSecret) {
584        let name = prost.name.clone();
585        let id = prost.id;
586        let secret = SecretCatalog::from(prost);
587        let secret_ref = Arc::new(secret);
588
589        let old_secret = self.secret_by_id.get(&id).unwrap();
590        // check if the secret name gets updated.
591        if old_secret.name != name
592            && let Some(s) = self.secret_by_name.get(&old_secret.name)
593            && s.id == id
594        {
595            self.secret_by_name.remove(&old_secret.name);
596        }
597
598        self.secret_by_name.insert(name, secret_ref.clone());
599        self.secret_by_id.insert(id, secret_ref);
600    }
601
602    pub fn drop_secret(&mut self, secret_id: SecretId) {
603        let secret_ref = self
604            .secret_by_id
605            .remove(&secret_id)
606            .expect("secret not found by id");
607        self.secret_by_name
608            .remove(&secret_ref.name)
609            .expect("secret not found by name");
610    }
611
612    pub fn iter_object_ids(&self) -> impl Iterator<Item = ObjectId> + '_ {
613        self.table_by_id
614            .keys()
615            .map(|id| id.as_object_id())
616            .chain(self.source_by_id.keys().map(|id| id.as_object_id()))
617            .chain(self.sink_by_id.keys().map(|id| id.as_object_id()))
618            .chain(self.subscription_by_id.keys().map(|id| id.as_object_id()))
619            .chain(self.index_by_id.keys().map(|id| id.as_object_id()))
620            .chain(self.view_by_id.keys().map(|id| id.as_object_id()))
621            .chain(self.function_by_id.keys().map(|id| id.as_object_id()))
622            .chain(self.connection_by_id.keys().map(|id| id.as_object_id()))
623            .chain(self.secret_by_id.keys().map(|id| id.as_object_id()))
624    }
625
626    pub fn iter_all(&self) -> impl Iterator<Item = &Arc<TableCatalog>> {
627        self.table_by_name.values()
628    }
629
630    pub fn iter_user_table(&self) -> impl Iterator<Item = &Arc<TableCatalog>> {
631        self.table_by_name.values().filter(|v| v.is_user_table())
632    }
633
634    pub fn iter_user_table_with_acl<'a>(
635        &'a self,
636        user: &'a UserCatalog,
637    ) -> impl Iterator<Item = &'a Arc<TableCatalog>> {
638        self.table_by_name
639            .values()
640            .filter(|v| v.is_user_table() && has_access_to_object(user, v.id, v.owner))
641    }
642
643    pub fn iter_internal_table(&self) -> impl Iterator<Item = &Arc<TableCatalog>> {
644        self.table_by_name
645            .values()
646            .filter(|v| v.is_internal_table())
647    }
648
649    pub fn iter_internal_table_with_acl<'a>(
650        &'a self,
651        user: &'a UserCatalog,
652    ) -> impl Iterator<Item = &'a Arc<TableCatalog>> {
653        self.table_by_name
654            .values()
655            .filter(|v| v.is_internal_table() && has_access_to_object(user, v.id, v.owner))
656    }
657
658    /// Iterate all non-internal tables, including user tables, materialized views and indices.
659    pub fn iter_table_mv_indices(&self) -> impl Iterator<Item = &Arc<TableCatalog>> {
660        self.table_by_name
661            .values()
662            .filter(|v| !v.is_internal_table())
663    }
664
665    pub fn iter_table_mv_indices_with_acl<'a>(
666        &'a self,
667        user: &'a UserCatalog,
668    ) -> impl Iterator<Item = &'a Arc<TableCatalog>> {
669        self.table_by_name
670            .values()
671            .filter(|v| !v.is_internal_table() && has_access_to_object(user, v.id, v.owner))
672    }
673
674    /// Iterate all materialized views, excluding the indices.
675    pub fn iter_all_mvs(&self) -> impl Iterator<Item = &Arc<TableCatalog>> {
676        self.table_by_name.values().filter(|v| v.is_mview())
677    }
678
679    pub fn iter_all_mvs_with_acl<'a>(
680        &'a self,
681        user: &'a UserCatalog,
682    ) -> impl Iterator<Item = &'a Arc<TableCatalog>> {
683        self.table_by_name
684            .values()
685            .filter(|v| v.is_mview() && has_access_to_object(user, v.id, v.owner))
686    }
687
688    /// Iterate created materialized views, excluding the indices.
689    pub fn iter_created_mvs(&self) -> impl Iterator<Item = &Arc<TableCatalog>> {
690        self.table_by_name
691            .values()
692            .filter(|v| v.is_mview() && v.is_created())
693    }
694
695    pub fn iter_created_mvs_with_acl<'a>(
696        &'a self,
697        user: &'a UserCatalog,
698    ) -> impl Iterator<Item = &'a Arc<TableCatalog>> {
699        self.table_by_name
700            .values()
701            .filter(|v| v.is_mview() && v.is_created() && has_access_to_object(user, v.id, v.owner))
702    }
703
704    /// Iterate all indices
705    pub fn iter_index(&self) -> impl Iterator<Item = &Arc<IndexCatalog>> {
706        self.index_by_name.values()
707    }
708
709    pub fn iter_index_with_acl<'a>(
710        &'a self,
711        user: &'a UserCatalog,
712    ) -> impl Iterator<Item = &'a Arc<IndexCatalog>> {
713        self.index_by_name
714            .values()
715            .filter(|idx| has_access_to_object(user, idx.id, idx.owner()))
716    }
717
718    /// Iterate all sources
719    pub fn iter_source(&self) -> impl Iterator<Item = &Arc<SourceCatalog>> {
720        self.source_by_name.values()
721    }
722
723    pub fn iter_source_with_acl<'a>(
724        &'a self,
725        user: &'a UserCatalog,
726    ) -> impl Iterator<Item = &'a Arc<SourceCatalog>> {
727        self.source_by_name
728            .values()
729            .filter(|s| has_access_to_object(user, s.id, s.owner))
730    }
731
732    pub fn iter_sink(&self) -> impl Iterator<Item = &Arc<SinkCatalog>> {
733        self.sink_by_name.values()
734    }
735
736    pub fn iter_sink_with_acl<'a>(
737        &'a self,
738        user: &'a UserCatalog,
739    ) -> impl Iterator<Item = &'a Arc<SinkCatalog>> {
740        self.sink_by_name
741            .values()
742            .filter(|s| has_access_to_object(user, s.id, s.owner))
743    }
744
745    pub fn iter_subscription(&self) -> impl Iterator<Item = &Arc<SubscriptionCatalog>> {
746        self.subscription_by_name.values()
747    }
748
749    pub fn iter_subscription_with_acl<'a>(
750        &'a self,
751        user: &'a UserCatalog,
752    ) -> impl Iterator<Item = &'a Arc<SubscriptionCatalog>> {
753        self.subscription_by_name
754            .values()
755            .filter(|s| has_access_to_object(user, s.id, s.owner))
756    }
757
758    pub fn iter_view(&self) -> impl Iterator<Item = &Arc<ViewCatalog>> {
759        self.view_by_name.values()
760    }
761
762    pub fn iter_view_with_acl<'a>(
763        &'a self,
764        user: &'a UserCatalog,
765    ) -> impl Iterator<Item = &'a Arc<ViewCatalog>> {
766        self.view_by_name
767            .values()
768            .filter(|v| v.is_system_view() || has_access_to_object(user, v.id, v.owner))
769    }
770
771    pub fn iter_function(&self) -> impl Iterator<Item = &Arc<FunctionCatalog>> {
772        self.function_by_name.values().flat_map(|v| v.values())
773    }
774
775    pub fn iter_function_with_acl<'a>(
776        &'a self,
777        user: &'a UserCatalog,
778    ) -> impl Iterator<Item = &'a Arc<FunctionCatalog>> {
779        self.function_by_name
780            .values()
781            .flat_map(|v| v.values())
782            .filter(|f| has_access_to_object(user, f.id, f.owner))
783    }
784
785    pub fn iter_connections(&self) -> impl Iterator<Item = &Arc<ConnectionCatalog>> {
786        self.connection_by_name.values()
787    }
788
789    pub fn iter_connections_with_acl<'a>(
790        &'a self,
791        user: &'a UserCatalog,
792    ) -> impl Iterator<Item = &'a Arc<ConnectionCatalog>> {
793        self.connection_by_name
794            .values()
795            .filter(|c| has_access_to_object(user, c.id, c.owner))
796    }
797
798    pub fn iter_secret(&self) -> impl Iterator<Item = &Arc<SecretCatalog>> {
799        self.secret_by_name.values()
800    }
801
802    pub fn iter_secret_with_acl<'a>(
803        &'a self,
804        user: &'a UserCatalog,
805    ) -> impl Iterator<Item = &'a Arc<SecretCatalog>> {
806        self.secret_by_name
807            .values()
808            .filter(|s| has_access_to_object(user, s.id, s.owner))
809    }
810
811    pub fn iter_system_tables(&self) -> impl Iterator<Item = &Arc<SystemTableCatalog>> {
812        self.system_table_by_name.values()
813    }
814
815    pub fn get_table_by_name(
816        &self,
817        table_name: &str,
818        bind_creating_relations: bool,
819    ) -> Option<&Arc<TableCatalog>> {
820        self.table_by_name
821            .get(table_name)
822            .filter(|&table| bind_creating_relations || table.is_created())
823    }
824
825    pub fn get_any_table_by_name(&self, table_name: &str) -> Option<&Arc<TableCatalog>> {
826        self.get_table_by_name(table_name, true)
827    }
828
829    pub fn get_created_table_by_name(&self, table_name: &str) -> Option<&Arc<TableCatalog>> {
830        self.get_table_by_name(table_name, false)
831    }
832
833    pub fn get_table_by_id(&self, table_id: TableId) -> Option<&Arc<TableCatalog>> {
834        self.table_by_id.get(&table_id)
835    }
836
837    pub fn get_created_table_by_id(&self, table_id: TableId) -> Option<&Arc<TableCatalog>> {
838        self.table_by_id
839            .get(&table_id)
840            .filter(|&table| table.stream_job_status == StreamJobStatus::Created)
841    }
842
843    pub fn get_view_by_name(&self, view_name: &str) -> Option<&Arc<ViewCatalog>> {
844        self.view_by_name.get(view_name)
845    }
846
847    pub fn get_view_by_id(&self, view_id: ViewId) -> Option<&Arc<ViewCatalog>> {
848        self.view_by_id.get(&view_id)
849    }
850
851    pub fn get_source_by_name(&self, source_name: &str) -> Option<&Arc<SourceCatalog>> {
852        self.source_by_name.get(source_name)
853    }
854
855    pub fn get_source_by_id(&self, source_id: SourceId) -> Option<&Arc<SourceCatalog>> {
856        self.source_by_id.get(&source_id)
857    }
858
859    pub fn get_sink_by_name(
860        &self,
861        sink_name: &str,
862        bind_creating: bool,
863    ) -> Option<&Arc<SinkCatalog>> {
864        self.sink_by_name
865            .get(sink_name)
866            .filter(|s| bind_creating || s.is_created())
867    }
868
869    pub fn get_any_sink_by_name(&self, sink_name: &str) -> Option<&Arc<SinkCatalog>> {
870        self.get_sink_by_name(sink_name, true)
871    }
872
873    pub fn get_created_sink_by_name(&self, sink_name: &str) -> Option<&Arc<SinkCatalog>> {
874        self.get_sink_by_name(sink_name, false)
875    }
876
877    pub fn get_sink_by_id(&self, sink_id: SinkId) -> Option<&Arc<SinkCatalog>> {
878        self.sink_by_id.get(&sink_id)
879    }
880
881    pub fn get_subscription_by_name(
882        &self,
883        subscription_name: &str,
884    ) -> Option<&Arc<SubscriptionCatalog>> {
885        self.subscription_by_name.get(subscription_name)
886    }
887
888    pub fn get_subscription_by_id(
889        &self,
890        subscription_id: SubscriptionId,
891    ) -> Option<&Arc<SubscriptionCatalog>> {
892        self.subscription_by_id.get(&subscription_id)
893    }
894
895    pub fn get_index_by_name(
896        &self,
897        index_name: &str,
898        bind_creating: bool,
899    ) -> Option<&Arc<IndexCatalog>> {
900        self.index_by_name
901            .get(index_name)
902            .filter(|i| bind_creating || i.is_created())
903    }
904
905    pub fn get_any_index_by_name(&self, index_name: &str) -> Option<&Arc<IndexCatalog>> {
906        self.get_index_by_name(index_name, true)
907    }
908
909    pub fn get_created_index_by_name(&self, index_name: &str) -> Option<&Arc<IndexCatalog>> {
910        self.get_index_by_name(index_name, false)
911    }
912
913    pub fn get_index_by_id(&self, index_id: IndexId) -> Option<&Arc<IndexCatalog>> {
914        self.index_by_id.get(&index_id)
915    }
916
917    pub fn get_indexes_by_table_id(
918        &self,
919        table_id: TableId,
920        include_creating: bool,
921    ) -> Vec<Arc<IndexCatalog>> {
922        self.indexes_by_table_id
923            .get(&table_id)
924            .cloned()
925            .unwrap_or_default()
926            .into_iter()
927            .filter(|i| include_creating || i.is_created())
928            .collect()
929    }
930
931    pub fn get_any_indexes_by_table_id(&self, table_id: TableId) -> Vec<Arc<IndexCatalog>> {
932        self.get_indexes_by_table_id(table_id, true)
933    }
934
935    pub fn get_created_indexes_by_table_id(&self, table_id: TableId) -> Vec<Arc<IndexCatalog>> {
936        self.get_indexes_by_table_id(table_id, false)
937    }
938
939    pub fn get_system_table_by_name(&self, table_name: &str) -> Option<&Arc<SystemTableCatalog>> {
940        self.system_table_by_name.get(table_name)
941    }
942
943    pub fn get_table_name_by_id(&self, table_id: TableId) -> Option<String> {
944        self.table_by_id
945            .get(&table_id)
946            .map(|table| table.name.clone())
947    }
948
949    pub fn get_function_by_id(&self, function_id: FunctionId) -> Option<&Arc<FunctionCatalog>> {
950        self.function_by_id.get(&function_id)
951    }
952
953    pub fn get_function_by_name_inputs(
954        &self,
955        name: &str,
956        inputs: &mut [ExprImpl],
957    ) -> Option<&Arc<FunctionCatalog>> {
958        infer_type_with_sigmap(
959            FuncName::Udf(name.to_owned()),
960            inputs,
961            &self.function_registry,
962        )
963        .ok()?;
964        let args = inputs.iter().map(|x| x.return_type()).collect_vec();
965        self.function_by_name.get(name)?.get(&args)
966    }
967
968    pub fn get_function_by_name_args(
969        &self,
970        name: &str,
971        args: &[DataType],
972    ) -> Option<&Arc<FunctionCatalog>> {
973        let args = args.iter().map(|x| Some(x.clone())).collect_vec();
974        let func = infer_type_name(
975            &self.function_registry,
976            FuncName::Udf(name.to_owned()),
977            &args,
978        )
979        .ok()?;
980
981        let args = func
982            .inputs_type
983            .iter()
984            .filter_map(|x| {
985                if let SigDataType::Exact(t) = x {
986                    Some(t.clone())
987                } else {
988                    None
989                }
990            })
991            .collect_vec();
992
993        self.function_by_name.get(name)?.get(&args)
994    }
995
996    pub fn get_functions_by_name(&self, name: &str) -> Option<Vec<&Arc<FunctionCatalog>>> {
997        let functions = self.function_by_name.get(name)?;
998        if functions.is_empty() {
999            return None;
1000        }
1001        Some(functions.values().collect())
1002    }
1003
1004    pub fn get_connection_by_id(
1005        &self,
1006        connection_id: ConnectionId,
1007    ) -> Option<&Arc<ConnectionCatalog>> {
1008        self.connection_by_id.get(&connection_id)
1009    }
1010
1011    pub fn get_connection_by_name(&self, connection_name: &str) -> Option<&Arc<ConnectionCatalog>> {
1012        self.connection_by_name.get(connection_name)
1013    }
1014
1015    pub fn get_secret_by_name(&self, secret_name: &str) -> Option<&Arc<SecretCatalog>> {
1016        self.secret_by_name.get(secret_name)
1017    }
1018
1019    pub fn get_secret_by_id(&self, secret_id: SecretId) -> Option<&Arc<SecretCatalog>> {
1020        self.secret_by_id.get(&secret_id)
1021    }
1022
1023    /// get all sources referencing the connection
1024    pub fn get_source_ids_by_connection(
1025        &self,
1026        connection_id: ConnectionId,
1027    ) -> Option<Vec<SourceId>> {
1028        self.connection_source_ref
1029            .get(&connection_id)
1030            .map(|c| c.to_owned())
1031    }
1032
1033    /// get all sinks referencing the connection
1034    pub fn get_sink_ids_by_connection(&self, connection_id: ConnectionId) -> Option<Vec<SinkId>> {
1035        self.connection_sink_ref
1036            .get(&connection_id)
1037            .map(|s| s.to_owned())
1038    }
1039
1040    pub fn get_grant_object_by_oid(&self, oid: ObjectId) -> Option<OwnedGrantObject> {
1041        #[expect(clippy::manual_map)]
1042        if let Some(table) = self.get_created_table_by_id(oid.as_table_id()) {
1043            Some(OwnedGrantObject {
1044                owner: table.owner,
1045                object: Object::TableId(oid.as_table_id()),
1046            })
1047        } else if let Some(index) = self.get_index_by_id(oid.as_index_id()) {
1048            Some(OwnedGrantObject {
1049                owner: index.owner(),
1050                object: Object::TableId(oid.as_table_id()),
1051            })
1052        } else if let Some(source) = self.get_source_by_id(oid.as_source_id()) {
1053            Some(OwnedGrantObject {
1054                owner: source.owner,
1055                object: Object::SourceId(oid.as_source_id()),
1056            })
1057        } else if let Some(sink) = self.get_sink_by_id(oid.as_sink_id()) {
1058            Some(OwnedGrantObject {
1059                owner: sink.owner,
1060                object: Object::SinkId(oid.as_sink_id()),
1061            })
1062        } else if let Some(view) = self.get_view_by_id(oid.as_view_id()) {
1063            Some(OwnedGrantObject {
1064                owner: view.owner,
1065                object: Object::ViewId(oid.as_view_id()),
1066            })
1067        } else if let Some(function) = self.get_function_by_id(oid.as_function_id()) {
1068            Some(OwnedGrantObject {
1069                owner: function.owner(),
1070                object: Object::FunctionId(oid.as_function_id()),
1071            })
1072        } else if let Some(subscription) = self.get_subscription_by_id(oid.as_subscription_id()) {
1073            Some(OwnedGrantObject {
1074                owner: subscription.owner,
1075                object: Object::SubscriptionId(oid.as_subscription_id()),
1076            })
1077        } else if let Some(connection) = self.get_connection_by_id(oid.as_connection_id()) {
1078            Some(OwnedGrantObject {
1079                owner: connection.owner,
1080                object: Object::ConnectionId(oid.as_connection_id()),
1081            })
1082        } else if let Some(secret) = self.get_secret_by_id(oid.as_secret_id()) {
1083            Some(OwnedGrantObject {
1084                owner: secret.owner,
1085                object: Object::SecretId(oid.as_secret_id()),
1086            })
1087        } else {
1088            None
1089        }
1090    }
1091
1092    pub fn contains_object(&self, oid: ObjectId) -> bool {
1093        self.table_by_id.contains_key(&oid.as_table_id())
1094            || self.index_by_id.contains_key(&oid.as_index_id())
1095            || self.source_by_id.contains_key(&oid.as_source_id())
1096            || self.sink_by_id.contains_key(&oid.as_sink_id())
1097            || self.view_by_id.contains_key(&oid.as_view_id())
1098            || self.function_by_id.contains_key(&oid.as_function_id())
1099            || self
1100                .subscription_by_id
1101                .contains_key(&oid.as_subscription_id())
1102            || self.connection_by_id.contains_key(&oid.as_connection_id())
1103    }
1104
1105    pub fn id(&self) -> SchemaId {
1106        self.id
1107    }
1108
1109    pub fn database_id(&self) -> DatabaseId {
1110        self.database_id
1111    }
1112
1113    pub fn name(&self) -> String {
1114        self.name.clone()
1115    }
1116}
1117
1118impl OwnedByUserCatalog for SchemaCatalog {
1119    fn owner(&self) -> UserId {
1120        self.owner
1121    }
1122}
1123
1124impl From<&PbSchema> for SchemaCatalog {
1125    fn from(schema: &PbSchema) -> Self {
1126        Self {
1127            id: schema.id,
1128            owner: schema.owner,
1129            name: schema.name.clone(),
1130            database_id: schema.database_id,
1131            table_by_name: HashMap::new(),
1132            table_by_id: HashMap::new(),
1133            source_by_name: HashMap::new(),
1134            source_by_id: HashMap::new(),
1135            sink_by_name: HashMap::new(),
1136            sink_by_id: HashMap::new(),
1137            table_incoming_sinks: HashMap::new(),
1138            index_by_name: HashMap::new(),
1139            index_by_id: HashMap::new(),
1140            indexes_by_table_id: HashMap::new(),
1141            system_table_by_name: HashMap::new(),
1142            view_by_name: HashMap::new(),
1143            view_by_id: HashMap::new(),
1144            function_registry: FunctionRegistry::default(),
1145            function_by_name: HashMap::new(),
1146            function_by_id: HashMap::new(),
1147            connection_by_name: HashMap::new(),
1148            connection_by_id: HashMap::new(),
1149            secret_by_name: HashMap::new(),
1150            secret_by_id: HashMap::new(),
1151            _secret_source_ref: HashMap::new(),
1152            _secret_sink_ref: HashMap::new(),
1153            connection_source_ref: HashMap::new(),
1154            connection_sink_ref: HashMap::new(),
1155            subscription_by_name: HashMap::new(),
1156            subscription_by_id: HashMap::new(),
1157        }
1158    }
1159}
1160
1161#[cfg(test)]
1162mod tests {
1163    use risingwave_pb::catalog::PbSchema;
1164
1165    use super::SchemaCatalog;
1166
1167    #[test]
1168    fn test_drop_missing_relation_is_idempotent() {
1169        let mut schema = SchemaCatalog::from(&PbSchema::default());
1170        schema.drop_index(1.into());
1171        schema.drop_source(2.into());
1172    }
1173}