Merge pull request #48017 from ClickHouse/rs/show_columns

MySQL compatibility: Implement `SHOW COLUMNS`
This commit is contained in:
Robert Schulze 2023-03-31 15:50:23 +02:00 committed by GitHub
commit 5d64841276
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 526 additions and 44 deletions

View File

@ -30,7 +30,7 @@ This statement is identical to the query:
SELECT name FROM system.databases [WHERE name [NOT] LIKE | ILIKE '<pattern>'] [LIMIT <N>] [INTO OUTFILE filename] [FORMAT format]
```
### Examples
**Examples**
Getting database names, containing the symbols sequence 'de' in their names:
@ -92,7 +92,7 @@ Result:
└────────────────────────────────┘
```
### See Also
**See also**
- [CREATE DATABASE](https://clickhouse.com/docs/en/sql-reference/statements/create/database/#query-language-create-database)
@ -128,7 +128,7 @@ This statement is identical to the query:
SELECT name FROM system.tables [WHERE name [NOT] LIKE | ILIKE '<pattern>'] [LIMIT <N>] [INTO OUTFILE <filename>] [FORMAT <format>]
```
### Examples
**Examples**
Getting table names, containing the symbols sequence 'user' in their names:
@ -191,11 +191,59 @@ Result:
└────────────────────────────────┘
```
### See Also
**See also**
- [Create Tables](https://clickhouse.com/docs/en/getting-started/tutorial/#create-tables)
- [SHOW CREATE TABLE](https://clickhouse.com/docs/en/sql-reference/statements/show/#show-create-table)
## SHOW COLUMNS
Displays a list of columns
```sql
SHOW [EXTENDED] [FULL] COLUMNS {FROM | IN} <table> [{FROM | IN} <db>] [{[NOT] {LIKE | ILIKE} '<pattern>' | WHERE <expr>}] [LIMIT <N>] [INTO
OUTFILE <filename>] [FORMAT <format>]
```
The database and table name can be specified in abbreviated form as `<db>.<table>`, i.e. `FROM tab FROM db` and `FROM db.tab` are
equivalent. If no database is specified, the query returns the list of columns from the current database.
The optional keyword `EXTENDED` currently has no effect, it only exists for MySQL compatibility.
The optional keyword `FULL` causes the output to include the collation, comment and privilege columns.
`SHOW COLUMNS` produces a result table with the following structure:
- field - The name of the column (String)
- type - The column data type (String)
- null - If the column data type is Nullable (UInt8)
- key - `PRI` if the column is part of the primary key, `SOR` if the column is part of the sorting key, empty otherwise (String)
- default - Default expression of the column if it is of type `ALIAS`, `DEFAULT`, or `MATERIALIZED`, otherwise `NULL`. (Nullable(String))
- extra - Additional information, currently unused (String)
- collation - Collation of the column, always `NULL` because ClickHouse has no per-column collations, only if `FULL` keyword was specified (Nullable(String))
- comment - Comment on the column, only if `FULL` keyword was specified (String)
- privilege - The privilege you have on this column, currently not available, only if `FULL` keyword was specified (String)
**Examples**
Getting information about all columns in table 'order' starting with 'delivery_':
```sql
SHOW COLUMNS FROM 'orders' LIKE 'delivery_%'
```
Result:
``` text
┌─field───────────┬─type─────┬─null─┬─key─────┬─default─┬─extra─┐
│ delivery_date │ DateTime │ 0 │ PRI SOR │ ᴺᵁᴸᴸ │ │
│ delivery_status │ Bool │ 0 │ │ ᴺᵁᴸᴸ │ │
└─────────────────┴──────────┴──────┴─────────┴─────────┴───────┘
```
**See also**
- [system.columns](https://clickhouse.com/docs/en/operations/system-tables/columns)
## SHOW DICTIONARIES
Displays a list of [Dictionaries](../../sql-reference/dictionaries/index.md).
@ -212,7 +260,7 @@ You can get the same results as the `SHOW DICTIONARIES` query in the following w
SELECT name FROM system.dictionaries WHERE database = <db> [AND name LIKE <pattern>] [LIMIT <N>] [INTO OUTFILE <filename>] [FORMAT <format>]
```
**Example**
**Examples**
The following query selects the first two rows from the list of tables in the `system` database, whose names contain `reg`.
@ -231,7 +279,7 @@ SHOW DICTIONARIES FROM db LIKE '%reg%' LIMIT 2
Shows privileges for a user.
### Syntax
**Syntax**
``` sql
SHOW GRANTS [FOR user1 [, user2 ...]]
@ -245,7 +293,7 @@ Shows parameters that were used at a [user creation](../../sql-reference/stateme
`SHOW CREATE USER` does not output user passwords.
### Syntax
**Syntax**
``` sql
SHOW CREATE USER [name1 [, name2 ...] | CURRENT_USER]
@ -255,7 +303,7 @@ SHOW CREATE USER [name1 [, name2 ...] | CURRENT_USER]
Shows parameters that were used at a [role creation](../../sql-reference/statements/create/role.md).
### Syntax
**Syntax**
``` sql
SHOW CREATE ROLE name1 [, name2 ...]
@ -265,7 +313,7 @@ SHOW CREATE ROLE name1 [, name2 ...]
Shows parameters that were used at a [row policy creation](../../sql-reference/statements/create/row-policy.md).
### Syntax
**Syntax**
``` sql
SHOW CREATE [ROW] POLICY name ON [database1.]table1 [, [database2.]table2 ...]
@ -275,7 +323,7 @@ SHOW CREATE [ROW] POLICY name ON [database1.]table1 [, [database2.]table2 ...]
Shows parameters that were used at a [quota creation](../../sql-reference/statements/create/quota.md).
### Syntax
**Syntax**
``` sql
SHOW CREATE QUOTA [name1 [, name2 ...] | CURRENT]
@ -285,7 +333,7 @@ SHOW CREATE QUOTA [name1 [, name2 ...] | CURRENT]
Shows parameters that were used at a [settings profile creation](../../sql-reference/statements/create/settings-profile.md).
### Syntax
**Syntax**
``` sql
SHOW CREATE [SETTINGS] PROFILE name1 [, name2 ...]
@ -295,7 +343,7 @@ SHOW CREATE [SETTINGS] PROFILE name1 [, name2 ...]
Returns a list of [user account](../../guides/sre/user-management/index.md#user-account-management) names. To view user accounts parameters, see the system table [system.users](../../operations/system-tables/users.md#system_tables-users).
### Syntax
**Syntax**
``` sql
SHOW USERS
@ -305,7 +353,7 @@ SHOW USERS
Returns a list of [roles](../../guides/sre/user-management/index.md#role-management). To view another parameters, see system tables [system.roles](../../operations/system-tables/roles.md#system_tables-roles) and [system.role_grants](../../operations/system-tables/role-grants.md#system_tables-role_grants).
### Syntax
**Syntax**
``` sql
SHOW [CURRENT|ENABLED] ROLES
@ -314,7 +362,7 @@ SHOW [CURRENT|ENABLED] ROLES
Returns a list of [setting profiles](../../guides/sre/user-management/index.md#settings-profiles-management). To view user accounts parameters, see the system table [settings_profiles](../../operations/system-tables/settings_profiles.md#system_tables-settings_profiles).
### Syntax
**Syntax**
``` sql
SHOW [SETTINGS] PROFILES
@ -324,7 +372,7 @@ SHOW [SETTINGS] PROFILES
Returns a list of [row policies](../../guides/sre/user-management/index.md#row-policy-management) for the specified table. To view user accounts parameters, see the system table [system.row_policies](../../operations/system-tables/row_policies.md#system_tables-row_policies).
### Syntax
**Syntax**
``` sql
SHOW [ROW] POLICIES [ON [db.]table]
@ -334,7 +382,7 @@ SHOW [ROW] POLICIES [ON [db.]table]
Returns a list of [quotas](../../guides/sre/user-management/index.md#quotas-management). To view quotas parameters, see the system table [system.quotas](../../operations/system-tables/quotas.md#system_tables-quotas).
### Syntax
**Syntax**
``` sql
SHOW QUOTAS
@ -344,7 +392,7 @@ SHOW QUOTAS
Returns a [quota](../../operations/quotas.md) consumption for all users or for current user. To view another parameters, see system tables [system.quotas_usage](../../operations/system-tables/quotas_usage.md#system_tables-quotas_usage) and [system.quota_usage](../../operations/system-tables/quota_usage.md#system_tables-quota_usage).
### Syntax
**Syntax**
``` sql
SHOW [CURRENT] QUOTA
@ -353,7 +401,7 @@ SHOW [CURRENT] QUOTA
Shows all [users](../../guides/sre/user-management/index.md#user-account-management), [roles](../../guides/sre/user-management/index.md#role-management), [profiles](../../guides/sre/user-management/index.md#settings-profiles-management), etc. and all their [grants](../../sql-reference/statements/grant.md#grant-privileges).
### Syntax
**Syntax**
``` sql
SHOW ACCESS
@ -366,13 +414,14 @@ Returns a list of clusters. All available clusters are listed in the [system.clu
`SHOW CLUSTER name` query displays the contents of system.clusters table for this cluster.
:::
### Syntax
**Syntax**
``` sql
SHOW CLUSTER '<name>'
SHOW CLUSTERS [[NOT] LIKE|ILIKE '<pattern>'] [LIMIT <N>]
```
### Examples
**Examples**
Query:

View File

@ -21,6 +21,7 @@
#include <Parsers/ASTShowEngineQuery.h>
#include <Parsers/ASTShowProcesslistQuery.h>
#include <Parsers/ASTShowTablesQuery.h>
#include <Parsers/ASTShowColumnsQuery.h>
#include <Parsers/ASTUseQuery.h>
#include <Parsers/ASTWatchQuery.h>
#include <Parsers/ASTCreateNamedCollectionQuery.h>
@ -79,6 +80,7 @@
#include <Interpreters/InterpreterShowEngineQuery.h>
#include <Interpreters/InterpreterShowProcesslistQuery.h>
#include <Interpreters/InterpreterShowTablesQuery.h>
#include <Interpreters/InterpreterShowColumnsQuery.h>
#include <Interpreters/InterpreterSystemQuery.h>
#include <Interpreters/InterpreterUseQuery.h>
#include <Interpreters/InterpreterWatchQuery.h>
@ -175,6 +177,10 @@ std::unique_ptr<IInterpreter> InterpreterFactory::get(ASTPtr & query, ContextMut
{
return std::make_unique<InterpreterShowTablesQuery>(query, context);
}
else if (query->as<ASTShowColumnsQuery>())
{
return std::make_unique<InterpreterShowColumnsQuery>(query, context);
}
else if (query->as<ASTShowEnginesQuery>())
{
return std::make_unique<InterpreterShowEnginesQuery>(query, context);

View File

@ -0,0 +1,103 @@
#include <Interpreters/InterpreterShowColumnsQuery.h>
#include <IO/WriteBufferFromString.h>
#include <Parsers/ASTShowColumnsQuery.h>
#include <Parsers/formatAST.h>
#include <Interpreters/Context.h>
#include <Interpreters/executeQuery.h>
#include <IO/Operators.h>
#include <boost/algorithm/string.hpp>
namespace DB
{
InterpreterShowColumnsQuery::InterpreterShowColumnsQuery(const ASTPtr & query_ptr_, ContextMutablePtr context_)
: WithMutableContext(context_)
, query_ptr(query_ptr_)
{
}
String InterpreterShowColumnsQuery::getRewrittenQuery()
{
const auto & query = query_ptr->as<ASTShowColumnsQuery &>();
WriteBufferFromOwnString rewritten_query;
rewritten_query << "SELECT name AS field, type AS type, startsWith(type, 'Nullable') AS null, trim(concatWithSeparator(' ', if(is_in_primary_key, 'PRI', ''), if (is_in_sorting_key, 'SOR', ''))) AS key, if(default_kind IN ('ALIAS', 'DEFAULT', 'MATERIALIZED'), default_expression, NULL) AS default, '' AS extra ";
// TODO Interpret query.extended. It is supposed to show internal/virtual columns. Need to fetch virtual column names, see
// IStorage::getVirtuals(). We can't easily do that via SQL.
if (query.full)
{
/// "Full" mode is mostly for MySQL compat
/// - collation: no such thing in ClickHouse
/// - comment
/// - privileges: <not implemented, TODO ask system.grants>
rewritten_query << ", NULL AS collation, comment, '' AS privileges ";
}
rewritten_query << "FROM system.columns WHERE ";
String database;
String table;
if (query.from_table.contains("."))
{
/// FROM <db>.<table> (abbreviated form)
chassert(query.from_database.empty());
std::vector<String> split;
boost::split(split, query.from_table, boost::is_any_of("."));
chassert(split.size() == 2);
database = split[0];
table = split[1];
}
else if (query.from_database.empty())
{
/// FROM <table>
chassert(!query.from_table.empty());
database = getContext()->getCurrentDatabase();
table = query.from_table;
}
else
{
/// FROM <database> FROM <table>
chassert(!query.from_database.empty());
chassert(!query.from_table.empty());
database = query.from_database;
table = query.from_table;
}
rewritten_query << "database = " << DB::quote << database;
rewritten_query << " AND table = " << DB::quote << table;
if (!query.like.empty())
rewritten_query
<< " AND name "
<< (query.not_like ? "NOT " : "")
<< (query.case_insensitive_like ? "ILIKE " : "LIKE ")
<< DB::quote << query.like;
else if (query.where_expression)
rewritten_query << " AND (" << query.where_expression << ")";
/// Sorting is strictly speaking not necessary but 1. it is convenient for users, 2. SQL currently does not allow to
/// sort the output of SHOW COLUMNS otherwise (SELECT * FROM (SHOW COLUMNS ...) ORDER BY ...) is rejected) and 3. some
/// SQL tests can take advantage of this.
rewritten_query << " ORDER BY field, type, null, key, default, extra";
if (query.limit_length)
rewritten_query << " LIMIT " << query.limit_length;
return rewritten_query.str();
}
BlockIO InterpreterShowColumnsQuery::execute()
{
return executeQuery(getRewrittenQuery(), getContext(), true);
}
}

View File

@ -0,0 +1,32 @@
#pragma once
#include <Interpreters/IInterpreter.h>
#include <Parsers/IAST_fwd.h>
namespace DB
{
class Context;
/// Returns a list of columns which meet some conditions.
class InterpreterShowColumnsQuery : public IInterpreter, WithMutableContext
{
public:
InterpreterShowColumnsQuery(const ASTPtr & query_ptr_, ContextMutablePtr context_);
BlockIO execute() override;
/// Ignore quota and limits here because execute() produces a SELECT query which checks quotas/limits by itself.
bool ignoreQuota() const override { return true; }
bool ignoreLimits() const override { return true; }
private:
ASTPtr query_ptr;
String getRewrittenQuery();
};
}

View File

@ -1,4 +1,4 @@
#include <IO/ReadBufferFromString.h>
#include <IO/WriteBufferFromString.h>
#include <Parsers/ASTShowTablesQuery.h>
#include <Parsers/formatAST.h>
#include <Interpreters/Context.h>
@ -24,7 +24,8 @@ namespace ErrorCodes
InterpreterShowTablesQuery::InterpreterShowTablesQuery(const ASTPtr & query_ptr_, ContextMutablePtr context_)
: WithMutableContext(context_), query_ptr(query_ptr_)
: WithMutableContext(context_)
, query_ptr(query_ptr_)
{
}

View File

@ -20,8 +20,7 @@ public:
BlockIO execute() override;
/// We ignore the quota and limits here because execute() will rewrite a show query as a SELECT query and then
/// the SELECT query will checks the quota and limits.
/// Ignore quota and limits here because execute() produces a SELECT query which checks quotas/limits by itself.
bool ignoreQuota() const override { return true; }
bool ignoreLimits() const override { return true; }

View File

@ -17,17 +17,21 @@ class ASTTableIdentifier;
void setIdentifierSpecial(ASTPtr & ast);
String getIdentifierName(const IAST * ast);
std::optional<String> tryGetIdentifierName(const IAST * ast);
bool tryGetIdentifierNameInto(const IAST * ast, String & name);
inline String getIdentifierName(const ASTPtr & ast)
{
return getIdentifierName(ast.get());
}
inline std::optional<String> tryGetIdentifierName(const ASTPtr & ast)
{
return tryGetIdentifierName(ast.get());
}
inline bool tryGetIdentifierNameInto(const ASTPtr & ast, String & name)
{
return tryGetIdentifierNameInto(ast.get(), name);

View File

@ -0,0 +1,53 @@
#include <Parsers/ASTShowColumnsQuery.h>
#include <iomanip>
#include <Common/quoteString.h>
#include <IO/Operators.h>
namespace DB
{
ASTPtr ASTShowColumnsQuery::clone() const
{
auto res = std::make_shared<ASTShowColumnsQuery>(*this);
res->children.clear();
cloneOutputOptions(*res);
return res;
}
void ASTShowColumnsQuery::formatQueryImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const
{
settings.ostr << (settings.hilite ? hilite_keyword : "")
<< "SHOW "
<< (extended ? "EXTENDED " : "")
<< (full ? "FULL " : "")
<< "COLUMNS"
<< (settings.hilite ? hilite_none : "");
if (from_database.empty())
settings.ostr << (settings.hilite ? hilite_keyword : "") << " FROM " << (settings.hilite ? hilite_none : "") << backQuoteIfNeed(from_table);
else
settings.ostr << (settings.hilite ? hilite_keyword : "") << " FROM " << (settings.hilite ? hilite_none : "") << backQuoteIfNeed(from_database) << "." << backQuoteIfNeed(from_table);
if (!like.empty())
settings.ostr << (settings.hilite ? hilite_keyword : "")
<< (not_like ? " NOT " : "")
<< (case_insensitive_like ? " ILIKE " : " LIKE")
<< (settings.hilite ? hilite_none : "")
<< DB::quote << like;
if (where_expression)
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << " WHERE " << (settings.hilite ? hilite_none : "");
where_expression->formatImpl(settings, state, frame);
}
if (limit_length)
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << " LIMIT " << (settings.hilite ? hilite_none : "");
limit_length->formatImpl(settings, state, frame);
}
}
}

View File

@ -0,0 +1,34 @@
#pragma once
#include <Parsers/IAST_fwd.h>
#include <Parsers/ASTQueryWithOutput.h>
namespace DB
{
/// Query SHOW COLUMNS
class ASTShowColumnsQuery : public ASTQueryWithOutput
{
public:
bool extended = false;
bool full = false;
bool not_like = false;
bool case_insensitive_like = false;
ASTPtr where_expression;
ASTPtr limit_length;
String from_database;
String from_table;
String like;
String getID(char) const override { return "ShowColumns"; }
ASTPtr clone() const override;
QueryKind getQueryKind() const override { return QueryKind::Show; }
protected:
void formatQueryImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const override;
};
}

View File

@ -14,31 +14,28 @@ namespace DB
class ASTShowTablesQuery : public ASTQueryWithOutput
{
public:
bool databases{false};
bool clusters{false};
bool cluster{false};
bool dictionaries{false};
bool m_settings{false};
bool changed{false};
bool temporary{false};
bool caches{false};
bool full{false};
bool databases = false;
bool clusters = false;
bool cluster = false;
bool dictionaries = false;
bool m_settings = false;
bool changed = false;
bool temporary = false;
bool caches = false;
bool full = false;
String cluster_str;
String from;
String like;
bool not_like{false};
bool case_insensitive_like{false};
bool not_like = false;
bool case_insensitive_like = false;
ASTPtr where_expression;
ASTPtr limit_length;
/** Get the text that identifies this element. */
String getID(char) const override { return "ShowTables"; }
ASTPtr clone() const override;
QueryKind getQueryKind() const override { return QueryKind::Show; }
protected:

View File

@ -16,6 +16,7 @@
#include <Parsers/ParserSetQuery.h>
#include <Parsers/ParserShowProcesslistQuery.h>
#include <Parsers/ParserShowTablesQuery.h>
#include <Parsers/ParserShowColumnsQuery.h>
#include <Parsers/ParserShowEngineQuery.h>
#include <Parsers/ParserTablePropertiesQuery.h>
#include <Parsers/ParserWatchQuery.h>
@ -35,6 +36,7 @@ namespace DB
bool ParserQueryWithOutput::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
ParserShowTablesQuery show_tables_p;
ParserShowColumnsQuery show_columns_p;
ParserShowEnginesQuery show_engine_p;
ParserSelectWithUnionQuery select_p;
ParserTablePropertiesQuery table_p;
@ -64,6 +66,7 @@ bool ParserQueryWithOutput::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
|| select_p.parse(pos, query, expected)
|| show_create_access_entity_p.parse(pos, query, expected) /// should be before `show_tables_p`
|| show_tables_p.parse(pos, query, expected)
|| show_columns_p.parse(pos, query, expected)
|| show_engine_p.parse(pos, query, expected)
|| table_p.parse(pos, query, expected)
|| describe_cache_p.parse(pos, query, expected)

View File

@ -0,0 +1,80 @@
#include <Parsers/ParserShowColumnsQuery.h>
#include <Parsers/ASTIdentifier_fwd.h>
#include <Parsers/ASTLiteral.h>
#include <Parsers/ASTShowColumnsQuery.h>
#include <Parsers/CommonParsers.h>
#include <Parsers/ExpressionElementParsers.h>
#include <Parsers/ExpressionListParsers.h>
namespace DB
{
bool ParserShowColumnsQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
ASTPtr like;
ASTPtr from_db;
ASTPtr from_table;
auto query = std::make_shared<ASTShowColumnsQuery>();
if (!ParserKeyword("SHOW").ignore(pos, expected))
return false;
if (ParserKeyword("EXTENDED").ignore(pos, expected))
query->extended = true;
if (ParserKeyword("FULL").ignore(pos, expected))
query->full = true;
if (!ParserKeyword("COLUMNS").ignore(pos, expected) || ParserKeyword("FIELDS").ignore(pos, expected))
return false;
if (ParserKeyword("FROM").ignore(pos, expected) || ParserKeyword("IN").ignore(pos, expected))
{
if (!ParserCompoundIdentifier().parse(pos, from_table, expected))
return false;
}
else
return false;
tryGetIdentifierNameInto(from_table, query->from_table);
bool abbreviated_form = query->from_table.contains("."); /// FROM <db>.<table>
if (!abbreviated_form)
if (ParserKeyword("FROM").ignore(pos, expected) || ParserKeyword("IN").ignore(pos, expected))
if (!ParserIdentifier().parse(pos, from_db, expected))
return false;
tryGetIdentifierNameInto(from_db, query->from_database);
if (ParserKeyword("NOT").ignore(pos, expected))
query->not_like = true;
if (bool insensitive = ParserKeyword("ILIKE").ignore(pos, expected); insensitive || ParserKeyword("LIKE").ignore(pos, expected))
{
if (insensitive)
query->case_insensitive_like = true;
if (!ParserStringLiteral().parse(pos, like, expected))
return false;
}
else if (query->not_like)
return false;
else if (ParserKeyword("WHERE").ignore(pos, expected))
if (!ParserExpressionWithOptionalAlias(false).parse(pos, query->where_expression, expected))
return false;
if (ParserKeyword("LIMIT").ignore(pos, expected))
if (!ParserExpressionWithOptionalAlias(false).parse(pos, query->limit_length, expected))
return false;
if (like)
query->like = like->as<ASTLiteral &>().value.safeGet<const String &>();
node = query;
return true;
}
}

View File

@ -0,0 +1,19 @@
#pragma once
#include <Parsers/IParserBase.h>
namespace DB
{
/** Parses queries of the form
* SHOW [EXTENDED] [FULL] COLUMNS (FROM|IN) tbl [(FROM|IN) db] [(([NOT] (LIKE|ILIKE) expr) | (WHERE expr))] [LIMIT n]
*/
class ParserShowColumnsQuery : public IParserBase
{
protected:
const char * getName() const override { return "SHOW COLUMNS query"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
}

View File

@ -149,10 +149,8 @@ bool ParserShowTablesQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
}
if (s_from.ignore(pos, expected) || s_in.ignore(pos, expected))
{
if (!name_p.parse(pos, database, expected))
return false;
}
if (s_not.ignore(pos, expected))
query->not_like = true;
@ -168,16 +166,12 @@ bool ParserShowTablesQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
else if (query->not_like)
return false;
else if (s_where.ignore(pos, expected))
{
if (!exp_elem.parse(pos, query->where_expression, expected))
return false;
}
if (s_limit.ignore(pos, expected))
{
if (!exp_elem.parse(pos, query->limit_length, expected))
return false;
}
}
tryGetIdentifierNameInto(database, query->from);

View File

@ -0,0 +1,38 @@
int32 Nullable(Int32) 1 \N
str String 0 SOR \N
uint64 UInt64 0 PRI SOR \N
--- EXTENDED
int32 Nullable(Int32) 1 \N
str String 0 SOR \N
uint64 UInt64 0 PRI SOR \N
--- FULL
int32 Nullable(Int32) 1 \N \N example comment
str String 0 SOR \N \N
uint64 UInt64 0 PRI SOR \N \N
--- LIKE
int32 Nullable(Int32) 1 \N
uint64 UInt64 0 PRI SOR \N
--- NOT LIKE
str String 0 SOR \N
--- ILIKE
int32 Nullable(Int32) 1 \N
uint64 UInt64 0 PRI SOR \N
--- NOT ILIKE
str String 0 SOR \N
--- WHERE
int32 Nullable(Int32) 1 \N
uint64 UInt64 0 PRI SOR \N
--- LIMIT
int32 Nullable(Int32) 1 \N
--- Original table
int32 Nullable(Int32) 1 \N
str String 0 SOR \N
uint64 UInt64 0 PRI SOR \N
--- Equally named table in other database
int32 Int32 0 \N
str String 0 \N
uint64 UInt64 0 PRI SOR \N
--- Short form
int32 Int32 0 \N
str String 0 \N
uint64 UInt64 0 PRI SOR \N

View File

@ -0,0 +1,70 @@
-- Tags: no-parallel
-- no-parallel: creates a custom database schema and expects to use it exclusively
-- Create a test table and verify that the output of SHOW COLUMNS is sane.
-- The matching of actual/expected results relies on the fact that the output of SHOW COLUMNS is sorted.
DROP TABLE IF EXISTS tab;
CREATE TABLE tab
(
`uint64` UInt64,
`int32` Nullable(Int32) COMMENT 'example comment',
`str` String,
INDEX idx str TYPE set(1000)
)
ENGINE = MergeTree
PRIMARY KEY (uint64)
ORDER BY (uint64, str);
SHOW COLUMNS FROM tab;
SELECT '--- EXTENDED';
SHOW EXTENDED COLUMNS FROM tab;
SELECT '--- FULL';
SHOW FULL COLUMNS FROM tab;
SELECT '--- LIKE';
SHOW COLUMNS FROM tab LIKE '%int%';
SELECT '--- NOT LIKE';
SHOW COLUMNS FROM tab NOT LIKE '%int%';
SELECT '--- ILIKE';
SHOW COLUMNS FROM tab ILIKE '%INT%';
SELECT '--- NOT ILIKE';
SHOW COLUMNS FROM tab NOT ILIKE '%INT%';
SELECT '--- WHERE';
SHOW COLUMNS FROM tab WHERE field LIKE '%int%';
SELECT '--- LIMIT';
SHOW COLUMNS FROM tab LIMIT 1;
-- Create a table in a different database. Intentionally useing the same table/column names as above so
-- we notice if something is buggy in the implementation of SHOW COLUMNS.
DROP DATABASE IF EXISTS database_123456789abcde;
CREATE DATABASE database_123456789abcde; -- pseudo-random database name
DROP TABLE IF EXISTS database_123456789abcde.tab;
CREATE TABLE database_123456789abcde.tab
(
`uint64` UInt64,
`int32` Int32,
`str` String
)
ENGINE = MergeTree
ORDER BY uint64;
SELECT '--- Original table';
SHOW COLUMNS FROM tab;
SELECT '--- Equally named table in other database';
SHOW COLUMNS FROM tab FROM database_123456789abcde;
SELECT '--- Short form';
SHOW COLUMNS FROM database_123456789abcde.tab;
DROP DATABASE database_123456789abcde;
DROP TABLE tab;