Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/common/enum_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3839,19 +3839,20 @@ SettingScope EnumUtil::FromString<SettingScope>(const char *value) {
const StringUtil::EnumStringLiteral *GetShowTypeValues() {
static constexpr StringUtil::EnumStringLiteral values[] {
{ static_cast<uint32_t>(ShowType::SUMMARY), "SUMMARY" },
{ static_cast<uint32_t>(ShowType::DESCRIBE), "DESCRIBE" }
{ static_cast<uint32_t>(ShowType::DESCRIBE), "DESCRIBE" },
{ static_cast<uint32_t>(ShowType::SHOW_FROM), "SHOW_FROM" }
};
return values;
}

template<>
const char* EnumUtil::ToChars<ShowType>(ShowType value) {
return StringUtil::EnumToString(GetShowTypeValues(), 2, "ShowType", static_cast<uint32_t>(value));
return StringUtil::EnumToString(GetShowTypeValues(), 3, "ShowType", static_cast<uint32_t>(value));
}

template<>
ShowType EnumUtil::FromString<ShowType>(const char *value) {
return static_cast<ShowType>(StringUtil::StringToEnum(GetShowTypeValues(), 2, "ShowType", value));
return static_cast<ShowType>(StringUtil::StringToEnum(GetShowTypeValues(), 3, "ShowType", value));
}

const StringUtil::EnumStringLiteral *GetSimplifiedTokenTypeValues() {
Expand Down
23 changes: 19 additions & 4 deletions src/function/pragma/pragma_queries.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,32 @@ static string PragmaTableInfo(ClientContext &context, const FunctionParameters &
KeywordHelper::WriteQuoted(parameters.values[0].ToString(), '\''));
}

string PragmaShowTables() {
string PragmaShowTables(const string &database, const string &schema) {
string where_clause = "";
vector<string> where_conditions;
if (!database.empty()) {
where_conditions.push_back(StringUtil::Format("lower(database_name) = lower(%s)", SQLString(database)));
}
if (!schema.empty()) {
where_conditions.push_back(StringUtil::Format("lower(schema_name) = lower(%s)", SQLString(schema)));
}
if (where_conditions.empty()) {
where_conditions.push_back("in_search_path(database_name, schema_name)");
}
where_clause = "WHERE " + StringUtil::Join(where_conditions, " AND ");

// clang-format off
return R"EOF(
string query = R"EOF(
with "tables" as
(
SELECT table_name as "name"
FROM duckdb_tables
where in_search_path(database_name, schema_name)
)EOF" + where_clause + R"EOF(
), "views" as
(
SELECT view_name as "name"
FROM duckdb_views
where in_search_path(database_name, schema_name)
)EOF" + where_clause + R"EOF(
), db_objects as
(
SELECT "name" FROM "tables"
Expand All @@ -41,6 +54,8 @@ string PragmaShowTables() {
SELECT "name"
FROM db_objects
ORDER BY "name";)EOF";

return query;
// clang-format on
}

Expand Down
2 changes: 1 addition & 1 deletion src/include/duckdb/function/pragma/pragma_functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ struct PragmaFunctions {
static void RegisterFunction(BuiltinFunctions &set);
};

string PragmaShowTables();
string PragmaShowTables(const string &catalog = "", const string &schema = "");
string PragmaShowTablesExpanded();
string PragmaShowDatabases();
string PragmaShowVariables();
Expand Down
6 changes: 5 additions & 1 deletion src/include/duckdb/parser/tableref/showref.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

namespace duckdb {

enum class ShowType : uint8_t { SUMMARY, DESCRIBE };
enum class ShowType : uint8_t { SUMMARY, DESCRIBE, SHOW_FROM };

//! Represents a SHOW/DESCRIBE/SUMMARIZE statement
class ShowRef : public TableRef {
Expand All @@ -28,6 +28,10 @@ class ShowRef : public TableRef {

//! The table name (if any)
string table_name;
//! The catalog name (if any)
string catalog_name;
//! The schema name (if any)
string schema_name;
//! The QueryNode of select query (if any)
unique_ptr<QueryNode> query;
//! Whether or not we are requesting a summary or a describe
Expand Down
10 changes: 10 additions & 0 deletions src/include/duckdb/storage/serialization/tableref.json
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,16 @@
"id": 202,
"name": "show_type",
"type": "ShowType"
},
{
"id": 203,
"name": "catalog_name",
"type": "string"
},
{
"id": 204,
"name": "schema_name",
"type": "string"
}
]
},
Expand Down
14 changes: 14 additions & 0 deletions src/parser/tableref/showref.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "duckdb/parser/tableref/showref.hpp"
#include "duckdb/parser/keyword_helper.hpp"

namespace duckdb {

Expand All @@ -9,6 +10,17 @@ string ShowRef::ToString() const {
string result;
if (show_type == ShowType::SUMMARY) {
result += "SUMMARIZE ";
} else if (show_type == ShowType::SHOW_FROM) {
result += "SHOW TABLES FROM ";
string name = "";
if (!catalog_name.empty()) {
name += KeywordHelper::WriteOptionallyQuoted(catalog_name, '"');
if (!schema_name.empty()) {
name += ".";
}
}
name += KeywordHelper::WriteOptionallyQuoted(schema_name, '"');
result += name;
} else {
result += "DESCRIBE ";
}
Expand Down Expand Up @@ -38,6 +50,8 @@ bool ShowRef::Equals(const TableRef &other_p) const {
unique_ptr<TableRef> ShowRef::Copy() {
auto copy = make_uniq<ShowRef>();

copy->catalog_name = catalog_name;
copy->schema_name = schema_name;
copy->table_name = table_name;
copy->query = query ? query->Copy() : nullptr;
copy->show_type = show_type;
Expand Down
26 changes: 22 additions & 4 deletions src/parser/transform/statement/transform_show.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,31 @@ unique_ptr<QueryNode> Transformer::TransformShow(duckdb_libpgquery::PGVariableSh
select_node->select_list.push_back(make_uniq<StarExpression>());
auto showref = make_uniq<ShowRef>();
if (stmt.set) {
// describing a set (e.g. SHOW ALL TABLES) - push it in the table name
showref->table_name = stmt.set;
if (std::string(stmt.set) == "__show_tables_from_database") {
showref->show_type = ShowType::SHOW_FROM;
auto qualified_name = TransformQualifiedName(*stmt.relation);
if (!IsInvalidCatalog(qualified_name.catalog)) {
throw ParserException("Expected \"SHOW TABLES FROM database\", \"SHOW TABLES FROM schema\", or "
"\"SHOW TABLES FROM database.schema\"");
}
if (qualified_name.schema.empty()) {
showref->schema_name = qualified_name.name;
} else {
showref->catalog_name = qualified_name.schema;
showref->schema_name = qualified_name.name;
}
} else {
// describing a set (e.g. SHOW ALL TABLES) - push it in the table name
showref->table_name = stmt.set;
}
} else if (!stmt.relation->schemaname) {
// describing an unqualified relation - check if this is a "special" relation
string table_name = StringUtil::Lower(stmt.relation->relname);
if (table_name == "databases" || table_name == "tables" || table_name == "variables") {
showref->table_name = "\"" + std::move(table_name) + "\"";
}
}
if (showref->table_name.empty()) {
if (showref->table_name.empty() && showref->show_type != ShowType::SHOW_FROM) {
// describing a single relation
// wrap the relation in a "SELECT * FROM [table_name]" query
auto show_select_node = make_uniq<SelectNode>();
Expand All @@ -34,7 +49,10 @@ unique_ptr<QueryNode> Transformer::TransformShow(duckdb_libpgquery::PGVariableSh
showref->query = std::move(show_select_node);
}

showref->show_type = stmt.is_summary ? ShowType::SUMMARY : ShowType::DESCRIBE;
// If the show type is set to default, check if summary
if (showref->show_type == ShowType::DESCRIBE) {
showref->show_type = stmt.is_summary ? ShowType::SUMMARY : ShowType::DESCRIBE;
}
select_node->from_table = std::move(showref);
return std::move(select_node);
}
Expand Down
30 changes: 30 additions & 0 deletions src/planner/binder/tableref/bind_showref.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
#include "duckdb/planner/operator/logical_get.hpp"
#include "duckdb/planner/operator/logical_projection.hpp"
#include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp"
#include "duckdb/catalog/catalog.hpp"
#include "duckdb/catalog/catalog_search_path.hpp"
#include "duckdb/main/client_data.hpp"
#include "duckdb/main/client_context.hpp"

namespace duckdb {

Expand Down Expand Up @@ -151,6 +155,32 @@ unique_ptr<BoundTableRef> Binder::BindShowTable(ShowRef &ref) {
sql = PragmaShowDatabases();
} else if (lname == "\"tables\"") {
sql = PragmaShowTables();
} else if (ref.show_type == ShowType::SHOW_FROM) {
auto catalog_name = ref.catalog_name;
auto schema_name = ref.schema_name;

// Check for unqualified name, promote schema to catalog if unambiguous, and set schema_name to empty if so
Binder::BindSchemaOrCatalog(catalog_name, schema_name);

// If fully qualified, check if the schema exists
if (!catalog_name.empty() && !schema_name.empty()) {
auto schema_entry = Catalog::GetSchema(context, catalog_name, schema_name, OnEntryNotFound::RETURN_NULL);
if (!schema_entry) {
throw CatalogException("SHOW TABLES FROM: No catalog + schema named \"%s.%s\" found.", catalog_name,
schema_name);
}
} else if (catalog_name.empty() && !schema_name.empty()) {
// We have a schema name, use default catalog
auto &client_data = ClientData::Get(context);
auto &default_entry = client_data.catalog_search_path->GetDefault();
catalog_name = default_entry.catalog;
auto schema_entry = Catalog::GetSchema(context, catalog_name, schema_name, OnEntryNotFound::RETURN_NULL);
if (!schema_entry) {
throw CatalogException("SHOW TABLES FROM: No catalog + schema named \"%s.%s\" found.", catalog_name,
schema_name);
}
}
sql = PragmaShowTables(catalog_name, schema_name);
} else if (lname == "\"variables\"") {
sql = PragmaShowVariables();
} else if (lname == "__show_tables_expanded") {
Expand Down
4 changes: 4 additions & 0 deletions src/storage/serialization/serialize_tableref.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,17 @@ void ShowRef::Serialize(Serializer &serializer) const {
serializer.WritePropertyWithDefault<string>(200, "table_name", table_name);
serializer.WritePropertyWithDefault<unique_ptr<QueryNode>>(201, "query", query);
serializer.WriteProperty<ShowType>(202, "show_type", show_type);
serializer.WritePropertyWithDefault<string>(203, "catalog_name", catalog_name);
serializer.WritePropertyWithDefault<string>(204, "schema_name", schema_name);
}

unique_ptr<TableRef> ShowRef::Deserialize(Deserializer &deserializer) {
auto result = duckdb::unique_ptr<ShowRef>(new ShowRef());
deserializer.ReadPropertyWithDefault<string>(200, "table_name", result->table_name);
deserializer.ReadPropertyWithDefault<unique_ptr<QueryNode>>(201, "query", result->query);
deserializer.ReadProperty<ShowType>(202, "show_type", result->show_type);
deserializer.ReadPropertyWithDefault<string>(203, "catalog_name", result->catalog_name);
deserializer.ReadPropertyWithDefault<string>(204, "schema_name", result->schema_name);
return std::move(result);
}

Expand Down
116 changes: 116 additions & 0 deletions test/sql/pragma/test_show_tables_from.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# name: test/sql/pragma/test_show_tables_from.test
# description: Test SHOW TABLES FROM syntax
# group: [pragma]

statement ok
PRAGMA enable_verification

statement ok
ATTACH IF NOT EXISTS ':memory:' AS db

statement ok
USE db

statement ok
CREATE TABLE main_table1(i INTEGER)

statement ok
CREATE SCHEMA test_schema

statement ok
CREATE TABLE test_schema.test_schema_table1(k INTEGER)

statement ok
ATTACH DATABASE ':memory:' AS db1

statement ok
CREATE TABLE db1.db1_table1(m INTEGER)

statement ok
CREATE SCHEMA db1.db1_schema

statement ok
CREATE TABLE db1.db1_schema.db1_schema_table1(n INTEGER)

statement ok
ATTACH DATABASE ':memory:' AS "db_quo""ted"

statement ok
CREATE SCHEMA "db_quo""ted"."db_quo""ted_schema";

statement ok
CREATE TABLE "db_quo""ted"."db_quo""ted_schema"."db_quo""ted_table1"(m INTEGER)

# Test basic SHOW TABLES FROM database syntax
query I
SHOW TABLES FROM db.main
----
main_table1

query I
SHOW TABLES FROM db1
----
db1_schema_table1
db1_table1

query I
SHOW TABLES FROM test_schema
----
test_schema_table1

query I
SHOW TABLES FROM db1.main
----
db1_table1

query I
SHOW TABLES FROM db1.db1_schema
----
db1_schema_table1

# Test with case insensitive database/schema names
query I
SHOW TABLES FROM DB1
----
db1_schema_table1
db1_table1

query I
SHOW TABLES FROM DB1.DB1_SCHEMA
----
db1_schema_table1

query I
SHOW TABLES FROM db1.DB1_SCHEMA
----
db1_schema_table1

# Test with quoted identifiers
statement ok
CREATE SCHEMA "Quoted Schema"

statement ok
CREATE TABLE "Quoted Schema"."Quoted Table"(r INTEGER)

query I
SHOW TABLES FROM db."Quoted Schema"
----
Quoted Table

# Test with quotes in identifiers
query I
SHOW TABLES FROM "db_quo""ted"."db_quo""ted_schema"
----
db_quo"ted_table1

# Errors
statement error
SHOW TABLES FROM nonexistent_db
----
Catalog Error: SHOW TABLES FROM: No catalog + schema named "db.nonexistent_db" found

# Test non-existent schema
statement error
SHOW TABLES FROM main.nonexistent_schema
----
Catalog Error: SHOW TABLES FROM: No catalog + schema named "main.nonexistent_schema" found
12 changes: 10 additions & 2 deletions third_party/libpg_query/grammar/statements/variable_show.y
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* allows SET or RESET without LOCAL */
VariableShowStmt:
show_or_describe SelectStmt {
show_or_describe SelectStmt {
PGVariableShowSelectStmt *n = makeNode(PGVariableShowSelectStmt);
n->stmt = $2;
n->name = (char*) "select";
Expand All @@ -21,7 +21,15 @@ VariableShowStmt:
n->is_summary = 1;
$$ = (PGNode *) n;
}
| show_or_describe qualified_name
| show_or_describe TABLES FROM qualified_name
{
PGVariableShowStmt *n = makeNode(PGVariableShowStmt);
n->relation = $4;
n->set = (char*) "__show_tables_from_database";
n->is_summary = 0;
$$ = (PGNode *) n;
}
| show_or_describe qualified_name
{
PGVariableShowStmt *n = makeNode(PGVariableShowStmt);
n->relation = $2;
Expand Down
Loading
Loading