1 | #include "duckdb/planner/expression/bound_function_expression.hpp" |
2 | #include "duckdb/common/string_util.hpp" |
3 | #include "duckdb/parser/expression/bound_expression.hpp" |
4 | #include "duckdb/function/scalar/nested_functions.hpp" |
5 | #include "duckdb/common/types/chunk_collection.hpp" |
6 | #include "duckdb/common/types/data_chunk.hpp" |
7 | |
8 | using namespace std; |
9 | |
10 | namespace duckdb { |
11 | |
12 | static void list_value_fun(DataChunk &args, ExpressionState &state, Vector &result) { |
13 | // auto &func_expr = (BoundFunctionExpression &)state.expr; |
14 | // auto &info = (VariableReturnBindData &)*func_expr.bind_info; |
15 | |
16 | assert(result.type == TypeId::LIST); |
17 | auto list_child = make_unique<ChunkCollection>(); |
18 | ListVector::SetEntry(result, move(list_child)); |
19 | |
20 | auto &cc = ListVector::GetEntry(result); |
21 | DataChunk append_vals; |
22 | vector<TypeId> types; |
23 | if (args.column_count() > 0) { |
24 | types.push_back(args.GetTypes()[0]); |
25 | append_vals.Initialize(types); |
26 | append_vals.SetCardinality(1); |
27 | } |
28 | result.vector_type = VectorType::CONSTANT_VECTOR; |
29 | for (idx_t i = 0; i < args.column_count(); i++) { |
30 | if (args.data[i].vector_type != VectorType::CONSTANT_VECTOR) { |
31 | result.vector_type = VectorType::FLAT_VECTOR; |
32 | } |
33 | } |
34 | |
35 | auto result_data = FlatVector::GetData<list_entry_t>(result); |
36 | for (idx_t i = 0; i < args.size(); i++) { |
37 | result_data[i].offset = cc.count; |
38 | for (idx_t col_idx = 0; col_idx < args.column_count(); col_idx++) { |
39 | append_vals.SetValue(0, 0, args.GetValue(col_idx, i).CastAs(types[0])); // FIXME evil pattern |
40 | cc.Append(append_vals); |
41 | } |
42 | result_data[i].length = args.column_count(); |
43 | } |
44 | result.Verify(args.size()); |
45 | } |
46 | |
47 | static unique_ptr<FunctionData> list_value_bind(BoundFunctionExpression &expr, ClientContext &context) { |
48 | SQLType stype(SQLTypeId::LIST); |
49 | |
50 | // collect names and deconflict, construct return type |
51 | assert(expr.arguments.size() == expr.children.size()); |
52 | |
53 | if (expr.children.size() > 0) { |
54 | stype.child_type.push_back(make_pair("" , expr.arguments[0])); |
55 | } |
56 | |
57 | // this is more for completeness reasons |
58 | expr.sql_return_type = stype; |
59 | return make_unique<VariableReturnBindData>(stype); |
60 | } |
61 | |
62 | void ListValueFun::RegisterFunction(BuiltinFunctions &set) { |
63 | // the arguments and return types are actually set in the binder function |
64 | ScalarFunction fun("list_value" , {}, SQLType::LIST, list_value_fun, false, list_value_bind); |
65 | fun.varargs = SQLType::ANY; |
66 | set.AddFunction(fun); |
67 | } |
68 | |
69 | } // namespace duckdb |
70 | |