diff --git a/rust/cubesql/cubesql/src/compile/engine/context_postgresql.rs b/rust/cubesql/cubesql/src/compile/engine/context_postgresql.rs index 2b1b227553d8c..5249672e84e50 100644 --- a/rust/cubesql/cubesql/src/compile/engine/context_postgresql.rs +++ b/rust/cubesql/cubesql/src/compile/engine/context_postgresql.rs @@ -14,6 +14,7 @@ use super::information_schema::postgres::{ views::InfoSchemaViewsProvider as PostgresSchemaViewsProvider, InfoSchemaRoleColumnGrantsProvider as PostgresInfoSchemaRoleColumnGrantsProvider, InfoSchemaRoleTableGrantsProvider as PostgresInfoSchemaRoleTableGrantsProvider, + InfoSchemaSqlImplementationInfoProvider as PostgresInfoSchemaSqlImplementationInfoProvider, InfoSchemaTestingBlockingProvider, InfoSchemaTestingDatasetProvider, PgCatalogAmProvider, PgCatalogAttrdefProvider, PgCatalogAttributeProvider, PgCatalogClassProvider, PgCatalogConstraintProvider, PgCatalogDatabaseProvider, PgCatalogDependProvider, @@ -70,6 +71,10 @@ impl DatabaseProtocol { "information_schema.role_column_grants".to_string() } else if let Some(_) = any.downcast_ref::() { "information_schema.schemata".to_string() + } else if let Some(_) = + any.downcast_ref::() + { + "information_schema.sql_implementation_info".to_string() } else if let Some(_) = any.downcast_ref::() { "pg_catalog.pg_tables".to_string() } else if let Some(_) = any.downcast_ref::() { @@ -289,6 +294,11 @@ impl DatabaseProtocol { &context.session_state.database().unwrap_or("db".to_string()), ))) } + "sql_implementation_info" => { + return Some(Arc::new( + PostgresInfoSchemaSqlImplementationInfoProvider::new(), + )) + } #[cfg(debug_assertions)] "testing_dataset" => { return Some(Arc::new(InfoSchemaTestingDatasetProvider::new(5, 1000))) diff --git a/rust/cubesql/cubesql/src/compile/engine/information_schema/postgres/mod.rs b/rust/cubesql/cubesql/src/compile/engine/information_schema/postgres/mod.rs index 6a60560eb3585..c798cce3517b0 100644 --- a/rust/cubesql/cubesql/src/compile/engine/information_schema/postgres/mod.rs +++ b/rust/cubesql/cubesql/src/compile/engine/information_schema/postgres/mod.rs @@ -7,6 +7,7 @@ pub mod constraint_column_usage; pub mod key_column_usage; pub mod referential_constraints; pub mod schemata; +pub mod sql_implementation_info; pub mod table_constraints; pub mod tables; pub mod views; @@ -77,5 +78,6 @@ pub use pg_user::*; pub use pg_views::*; pub use role_column_grants::*; pub use role_table_grants::*; +pub use sql_implementation_info::*; pub use testing_blocking::*; pub use testing_dataset::*; diff --git a/rust/cubesql/cubesql/src/compile/engine/information_schema/postgres/sql_implementation_info.rs b/rust/cubesql/cubesql/src/compile/engine/information_schema/postgres/sql_implementation_info.rs new file mode 100644 index 0000000000000..f4cd7a8294d9f --- /dev/null +++ b/rust/cubesql/cubesql/src/compile/engine/information_schema/postgres/sql_implementation_info.rs @@ -0,0 +1,125 @@ +use std::{any::Any, sync::Arc}; + +use async_trait::async_trait; +use datafusion::{ + arrow::{ + array::{Array, ArrayRef, StringBuilder, UInt32Builder}, + datatypes::{DataType, Field, Schema, SchemaRef}, + record_batch::RecordBatch, + }, + datasource::{datasource::TableProviderFilterPushDown, TableProvider, TableType}, + error::DataFusionError, + logical_plan::Expr, + physical_plan::{memory::MemoryExec, ExecutionPlan}, +}; + +struct InfoSchemaSqlImplementationInfoBuilder { + implementation_info_id: StringBuilder, + implementation_info_name: StringBuilder, + integer_value: UInt32Builder, + character_value: StringBuilder, + comments: StringBuilder, +} + +impl InfoSchemaSqlImplementationInfoBuilder { + fn new(capacity: usize) -> Self { + Self { + implementation_info_id: StringBuilder::new(capacity), + implementation_info_name: StringBuilder::new(capacity), + integer_value: UInt32Builder::new(capacity), + character_value: StringBuilder::new(capacity), + comments: StringBuilder::new(capacity), + } + } + + fn add_info( + &mut self, + implementation_info_id: impl AsRef, + implementation_info_name: impl AsRef, + integer_value: Option, + character_value: Option<&str>, + comments: Option<&str>, + ) { + self.implementation_info_id + .append_value(&implementation_info_id) + .unwrap(); + self.implementation_info_name + .append_value(&implementation_info_name) + .unwrap(); + self.integer_value.append_option(integer_value).unwrap(); + self.character_value.append_option(character_value).unwrap(); + self.comments.append_option(comments).unwrap(); + } + + fn finish(mut self) -> Vec> { + let columns: Vec> = vec![ + Arc::new(self.implementation_info_id.finish()), + Arc::new(self.implementation_info_name.finish()), + Arc::new(self.integer_value.finish()), + Arc::new(self.character_value.finish()), + Arc::new(self.comments.finish()), + ]; + + columns + } +} + +pub struct InfoSchemaSqlImplementationInfoProvider { + data: Arc>, +} + +impl InfoSchemaSqlImplementationInfoProvider { + pub fn new() -> Self { + let mut builder = InfoSchemaSqlImplementationInfoBuilder::new(2); + + builder.add_info("17", "DBMS NAME", None, Some("PostgreSQL"), None); + builder.add_info("18", "DBMS VERSION", None, Some("14.02.0000)"), None); + + Self { + data: Arc::new(builder.finish()), + } + } +} + +#[async_trait] +impl TableProvider for InfoSchemaSqlImplementationInfoProvider { + fn as_any(&self) -> &dyn Any { + self + } + + fn table_type(&self) -> TableType { + TableType::View + } + + fn schema(&self) -> SchemaRef { + Arc::new(Schema::new(vec![ + Field::new("implementation_info_id", DataType::Utf8, false), + Field::new("implementation_info_name", DataType::Utf8, false), + Field::new("integer_value", DataType::UInt32, true), + Field::new("character_value", DataType::Utf8, true), + Field::new("comments", DataType::Utf8, true), + ])) + } + + async fn scan( + &self, + projection: &Option>, + _filters: &[Expr], + _limit: Option, + ) -> Result, DataFusionError> { + let batch = RecordBatch::try_new(self.schema(), self.data.to_vec())?; + + Ok(Arc::new(MemoryExec::try_new( + &[vec![batch]], + self.schema(), + projection.clone(), + )?)) + } + + fn supports_filter_pushdown( + &self, + _filter: &Expr, + ) -> Result { + Ok(TableProviderFilterPushDown::Unsupported) + } +} diff --git a/rust/cubesql/cubesql/src/compile/mod.rs b/rust/cubesql/cubesql/src/compile/mod.rs index d517a2ff65369..4824a8957a5b9 100644 --- a/rust/cubesql/cubesql/src/compile/mod.rs +++ b/rust/cubesql/cubesql/src/compile/mod.rs @@ -18421,4 +18421,23 @@ LIMIT {{ limit }}{% endif %}"#.to_string(), } ) } + + #[tokio::test] + async fn test_quicksight_sql_implementation_info() -> Result<(), CubeError> { + insta::assert_snapshot!( + "quicksight_sql_implementation_info", + execute_query( + r#" + SELECT character_value, version() + FROM INFORMATION_SCHEMA.SQL_IMPLEMENTATION_INFO + WHERE implementation_info_id IN ('17','18') + "# + .to_string(), + DatabaseProtocol::PostgreSQL + ) + .await? + ); + + Ok(()) + } } diff --git a/rust/cubesql/cubesql/src/compile/query_engine.rs b/rust/cubesql/cubesql/src/compile/query_engine.rs index aa30f45fe9dfc..67b5029d4cad7 100644 --- a/rust/cubesql/cubesql/src/compile/query_engine.rs +++ b/rust/cubesql/cubesql/src/compile/query_engine.rs @@ -366,7 +366,7 @@ impl QueryEngine for SqlQueryEngine { ctx.register_udf(create_user_udf(state.clone())); } else if state.protocol == DatabaseProtocol::PostgreSQL { ctx.register_udf(create_version_udf( - "PostgreSQL 14.1 on x86_64-cubesql".to_string(), + "PostgreSQL 14.2 on x86_64-cubesql".to_string(), )); ctx.register_udf(create_db_udf("current_database".to_string(), state.clone())); ctx.register_udf(create_db_udf("current_schema".to_string(), state.clone())); diff --git a/rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__pg_catalog_udf_search_path.snap b/rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__pg_catalog_udf_search_path.snap index 5a60c70f5acb6..d707f97582db9 100644 --- a/rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__pg_catalog_udf_search_path.snap +++ b/rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__pg_catalog_udf_search_path.snap @@ -1,11 +1,10 @@ --- source: cubesql/src/compile/mod.rs -assertion_line: 7401 -expression: "execute_query(\"SELECT version() UNION ALL SELECT pg_catalog.version();\".to_string(),\n DatabaseProtocol::PostgreSQL).await?" +expression: "execute_query(\"SELECT version() UNION ALL SELECT pg_catalog.version();\".to_string(),\nDatabaseProtocol::PostgreSQL).await?" --- +-----------------------------------+ | version() | +-----------------------------------+ -| PostgreSQL 14.1 on x86_64-cubesql | -| PostgreSQL 14.1 on x86_64-cubesql | +| PostgreSQL 14.2 on x86_64-cubesql | +| PostgreSQL 14.2 on x86_64-cubesql | +-----------------------------------+ diff --git a/rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__quicksight_sql_implementation_info.snap b/rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__quicksight_sql_implementation_info.snap new file mode 100644 index 0000000000000..4614e9ff83b70 --- /dev/null +++ b/rust/cubesql/cubesql/src/compile/snapshots/cubesql__compile__tests__quicksight_sql_implementation_info.snap @@ -0,0 +1,10 @@ +--- +source: cubesql/src/compile/mod.rs +expression: "execute_query(r#\"\n SELECT character_value, version() \n FROM INFORMATION_SCHEMA.SQL_IMPLEMENTATION_INFO\n WHERE implementation_info_id IN ('17','18')\n \"#.to_string(),\nDatabaseProtocol::PostgreSQL).await?" +--- ++-----------------+-----------------------------------+ +| character_value | version() | ++-----------------+-----------------------------------+ +| PostgreSQL | PostgreSQL 14.2 on x86_64-cubesql | +| 14.02.0000) | PostgreSQL 14.2 on x86_64-cubesql | ++-----------------+-----------------------------------+