1#include "duckdb/planner/pragma_handler.hpp"
2
3#include "duckdb/parser/statement/select_statement.hpp"
4#include "duckdb/parser/query_node/select_node.hpp"
5#include "duckdb/parser/expression/constant_expression.hpp"
6#include "duckdb/parser/expression/star_expression.hpp"
7#include "duckdb/parser/tableref/table_function_ref.hpp"
8#include "duckdb/parser/expression/columnref_expression.hpp"
9#include "duckdb/parser/expression/function_expression.hpp"
10#include "duckdb/parser/parsed_data/pragma_info.hpp"
11#include "duckdb/parser/parser.hpp"
12
13#include "duckdb/common/string_util.hpp"
14
15using namespace duckdb;
16using namespace std;
17
18PragmaHandler::PragmaHandler(ClientContext &context) : context(context) {
19}
20
21unique_ptr<SQLStatement> PragmaHandler::HandlePragma(PragmaInfo &pragma) {
22 string keyword = StringUtil::Lower(pragma.name);
23 if (keyword == "table_info") {
24 if (pragma.pragma_type != PragmaType::CALL) {
25 throw ParserException("Invalid PRAGMA table_info: expected table name");
26 }
27 if (pragma.parameters.size() != 1) {
28 throw ParserException("Invalid PRAGMA table_info: table_info takes exactly one argument");
29 }
30 // generate a SelectStatement that selects from the pragma_table_info function
31 // i.e. SELECT * FROM pragma_table_info('table_name')
32 Parser parser;
33 parser.ParseQuery("SELECT * FROM pragma_table_info()");
34
35 // push the table name parameter into the table function
36 auto select_statement = move(parser.statements[0]);
37 auto &select = (SelectStatement &)*select_statement;
38 auto &select_node = (SelectNode &)*select.node;
39 auto &table_function = (TableFunctionRef &)*select_node.from_table;
40 auto &function = (FunctionExpression &)*table_function.function;
41 function.children.push_back(make_unique<ConstantExpression>(SQLTypeId::VARCHAR, pragma.parameters[0]));
42 return select_statement;
43 } else if (keyword == "show_tables") {
44 if (pragma.pragma_type != PragmaType::NOTHING) {
45 throw ParserException("Invalid PRAGMA show_tables: cannot be called");
46 }
47 // turn into SELECT name FROM sqlite_master();
48 Parser parser;
49 parser.ParseQuery("SELECT name FROM sqlite_master() ORDER BY name");
50 return move(parser.statements[0]);
51 } else if (keyword == "collations") {
52 if (pragma.pragma_type != PragmaType::NOTHING) {
53 throw ParserException("Invalid PRAGMA collations: cannot be called");
54 }
55 // turn into SELECT * FROM pragma_collations();
56 Parser parser;
57 parser.ParseQuery("SELECT * FROM pragma_collations() ORDER BY 1");
58 return move(parser.statements[0]);
59 } else if (keyword == "show") {
60 if (pragma.pragma_type != PragmaType::CALL) {
61 throw ParserException("Invalid PRAGMA show_tables: expected a function call");
62 }
63 if (pragma.parameters.size() != 1) {
64 throw ParserException("Invalid PRAGMA show_tables: show_tables does not take any arguments");
65 }
66 // PRAGMA table_info but with some aliases
67 Parser parser;
68 parser.ParseQuery(
69 "SELECT name AS \"Field\", type as \"Type\", CASE WHEN \"notnull\" THEN 'NO' ELSE 'YES' END AS \"Null\", "
70 "NULL AS \"Key\", dflt_value AS \"Default\", NULL AS \"Extra\" FROM pragma_table_info()");
71
72 // push the table name parameter into the table function
73 auto select_statement = move(parser.statements[0]);
74 auto &select = (SelectStatement &)*select_statement;
75 auto &select_node = (SelectNode &)*select.node;
76 auto &table_function = (TableFunctionRef &)*select_node.from_table;
77 auto &function = (FunctionExpression &)*table_function.function;
78 function.children.push_back(make_unique<ConstantExpression>(SQLTypeId::VARCHAR, pragma.parameters[0]));
79 return select_statement;
80 }
81 return nullptr;
82}
83