1pub mod information_schema;
16mod memory_table;
17pub mod numbers_table_provider;
18pub mod pg_catalog;
19pub mod predicate;
20pub mod semantic_graph;
21mod utils;
22
23use std::collections::HashMap;
24use std::sync::Arc;
25
26use common_error::ext::BoxedError;
27use common_recordbatch::{RecordBatchStreamWrapper, SendableRecordBatchStream};
28use common_telemetry::tracing::Span;
29use datafusion::physical_plan::ExecutionPlan;
30use datatypes::schema::SchemaRef;
31use futures_util::StreamExt;
32use snafu::ResultExt;
33use store_api::data_source::DataSource;
34use store_api::storage::ScanRequest;
35use table::error::{SchemaConversionSnafu, TablesRecordBatchSnafu};
36use table::metadata::{FilterPushDownType, TableId, TableInfoBuilder, TableMetaBuilder, TableType};
37use table::requests::TableOptions;
38use table::{Table, TableRef};
39
40use crate::error::Result;
41
42pub trait SystemSchemaProvider {
43 fn tables(&self) -> &HashMap<String, TableRef>;
45
46 fn table(&self, name: &str) -> Option<TableRef> {
48 self.tables().get(name).cloned()
49 }
50
51 fn table_names(&self) -> Vec<String> {
53 let mut tables = self.tables().values().clone().collect::<Vec<_>>();
54
55 tables.sort_by(|t1, t2| {
56 t1.table_info()
57 .table_id()
58 .partial_cmp(&t2.table_info().table_id())
59 .unwrap()
60 });
61 tables
62 .into_iter()
63 .map(|t| t.table_info().name.clone())
64 .collect()
65 }
66}
67
68trait SystemSchemaProviderInner {
69 fn catalog_name(&self) -> &str;
70 fn schema_name() -> &'static str;
71 fn build_table(&self, name: &str) -> Option<TableRef> {
72 self.system_table(name).map(|table| {
73 build_system_table(
74 self.catalog_name().to_string(),
75 Self::schema_name(),
76 table,
77 TableOptions::default(),
78 )
79 })
80 }
81 fn system_table(&self, name: &str) -> Option<SystemTableRef>;
82}
83
84fn build_system_table(
85 catalog_name: String,
86 schema_name: &str,
87 table: SystemTableRef,
88 options: TableOptions,
89) -> TableRef {
90 let table_meta = TableMetaBuilder::empty()
91 .schema(table.schema())
92 .primary_key_indices(vec![])
93 .next_column_id(0)
94 .options(options)
95 .build()
96 .unwrap();
97 let table_info = TableInfoBuilder::default()
98 .table_id(table.table_id())
99 .name(table.table_name().to_string())
100 .catalog_name(catalog_name)
101 .schema_name(schema_name.to_string())
102 .meta(table_meta)
103 .table_type(table.table_type())
104 .build()
105 .unwrap();
106 Arc::new(Table::new(
107 Arc::new(table_info),
108 FilterPushDownType::Inexact,
109 Arc::new(SystemTableDataSource::new(table)),
110 ))
111}
112
113pub trait SystemTable {
114 fn table_id(&self) -> TableId;
115
116 fn table_name(&self) -> &'static str;
117
118 fn schema(&self) -> SchemaRef;
119
120 fn to_stream(&self, request: ScanRequest) -> Result<SendableRecordBatchStream>;
121
122 fn scan_plan(&self, _request: ScanRequest) -> Result<Option<Arc<dyn ExecutionPlan>>> {
123 Ok(None)
124 }
125
126 fn table_type(&self) -> TableType {
127 TableType::Temporary
128 }
129}
130
131pub type SystemTableRef = Arc<dyn SystemTable + Send + Sync>;
132
133struct SystemTableDataSource {
134 table: SystemTableRef,
135}
136
137impl SystemTableDataSource {
138 fn new(table: SystemTableRef) -> Self {
139 Self { table }
140 }
141
142 fn try_project(&self, projection: &[usize]) -> std::result::Result<SchemaRef, BoxedError> {
143 let schema = self
144 .table
145 .schema()
146 .try_project(projection)
147 .context(SchemaConversionSnafu)
148 .map_err(BoxedError::new)?;
149 Ok(Arc::new(schema))
150 }
151}
152
153impl DataSource for SystemTableDataSource {
154 fn get_stream(
155 &self,
156 request: ScanRequest,
157 ) -> std::result::Result<SendableRecordBatchStream, BoxedError> {
158 let projection = request.projection.clone();
159 let projected_schema = match request.projection.as_ref() {
160 Some(projection) => self.try_project(projection)?,
161 None => self.table.schema(),
162 };
163
164 let stream = self
165 .table
166 .to_stream(request)
167 .map_err(BoxedError::new)
168 .context(TablesRecordBatchSnafu)
169 .map_err(BoxedError::new)?
170 .map(move |batch| match (&projection, batch) {
171 (Some(p), Ok(b)) if b.num_columns() != p.len() => b.try_project(p),
175 (_, res) => res,
176 });
177
178 let stream = RecordBatchStreamWrapper {
179 schema: projected_schema,
180 stream: Box::pin(stream),
181 output_ordering: None,
182 metrics: Default::default(),
183 span: Span::current(),
184 };
185
186 Ok(Box::pin(stream))
187 }
188
189 fn get_physical_plan(
190 &self,
191 request: ScanRequest,
192 ) -> std::result::Result<Option<Arc<dyn ExecutionPlan>>, BoxedError> {
193 self.table
194 .scan_plan(request)
195 .map_err(BoxedError::new)
196 .context(TablesRecordBatchSnafu)
197 .map_err(BoxedError::new)
198 }
199}