Merge pull request #1901 from zhang2014/fix/ISSUES-117

ISSUES-117 add show create & exist temporary table
This commit is contained in:
alexey-milovidov 2018-03-07 22:53:11 +03:00 committed by GitHub
commit 1ecb9dac72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 72 additions and 23 deletions

View File

@ -673,6 +673,11 @@ bool Context::isDatabaseExist(const String & database_name) const
return shared->databases.end() != shared->databases.find(db);
}
bool Context::isExternalTableExist(const String & table_name) const
{
return external_tables.end() != external_tables.find(table_name);
}
void Context::assertTableExists(const String & database_name, const String & table_name) const
{
@ -733,7 +738,10 @@ Tables Context::getExternalTables() const
{
auto lock = getLock();
Tables res = external_tables;
Tables res;
for (auto & table : external_tables)
res[table.first] = table.second.first;
if (session_context && session_context != this)
{
Tables buf = session_context->getExternalTables();
@ -750,10 +758,11 @@ Tables Context::getExternalTables() const
StoragePtr Context::tryGetExternalTable(const String & table_name) const
{
auto it = external_tables.find(table_name);
if (external_tables.end() == it)
TableAndCreateASTs::const_iterator jt = external_tables.find(table_name);
if (external_tables.end() == jt)
return StoragePtr();
return it->second;
return jt->second.first;
}
@ -807,12 +816,12 @@ StoragePtr Context::getTableImpl(const String & database_name, const String & ta
}
void Context::addExternalTable(const String & table_name, const StoragePtr & storage)
void Context::addExternalTable(const String & table_name, const StoragePtr & storage, const ASTPtr & ast)
{
if (external_tables.end() != external_tables.find(table_name))
throw Exception("Temporary table " + table_name + " already exists.", ErrorCodes::TABLE_ALREADY_EXISTS);
external_tables[table_name] = storage;
external_tables[table_name] = std::pair(storage, ast);
if (process_list_elem)
{
@ -823,11 +832,12 @@ void Context::addExternalTable(const String & table_name, const StoragePtr & sto
StoragePtr Context::tryRemoveExternalTable(const String & table_name)
{
auto it = external_tables.find(table_name);
TableAndCreateASTs::const_iterator it = external_tables.find(table_name);
if (external_tables.end() == it)
return StoragePtr();
auto storage = it->second;
auto storage = it->second.first;
external_tables.erase(it);
return storage;
}
@ -917,6 +927,15 @@ ASTPtr Context::getCreateQuery(const String & database_name, const String & tabl
return shared->databases[db]->getCreateQuery(*this, table_name);
}
ASTPtr Context::getCreateExternalQuery(const String & table_name) const
{
TableAndCreateASTs::const_iterator jt = external_tables.find(table_name);
if (external_tables.end() == jt)
throw Exception("Temporary Table" + table_name + " doesn't exist", ErrorCodes::UNKNOWN_TABLE);
return jt->second.second;
}
Settings Context::getSettings() const
{

View File

@ -77,6 +77,9 @@ using DatabaseAndTableName = std::pair<String, String>;
using ViewDependencies = std::map<DatabaseAndTableName, std::set<DatabaseAndTableName>>;
using Dependencies = std::vector<DatabaseAndTableName>;
using TableAndCreateAST = std::pair<StoragePtr, ASTPtr>;
using TableAndCreateASTs = std::map<String, TableAndCreateAST>;
/** A set of known objects that can be used in the query.
* Consists of a shared part (always common to all sessions and queries)
@ -103,7 +106,7 @@ private:
String default_format; /// Format, used when server formats data by itself and if query does not have FORMAT specification.
/// Thus, used in HTTP interface. If not specified - then some globally default format is used.
Tables external_tables; /// Temporary tables. Keyed by table name.
TableAndCreateASTs external_tables; /// Temporary tables.
Tables table_function_results; /// Temporary tables obtained by execution of table functions. Keyed by AST tree id.
Context * query_context = nullptr;
Context * session_context = nullptr; /// Session context or nullptr. Could be equal to this.
@ -165,6 +168,7 @@ public:
/// Checking the existence of the table/database. Database can be empty - in this case the current database is used.
bool isTableExist(const String & database_name, const String & table_name) const;
bool isDatabaseExist(const String & database_name) const;
bool isExternalTableExist(const String & table_name) const;
void assertTableExists(const String & database_name, const String & table_name) const;
/** The parameter check_database_access_rights exists to not check the permissions of the database again,
@ -180,7 +184,7 @@ public:
StoragePtr tryGetExternalTable(const String & table_name) const;
StoragePtr getTable(const String & database_name, const String & table_name) const;
StoragePtr tryGetTable(const String & database_name, const String & table_name) const;
void addExternalTable(const String & table_name, const StoragePtr & storage);
void addExternalTable(const String & table_name, const StoragePtr & storage, const ASTPtr & ast = {});
StoragePtr tryRemoveExternalTable(const String & table_name);
StoragePtr executeTableFunction(const ASTPtr & table_expression);
@ -240,6 +244,7 @@ public:
/// Get query for the CREATE table.
ASTPtr getCreateQuery(const String & database_name, const String & table_name) const;
ASTPtr getCreateExternalQuery(const String & table_name) const;
const DatabasePtr getDatabase(const String & database_name) const;
DatabasePtr getDatabase(const String & database_name);

View File

@ -538,7 +538,7 @@ BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create)
false);
if (create.is_temporary)
context.getSessionContext().addExternalTable(table_name, res);
context.getSessionContext().addExternalTable(table_name, res, query_ptr);
else
database->createTable(context, table_name, res, query_ptr);
}

View File

@ -33,7 +33,7 @@ Block InterpreterExistsQuery::getSampleBlock()
BlockInputStreamPtr InterpreterExistsQuery::executeImpl()
{
const ASTExistsQuery & ast = typeid_cast<const ASTExistsQuery &>(*query_ptr);
bool res = context.isTableExist(ast.database, ast.table);
bool res = ast.temporary ? context.isExternalTableExist(ast.table) : context.isTableExist(ast.database, ast.table);
return std::make_shared<OneBlockInputStream>(Block{{
ColumnUInt8::create(1, res),

View File

@ -11,10 +11,15 @@
#include <Interpreters/Context.h>
#include <Interpreters/InterpreterShowCreateQuery.h>
namespace DB
{
namespace ErrorCodes
{
extern const int SYNTAX_ERROR;
extern const int THERE_IS_NO_QUERY;
}
BlockIO InterpreterShowCreateQuery::execute()
{
BlockIO res;
@ -36,8 +41,17 @@ BlockInputStreamPtr InterpreterShowCreateQuery::executeImpl()
{
const ASTShowCreateQuery & ast = typeid_cast<const ASTShowCreateQuery &>(*query_ptr);
if (ast.temporary && !ast.database.empty())
throw Exception("Temporary databases are not possible.", ErrorCodes::SYNTAX_ERROR);
ASTPtr create_query = (ast.temporary ? context.getCreateExternalQuery(ast.table) :
context.getCreateQuery(ast.database, ast.table));
if (!create_query && ast.temporary)
throw Exception("Unable to show the create query of " + ast.table + ". Maybe it was created by the system.", ErrorCodes::THERE_IS_NO_QUERY);
std::stringstream stream;
formatAST(*context.getCreateQuery(ast.database, ast.table), stream, false, true);
formatAST(*create_query, stream, false, true);
String res = stream.str();
MutableColumnPtr column = ColumnString::create();

View File

@ -15,6 +15,7 @@ class ASTQueryWithTableAndOutput : public ASTQueryWithOutput
public:
String database;
String table;
bool temporary{false};
protected:
void formatHelper(const FormatSettings & settings, const char * name) const

View File

@ -14,6 +14,7 @@ namespace DB
bool ParserTablePropertiesQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
ParserKeyword s_exists("EXISTS");
ParserKeyword s_temporary("TEMPORARY");
ParserKeyword s_describe("DESCRIBE");
ParserKeyword s_desc("DESC");
ParserKeyword s_show("SHOW");
@ -42,6 +43,9 @@ bool ParserTablePropertiesQuery::parseImpl(Pos & pos, ASTPtr & node, Expected &
return false;
}
if (s_temporary.ignore(pos, expected))
query->temporary = true;
s_table.ignore(pos, expected);
if (!name_p.parse(pos, table, expected))

View File

@ -1,4 +0,0 @@
DROP TEMPORARY TABLE IF EXISTS temp_tab;
CREATE TEMPORARY TABLE temp_tab (number UInt64);
SHOW TEMPORARY TABLES LIKE 'temp_tab';
DROP TEMPORARY TABLE temp_tab;

View File

@ -0,0 +1,4 @@
1
CREATE TEMPORARY TABLE temp_tab ( number UInt64) ENGINE = Memory
temp_tab
0

View File

@ -0,0 +1,7 @@
DROP TEMPORARY TABLE IF EXISTS temp_tab;
CREATE TEMPORARY TABLE temp_tab (number UInt64);
EXISTS TEMPORARY TABLE temp_tab;
SHOW CREATE TEMPORARY TABLE temp_tab;
SHOW TEMPORARY TABLES LIKE 'temp_tab';
DROP TEMPORARY TABLE temp_tab;
EXISTS TEMPORARY TABLE temp_tab;

View File

@ -184,7 +184,7 @@ Deletes all tables inside the 'db' database, then deletes the 'db' database itse
If `IF EXISTS` is specified, it doesn't return an error if the database doesn't exist.
```sql
DROP TABLE [IF EXISTS] [db.]name [ON CLUSTER cluster]
DROP [TEMPORARY] TABLE [IF EXISTS] [db.]name [ON CLUSTER cluster]
```
Deletes the table.
@ -452,7 +452,7 @@ See also the section "Formats".
## SHOW TABLES
```sql
SHOW TABLES [FROM db] [LIKE 'pattern'] [INTO OUTFILE filename] [FORMAT format]
SHOW [TEMPORARY] TABLES [FROM db] [LIKE 'pattern'] [INTO OUTFILE filename] [FORMAT format]
```
Displays a list of tables
@ -499,7 +499,7 @@ watch -n1 "clickhouse-client --query='SHOW PROCESSLIST'"
## SHOW CREATE TABLE
```sql
SHOW CREATE TABLE [db.]table [INTO OUTFILE filename] [FORMAT format]
SHOW CREATE [TEMPORARY] TABLE [db.]table [INTO OUTFILE filename] [FORMAT format]
```
Returns a single `String`-type 'statement' column, which contains a single value the `CREATE` query used for creating the specified table.
@ -517,7 +517,7 @@ Nested data structures are output in "expanded" format. Each column is shown sep
## EXISTS
```sql
EXISTS TABLE [db.]name [INTO OUTFILE filename] [FORMAT format]
EXISTS [TEMPORARY] TABLE [db.]name [INTO OUTFILE filename] [FORMAT format]
```
Returns a single `UInt8`-type column, which contains the single value `0` if the table or database doesn't exist, or `1` if the table exists in the specified database.