ClickHouse/dbms/src/Parsers/formatAST.cpp

403 lines
11 KiB
C++
Raw Normal View History

2010-06-28 13:44:42 +00:00
#include <sstream>
#include <boost/variant/static_visitor.hpp>
#include <Poco/NumberFormatter.h>
#include <mysqlxx/Manip.h>
2010-06-28 13:44:42 +00:00
2011-11-06 20:47:07 +00:00
#include <DB/IO/WriteBufferFromOStream.h>
#include <DB/IO/WriteHelpers.h>
2010-06-28 13:44:42 +00:00
#include <DB/Core/Exception.h>
#include <DB/Core/ErrorCodes.h>
#include <DB/Parsers/formatAST.h>
namespace DB
{
2011-11-07 02:10:34 +00:00
static const char * hilite_keyword = "\033[1;37m";
static const char * hilite_identifier = "\033[0;36m";
static const char * hilite_function = "\033[0;33m";
static const char * hilite_alias = "\033[0;32m";
static const char * hilite_none = "\033[0m";
2012-06-18 07:49:19 +00:00
// TODO: Правильно квотировать идентификаторы (в обратных кавычках, если идентификатор необычный).
2012-05-30 01:38:02 +00:00
void formatAST(const IAST & ast, std::ostream & s, size_t indent, bool hilite, bool one_line)
2010-06-28 13:44:42 +00:00
{
const ASTSelectQuery * select = dynamic_cast<const ASTSelectQuery *>(&ast);
if (select)
{
2012-05-30 01:38:02 +00:00
formatAST(*select, s, indent, hilite, one_line);
2010-06-28 13:44:42 +00:00
return;
}
2011-08-18 18:48:00 +00:00
2012-01-09 19:20:48 +00:00
const ASTInsertQuery * insert = dynamic_cast<const ASTInsertQuery *>(&ast);
if (insert)
{
2012-05-30 01:38:02 +00:00
formatAST(*insert, s, indent, hilite, one_line);
2012-01-09 19:20:48 +00:00
return;
}
2011-08-18 18:48:00 +00:00
const ASTCreateQuery * create = dynamic_cast<const ASTCreateQuery *>(&ast);
if (create)
{
2012-05-30 01:38:02 +00:00
formatAST(*create, s, indent, hilite, one_line);
2011-08-18 18:48:00 +00:00
return;
}
2012-01-09 19:20:48 +00:00
const ASTDropQuery * drop = dynamic_cast<const ASTDropQuery *>(&ast);
if (drop)
{
2012-05-30 01:38:02 +00:00
formatAST(*drop, s, indent, hilite, one_line);
2012-01-09 19:20:48 +00:00
return;
}
2012-06-18 06:19:13 +00:00
const ASTRenameQuery * rename = dynamic_cast<const ASTRenameQuery *>(&ast);
if (rename)
{
formatAST(*rename, s, indent, hilite, one_line);
return;
}
2012-06-18 07:49:19 +00:00
const ASTShowTablesQuery * show_tables = dynamic_cast<const ASTShowTablesQuery *>(&ast);
if (show_tables)
{
formatAST(*show_tables, s, indent, hilite, one_line);
return;
}
2010-06-28 13:44:42 +00:00
const ASTExpressionList * exp_list = dynamic_cast<const ASTExpressionList *>(&ast);
if (exp_list)
{
2012-05-30 01:38:02 +00:00
formatAST(*exp_list, s, indent, hilite, one_line);
2010-06-28 13:44:42 +00:00
return;
}
const ASTFunction * func = dynamic_cast<const ASTFunction *>(&ast);
if (func)
{
2012-05-30 01:38:02 +00:00
formatAST(*func, s, indent, hilite, one_line);
2010-06-28 13:44:42 +00:00
return;
}
const ASTIdentifier * id = dynamic_cast<const ASTIdentifier *>(&ast);
if (id)
{
2012-05-30 01:38:02 +00:00
formatAST(*id, s, indent, hilite, one_line);
2010-06-28 13:44:42 +00:00
return;
}
const ASTLiteral * lit = dynamic_cast<const ASTLiteral *>(&ast);
if (lit)
{
2012-05-30 01:38:02 +00:00
formatAST(*lit, s, indent, hilite, one_line);
2010-06-28 13:44:42 +00:00
return;
}
2011-08-18 18:48:00 +00:00
const ASTNameTypePair * ntp = dynamic_cast<const ASTNameTypePair *>(&ast);
if (ntp)
{
2012-05-30 01:38:02 +00:00
formatAST(*ntp, s, indent, hilite, one_line);
2011-08-18 18:48:00 +00:00
return;
}
2011-08-28 08:50:27 +00:00
const ASTAsterisk * asterisk = dynamic_cast<const ASTAsterisk *>(&ast);
if (asterisk)
{
2012-05-30 01:38:02 +00:00
formatAST(*asterisk, s, indent, hilite, one_line);
2011-08-28 08:50:27 +00:00
return;
}
2011-09-04 05:14:52 +00:00
const ASTOrderByElement * order_by_elem = dynamic_cast<const ASTOrderByElement *>(&ast);
if (order_by_elem)
{
2012-05-30 01:38:02 +00:00
formatAST(*order_by_elem, s, indent, hilite, one_line);
2011-09-04 05:14:52 +00:00
return;
}
2012-01-09 19:20:48 +00:00
throw DB::Exception("Unknown element in AST: " + std::string(ast.range.first, ast.range.second - ast.range.first), ErrorCodes::UNKNOWN_ELEMENT_IN_AST);
2010-06-28 13:44:42 +00:00
}
2012-05-30 01:38:02 +00:00
void formatAST(const ASTSelectQuery & ast, std::ostream & s, size_t indent, bool hilite, bool one_line)
2010-06-28 13:44:42 +00:00
{
2012-05-30 01:38:02 +00:00
std::string indent_str = one_line ? "" : std::string(4 * indent, ' ');
std::string nl_or_ws = one_line ? " " : "\n";
2011-11-07 02:10:34 +00:00
2012-05-21 20:38:34 +00:00
s << (hilite ? hilite_keyword : "") << indent_str << "SELECT " << (hilite ? hilite_none : "");
2012-05-30 01:38:02 +00:00
formatAST(*ast.select_expression_list, s, indent, hilite, one_line);
2011-08-28 00:31:30 +00:00
if (ast.table)
{
2012-05-30 01:38:02 +00:00
s << (hilite ? hilite_keyword : "") << nl_or_ws << indent_str << "FROM " << (hilite ? hilite_none : "");
2011-08-28 00:31:30 +00:00
if (ast.database)
{
2012-05-30 01:38:02 +00:00
formatAST(*ast.database, s, indent, hilite, one_line);
2011-08-28 00:31:30 +00:00
s << ".";
}
2011-11-07 02:10:34 +00:00
if (dynamic_cast<const ASTSelectQuery *>(&*ast.table))
{
2012-05-30 01:38:02 +00:00
if (one_line)
s << " (";
else
s << "\n" << indent_str << "(\n";
formatAST(*ast.table, s, indent + 1, hilite, one_line);
if (one_line)
s << ")";
else
s << "\n" << indent_str << ")";
2011-11-07 02:10:34 +00:00
}
else
2012-05-30 01:38:02 +00:00
formatAST(*ast.table, s, indent, hilite, one_line);
2011-08-28 00:31:30 +00:00
}
if (ast.where_expression)
{
2012-05-30 01:38:02 +00:00
s << (hilite ? hilite_keyword : "") << nl_or_ws << indent_str << "WHERE " << (hilite ? hilite_none : "");
formatAST(*ast.where_expression, s, indent, hilite, one_line);
2011-08-28 00:31:30 +00:00
}
if (ast.group_expression_list)
{
2012-05-30 01:38:02 +00:00
s << (hilite ? hilite_keyword : "") << nl_or_ws << indent_str << "GROUP BY " << (hilite ? hilite_none : "");
formatAST(*ast.group_expression_list, s, indent, hilite, one_line);
2011-08-28 00:31:30 +00:00
}
if (ast.having_expression)
{
2012-05-30 01:38:02 +00:00
s << (hilite ? hilite_keyword : "") << nl_or_ws << indent_str << "HAVING " << (hilite ? hilite_none : "");
formatAST(*ast.having_expression, s, indent, hilite, one_line);
2011-08-28 00:31:30 +00:00
}
if (ast.order_expression_list)
{
2012-05-30 01:38:02 +00:00
s << (hilite ? hilite_keyword : "") << nl_or_ws << indent_str << "ORDER BY " << (hilite ? hilite_none : "");
formatAST(*ast.order_expression_list, s, indent, hilite, one_line);
2011-08-28 00:31:30 +00:00
}
if (ast.limit_length)
{
2012-05-30 01:38:02 +00:00
s << (hilite ? hilite_keyword : "") << nl_or_ws << indent_str << "LIMIT " << (hilite ? hilite_none : "");
2011-08-28 00:31:30 +00:00
if (ast.limit_offset)
{
2012-05-30 01:38:02 +00:00
formatAST(*ast.limit_offset, s, indent, hilite, one_line);
2011-08-28 00:31:30 +00:00
s << ", ";
}
2012-05-30 01:38:02 +00:00
formatAST(*ast.limit_length, s, indent, hilite, one_line);
2011-08-28 00:31:30 +00:00
}
2011-10-30 05:19:41 +00:00
if (ast.format)
{
2012-05-30 01:38:02 +00:00
s << (hilite ? hilite_keyword : "") << nl_or_ws << indent_str << "FORMAT " << (hilite ? hilite_none : "");
formatAST(*ast.format, s, indent, hilite, one_line);
2011-10-30 05:19:41 +00:00
}
2010-06-28 13:44:42 +00:00
}
2012-05-30 01:38:02 +00:00
void formatAST(const ASTCreateQuery & ast, std::ostream & s, size_t indent, bool hilite, bool one_line)
2011-08-18 18:48:00 +00:00
{
2012-05-30 01:38:02 +00:00
std::string nl_or_ws = one_line ? " " : "\n";
2011-12-26 07:07:30 +00:00
if (!ast.database.empty() && ast.table.empty())
{
2012-05-21 20:38:34 +00:00
s << (hilite ? hilite_keyword : "") << (ast.attach ? "ATTACH DATABASE " : "CREATE DATABASE ") << (ast.if_not_exists ? "IF NOT EXISTS " : "") << (hilite ? hilite_none : "")
2011-12-26 07:07:30 +00:00
<< ast.database;
return;
}
2012-05-21 20:38:34 +00:00
s << (hilite ? hilite_keyword : "") << (ast.attach ? "ATTACH TABLE " : "CREATE TABLE ") << (ast.if_not_exists ? "IF NOT EXISTS " : "") << (hilite ? hilite_none : "")
2011-12-26 07:07:30 +00:00
<< (!ast.database.empty() ? ast.database + "." : "") << ast.table;
if (!ast.as_table.empty())
{
2012-05-21 20:38:34 +00:00
s << (hilite ? hilite_keyword : "") << " AS " << (hilite ? hilite_none : "")
2011-12-26 07:07:30 +00:00
<< (!ast.as_database.empty() ? ast.as_database + "." : "") << ast.as_table;
}
if (ast.columns)
{
2012-05-30 01:38:02 +00:00
if (one_line)
s << " (";
else
s << "\n(\n";
formatAST(*ast.columns, s, indent + 1, hilite, one_line);
2011-12-26 07:07:30 +00:00
s << ")";
}
if (ast.storage)
{
2012-05-21 20:38:34 +00:00
s << (hilite ? hilite_keyword : "") << " ENGINE" << (hilite ? hilite_none : "") << " = ";
2012-05-30 01:38:02 +00:00
formatAST(*ast.storage, s, indent, hilite, one_line);
2011-12-26 07:07:30 +00:00
}
if (ast.select)
{
2012-05-30 01:38:02 +00:00
s << (hilite ? hilite_keyword : "") << " AS" << nl_or_ws << (hilite ? hilite_none : "");
formatAST(*ast.select, s, indent, hilite, one_line);
2011-12-26 07:07:30 +00:00
}
2011-08-18 18:48:00 +00:00
}
2012-05-30 01:38:02 +00:00
void formatAST(const ASTDropQuery & ast, std::ostream & s, size_t indent, bool hilite, bool one_line)
2012-01-09 19:20:48 +00:00
{
2012-06-18 06:19:13 +00:00
if (ast.table.empty() && !ast.database.empty())
2012-01-09 19:20:48 +00:00
{
2012-05-21 20:38:34 +00:00
s << (hilite ? hilite_keyword : "") << (ast.detach ? "DETACH DATABASE " : "DROP DATABASE ") << (ast.if_exists ? "IF EXISTS " : "") << (hilite ? hilite_none : "") << ast.database;
2012-01-09 19:20:48 +00:00
return;
}
2012-06-18 06:19:13 +00:00
s << (hilite ? hilite_keyword : "") << (ast.detach ? "DETACH TABLE " : "DROP TABLE ") << (ast.if_exists ? "IF EXISTS " : "") << (hilite ? hilite_none : "")
<< (!ast.database.empty() ? ast.database + "." : "") << ast.table;
}
void formatAST(const ASTRenameQuery & ast, std::ostream & s, size_t indent, bool hilite, bool one_line)
{
s << (hilite ? hilite_keyword : "") << "RENAME TABLE " << (hilite ? hilite_none : "");
for (ASTRenameQuery::Elements::const_iterator it = ast.elements.begin(); it != ast.elements.end(); ++it)
{
if (it != ast.elements.begin())
s << ", ";
s << (!it->from.database.empty() ? it->from.database + "." : "") << it->from.table
<< (hilite ? hilite_keyword : "") << " TO " << (hilite ? hilite_none : "")
<< (!it->to.database.empty() ? it->to.database + "." : "") << it->to.table;
}
2012-01-09 19:20:48 +00:00
}
2012-06-18 07:49:19 +00:00
void formatAST(const ASTShowTablesQuery & ast, std::ostream & s, size_t indent, bool hilite, bool one_line)
{
if (ast.databases)
{
s << (hilite ? hilite_keyword : "") << "SHOW DATABASES" << (hilite ? hilite_none : "");
return;
}
s << (hilite ? hilite_keyword : "") << "SHOW TABLES" << (hilite ? hilite_none : "");
if (!ast.from.empty())
s << (hilite ? hilite_keyword : "") << " FROM " << (hilite ? hilite_none : "")
<< ast.from;
if (!ast.like.empty())
s << (hilite ? hilite_keyword : "") << " LIKE " << (hilite ? hilite_none : "")
<< mysqlxx::quote << ast.like;
}
2012-05-30 01:38:02 +00:00
void formatAST(const ASTInsertQuery & ast, std::ostream & s, size_t indent, bool hilite, bool one_line)
2011-10-30 05:19:41 +00:00
{
2012-05-21 20:38:34 +00:00
s << (hilite ? hilite_keyword : "") << "INSERT INTO " << (hilite ? hilite_none : "") << (!ast.database.empty() ? ast.database + "." : "") << ast.table;
2011-10-30 05:19:41 +00:00
if (ast.columns)
{
s << " (";
2012-05-30 01:38:02 +00:00
formatAST(*ast.columns, s, indent, hilite, one_line);
2011-10-30 05:19:41 +00:00
s << ")";
}
if (ast.select)
{
s << " ";
2012-05-30 01:38:02 +00:00
formatAST(*ast.select, s, indent, hilite, one_line);
2011-10-30 05:19:41 +00:00
}
else
{
if (!ast.format.empty())
{
2012-05-21 20:38:34 +00:00
s << (hilite ? hilite_keyword : "") << " FORMAT " << (hilite ? hilite_none : "") << ast.format;
2011-10-30 05:19:41 +00:00
}
else
{
2012-05-21 20:38:34 +00:00
s << (hilite ? hilite_keyword : "") << " VALUES" << (hilite ? hilite_none : "");
2011-10-30 05:19:41 +00:00
}
}
}
2012-05-30 01:38:02 +00:00
void formatAST(const ASTExpressionList & ast, std::ostream & s, size_t indent, bool hilite, bool one_line)
2010-06-28 13:44:42 +00:00
{
for (ASTs::const_iterator it = ast.children.begin(); it != ast.children.end(); ++it)
{
if (it != ast.children.begin())
s << ", ";
2012-05-30 01:38:02 +00:00
formatAST(**it, s, indent, hilite, one_line);
2010-06-28 13:44:42 +00:00
}
}
2012-05-30 01:38:02 +00:00
static void writeAlias(const String & name, std::ostream & s, bool hilite, bool one_line)
2011-11-06 20:47:07 +00:00
{
2012-05-21 20:38:34 +00:00
s << (hilite ? hilite_keyword : "") << " AS " << (hilite ? hilite_alias : "");
2011-11-07 02:10:34 +00:00
{
2012-06-18 07:49:19 +00:00
WriteBufferFromOStream wb(s, 32);
2011-11-07 02:10:34 +00:00
writeProbablyBackQuotedString(name, wb);
}
2012-05-21 20:38:34 +00:00
s << (hilite ? hilite_none : "");
2011-11-06 20:47:07 +00:00
}
2012-05-30 01:38:02 +00:00
void formatAST(const ASTFunction & ast, std::ostream & s, size_t indent, bool hilite, bool one_line)
2010-06-28 13:44:42 +00:00
{
2012-05-21 20:38:34 +00:00
s << (hilite ? hilite_function : "") << ast.name;
2011-08-18 18:48:00 +00:00
if (ast.arguments)
{
2012-05-21 20:38:34 +00:00
s << '(' << (hilite ? hilite_none : "");
2012-05-30 01:38:02 +00:00
formatAST(*ast.arguments, s, indent, hilite, one_line);
2012-05-21 20:38:34 +00:00
s << (hilite ? hilite_function : "") << ')';
2011-08-18 18:48:00 +00:00
}
2012-05-21 20:38:34 +00:00
s << (hilite ? hilite_none : "");
2011-11-06 20:47:07 +00:00
if (!ast.alias.empty())
2012-05-30 01:38:02 +00:00
writeAlias(ast.alias, s, hilite, one_line);
2010-06-28 13:44:42 +00:00
}
2012-05-30 01:38:02 +00:00
void formatAST(const ASTIdentifier & ast, std::ostream & s, size_t indent, bool hilite, bool one_line)
2010-06-28 13:44:42 +00:00
{
2012-05-21 20:38:34 +00:00
s << (hilite ? hilite_identifier : "");
2011-11-06 20:47:07 +00:00
{
2012-06-18 07:49:19 +00:00
WriteBufferFromOStream wb(s, 32);
2011-11-06 20:47:07 +00:00
writeProbablyBackQuotedString(ast.name, wb);
}
2012-05-21 20:38:34 +00:00
s << (hilite ? hilite_none : "");
2011-11-06 20:47:07 +00:00
if (!ast.alias.empty())
2012-05-30 01:38:02 +00:00
writeAlias(ast.alias, s, hilite, one_line);
2010-06-28 13:44:42 +00:00
}
2012-05-30 01:38:02 +00:00
void formatAST(const ASTLiteral & ast, std::ostream & s, size_t indent, bool hilite, bool one_line)
2010-06-28 13:44:42 +00:00
{
s << boost::apply_visitor(FieldVisitorToString(), ast.value);
2011-11-06 20:47:07 +00:00
if (!ast.alias.empty())
2012-05-30 01:38:02 +00:00
writeAlias(ast.alias, s, hilite, one_line);
2010-06-28 13:44:42 +00:00
}
2012-05-30 01:38:02 +00:00
void formatAST(const ASTNameTypePair & ast, std::ostream & s, size_t indent, bool hilite, bool one_line)
2011-08-18 18:48:00 +00:00
{
2012-05-30 01:38:02 +00:00
std::string indent_str = one_line ? "" : std::string(4 * indent, ' ');
std::string nl_or_ws = one_line ? " " : "\n";
2011-12-26 07:07:30 +00:00
s << indent_str << ast.name << " ";
2012-05-30 01:38:02 +00:00
formatAST(*ast.type, s, indent, hilite, one_line);
s << nl_or_ws;
2011-08-18 18:48:00 +00:00
}
2012-05-30 01:38:02 +00:00
void formatAST(const ASTAsterisk & ast, std::ostream & s, size_t indent, bool hilite, bool one_line)
2011-08-28 08:50:27 +00:00
{
s << "*";
}
2012-05-30 01:38:02 +00:00
void formatAST(const ASTOrderByElement & ast, std::ostream & s, size_t indent, bool hilite, bool one_line)
2011-09-04 05:14:52 +00:00
{
2012-05-30 01:38:02 +00:00
formatAST(*ast.children.front(), s, indent, hilite, one_line);
2012-05-21 20:38:34 +00:00
s << (hilite ? hilite_keyword : "") << (ast.direction == -1 ? " DESC" : " ASC") << (hilite ? hilite_none : "");
2011-09-04 05:14:52 +00:00
}
2010-06-28 13:44:42 +00:00
}