1#include "duckdb/parser/statement/create_statement.hpp"
2#include "duckdb/planner/operator/logical_create.hpp"
3#include "duckdb/planner/operator/logical_create_table.hpp"
4#include "duckdb/planner/operator/logical_create_index.hpp"
5#include "duckdb/planner/operator/logical_get.hpp"
6#include "duckdb/planner/parsed_data/bound_create_table_info.hpp"
7#include "duckdb/catalog/catalog.hpp"
8#include "duckdb/catalog/catalog_entry/schema_catalog_entry.hpp"
9#include "duckdb/planner/binder.hpp"
10#include "duckdb/planner/expression_binder/index_binder.hpp"
11#include "duckdb/parser/parsed_data/create_view_info.hpp"
12#include "duckdb/parser/parsed_data/create_index_info.hpp"
13#include "duckdb/planner/bound_query_node.hpp"
14#include "duckdb/planner/tableref/bound_basetableref.hpp"
15
16using namespace duckdb;
17using namespace std;
18
19SchemaCatalogEntry *Binder::BindSchema(CreateInfo &info) {
20 if (info.schema == INVALID_SCHEMA) {
21 info.schema = info.temporary ? TEMP_SCHEMA : DEFAULT_SCHEMA;
22 }
23
24 if (!info.temporary) {
25 // non-temporary create: not read only
26 if (info.schema == TEMP_SCHEMA) {
27 throw ParserException("Only TEMPORARY table names can use the \"temp\" schema");
28 }
29 this->read_only = false;
30 } else {
31 if (info.schema != TEMP_SCHEMA) {
32 throw ParserException("TEMPORARY table names can *only* use the \"%s\" schema", TEMP_SCHEMA);
33 }
34 }
35 // fetch the schema in which we want to create the object
36 auto schema_obj = Catalog::GetCatalog(context).GetSchema(context, info.schema);
37 assert(schema_obj->type == CatalogType::SCHEMA);
38 info.schema = schema_obj->name;
39 return schema_obj;
40}
41
42BoundStatement Binder::Bind(CreateStatement &stmt) {
43 BoundStatement result;
44 result.names = {"Count"};
45 result.types = {SQLType::BIGINT};
46
47 auto catalog_type = stmt.info->type;
48 switch (catalog_type) {
49 case CatalogType::SCHEMA:
50 result.plan = make_unique<LogicalCreate>(LogicalOperatorType::CREATE_SCHEMA, move(stmt.info));
51 break;
52 case CatalogType::VIEW: {
53 auto &base = (CreateViewInfo &)*stmt.info;
54 // bind the schema
55 auto schema = BindSchema(*stmt.info);
56
57 // bind the view as if it were a query so we can catch errors
58 // note that we bind a copy and don't actually use the bind result
59 auto copy = base.query->Copy();
60 auto query_node = Bind(*copy);
61 if (base.aliases.size() > query_node.names.size()) {
62 throw BinderException("More VIEW aliases than columns in query result");
63 }
64 // fill up the aliases with the remaining names of the bound query
65 for (idx_t i = base.aliases.size(); i < query_node.names.size(); i++) {
66 base.aliases.push_back(query_node.names[i]);
67 }
68 base.types = query_node.types;
69 result.plan = make_unique<LogicalCreate>(LogicalOperatorType::CREATE_VIEW, move(stmt.info), schema);
70 break;
71 }
72 case CatalogType::SEQUENCE: {
73 auto schema = BindSchema(*stmt.info);
74 result.plan = make_unique<LogicalCreate>(LogicalOperatorType::CREATE_SEQUENCE, move(stmt.info), schema);
75 break;
76 }
77 case CatalogType::INDEX: {
78 auto &base = (CreateIndexInfo &)*stmt.info;
79
80 // visit the table reference
81 auto bound_table = Bind(*base.table);
82 if (bound_table->type != TableReferenceType::BASE_TABLE) {
83 throw BinderException("Can only delete from base table!");
84 }
85 // bind the index expressions
86 vector<unique_ptr<Expression>> expressions;
87 IndexBinder binder(*this, context);
88 for (auto &expr : base.expressions) {
89 expressions.push_back(binder.Bind(expr));
90 }
91
92 auto plan = CreatePlan(*bound_table);
93 if (plan->type != LogicalOperatorType::GET) {
94 throw BinderException("Cannot create index on a view!");
95 }
96 auto &get = (LogicalGet &)*plan;
97 for (auto &column_id : get.column_ids) {
98 if (column_id == COLUMN_IDENTIFIER_ROW_ID) {
99 throw BinderException("Cannot create an index on the rowid!");
100 }
101 }
102 // this gives us a logical table scan
103 // we take the required columns from here
104 // create the logical operator
105 result.plan = make_unique<LogicalCreateIndex>(*get.table, get.column_ids, move(expressions),
106 unique_ptr_cast<CreateInfo, CreateIndexInfo>(move(stmt.info)));
107 break;
108 }
109 case CatalogType::TABLE: {
110 auto bound_info = BindCreateTableInfo(move(stmt.info));
111 auto root = move(bound_info->query);
112
113 // create the logical operator
114 auto create_table = make_unique<LogicalCreateTable>(bound_info->schema, move(bound_info));
115 if (root) {
116 create_table->children.push_back(move(root));
117 }
118 result.plan = move(create_table);
119 return result;
120 }
121 default:
122 throw Exception("Unrecognized type!");
123 }
124 return result;
125}
126