1#include "duckdb/planner/expression_binder/check_binder.hpp"
2
3#include "duckdb/parser/expression/columnref_expression.hpp"
4#include "duckdb/planner/expression/bound_reference_expression.hpp"
5
6using namespace duckdb;
7using namespace std;
8
9CheckBinder::CheckBinder(Binder &binder, ClientContext &context, string table, vector<ColumnDefinition> &columns,
10 unordered_set<column_t> &bound_columns)
11 : ExpressionBinder(binder, context), table(table), columns(columns), bound_columns(bound_columns) {
12 target_type = SQLType::INTEGER;
13}
14
15BindResult CheckBinder::BindExpression(ParsedExpression &expr, idx_t depth, bool root_expression) {
16 switch (expr.GetExpressionClass()) {
17 case ExpressionClass::WINDOW:
18 return BindResult("window functions are not allowed in check constraints");
19 case ExpressionClass::SUBQUERY:
20 return BindResult("cannot use subquery in check constraint");
21 case ExpressionClass::COLUMN_REF:
22 return BindCheckColumn((ColumnRefExpression &)expr);
23 default:
24 return ExpressionBinder::BindExpression(expr, depth);
25 }
26}
27
28string CheckBinder::UnsupportedAggregateMessage() {
29 return "aggregate functions are not allowed in check constraints";
30}
31
32BindResult CheckBinder::BindCheckColumn(ColumnRefExpression &colref) {
33 if (!colref.table_name.empty() && colref.table_name != table) {
34 throw BinderException("Cannot reference table %s from within check constraint for table %s!",
35 colref.table_name.c_str(), table.c_str());
36 }
37 for (idx_t i = 0; i < columns.size(); i++) {
38 if (colref.column_name == columns[i].name) {
39 bound_columns.insert(i);
40 return BindResult(make_unique<BoundReferenceExpression>(GetInternalType(columns[i].type), i),
41 columns[i].type);
42 }
43 }
44 throw BinderException("Table does not contain column %s referenced in check constraint!",
45 colref.column_name.c_str());
46}
47