feat: add table id and engine to information_schema.TABLES (#1407)

* feat: add table id and engine to informatin_schema.TABLES

* Update src/catalog/src/information_schema/tables.rs

Co-authored-by: Yingwen <realevenyag@gmail.com>

* chore: change table_engine to engine

* test: update sqlness for information schema

* test: update information_schema test in frontend::tests::instance_test.rs

* fix: github action sqlness information_schema test fail

* test: ignore table_id in information_schema

* test: support distribute and standalone have different output

---------

Co-authored-by: Yingwen <realevenyag@gmail.com>
This commit is contained in:
Hao
2023-04-19 10:52:02 +08:00
committed by GitHub
parent e8bb00f0be
commit e4cd08c750
5 changed files with 87 additions and 26 deletions

View File

@@ -23,7 +23,7 @@ use datafusion::physical_plan::stream::RecordBatchStreamAdapter as DfRecordBatch
use datafusion::physical_plan::SendableRecordBatchStream as DfSendableRecordBatchStream;
use datatypes::prelude::{ConcreteDataType, ScalarVectorBuilder, VectorRef};
use datatypes::schema::{ColumnSchema, Schema, SchemaRef};
use datatypes::vectors::StringVectorBuilder;
use datatypes::vectors::{StringVectorBuilder, UInt32VectorBuilder};
use snafu::ResultExt;
use table::metadata::TableType;
@@ -44,6 +44,8 @@ impl InformationSchemaTables {
ColumnSchema::new("table_schema", ConcreteDataType::string_datatype(), false),
ColumnSchema::new("table_name", ConcreteDataType::string_datatype(), false),
ColumnSchema::new("table_type", ConcreteDataType::string_datatype(), false),
ColumnSchema::new("table_id", ConcreteDataType::uint32_datatype(), true),
ColumnSchema::new("engine", ConcreteDataType::string_datatype(), true),
]));
Self {
schema,
@@ -73,6 +75,8 @@ struct InformationSchemaTablesBuilder {
schema_names: StringVectorBuilder,
table_names: StringVectorBuilder,
table_types: StringVectorBuilder,
table_ids: UInt32VectorBuilder,
engines: StringVectorBuilder,
}
impl InformationSchemaTablesBuilder {
@@ -85,6 +89,8 @@ impl InformationSchemaTablesBuilder {
schema_names: StringVectorBuilder::with_capacity(42),
table_names: StringVectorBuilder::with_capacity(42),
table_types: StringVectorBuilder::with_capacity(42),
table_ids: UInt32VectorBuilder::with_capacity(42),
engines: StringVectorBuilder::with_capacity(42),
}
}
@@ -100,7 +106,15 @@ impl InformationSchemaTablesBuilder {
let Some(schema) = self.catalog_provider.schema(&schema_name)? else { continue };
for table_name in schema.table_names()? {
let Some(table) = schema.table(&table_name).await? else { continue };
self.add_table(&catalog_name, &schema_name, &table_name, table.table_type());
let table_info = table.table_info();
self.add_table(
&catalog_name,
&schema_name,
&table_name,
table.table_type(),
Some(table_info.ident.table_id),
Some(&table_info.meta.engine),
);
}
}
@@ -110,6 +124,8 @@ impl InformationSchemaTablesBuilder {
INFORMATION_SCHEMA_NAME,
TABLES,
TableType::View,
None,
None,
);
self.finish()
@@ -121,6 +137,8 @@ impl InformationSchemaTablesBuilder {
schema_name: &str,
table_name: &str,
table_type: TableType,
table_id: Option<u32>,
engine: Option<&str>,
) {
self.catalog_names.push(Some(catalog_name));
self.schema_names.push(Some(schema_name));
@@ -130,6 +148,8 @@ impl InformationSchemaTablesBuilder {
TableType::View => "VIEW",
TableType::Temporary => "LOCAL TEMPORARY",
}));
self.table_ids.push(table_id);
self.engines.push(engine);
}
fn finish(&mut self) -> Result<RecordBatch> {
@@ -138,6 +158,8 @@ impl InformationSchemaTablesBuilder {
Arc::new(self.schema_names.finish()),
Arc::new(self.table_names.finish()),
Arc::new(self.table_types.finish()),
Arc::new(self.table_ids.finish()),
Arc::new(self.engines.finish()),
];
RecordBatch::new(self.schema.clone(), columns).context(CreateRecordBatchSnafu)
}

View File

@@ -904,6 +904,7 @@ async fn test_execute_copy_from_s3(instance: Arc<dyn MockInstance>) {
#[apply(both_instances_cases)]
async fn test_information_schema(instance: Arc<dyn MockInstance>) {
let is_distributed_mode = instance.is_distributed_mode();
let instance = instance.frontend();
let sql = "create table another_table(i bigint time index)";
@@ -913,27 +914,55 @@ async fn test_information_schema(instance: Arc<dyn MockInstance>) {
// User can only see information schema under current catalog.
// A necessary requirement to GreptimeCloud.
let sql = "select table_catalog, table_schema, table_name, table_type from information_schema.tables where table_type != 'SYSTEM VIEW' order by table_name";
let sql = "select table_catalog, table_schema, table_name, table_type, table_id, engine from information_schema.tables where table_type != 'SYSTEM VIEW' order by table_name";
let output = execute_sql(&instance, sql).await;
let expected = "\
+---------------+--------------------+------------+------------+
| table_catalog | table_schema | table_name | table_type |
+---------------+--------------------+------------+------------+
| greptime | public | numbers | BASE TABLE |
| greptime | public | scripts | BASE TABLE |
| greptime | information_schema | tables | VIEW |
+---------------+--------------------+------------+------------+";
let expected = match is_distributed_mode {
true => {
"\
+---------------+--------------------+------------+------------+----------+-------------+
| table_catalog | table_schema | table_name | table_type | table_id | engine |
+---------------+--------------------+------------+------------+----------+-------------+
| greptime | public | numbers | BASE TABLE | 1 | test_engine |
| greptime | public | scripts | BASE TABLE | 1024 | mito |
| greptime | information_schema | tables | VIEW | | |
+---------------+--------------------+------------+------------+----------+-------------+"
}
false => {
"\
+---------------+--------------------+------------+------------+----------+-------------+
| table_catalog | table_schema | table_name | table_type | table_id | engine |
+---------------+--------------------+------------+------------+----------+-------------+
| greptime | public | numbers | BASE TABLE | 1 | test_engine |
| greptime | public | scripts | BASE TABLE | 1 | mito |
| greptime | information_schema | tables | VIEW | | |
+---------------+--------------------+------------+------------+----------+-------------+"
}
};
check_output_stream(output, expected).await;
let output = execute_sql_with(&instance, sql, query_ctx).await;
let expected = "\
+-----------------+--------------------+---------------+------------+
| table_catalog | table_schema | table_name | table_type |
+-----------------+--------------------+---------------+------------+
| another_catalog | another_schema | another_table | BASE TABLE |
| another_catalog | information_schema | tables | VIEW |
+-----------------+--------------------+---------------+------------+";
let expected = match is_distributed_mode {
true => {
"\
+-----------------+--------------------+---------------+------------+----------+--------+
| table_catalog | table_schema | table_name | table_type | table_id | engine |
+-----------------+--------------------+---------------+------------+----------+--------+
| another_catalog | another_schema | another_table | BASE TABLE | 1025 | mito |
| another_catalog | information_schema | tables | VIEW | | |
+-----------------+--------------------+---------------+------------+----------+--------+"
}
false => {
"\
+-----------------+--------------------+---------------+------------+----------+--------+
| table_catalog | table_schema | table_name | table_type | table_id | engine |
+-----------------+--------------------+---------------+------------+----------+--------+
| another_catalog | another_schema | another_table | BASE TABLE | 1024 | mito |
| another_catalog | information_schema | tables | VIEW | | |
+-----------------+--------------------+---------------+------------+----------+--------+"
}
};
check_output_stream(output, expected).await;
}

View File

@@ -26,18 +26,28 @@ use crate::tests::{
pub(crate) trait MockInstance {
fn frontend(&self) -> Arc<Instance>;
fn is_distributed_mode(&self) -> bool;
}
impl MockInstance for MockStandaloneInstance {
fn frontend(&self) -> Arc<Instance> {
self.instance.clone()
}
fn is_distributed_mode(&self) -> bool {
false
}
}
impl MockInstance for MockDistributedInstance {
fn frontend(&self) -> Arc<Instance> {
self.frontend.clone()
}
fn is_distributed_mode(&self) -> bool {
true
}
}
pub(crate) async fn standalone() -> Arc<dyn MockInstance> {

View File

@@ -27,18 +27,18 @@ order by table_name;
| foo |
+------------+
select table_catalog, table_schema, table_name, table_type
select table_catalog, table_schema, table_name, table_type, engine
from information_schema.tables
where table_catalog = 'greptime'
and table_schema != 'public'
order by table_schema, table_name;
+---------------+--------------------+------------+------------+
| table_catalog | table_schema | table_name | table_type |
+---------------+--------------------+------------+------------+
| greptime | information_schema | tables | VIEW |
| greptime | my_db | foo | BASE TABLE |
+---------------+--------------------+------------+------------+
+---------------+--------------------+------------+------------+--------+
| table_catalog | table_schema | table_name | table_type | engine |
+---------------+--------------------+------------+------------+--------+
| greptime | information_schema | tables | VIEW | |
| greptime | my_db | foo | BASE TABLE | mito |
+---------------+--------------------+------------+------------+--------+
use
public;

View File

@@ -14,7 +14,7 @@ from information_schema.tables
where table_schema = 'my_db'
order by table_name;
select table_catalog, table_schema, table_name, table_type
select table_catalog, table_schema, table_name, table_type, engine
from information_schema.tables
where table_catalog = 'greptime'
and table_schema != 'public'