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
8using namespace std;
9
10namespace duckdb {
11
12static 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
47static 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
62void 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