From ff473d84fcdf2860e8832494096ade00a7bdb73f Mon Sep 17 00:00:00 2001 From: J0hn50n133 <0xjohnsonlee@gmail.com> Date: Mon, 22 Jul 2024 18:46:03 +0800 Subject: [PATCH 01/14] feat: add function 'pg_catalog.pg_table_is_visible'q --- .../function/src/scalars/expression/unary.rs | 2 - src/common/function/src/system.rs | 3 + src/common/function/src/system/pg_catalog.rs | 36 ++++++++++ .../src/system/pg_catalog/table_is_visible.rs | 72 +++++++++++++++++++ 4 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 src/common/function/src/system/pg_catalog.rs create mode 100644 src/common/function/src/system/pg_catalog/table_is_visible.rs diff --git a/src/common/function/src/scalars/expression/unary.rs b/src/common/function/src/scalars/expression/unary.rs index 3927adb327a9..533705feb1b6 100644 --- a/src/common/function/src/scalars/expression/unary.rs +++ b/src/common/function/src/scalars/expression/unary.rs @@ -19,8 +19,6 @@ use snafu::ResultExt; use crate::scalars::expression::ctx::EvalContext; -/// TODO: remove the allow_unused when it's used. -#[allow(unused)] pub fn scalar_unary_op( l: &VectorRef, f: F, diff --git a/src/common/function/src/system.rs b/src/common/function/src/system.rs index b50dbfba07b6..9b90004f4a8d 100644 --- a/src/common/function/src/system.rs +++ b/src/common/function/src/system.rs @@ -14,6 +14,7 @@ mod build; mod database; +mod pg_catalog; mod procedure_state; mod timezone; mod version; @@ -22,6 +23,7 @@ use std::sync::Arc; use build::BuildFunction; use database::DatabaseFunction; +use pg_catalog::PGCatalogFunction; use procedure_state::ProcedureStateFunction; use timezone::TimezoneFunction; use version::VersionFunction; @@ -37,5 +39,6 @@ impl SystemFunction { registry.register(Arc::new(DatabaseFunction)); registry.register(Arc::new(TimezoneFunction)); registry.register(Arc::new(ProcedureStateFunction)); + PGCatalogFunction::register(registry); } } diff --git a/src/common/function/src/system/pg_catalog.rs b/src/common/function/src/system/pg_catalog.rs new file mode 100644 index 000000000000..4e7ed7467743 --- /dev/null +++ b/src/common/function/src/system/pg_catalog.rs @@ -0,0 +1,36 @@ +// Copyright 2023 Greptime Team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::sync::Arc; + +use table_is_visible::PGTableIsVisbleFunction; + +use crate::function_registry::FunctionRegistry; + +mod table_is_visible; + +#[macro_export] +macro_rules! pg_catalog_func_fullname { + ($name:literal) => { + concat!("pg_catalog.", $name) + }; +} + +pub(super) struct PGCatalogFunction; + +impl PGCatalogFunction { + pub fn register(registry: &FunctionRegistry) { + registry.register(Arc::new(PGTableIsVisbleFunction)) + } +} diff --git a/src/common/function/src/system/pg_catalog/table_is_visible.rs b/src/common/function/src/system/pg_catalog/table_is_visible.rs new file mode 100644 index 000000000000..6f173b93d641 --- /dev/null +++ b/src/common/function/src/system/pg_catalog/table_is_visible.rs @@ -0,0 +1,72 @@ +// Copyright 2023 Greptime Team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::fmt::{self}; +use std::sync::Arc; + +use common_query::error::Result; +use common_query::prelude::{Signature, Volatility}; +use datatypes::prelude::{ConcreteDataType, DataType, VectorRef}; +use datatypes::types::LogicalPrimitiveType; +use datatypes::with_match_primitive_type_id; +use num_traits::AsPrimitive; + +use crate::function::{Function, FunctionContext}; +use crate::scalars::expression::{scalar_unary_op, EvalContext}; + +#[derive(Clone, Debug, Default)] +pub struct PGTableIsVisbleFunction; + +const NAME: &str = crate::pg_catalog_func_fullname!("pg_table_is_visible"); + +impl fmt::Display for PGTableIsVisbleFunction { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, crate::pg_catalog_func_fullname!("PG_TABLE_IS_VISIBLE")) + } +} + +impl Function for PGTableIsVisbleFunction { + fn name(&self) -> &str { + NAME + } + + fn return_type(&self, _input_types: &[ConcreteDataType]) -> Result { + Ok(ConcreteDataType::boolean_datatype()) + } + + fn signature(&self) -> Signature { + Signature::uniform( + 1, + vec![ConcreteDataType::uint32_datatype()], + Volatility::Immutable, + ) + } + + fn eval(&self, _func_ctx: FunctionContext, columns: &[VectorRef]) -> Result { + with_match_primitive_type_id!(columns[0].data_type().logical_type_id(), |$T| { + let col = scalar_unary_op::<<$T as LogicalPrimitiveType>::Native, bool, _>(&columns[0], pg_table_is_visible, &mut EvalContext::default())?; + Ok(Arc::new(col)) + }, { + unreachable!() + }) + } +} + +fn pg_table_is_visible(table_oid: Option, _ctx: &mut EvalContext) -> Option +where + I: AsPrimitive, +{ + // There is no table visibility in greptime, so we always return true + table_oid.map(|_| true) +} From 846a1d120e9354b0b5ca846296a3437086d18412 Mon Sep 17 00:00:00 2001 From: J0hn50n133 <0xjohnsonlee@gmail.com> Date: Wed, 24 Jul 2024 19:11:16 +0800 Subject: [PATCH 02/14] feat: add 'pg_class' and 'pg_namespace', now we can run '\d' and '\dt'! * refactor: move memory_table::tables to utils::tables --- src/common/catalog/src/consts.rs | 1 + src/common/function/src/system/pg_catalog.rs | 9 ++- .../src/system/pg_catalog/pg_get_userbyid.rs | 72 +++++++++++++++++++ 3 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 src/common/function/src/system/pg_catalog/pg_get_userbyid.rs diff --git a/src/common/catalog/src/consts.rs b/src/common/catalog/src/consts.rs index ac1b4de5bee8..6020a4bef805 100644 --- a/src/common/catalog/src/consts.rs +++ b/src/common/catalog/src/consts.rs @@ -103,6 +103,7 @@ pub const INFORMATION_SCHEMA_FLOW_TABLE_ID: u32 = 33; /// ----- Begin of pg_catalog tables ----- pub const PG_CATALOG_PG_CLASS_TABLE_ID: u32 = 256; pub const PG_CATALOG_PG_TYPE_TABLE_ID: u32 = 257; +pub const PG_CATALOG_PG_NAMESPACE_TABLE_ID: u32 = 258; /// ----- End of pg_catalog tables ----- pub const MITO_ENGINE: &str = "mito"; diff --git a/src/common/function/src/system/pg_catalog.rs b/src/common/function/src/system/pg_catalog.rs index 4e7ed7467743..94fef5970ceb 100644 --- a/src/common/function/src/system/pg_catalog.rs +++ b/src/common/function/src/system/pg_catalog.rs @@ -12,14 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. +mod pg_get_userbyid; +mod table_is_visible; + use std::sync::Arc; +use pg_get_userbyid::PGGetUserByIdFunction; use table_is_visible::PGTableIsVisbleFunction; use crate::function_registry::FunctionRegistry; -mod table_is_visible; - #[macro_export] macro_rules! pg_catalog_func_fullname { ($name:literal) => { @@ -31,6 +33,7 @@ pub(super) struct PGCatalogFunction; impl PGCatalogFunction { pub fn register(registry: &FunctionRegistry) { - registry.register(Arc::new(PGTableIsVisbleFunction)) + registry.register(Arc::new(PGTableIsVisbleFunction)); + registry.register(Arc::new(PGGetUserByIdFunction)); } } diff --git a/src/common/function/src/system/pg_catalog/pg_get_userbyid.rs b/src/common/function/src/system/pg_catalog/pg_get_userbyid.rs new file mode 100644 index 000000000000..1ab5a269c383 --- /dev/null +++ b/src/common/function/src/system/pg_catalog/pg_get_userbyid.rs @@ -0,0 +1,72 @@ +// Copyright 2023 Greptime Team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::fmt::{self}; +use std::sync::Arc; + +use common_query::error::Result; +use common_query::prelude::{Signature, Volatility}; +use datatypes::prelude::{ConcreteDataType, DataType, VectorRef}; +use datatypes::types::LogicalPrimitiveType; +use datatypes::with_match_primitive_type_id; +use num_traits::AsPrimitive; + +use crate::function::{Function, FunctionContext}; +use crate::scalars::expression::{scalar_unary_op, EvalContext}; + +#[derive(Clone, Debug, Default)] +pub struct PGGetUserByIdFunction; + +const NAME: &str = crate::pg_catalog_func_fullname!("pg_get_userbyid"); + +impl fmt::Display for PGGetUserByIdFunction { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, crate::pg_catalog_func_fullname!("PG_GET_USERBYID")) + } +} + +impl Function for PGGetUserByIdFunction { + fn name(&self) -> &str { + NAME + } + + fn return_type(&self, _input_types: &[ConcreteDataType]) -> Result { + Ok(ConcreteDataType::string_datatype()) + } + + fn signature(&self) -> Signature { + Signature::uniform( + 1, + vec![ConcreteDataType::uint32_datatype()], + Volatility::Immutable, + ) + } + + fn eval(&self, _func_ctx: FunctionContext, columns: &[VectorRef]) -> Result { + with_match_primitive_type_id!(columns[0].data_type().logical_type_id(), |$T| { + let col = scalar_unary_op::<<$T as LogicalPrimitiveType>::Native, String, _>(&columns[0], pg_get_user_by_id, &mut EvalContext::default())?; + Ok(Arc::new(col)) + }, { + unreachable!() + }) + } +} + +fn pg_get_user_by_id(table_oid: Option, _ctx: &mut EvalContext) -> Option +where + I: AsPrimitive, +{ + // There is no user authentication in greptime open source core, so we always return "" + table_oid.map(|_| "".to_string()) +} From 5d6e92b6071b54087d31eaea57e5b0e6f8dde118 Mon Sep 17 00:00:00 2001 From: J0hn50n133 <0xjohnsonlee@gmail.com> Date: Wed, 24 Jul 2024 21:07:54 +0800 Subject: [PATCH 03/14] refactor: move out predicate to system_schema to reuse it --- src/catalog/src/system_schema.rs | 2 + .../src/system_schema/information_schema.rs | 9 +- .../information_memory_table.rs | 2 +- src/catalog/src/system_schema/memory_table.rs | 1 - src/catalog/src/system_schema/pg_catalog.rs | 23 +- .../pg_catalog/pg_catalog_memory_table.rs | 2 +- .../src/system_schema/pg_catalog/pg_class.rs | 225 ++++++++++++++++++ .../system_schema/pg_catalog/pg_namespace.rs | 181 ++++++++++++++ .../{information_schema => }/predicate.rs | 2 +- .../{information_schema => }/utils.rs | 2 + .../{memory_table => utils}/tables.rs | 0 11 files changed, 439 insertions(+), 10 deletions(-) create mode 100644 src/catalog/src/system_schema/pg_catalog/pg_class.rs create mode 100644 src/catalog/src/system_schema/pg_catalog/pg_namespace.rs rename src/catalog/src/system_schema/{information_schema => }/predicate.rs (99%) rename src/catalog/src/system_schema/{information_schema => }/utils.rs (99%) rename src/catalog/src/system_schema/{memory_table => utils}/tables.rs (100%) diff --git a/src/catalog/src/system_schema.rs b/src/catalog/src/system_schema.rs index d804d9c97ca4..95d6daa4182a 100644 --- a/src/catalog/src/system_schema.rs +++ b/src/catalog/src/system_schema.rs @@ -15,6 +15,8 @@ pub mod information_schema; mod memory_table; pub mod pg_catalog; +mod predicate; +mod utils; use std::collections::HashMap; use std::sync::Arc; diff --git a/src/catalog/src/system_schema/information_schema.rs b/src/catalog/src/system_schema/information_schema.rs index bc4f3167c78d..3982931a71a4 100644 --- a/src/catalog/src/system_schema/information_schema.rs +++ b/src/catalog/src/system_schema/information_schema.rs @@ -18,14 +18,12 @@ pub mod flows; mod information_memory_table; pub mod key_column_usage; mod partitions; -mod predicate; mod region_peers; mod runtime_metrics; pub mod schemata; mod table_constraints; mod table_names; pub mod tables; -pub(crate) mod utils; mod views; use std::collections::HashMap; @@ -37,7 +35,6 @@ use common_recordbatch::SendableRecordBatchStream; use datatypes::schema::SchemaRef; use lazy_static::lazy_static; use paste::paste; -pub(crate) use predicate::Predicates; use store_api::storage::{ScanRequest, TableId}; use table::metadata::TableType; use table::TableRef; @@ -45,6 +42,12 @@ pub use table_names::*; use views::InformationSchemaViews; use self::columns::InformationSchemaColumns; +pub(crate) use crate::system_schema::predicate::Predicates; +// TODO(J0HN150N133): re-export to provide compatibility for legacy `information_schema` code. +pub(crate) mod utils { + pub use crate::system_schema::utils::*; +} + use super::{SystemSchemaProviderInner, SystemTable, SystemTableRef}; use crate::error::Result; use crate::system_schema::information_schema::cluster_info::InformationSchemaClusterInfo; diff --git a/src/catalog/src/system_schema/information_schema/information_memory_table.rs b/src/catalog/src/system_schema/information_schema/information_memory_table.rs index e6459fbe8ab5..bd7aba10a5f3 100644 --- a/src/catalog/src/system_schema/information_schema/information_memory_table.rs +++ b/src/catalog/src/system_schema/information_schema/information_memory_table.rs @@ -19,7 +19,7 @@ use datatypes::schema::{Schema, SchemaRef}; use datatypes::vectors::{Int64Vector, StringVector, VectorRef}; use super::table_names::*; -use crate::system_schema::memory_table::tables::{ +use crate::system_schema::utils::tables::{ bigint_column, datetime_column, string_column, string_columns, }; diff --git a/src/catalog/src/system_schema/memory_table.rs b/src/catalog/src/system_schema/memory_table.rs index 92caa641a9d0..dd026010bb44 100644 --- a/src/catalog/src/system_schema/memory_table.rs +++ b/src/catalog/src/system_schema/memory_table.rs @@ -13,7 +13,6 @@ // limitations under the License. mod table_columns; -pub mod tables; use std::sync::Arc; diff --git a/src/catalog/src/system_schema/pg_catalog.rs b/src/catalog/src/system_schema/pg_catalog.rs index 2b2ca876642f..51c9b426ac12 100644 --- a/src/catalog/src/system_schema/pg_catalog.rs +++ b/src/catalog/src/system_schema/pg_catalog.rs @@ -13,6 +13,8 @@ // limitations under the License. mod pg_catalog_memory_table; +mod pg_class; +mod pg_namespace; mod table_names; use std::collections::HashMap; @@ -23,11 +25,13 @@ use datatypes::schema::ColumnSchema; use lazy_static::lazy_static; use paste::paste; use pg_catalog_memory_table::get_schema_columns; +use pg_class::PGClass; +use pg_namespace::PGNamespace; use table::TableRef; pub use table_names::*; -use super::memory_table::tables::u32_column; use super::memory_table::MemoryTable; +use super::utils::tables::u32_column; use super::{SystemSchemaProvider, SystemSchemaProviderInner, SystemTableRef}; use crate::CatalogManager; @@ -46,7 +50,7 @@ fn oid_column() -> ColumnSchema { /// [`PGCatalogProvider`] is the provider for a schema named `pg_catalog`, it is not a catalog. pub struct PGCatalogProvider { catalog_name: String, - _catalog_manager: Weak, + catalog_manager: Weak, tables: HashMap, } @@ -79,7 +83,7 @@ impl PGCatalogProvider { pub fn new(catalog_name: String, catalog_manager: Weak) -> Self { let mut provider = Self { catalog_name, - _catalog_manager: catalog_manager, + catalog_manager, tables: HashMap::new(), }; provider.build_tables(); @@ -93,6 +97,11 @@ impl PGCatalogProvider { for name in MEMORY_TABLES.iter() { tables.insert(name.to_string(), self.build_table(name).expect(name)); } + tables.insert( + PG_NAMESPACE.to_string(), + self.build_table(PG_NAMESPACE).unwrap(), + ); + tables.insert(PG_CLASS.to_string(), self.build_table(PG_CLASS).unwrap()); self.tables = tables; } } @@ -105,6 +114,14 @@ impl SystemSchemaProviderInner for PGCatalogProvider { fn system_table(&self, name: &str) -> Option { match name { table_names::PG_TYPE => setup_memory_table!(PG_TYPE), + table_names::PG_NAMESPACE => Some(Arc::new(PGNamespace::new( + self.catalog_name.clone(), + self.catalog_manager.clone(), + ))), + table_names::PG_CLASS => Some(Arc::new(PGClass::new( + self.catalog_name.clone(), + self.catalog_manager.clone(), + ))), _ => None, } } diff --git a/src/catalog/src/system_schema/pg_catalog/pg_catalog_memory_table.rs b/src/catalog/src/system_schema/pg_catalog/pg_catalog_memory_table.rs index 53be0c50dd16..cdc15329c16a 100644 --- a/src/catalog/src/system_schema/pg_catalog/pg_catalog_memory_table.rs +++ b/src/catalog/src/system_schema/pg_catalog/pg_catalog_memory_table.rs @@ -20,7 +20,7 @@ use datatypes::vectors::{Int16Vector, StringVector, UInt32Vector, VectorRef}; use super::oid_column; use super::table_names::PG_TYPE; use crate::memory_table_cols; -use crate::system_schema::memory_table::tables::{i16_column, string_column}; +use crate::system_schema::utils::tables::{i16_column, string_column}; fn pg_type_schema_columns() -> (Vec, Vec) { // TODO(j0hn50n133): acquire this information from `DataType` instead of hardcoding it to avoid regression. diff --git a/src/catalog/src/system_schema/pg_catalog/pg_class.rs b/src/catalog/src/system_schema/pg_catalog/pg_class.rs new file mode 100644 index 000000000000..14fff4eb25f9 --- /dev/null +++ b/src/catalog/src/system_schema/pg_catalog/pg_class.rs @@ -0,0 +1,225 @@ +// Copyright 2023 Greptime Team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::sync::{Arc, Weak}; + +use arrow_schema::SchemaRef as ArrowSchemaRef; +use common_catalog::consts::PG_CATALOG_PG_CLASS_TABLE_ID; +use common_error::ext::BoxedError; +use common_recordbatch::adapter::RecordBatchStreamAdapter; +use common_recordbatch::{DfSendableRecordBatchStream, RecordBatch}; +use datafusion::execution::TaskContext; +use datafusion::physical_plan::stream::RecordBatchStreamAdapter as DfRecordBatchStreamAdapter; +use datafusion::physical_plan::streaming::PartitionStream as DfPartitionStream; +use datatypes::scalars::ScalarVectorBuilder; +use datatypes::schema::{Schema, SchemaRef}; +use datatypes::vectors::{StringVectorBuilder, UInt32VectorBuilder, VectorRef}; +use futures::TryStreamExt; +use snafu::{OptionExt, ResultExt}; +use store_api::storage::ScanRequest; +use table::metadata::TableType; + +use super::{OID_COLUMN_NAME, PG_CLASS}; +use crate::error::{ + CreateRecordBatchSnafu, InternalSnafu, Result, UpgradeWeakCatalogManagerRefSnafu, +}; +use crate::system_schema::utils::tables::{string_column, u32_column}; +use crate::system_schema::SystemTable; +use crate::CatalogManager; + +// === column name === +pub const RELNAME: &str = "relname"; +pub const RELNAMESPACE: &str = "relnamespace"; +pub const RELKIND: &str = "relkind"; +pub const RELOWNER: &str = "relowner"; + +// === enum value of relkind === +pub const RELKIND_TABLE: &str = "r"; +pub const RELKIND_VIEW: &str = "v"; + +/// The initial capacity of the vector builders. +const INIT_CAPACITY: usize = 42; +/// The dummy owner id for the namespace. +const DUMMY_OWNER_ID: u32 = 0; + +/// The `pg_catalog.pg_class` table implementation. +pub(super) struct PGClass { + schema: SchemaRef, + catalog_name: String, + catalog_manager: Weak, +} + +impl PGClass { + pub(super) fn new(catalog_name: String, catalog_manager: Weak) -> Self { + Self { + schema: Self::schema(), + catalog_name, + catalog_manager, + } + } + + fn schema() -> SchemaRef { + Arc::new(Schema::new(vec![ + u32_column(OID_COLUMN_NAME), + string_column(RELNAME), + string_column(RELNAMESPACE), + string_column(RELKIND), + u32_column(RELOWNER), + ])) + } + + fn builder(&self) -> PGClassBuilder { + PGClassBuilder::new( + self.schema.clone(), + self.catalog_name.clone(), + self.catalog_manager.clone(), + ) + } +} + +impl SystemTable for PGClass { + fn table_id(&self) -> table::metadata::TableId { + PG_CATALOG_PG_CLASS_TABLE_ID + } + + fn table_name(&self) -> &'static str { + PG_CLASS + } + + fn schema(&self) -> SchemaRef { + self.schema.clone() + } + + fn to_stream( + &self, + request: ScanRequest, + ) -> Result { + let schema = self.schema.arrow_schema().clone(); + let mut builder = self.builder(); + let stream = Box::pin(DfRecordBatchStreamAdapter::new( + schema, + futures::stream::once(async move { + builder + .make_class(Some(request)) + .await + .map(|x| x.into_df_record_batch()) + .map_err(Into::into) + }), + )); + Ok(Box::pin( + RecordBatchStreamAdapter::try_new(stream) + .map_err(BoxedError::new) + .context(InternalSnafu)?, + )) + } +} + +impl DfPartitionStream for PGClass { + fn schema(&self) -> &ArrowSchemaRef { + self.schema.arrow_schema() + } + + fn execute(&self, _: Arc) -> DfSendableRecordBatchStream { + let schema = self.schema.arrow_schema().clone(); + let mut builder = self.builder(); + Box::pin(DfRecordBatchStreamAdapter::new( + schema, + futures::stream::once(async move { + builder + .make_class(None) + .await + .map(|x| x.into_df_record_batch()) + .map_err(Into::into) + }), + )) + } +} + +/// Builds the `pg_catalog.pg_class` table row by row +/// `relowner` is always the [`DUMMY_OWNER_ID`] cuz we don't have user +struct PGClassBuilder { + schema: SchemaRef, + catalog_name: String, + catalog_manager: Weak, + + oid: UInt32VectorBuilder, + relname: StringVectorBuilder, + relnamespace: StringVectorBuilder, + relkind: StringVectorBuilder, + relowner: UInt32VectorBuilder, +} + +impl PGClassBuilder { + fn new( + schema: SchemaRef, + catalog_name: String, + catalog_manager: Weak, + ) -> Self { + Self { + schema, + catalog_name, + catalog_manager, + + oid: UInt32VectorBuilder::with_capacity(INIT_CAPACITY), + relname: StringVectorBuilder::with_capacity(INIT_CAPACITY), + relnamespace: StringVectorBuilder::with_capacity(INIT_CAPACITY), + relkind: StringVectorBuilder::with_capacity(INIT_CAPACITY), + relowner: UInt32VectorBuilder::with_capacity(INIT_CAPACITY), + } + } + + async fn make_class(&mut self, _request: Option) -> Result { + let catalog_name = self.catalog_name.clone(); + let catalog_manager = self + .catalog_manager + .upgrade() + .context(UpgradeWeakCatalogManagerRefSnafu)?; + for schema_name in catalog_manager.schema_names(&catalog_name).await? { + let mut stream = catalog_manager.tables(&catalog_name, &schema_name); + while let Some(table) = stream.try_next().await? { + let table_info = table.table_info(); + self.add_class( + table_info.table_id(), + &schema_name, + &table_info.name, + if table_info.table_type == TableType::View { + RELKIND_VIEW + } else { + RELKIND_TABLE + }, + ); + } + } + self.finish() + } + + fn add_class(&mut self, oid: u32, schema: &str, table: &str, kind: &str) { + self.oid.push(Some(oid)); + self.relnamespace.push(Some(schema)); + self.relname.push(Some(table)); + self.relkind.push(Some(kind)); + self.relowner.push(Some(DUMMY_OWNER_ID)); + } + + fn finish(&mut self) -> Result { + let columns: Vec = vec![ + Arc::new(self.oid.finish()), + Arc::new(self.relname.finish()), + Arc::new(self.relnamespace.finish()), + Arc::new(self.relkind.finish()), + Arc::new(self.relowner.finish()), + ]; + RecordBatch::new(self.schema.clone(), columns).context(CreateRecordBatchSnafu) + } +} diff --git a/src/catalog/src/system_schema/pg_catalog/pg_namespace.rs b/src/catalog/src/system_schema/pg_catalog/pg_namespace.rs new file mode 100644 index 000000000000..93d01ad83b77 --- /dev/null +++ b/src/catalog/src/system_schema/pg_catalog/pg_namespace.rs @@ -0,0 +1,181 @@ +// Copyright 2023 Greptim Team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::sync::{Arc, Weak}; + +use arrow_schema::SchemaRef as ArrowSchemaRef; +use common_catalog::consts::PG_CATALOG_PG_NAMESPACE_TABLE_ID; +use common_error::ext::BoxedError; +use common_recordbatch::adapter::RecordBatchStreamAdapter; +use common_recordbatch::{DfSendableRecordBatchStream, RecordBatch, SendableRecordBatchStream}; +use datafusion::execution::TaskContext; +use datafusion::physical_plan::stream::RecordBatchStreamAdapter as DfRecordBatchStreamAdapter; +use datafusion::physical_plan::streaming::PartitionStream as DfPartitionStream; +use datatypes::scalars::ScalarVectorBuilder; +use datatypes::schema::{Schema, SchemaRef}; +use datatypes::vectors::{StringVectorBuilder, VectorRef}; +use snafu::{OptionExt, ResultExt}; +use store_api::storage::ScanRequest; + +use super::{OID_COLUMN_NAME, PG_NAMESPACE}; +use crate::error::{ + CreateRecordBatchSnafu, InternalSnafu, Result, UpgradeWeakCatalogManagerRefSnafu, +}; +use crate::system_schema::utils::tables::string_column; +use crate::system_schema::SystemTable; +use crate::CatalogManager; + +/// The `pg_catalog.pg_namespace` table implementation. +/// namespace is a schema in greptime + +const NSPNAME: &str = "nspname"; +const INIT_CAPACITY: usize = 42; + +pub(super) struct PGNamespace { + schema: SchemaRef, + catalog_name: String, + catalog_manager: Weak, +} + +impl PGNamespace { + pub(super) fn new(catalog_name: String, catalog_manager: Weak) -> Self { + Self { + schema: Self::schema(), + catalog_name, + catalog_manager, + } + } + + fn schema() -> SchemaRef { + Arc::new(Schema::new(vec![ + // TODO(J0HN50N133): we do not have a numeric schema id, use schema name as a workround. Use a proper schema id once we have it. + string_column(OID_COLUMN_NAME), + string_column(NSPNAME), + ])) + } + + fn builder(&self) -> PGNamespaceBuilder { + PGNamespaceBuilder::new( + self.schema.clone(), + self.catalog_name.clone(), + self.catalog_manager.clone(), + ) + } +} + +impl SystemTable for PGNamespace { + fn schema(&self) -> SchemaRef { + self.schema.clone() + } + + fn table_id(&self) -> table::metadata::TableId { + PG_CATALOG_PG_NAMESPACE_TABLE_ID + } + + fn table_name(&self) -> &'static str { + PG_NAMESPACE + } + + fn to_stream(&self, request: ScanRequest) -> Result { + let schema = self.schema.arrow_schema().clone(); + let mut builder = self.builder(); + let stream = Box::pin(DfRecordBatchStreamAdapter::new( + schema, + futures::stream::once(async move { + builder + .make_namespace(Some(request)) + .await + .map(|x| x.into_df_record_batch()) + .map_err(Into::into) + }), + )); + Ok(Box::pin( + RecordBatchStreamAdapter::try_new(stream) + .map_err(BoxedError::new) + .context(InternalSnafu)?, + )) + } +} + +impl DfPartitionStream for PGNamespace { + fn schema(&self) -> &ArrowSchemaRef { + self.schema.arrow_schema() + } + + fn execute(&self, _: Arc) -> DfSendableRecordBatchStream { + let schema = self.schema.arrow_schema().clone(); + let mut builder = self.builder(); + Box::pin(DfRecordBatchStreamAdapter::new( + schema, + futures::stream::once(async move { + builder + .make_namespace(None) + .await + .map(|x| x.into_df_record_batch()) + .map_err(Into::into) + }), + )) + } +} + +/// Builds the `pg_catalog.pg_namespace` table row by row +/// `oid` use schema name as a workaround since we don't have numeric schema id. +/// `nspname` is the schema name. +struct PGNamespaceBuilder { + schema: SchemaRef, + catalog_name: String, + catalog_manager: Weak, + + oid: StringVectorBuilder, + nspname: StringVectorBuilder, +} + +impl PGNamespaceBuilder { + fn new( + schema: SchemaRef, + catalog_name: String, + catalog_manager: Weak, + ) -> Self { + Self { + schema, + catalog_name, + catalog_manager, + oid: StringVectorBuilder::with_capacity(INIT_CAPACITY), + nspname: StringVectorBuilder::with_capacity(INIT_CAPACITY), + } + } + + /// Construct the `pg_catalog.pg_namespace` virtual table + async fn make_namespace(&mut self, _request: Option) -> Result { + let catalog_name = self.catalog_name.clone(); + let catalog_manager = self + .catalog_manager + .upgrade() + .context(UpgradeWeakCatalogManagerRefSnafu)?; + for schema_name in catalog_manager.schema_names(&catalog_name).await? { + self.add_namespace(&schema_name); + } + self.finish() + } + fn finish(&mut self) -> Result { + let columns: Vec = + vec![Arc::new(self.oid.finish()), Arc::new(self.nspname.finish())]; + RecordBatch::new(self.schema.clone(), columns).context(CreateRecordBatchSnafu) + } + + fn add_namespace(&mut self, schema_name: &str) { + self.oid.push(Some(schema_name)); + self.nspname.push(Some(schema_name)); + } +} diff --git a/src/catalog/src/system_schema/information_schema/predicate.rs b/src/catalog/src/system_schema/predicate.rs similarity index 99% rename from src/catalog/src/system_schema/information_schema/predicate.rs rename to src/catalog/src/system_schema/predicate.rs index 8bec0d3d12f5..3bf04124c32d 100644 --- a/src/catalog/src/system_schema/information_schema/predicate.rs +++ b/src/catalog/src/system_schema/predicate.rs @@ -25,7 +25,7 @@ type ColumnName = String; /// we only support these simple predicates currently. /// TODO(dennis): supports more predicate types. #[derive(Clone, PartialEq, Eq, Debug)] -enum Predicate { +pub(crate) enum Predicate { Eq(ColumnName, Value), Like(ColumnName, String, bool), NotEq(ColumnName, Value), diff --git a/src/catalog/src/system_schema/information_schema/utils.rs b/src/catalog/src/system_schema/utils.rs similarity index 99% rename from src/catalog/src/system_schema/information_schema/utils.rs rename to src/catalog/src/system_schema/utils.rs index 6a3594718203..2a2e89516a6f 100644 --- a/src/catalog/src/system_schema/information_schema/utils.rs +++ b/src/catalog/src/system_schema/utils.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +pub mod tables; + use std::sync::{Arc, Weak}; use common_config::Mode; diff --git a/src/catalog/src/system_schema/memory_table/tables.rs b/src/catalog/src/system_schema/utils/tables.rs similarity index 100% rename from src/catalog/src/system_schema/memory_table/tables.rs rename to src/catalog/src/system_schema/utils/tables.rs From 43e9fd5db0a4f5d2f59adef6c78f0c25ee77ccc2 Mon Sep 17 00:00:00 2001 From: J0hn50n133 <0xjohnsonlee@gmail.com> Date: Wed, 24 Jul 2024 21:23:32 +0800 Subject: [PATCH 04/14] feat: predicates pushdown --- .../src/system_schema/pg_catalog/pg_class.rs | 27 +++++++++++++++++-- .../system_schema/pg_catalog/pg_namespace.rs | 16 ++++++++--- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/catalog/src/system_schema/pg_catalog/pg_class.rs b/src/catalog/src/system_schema/pg_catalog/pg_class.rs index 14fff4eb25f9..e9978c41a099 100644 --- a/src/catalog/src/system_schema/pg_catalog/pg_class.rs +++ b/src/catalog/src/system_schema/pg_catalog/pg_class.rs @@ -24,6 +24,7 @@ use datafusion::physical_plan::stream::RecordBatchStreamAdapter as DfRecordBatch use datafusion::physical_plan::streaming::PartitionStream as DfPartitionStream; use datatypes::scalars::ScalarVectorBuilder; use datatypes::schema::{Schema, SchemaRef}; +use datatypes::value::Value; use datatypes::vectors::{StringVectorBuilder, UInt32VectorBuilder, VectorRef}; use futures::TryStreamExt; use snafu::{OptionExt, ResultExt}; @@ -34,6 +35,7 @@ use super::{OID_COLUMN_NAME, PG_CLASS}; use crate::error::{ CreateRecordBatchSnafu, InternalSnafu, Result, UpgradeWeakCatalogManagerRefSnafu, }; +use crate::information_schema::Predicates; use crate::system_schema::utils::tables::{string_column, u32_column}; use crate::system_schema::SystemTable; use crate::CatalogManager; @@ -179,17 +181,19 @@ impl PGClassBuilder { } } - async fn make_class(&mut self, _request: Option) -> Result { + async fn make_class(&mut self, request: Option) -> Result { let catalog_name = self.catalog_name.clone(); let catalog_manager = self .catalog_manager .upgrade() .context(UpgradeWeakCatalogManagerRefSnafu)?; + let predicates = Predicates::from_scan_request(&request); for schema_name in catalog_manager.schema_names(&catalog_name).await? { let mut stream = catalog_manager.tables(&catalog_name, &schema_name); while let Some(table) = stream.try_next().await? { let table_info = table.table_info(); self.add_class( + &predicates, table_info.table_id(), &schema_name, &table_info.name, @@ -204,7 +208,26 @@ impl PGClassBuilder { self.finish() } - fn add_class(&mut self, oid: u32, schema: &str, table: &str, kind: &str) { + fn add_class( + &mut self, + predicates: &Predicates, + oid: u32, + schema: &str, + table: &str, + kind: &str, + ) { + let row = [ + (OID_COLUMN_NAME, &Value::from(oid)), + (RELNAMESPACE, &Value::from(schema)), + (RELNAME, &Value::from(table)), + (RELKIND, &Value::from(kind)), + (RELOWNER, &Value::from(DUMMY_OWNER_ID)), + ]; + + if !predicates.eval(&row) { + return; + } + self.oid.push(Some(oid)); self.relnamespace.push(Some(schema)); self.relname.push(Some(table)); diff --git a/src/catalog/src/system_schema/pg_catalog/pg_namespace.rs b/src/catalog/src/system_schema/pg_catalog/pg_namespace.rs index 93d01ad83b77..b405a6bea39c 100644 --- a/src/catalog/src/system_schema/pg_catalog/pg_namespace.rs +++ b/src/catalog/src/system_schema/pg_catalog/pg_namespace.rs @@ -24,6 +24,7 @@ use datafusion::physical_plan::stream::RecordBatchStreamAdapter as DfRecordBatch use datafusion::physical_plan::streaming::PartitionStream as DfPartitionStream; use datatypes::scalars::ScalarVectorBuilder; use datatypes::schema::{Schema, SchemaRef}; +use datatypes::value::Value; use datatypes::vectors::{StringVectorBuilder, VectorRef}; use snafu::{OptionExt, ResultExt}; use store_api::storage::ScanRequest; @@ -32,6 +33,7 @@ use super::{OID_COLUMN_NAME, PG_NAMESPACE}; use crate::error::{ CreateRecordBatchSnafu, InternalSnafu, Result, UpgradeWeakCatalogManagerRefSnafu, }; +use crate::information_schema::Predicates; use crate::system_schema::utils::tables::string_column; use crate::system_schema::SystemTable; use crate::CatalogManager; @@ -157,14 +159,15 @@ impl PGNamespaceBuilder { } /// Construct the `pg_catalog.pg_namespace` virtual table - async fn make_namespace(&mut self, _request: Option) -> Result { + async fn make_namespace(&mut self, request: Option) -> Result { let catalog_name = self.catalog_name.clone(); let catalog_manager = self .catalog_manager .upgrade() .context(UpgradeWeakCatalogManagerRefSnafu)?; + let predicates = Predicates::from_scan_request(&request); for schema_name in catalog_manager.schema_names(&catalog_name).await? { - self.add_namespace(&schema_name); + self.add_namespace(&predicates, &schema_name); } self.finish() } @@ -174,7 +177,14 @@ impl PGNamespaceBuilder { RecordBatch::new(self.schema.clone(), columns).context(CreateRecordBatchSnafu) } - fn add_namespace(&mut self, schema_name: &str) { + fn add_namespace(&mut self, predicates: &Predicates, schema_name: &str) { + let row = [ + (OID_COLUMN_NAME, &Value::from(schema_name)), + (NSPNAME, &Value::from(schema_name)), + ]; + if !predicates.eval(&row) { + return; + } self.oid.push(Some(schema_name)); self.nspname.push(Some(schema_name)); } From 1fc91001cdd795bc7c279d1c52d2d2670e957834 Mon Sep 17 00:00:00 2001 From: J0hn50n133 <0xjohnsonlee@gmail.com> Date: Wed, 24 Jul 2024 22:48:00 +0800 Subject: [PATCH 05/14] test: add pg_namespace, pg_class related sqlness test --- .../common/information_schema/tables.result | 18 +- .../common/system/information_schema.result | 9 + .../common/system/pg_catalog.result | 181 ++++++++++++++++++ .../standalone/common/system/pg_catalog.sql | 107 ++++++++++- .../standalone/common/view/create.result | 39 ++++ tests/cases/standalone/common/view/create.sql | 28 +++ 6 files changed, 373 insertions(+), 9 deletions(-) diff --git a/tests/cases/standalone/common/information_schema/tables.result b/tests/cases/standalone/common/information_schema/tables.result index f48e65630282..28416fc0720c 100644 --- a/tests/cases/standalone/common/information_schema/tables.result +++ b/tests/cases/standalone/common/information_schema/tables.result @@ -24,14 +24,16 @@ Affected Rows: 0 select table_catalog, table_schema, table_name from information_schema.tables where table_schema != 'information_schema'; -+---------------+--------------+------------+ -| table_catalog | table_schema | table_name | -+---------------+--------------+------------+ -| greptime | abc | t | -| greptime | abcde | t | -| greptime | pg_catalog | pg_type | -| greptime | public | numbers | -+---------------+--------------+------------+ ++---------------+--------------+--------------+ +| table_catalog | table_schema | table_name | ++---------------+--------------+--------------+ +| greptime | abc | t | +| greptime | abcde | t | +| greptime | pg_catalog | pg_class | +| greptime | pg_catalog | pg_type | +| greptime | pg_catalog | pg_namespace | +| greptime | public | numbers | ++---------------+--------------+--------------+ use public; diff --git a/tests/cases/standalone/common/system/information_schema.result b/tests/cases/standalone/common/system/information_schema.result index 9dc0c0fc0751..77c486600e17 100644 --- a/tests/cases/standalone/common/system/information_schema.result +++ b/tests/cases/standalone/common/system/information_schema.result @@ -45,6 +45,8 @@ order by table_schema, table_name; |greptime|information_schema|tables|LOCALTEMPORARY|3|0|0|0|0|0||11|Fixed|0|0|0|DATETIME||||0|||Y| |greptime|information_schema|triggers|LOCALTEMPORARY|24|0|0|0|0|0||11|Fixed|0|0|0|DATETIME||||0|||Y| |greptime|information_schema|views|LOCALTEMPORARY|32|0|0|0|0|0||11|Fixed|0|0|0|DATETIME||||0|||Y| +|greptime|pg_catalog|pg_class|LOCALTEMPORARY|256|0|0|0|0|0||11|Fixed|0|0|0|DATETIME||||0|||Y| +|greptime|pg_catalog|pg_namespace|LOCALTEMPORARY|258|0|0|0|0|0||11|Fixed|0|0|0|DATETIME||||0|||Y| |greptime|pg_catalog|pg_type|LOCALTEMPORARY|257|0|0|0|0|0||11|Fixed|0|0|0|DATETIME||||0|||Y| |greptime|public|numbers|LOCALTEMPORARY|2|0|0|0|0|0|test_engine|11|Fixed|0|0|0|DATETIME||||0|||Y| +++++++++++++++++++++++++ @@ -411,6 +413,13 @@ select * from information_schema.columns order by table_schema, table_name, colu | greptime | information_schema | views | table_name | 3 | 2147483647 | 2147483647 | | | | utf8 | utf8_bin | | | select,insert | | String | string | FIELD | | No | string | | | | greptime | information_schema | views | table_schema | 2 | 2147483647 | 2147483647 | | | | utf8 | utf8_bin | | | select,insert | | String | string | FIELD | | No | string | | | | greptime | information_schema | views | view_definition | 4 | 2147483647 | 2147483647 | | | | utf8 | utf8_bin | | | select,insert | | String | string | FIELD | | No | string | | | +| greptime | pg_catalog | pg_class | oid | 1 | | | 10 | 0 | | | | | | select,insert | | UInt32 | int unsigned | FIELD | | No | int unsigned | | | +| greptime | pg_catalog | pg_class | relkind | 4 | 2147483647 | 2147483647 | | | | utf8 | utf8_bin | | | select,insert | | String | string | FIELD | | No | string | | | +| greptime | pg_catalog | pg_class | relname | 2 | 2147483647 | 2147483647 | | | | utf8 | utf8_bin | | | select,insert | | String | string | FIELD | | No | string | | | +| greptime | pg_catalog | pg_class | relnamespace | 3 | 2147483647 | 2147483647 | | | | utf8 | utf8_bin | | | select,insert | | String | string | FIELD | | No | string | | | +| greptime | pg_catalog | pg_class | relowner | 5 | | | 10 | 0 | | | | | | select,insert | | UInt32 | int unsigned | FIELD | | No | int unsigned | | | +| greptime | pg_catalog | pg_namespace | nspname | 2 | 2147483647 | 2147483647 | | | | utf8 | utf8_bin | | | select,insert | | String | string | FIELD | | No | string | | | +| greptime | pg_catalog | pg_namespace | oid | 1 | 2147483647 | 2147483647 | | | | utf8 | utf8_bin | | | select,insert | | String | string | FIELD | | No | string | | | | greptime | pg_catalog | pg_type | oid | 1 | | | 10 | 0 | | | | | | select,insert | | UInt32 | int unsigned | FIELD | | No | int unsigned | | | | greptime | pg_catalog | pg_type | typlen | 3 | | | 5 | 0 | | | | | | select,insert | | Int16 | smallint | FIELD | | No | smallint | | | | greptime | pg_catalog | pg_type | typname | 2 | 2147483647 | 2147483647 | | | | utf8 | utf8_bin | | | select,insert | | String | string | FIELD | | No | string | | | diff --git a/tests/cases/standalone/common/system/pg_catalog.result b/tests/cases/standalone/common/system/pg_catalog.result index f2b9677feb99..6d11ed2ff4ff 100644 --- a/tests/cases/standalone/common/system/pg_catalog.result +++ b/tests/cases/standalone/common/system/pg_catalog.result @@ -30,3 +30,184 @@ select * from pg_catalog.pg_type order by oid; | 20 | List | -1 | +-----+-----------+--------+ +-- \d +SELECT n.nspname as "Schema", + c.relname as "Name", + CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 't' THEN 'TOAST table' WHEN 'f' THEN 'foreign table' WHEN 'p' THEN 'partitioned table' WHEN 'I' THEN 'partitioned index' END as "Type", + pg_catalog.pg_get_userbyid(c.relowner) as "Owner" +FROM pg_catalog.pg_class c + LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace +WHERE c.relkind IN ('r','p','v','m','S','f','') + AND n.nspname <> 'pg_catalog' + AND n.nspname !~ '^pg_toast' + AND n.nspname <> 'information_schema' + AND pg_catalog.pg_table_is_visible(c.oid) +ORDER BY 1,2; + ++--------+---------+-------+-------+ +| Schema | Name | Type | Owner | ++--------+---------+-------+-------+ +| public | numbers | table | | ++--------+---------+-------+-------+ + +-- \dt +SELECT n.nspname as "Schema", + c.relname as "Name", + CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 't' THEN 'TOAST table' WHEN 'f' THEN 'foreign table' WHEN 'p' THEN 'partitioned table' WHEN 'I' THEN 'partitioned index' END as "Type", + pg_catalog.pg_get_userbyid(c.relowner) as "Owner" +FROM pg_catalog.pg_class c + LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace +WHERE c.relkind IN ('r','p','') + AND n.nspname <> 'pg_catalog' + AND n.nspname !~ '^pg_toast' + AND n.nspname <> 'information_schema' + AND pg_catalog.pg_table_is_visible(c.oid) +ORDER BY 1,2; + ++--------+---------+-------+-------+ +| Schema | Name | Type | Owner | ++--------+---------+-------+-------+ +| public | numbers | table | | ++--------+---------+-------+-------+ + +create +database my_db; + +Affected Rows: 1 + +use my_db; + +Affected Rows: 0 + +create table foo +( + ts TIMESTAMP TIME INDEX +); + +Affected Rows: 0 + +-- show tables in `my_db` +select relname +from pg_catalog.pg_class +where relnamespace = ( + select oid + from pg_catalog.pg_namespace + where nspname = 'my_db' +); + ++---------+ +| relname | ++---------+ +| foo | ++---------+ + +-- \dt +SELECT n.nspname as "Schema", + c.relname as "Name", + CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 't' THEN 'TOAST table' WHEN 'f' THEN 'foreign table' WHEN 'p' THEN 'partitioned table' WHEN 'I' THEN 'partitioned index' END as "Type", + pg_catalog.pg_get_userbyid(c.relowner) as "Owner" +FROM pg_catalog.pg_class c + LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace +WHERE c.relkind IN ('r','p','') + AND n.nspname <> 'pg_catalog' + AND n.nspname !~ '^pg_toast' + AND n.nspname <> 'information_schema' + AND pg_catalog.pg_table_is_visible(c.oid) +ORDER BY 1,2; + ++--------+---------+-------+-------+ +| Schema | Name | Type | Owner | ++--------+---------+-------+-------+ +| my_db | foo | table | | +| public | numbers | table | | ++--------+---------+-------+-------+ + +-- show tables in `my_db`, `public` +select relname +from pg_catalog.pg_class +where relnamespace in ( + select oid + from pg_catalog.pg_namespace + where nspname = 'my_db' or nspname = 'public' +); + ++---------+ +| relname | ++---------+ +| numbers | +| foo | ++---------+ + +select relname +from pg_catalog.pg_class +where relnamespace in ( + select oid + from pg_catalog.pg_namespace + where nspname like 'my%' +); + ++---------+ +| relname | ++---------+ +| foo | ++---------+ + +select relnamespace, relname, relkind +from pg_catalog.pg_class +where relnamespace in ( + select oid + from pg_catalog.pg_namespace + where nspname <> 'public' + and nspname <> 'information_schema' + and nspname <> 'pg_catalog' +) +order by relnamespace, relname; + ++--------------+---------+---------+ +| relnamespace | relname | relkind | ++--------------+---------+---------+ +| my_db | foo | r | ++--------------+---------+---------+ + +use public; + +Affected Rows: 0 + +drop schema my_db; + +Affected Rows: 0 + +use pg_catalog; + +Affected Rows: 0 + +-- pg_class +desc table pg_class; + ++--------------+--------+-----+------+---------+---------------+ +| Column | Type | Key | Null | Default | Semantic Type | ++--------------+--------+-----+------+---------+---------------+ +| oid | UInt32 | | NO | | FIELD | +| relname | String | | NO | | FIELD | +| relnamespace | String | | NO | | FIELD | +| relkind | String | | NO | | FIELD | +| relowner | UInt32 | | NO | | FIELD | ++--------------+--------+-----+------+---------+---------------+ + +desc table pg_namespace; + ++---------+--------+-----+------+---------+---------------+ +| Column | Type | Key | Null | Default | Semantic Type | ++---------+--------+-----+------+---------+---------------+ +| oid | String | | NO | | FIELD | +| nspname | String | | NO | | FIELD | ++---------+--------+-----+------+---------+---------------+ + +drop table my_db.foo; + +Error: 4001(TableNotFound), Table not found: greptime.my_db.foo + +use public; + +Affected Rows: 0 + diff --git a/tests/cases/standalone/common/system/pg_catalog.sql b/tests/cases/standalone/common/system/pg_catalog.sql index b958b4c3d6c2..43485899be58 100644 --- a/tests/cases/standalone/common/system/pg_catalog.sql +++ b/tests/cases/standalone/common/system/pg_catalog.sql @@ -1,4 +1,109 @@ -- should not able to create pg_catalog create database pg_catalog; -select * from pg_catalog.pg_type order by oid; \ No newline at end of file +select * from pg_catalog.pg_type order by oid; + +-- \d +SELECT n.nspname as "Schema", + c.relname as "Name", + CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 't' THEN 'TOAST table' WHEN 'f' THEN 'foreign table' WHEN 'p' THEN 'partitioned table' WHEN 'I' THEN 'partitioned index' END as "Type", + pg_catalog.pg_get_userbyid(c.relowner) as "Owner" +FROM pg_catalog.pg_class c + LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace +WHERE c.relkind IN ('r','p','v','m','S','f','') + AND n.nspname <> 'pg_catalog' + AND n.nspname !~ '^pg_toast' + AND n.nspname <> 'information_schema' + AND pg_catalog.pg_table_is_visible(c.oid) +ORDER BY 1,2; + +-- \dt + +SELECT n.nspname as "Schema", + c.relname as "Name", + CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 't' THEN 'TOAST table' WHEN 'f' THEN 'foreign table' WHEN 'p' THEN 'partitioned table' WHEN 'I' THEN 'partitioned index' END as "Type", + pg_catalog.pg_get_userbyid(c.relowner) as "Owner" +FROM pg_catalog.pg_class c + LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace +WHERE c.relkind IN ('r','p','') + AND n.nspname <> 'pg_catalog' + AND n.nspname !~ '^pg_toast' + AND n.nspname <> 'information_schema' + AND pg_catalog.pg_table_is_visible(c.oid) +ORDER BY 1,2; + +create +database my_db; + +use my_db; + +create table foo +( + ts TIMESTAMP TIME INDEX +); + +-- show tables in `my_db` +select relname +from pg_catalog.pg_class +where relnamespace = ( + select oid + from pg_catalog.pg_namespace + where nspname = 'my_db' +); + +-- \dt +SELECT n.nspname as "Schema", + c.relname as "Name", + CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 't' THEN 'TOAST table' WHEN 'f' THEN 'foreign table' WHEN 'p' THEN 'partitioned table' WHEN 'I' THEN 'partitioned index' END as "Type", + pg_catalog.pg_get_userbyid(c.relowner) as "Owner" +FROM pg_catalog.pg_class c + LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace +WHERE c.relkind IN ('r','p','') + AND n.nspname <> 'pg_catalog' + AND n.nspname !~ '^pg_toast' + AND n.nspname <> 'information_schema' + AND pg_catalog.pg_table_is_visible(c.oid) +ORDER BY 1,2; + +-- show tables in `my_db`, `public` +select relname +from pg_catalog.pg_class +where relnamespace in ( + select oid + from pg_catalog.pg_namespace + where nspname = 'my_db' or nspname = 'public' +); + +select relname +from pg_catalog.pg_class +where relnamespace in ( + select oid + from pg_catalog.pg_namespace + where nspname like 'my%' +); + +select relnamespace, relname, relkind +from pg_catalog.pg_class +where relnamespace in ( + select oid + from pg_catalog.pg_namespace + where nspname <> 'public' + and nspname <> 'information_schema' + and nspname <> 'pg_catalog' +) +order by relnamespace, relname; + +use public; + +drop schema my_db; + +use pg_catalog; + +-- pg_class +desc table pg_class; + +desc table pg_namespace; + +drop table my_db.foo; + +use public; diff --git a/tests/cases/standalone/common/view/create.result b/tests/cases/standalone/common/view/create.result index 05480b396922..68ac759711b2 100644 --- a/tests/cases/standalone/common/view/create.result +++ b/tests/cases/standalone/common/view/create.result @@ -63,6 +63,26 @@ SHOW FULL TABLES; | test_view | VIEW | +------------+-----------------+ +-- psql: \dv +SELECT n.nspname as "Schema", + c.relname as "Name", + CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 't' THEN 'TOAST table' WHEN 'f' THEN 'foreign table' WHEN 'p' THEN 'partitioned table' WHEN 'I' THEN 'partitioned index' END as "Type", + pg_catalog.pg_get_userbyid(c.relowner) as "Owner" +FROM pg_catalog.pg_class c + LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace +WHERE c.relkind IN ('v','') + AND n.nspname <> 'pg_catalog' + AND n.nspname !~ '^pg_toast' + AND n.nspname <> 'information_schema' + AND pg_catalog.pg_table_is_visible(c.oid) +ORDER BY 1,2; + ++--------+-----------+------+-------+ +| Schema | Name | Type | Owner | ++--------+-----------+------+-------+ +| public | test_view | view | | ++--------+-----------+------+-------+ + -- SQLNESS REPLACE (\s\d+\s) ID -- SQLNESS REPLACE (\s[\-0-9T:\.]{15,}) DATETIME -- SQLNESS REPLACE [\u0020\-]+ @@ -90,6 +110,8 @@ SELECT * FROM INFORMATION_SCHEMA.TABLES ORDER BY TABLE_NAME, TABLE_TYPE; |greptime|information_schema|optimizer_trace|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| |greptime|information_schema|parameters|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| |greptime|information_schema|partitions|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| +|greptime|pg_catalog|pg_class|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| +|greptime|pg_catalog|pg_namespace|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| |greptime|pg_catalog|pg_type|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| |greptime|information_schema|profiling|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| |greptime|information_schema|referential_constraints|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| @@ -169,3 +191,20 @@ SHOW TABLES; | numbers | +---------+ +-- psql: \dv +SELECT n.nspname as "Schema", + c.relname as "Name", + CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 't' THEN 'TOAST table' WHEN 'f' THEN 'foreign table' WHEN 'p' THEN 'partitioned table' WHEN 'I' THEN 'partitioned index' END as "Type", + pg_catalog.pg_get_userbyid(c.relowner) as "Owner" +FROM pg_catalog.pg_class c + LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace +WHERE c.relkind IN ('v','') + AND n.nspname <> 'pg_catalog' + AND n.nspname !~ '^pg_toast' + AND n.nspname <> 'information_schema' + AND pg_catalog.pg_table_is_visible(c.oid) +ORDER BY 1,2; + +++ +++ + diff --git a/tests/cases/standalone/common/view/create.sql b/tests/cases/standalone/common/view/create.sql index d2665249ad5a..d5e390de0733 100644 --- a/tests/cases/standalone/common/view/create.sql +++ b/tests/cases/standalone/common/view/create.sql @@ -27,6 +27,20 @@ SHOW TABLES; SHOW FULL TABLES; +-- psql: \dv +SELECT n.nspname as "Schema", + c.relname as "Name", + CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 't' THEN 'TOAST table' WHEN 'f' THEN 'foreign table' WHEN 'p' THEN 'partitioned table' WHEN 'I' THEN 'partitioned index' END as "Type", + pg_catalog.pg_get_userbyid(c.relowner) as "Owner" +FROM pg_catalog.pg_class c + LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace +WHERE c.relkind IN ('v','') + AND n.nspname <> 'pg_catalog' + AND n.nspname !~ '^pg_toast' + AND n.nspname <> 'information_schema' + AND pg_catalog.pg_table_is_visible(c.oid) +ORDER BY 1,2; + -- SQLNESS REPLACE (\s\d+\s) ID -- SQLNESS REPLACE (\s[\-0-9T:\.]{15,}) DATETIME -- SQLNESS REPLACE [\u0020\-]+ @@ -50,3 +64,17 @@ DROP TABLE test_table; SELECT * FROM test_view LIMIT 10; SHOW TABLES; + +-- psql: \dv +SELECT n.nspname as "Schema", + c.relname as "Name", + CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 't' THEN 'TOAST table' WHEN 'f' THEN 'foreign table' WHEN 'p' THEN 'partitioned table' WHEN 'I' THEN 'partitioned index' END as "Type", + pg_catalog.pg_get_userbyid(c.relowner) as "Owner" +FROM pg_catalog.pg_class c + LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace +WHERE c.relkind IN ('v','') + AND n.nspname <> 'pg_catalog' + AND n.nspname !~ '^pg_toast' + AND n.nspname <> 'information_schema' + AND pg_catalog.pg_table_is_visible(c.oid) +ORDER BY 1,2; From 35d845582a1d49906fe2ef3b73a97d217019abf4 Mon Sep 17 00:00:00 2001 From: J0hn50n133 <0xjohnsonlee@gmail.com> Date: Wed, 24 Jul 2024 23:28:35 +0800 Subject: [PATCH 06/14] fix: typos and license header --- src/catalog/src/system_schema/pg_catalog/pg_namespace.rs | 4 ++-- src/common/function/src/system/pg_catalog.rs | 4 ++-- .../function/src/system/pg_catalog/table_is_visible.rs | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/catalog/src/system_schema/pg_catalog/pg_namespace.rs b/src/catalog/src/system_schema/pg_catalog/pg_namespace.rs index b405a6bea39c..a02b8953851d 100644 --- a/src/catalog/src/system_schema/pg_catalog/pg_namespace.rs +++ b/src/catalog/src/system_schema/pg_catalog/pg_namespace.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Greptim Team +// Copyright 2023 Greptime Team // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -61,7 +61,7 @@ impl PGNamespace { fn schema() -> SchemaRef { Arc::new(Schema::new(vec![ - // TODO(J0HN50N133): we do not have a numeric schema id, use schema name as a workround. Use a proper schema id once we have it. + // TODO(J0HN50N133): we do not have a numeric schema id, use schema name as a workaround. Use a proper schema id once we have it. string_column(OID_COLUMN_NAME), string_column(NSPNAME), ])) diff --git a/src/common/function/src/system/pg_catalog.rs b/src/common/function/src/system/pg_catalog.rs index 94fef5970ceb..78726cffbeae 100644 --- a/src/common/function/src/system/pg_catalog.rs +++ b/src/common/function/src/system/pg_catalog.rs @@ -18,7 +18,7 @@ mod table_is_visible; use std::sync::Arc; use pg_get_userbyid::PGGetUserByIdFunction; -use table_is_visible::PGTableIsVisbleFunction; +use table_is_visible::PGTableIsVisibleFunction; use crate::function_registry::FunctionRegistry; @@ -33,7 +33,7 @@ pub(super) struct PGCatalogFunction; impl PGCatalogFunction { pub fn register(registry: &FunctionRegistry) { - registry.register(Arc::new(PGTableIsVisbleFunction)); + registry.register(Arc::new(PGTableIsVisibleFunction)); registry.register(Arc::new(PGGetUserByIdFunction)); } } diff --git a/src/common/function/src/system/pg_catalog/table_is_visible.rs b/src/common/function/src/system/pg_catalog/table_is_visible.rs index 6f173b93d641..630ad137628a 100644 --- a/src/common/function/src/system/pg_catalog/table_is_visible.rs +++ b/src/common/function/src/system/pg_catalog/table_is_visible.rs @@ -26,17 +26,17 @@ use crate::function::{Function, FunctionContext}; use crate::scalars::expression::{scalar_unary_op, EvalContext}; #[derive(Clone, Debug, Default)] -pub struct PGTableIsVisbleFunction; +pub struct PGTableIsVisibleFunction; const NAME: &str = crate::pg_catalog_func_fullname!("pg_table_is_visible"); -impl fmt::Display for PGTableIsVisbleFunction { +impl fmt::Display for PGTableIsVisibleFunction { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, crate::pg_catalog_func_fullname!("PG_TABLE_IS_VISIBLE")) } } -impl Function for PGTableIsVisbleFunction { +impl Function for PGTableIsVisibleFunction { fn name(&self) -> &str { NAME } From f7d251ab5657de5d11858b190ddbbc15a8632b2d Mon Sep 17 00:00:00 2001 From: J0hn50n133 <0xjohnsonlee@gmail.com> Date: Wed, 24 Jul 2024 23:57:45 +0800 Subject: [PATCH 07/14] fix: sqlness test --- tests/cases/standalone/common/system/pg_catalog.result | 5 +++-- tests/cases/standalone/common/system/pg_catalog.sql | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/cases/standalone/common/system/pg_catalog.result b/tests/cases/standalone/common/system/pg_catalog.result index 6d11ed2ff4ff..3740dac9745d 100644 --- a/tests/cases/standalone/common/system/pg_catalog.result +++ b/tests/cases/standalone/common/system/pg_catalog.result @@ -129,13 +129,14 @@ where relnamespace in ( select oid from pg_catalog.pg_namespace where nspname = 'my_db' or nspname = 'public' -); +) +order by relname; +---------+ | relname | +---------+ -| numbers | | foo | +| numbers | +---------+ select relname diff --git a/tests/cases/standalone/common/system/pg_catalog.sql b/tests/cases/standalone/common/system/pg_catalog.sql index 43485899be58..a1a16a3edb15 100644 --- a/tests/cases/standalone/common/system/pg_catalog.sql +++ b/tests/cases/standalone/common/system/pg_catalog.sql @@ -72,7 +72,8 @@ where relnamespace in ( select oid from pg_catalog.pg_namespace where nspname = 'my_db' or nspname = 'public' -); +) +order by relname; select relname from pg_catalog.pg_class From fa5036f5ae37a4280ddef2cf6aea504ad4e8e54b Mon Sep 17 00:00:00 2001 From: J0hn50n133 <0xjohnsonlee@gmail.com> Date: Thu, 25 Jul 2024 00:37:49 +0800 Subject: [PATCH 08/14] refactor: use `expect` instead of `unwrap` here --- src/catalog/src/system_schema/pg_catalog.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/catalog/src/system_schema/pg_catalog.rs b/src/catalog/src/system_schema/pg_catalog.rs index 51c9b426ac12..4c94d3779593 100644 --- a/src/catalog/src/system_schema/pg_catalog.rs +++ b/src/catalog/src/system_schema/pg_catalog.rs @@ -99,9 +99,12 @@ impl PGCatalogProvider { } tables.insert( PG_NAMESPACE.to_string(), - self.build_table(PG_NAMESPACE).unwrap(), + self.build_table(PG_NAMESPACE).expect(PG_NAMESPACE), + ); + tables.insert( + PG_CLASS.to_string(), + self.build_table(PG_CLASS).expect(PG_NAMESPACE), ); - tables.insert(PG_CLASS.to_string(), self.build_table(PG_CLASS).unwrap()); self.tables = tables; } } From 6ab5cc5fec013ffde6aadee47bf99502cdb789f4 Mon Sep 17 00:00:00 2001 From: J0hn50n133 <0xjohnsonlee@gmail.com> Date: Thu, 25 Jul 2024 00:42:12 +0800 Subject: [PATCH 09/14] refactor: remove the `information_schema::utils` mod --- src/catalog/src/system_schema/information_schema.rs | 7 +------ .../src/system_schema/information_schema/cluster_info.rs | 3 ++- .../src/system_schema/information_schema/schemata.rs | 3 ++- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/catalog/src/system_schema/information_schema.rs b/src/catalog/src/system_schema/information_schema.rs index 3982931a71a4..93dfaa75b531 100644 --- a/src/catalog/src/system_schema/information_schema.rs +++ b/src/catalog/src/system_schema/information_schema.rs @@ -42,12 +42,6 @@ pub use table_names::*; use views::InformationSchemaViews; use self::columns::InformationSchemaColumns; -pub(crate) use crate::system_schema::predicate::Predicates; -// TODO(J0HN150N133): re-export to provide compatibility for legacy `information_schema` code. -pub(crate) mod utils { - pub use crate::system_schema::utils::*; -} - use super::{SystemSchemaProviderInner, SystemTable, SystemTableRef}; use crate::error::Result; use crate::system_schema::information_schema::cluster_info::InformationSchemaClusterInfo; @@ -61,6 +55,7 @@ use crate::system_schema::information_schema::schemata::InformationSchemaSchemat use crate::system_schema::information_schema::table_constraints::InformationSchemaTableConstraints; use crate::system_schema::information_schema::tables::InformationSchemaTables; use crate::system_schema::memory_table::MemoryTable; +pub(crate) use crate::system_schema::predicate::Predicates; use crate::system_schema::SystemSchemaProvider; use crate::CatalogManager; diff --git a/src/catalog/src/system_schema/information_schema/cluster_info.rs b/src/catalog/src/system_schema/information_schema/cluster_info.rs index e878b94baf4a..e85e2103043b 100644 --- a/src/catalog/src/system_schema/information_schema/cluster_info.rs +++ b/src/catalog/src/system_schema/information_schema/cluster_info.rs @@ -41,7 +41,8 @@ use store_api::storage::{ScanRequest, TableId}; use super::CLUSTER_INFO; use crate::error::{CreateRecordBatchSnafu, InternalSnafu, ListNodesSnafu, Result}; -use crate::system_schema::information_schema::{utils, InformationTable, Predicates}; +use crate::system_schema::information_schema::{InformationTable, Predicates}; +use crate::system_schema::utils; use crate::CatalogManager; const PEER_ID: &str = "peer_id"; diff --git a/src/catalog/src/system_schema/information_schema/schemata.rs b/src/catalog/src/system_schema/information_schema/schemata.rs index de94914fe603..ca594b61a68f 100644 --- a/src/catalog/src/system_schema/information_schema/schemata.rs +++ b/src/catalog/src/system_schema/information_schema/schemata.rs @@ -36,7 +36,8 @@ use crate::error::{ CreateRecordBatchSnafu, InternalSnafu, Result, TableMetadataManagerSnafu, UpgradeWeakCatalogManagerRefSnafu, }; -use crate::system_schema::information_schema::{utils, InformationTable, Predicates}; +use crate::system_schema::information_schema::{InformationTable, Predicates}; +use crate::system_schema::utils; use crate::CatalogManager; pub const CATALOG_NAME: &str = "catalog_name"; From c52da9878a0653e198480161255978d489c8ae66 Mon Sep 17 00:00:00 2001 From: J0hn50n133 <0xjohnsonlee@gmail.com> Date: Thu, 25 Jul 2024 00:51:55 +0800 Subject: [PATCH 10/14] doc: make the comment in pg_get_userbyid more precise --- src/common/function/src/system/pg_catalog/pg_get_userbyid.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/function/src/system/pg_catalog/pg_get_userbyid.rs b/src/common/function/src/system/pg_catalog/pg_get_userbyid.rs index 1ab5a269c383..d618ec4ecd11 100644 --- a/src/common/function/src/system/pg_catalog/pg_get_userbyid.rs +++ b/src/common/function/src/system/pg_catalog/pg_get_userbyid.rs @@ -67,6 +67,6 @@ fn pg_get_user_by_id(table_oid: Option, _ctx: &mut EvalContext) -> Option< where I: AsPrimitive, { - // There is no user authentication in greptime open source core, so we always return "" + // TODO(J0HN50N133): We lack way to get the user_info by a numeric value. Once we have it, we can implement this function. table_oid.map(|_| "".to_string()) } From 3b35ffd9d4175f6481d30600fb64d8da3a02bf06 Mon Sep 17 00:00:00 2001 From: J0hn50n133 <0xjohnsonlee@gmail.com> Date: Fri, 26 Jul 2024 19:35:22 +0800 Subject: [PATCH 11/14] doc: add TODO and comment in pg_catalog --- src/catalog/src/system_schema/pg_catalog.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/catalog/src/system_schema/pg_catalog.rs b/src/catalog/src/system_schema/pg_catalog.rs index 4c94d3779593..c4102bf88b29 100644 --- a/src/catalog/src/system_schema/pg_catalog.rs +++ b/src/catalog/src/system_schema/pg_catalog.rs @@ -94,6 +94,8 @@ impl PGCatalogProvider { // SECURITY NOTE: // Must follow the same security rules as [`InformationSchemaProvider::build_tables`]. let mut tables = HashMap::new(); + // TODO(J0HN50N133): modeling the table_name as a enum type to get rid of expect/unwrap here + // It's safe to unwrap here because we are sure that the constants have been handle corretly inside system_table. for name in MEMORY_TABLES.iter() { tables.insert(name.to_string(), self.build_table(name).expect(name)); } From 51ec617fa6d4b92a2da64e1ee164a155fd50372d Mon Sep 17 00:00:00 2001 From: J0hn50n133 <0xjohnsonlee@gmail.com> Date: Sat, 27 Jul 2024 20:49:30 +0800 Subject: [PATCH 12/14] fix: typo --- src/catalog/src/system_schema/pg_catalog.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/catalog/src/system_schema/pg_catalog.rs b/src/catalog/src/system_schema/pg_catalog.rs index c4102bf88b29..27d785e4afae 100644 --- a/src/catalog/src/system_schema/pg_catalog.rs +++ b/src/catalog/src/system_schema/pg_catalog.rs @@ -95,7 +95,7 @@ impl PGCatalogProvider { // Must follow the same security rules as [`InformationSchemaProvider::build_tables`]. let mut tables = HashMap::new(); // TODO(J0HN50N133): modeling the table_name as a enum type to get rid of expect/unwrap here - // It's safe to unwrap here because we are sure that the constants have been handle corretly inside system_table. + // It's safe to unwrap here because we are sure that the constants have been handle correctly inside system_table. for name in MEMORY_TABLES.iter() { tables.insert(name.to_string(), self.build_table(name).expect(name)); } From 3617c15128c540faed4385891efefadf6c45bf77 Mon Sep 17 00:00:00 2001 From: J0hn50n133 <0xjohnsonlee@gmail.com> Date: Sun, 28 Jul 2024 00:21:37 +0800 Subject: [PATCH 13/14] fix: sqlness --- .../standalone/common/view/create.result | 72 ++++++++++--------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/tests/cases/standalone/common/view/create.result b/tests/cases/standalone/common/view/create.result index 6934a143f388..bb0ea87834e0 100644 --- a/tests/cases/standalone/common/view/create.result +++ b/tests/cases/standalone/common/view/create.result @@ -91,41 +91,43 @@ SELECT * FROM INFORMATION_SCHEMA.TABLES ORDER BY TABLE_NAME, TABLE_TYPE; +++++++++++++++++++++++++ |table_catalog|table_schema|table_name|table_type|table_id|data_length|max_data_length|index_length|max_index_length|avg_row_length|engine|version|row_format|table_rows|data_free|auto_increment|create_time|update_time|check_time|table_collation|checksum|create_options|table_comment|temporary| +++++++++++++++++++++++++ -|greptime|information_schema|build_info|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|character_sets|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|check_constraints|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|cluster_info|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|collation_character_set_applicability|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|collations|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|column_privileges|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|column_statistics|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|columns|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|engines|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|events|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|files|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|flows|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|global_status|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|key_column_usage|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|public|numbers|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID|test_engine|ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|optimizer_trace|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|parameters|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|partitions|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|pg_catalog|pg_type|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|profiling|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|referential_constraints|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|region_peers|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|routines|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|runtime_metrics|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|schema_privileges|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|schemata|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|session_status|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|table_constraints|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|table_privileges|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|tables|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|public|test_table|BASETABLE|ID|ID|ID|ID|ID|ID|mito|ID|Fixed|ID|ID|ID|DATETIME||||ID|||N| -|greptime|public|test_view|VIEW|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||N| -|greptime|information_schema|triggers|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| -|greptime|information_schema|views|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME||||ID|||Y| +|greptime|information_schema|build_info|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|character_sets|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|check_constraints|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|cluster_info|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|collation_character_set_applicability|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|collations|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|column_privileges|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|column_statistics|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|columns|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|engines|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|events|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|files|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|flows|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|global_status|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|key_column_usage|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|public|numbers|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID|test_engine|ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|optimizer_trace|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|parameters|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|partitions|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|pg_catalog|pg_class|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|pg_catalog|pg_namespace|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|pg_catalog|pg_type|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|profiling|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|referential_constraints|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|region_peers|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|routines|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|runtime_metrics|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|schema_privileges|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|schemata|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|session_status|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|table_constraints|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|table_privileges|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|tables|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|public|test_table|BASETABLE|ID|ID|ID|ID|ID|ID|mito|ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||N| +|greptime|public|test_view|VIEW|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||N| +|greptime|information_schema|triggers|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +|greptime|information_schema|views|LOCALTEMPORARY|ID|ID|ID|ID|ID|ID||ID|Fixed|ID|ID|ID|DATETIME|||utf8_bin|ID|||Y| +++++++++++++++++++++++++ -- SQLNESS REPLACE (\s\d+\s) ID From 97a3435b6e80c5fa8f3f278aab16e20d63ca8375 Mon Sep 17 00:00:00 2001 From: J0hn50n133 <0xjohnsonlee@gmail.com> Date: Sun, 28 Jul 2024 15:41:12 +0800 Subject: [PATCH 14/14] doc: change to comment on PGClassBuilder to TODO --- src/catalog/src/system_schema/pg_catalog/pg_class.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/catalog/src/system_schema/pg_catalog/pg_class.rs b/src/catalog/src/system_schema/pg_catalog/pg_class.rs index e9978c41a099..36373b73f71c 100644 --- a/src/catalog/src/system_schema/pg_catalog/pg_class.rs +++ b/src/catalog/src/system_schema/pg_catalog/pg_class.rs @@ -149,7 +149,8 @@ impl DfPartitionStream for PGClass { } /// Builds the `pg_catalog.pg_class` table row by row -/// `relowner` is always the [`DUMMY_OWNER_ID`] cuz we don't have user +/// TODO(J0HN50N133): `relowner` is always the [`DUMMY_OWNER_ID`] cuz we don't have user. +/// Once we have user system, make it the actual owner of the table. struct PGClassBuilder { schema: SchemaRef, catalog_name: String,