| 1 | //===----------------------------------------------------------------------===// |
| 2 | // DuckDB |
| 3 | // |
| 4 | // duckdb/planner/table_binding.hpp |
| 5 | // |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #pragma once |
| 10 | |
| 11 | #include "duckdb/common/common.hpp" |
| 12 | #include "duckdb/common/case_insensitive_map.hpp" |
| 13 | #include "duckdb/parser/column_definition.hpp" |
| 14 | #include "duckdb/parser/parsed_expression.hpp" |
| 15 | #include "duckdb/planner/expression_binder.hpp" |
| 16 | #include "duckdb/catalog/catalog_entry/table_column_type.hpp" |
| 17 | |
| 18 | namespace duckdb { |
| 19 | class BindContext; |
| 20 | class BoundQueryNode; |
| 21 | class ColumnRefExpression; |
| 22 | class SubqueryRef; |
| 23 | class LogicalGet; |
| 24 | class TableCatalogEntry; |
| 25 | class TableFunctionCatalogEntry; |
| 26 | class BoundTableFunction; |
| 27 | class StandardEntry; |
| 28 | struct ColumnBinding; |
| 29 | |
| 30 | enum class BindingType { BASE, TABLE, DUMMY, CATALOG_ENTRY }; |
| 31 | |
| 32 | //! A Binding represents a binding to a table, table-producing function or subquery with a specified table index. |
| 33 | struct Binding { |
| 34 | Binding(BindingType binding_type, const string &alias, vector<LogicalType> types, vector<string> names, |
| 35 | idx_t index); |
| 36 | virtual ~Binding() = default; |
| 37 | |
| 38 | //! The type of Binding |
| 39 | BindingType binding_type; |
| 40 | //! The alias of the binding |
| 41 | string alias; |
| 42 | //! The table index of the binding |
| 43 | idx_t index; |
| 44 | //! The types of the bound columns |
| 45 | vector<LogicalType> types; |
| 46 | //! Column names of the subquery |
| 47 | vector<string> names; |
| 48 | //! Name -> index for the names |
| 49 | case_insensitive_map_t<column_t> name_map; |
| 50 | |
| 51 | public: |
| 52 | bool TryGetBindingIndex(const string &column_name, column_t &column_index); |
| 53 | column_t GetBindingIndex(const string &column_name); |
| 54 | bool HasMatchingBinding(const string &column_name); |
| 55 | virtual string ColumnNotFoundError(const string &column_name) const; |
| 56 | virtual BindResult Bind(ColumnRefExpression &colref, idx_t depth); |
| 57 | virtual optional_ptr<StandardEntry> GetStandardEntry(); |
| 58 | |
| 59 | public: |
| 60 | template <class TARGET> |
| 61 | TARGET &Cast() { |
| 62 | if (binding_type != TARGET::TYPE) { |
| 63 | throw InternalException("Failed to cast binding to type - binding type mismatch" ); |
| 64 | } |
| 65 | return reinterpret_cast<TARGET &>(*this); |
| 66 | } |
| 67 | |
| 68 | template <class TARGET> |
| 69 | const TARGET &Cast() const { |
| 70 | if (binding_type != TARGET::TYPE) { |
| 71 | throw InternalException("Failed to cast binding to type - binding type mismatch" ); |
| 72 | } |
| 73 | return reinterpret_cast<const TARGET &>(*this); |
| 74 | } |
| 75 | }; |
| 76 | |
| 77 | struct EntryBinding : public Binding { |
| 78 | public: |
| 79 | static constexpr const BindingType TYPE = BindingType::CATALOG_ENTRY; |
| 80 | |
| 81 | public: |
| 82 | EntryBinding(const string &alias, vector<LogicalType> types, vector<string> names, idx_t index, |
| 83 | StandardEntry &entry); |
| 84 | StandardEntry &entry; |
| 85 | |
| 86 | public: |
| 87 | optional_ptr<StandardEntry> GetStandardEntry() override; |
| 88 | }; |
| 89 | |
| 90 | //! TableBinding is exactly like the Binding, except it keeps track of which columns were bound in the linked LogicalGet |
| 91 | //! node for projection pushdown purposes. |
| 92 | struct TableBinding : public Binding { |
| 93 | public: |
| 94 | static constexpr const BindingType TYPE = BindingType::TABLE; |
| 95 | |
| 96 | public: |
| 97 | TableBinding(const string &alias, vector<LogicalType> types, vector<string> names, |
| 98 | vector<column_t> &bound_column_ids, optional_ptr<StandardEntry> entry, idx_t index, |
| 99 | bool add_row_id = false); |
| 100 | |
| 101 | //! A reference to the set of bound column ids |
| 102 | vector<column_t> &bound_column_ids; |
| 103 | //! The underlying catalog entry (if any) |
| 104 | optional_ptr<StandardEntry> entry; |
| 105 | |
| 106 | public: |
| 107 | unique_ptr<ParsedExpression> ExpandGeneratedColumn(const string &column_name); |
| 108 | BindResult Bind(ColumnRefExpression &colref, idx_t depth) override; |
| 109 | optional_ptr<StandardEntry> GetStandardEntry() override; |
| 110 | string ColumnNotFoundError(const string &column_name) const override; |
| 111 | // These are columns that are present in the name_map, appearing in the order that they're bound |
| 112 | const vector<column_t> &GetBoundColumnIds() const; |
| 113 | |
| 114 | protected: |
| 115 | ColumnBinding GetColumnBinding(column_t column_index); |
| 116 | }; |
| 117 | |
| 118 | //! DummyBinding is like the Binding, except the alias and index are set by default. Used for binding lambdas and macro |
| 119 | //! parameters. |
| 120 | struct DummyBinding : public Binding { |
| 121 | public: |
| 122 | static constexpr const BindingType TYPE = BindingType::DUMMY; |
| 123 | // NOTE: changing this string conflicts with the storage version |
| 124 | static constexpr const char *DUMMY_NAME = "0_macro_parameters" ; |
| 125 | |
| 126 | public: |
| 127 | DummyBinding(vector<LogicalType> types_p, vector<string> names_p, string dummy_name_p); |
| 128 | |
| 129 | //! Arguments |
| 130 | vector<unique_ptr<ParsedExpression>> *arguments; |
| 131 | //! The name of the dummy binding |
| 132 | string dummy_name; |
| 133 | |
| 134 | public: |
| 135 | BindResult Bind(ColumnRefExpression &colref, idx_t depth) override; |
| 136 | BindResult Bind(ColumnRefExpression &colref, idx_t lambda_index, idx_t depth); |
| 137 | |
| 138 | //! Given the parameter colref, returns a copy of the argument that was supplied for this parameter |
| 139 | unique_ptr<ParsedExpression> ParamToArg(ColumnRefExpression &colref); |
| 140 | }; |
| 141 | |
| 142 | } // namespace duckdb |
| 143 | |