//===----------------------------------------------------------------------===//
//
//                         DuckDB
//
// duckdb.h
//
//
//===----------------------------------------------------------------------===//
//
// !!!!!!!
// WARNING: this file is autogenerated by scripts/generate_c_api.py, manual changes will be overwritten
// !!!!!!!

#pragma once

#ifndef DUCKDB_C_API
#ifdef _WIN32
#ifdef DUCKDB_STATIC_BUILD
#define DUCKDB_C_API
#else
#if defined(DUCKDB_BUILD_LIBRARY) && !defined(DUCKDB_BUILD_LOADABLE_EXTENSION)
#define DUCKDB_C_API __declspec(dllexport)
#else
#define DUCKDB_C_API __declspec(dllimport)
#endif
#endif
#else
#define DUCKDB_C_API
#endif
#endif

//! duplicate of duckdb/main/winapi.hpp
#ifndef DUCKDB_EXTENSION_API
#ifdef _WIN32
#ifdef DUCKDB_STATIC_BUILD
#define DUCKDB_EXTENSION_API
#else
#define DUCKDB_EXTENSION_API __declspec(dllexport)
#endif
#else
#define DUCKDB_EXTENSION_API __attribute__((visibility("default")))
#endif
#endif

#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

//===--------------------------------------------------------------------===//
// Enums
//===--------------------------------------------------------------------===//

//! WARNING: The numbers of these enums should not be changed, as changing the numbers breaks ABI compatibility.
//! Always add enums at the END of the enum

//! An enum over DuckDB's internal types.
typedef enum DUCKDB_TYPE {
	DUCKDB_TYPE_INVALID = 0,
	// bool
	DUCKDB_TYPE_BOOLEAN = 1,
	// int8_t
	DUCKDB_TYPE_TINYINT = 2,
	// int16_t
	DUCKDB_TYPE_SMALLINT = 3,
	// int32_t
	DUCKDB_TYPE_INTEGER = 4,
	// int64_t
	DUCKDB_TYPE_BIGINT = 5,
	// uint8_t
	DUCKDB_TYPE_UTINYINT = 6,
	// uint16_t
	DUCKDB_TYPE_USMALLINT = 7,
	// uint32_t
	DUCKDB_TYPE_UINTEGER = 8,
	// uint64_t
	DUCKDB_TYPE_UBIGINT = 9,
	// float
	DUCKDB_TYPE_FLOAT = 10,
	// double
	DUCKDB_TYPE_DOUBLE = 11,
	// duckdb_timestamp (microseconds)
	DUCKDB_TYPE_TIMESTAMP = 12,
	// duckdb_date
	DUCKDB_TYPE_DATE = 13,
	// duckdb_time
	DUCKDB_TYPE_TIME = 14,
	// duckdb_interval
	DUCKDB_TYPE_INTERVAL = 15,
	// duckdb_hugeint
	DUCKDB_TYPE_HUGEINT = 16,
	// duckdb_uhugeint
	DUCKDB_TYPE_UHUGEINT = 32,
	// const char*
	DUCKDB_TYPE_VARCHAR = 17,
	// duckdb_blob
	DUCKDB_TYPE_BLOB = 18,
	// duckdb_decimal
	DUCKDB_TYPE_DECIMAL = 19,
	// duckdb_timestamp_s (seconds)
	DUCKDB_TYPE_TIMESTAMP_S = 20,
	// duckdb_timestamp_ms (milliseconds)
	DUCKDB_TYPE_TIMESTAMP_MS = 21,
	// duckdb_timestamp_ns (nanoseconds)
	DUCKDB_TYPE_TIMESTAMP_NS = 22,
	// enum type, only useful as logical type
	DUCKDB_TYPE_ENUM = 23,
	// list type, only useful as logical type
	DUCKDB_TYPE_LIST = 24,
	// struct type, only useful as logical type
	DUCKDB_TYPE_STRUCT = 25,
	// map type, only useful as logical type
	DUCKDB_TYPE_MAP = 26,
	// duckdb_array, only useful as logical type
	DUCKDB_TYPE_ARRAY = 33,
	// duckdb_hugeint
	DUCKDB_TYPE_UUID = 27,
	// union type, only useful as logical type
	DUCKDB_TYPE_UNION = 28,
	// duckdb_bit
	DUCKDB_TYPE_BIT = 29,
	// duckdb_time_tz
	DUCKDB_TYPE_TIME_TZ = 30,
	// duckdb_timestamp (microseconds)
	DUCKDB_TYPE_TIMESTAMP_TZ = 31,
	// enum type, only useful as logical type
	DUCKDB_TYPE_ANY = 34,
	// duckdb_bignum
	DUCKDB_TYPE_BIGNUM = 35,
	// enum type, only useful as logical type
	DUCKDB_TYPE_SQLNULL = 36,
	// enum type, only useful as logical type
	DUCKDB_TYPE_STRING_LITERAL = 37,
	// enum type, only useful as logical type
	DUCKDB_TYPE_INTEGER_LITERAL = 38,
	// duckdb_time_ns (nanoseconds)
	DUCKDB_TYPE_TIME_NS = 39,
} duckdb_type;

//! An enum over the returned state of different functions.
typedef enum duckdb_state { DuckDBSuccess = 0, DuckDBError = 1 } duckdb_state;

//! An enum over the pending state of a pending query result.
typedef enum duckdb_pending_state {
	DUCKDB_PENDING_RESULT_READY = 0,
	DUCKDB_PENDING_RESULT_NOT_READY = 1,
	DUCKDB_PENDING_ERROR = 2,
	DUCKDB_PENDING_NO_TASKS_AVAILABLE = 3
} duckdb_pending_state;

//! An enum over DuckDB's different result types.
typedef enum duckdb_result_type {
	DUCKDB_RESULT_TYPE_INVALID = 0,
	DUCKDB_RESULT_TYPE_CHANGED_ROWS = 1,
	DUCKDB_RESULT_TYPE_NOTHING = 2,
	DUCKDB_RESULT_TYPE_QUERY_RESULT = 3,
} duckdb_result_type;

//! An enum over DuckDB's different statement types.
typedef enum duckdb_statement_type {
	DUCKDB_STATEMENT_TYPE_INVALID = 0,
	DUCKDB_STATEMENT_TYPE_SELECT = 1,
	DUCKDB_STATEMENT_TYPE_INSERT = 2,
	DUCKDB_STATEMENT_TYPE_UPDATE = 3,
	DUCKDB_STATEMENT_TYPE_EXPLAIN = 4,
	DUCKDB_STATEMENT_TYPE_DELETE = 5,
	DUCKDB_STATEMENT_TYPE_PREPARE = 6,
	DUCKDB_STATEMENT_TYPE_CREATE = 7,
	DUCKDB_STATEMENT_TYPE_EXECUTE = 8,
	DUCKDB_STATEMENT_TYPE_ALTER = 9,
	DUCKDB_STATEMENT_TYPE_TRANSACTION = 10,
	DUCKDB_STATEMENT_TYPE_COPY = 11,
	DUCKDB_STATEMENT_TYPE_ANALYZE = 12,
	DUCKDB_STATEMENT_TYPE_VARIABLE_SET = 13,
	DUCKDB_STATEMENT_TYPE_CREATE_FUNC = 14,
	DUCKDB_STATEMENT_TYPE_DROP = 15,
	DUCKDB_STATEMENT_TYPE_EXPORT = 16,
	DUCKDB_STATEMENT_TYPE_PRAGMA = 17,
	DUCKDB_STATEMENT_TYPE_VACUUM = 18,
	DUCKDB_STATEMENT_TYPE_CALL = 19,
	DUCKDB_STATEMENT_TYPE_SET = 20,
	DUCKDB_STATEMENT_TYPE_LOAD = 21,
	DUCKDB_STATEMENT_TYPE_RELATION = 22,
	DUCKDB_STATEMENT_TYPE_EXTENSION = 23,
	DUCKDB_STATEMENT_TYPE_LOGICAL_PLAN = 24,
	DUCKDB_STATEMENT_TYPE_ATTACH = 25,
	DUCKDB_STATEMENT_TYPE_DETACH = 26,
	DUCKDB_STATEMENT_TYPE_MULTI = 27,
} duckdb_statement_type;

//! An enum over DuckDB's different error types.
typedef enum duckdb_error_type {
	DUCKDB_ERROR_INVALID = 0,
	DUCKDB_ERROR_OUT_OF_RANGE = 1,
	DUCKDB_ERROR_CONVERSION = 2,
	DUCKDB_ERROR_UNKNOWN_TYPE = 3,
	DUCKDB_ERROR_DECIMAL = 4,
	DUCKDB_ERROR_MISMATCH_TYPE = 5,
	DUCKDB_ERROR_DIVIDE_BY_ZERO = 6,
	DUCKDB_ERROR_OBJECT_SIZE = 7,
	DUCKDB_ERROR_INVALID_TYPE = 8,
	DUCKDB_ERROR_SERIALIZATION = 9,
	DUCKDB_ERROR_TRANSACTION = 10,
	DUCKDB_ERROR_NOT_IMPLEMENTED = 11,
	DUCKDB_ERROR_EXPRESSION = 12,
	DUCKDB_ERROR_CATALOG = 13,
	DUCKDB_ERROR_PARSER = 14,
	DUCKDB_ERROR_PLANNER = 15,
	DUCKDB_ERROR_SCHEDULER = 16,
	DUCKDB_ERROR_EXECUTOR = 17,
	DUCKDB_ERROR_CONSTRAINT = 18,
	DUCKDB_ERROR_INDEX = 19,
	DUCKDB_ERROR_STAT = 20,
	DUCKDB_ERROR_CONNECTION = 21,
	DUCKDB_ERROR_SYNTAX = 22,
	DUCKDB_ERROR_SETTINGS = 23,
	DUCKDB_ERROR_BINDER = 24,
	DUCKDB_ERROR_NETWORK = 25,
	DUCKDB_ERROR_OPTIMIZER = 26,
	DUCKDB_ERROR_NULL_POINTER = 27,
	DUCKDB_ERROR_IO = 28,
	DUCKDB_ERROR_INTERRUPT = 29,
	DUCKDB_ERROR_FATAL = 30,
	DUCKDB_ERROR_INTERNAL = 31,
	DUCKDB_ERROR_INVALID_INPUT = 32,
	DUCKDB_ERROR_OUT_OF_MEMORY = 33,
	DUCKDB_ERROR_PERMISSION = 34,
	DUCKDB_ERROR_PARAMETER_NOT_RESOLVED = 35,
	DUCKDB_ERROR_PARAMETER_NOT_ALLOWED = 36,
	DUCKDB_ERROR_DEPENDENCY = 37,
	DUCKDB_ERROR_HTTP = 38,
	DUCKDB_ERROR_MISSING_EXTENSION = 39,
	DUCKDB_ERROR_AUTOLOAD = 40,
	DUCKDB_ERROR_SEQUENCE = 41,
	DUCKDB_INVALID_CONFIGURATION = 42
} duckdb_error_type;

//! An enum over DuckDB's different cast modes.
typedef enum duckdb_cast_mode { DUCKDB_CAST_NORMAL = 0, DUCKDB_CAST_TRY = 1 } duckdb_cast_mode;

//===--------------------------------------------------------------------===//
// General type definitions
//===--------------------------------------------------------------------===//

//! DuckDB's index type.
typedef uint64_t idx_t;

//! Type definition for the data pointers of selection vectors.
typedef uint32_t sel_t;

//! The callback to destroy data, e.g.,
//! bind data (if any), init data (if any), extra data for replacement scans (if any), etc.
typedef void (*duckdb_delete_callback_t)(void *data);

//! The callback to copy data, e.g., bind data (if any).
typedef void *(*duckdb_copy_callback_t)(void *data);

//! Used for threading, contains a task state.
//! Must be destroyed with `duckdb_destroy_task_state`.
typedef void *duckdb_task_state;

//===--------------------------------------------------------------------===//
// Types (no explicit freeing)
//===--------------------------------------------------------------------===//

//! DATE is stored as days since 1970-01-01.
//! Use the `duckdb_from_date` and `duckdb_to_date` functions to extract individual information.
typedef struct {
	int32_t days;
} duckdb_date;

typedef struct {
	int32_t year;
	int8_t month;
	int8_t day;
} duckdb_date_struct;

//! TIME is stored as microseconds since 00:00:00.
//! Use the `duckdb_from_time` and `duckdb_to_time` functions to extract individual information.
typedef struct {
	int64_t micros;
} duckdb_time;

typedef struct {
	int8_t hour;
	int8_t min;
	int8_t sec;
	int32_t micros;
} duckdb_time_struct;

//! TIME_NS is stored as nanoseconds since 00:00:00.
typedef struct {
	int64_t nanos;
} duckdb_time_ns;

//! TIME_TZ is stored as 40 bits for the int64_t microseconds, and 24 bits for the int32_t offset.
//! Use the `duckdb_from_time_tz` function to extract individual information.
typedef struct {
	uint64_t bits;
} duckdb_time_tz;

typedef struct {
	duckdb_time_struct time;
	int32_t offset;
} duckdb_time_tz_struct;

//! TIMESTAMP is stored as microseconds since 1970-01-01.
//! Use the `duckdb_from_timestamp` and `duckdb_to_timestamp` functions to extract individual information.
typedef struct {
	int64_t micros;
} duckdb_timestamp;

typedef struct {
	duckdb_date_struct date;
	duckdb_time_struct time;
} duckdb_timestamp_struct;

//! TIMESTAMP_S is stored as seconds since 1970-01-01.
typedef struct {
	int64_t seconds;
} duckdb_timestamp_s;

//! TIMESTAMP_MS is stored as milliseconds since 1970-01-01.
typedef struct {
	int64_t millis;
} duckdb_timestamp_ms;

//! TIMESTAMP_NS is stored as nanoseconds since 1970-01-01.
typedef struct {
	int64_t nanos;
} duckdb_timestamp_ns;

//! INTERVAL is stored in months, days, and micros.
typedef struct {
	int32_t months;
	int32_t days;
	int64_t micros;
} duckdb_interval;

//! HUGEINT is composed of a lower and upper component.
//! Its value is upper * 2^64 + lower.
//! For simplified usage, use `duckdb_hugeint_to_double` and `duckdb_double_to_hugeint`.
typedef struct {
	uint64_t lower;
	int64_t upper;
} duckdb_hugeint;

//! UHUGEINT is composed of a lower and upper component.
//! Its value is upper * 2^64 + lower.
//! For simplified usage, use `duckdb_uhugeint_to_double` and `duckdb_double_to_uhugeint`.
typedef struct {
	uint64_t lower;
	uint64_t upper;
} duckdb_uhugeint;

//! DECIMAL is composed of a width and a scale.
//! Their value is stored in a HUGEINT.
typedef struct {
	uint8_t width;
	uint8_t scale;
	duckdb_hugeint value;
} duckdb_decimal;

//! A type holding information about the query execution progress.
typedef struct {
	double percentage;
	uint64_t rows_processed;
	uint64_t total_rows_to_process;
} duckdb_query_progress_type;

//! The internal representation of a VARCHAR (string_t). If the VARCHAR does not
//! exceed 12 characters, then we inline it. Otherwise, we inline a four-byte prefix for faster
//! string comparisons and store a pointer to the remaining characters. This is a non-
//! owning structure, i.e., it does not have to be freed.
typedef struct {
	union {
		struct {
			uint32_t length;
			char prefix[4];
			char *ptr;
		} pointer;
		struct {
			uint32_t length;
			char inlined[12];
		} inlined;
	} value;
} duckdb_string_t;

//! DuckDB's LISTs are composed of a 'parent' vector holding metadata of each list,
//! and a child vector holding the entries of the lists.
//! The `duckdb_list_entry` struct contains the internal representation of a LIST metadata entry.
//! A metadata entry contains the length of the list, and its offset in the child vector.
typedef struct {
	uint64_t offset;
	uint64_t length;
} duckdb_list_entry;

//! A column consists of a pointer to its internal data. Don't operate on this type directly.
//! Instead, use functions such as `duckdb_column_data`, `duckdb_nullmask_data`,
//! `duckdb_column_type`, and `duckdb_column_name`.
typedef struct {
	// Deprecated, use `duckdb_column_data`.
	void *deprecated_data;
	// Deprecated, use `duckdb_nullmask_data`.
	bool *deprecated_nullmask;
	// Deprecated, use `duckdb_column_type`.
	duckdb_type deprecated_type;
	// Deprecated, use `duckdb_column_name`.
	char *deprecated_name;
	void *internal_data;
} duckdb_column;

//! 1. A standalone vector that must be destroyed, or
//! 2. A vector to a column in a data chunk that lives as long as the data chunk lives.
typedef struct _duckdb_vector {
	void *internal_ptr;
} * duckdb_vector;

//! A selection vector is a vector of indices, which usually refer to values in a vector.
//! Can be used to slice vectors, changing their length and the order of their entries.
//! Standalone selection vectors must be destroyed.
typedef struct _duckdb_selection_vector {
	void *internal_ptr;
} * duckdb_selection_vector;

//===--------------------------------------------------------------------===//
// Types (explicit freeing/destroying)
//===--------------------------------------------------------------------===//

//! Strings are composed of a `char` pointer and a size.
//! You must free `string.data` with `duckdb_free`.
typedef struct {
	char *data;
	idx_t size;
} duckdb_string;

//! BLOBs are composed of a byte pointer and a size.
//! You must free `blob.data` with `duckdb_free`.
typedef struct {
	void *data;
	idx_t size;
} duckdb_blob;

//! BITs are composed of a byte pointer and a size.
//! BIT byte data has 0 to 7 bits of padding.
//! The first byte contains the number of padding bits.
//! The padding bits of the second byte are set to 1, starting from the MSB.
//! You must free `data` with `duckdb_free`.
typedef struct {
	uint8_t *data;
	idx_t size;
} duckdb_bit;

//! BIGNUMs are composed of a byte pointer, a size, and an `is_negative` bool.
//! The absolute value of the number is stored in `data` in little endian format.
//! You must free `data` with `duckdb_free`.
typedef struct {
	uint8_t *data;
	idx_t size;
	bool is_negative;
} duckdb_bignum;

//! A query result consists of a pointer to its internal data.
//! Must be freed with 'duckdb_destroy_result'.
typedef struct {
	// Deprecated, use `duckdb_column_count`.
	idx_t deprecated_column_count;
	// Deprecated, use `duckdb_row_count`.
	idx_t deprecated_row_count;
	// Deprecated, use `duckdb_rows_changed`.
	idx_t deprecated_rows_changed;
	// Deprecated, use `duckdb_column_*`-family of functions.
	duckdb_column *deprecated_columns;
	// Deprecated, use `duckdb_result_error`.
	char *deprecated_error_message;
	void *internal_data;
} duckdb_result;

//! A database instance cache object. Must be destroyed with `duckdb_destroy_instance_cache`.
typedef struct _duckdb_instance_cache {
	void *internal_ptr;
} * duckdb_instance_cache;

//! A database object. Must be closed with `duckdb_close`.
typedef struct _duckdb_database {
	void *internal_ptr;
} * duckdb_database;

//! A connection to a duckdb database. Must be closed with `duckdb_disconnect`.
typedef struct _duckdb_connection {
	void *internal_ptr;
} * duckdb_connection;

//! A client context of a duckdb connection. Must be destroyed with `duckdb_destroy_context`.
typedef struct _duckdb_client_context {
	void *internal_ptr;
} * duckdb_client_context;

//! A prepared statement is a parameterized query that allows you to bind parameters to it.
//! Must be destroyed with `duckdb_destroy_prepare`.
typedef struct _duckdb_prepared_statement {
	void *internal_ptr;
} * duckdb_prepared_statement;

//! Extracted statements. Must be destroyed with `duckdb_destroy_extracted`.
typedef struct _duckdb_extracted_statements {
	void *internal_ptr;
} * duckdb_extracted_statements;

//! The pending result represents an intermediate structure for a query that is not yet fully executed.
//! Must be destroyed with `duckdb_destroy_pending`.
typedef struct _duckdb_pending_result {
	void *internal_ptr;
} * duckdb_pending_result;

//! The appender enables fast data loading into DuckDB.
//! Must be destroyed with `duckdb_appender_destroy`.
typedef struct _duckdb_appender {
	void *internal_ptr;
} * duckdb_appender;

//! The table description allows querying information about the table.
//! Must be destroyed with `duckdb_table_description_destroy`.
typedef struct _duckdb_table_description {
	void *internal_ptr;
} * duckdb_table_description;

//! The configuration can be used to provide start-up options for a database.
//! Must be destroyed with `duckdb_destroy_config`.
typedef struct _duckdb_config {
	void *internal_ptr;
} * duckdb_config;

//! A logical type.
//! Must be destroyed with `duckdb_destroy_logical_type`.
typedef struct _duckdb_logical_type {
	void *internal_ptr;
} * duckdb_logical_type;

//! Holds extra information to register a custom logical type.
//! Reserved for future use.
typedef struct _duckdb_create_type_info {
	void *internal_ptr;
} * duckdb_create_type_info;

//! Contains a data chunk of a duckdb_result.
//! Must be destroyed with `duckdb_destroy_data_chunk`.
typedef struct _duckdb_data_chunk {
	void *internal_ptr;
} * duckdb_data_chunk;

//! A value of a logical type.
//! Must be destroyed with `duckdb_destroy_value`.
typedef struct _duckdb_value {
	void *internal_ptr;
} * duckdb_value;

//! Holds a recursive tree containing profiling metrics.
//! The tree matches the query plan, and has a top-level node.
typedef struct _duckdb_profiling_info {
	void *internal_ptr;
} * duckdb_profiling_info;

//! Holds error data.
//! Must be destroyed with `duckdb_destroy_error_data`.
typedef struct _duckdb_error_data {
	void *internal_ptr;
} * duckdb_error_data;

//! Holds a bound expression.
//! Must be destroyed with `duckdb_destroy_expression`.
typedef struct _duckdb_expression {
	void *internal_ptr;
} * duckdb_expression;

//===--------------------------------------------------------------------===//
// C API extension information
//===--------------------------------------------------------------------===//

//! Holds the state of the C API extension initialization process.
typedef struct _duckdb_extension_info {
	void *internal_ptr;
} * duckdb_extension_info;

//===--------------------------------------------------------------------===//
// Function types
//===--------------------------------------------------------------------===//

//! Additional function info.
//! When setting this info, it is necessary to pass a destroy-callback function.
typedef struct _duckdb_function_info {
	void *internal_ptr;
} * duckdb_function_info;

//! The bind info of a function.
//! When setting this info, it is necessary to pass a destroy-callback function.
typedef struct _duckdb_bind_info {
	void *internal_ptr;
} * duckdb_bind_info;

//===--------------------------------------------------------------------===//
// Scalar function types
//===--------------------------------------------------------------------===//

//! A scalar function. Must be destroyed with `duckdb_destroy_scalar_function`.
typedef struct _duckdb_scalar_function {
	void *internal_ptr;
} * duckdb_scalar_function;

//! A scalar function set. Must be destroyed with `duckdb_destroy_scalar_function_set`.
typedef struct _duckdb_scalar_function_set {
	void *internal_ptr;
} * duckdb_scalar_function_set;

//! The bind function callback of the scalar function.
typedef void (*duckdb_scalar_function_bind_t)(duckdb_bind_info info);

//! The function to execute the scalar function on an input chunk.
typedef void (*duckdb_scalar_function_t)(duckdb_function_info info, duckdb_data_chunk input, duckdb_vector output);

//===--------------------------------------------------------------------===//
// Aggregate function types
//===--------------------------------------------------------------------===//

//! An aggregate function. Must be destroyed with `duckdb_destroy_aggregate_function`.
typedef struct _duckdb_aggregate_function {
	void *internal_ptr;
} * duckdb_aggregate_function;

//! A aggregate function set. Must be destroyed with `duckdb_destroy_aggregate_function_set`.
typedef struct _duckdb_aggregate_function_set {
	void *internal_ptr;
} * duckdb_aggregate_function_set;

//! The state of an aggregate function.
typedef struct _duckdb_aggregate_state {
	void *internal_ptr;
} * duckdb_aggregate_state;

//! A function to return the aggregate state's size.
typedef idx_t (*duckdb_aggregate_state_size)(duckdb_function_info info);

//! A function to initialize an aggregate state.
typedef void (*duckdb_aggregate_init_t)(duckdb_function_info info, duckdb_aggregate_state state);

//! An optional function to destroy an aggregate state.
typedef void (*duckdb_aggregate_destroy_t)(duckdb_aggregate_state *states, idx_t count);

//! A function to update a set of aggregate states with new values.
typedef void (*duckdb_aggregate_update_t)(duckdb_function_info info, duckdb_data_chunk input,
                                          duckdb_aggregate_state *states);

//! A function to combine aggregate states.
typedef void (*duckdb_aggregate_combine_t)(duckdb_function_info info, duckdb_aggregate_state *source,
                                           duckdb_aggregate_state *target, idx_t count);

//! A function to finalize aggregate states into a result vector.
typedef void (*duckdb_aggregate_finalize_t)(duckdb_function_info info, duckdb_aggregate_state *source,
                                            duckdb_vector result, idx_t count, idx_t offset);

//===--------------------------------------------------------------------===//
// Table function types
//===--------------------------------------------------------------------===//

//! A table function. Must be destroyed with `duckdb_destroy_table_function`.
typedef struct _duckdb_table_function {
	void *internal_ptr;
} * duckdb_table_function;

//! Additional function initialization info.
//! When setting this info, it is necessary to pass a destroy-callback function.
typedef struct _duckdb_init_info {
	void *internal_ptr;
} * duckdb_init_info;

//! The bind function of the table function.
typedef void (*duckdb_table_function_bind_t)(duckdb_bind_info info);

//! The possibly thread-local initialization function of the table function.
typedef void (*duckdb_table_function_init_t)(duckdb_init_info info);

//! The function to generate an output chunk during table function execution.
typedef void (*duckdb_table_function_t)(duckdb_function_info info, duckdb_data_chunk output);

//===--------------------------------------------------------------------===//
// Cast types
//===--------------------------------------------------------------------===//

//! A cast function. Must be destroyed with `duckdb_destroy_cast_function`.
typedef struct _duckdb_cast_function {
	void *internal_ptr;
} * duckdb_cast_function;

//! The function to cast from an input vector to an output vector.
typedef bool (*duckdb_cast_function_t)(duckdb_function_info info, idx_t count, duckdb_vector input,
                                       duckdb_vector output);

//===--------------------------------------------------------------------===//
// Replacement scan types
//===--------------------------------------------------------------------===//

//! Additional replacement scan info. When setting this info, it is necessary to pass a destroy-callback function.
typedef struct _duckdb_replacement_scan_info {
	void *internal_ptr;
} * duckdb_replacement_scan_info;

//! A replacement scan function.
typedef void (*duckdb_replacement_callback_t)(duckdb_replacement_scan_info info, const char *table_name, void *data);

//===--------------------------------------------------------------------===//
// Arrow-related types
//===--------------------------------------------------------------------===//

//! Forward declare Arrow structs
//! It is important to notice that these structs are not defined by DuckDB but are actually Arrow external objects.
//! They're defined by the C Data Interface Arrow spec: https://arrow.apache.org/docs/format/CDataInterface.html

struct ArrowArray;

struct ArrowSchema;

//! Holds an arrow query result. Must be destroyed with `duckdb_destroy_arrow`.
typedef struct _duckdb_arrow {
	void *internal_ptr;
} * duckdb_arrow;

//! Holds an arrow array stream. Must be destroyed with `duckdb_destroy_arrow_stream`.
typedef struct _duckdb_arrow_stream {
	void *internal_ptr;
} * duckdb_arrow_stream;

//! Holds an arrow schema. Remember to release the respective ArrowSchema object.
typedef struct _duckdb_arrow_schema {
	void *internal_ptr;
} * duckdb_arrow_schema;

//! Holds an arrow converted schema (i.e., duckdb::ArrowTableSchema).
//! In practice, this object holds the information necessary to do proper conversion between Arrow Types and DuckDB
//! Types. Check duckdb/function/table/arrow/arrow_duck_schema.hpp for more details! Must be destroyed with
//! `duckdb_destroy_arrow_converted_schema`
typedef struct _duckdb_arrow_converted_schema {
	void *internal_ptr;
} * duckdb_arrow_converted_schema;

//! Holds an arrow array. Remember to release the respective ArrowSchema object.
typedef struct _duckdb_arrow_array {
	void *internal_ptr;
} * duckdb_arrow_array;

//! The arrow options used when transforming the DuckDB schema and datachunks into Arrow schema and arrays.
//! Used in `duckdb_to_arrow_schema` and `duckdb_data_chunk_to_arrow`
typedef struct _duckdb_arrow_options {
	void *internal_ptr;
} * duckdb_arrow_options;

//===--------------------------------------------------------------------===//
// DuckDB extension access
//===--------------------------------------------------------------------===//

//! Passed to C API extension as a parameter to the entrypoint.
struct duckdb_extension_access {
	//! Indicate that an error has occurred.
	void (*set_error)(duckdb_extension_info info, const char *error);
	//! Fetch the database on which to register the extension.
	duckdb_database *(*get_database)(duckdb_extension_info info);
	//! Fetch the API struct pointer.
	const void *(*get_api)(duckdb_extension_info info, const char *version);
};

#ifndef DUCKDB_API_EXCLUDE_FUNCTIONS

//===--------------------------------------------------------------------===//
// Functions
//===--------------------------------------------------------------------===//

//===--------------------------------------------------------------------===//
// Open Connect
//===--------------------------------------------------------------------===//

/*!
Creates a new database instance cache.
The instance cache is necessary if a client/program (re)opens multiple databases to the same file within the same
process. Must be destroyed with 'duckdb_destroy_instance_cache'.

* @return The database instance cache.
*/
DUCKDB_C_API duckdb_instance_cache duckdb_create_instance_cache();

/*!
Creates a new database instance in the instance cache, or retrieves an existing database instance.
Must be closed with 'duckdb_close'.

* @param instance_cache The instance cache in which to create the database, or from which to take the database.
* @param path Path to the database file on disk. Both `nullptr` and `:memory:` open or retrieve an in-memory database.
* @param out_database The resulting cached database.
* @param config (Optional) configuration used to create the database.
* @param out_error If set and the function returns `DuckDBError`, this contains the error message.
Note that the error message must be freed using `duckdb_free`.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_get_or_create_from_cache(duckdb_instance_cache instance_cache, const char *path,
                                                          duckdb_database *out_database, duckdb_config config,
                                                          char **out_error);

/*!
Destroys an existing database instance cache and de-allocates its memory.

* @param instance_cache The instance cache to destroy.
*/
DUCKDB_C_API void duckdb_destroy_instance_cache(duckdb_instance_cache *instance_cache);

/*!
Creates a new database or opens an existing database file stored at the given path.
If no path is given a new in-memory database is created instead.
The database must be closed with 'duckdb_close'.

* @param path Path to the database file on disk. Both `nullptr` and `:memory:` open an in-memory database.
* @param out_database The result database object.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_open(const char *path, duckdb_database *out_database);

/*!
Extended version of duckdb_open. Creates a new database or opens an existing database file stored at the given path.
The database must be closed with 'duckdb_close'.

* @param path Path to the database file on disk. Both `nullptr` and `:memory:` open an in-memory database.
* @param out_database The result database object.
* @param config (Optional) configuration used to start up the database.
* @param out_error If set and the function returns `DuckDBError`, this contains the error message.
Note that the error message must be freed using `duckdb_free`.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_open_ext(const char *path, duckdb_database *out_database, duckdb_config config,
                                          char **out_error);

/*!
Closes the specified database and de-allocates all memory allocated for that database.
This should be called after you are done with any database allocated through `duckdb_open` or `duckdb_open_ext`.
Note that failing to call `duckdb_close` (in case of e.g. a program crash) will not cause data corruption.
Still, it is recommended to always correctly close a database object after you are done with it.

* @param database The database object to shut down.
*/
DUCKDB_C_API void duckdb_close(duckdb_database *database);

/*!
Opens a connection to a database. Connections are required to query the database, and store transactional state
associated with the connection.
The instantiated connection should be closed using 'duckdb_disconnect'.

* @param database The database file to connect to.
* @param out_connection The result connection object.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_connect(duckdb_database database, duckdb_connection *out_connection);

/*!
Interrupt running query

* @param connection The connection to interrupt
*/
DUCKDB_C_API void duckdb_interrupt(duckdb_connection connection);

/*!
Get progress of the running query

* @param connection The working connection
* @return -1 if no progress or a percentage of the progress
*/
DUCKDB_C_API duckdb_query_progress_type duckdb_query_progress(duckdb_connection connection);

/*!
Closes the specified connection and de-allocates all memory allocated for that connection.

* @param connection The connection to close.
*/
DUCKDB_C_API void duckdb_disconnect(duckdb_connection *connection);

/*!
Retrieves the client context of the connection.

* @param connection The connection.
* @param out_context The client context of the connection. Must be destroyed with `duckdb_destroy_client_context`.
*/
DUCKDB_C_API void duckdb_connection_get_client_context(duckdb_connection connection,
                                                       duckdb_client_context *out_context);

/*!
Retrieves the arrow options of the connection.

* @param connection The connection.
*/
DUCKDB_C_API void duckdb_connection_get_arrow_options(duckdb_connection connection,
                                                      duckdb_arrow_options *out_arrow_options);

/*!
Returns the connection id of the client context.

* @param context The client context.
* @return The connection id of the client context.
*/
DUCKDB_C_API idx_t duckdb_client_context_get_connection_id(duckdb_client_context context);

/*!
Destroys the client context and deallocates its memory.

* @param context The client context to destroy.
*/
DUCKDB_C_API void duckdb_destroy_client_context(duckdb_client_context *context);

/*!
Destroys the arrow options and deallocates its memory.

* @param arrow_options The arrow options to destroy.
*/
DUCKDB_C_API void duckdb_destroy_arrow_options(duckdb_arrow_options *arrow_options);

/*!
Returns the version of the linked DuckDB, with a version postfix for dev versions

Usually used for developing C extensions that must return this for a compatibility check.
*/
DUCKDB_C_API const char *duckdb_library_version();

/*!
Get the list of (fully qualified) table names of the query.

* @param connection The connection for which to get the table names.
* @param query The query for which to get the table names.
* @param qualified Returns fully qualified table names (catalog.schema.table), if set to true, else only the (not
escaped) table names.
* @return A duckdb_value of type VARCHAR[] containing the (fully qualified) table names of the query. Must be destroyed
with duckdb_destroy_value.
*/
DUCKDB_C_API duckdb_value duckdb_get_table_names(duckdb_connection connection, const char *query, bool qualified);

//===--------------------------------------------------------------------===//
// Configuration
//===--------------------------------------------------------------------===//

/*!
Initializes an empty configuration object that can be used to provide start-up options for the DuckDB instance
through `duckdb_open_ext`.
The duckdb_config must be destroyed using 'duckdb_destroy_config'

This will always succeed unless there is a malloc failure.

Note that `duckdb_destroy_config` should always be called on the resulting config, even if the function returns
`DuckDBError`.

* @param out_config The result configuration object.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_create_config(duckdb_config *out_config);

/*!
This returns the total amount of configuration options available for usage with `duckdb_get_config_flag`.

This should not be called in a loop as it internally loops over all the options.

* @return The amount of config options available.
*/
DUCKDB_C_API size_t duckdb_config_count();

/*!
Obtains a human-readable name and description of a specific configuration option. This can be used to e.g.
display configuration options. This will succeed unless `index` is out of range (i.e. `>= duckdb_config_count`).

The result name or description MUST NOT be freed.

* @param index The index of the configuration option (between 0 and `duckdb_config_count`)
* @param out_name A name of the configuration flag.
* @param out_description A description of the configuration flag.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_get_config_flag(size_t index, const char **out_name, const char **out_description);

/*!
Sets the specified option for the specified configuration. The configuration option is indicated by name.
To obtain a list of config options, see `duckdb_get_config_flag`.

In the source code, configuration options are defined in `config.cpp`.

This can fail if either the name is invalid, or if the value provided for the option is invalid.

* @param config The configuration object to set the option on.
* @param name The name of the configuration flag to set.
* @param option The value to set the configuration flag to.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_set_config(duckdb_config config, const char *name, const char *option);

/*!
Destroys the specified configuration object and de-allocates all memory allocated for the object.

* @param config The configuration object to destroy.
*/
DUCKDB_C_API void duckdb_destroy_config(duckdb_config *config);

//===--------------------------------------------------------------------===//
// Error Data
//===--------------------------------------------------------------------===//

// Functions that can throw DuckDB errors must return duckdb_error_data.
// Please use this interface for all new functions, as it deprecates all previous error handling approaches.

/*!
Creates duckdb_error_data.
Must be destroyed with `duckdb_destroy_error_data`.

* @param type The error type.
* @param message The error message.
* @return The error data.
*/
DUCKDB_C_API duckdb_error_data duckdb_create_error_data(duckdb_error_type type, const char *message);

/*!
Destroys the error data and deallocates its memory.

* @param error_data The error data to destroy.
*/
DUCKDB_C_API void duckdb_destroy_error_data(duckdb_error_data *error_data);

/*!
Returns the duckdb_error_type of the error data.

* @param error_data The error data.
* @return The error type.
*/
DUCKDB_C_API duckdb_error_type duckdb_error_data_error_type(duckdb_error_data error_data);

/*!
Returns the error message of the error data. Must not be freed.

* @param error_data The error data.
* @return The error message.
*/
DUCKDB_C_API const char *duckdb_error_data_message(duckdb_error_data error_data);

/*!
Returns whether the error data contains an error or not.

* @param error_data The error data.
* @return True, if the error data contains an exception, else false.
*/
DUCKDB_C_API bool duckdb_error_data_has_error(duckdb_error_data error_data);

//===--------------------------------------------------------------------===//
// Query Execution
//===--------------------------------------------------------------------===//

/*!
Executes a SQL query within a connection and stores the full (materialized) result in the out_result pointer.
If the query fails to execute, DuckDBError is returned and the error message can be retrieved by calling
`duckdb_result_error`.

Note that after running `duckdb_query`, `duckdb_destroy_result` must be called on the result object even if the
query fails, otherwise the error stored within the result will not be freed correctly.

* @param connection The connection to perform the query in.
* @param query The SQL query to run.
* @param out_result The query result.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_query(duckdb_connection connection, const char *query, duckdb_result *out_result);

/*!
Closes the result and de-allocates all memory allocated for that result.

* @param result The result to destroy.
*/
DUCKDB_C_API void duckdb_destroy_result(duckdb_result *result);

/*!
Returns the column name of the specified column. The result should not need to be freed; the column names will
automatically be destroyed when the result is destroyed.

Returns `NULL` if the column is out of range.

* @param result The result object to fetch the column name from.
* @param col The column index.
* @return The column name of the specified column.
*/
DUCKDB_C_API const char *duckdb_column_name(duckdb_result *result, idx_t col);

/*!
Returns the column type of the specified column.

Returns `DUCKDB_TYPE_INVALID` if the column is out of range.

* @param result The result object to fetch the column type from.
* @param col The column index.
* @return The column type of the specified column.
*/
DUCKDB_C_API duckdb_type duckdb_column_type(duckdb_result *result, idx_t col);

/*!
Returns the statement type of the statement that was executed

* @param result The result object to fetch the statement type from.
* @return duckdb_statement_type value or DUCKDB_STATEMENT_TYPE_INVALID
*/
DUCKDB_C_API duckdb_statement_type duckdb_result_statement_type(duckdb_result result);

/*!
Returns the logical column type of the specified column.

The return type of this call should be destroyed with `duckdb_destroy_logical_type`.

Returns `NULL` if the column is out of range.

* @param result The result object to fetch the column type from.
* @param col The column index.
* @return The logical column type of the specified column.
*/
DUCKDB_C_API duckdb_logical_type duckdb_column_logical_type(duckdb_result *result, idx_t col);

/*!
Returns the arrow options associated with the given result. These options are definitions of how the arrow arrays/schema
should be produced.
* @param result The result object to fetch arrow options from.
* @return The arrow options associated with the given result. This must be destroyed with
`duckdb_destroy_arrow_options`.
*/
DUCKDB_C_API duckdb_arrow_options duckdb_result_get_arrow_options(duckdb_result *result);

/*!
Returns the number of columns present in a the result object.

* @param result The result object.
* @return The number of columns present in the result object.
*/
DUCKDB_C_API idx_t duckdb_column_count(duckdb_result *result);

#ifndef DUCKDB_API_NO_DEPRECATED
/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

Returns the number of rows present in the result object.

* @param result The result object.
* @return The number of rows present in the result object.
*/
DUCKDB_C_API idx_t duckdb_row_count(duckdb_result *result);

#endif

/*!
Returns the number of rows changed by the query stored in the result. This is relevant only for INSERT/UPDATE/DELETE
queries. For other queries the rows_changed will be 0.

* @param result The result object.
* @return The number of rows changed.
*/
DUCKDB_C_API idx_t duckdb_rows_changed(duckdb_result *result);

#ifndef DUCKDB_API_NO_DEPRECATED
/*!
**DEPRECATED**: Prefer using `duckdb_result_get_chunk` instead.

Returns the data of a specific column of a result in columnar format.

The function returns a dense array which contains the result data. The exact type stored in the array depends on the
corresponding duckdb_type (as provided by `duckdb_column_type`). For the exact type by which the data should be
accessed, see the comments in [the types section](types) or the `DUCKDB_TYPE` enum.

For example, for a column of type `DUCKDB_TYPE_INTEGER`, rows can be accessed in the following manner:
```c
int32_t *data = (int32_t *) duckdb_column_data(&result, 0);
printf("Data for row %d: %d\n", row, data[row]);
```

* @param result The result object to fetch the column data from.
* @param col The column index.
* @return The column data of the specified column.
*/
DUCKDB_C_API void *duckdb_column_data(duckdb_result *result, idx_t col);

/*!
**DEPRECATED**: Prefer using `duckdb_result_get_chunk` instead.

Returns the nullmask of a specific column of a result in columnar format. The nullmask indicates for every row
whether or not the corresponding row is `NULL`. If a row is `NULL`, the values present in the array provided
by `duckdb_column_data` are undefined.

```c
int32_t *data = (int32_t *) duckdb_column_data(&result, 0);
bool *nullmask = duckdb_nullmask_data(&result, 0);
if (nullmask[row]) {
    printf("Data for row %d: NULL\n", row);
} else {
    printf("Data for row %d: %d\n", row, data[row]);
}
```

* @param result The result object to fetch the nullmask from.
* @param col The column index.
* @return The nullmask of the specified column.
*/
DUCKDB_C_API bool *duckdb_nullmask_data(duckdb_result *result, idx_t col);

#endif

/*!
Returns the error message contained within the result. The error is only set if `duckdb_query` returns `DuckDBError`.

The result of this function must not be freed. It will be cleaned up when `duckdb_destroy_result` is called.

* @param result The result object to fetch the error from.
* @return The error of the result.
*/
DUCKDB_C_API const char *duckdb_result_error(duckdb_result *result);

/*!
Returns the result error type contained within the result. The error is only set if `duckdb_query` returns
`DuckDBError`.

* @param result The result object to fetch the error from.
* @return The error type of the result.
*/
DUCKDB_C_API duckdb_error_type duckdb_result_error_type(duckdb_result *result);

//===--------------------------------------------------------------------===//
// Result Functions
//===--------------------------------------------------------------------===//

#ifndef DUCKDB_API_NO_DEPRECATED
/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

Fetches a data chunk from the duckdb_result. This function should be called repeatedly until the result is exhausted.

The result must be destroyed with `duckdb_destroy_data_chunk`.

This function supersedes all `duckdb_value` functions, as well as the `duckdb_column_data` and `duckdb_nullmask_data`
functions. It results in significantly better performance, and should be preferred in newer code-bases.

If this function is used, none of the other result functions can be used and vice versa (i.e. this function cannot be
mixed with the legacy result functions).

Use `duckdb_result_chunk_count` to figure out how many chunks there are in the result.

* @param result The result object to fetch the data chunk from.
* @param chunk_index The chunk index to fetch from.
* @return The resulting data chunk. Returns `NULL` if the chunk index is out of bounds.
*/
DUCKDB_C_API duckdb_data_chunk duckdb_result_get_chunk(duckdb_result result, idx_t chunk_index);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

Checks if the type of the internal result is StreamQueryResult.

* @param result The result object to check.
* @return Whether or not the result object is of the type StreamQueryResult
*/
DUCKDB_C_API bool duckdb_result_is_streaming(duckdb_result result);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

Returns the number of data chunks present in the result.

* @param result The result object
* @return Number of data chunks present in the result.
*/
DUCKDB_C_API idx_t duckdb_result_chunk_count(duckdb_result result);

#endif

/*!
Returns the return_type of the given result, or DUCKDB_RETURN_TYPE_INVALID on error

* @param result The result object
* @return The return_type
*/
DUCKDB_C_API duckdb_result_type duckdb_result_return_type(duckdb_result result);

//===--------------------------------------------------------------------===//
// Safe Fetch Functions
//===--------------------------------------------------------------------===//

// These functions will perform conversions if necessary.
// On failure (e.g. if conversion cannot be performed or if the value is NULL) a default value is returned.
// Note that these functions are slow since they perform bounds checking and conversion
// For fast access of values prefer using `duckdb_result_get_chunk`
#ifndef DUCKDB_API_NO_DEPRECATED
/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

* @return The boolean value at the specified location, or false if the value cannot be converted.
*/
DUCKDB_C_API bool duckdb_value_boolean(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

* @return The int8_t value at the specified location, or 0 if the value cannot be converted.
*/
DUCKDB_C_API int8_t duckdb_value_int8(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

* @return The int16_t value at the specified location, or 0 if the value cannot be converted.
*/
DUCKDB_C_API int16_t duckdb_value_int16(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

* @return The int32_t value at the specified location, or 0 if the value cannot be converted.
*/
DUCKDB_C_API int32_t duckdb_value_int32(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

* @return The int64_t value at the specified location, or 0 if the value cannot be converted.
*/
DUCKDB_C_API int64_t duckdb_value_int64(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

* @return The duckdb_hugeint value at the specified location, or 0 if the value cannot be converted.
*/
DUCKDB_C_API duckdb_hugeint duckdb_value_hugeint(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

* @return The duckdb_uhugeint value at the specified location, or 0 if the value cannot be converted.
*/
DUCKDB_C_API duckdb_uhugeint duckdb_value_uhugeint(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

* @return The duckdb_decimal value at the specified location, or 0 if the value cannot be converted.
*/
DUCKDB_C_API duckdb_decimal duckdb_value_decimal(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

* @return The uint8_t value at the specified location, or 0 if the value cannot be converted.
*/
DUCKDB_C_API uint8_t duckdb_value_uint8(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

* @return The uint16_t value at the specified location, or 0 if the value cannot be converted.
*/
DUCKDB_C_API uint16_t duckdb_value_uint16(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

* @return The uint32_t value at the specified location, or 0 if the value cannot be converted.
*/
DUCKDB_C_API uint32_t duckdb_value_uint32(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

* @return The uint64_t value at the specified location, or 0 if the value cannot be converted.
*/
DUCKDB_C_API uint64_t duckdb_value_uint64(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

* @return The float value at the specified location, or 0 if the value cannot be converted.
*/
DUCKDB_C_API float duckdb_value_float(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

* @return The double value at the specified location, or 0 if the value cannot be converted.
*/
DUCKDB_C_API double duckdb_value_double(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

* @return The duckdb_date value at the specified location, or 0 if the value cannot be converted.
*/
DUCKDB_C_API duckdb_date duckdb_value_date(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

* @return The duckdb_time value at the specified location, or 0 if the value cannot be converted.
*/
DUCKDB_C_API duckdb_time duckdb_value_time(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

* @return The duckdb_timestamp value at the specified location, or 0 if the value cannot be converted.
*/
DUCKDB_C_API duckdb_timestamp duckdb_value_timestamp(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

* @return The duckdb_interval value at the specified location, or 0 if the value cannot be converted.
*/
DUCKDB_C_API duckdb_interval duckdb_value_interval(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATED**: Use duckdb_value_string instead. This function does not work correctly if the string contains null
bytes.

* @return The text value at the specified location as a null-terminated string, or nullptr if the value cannot be
converted. The result must be freed with `duckdb_free`.
*/
DUCKDB_C_API char *duckdb_value_varchar(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

No support for nested types, and for other complex types.
The resulting field "string.data" must be freed with `duckdb_free.`

* @return The string value at the specified location. Attempts to cast the result value to string.
*/
DUCKDB_C_API duckdb_string duckdb_value_string(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATED**: Use duckdb_value_string_internal instead. This function does not work correctly if the string contains
null bytes.

* @return The char* value at the specified location. ONLY works on VARCHAR columns and does not auto-cast.
If the column is NOT a VARCHAR column this function will return NULL.

The result must NOT be freed.
*/
DUCKDB_C_API char *duckdb_value_varchar_internal(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATED**: Use duckdb_value_string_internal instead. This function does not work correctly if the string contains
null bytes.
* @return The char* value at the specified location. ONLY works on VARCHAR columns and does not auto-cast.
If the column is NOT a VARCHAR column this function will return NULL.

The result must NOT be freed.
*/
DUCKDB_C_API duckdb_string duckdb_value_string_internal(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

* @return The duckdb_blob value at the specified location. Returns a blob with blob.data set to nullptr if the
value cannot be converted. The resulting field "blob.data" must be freed with `duckdb_free.`
*/
DUCKDB_C_API duckdb_blob duckdb_value_blob(duckdb_result *result, idx_t col, idx_t row);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

* @return Returns true if the value at the specified index is NULL, and false otherwise.
*/
DUCKDB_C_API bool duckdb_value_is_null(duckdb_result *result, idx_t col, idx_t row);

#endif

//===--------------------------------------------------------------------===//
// Helpers
//===--------------------------------------------------------------------===//

/*!
Allocate `size` bytes of memory using the duckdb internal malloc function. Any memory allocated in this manner
should be freed using `duckdb_free`.

* @param size The number of bytes to allocate.
* @return A pointer to the allocated memory region.
*/
DUCKDB_C_API void *duckdb_malloc(size_t size);

/*!
Free a value returned from `duckdb_malloc`, `duckdb_value_varchar`, `duckdb_value_blob`, or
`duckdb_value_string`.

* @param ptr The memory region to de-allocate.
*/
DUCKDB_C_API void duckdb_free(void *ptr);

/*!
The internal vector size used by DuckDB.
This is the amount of tuples that will fit into a data chunk created by `duckdb_create_data_chunk`.

* @return The vector size.
*/
DUCKDB_C_API idx_t duckdb_vector_size();

/*!
Whether or not the duckdb_string_t value is inlined.
This means that the data of the string does not have a separate allocation.

*/
DUCKDB_C_API bool duckdb_string_is_inlined(duckdb_string_t string);

/*!
Get the string length of a string_t

* @param string The string to get the length of.
* @return The length.
*/
DUCKDB_C_API uint32_t duckdb_string_t_length(duckdb_string_t string);

/*!
Get a pointer to the string data of a string_t

* @param string The string to get the pointer to.
* @return The pointer.
*/
DUCKDB_C_API const char *duckdb_string_t_data(duckdb_string_t *string);

//===--------------------------------------------------------------------===//
// Date Time Timestamp Helpers
//===--------------------------------------------------------------------===//

/*!
Decompose a `duckdb_date` object into year, month and date (stored as `duckdb_date_struct`).

* @param date The date object, as obtained from a `DUCKDB_TYPE_DATE` column.
* @return The `duckdb_date_struct` with the decomposed elements.
*/
DUCKDB_C_API duckdb_date_struct duckdb_from_date(duckdb_date date);

/*!
Re-compose a `duckdb_date` from year, month and date (`duckdb_date_struct`).

* @param date The year, month and date stored in a `duckdb_date_struct`.
* @return The `duckdb_date` element.
*/
DUCKDB_C_API duckdb_date duckdb_to_date(duckdb_date_struct date);

/*!
Test a `duckdb_date` to see if it is a finite value.

* @param date The date object, as obtained from a `DUCKDB_TYPE_DATE` column.
* @return True if the date is finite, false if it is ±infinity.
*/
DUCKDB_C_API bool duckdb_is_finite_date(duckdb_date date);

/*!
Decompose a `duckdb_time` object into hour, minute, second and microsecond (stored as `duckdb_time_struct`).

* @param time The time object, as obtained from a `DUCKDB_TYPE_TIME` column.
* @return The `duckdb_time_struct` with the decomposed elements.
*/
DUCKDB_C_API duckdb_time_struct duckdb_from_time(duckdb_time time);

/*!
Create a `duckdb_time_tz` object from micros and a timezone offset.

* @param micros The microsecond component of the time.
* @param offset The timezone offset component of the time.
* @return The `duckdb_time_tz` element.
*/
DUCKDB_C_API duckdb_time_tz duckdb_create_time_tz(int64_t micros, int32_t offset);

/*!
Decompose a TIME_TZ objects into micros and a timezone offset.

Use `duckdb_from_time` to further decompose the micros into hour, minute, second and microsecond.

* @param micros The time object, as obtained from a `DUCKDB_TYPE_TIME_TZ` column.
*/
DUCKDB_C_API duckdb_time_tz_struct duckdb_from_time_tz(duckdb_time_tz micros);

/*!
Re-compose a `duckdb_time` from hour, minute, second and microsecond (`duckdb_time_struct`).

* @param time The hour, minute, second and microsecond in a `duckdb_time_struct`.
* @return The `duckdb_time` element.
*/
DUCKDB_C_API duckdb_time duckdb_to_time(duckdb_time_struct time);

/*!
Decompose a `duckdb_timestamp` object into a `duckdb_timestamp_struct`.

* @param ts The ts object, as obtained from a `DUCKDB_TYPE_TIMESTAMP` column.
* @return The `duckdb_timestamp_struct` with the decomposed elements.
*/
DUCKDB_C_API duckdb_timestamp_struct duckdb_from_timestamp(duckdb_timestamp ts);

/*!
Re-compose a `duckdb_timestamp` from a duckdb_timestamp_struct.

* @param ts The de-composed elements in a `duckdb_timestamp_struct`.
* @return The `duckdb_timestamp` element.
*/
DUCKDB_C_API duckdb_timestamp duckdb_to_timestamp(duckdb_timestamp_struct ts);

/*!
Test a `duckdb_timestamp` to see if it is a finite value.

* @param ts The duckdb_timestamp object, as obtained from a `DUCKDB_TYPE_TIMESTAMP` column.
* @return True if the timestamp is finite, false if it is ±infinity.
*/
DUCKDB_C_API bool duckdb_is_finite_timestamp(duckdb_timestamp ts);

/*!
Test a `duckdb_timestamp_s` to see if it is a finite value.

* @param ts The duckdb_timestamp_s object, as obtained from a `DUCKDB_TYPE_TIMESTAMP_S` column.
* @return True if the timestamp is finite, false if it is ±infinity.
*/
DUCKDB_C_API bool duckdb_is_finite_timestamp_s(duckdb_timestamp_s ts);

/*!
Test a `duckdb_timestamp_ms` to see if it is a finite value.

* @param ts The duckdb_timestamp_ms object, as obtained from a `DUCKDB_TYPE_TIMESTAMP_MS` column.
* @return True if the timestamp is finite, false if it is ±infinity.
*/
DUCKDB_C_API bool duckdb_is_finite_timestamp_ms(duckdb_timestamp_ms ts);

/*!
Test a `duckdb_timestamp_ns` to see if it is a finite value.

* @param ts The duckdb_timestamp_ns object, as obtained from a `DUCKDB_TYPE_TIMESTAMP_NS` column.
* @return True if the timestamp is finite, false if it is ±infinity.
*/
DUCKDB_C_API bool duckdb_is_finite_timestamp_ns(duckdb_timestamp_ns ts);

//===--------------------------------------------------------------------===//
// Hugeint Helpers
//===--------------------------------------------------------------------===//

/*!
Converts a duckdb_hugeint object (as obtained from a `DUCKDB_TYPE_HUGEINT` column) into a double.

* @param val The hugeint value.
* @return The converted `double` element.
*/
DUCKDB_C_API double duckdb_hugeint_to_double(duckdb_hugeint val);

/*!
Converts a double value to a duckdb_hugeint object.

If the conversion fails because the double value is too big the result will be 0.

* @param val The double value.
* @return The converted `duckdb_hugeint` element.
*/
DUCKDB_C_API duckdb_hugeint duckdb_double_to_hugeint(double val);

//===--------------------------------------------------------------------===//
// Unsigned Hugeint Helpers
//===--------------------------------------------------------------------===//

/*!
Converts a duckdb_uhugeint object (as obtained from a `DUCKDB_TYPE_UHUGEINT` column) into a double.

* @param val The uhugeint value.
* @return The converted `double` element.
*/
DUCKDB_C_API double duckdb_uhugeint_to_double(duckdb_uhugeint val);

/*!
Converts a double value to a duckdb_uhugeint object.

If the conversion fails because the double value is too big the result will be 0.

* @param val The double value.
* @return The converted `duckdb_uhugeint` element.
*/
DUCKDB_C_API duckdb_uhugeint duckdb_double_to_uhugeint(double val);

//===--------------------------------------------------------------------===//
// Decimal Helpers
//===--------------------------------------------------------------------===//

/*!
Converts a double value to a duckdb_decimal object.

If the conversion fails because the double value is too big, or the width/scale are invalid the result will be 0.

* @param val The double value.
* @return The converted `duckdb_decimal` element.
*/
DUCKDB_C_API duckdb_decimal duckdb_double_to_decimal(double val, uint8_t width, uint8_t scale);

/*!
Converts a duckdb_decimal object (as obtained from a `DUCKDB_TYPE_DECIMAL` column) into a double.

* @param val The decimal value.
* @return The converted `double` element.
*/
DUCKDB_C_API double duckdb_decimal_to_double(duckdb_decimal val);

//===--------------------------------------------------------------------===//
// Prepared Statements
//===--------------------------------------------------------------------===//

// A prepared statement is a parameterized query that allows you to bind parameters to it.
// * This is useful to easily supply parameters to functions and avoid SQL injection attacks.
// * This is useful to speed up queries that you will execute several times with different parameters.
// Because the query will only be parsed, bound, optimized and planned once during the prepare stage,
// rather than once per execution.
// For example:
//   SELECT * FROM tbl WHERE id=?
// Or a query with multiple parameters:
//   SELECT * FROM tbl WHERE id=$1 OR name=$2
/*!
Create a prepared statement object from a query.

Note that after calling `duckdb_prepare`, the prepared statement should always be destroyed using
`duckdb_destroy_prepare`, even if the prepare fails.

If the prepare fails, `duckdb_prepare_error` can be called to obtain the reason why the prepare failed.

* @param connection The connection object
* @param query The SQL query to prepare
* @param out_prepared_statement The resulting prepared statement object
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_prepare(duckdb_connection connection, const char *query,
                                         duckdb_prepared_statement *out_prepared_statement);

/*!
Closes the prepared statement and de-allocates all memory allocated for the statement.

* @param prepared_statement The prepared statement to destroy.
*/
DUCKDB_C_API void duckdb_destroy_prepare(duckdb_prepared_statement *prepared_statement);

/*!
Returns the error message associated with the given prepared statement.
If the prepared statement has no error message, this returns `nullptr` instead.

The error message should not be freed. It will be de-allocated when `duckdb_destroy_prepare` is called.

* @param prepared_statement The prepared statement to obtain the error from.
* @return The error message, or `nullptr` if there is none.
*/
DUCKDB_C_API const char *duckdb_prepare_error(duckdb_prepared_statement prepared_statement);

/*!
Returns the number of parameters that can be provided to the given prepared statement.

Returns 0 if the query was not successfully prepared.

* @param prepared_statement The prepared statement to obtain the number of parameters for.
*/
DUCKDB_C_API idx_t duckdb_nparams(duckdb_prepared_statement prepared_statement);

/*!
Returns the name used to identify the parameter
The returned string should be freed using `duckdb_free`.

Returns NULL if the index is out of range for the provided prepared statement.

* @param prepared_statement The prepared statement for which to get the parameter name from.
*/
DUCKDB_C_API const char *duckdb_parameter_name(duckdb_prepared_statement prepared_statement, idx_t index);

/*!
Returns the parameter type for the parameter at the given index.

Returns `DUCKDB_TYPE_INVALID` if the parameter index is out of range or the statement was not successfully prepared.

* @param prepared_statement The prepared statement.
* @param param_idx The parameter index.
* @return The parameter type
*/
DUCKDB_C_API duckdb_type duckdb_param_type(duckdb_prepared_statement prepared_statement, idx_t param_idx);

/*!
Returns the logical type for the parameter at the given index.

Returns `nullptr` if the parameter index is out of range or the statement was not successfully prepared.

The return type of this call should be destroyed with `duckdb_destroy_logical_type`.

* @param prepared_statement The prepared statement.
* @param param_idx The parameter index.
* @return The logical type of the parameter
*/
DUCKDB_C_API duckdb_logical_type duckdb_param_logical_type(duckdb_prepared_statement prepared_statement,
                                                           idx_t param_idx);

/*!
Clear the params bind to the prepared statement.
*/
DUCKDB_C_API duckdb_state duckdb_clear_bindings(duckdb_prepared_statement prepared_statement);

/*!
Returns the statement type of the statement to be executed

* @param statement The prepared statement.
* @return duckdb_statement_type value or DUCKDB_STATEMENT_TYPE_INVALID
*/
DUCKDB_C_API duckdb_statement_type duckdb_prepared_statement_type(duckdb_prepared_statement statement);

/*!
Returns the number of columns present in a the result of the prepared statement. If any of the column types are invalid,
the result will be 1.

* @param prepared_statement The prepared statement.
* @return The number of columns present in the result of the prepared statement.
*/
DUCKDB_C_API idx_t duckdb_prepared_statement_column_count(duckdb_prepared_statement prepared_statement);

/*!
Returns the name of the specified column of the result of the prepared_statement.
The returned string should be freed using `duckdb_free`.

Returns `nullptr` if the column is out of range.

* @param prepared_statement The prepared statement.
* @param col_idx The column index.
* @return The column name of the specified column.
*/
DUCKDB_C_API const char *duckdb_prepared_statement_column_name(duckdb_prepared_statement prepared_statement,
                                                               idx_t col_idx);

/*!
Returns the column type of the specified column of the result of the prepared_statement.

Returns `DUCKDB_TYPE_INVALID` if the column is out of range.
The return type of this call should be destroyed with `duckdb_destroy_logical_type`.

* @param prepared_statement The prepared statement to fetch the column type from.
* @param col_idx The column index.
* @return The logical type of the specified column.
*/
DUCKDB_C_API duckdb_logical_type
duckdb_prepared_statement_column_logical_type(duckdb_prepared_statement prepared_statement, idx_t col_idx);

/*!
Returns the column type of the specified column of the result of the prepared_statement.

Returns `DUCKDB_TYPE_INVALID` if the column is out of range.

* @param prepared_statement The prepared statement to fetch the column type from.
* @param col_idx The column index.
* @return The type of the specified column.
*/
DUCKDB_C_API duckdb_type duckdb_prepared_statement_column_type(duckdb_prepared_statement prepared_statement,
                                                               idx_t col_idx);

//===--------------------------------------------------------------------===//
// Bind Values to Prepared Statements
//===--------------------------------------------------------------------===//

/*!
Binds a value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_value(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                            duckdb_value val);

/*!
Retrieve the index of the parameter for the prepared statement, identified by name
*/
DUCKDB_C_API duckdb_state duckdb_bind_parameter_index(duckdb_prepared_statement prepared_statement,
                                                      idx_t *param_idx_out, const char *name);

/*!
Binds a bool value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_boolean(duckdb_prepared_statement prepared_statement, idx_t param_idx, bool val);

/*!
Binds an int8_t value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_int8(duckdb_prepared_statement prepared_statement, idx_t param_idx, int8_t val);

/*!
Binds an int16_t value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_int16(duckdb_prepared_statement prepared_statement, idx_t param_idx, int16_t val);

/*!
Binds an int32_t value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_int32(duckdb_prepared_statement prepared_statement, idx_t param_idx, int32_t val);

/*!
Binds an int64_t value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_int64(duckdb_prepared_statement prepared_statement, idx_t param_idx, int64_t val);

/*!
Binds a duckdb_hugeint value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_hugeint(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                              duckdb_hugeint val);

/*!
Binds a duckdb_uhugeint value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_uhugeint(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                               duckdb_uhugeint val);

/*!
Binds a duckdb_decimal value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_decimal(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                              duckdb_decimal val);

/*!
Binds a uint8_t value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_uint8(duckdb_prepared_statement prepared_statement, idx_t param_idx, uint8_t val);

/*!
Binds a uint16_t value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_uint16(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                             uint16_t val);

/*!
Binds a uint32_t value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_uint32(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                             uint32_t val);

/*!
Binds a uint64_t value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_uint64(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                             uint64_t val);

/*!
Binds a float value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_float(duckdb_prepared_statement prepared_statement, idx_t param_idx, float val);

/*!
Binds a double value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_double(duckdb_prepared_statement prepared_statement, idx_t param_idx, double val);

/*!
Binds a duckdb_date value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_date(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                           duckdb_date val);

/*!
Binds a duckdb_time value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_time(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                           duckdb_time val);

/*!
Binds a duckdb_timestamp value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_timestamp(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                                duckdb_timestamp val);

/*!
Binds a duckdb_timestamp value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_timestamp_tz(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                                   duckdb_timestamp val);

/*!
Binds a duckdb_interval value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_interval(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                               duckdb_interval val);

/*!
Binds a null-terminated varchar value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_varchar(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                              const char *val);

/*!
Binds a varchar value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_varchar_length(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                                     const char *val, idx_t length);

/*!
Binds a blob value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_blob(duckdb_prepared_statement prepared_statement, idx_t param_idx,
                                           const void *data, idx_t length);

/*!
Binds a NULL value to the prepared statement at the specified index.
*/
DUCKDB_C_API duckdb_state duckdb_bind_null(duckdb_prepared_statement prepared_statement, idx_t param_idx);

//===--------------------------------------------------------------------===//
// Execute Prepared Statements
//===--------------------------------------------------------------------===//

/*!
Executes the prepared statement with the given bound parameters, and returns a materialized query result.

This method can be called multiple times for each prepared statement, and the parameters can be modified
between calls to this function.

Note that the result must be freed with `duckdb_destroy_result`.

* @param prepared_statement The prepared statement to execute.
* @param out_result The query result.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_execute_prepared(duckdb_prepared_statement prepared_statement,
                                                  duckdb_result *out_result);

#ifndef DUCKDB_API_NO_DEPRECATED
/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

Executes the prepared statement with the given bound parameters, and returns an optionally-streaming query result.
To determine if the resulting query was in fact streamed, use `duckdb_result_is_streaming`

This method can be called multiple times for each prepared statement, and the parameters can be modified
between calls to this function.

Note that the result must be freed with `duckdb_destroy_result`.

* @param prepared_statement The prepared statement to execute.
* @param out_result The query result.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_execute_prepared_streaming(duckdb_prepared_statement prepared_statement,
                                                            duckdb_result *out_result);

#endif

//===--------------------------------------------------------------------===//
// Extract Statements
//===--------------------------------------------------------------------===//

// A query string can be extracted into multiple SQL statements. Each statement can be prepared and executed separately.
/*!
Extract all statements from a query.
Note that after calling `duckdb_extract_statements`, the extracted statements should always be destroyed using
`duckdb_destroy_extracted`, even if no statements were extracted.

If the extract fails, `duckdb_extract_statements_error` can be called to obtain the reason why the extract failed.

* @param connection The connection object
* @param query The SQL query to extract
* @param out_extracted_statements The resulting extracted statements object
* @return The number of extracted statements or 0 on failure.
*/
DUCKDB_C_API idx_t duckdb_extract_statements(duckdb_connection connection, const char *query,
                                             duckdb_extracted_statements *out_extracted_statements);

/*!
Prepare an extracted statement.
Note that after calling `duckdb_prepare_extracted_statement`, the prepared statement should always be destroyed using
`duckdb_destroy_prepare`, even if the prepare fails.

If the prepare fails, `duckdb_prepare_error` can be called to obtain the reason why the prepare failed.

* @param connection The connection object
* @param extracted_statements The extracted statements object
* @param index The index of the extracted statement to prepare
* @param out_prepared_statement The resulting prepared statement object
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_prepare_extracted_statement(duckdb_connection connection,
                                                             duckdb_extracted_statements extracted_statements,
                                                             idx_t index,
                                                             duckdb_prepared_statement *out_prepared_statement);

/*!
Returns the error message contained within the extracted statements.
The result of this function must not be freed. It will be cleaned up when `duckdb_destroy_extracted` is called.

* @param extracted_statements The extracted statements to fetch the error from.
* @return The error of the extracted statements.
*/
DUCKDB_C_API const char *duckdb_extract_statements_error(duckdb_extracted_statements extracted_statements);

/*!
De-allocates all memory allocated for the extracted statements.
* @param extracted_statements The extracted statements to destroy.
*/
DUCKDB_C_API void duckdb_destroy_extracted(duckdb_extracted_statements *extracted_statements);

//===--------------------------------------------------------------------===//
// Pending Result Interface
//===--------------------------------------------------------------------===//

/*!
Executes the prepared statement with the given bound parameters, and returns a pending result.
The pending result represents an intermediate structure for a query that is not yet fully executed.
The pending result can be used to incrementally execute a query, returning control to the client between tasks.

Note that after calling `duckdb_pending_prepared`, the pending result should always be destroyed using
`duckdb_destroy_pending`, even if this function returns DuckDBError.

* @param prepared_statement The prepared statement to execute.
* @param out_result The pending query result.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_pending_prepared(duckdb_prepared_statement prepared_statement,
                                                  duckdb_pending_result *out_result);

#ifndef DUCKDB_API_NO_DEPRECATED
/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

Executes the prepared statement with the given bound parameters, and returns a pending result.
This pending result will create a streaming duckdb_result when executed.
The pending result represents an intermediate structure for a query that is not yet fully executed.

Note that after calling `duckdb_pending_prepared_streaming`, the pending result should always be destroyed using
`duckdb_destroy_pending`, even if this function returns DuckDBError.

* @param prepared_statement The prepared statement to execute.
* @param out_result The pending query result.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_pending_prepared_streaming(duckdb_prepared_statement prepared_statement,
                                                            duckdb_pending_result *out_result);

#endif

/*!
Closes the pending result and de-allocates all memory allocated for the result.

* @param pending_result The pending result to destroy.
*/
DUCKDB_C_API void duckdb_destroy_pending(duckdb_pending_result *pending_result);

/*!
Returns the error message contained within the pending result.

The result of this function must not be freed. It will be cleaned up when `duckdb_destroy_pending` is called.

* @param pending_result The pending result to fetch the error from.
* @return The error of the pending result.
*/
DUCKDB_C_API const char *duckdb_pending_error(duckdb_pending_result pending_result);

/*!
Executes a single task within the query, returning whether or not the query is ready.

If this returns DUCKDB_PENDING_RESULT_READY, the duckdb_execute_pending function can be called to obtain the result.
If this returns DUCKDB_PENDING_RESULT_NOT_READY, the duckdb_pending_execute_task function should be called again.
If this returns DUCKDB_PENDING_ERROR, an error occurred during execution.

The error message can be obtained by calling duckdb_pending_error on the pending_result.

* @param pending_result The pending result to execute a task within.
* @return The state of the pending result after the execution.
*/
DUCKDB_C_API duckdb_pending_state duckdb_pending_execute_task(duckdb_pending_result pending_result);

/*!
If this returns DUCKDB_PENDING_RESULT_READY, the duckdb_execute_pending function can be called to obtain the result.
If this returns DUCKDB_PENDING_RESULT_NOT_READY, the duckdb_pending_execute_check_state function should be called again.
If this returns DUCKDB_PENDING_ERROR, an error occurred during execution.

The error message can be obtained by calling duckdb_pending_error on the pending_result.

* @param pending_result The pending result.
* @return The state of the pending result.
*/
DUCKDB_C_API duckdb_pending_state duckdb_pending_execute_check_state(duckdb_pending_result pending_result);

/*!
Fully execute a pending query result, returning the final query result.

If duckdb_pending_execute_task has been called until DUCKDB_PENDING_RESULT_READY was returned, this will return fast.
Otherwise, all remaining tasks must be executed first.

Note that the result must be freed with `duckdb_destroy_result`.

* @param pending_result The pending result to execute.
* @param out_result The result object.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_execute_pending(duckdb_pending_result pending_result, duckdb_result *out_result);

/*!
Returns whether a duckdb_pending_state is finished executing. For example if `pending_state` is
DUCKDB_PENDING_RESULT_READY, this function will return true.

* @param pending_state The pending state on which to decide whether to finish execution.
* @return Boolean indicating pending execution should be considered finished.
*/
DUCKDB_C_API bool duckdb_pending_execution_is_finished(duckdb_pending_state pending_state);

//===--------------------------------------------------------------------===//
// Value Interface
//===--------------------------------------------------------------------===//

/*!
Destroys the value and de-allocates all memory allocated for that type.

* @param value The value to destroy.
*/
DUCKDB_C_API void duckdb_destroy_value(duckdb_value *value);

/*!
Creates a value from a null-terminated string

* @param text The null-terminated string
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_varchar(const char *text);

/*!
Creates a value from a string

* @param text The text
* @param length The length of the text
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_varchar_length(const char *text, idx_t length);

/*!
Creates a value from a boolean

* @param input The boolean value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_bool(bool input);

/*!
Creates a value from an int8_t (a tinyint)

* @param input The tinyint value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_int8(int8_t input);

/*!
Creates a value from a uint8_t (a utinyint)

* @param input The utinyint value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_uint8(uint8_t input);

/*!
Creates a value from an int16_t (a smallint)

* @param input The smallint value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_int16(int16_t input);

/*!
Creates a value from a uint16_t (a usmallint)

* @param input The usmallint value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_uint16(uint16_t input);

/*!
Creates a value from an int32_t (an integer)

* @param input The integer value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_int32(int32_t input);

/*!
Creates a value from a uint32_t (a uinteger)

* @param input The uinteger value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_uint32(uint32_t input);

/*!
Creates a value from a uint64_t (a ubigint)

* @param input The ubigint value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_uint64(uint64_t input);

/*!
Creates a value from an int64

* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_int64(int64_t val);

/*!
Creates a value from a hugeint

* @param input The hugeint value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_hugeint(duckdb_hugeint input);

/*!
Creates a value from a uhugeint

* @param input The uhugeint value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_uhugeint(duckdb_uhugeint input);

/*!
Creates a BIGNUM value from a duckdb_bignum

* @param input The duckdb_bignum value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_bignum(duckdb_bignum input);

/*!
Creates a DECIMAL value from a duckdb_decimal

* @param input The duckdb_decimal value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_decimal(duckdb_decimal input);

/*!
Creates a value from a float

* @param input The float value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_float(float input);

/*!
Creates a value from a double

* @param input The double value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_double(double input);

/*!
Creates a value from a date

* @param input The date value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_date(duckdb_date input);

/*!
Creates a value from a time

* @param input The time value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_time(duckdb_time input);

/*!
Creates a value from a time_ns

* @param input The time value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_time_ns(duckdb_time_ns input);

/*!
Creates a value from a time_tz.
Not to be confused with `duckdb_create_time_tz`, which creates a duckdb_time_tz_t.

* @param value The time_tz value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_time_tz_value(duckdb_time_tz value);

/*!
Creates a TIMESTAMP value from a duckdb_timestamp

* @param input The duckdb_timestamp value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_timestamp(duckdb_timestamp input);

/*!
Creates a TIMESTAMP_TZ value from a duckdb_timestamp

* @param input The duckdb_timestamp value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_timestamp_tz(duckdb_timestamp input);

/*!
Creates a TIMESTAMP_S value from a duckdb_timestamp_s

* @param input The duckdb_timestamp_s value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_timestamp_s(duckdb_timestamp_s input);

/*!
Creates a TIMESTAMP_MS value from a duckdb_timestamp_ms

* @param input The duckdb_timestamp_ms value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_timestamp_ms(duckdb_timestamp_ms input);

/*!
Creates a TIMESTAMP_NS value from a duckdb_timestamp_ns

* @param input The duckdb_timestamp_ns value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_timestamp_ns(duckdb_timestamp_ns input);

/*!
Creates a value from an interval

* @param input The interval value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_interval(duckdb_interval input);

/*!
Creates a value from a blob

* @param data The blob data
* @param length The length of the blob data
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_blob(const uint8_t *data, idx_t length);

/*!
Creates a BIT value from a duckdb_bit

* @param input The duckdb_bit value
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_bit(duckdb_bit input);

/*!
Creates a UUID value from a uhugeint

* @param input The duckdb_uhugeint containing the UUID
* @return The value. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_uuid(duckdb_uhugeint input);

/*!
Returns the boolean value of the given value.

* @param val A duckdb_value containing a boolean
* @return A boolean, or false if the value cannot be converted
*/
DUCKDB_C_API bool duckdb_get_bool(duckdb_value val);

/*!
Returns the int8_t value of the given value.

* @param val A duckdb_value containing a tinyint
* @return A int8_t, or MinValue<int8> if the value cannot be converted
*/
DUCKDB_C_API int8_t duckdb_get_int8(duckdb_value val);

/*!
Returns the uint8_t value of the given value.

* @param val A duckdb_value containing a utinyint
* @return A uint8_t, or MinValue<uint8> if the value cannot be converted
*/
DUCKDB_C_API uint8_t duckdb_get_uint8(duckdb_value val);

/*!
Returns the int16_t value of the given value.

* @param val A duckdb_value containing a smallint
* @return A int16_t, or MinValue<int16> if the value cannot be converted
*/
DUCKDB_C_API int16_t duckdb_get_int16(duckdb_value val);

/*!
Returns the uint16_t value of the given value.

* @param val A duckdb_value containing a usmallint
* @return A uint16_t, or MinValue<uint16> if the value cannot be converted
*/
DUCKDB_C_API uint16_t duckdb_get_uint16(duckdb_value val);

/*!
Returns the int32_t value of the given value.

* @param val A duckdb_value containing an integer
* @return A int32_t, or MinValue<int32> if the value cannot be converted
*/
DUCKDB_C_API int32_t duckdb_get_int32(duckdb_value val);

/*!
Returns the uint32_t value of the given value.

* @param val A duckdb_value containing a uinteger
* @return A uint32_t, or MinValue<uint32> if the value cannot be converted
*/
DUCKDB_C_API uint32_t duckdb_get_uint32(duckdb_value val);

/*!
Returns the int64_t value of the given value.

* @param val A duckdb_value containing a bigint
* @return A int64_t, or MinValue<int64> if the value cannot be converted
*/
DUCKDB_C_API int64_t duckdb_get_int64(duckdb_value val);

/*!
Returns the uint64_t value of the given value.

* @param val A duckdb_value containing a ubigint
* @return A uint64_t, or MinValue<uint64> if the value cannot be converted
*/
DUCKDB_C_API uint64_t duckdb_get_uint64(duckdb_value val);

/*!
Returns the hugeint value of the given value.

* @param val A duckdb_value containing a hugeint
* @return A duckdb_hugeint, or MinValue<hugeint> if the value cannot be converted
*/
DUCKDB_C_API duckdb_hugeint duckdb_get_hugeint(duckdb_value val);

/*!
Returns the uhugeint value of the given value.

* @param val A duckdb_value containing a uhugeint
* @return A duckdb_uhugeint, or MinValue<uhugeint> if the value cannot be converted
*/
DUCKDB_C_API duckdb_uhugeint duckdb_get_uhugeint(duckdb_value val);

/*!
Returns the duckdb_bignum value of the given value.
The `data` field must be destroyed with `duckdb_free`.

* @param val A duckdb_value containing a BIGNUM
* @return A duckdb_bignum. The `data` field must be destroyed with `duckdb_free`.
*/
DUCKDB_C_API duckdb_bignum duckdb_get_bignum(duckdb_value val);

/*!
Returns the duckdb_decimal value of the given value.

* @param val A duckdb_value containing a DECIMAL
* @return A duckdb_decimal, or MinValue<decimal> if the value cannot be converted
*/
DUCKDB_C_API duckdb_decimal duckdb_get_decimal(duckdb_value val);

/*!
Returns the float value of the given value.

* @param val A duckdb_value containing a float
* @return A float, or NAN if the value cannot be converted
*/
DUCKDB_C_API float duckdb_get_float(duckdb_value val);

/*!
Returns the double value of the given value.

* @param val A duckdb_value containing a double
* @return A double, or NAN if the value cannot be converted
*/
DUCKDB_C_API double duckdb_get_double(duckdb_value val);

/*!
Returns the date value of the given value.

* @param val A duckdb_value containing a date
* @return A duckdb_date, or MinValue<date> if the value cannot be converted
*/
DUCKDB_C_API duckdb_date duckdb_get_date(duckdb_value val);

/*!
Returns the time value of the given value.

* @param val A duckdb_value containing a time
* @return A duckdb_time, or MinValue<time> if the value cannot be converted
*/
DUCKDB_C_API duckdb_time duckdb_get_time(duckdb_value val);

/*!
Returns the time_ns value of the given value.

* @param val A duckdb_value containing a time_ns
* @return A duckdb_time_ns, or MinValue<time_ns> if the value cannot be converted
*/
DUCKDB_C_API duckdb_time_ns duckdb_get_time_ns(duckdb_value val);

/*!
Returns the time_tz value of the given value.

* @param val A duckdb_value containing a time_tz
* @return A duckdb_time_tz, or MinValue<time_tz> if the value cannot be converted
*/
DUCKDB_C_API duckdb_time_tz duckdb_get_time_tz(duckdb_value val);

/*!
Returns the TIMESTAMP value of the given value.

* @param val A duckdb_value containing a TIMESTAMP
* @return A duckdb_timestamp, or MinValue<timestamp> if the value cannot be converted
*/
DUCKDB_C_API duckdb_timestamp duckdb_get_timestamp(duckdb_value val);

/*!
Returns the TIMESTAMP_TZ value of the given value.

* @param val A duckdb_value containing a TIMESTAMP_TZ
* @return A duckdb_timestamp, or MinValue<timestamp_tz> if the value cannot be converted
*/
DUCKDB_C_API duckdb_timestamp duckdb_get_timestamp_tz(duckdb_value val);

/*!
Returns the duckdb_timestamp_s value of the given value.

* @param val A duckdb_value containing a TIMESTAMP_S
* @return A duckdb_timestamp_s, or MinValue<timestamp_s> if the value cannot be converted
*/
DUCKDB_C_API duckdb_timestamp_s duckdb_get_timestamp_s(duckdb_value val);

/*!
Returns the duckdb_timestamp_ms value of the given value.

* @param val A duckdb_value containing a TIMESTAMP_MS
* @return A duckdb_timestamp_ms, or MinValue<timestamp_ms> if the value cannot be converted
*/
DUCKDB_C_API duckdb_timestamp_ms duckdb_get_timestamp_ms(duckdb_value val);

/*!
Returns the duckdb_timestamp_ns value of the given value.

* @param val A duckdb_value containing a TIMESTAMP_NS
* @return A duckdb_timestamp_ns, or MinValue<timestamp_ns> if the value cannot be converted
*/
DUCKDB_C_API duckdb_timestamp_ns duckdb_get_timestamp_ns(duckdb_value val);

/*!
Returns the interval value of the given value.

* @param val A duckdb_value containing a interval
* @return A duckdb_interval, or MinValue<interval> if the value cannot be converted
*/
DUCKDB_C_API duckdb_interval duckdb_get_interval(duckdb_value val);

/*!
Returns the type of the given value. The type is valid as long as the value is not destroyed.
The type itself must not be destroyed.

* @param val A duckdb_value
* @return A duckdb_logical_type.
*/
DUCKDB_C_API duckdb_logical_type duckdb_get_value_type(duckdb_value val);

/*!
Returns the blob value of the given value.

* @param val A duckdb_value containing a blob
* @return A duckdb_blob
*/
DUCKDB_C_API duckdb_blob duckdb_get_blob(duckdb_value val);

/*!
Returns the duckdb_bit value of the given value.
The `data` field must be destroyed with `duckdb_free`.

* @param val A duckdb_value containing a BIT
* @return A duckdb_bit
*/
DUCKDB_C_API duckdb_bit duckdb_get_bit(duckdb_value val);

/*!
Returns a duckdb_uhugeint representing the UUID value of the given value.

* @param val A duckdb_value containing a UUID
* @return A duckdb_uhugeint representing the UUID value
*/
DUCKDB_C_API duckdb_uhugeint duckdb_get_uuid(duckdb_value val);

/*!
Obtains a string representation of the given value.
The result must be destroyed with `duckdb_free`.

* @param value The value
* @return The string value. This must be destroyed with `duckdb_free`.
*/
DUCKDB_C_API char *duckdb_get_varchar(duckdb_value value);

/*!
Creates a struct value from a type and an array of values. Must be destroyed with `duckdb_destroy_value`.

* @param type The type of the struct
* @param values The values for the struct fields
* @return The struct value, or nullptr, if any child type is `DUCKDB_TYPE_ANY` or `DUCKDB_TYPE_INVALID`.
*/
DUCKDB_C_API duckdb_value duckdb_create_struct_value(duckdb_logical_type type, duckdb_value *values);

/*!
Creates a list value from a child (element) type and an array of values of length `value_count`.
Must be destroyed with `duckdb_destroy_value`.

* @param type The type of the list
* @param values The values for the list
* @param value_count The number of values in the list
* @return The list value, or nullptr, if the child type is `DUCKDB_TYPE_ANY` or `DUCKDB_TYPE_INVALID`.
*/
DUCKDB_C_API duckdb_value duckdb_create_list_value(duckdb_logical_type type, duckdb_value *values, idx_t value_count);

/*!
Creates an array value from a child (element) type and an array of values of length `value_count`.
Must be destroyed with `duckdb_destroy_value`.

* @param type The type of the array
* @param values The values for the array
* @param value_count The number of values in the array
* @return The array value, or nullptr, if the child type is `DUCKDB_TYPE_ANY` or `DUCKDB_TYPE_INVALID`.
*/
DUCKDB_C_API duckdb_value duckdb_create_array_value(duckdb_logical_type type, duckdb_value *values, idx_t value_count);

/*!
Creates a map value from a map type and two arrays, one for the keys and one for the values, each of length
`entry_count`. Must be destroyed with `duckdb_destroy_value`.

* @param map_type The map type
* @param keys The keys of the map
* @param values The values of the map
* @param entry_count The number of entrys (key-value pairs) in the map
* @return The map value, or nullptr, if the parameters are invalid.
*/
DUCKDB_C_API duckdb_value duckdb_create_map_value(duckdb_logical_type map_type, duckdb_value *keys,
                                                  duckdb_value *values, idx_t entry_count);

/*!
Creates a union value from a union type, a tag index, and a value.
Must be destroyed with `duckdb_destroy_value`.

* @param union_type The union type
* @param tag_index The index of the tag of the union
* @param value The value of the union for that tag
* @return The union value, or nullptr, if the parameters are invalid.
*/
DUCKDB_C_API duckdb_value duckdb_create_union_value(duckdb_logical_type union_type, idx_t tag_index,
                                                    duckdb_value value);

/*!
Returns the number of elements in a MAP value.

* @param value The MAP value.
* @return The number of elements in the map.
*/
DUCKDB_C_API idx_t duckdb_get_map_size(duckdb_value value);

/*!
Returns the MAP key at index as a duckdb_value.

* @param value The MAP value.
* @param index The index of the key.
* @return The key as a duckdb_value.
*/
DUCKDB_C_API duckdb_value duckdb_get_map_key(duckdb_value value, idx_t index);

/*!
Returns the MAP value at index as a duckdb_value.

* @param value The MAP value.
* @param index The index of the value.
* @return The value as a duckdb_value.
*/
DUCKDB_C_API duckdb_value duckdb_get_map_value(duckdb_value value, idx_t index);

/*!
Returns whether the value's type is SQLNULL or not.

* @param value The value to check.
* @return True, if the value's type is SQLNULL, otherwise false.
*/
DUCKDB_C_API bool duckdb_is_null_value(duckdb_value value);

/*!
Creates a value of type SQLNULL.

* @return The duckdb_value representing SQLNULL. This must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_create_null_value();

/*!
Returns the number of elements in a LIST value.

* @param value The LIST value.
* @return The number of elements in the list.
*/
DUCKDB_C_API idx_t duckdb_get_list_size(duckdb_value value);

/*!
Returns the LIST child at index as a duckdb_value.

* @param value The LIST value.
* @param index The index of the child.
* @return The child as a duckdb_value.
*/
DUCKDB_C_API duckdb_value duckdb_get_list_child(duckdb_value value, idx_t index);

/*!
Creates an enum value from a type and a value. Must be destroyed with `duckdb_destroy_value`.

* @param type The type of the enum
* @param value The value for the enum
* @return The enum value, or nullptr.
*/
DUCKDB_C_API duckdb_value duckdb_create_enum_value(duckdb_logical_type type, uint64_t value);

/*!
Returns the enum value of the given value.

* @param value A duckdb_value containing an enum
* @return A uint64_t, or MinValue<uint64> if the value cannot be converted
*/
DUCKDB_C_API uint64_t duckdb_get_enum_value(duckdb_value value);

/*!
Returns the STRUCT child at index as a duckdb_value.

* @param value The STRUCT value.
* @param index The index of the child.
* @return The child as a duckdb_value.
*/
DUCKDB_C_API duckdb_value duckdb_get_struct_child(duckdb_value value, idx_t index);

/*!
Returns the SQL string representation of the given value.

* @param value A duckdb_value.
* @return The SQL string representation as a null-terminated string. The result must be freed with `duckdb_free`.
*/
DUCKDB_C_API char *duckdb_value_to_string(duckdb_value value);

//===--------------------------------------------------------------------===//
// Logical Type Interface
//===--------------------------------------------------------------------===//

/*!
Creates a `duckdb_logical_type` from a primitive type.
The resulting logical type must be destroyed with `duckdb_destroy_logical_type`.

Returns an invalid logical type, if type is: `DUCKDB_TYPE_INVALID`, `DUCKDB_TYPE_DECIMAL`, `DUCKDB_TYPE_ENUM`,
`DUCKDB_TYPE_LIST`, `DUCKDB_TYPE_STRUCT`, `DUCKDB_TYPE_MAP`, `DUCKDB_TYPE_ARRAY`, or `DUCKDB_TYPE_UNION`.

* @param type The primitive type to create.
* @return The logical type.
*/
DUCKDB_C_API duckdb_logical_type duckdb_create_logical_type(duckdb_type type);

/*!
Returns the alias of a duckdb_logical_type, if set, else `nullptr`.
The result must be destroyed with `duckdb_free`.

* @param type The logical type
* @return The alias or `nullptr`
*/
DUCKDB_C_API char *duckdb_logical_type_get_alias(duckdb_logical_type type);

/*!
Sets the alias of a duckdb_logical_type.

* @param type The logical type
* @param alias The alias to set
*/
DUCKDB_C_API void duckdb_logical_type_set_alias(duckdb_logical_type type, const char *alias);

/*!
Creates a LIST type from its child type.
The return type must be destroyed with `duckdb_destroy_logical_type`.

* @param type The child type of the list
* @return The logical type.
*/
DUCKDB_C_API duckdb_logical_type duckdb_create_list_type(duckdb_logical_type type);

/*!
Creates an ARRAY type from its child type.
The return type must be destroyed with `duckdb_destroy_logical_type`.

* @param type The child type of the array.
* @param array_size The number of elements in the array.
* @return The logical type.
*/
DUCKDB_C_API duckdb_logical_type duckdb_create_array_type(duckdb_logical_type type, idx_t array_size);

/*!
Creates a MAP type from its key type and value type.
The return type must be destroyed with `duckdb_destroy_logical_type`.

* @param key_type The map's key type.
* @param value_type The map's value type.
* @return The logical type.
*/
DUCKDB_C_API duckdb_logical_type duckdb_create_map_type(duckdb_logical_type key_type, duckdb_logical_type value_type);

/*!
Creates a UNION type from the passed arrays.
The return type must be destroyed with `duckdb_destroy_logical_type`.

* @param member_types The array of union member types.
* @param member_names The union member names.
* @param member_count The number of union members.
* @return The logical type.
*/
DUCKDB_C_API duckdb_logical_type duckdb_create_union_type(duckdb_logical_type *member_types, const char **member_names,
                                                          idx_t member_count);

/*!
Creates a STRUCT type based on the member types and names.
The resulting type must be destroyed with `duckdb_destroy_logical_type`.

* @param member_types The array of types of the struct members.
* @param member_names The array of names of the struct members.
* @param member_count The number of members of the struct.
* @return The logical type.
*/
DUCKDB_C_API duckdb_logical_type duckdb_create_struct_type(duckdb_logical_type *member_types, const char **member_names,
                                                           idx_t member_count);

/*!
Creates an ENUM type from the passed member name array.
The resulting type should be destroyed with `duckdb_destroy_logical_type`.

* @param member_names The array of names that the enum should consist of.
* @param member_count The number of elements that were specified in the array.
* @return The logical type.
*/
DUCKDB_C_API duckdb_logical_type duckdb_create_enum_type(const char **member_names, idx_t member_count);

/*!
Creates a DECIMAL type with the specified width and scale.
The resulting type should be destroyed with `duckdb_destroy_logical_type`.

* @param width The width of the decimal type
* @param scale The scale of the decimal type
* @return The logical type.
*/
DUCKDB_C_API duckdb_logical_type duckdb_create_decimal_type(uint8_t width, uint8_t scale);

/*!
Retrieves the enum `duckdb_type` of a `duckdb_logical_type`.

* @param type The logical type.
* @return The `duckdb_type` id.
*/
DUCKDB_C_API duckdb_type duckdb_get_type_id(duckdb_logical_type type);

/*!
Retrieves the width of a decimal type.

* @param type The logical type object
* @return The width of the decimal type
*/
DUCKDB_C_API uint8_t duckdb_decimal_width(duckdb_logical_type type);

/*!
Retrieves the scale of a decimal type.

* @param type The logical type object
* @return The scale of the decimal type
*/
DUCKDB_C_API uint8_t duckdb_decimal_scale(duckdb_logical_type type);

/*!
Retrieves the internal storage type of a decimal type.

* @param type The logical type object
* @return The internal type of the decimal type
*/
DUCKDB_C_API duckdb_type duckdb_decimal_internal_type(duckdb_logical_type type);

/*!
Retrieves the internal storage type of an enum type.

* @param type The logical type object
* @return The internal type of the enum type
*/
DUCKDB_C_API duckdb_type duckdb_enum_internal_type(duckdb_logical_type type);

/*!
Retrieves the dictionary size of the enum type.

* @param type The logical type object
* @return The dictionary size of the enum type
*/
DUCKDB_C_API uint32_t duckdb_enum_dictionary_size(duckdb_logical_type type);

/*!
Retrieves the dictionary value at the specified position from the enum.

The result must be freed with `duckdb_free`.

* @param type The logical type object
* @param index The index in the dictionary
* @return The string value of the enum type. Must be freed with `duckdb_free`.
*/
DUCKDB_C_API char *duckdb_enum_dictionary_value(duckdb_logical_type type, idx_t index);

/*!
Retrieves the child type of the given LIST type. Also accepts MAP types.
The result must be freed with `duckdb_destroy_logical_type`.

* @param type The logical type, either LIST or MAP.
* @return The child type of the LIST or MAP type.
*/
DUCKDB_C_API duckdb_logical_type duckdb_list_type_child_type(duckdb_logical_type type);

/*!
Retrieves the child type of the given ARRAY type.

The result must be freed with `duckdb_destroy_logical_type`.

* @param type The logical type. Must be ARRAY.
* @return The child type of the ARRAY type.
*/
DUCKDB_C_API duckdb_logical_type duckdb_array_type_child_type(duckdb_logical_type type);

/*!
Retrieves the array size of the given array type.

* @param type The logical type object
* @return The fixed number of elements the values of this array type can store.
*/
DUCKDB_C_API idx_t duckdb_array_type_array_size(duckdb_logical_type type);

/*!
Retrieves the key type of the given map type.

The result must be freed with `duckdb_destroy_logical_type`.

* @param type The logical type object
* @return The key type of the map type. Must be destroyed with `duckdb_destroy_logical_type`.
*/
DUCKDB_C_API duckdb_logical_type duckdb_map_type_key_type(duckdb_logical_type type);

/*!
Retrieves the value type of the given map type.

The result must be freed with `duckdb_destroy_logical_type`.

* @param type The logical type object
* @return The value type of the map type. Must be destroyed with `duckdb_destroy_logical_type`.
*/
DUCKDB_C_API duckdb_logical_type duckdb_map_type_value_type(duckdb_logical_type type);

/*!
Returns the number of children of a struct type.

* @param type The logical type object
* @return The number of children of a struct type.
*/
DUCKDB_C_API idx_t duckdb_struct_type_child_count(duckdb_logical_type type);

/*!
Retrieves the name of the struct child.

The result must be freed with `duckdb_free`.

* @param type The logical type object
* @param index The child index
* @return The name of the struct type. Must be freed with `duckdb_free`.
*/
DUCKDB_C_API char *duckdb_struct_type_child_name(duckdb_logical_type type, idx_t index);

/*!
Retrieves the child type of the given struct type at the specified index.

The result must be freed with `duckdb_destroy_logical_type`.

* @param type The logical type object
* @param index The child index
* @return The child type of the struct type. Must be destroyed with `duckdb_destroy_logical_type`.
*/
DUCKDB_C_API duckdb_logical_type duckdb_struct_type_child_type(duckdb_logical_type type, idx_t index);

/*!
Returns the number of members that the union type has.

* @param type The logical type (union) object
* @return The number of members of a union type.
*/
DUCKDB_C_API idx_t duckdb_union_type_member_count(duckdb_logical_type type);

/*!
Retrieves the name of the union member.

The result must be freed with `duckdb_free`.

* @param type The logical type object
* @param index The child index
* @return The name of the union member. Must be freed with `duckdb_free`.
*/
DUCKDB_C_API char *duckdb_union_type_member_name(duckdb_logical_type type, idx_t index);

/*!
Retrieves the child type of the given union member at the specified index.

The result must be freed with `duckdb_destroy_logical_type`.

* @param type The logical type object
* @param index The child index
* @return The child type of the union member. Must be destroyed with `duckdb_destroy_logical_type`.
*/
DUCKDB_C_API duckdb_logical_type duckdb_union_type_member_type(duckdb_logical_type type, idx_t index);

/*!
Destroys the logical type and de-allocates all memory allocated for that type.

* @param type The logical type to destroy.
*/
DUCKDB_C_API void duckdb_destroy_logical_type(duckdb_logical_type *type);

/*!
Registers a custom type within the given connection.
The type must have an alias

* @param con The connection to use
* @param type The custom type to register
* @return Whether or not the registration was successful.
*/
DUCKDB_C_API duckdb_state duckdb_register_logical_type(duckdb_connection con, duckdb_logical_type type,
                                                       duckdb_create_type_info info);

//===--------------------------------------------------------------------===//
// Data Chunk Interface
//===--------------------------------------------------------------------===//

/*!
Creates an empty data chunk with the specified column types.
The result must be destroyed with `duckdb_destroy_data_chunk`.

* @param types An array of column types. Column types can not contain ANY and INVALID types.
* @param column_count The number of columns.
* @return The data chunk.
*/
DUCKDB_C_API duckdb_data_chunk duckdb_create_data_chunk(duckdb_logical_type *types, idx_t column_count);

/*!
Destroys the data chunk and de-allocates all memory allocated for that chunk.

* @param chunk The data chunk to destroy.
*/
DUCKDB_C_API void duckdb_destroy_data_chunk(duckdb_data_chunk *chunk);

/*!
Resets a data chunk, clearing the validity masks and setting the cardinality of the data chunk to 0.
After calling this method, you must call `duckdb_vector_get_validity` and `duckdb_vector_get_data` to obtain current
data and validity pointers

* @param chunk The data chunk to reset.
*/
DUCKDB_C_API void duckdb_data_chunk_reset(duckdb_data_chunk chunk);

/*!
Retrieves the number of columns in a data chunk.

* @param chunk The data chunk to get the data from
* @return The number of columns in the data chunk
*/
DUCKDB_C_API idx_t duckdb_data_chunk_get_column_count(duckdb_data_chunk chunk);

/*!
Retrieves the vector at the specified column index in the data chunk.

The pointer to the vector is valid for as long as the chunk is alive.
It does NOT need to be destroyed.

* @param chunk The data chunk to get the data from
* @return The vector
*/
DUCKDB_C_API duckdb_vector duckdb_data_chunk_get_vector(duckdb_data_chunk chunk, idx_t col_idx);

/*!
Retrieves the current number of tuples in a data chunk.

* @param chunk The data chunk to get the data from
* @return The number of tuples in the data chunk
*/
DUCKDB_C_API idx_t duckdb_data_chunk_get_size(duckdb_data_chunk chunk);

/*!
Sets the current number of tuples in a data chunk.

* @param chunk The data chunk to set the size in
* @param size The number of tuples in the data chunk
*/
DUCKDB_C_API void duckdb_data_chunk_set_size(duckdb_data_chunk chunk, idx_t size);

//===--------------------------------------------------------------------===//
// Vector Interface
//===--------------------------------------------------------------------===//

/*!
Creates a flat vector. Must be destroyed with `duckdb_destroy_vector`.

* @param type The logical type of the vector.
* @param capacity The capacity of the vector.
* @return The vector.
*/
DUCKDB_C_API duckdb_vector duckdb_create_vector(duckdb_logical_type type, idx_t capacity);

/*!
Destroys the vector and de-allocates its memory.

* @param vector A pointer to the vector.
*/
DUCKDB_C_API void duckdb_destroy_vector(duckdb_vector *vector);

/*!
Retrieves the column type of the specified vector.

The result must be destroyed with `duckdb_destroy_logical_type`.

* @param vector The vector get the data from
* @return The type of the vector
*/
DUCKDB_C_API duckdb_logical_type duckdb_vector_get_column_type(duckdb_vector vector);

/*!
Retrieves the data pointer of the vector.

The data pointer can be used to read or write values from the vector.
How to read or write values depends on the type of the vector.

* @param vector The vector to get the data from
* @return The data pointer
*/
DUCKDB_C_API void *duckdb_vector_get_data(duckdb_vector vector);

/*!
Retrieves the validity mask pointer of the specified vector.

If all values are valid, this function MIGHT return NULL!

The validity mask is a bitset that signifies null-ness within the data chunk.
It is a series of uint64_t values, where each uint64_t value contains validity for 64 tuples.
The bit is set to 1 if the value is valid (i.e. not NULL) or 0 if the value is invalid (i.e. NULL).

Validity of a specific value can be obtained like this:

idx_t entry_idx = row_idx / 64;
idx_t idx_in_entry = row_idx % 64;
bool is_valid = validity_mask[entry_idx] & (1 << idx_in_entry);

Alternatively, the (slower) duckdb_validity_row_is_valid function can be used.

* @param vector The vector to get the data from
* @return The pointer to the validity mask, or NULL if no validity mask is present
*/
DUCKDB_C_API uint64_t *duckdb_vector_get_validity(duckdb_vector vector);

/*!
Ensures the validity mask is writable by allocating it.

After this function is called, `duckdb_vector_get_validity` will ALWAYS return non-NULL.
This allows NULL values to be written to the vector, regardless of whether a validity mask was present before.

* @param vector The vector to alter
*/
DUCKDB_C_API void duckdb_vector_ensure_validity_writable(duckdb_vector vector);

/*!
Assigns a string element in the vector at the specified location.

* @param vector The vector to alter
* @param index The row position in the vector to assign the string to
* @param str The null-terminated string
*/
DUCKDB_C_API void duckdb_vector_assign_string_element(duckdb_vector vector, idx_t index, const char *str);

/*!
Assigns a string element in the vector at the specified location. You may also use this function to assign BLOBs.

* @param vector The vector to alter
* @param index The row position in the vector to assign the string to
* @param str The string
* @param str_len The length of the string (in bytes)
*/
DUCKDB_C_API void duckdb_vector_assign_string_element_len(duckdb_vector vector, idx_t index, const char *str,
                                                          idx_t str_len);

/*!
Retrieves the child vector of a list vector.

The resulting vector is valid as long as the parent vector is valid.

* @param vector The vector
* @return The child vector
*/
DUCKDB_C_API duckdb_vector duckdb_list_vector_get_child(duckdb_vector vector);

/*!
Returns the size of the child vector of the list.

* @param vector The vector
* @return The size of the child list
*/
DUCKDB_C_API idx_t duckdb_list_vector_get_size(duckdb_vector vector);

/*!
Sets the total size of the underlying child-vector of a list vector.

* @param vector The list vector.
* @param size The size of the child list.
* @return The duckdb state. Returns DuckDBError if the vector is nullptr.
*/
DUCKDB_C_API duckdb_state duckdb_list_vector_set_size(duckdb_vector vector, idx_t size);

/*!
Sets the total capacity of the underlying child-vector of a list.

After calling this method, you must call `duckdb_vector_get_validity` and `duckdb_vector_get_data` to obtain current
data and validity pointers

* @param vector The list vector.
* @param required_capacity the total capacity to reserve.
* @return The duckdb state. Returns DuckDBError if the vector is nullptr.
*/
DUCKDB_C_API duckdb_state duckdb_list_vector_reserve(duckdb_vector vector, idx_t required_capacity);

/*!
Retrieves the child vector of a struct vector.
The resulting vector is valid as long as the parent vector is valid.

* @param vector The vector
* @param index The child index
* @return The child vector
*/
DUCKDB_C_API duckdb_vector duckdb_struct_vector_get_child(duckdb_vector vector, idx_t index);

/*!
Retrieves the child vector of an array vector.
The resulting vector is valid as long as the parent vector is valid.
The resulting vector has the size of the parent vector multiplied by the array size.

* @param vector The vector
* @return The child vector
*/
DUCKDB_C_API duckdb_vector duckdb_array_vector_get_child(duckdb_vector vector);

/*!
Slice a vector with a selection vector.
The length of the selection vector must be less than or equal to the length of the vector.
Turns the vector into a dictionary vector.

* @param vector The vector to slice.
* @param sel The selection vector.
* @param len The length of the selection vector.
*/
DUCKDB_C_API void duckdb_slice_vector(duckdb_vector vector, duckdb_selection_vector sel, idx_t len);

/*!
Copy the src vector to the dst with a selection vector that identifies which indices to copy.

* @param src The vector to copy from.
* @param dst The vector to copy to.
* @param sel The selection vector. The length of the selection vector should not be more than the length of the src
vector
* @param src_count The number of entries from selection vector to copy. Think of this as the effective length of the
selection vector starting from index 0
* @param src_offset The offset in the selection vector to copy from (important: actual number of items copied =
src_count - src_offset).
* @param dst_offset The offset in the dst vector to start copying to.
*/
DUCKDB_C_API void duckdb_vector_copy_sel(duckdb_vector src, duckdb_vector dst, duckdb_selection_vector sel,
                                         idx_t src_count, idx_t src_offset, idx_t dst_offset);

/*!
Copies the value from `value` to `vector`.

* @param vector The receiving vector.
* @param value The value to copy into the vector.
*/
DUCKDB_C_API void duckdb_vector_reference_value(duckdb_vector vector, duckdb_value value);

/*!
Changes `to_vector` to reference `from_vector. After, the vectors share ownership of the data.

* @param to_vector The receiving vector.
* @param from_vector The vector to reference.
*/
DUCKDB_C_API void duckdb_vector_reference_vector(duckdb_vector to_vector, duckdb_vector from_vector);

//===--------------------------------------------------------------------===//
// Validity Mask Functions
//===--------------------------------------------------------------------===//

/*!
Returns whether or not a row is valid (i.e. not NULL) in the given validity mask.

* @param validity The validity mask, as obtained through `duckdb_vector_get_validity`
* @param row The row index
* @return true if the row is valid, false otherwise
*/
DUCKDB_C_API bool duckdb_validity_row_is_valid(uint64_t *validity, idx_t row);

/*!
In a validity mask, sets a specific row to either valid or invalid.

Note that `duckdb_vector_ensure_validity_writable` should be called before calling `duckdb_vector_get_validity`,
to ensure that there is a validity mask to write to.

* @param validity The validity mask, as obtained through `duckdb_vector_get_validity`.
* @param row The row index
* @param valid Whether or not to set the row to valid, or invalid
*/
DUCKDB_C_API void duckdb_validity_set_row_validity(uint64_t *validity, idx_t row, bool valid);

/*!
In a validity mask, sets a specific row to invalid.

Equivalent to `duckdb_validity_set_row_validity` with valid set to false.

* @param validity The validity mask
* @param row The row index
*/
DUCKDB_C_API void duckdb_validity_set_row_invalid(uint64_t *validity, idx_t row);

/*!
In a validity mask, sets a specific row to valid.

Equivalent to `duckdb_validity_set_row_validity` with valid set to true.

* @param validity The validity mask
* @param row The row index
*/
DUCKDB_C_API void duckdb_validity_set_row_valid(uint64_t *validity, idx_t row);

//===--------------------------------------------------------------------===//
// Scalar Functions
//===--------------------------------------------------------------------===//

/*!
Creates a new empty scalar function.

The return value must be destroyed with `duckdb_destroy_scalar_function`.

* @return The scalar function object.
*/
DUCKDB_C_API duckdb_scalar_function duckdb_create_scalar_function();

/*!
Destroys the given scalar function object.

* @param scalar_function The scalar function to destroy
*/
DUCKDB_C_API void duckdb_destroy_scalar_function(duckdb_scalar_function *scalar_function);

/*!
Sets the name of the given scalar function.

* @param scalar_function The scalar function
* @param name The name of the scalar function
*/
DUCKDB_C_API void duckdb_scalar_function_set_name(duckdb_scalar_function scalar_function, const char *name);

/*!
Sets the parameters of the given scalar function to varargs. Does not require adding parameters with
duckdb_scalar_function_add_parameter.

* @param scalar_function The scalar function.
* @param type The type of the arguments.
* @return The parameter type. Cannot contain INVALID.
*/
DUCKDB_C_API void duckdb_scalar_function_set_varargs(duckdb_scalar_function scalar_function, duckdb_logical_type type);

/*!
Sets the scalar function's null-handling behavior to special.

* @param scalar_function The scalar function.
*/
DUCKDB_C_API void duckdb_scalar_function_set_special_handling(duckdb_scalar_function scalar_function);

/*!
Sets the Function Stability of the scalar function to VOLATILE, indicating the function should be re-run for every row.
This limits optimization that can be performed for the function.

* @param scalar_function The scalar function.
*/
DUCKDB_C_API void duckdb_scalar_function_set_volatile(duckdb_scalar_function scalar_function);

/*!
Adds a parameter to the scalar function.

* @param scalar_function The scalar function.
* @param type The parameter type. Cannot contain INVALID.
*/
DUCKDB_C_API void duckdb_scalar_function_add_parameter(duckdb_scalar_function scalar_function,
                                                       duckdb_logical_type type);

/*!
Sets the return type of the scalar function.

* @param scalar_function The scalar function
* @param type Cannot contain INVALID or ANY.
*/
DUCKDB_C_API void duckdb_scalar_function_set_return_type(duckdb_scalar_function scalar_function,
                                                         duckdb_logical_type type);

/*!
Assigns extra information to the scalar function that can be fetched during binding, etc.

* @param scalar_function The scalar function
* @param extra_info The extra information
* @param destroy The callback that will be called to destroy the extra information (if any)
*/
DUCKDB_C_API void duckdb_scalar_function_set_extra_info(duckdb_scalar_function scalar_function, void *extra_info,
                                                        duckdb_delete_callback_t destroy);

/*!
Sets the (optional) bind function of the scalar function.

* @param scalar_function The scalar function.
* @param bind The bind function.
*/
DUCKDB_C_API void duckdb_scalar_function_set_bind(duckdb_scalar_function scalar_function,
                                                  duckdb_scalar_function_bind_t bind);

/*!
Sets the user-provided bind data in the bind object of the scalar function.
The bind data object can be retrieved again during execution.
In most case, you also need to set the copy-callback of your bind data via duckdb_scalar_function_set_bind_data_copy.

* @param info The bind info of the scalar function.
* @param bind_data The bind data object.
* @param destroy The callback to destroy the bind data (if any).
*/
DUCKDB_C_API void duckdb_scalar_function_set_bind_data(duckdb_bind_info info, void *bind_data,
                                                       duckdb_delete_callback_t destroy);

/*!
Sets the copy-callback for the user-provided bind data in the bind object of the scalar function.

* @param info The bind info of the scalar function.
* @param copy The callback to copy the bind data (if any).
*/
DUCKDB_C_API void duckdb_scalar_function_set_bind_data_copy(duckdb_bind_info info, duckdb_copy_callback_t copy);

/*!
Report that an error has occurred while calling bind on a scalar function.

* @param info The bind info object.
* @param error The error message.
*/
DUCKDB_C_API void duckdb_scalar_function_bind_set_error(duckdb_bind_info info, const char *error);

/*!
Sets the main function of the scalar function.

* @param scalar_function The scalar function
* @param function The function
*/
DUCKDB_C_API void duckdb_scalar_function_set_function(duckdb_scalar_function scalar_function,
                                                      duckdb_scalar_function_t function);

/*!
Register the scalar function object within the given connection.

The function requires at least a name, a function and a return type.

If the function is incomplete or a function with this name already exists DuckDBError is returned.

* @param con The connection to register it in.
* @param scalar_function The function pointer
* @return Whether or not the registration was successful.
*/
DUCKDB_C_API duckdb_state duckdb_register_scalar_function(duckdb_connection con,
                                                          duckdb_scalar_function scalar_function);

/*!
Retrieves the extra info of the function as set in `duckdb_scalar_function_set_extra_info`.

* @param info The info object.
* @return The extra info.
*/
DUCKDB_C_API void *duckdb_scalar_function_get_extra_info(duckdb_function_info info);

/*!
Retrieves the extra info of the function as set in the bind info.

* @param info The info object.
* @return The extra info.
*/
DUCKDB_C_API void *duckdb_scalar_function_bind_get_extra_info(duckdb_bind_info info);

/*!
Gets the scalar function's bind data set by `duckdb_scalar_function_set_bind_data`.
Note that the bind data is read-only.

* @param info The function info.
* @return The bind data object.
*/
DUCKDB_C_API void *duckdb_scalar_function_get_bind_data(duckdb_function_info info);

/*!
Retrieves the client context of the bind info of a scalar function.

* @param info The bind info object of the scalar function.
* @param out_context The client context of the bind info. Must be destroyed with `duckdb_destroy_client_context`.
*/
DUCKDB_C_API void duckdb_scalar_function_get_client_context(duckdb_bind_info info, duckdb_client_context *out_context);

/*!
Report that an error has occurred while executing the scalar function.

* @param info The info object.
* @param error The error message
*/
DUCKDB_C_API void duckdb_scalar_function_set_error(duckdb_function_info info, const char *error);

/*!
Creates a new empty scalar function set.

The return value must be destroyed with `duckdb_destroy_scalar_function_set`.

* @return The scalar function set object.
*/
DUCKDB_C_API duckdb_scalar_function_set duckdb_create_scalar_function_set(const char *name);

/*!
Destroys the given scalar function set object.

*/
DUCKDB_C_API void duckdb_destroy_scalar_function_set(duckdb_scalar_function_set *scalar_function_set);

/*!
Adds the scalar function as a new overload to the scalar function set.

Returns DuckDBError if the function could not be added, for example if the overload already exists.

* @param set The scalar function set
* @param function The function to add
*/
DUCKDB_C_API duckdb_state duckdb_add_scalar_function_to_set(duckdb_scalar_function_set set,
                                                            duckdb_scalar_function function);

/*!
Register the scalar function set within the given connection.

The set requires at least a single valid overload.

If the set is incomplete or a function with this name already exists DuckDBError is returned.

* @param con The connection to register it in.
* @param set The function set to register
* @return Whether or not the registration was successful.
*/
DUCKDB_C_API duckdb_state duckdb_register_scalar_function_set(duckdb_connection con, duckdb_scalar_function_set set);

/*!
Returns the number of input arguments of the scalar function.

* @param info The bind info.
* @return The number of input arguments.
*/
DUCKDB_C_API idx_t duckdb_scalar_function_bind_get_argument_count(duckdb_bind_info info);

/*!
Returns the input argument at index of the scalar function.

* @param info The bind info.
* @param index The argument index.
* @return The input argument at index. Must be destroyed with `duckdb_destroy_expression`.
*/
DUCKDB_C_API duckdb_expression duckdb_scalar_function_bind_get_argument(duckdb_bind_info info, idx_t index);

//===--------------------------------------------------------------------===//
// Selection Vector Interface
//===--------------------------------------------------------------------===//

/*!
Creates a new selection vector of size `size`.
Must be destroyed with `duckdb_destroy_selection_vector`.

* @param size The size of the selection vector.
* @return The selection vector.
*/
DUCKDB_C_API duckdb_selection_vector duckdb_create_selection_vector(idx_t size);

/*!
Destroys the selection vector and de-allocates its memory.

* @param sel The selection vector.
*/
DUCKDB_C_API void duckdb_destroy_selection_vector(duckdb_selection_vector sel);

/*!
Access the data pointer of a selection vector.

* @param sel The selection vector.
* @return The data pointer.
*/
DUCKDB_C_API sel_t *duckdb_selection_vector_get_data_ptr(duckdb_selection_vector sel);

//===--------------------------------------------------------------------===//
// Aggregate Functions
//===--------------------------------------------------------------------===//

/*!
Creates a new empty aggregate function.

The return value should be destroyed with `duckdb_destroy_aggregate_function`.

* @return The aggregate function object.
*/
DUCKDB_C_API duckdb_aggregate_function duckdb_create_aggregate_function();

/*!
Destroys the given aggregate function object.

*/
DUCKDB_C_API void duckdb_destroy_aggregate_function(duckdb_aggregate_function *aggregate_function);

/*!
Sets the name of the given aggregate function.

* @param aggregate_function The aggregate function
* @param name The name of the aggregate function
*/
DUCKDB_C_API void duckdb_aggregate_function_set_name(duckdb_aggregate_function aggregate_function, const char *name);

/*!
Adds a parameter to the aggregate function.

* @param aggregate_function The aggregate function.
* @param type The parameter type. Cannot contain INVALID.
*/
DUCKDB_C_API void duckdb_aggregate_function_add_parameter(duckdb_aggregate_function aggregate_function,
                                                          duckdb_logical_type type);

/*!
Sets the return type of the aggregate function.

* @param aggregate_function The aggregate function.
* @param type The return type. Cannot contain INVALID or ANY.
*/
DUCKDB_C_API void duckdb_aggregate_function_set_return_type(duckdb_aggregate_function aggregate_function,
                                                            duckdb_logical_type type);

/*!
Sets the main functions of the aggregate function.

* @param aggregate_function The aggregate function
* @param state_size state size
* @param state_init state init function
* @param update update states
* @param combine combine states
* @param finalize finalize states
*/
DUCKDB_C_API void duckdb_aggregate_function_set_functions(duckdb_aggregate_function aggregate_function,
                                                          duckdb_aggregate_state_size state_size,
                                                          duckdb_aggregate_init_t state_init,
                                                          duckdb_aggregate_update_t update,
                                                          duckdb_aggregate_combine_t combine,
                                                          duckdb_aggregate_finalize_t finalize);

/*!
Sets the state destructor callback of the aggregate function (optional)

* @param aggregate_function The aggregate function
* @param destroy state destroy callback
*/
DUCKDB_C_API void duckdb_aggregate_function_set_destructor(duckdb_aggregate_function aggregate_function,
                                                           duckdb_aggregate_destroy_t destroy);

/*!
Register the aggregate function object within the given connection.

The function requires at least a name, functions and a return type.

If the function is incomplete or a function with this name already exists DuckDBError is returned.

* @param con The connection to register it in.
* @return Whether or not the registration was successful.
*/
DUCKDB_C_API duckdb_state duckdb_register_aggregate_function(duckdb_connection con,
                                                             duckdb_aggregate_function aggregate_function);

/*!
Sets the NULL handling of the aggregate function to SPECIAL_HANDLING.

* @param aggregate_function The aggregate function
*/
DUCKDB_C_API void duckdb_aggregate_function_set_special_handling(duckdb_aggregate_function aggregate_function);

/*!
Assigns extra information to the scalar function that can be fetched during binding, etc.

* @param aggregate_function The aggregate function
* @param extra_info The extra information
* @param destroy The callback that will be called to destroy the extra information (if any)
*/
DUCKDB_C_API void duckdb_aggregate_function_set_extra_info(duckdb_aggregate_function aggregate_function,
                                                           void *extra_info, duckdb_delete_callback_t destroy);

/*!
Retrieves the extra info of the function as set in `duckdb_aggregate_function_set_extra_info`.

* @param info The info object
* @return The extra info
*/
DUCKDB_C_API void *duckdb_aggregate_function_get_extra_info(duckdb_function_info info);

/*!
Report that an error has occurred while executing the aggregate function.

* @param info The info object
* @param error The error message
*/
DUCKDB_C_API void duckdb_aggregate_function_set_error(duckdb_function_info info, const char *error);

/*!
Creates a new empty aggregate function set.

The return value should be destroyed with `duckdb_destroy_aggregate_function_set`.

* @return The aggregate function set object.
*/
DUCKDB_C_API duckdb_aggregate_function_set duckdb_create_aggregate_function_set(const char *name);

/*!
Destroys the given aggregate function set object.

*/
DUCKDB_C_API void duckdb_destroy_aggregate_function_set(duckdb_aggregate_function_set *aggregate_function_set);

/*!
Adds the aggregate function as a new overload to the aggregate function set.

Returns DuckDBError if the function could not be added, for example if the overload already exists.

* @param set The aggregate function set
* @param function The function to add
*/
DUCKDB_C_API duckdb_state duckdb_add_aggregate_function_to_set(duckdb_aggregate_function_set set,
                                                               duckdb_aggregate_function function);

/*!
Register the aggregate function set within the given connection.

The set requires at least a single valid overload.

If the set is incomplete or a function with this name already exists DuckDBError is returned.

* @param con The connection to register it in.
* @param set The function set to register
* @return Whether or not the registration was successful.
*/
DUCKDB_C_API duckdb_state duckdb_register_aggregate_function_set(duckdb_connection con,
                                                                 duckdb_aggregate_function_set set);

//===--------------------------------------------------------------------===//
// Table Functions
//===--------------------------------------------------------------------===//

/*!
Creates a new empty table function.

The return value should be destroyed with `duckdb_destroy_table_function`.

* @return The table function object.
*/
DUCKDB_C_API duckdb_table_function duckdb_create_table_function();

/*!
Destroys the given table function object.

* @param table_function The table function to destroy
*/
DUCKDB_C_API void duckdb_destroy_table_function(duckdb_table_function *table_function);

/*!
Sets the name of the given table function.

* @param table_function The table function
* @param name The name of the table function
*/
DUCKDB_C_API void duckdb_table_function_set_name(duckdb_table_function table_function, const char *name);

/*!
Adds a parameter to the table function.

* @param table_function The table function.
* @param type The parameter type. Cannot contain INVALID.
*/
DUCKDB_C_API void duckdb_table_function_add_parameter(duckdb_table_function table_function, duckdb_logical_type type);

/*!
Adds a named parameter to the table function.

* @param table_function The table function.
* @param name The parameter name.
* @param type The parameter type. Cannot contain INVALID.
*/
DUCKDB_C_API void duckdb_table_function_add_named_parameter(duckdb_table_function table_function, const char *name,
                                                            duckdb_logical_type type);

/*!
Assigns extra information to the table function that can be fetched during binding, etc.

* @param table_function The table function
* @param extra_info The extra information
* @param destroy The callback that will be called to destroy the extra information (if any)
*/
DUCKDB_C_API void duckdb_table_function_set_extra_info(duckdb_table_function table_function, void *extra_info,
                                                       duckdb_delete_callback_t destroy);

/*!
Sets the bind function of the table function.

* @param table_function The table function
* @param bind The bind function
*/
DUCKDB_C_API void duckdb_table_function_set_bind(duckdb_table_function table_function,
                                                 duckdb_table_function_bind_t bind);

/*!
Sets the init function of the table function.

* @param table_function The table function
* @param init The init function
*/
DUCKDB_C_API void duckdb_table_function_set_init(duckdb_table_function table_function,
                                                 duckdb_table_function_init_t init);

/*!
Sets the thread-local init function of the table function.

* @param table_function The table function
* @param init The init function
*/
DUCKDB_C_API void duckdb_table_function_set_local_init(duckdb_table_function table_function,
                                                       duckdb_table_function_init_t init);

/*!
Sets the main function of the table function.

* @param table_function The table function
* @param function The function
*/
DUCKDB_C_API void duckdb_table_function_set_function(duckdb_table_function table_function,
                                                     duckdb_table_function_t function);

/*!
Sets whether or not the given table function supports projection pushdown.

If this is set to true, the system will provide a list of all required columns in the `init` stage through
the `duckdb_init_get_column_count` and `duckdb_init_get_column_index` functions.
If this is set to false (the default), the system will expect all columns to be projected.

* @param table_function The table function
* @param pushdown True if the table function supports projection pushdown, false otherwise.
*/
DUCKDB_C_API void duckdb_table_function_supports_projection_pushdown(duckdb_table_function table_function,
                                                                     bool pushdown);

/*!
Register the table function object within the given connection.

The function requires at least a name, a bind function, an init function and a main function.

If the function is incomplete or a function with this name already exists DuckDBError is returned.

* @param con The connection to register it in.
* @param function The function pointer
* @return Whether or not the registration was successful.
*/
DUCKDB_C_API duckdb_state duckdb_register_table_function(duckdb_connection con, duckdb_table_function function);

//===--------------------------------------------------------------------===//
// Table Function Bind
//===--------------------------------------------------------------------===//

/*!
Retrieves the extra info of the function as set in `duckdb_table_function_set_extra_info`.

* @param info The info object
* @return The extra info
*/
DUCKDB_C_API void *duckdb_bind_get_extra_info(duckdb_bind_info info);

/*!
Retrieves the client context of the bind info of a table function.

* @param info The bind info object of the table function.
* @param out_context The client context of the bind info. Must be destroyed with `duckdb_destroy_client_context`.
*/
DUCKDB_C_API void duckdb_table_function_get_client_context(duckdb_bind_info info, duckdb_client_context *out_context);

/*!
Adds a result column to the output of the table function.

* @param info The table function's bind info.
* @param name The column name.
* @param type The logical column type.
*/
DUCKDB_C_API void duckdb_bind_add_result_column(duckdb_bind_info info, const char *name, duckdb_logical_type type);

/*!
Retrieves the number of regular (non-named) parameters to the function.

* @param info The info object
* @return The number of parameters
*/
DUCKDB_C_API idx_t duckdb_bind_get_parameter_count(duckdb_bind_info info);

/*!
Retrieves the parameter at the given index.

The result must be destroyed with `duckdb_destroy_value`.

* @param info The info object
* @param index The index of the parameter to get
* @return The value of the parameter. Must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_bind_get_parameter(duckdb_bind_info info, idx_t index);

/*!
Retrieves a named parameter with the given name.

The result must be destroyed with `duckdb_destroy_value`.

* @param info The info object
* @param name The name of the parameter
* @return The value of the parameter. Must be destroyed with `duckdb_destroy_value`.
*/
DUCKDB_C_API duckdb_value duckdb_bind_get_named_parameter(duckdb_bind_info info, const char *name);

/*!
Sets the user-provided bind data in the bind object of the table function.
This object can be retrieved again during execution.

* @param info The bind info of the table function.
* @param bind_data The bind data object.
* @param destroy The callback to destroy the bind data (if any).
*/
DUCKDB_C_API void duckdb_bind_set_bind_data(duckdb_bind_info info, void *bind_data, duckdb_delete_callback_t destroy);

/*!
Sets the cardinality estimate for the table function, used for optimization.

* @param info The bind data object.
* @param is_exact Whether or not the cardinality estimate is exact, or an approximation
*/
DUCKDB_C_API void duckdb_bind_set_cardinality(duckdb_bind_info info, idx_t cardinality, bool is_exact);

/*!
Report that an error has occurred while calling bind on a table function.

* @param info The info object
* @param error The error message
*/
DUCKDB_C_API void duckdb_bind_set_error(duckdb_bind_info info, const char *error);

//===--------------------------------------------------------------------===//
// Table Function Init
//===--------------------------------------------------------------------===//

/*!
Retrieves the extra info of the function as set in `duckdb_table_function_set_extra_info`.

* @param info The info object
* @return The extra info
*/
DUCKDB_C_API void *duckdb_init_get_extra_info(duckdb_init_info info);

/*!
Gets the bind data set by `duckdb_bind_set_bind_data` during the bind.

Note that the bind data should be considered as read-only.
For tracking state, use the init data instead.

* @param info The info object
* @return The bind data object
*/
DUCKDB_C_API void *duckdb_init_get_bind_data(duckdb_init_info info);

/*!
Sets the user-provided init data in the init object. This object can be retrieved again during execution.

* @param info The info object
* @param init_data The init data object.
* @param destroy The callback that will be called to destroy the init data (if any)
*/
DUCKDB_C_API void duckdb_init_set_init_data(duckdb_init_info info, void *init_data, duckdb_delete_callback_t destroy);

/*!
Returns the number of projected columns.

This function must be used if projection pushdown is enabled to figure out which columns to emit.

* @param info The info object
* @return The number of projected columns.
*/
DUCKDB_C_API idx_t duckdb_init_get_column_count(duckdb_init_info info);

/*!
Returns the column index of the projected column at the specified position.

This function must be used if projection pushdown is enabled to figure out which columns to emit.

* @param info The info object
* @param column_index The index at which to get the projected column index, from 0..duckdb_init_get_column_count(info)
* @return The column index of the projected column.
*/
DUCKDB_C_API idx_t duckdb_init_get_column_index(duckdb_init_info info, idx_t column_index);

/*!
Sets how many threads can process this table function in parallel (default: 1)

* @param info The info object
* @param max_threads The maximum amount of threads that can process this table function
*/
DUCKDB_C_API void duckdb_init_set_max_threads(duckdb_init_info info, idx_t max_threads);

/*!
Report that an error has occurred while calling init.

* @param info The info object
* @param error The error message
*/
DUCKDB_C_API void duckdb_init_set_error(duckdb_init_info info, const char *error);

//===--------------------------------------------------------------------===//
// Table Function
//===--------------------------------------------------------------------===//

/*!
Retrieves the extra info of the function as set in `duckdb_table_function_set_extra_info`.

* @param info The info object
* @return The extra info
*/
DUCKDB_C_API void *duckdb_function_get_extra_info(duckdb_function_info info);

/*!
Gets the table function's bind data set by `duckdb_bind_set_bind_data`.

Note that the bind data is read-only.
For tracking state, use the init data instead.

* @param info The function info object.
* @return The bind data object.
*/
DUCKDB_C_API void *duckdb_function_get_bind_data(duckdb_function_info info);

/*!
Gets the init data set by `duckdb_init_set_init_data` during the init.

* @param info The info object
* @return The init data object
*/
DUCKDB_C_API void *duckdb_function_get_init_data(duckdb_function_info info);

/*!
Gets the thread-local init data set by `duckdb_init_set_init_data` during the local_init.

* @param info The info object
* @return The init data object
*/
DUCKDB_C_API void *duckdb_function_get_local_init_data(duckdb_function_info info);

/*!
Report that an error has occurred while executing the function.

* @param info The info object
* @param error The error message
*/
DUCKDB_C_API void duckdb_function_set_error(duckdb_function_info info, const char *error);

//===--------------------------------------------------------------------===//
// Replacement Scans
//===--------------------------------------------------------------------===//

/*!
Add a replacement scan definition to the specified database.

* @param db The database object to add the replacement scan to
* @param replacement The replacement scan callback
* @param extra_data Extra data that is passed back into the specified callback
* @param delete_callback The delete callback to call on the extra data, if any
*/
DUCKDB_C_API void duckdb_add_replacement_scan(duckdb_database db, duckdb_replacement_callback_t replacement,
                                              void *extra_data, duckdb_delete_callback_t delete_callback);

/*!
Sets the replacement function name. If this function is called in the replacement callback,
the replacement scan is performed. If it is not called, the replacement callback is not performed.

* @param info The info object
* @param function_name The function name to substitute.
*/
DUCKDB_C_API void duckdb_replacement_scan_set_function_name(duckdb_replacement_scan_info info,
                                                            const char *function_name);

/*!
Adds a parameter to the replacement scan function.

* @param info The info object
* @param parameter The parameter to add.
*/
DUCKDB_C_API void duckdb_replacement_scan_add_parameter(duckdb_replacement_scan_info info, duckdb_value parameter);

/*!
Report that an error has occurred while executing the replacement scan.

* @param info The info object
* @param error The error message
*/
DUCKDB_C_API void duckdb_replacement_scan_set_error(duckdb_replacement_scan_info info, const char *error);

//===--------------------------------------------------------------------===//
// Profiling Info
//===--------------------------------------------------------------------===//

/*!
Returns the root node of the profiling information. Returns nullptr, if profiling is not enabled.

* @param connection A connection object.
* @return A profiling information object.
*/
DUCKDB_C_API duckdb_profiling_info duckdb_get_profiling_info(duckdb_connection connection);

/*!
Returns the value of the metric of the current profiling info node. Returns nullptr, if the metric does
 not exist or is not enabled. Currently, the value holds a string, and you can retrieve the string
 by calling the corresponding function: char *duckdb_get_varchar(duckdb_value value).

* @param info A profiling information object.
* @param key The name of the requested metric.
* @return The value of the metric. Must be freed with `duckdb_destroy_value`
*/
DUCKDB_C_API duckdb_value duckdb_profiling_info_get_value(duckdb_profiling_info info, const char *key);

/*!
Returns the key-value metric map of this profiling node as a MAP duckdb_value.
The individual elements are accessible via the duckdb_value MAP functions.

* @param info A profiling information object.
* @return The key-value metric map as a MAP duckdb_value.
*/
DUCKDB_C_API duckdb_value duckdb_profiling_info_get_metrics(duckdb_profiling_info info);

/*!
Returns the number of children in the current profiling info node.

* @param info A profiling information object.
* @return The number of children in the current node.
*/
DUCKDB_C_API idx_t duckdb_profiling_info_get_child_count(duckdb_profiling_info info);

/*!
Returns the child node at the specified index.

* @param info A profiling information object.
* @param index The index of the child node.
* @return The child node at the specified index.
*/
DUCKDB_C_API duckdb_profiling_info duckdb_profiling_info_get_child(duckdb_profiling_info info, idx_t index);

//===--------------------------------------------------------------------===//
// Appender
//===--------------------------------------------------------------------===//

// Appenders are the most efficient way of loading data into DuckDB from within the C API.
// They are recommended for fast data loading as they perform better than prepared statements or individual `INSERT
// INTO` statements.

// Appends are possible in row-wise format, and by appending entire data chunks.

// Row-wise: for every column, a `duckdb_append_[type]` call should be made. After finishing all appends to a row, call
// `duckdb_appender_end_row`.

// Chunk-wise: Consecutively call `duckdb_append_data_chunk` until all chunks have been appended.

// After all data has been appended, call `duckdb_appender_close` to finalize the appender followed by
// `duckdb_appender_destroy` to clean up the memory.

/*!
Creates an appender object.

Note that the object must be destroyed with `duckdb_appender_destroy`.

* @param connection The connection context to create the appender in.
* @param schema The schema of the table to append to, or `nullptr` for the default schema.
* @param table The table name to append to.
* @param out_appender The resulting appender object.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_appender_create(duckdb_connection connection, const char *schema, const char *table,
                                                 duckdb_appender *out_appender);

/*!
Creates an appender object.

Note that the object must be destroyed with `duckdb_appender_destroy`.

* @param connection The connection context to create the appender in.
* @param catalog The catalog of the table to append to, or `nullptr` for the default catalog.
* @param schema The schema of the table to append to, or `nullptr` for the default schema.
* @param table The table name to append to.
* @param out_appender The resulting appender object.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_appender_create_ext(duckdb_connection connection, const char *catalog,
                                                     const char *schema, const char *table,
                                                     duckdb_appender *out_appender);

/*!
Creates an appender object that executes the given query with any data appended to it.

Note that the object must be destroyed with `duckdb_appender_destroy`.

* @param connection The connection context to create the appender in.
* @param query The query to execute, can be an INSERT, DELETE, UPDATE or MERGE INTO statement.
* @param column_count The number of columns to append.
* @param types The types of the columns to append.
* @param table_name (optionally) the table name used to refer to the appended data, defaults to "appended_data".
* @param column_names (optionally) the list of column names, defaults to "col1", "col2", ...
* @param out_appender The resulting appender object.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_appender_create_query(duckdb_connection connection, const char *query,
                                                       idx_t column_count, duckdb_logical_type *types,
                                                       const char *table_name, const char **column_names,
                                                       duckdb_appender *out_appender);

/*!
Returns the number of columns that belong to the appender.
If there is no active column list, then this equals the table's physical columns.

* @param appender The appender to get the column count from.
* @return The number of columns in the data chunks.
*/
DUCKDB_C_API idx_t duckdb_appender_column_count(duckdb_appender appender);

/*!
Returns the type of the column at the specified index. This is either a type in the active column list, or the same type
as a column in the receiving table.

Note: The resulting type must be destroyed with `duckdb_destroy_logical_type`.

* @param appender The appender to get the column type from.
* @param col_idx The index of the column to get the type of.
* @return The `duckdb_logical_type` of the column.
*/
DUCKDB_C_API duckdb_logical_type duckdb_appender_column_type(duckdb_appender appender, idx_t col_idx);

#ifndef DUCKDB_API_NO_DEPRECATED
/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.
Use duckdb_appender_error_data instead.

Returns the error message associated with the appender.
If the appender has no error message, this returns `nullptr` instead.

The error message should not be freed. It will be de-allocated when `duckdb_appender_destroy` is called.

* @param appender The appender to get the error from.
* @return The error message, or `nullptr` if there is none.
*/
DUCKDB_C_API const char *duckdb_appender_error(duckdb_appender appender);

#endif

/*!
Returns the error data associated with the appender.
Must be destroyed with duckdb_destroy_error_data.

* @param appender The appender to get the error data from.
* @return The error data.
*/
DUCKDB_C_API duckdb_error_data duckdb_appender_error_data(duckdb_appender appender);

/*!
Flush the appender to the table, forcing the cache of the appender to be cleared. If flushing the data triggers a
constraint violation or any other error, then all data is invalidated, and this function returns DuckDBError.
It is not possible to append more values. Call duckdb_appender_error_data to obtain the error data followed by
duckdb_appender_destroy to destroy the invalidated appender.

* @param appender The appender to flush.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_appender_flush(duckdb_appender appender);

/*!
Closes the appender by flushing all intermediate states and closing it for further appends. If flushing the data
triggers a constraint violation or any other error, then all data is invalidated, and this function returns DuckDBError.
Call duckdb_appender_error_data to obtain the error data followed by duckdb_appender_destroy to destroy the invalidated
appender.

* @param appender The appender to flush and close.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_appender_close(duckdb_appender appender);

/*!
Closes the appender by flushing all intermediate states to the table and destroying it. By destroying it, this function
de-allocates all memory associated with the appender. If flushing the data triggers a constraint violation,
then all data is invalidated, and this function returns DuckDBError. Due to the destruction of the appender, it is no
longer possible to obtain the specific error message with duckdb_appender_error. Therefore, call duckdb_appender_close
before destroying the appender, if you need insights into the specific error.

* @param appender The appender to flush, close and destroy.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_appender_destroy(duckdb_appender *appender);

/*!
Appends a column to the active column list of the appender. Immediately flushes all previous data.

The active column list specifies all columns that are expected when flushing the data. Any non-active columns are filled
with their default values, or NULL.

* @param appender The appender to add the column to.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_appender_add_column(duckdb_appender appender, const char *name);

/*!
Removes all columns from the active column list of the appender, resetting the appender to treat all columns as active.
Immediately flushes all previous data.

* @param appender The appender to clear the columns from.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_appender_clear_columns(duckdb_appender appender);

/*!
A nop function, provided for backwards compatibility reasons. Does nothing. Only `duckdb_appender_end_row` is required.
*/
DUCKDB_C_API duckdb_state duckdb_appender_begin_row(duckdb_appender appender);

/*!
Finish the current row of appends. After end_row is called, the next row can be appended.

* @param appender The appender.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_appender_end_row(duckdb_appender appender);

/*!
Append a DEFAULT value (NULL if DEFAULT not available for column) to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_default(duckdb_appender appender);

/*!
Append a DEFAULT value, at the specified row and column, (NULL if DEFAULT not available for column) to the chunk created
from the specified appender. The default value of the column must be a constant value. Non-deterministic expressions
like nextval('seq') or random() are not supported.

* @param appender The appender to get the default value from.
* @param chunk The data chunk to append the default value to.
* @param col The chunk column index to append the default value to.
* @param row The chunk row index to append the default value to.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_append_default_to_chunk(duckdb_appender appender, duckdb_data_chunk chunk, idx_t col,
                                                         idx_t row);

/*!
Append a bool value to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_bool(duckdb_appender appender, bool value);

/*!
Append an int8_t value to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_int8(duckdb_appender appender, int8_t value);

/*!
Append an int16_t value to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_int16(duckdb_appender appender, int16_t value);

/*!
Append an int32_t value to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_int32(duckdb_appender appender, int32_t value);

/*!
Append an int64_t value to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_int64(duckdb_appender appender, int64_t value);

/*!
Append a duckdb_hugeint value to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_hugeint(duckdb_appender appender, duckdb_hugeint value);

/*!
Append a uint8_t value to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_uint8(duckdb_appender appender, uint8_t value);

/*!
Append a uint16_t value to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_uint16(duckdb_appender appender, uint16_t value);

/*!
Append a uint32_t value to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_uint32(duckdb_appender appender, uint32_t value);

/*!
Append a uint64_t value to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_uint64(duckdb_appender appender, uint64_t value);

/*!
Append a duckdb_uhugeint value to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_uhugeint(duckdb_appender appender, duckdb_uhugeint value);

/*!
Append a float value to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_float(duckdb_appender appender, float value);

/*!
Append a double value to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_double(duckdb_appender appender, double value);

/*!
Append a duckdb_date value to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_date(duckdb_appender appender, duckdb_date value);

/*!
Append a duckdb_time value to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_time(duckdb_appender appender, duckdb_time value);

/*!
Append a duckdb_timestamp value to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_timestamp(duckdb_appender appender, duckdb_timestamp value);

/*!
Append a duckdb_interval value to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_interval(duckdb_appender appender, duckdb_interval value);

/*!
Append a varchar value to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_varchar(duckdb_appender appender, const char *val);

/*!
Append a varchar value to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_varchar_length(duckdb_appender appender, const char *val, idx_t length);

/*!
Append a blob value to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_blob(duckdb_appender appender, const void *data, idx_t length);

/*!
Append a NULL value to the appender (of any type).
*/
DUCKDB_C_API duckdb_state duckdb_append_null(duckdb_appender appender);

/*!
Append a duckdb_value to the appender.
*/
DUCKDB_C_API duckdb_state duckdb_append_value(duckdb_appender appender, duckdb_value value);

/*!
Appends a pre-filled data chunk to the specified appender.
 Attempts casting, if the data chunk types do not match the active appender types.

* @param appender The appender to append to.
* @param chunk The data chunk to append.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_append_data_chunk(duckdb_appender appender, duckdb_data_chunk chunk);

//===--------------------------------------------------------------------===//
// Table Description
//===--------------------------------------------------------------------===//

/*!
Creates a table description object. Note that `duckdb_table_description_destroy` should always be called on the
resulting table_description, even if the function returns `DuckDBError`.

* @param connection The connection context.
* @param schema The schema of the table, or `nullptr` for the default schema.
* @param table The table name.
* @param out The resulting table description object.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_table_description_create(duckdb_connection connection, const char *schema,
                                                          const char *table, duckdb_table_description *out);

/*!
Creates a table description object. Note that `duckdb_table_description_destroy` must be called on the resulting
table_description, even if the function returns `DuckDBError`.

* @param connection The connection context.
* @param catalog The catalog (database) name of the table, or `nullptr` for the default catalog.
* @param schema The schema of the table, or `nullptr` for the default schema.
* @param table The table name.
* @param out The resulting table description object.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_table_description_create_ext(duckdb_connection connection, const char *catalog,
                                                              const char *schema, const char *table,
                                                              duckdb_table_description *out);

/*!
Destroy the TableDescription object.

* @param table_description The table_description to destroy.
*/
DUCKDB_C_API void duckdb_table_description_destroy(duckdb_table_description *table_description);

/*!
Returns the error message associated with the given table_description.
If the table_description has no error message, this returns `nullptr` instead.
The error message should not be freed. It will be de-allocated when `duckdb_table_description_destroy` is called.

* @param table_description The table_description to get the error from.
* @return The error message, or `nullptr` if there is none.
*/
DUCKDB_C_API const char *duckdb_table_description_error(duckdb_table_description table_description);

/*!
Check if the column at 'index' index of the table has a DEFAULT expression.

* @param table_description The table_description to query.
* @param index The index of the column to query.
* @param out The out-parameter used to store the result.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_column_has_default(duckdb_table_description table_description, idx_t index, bool *out);

/*!
Obtain the column name at 'index'.
The out result must be destroyed with `duckdb_free`.

* @param table_description The table_description to query.
* @param index The index of the column to query.
* @return The column name.
*/
DUCKDB_C_API char *duckdb_table_description_get_column_name(duckdb_table_description table_description, idx_t index);

//===--------------------------------------------------------------------===//
// Arrow Interface
//===--------------------------------------------------------------------===//

/*!
Transforms a DuckDB Schema into an Arrow Schema

* @param arrow_options The Arrow settings used to produce arrow.
* @param types The DuckDB logical types for each column in the schema.
* @param names The names for each column in the schema.
* @param column_count The number of columns that exist in the schema.
* @param out_schema The resulting arrow schema. Must be destroyed with `out_schema->release(out_schema)`.
* @return The error data. Must be destroyed with `duckdb_destroy_error_data`.
*/
DUCKDB_C_API duckdb_error_data duckdb_to_arrow_schema(duckdb_arrow_options arrow_options, duckdb_logical_type *types,
                                                      const char **names, idx_t column_count,
                                                      struct ArrowSchema *out_schema);

/*!
Transforms a DuckDB data chunk into an Arrow array.

* @param arrow_options The Arrow settings used to produce arrow.
* @param chunk The DuckDB data chunk to convert.
* @param out_arrow_array The output Arrow structure that will hold the converted data. Must be released with
`out_arrow_array->release(out_arrow_array)`
* @return The error data. Must be destroyed with `duckdb_destroy_error_data`.
*/
DUCKDB_C_API duckdb_error_data duckdb_data_chunk_to_arrow(duckdb_arrow_options arrow_options, duckdb_data_chunk chunk,
                                                          struct ArrowArray *out_arrow_array);

/*!
Transforms an Arrow Schema into a DuckDB Schema.

* @param connection The connection to get the transformation settings from.
* @param schema The input Arrow schema. Must be released with `schema->release(schema)`.
* @param out_types The Arrow converted schema with extra information about the arrow types. Must be destroyed with
`duckdb_destroy_arrow_converted_schema`.
* @return The error data. Must be destroyed with `duckdb_destroy_error_data`.
*/
DUCKDB_C_API duckdb_error_data duckdb_schema_from_arrow(duckdb_connection connection, struct ArrowSchema *schema,
                                                        duckdb_arrow_converted_schema *out_types);

/*!
Transforms an Arrow array into a DuckDB data chunk. The data chunk will retain ownership of the underlying Arrow data.

* @param connection The connection to get the transformation settings from.
* @param arrow_array The input Arrow array. Data ownership is passed on to DuckDB's DataChunk, the underlying object
does not need to be released and won't have ownership of the data.
* @param converted_schema The Arrow converted schema with extra information about the arrow types.
* @param out_chunk The resulting DuckDB data chunk. Must be destroyed by duckdb_destroy_data_chunk.
* @return The error data. Must be destroyed with `duckdb_destroy_error_data`.
*/
DUCKDB_C_API duckdb_error_data duckdb_data_chunk_from_arrow(duckdb_connection connection,
                                                            struct ArrowArray *arrow_array,
                                                            duckdb_arrow_converted_schema converted_schema,
                                                            duckdb_data_chunk *out_chunk);

/*!
Destroys the arrow converted schema and de-allocates all memory allocated for that arrow converted schema.

* @param arrow_converted_schema The arrow converted schema to destroy.
*/
DUCKDB_C_API void duckdb_destroy_arrow_converted_schema(duckdb_arrow_converted_schema *arrow_converted_schema);

#ifndef DUCKDB_API_NO_DEPRECATED
/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

Executes a SQL query within a connection and stores the full (materialized) result in an arrow structure.
If the query fails to execute, DuckDBError is returned and the error message can be retrieved by calling
`duckdb_query_arrow_error`.

Note that after running `duckdb_query_arrow`, `duckdb_destroy_arrow` must be called on the result object even if the
query fails, otherwise the error stored within the result will not be freed correctly.

* @param connection The connection to perform the query in.
* @param query The SQL query to run.
* @param out_result The query result.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_query_arrow(duckdb_connection connection, const char *query, duckdb_arrow *out_result);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

Fetch the internal arrow schema from the arrow result. Remember to call release on the respective
ArrowSchema object.

* @param result The result to fetch the schema from.
* @param out_schema The output schema.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_query_arrow_schema(duckdb_arrow result, duckdb_arrow_schema *out_schema);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

Fetch the internal arrow schema from the prepared statement. Remember to call release on the respective
ArrowSchema object.

* @param prepared The prepared statement to fetch the schema from.
* @param out_schema The output schema.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_prepared_arrow_schema(duckdb_prepared_statement prepared,
                                                       duckdb_arrow_schema *out_schema);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

Convert a data chunk into an arrow struct array. Remember to call release on the respective
ArrowArray object.

* @param result The result object the data chunk have been fetched from.
* @param chunk The data chunk to convert.
* @param out_array The output array.
*/
DUCKDB_C_API void duckdb_result_arrow_array(duckdb_result result, duckdb_data_chunk chunk,
                                            duckdb_arrow_array *out_array);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

Fetch an internal arrow struct array from the arrow result. Remember to call release on the respective
ArrowArray object.

This function can be called multiple time to get next chunks, which will free the previous out_array.
So consume the out_array before calling this function again.

* @param result The result to fetch the array from.
* @param out_array The output array.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_query_arrow_array(duckdb_arrow result, duckdb_arrow_array *out_array);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

Returns the number of columns present in the arrow result object.

* @param result The result object.
* @return The number of columns present in the result object.
*/
DUCKDB_C_API idx_t duckdb_arrow_column_count(duckdb_arrow result);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

Returns the number of rows present in the arrow result object.

* @param result The result object.
* @return The number of rows present in the result object.
*/
DUCKDB_C_API idx_t duckdb_arrow_row_count(duckdb_arrow result);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

Returns the number of rows changed by the query stored in the arrow result. This is relevant only for
INSERT/UPDATE/DELETE queries. For other queries the rows_changed will be 0.

* @param result The result object.
* @return The number of rows changed.
*/
DUCKDB_C_API idx_t duckdb_arrow_rows_changed(duckdb_arrow result);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

 Returns the error message contained within the result. The error is only set if `duckdb_query_arrow` returns
`DuckDBError`.

The error message should not be freed. It will be de-allocated when `duckdb_destroy_arrow` is called.

* @param result The result object to fetch the error from.
* @return The error of the result.
*/
DUCKDB_C_API const char *duckdb_query_arrow_error(duckdb_arrow result);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

Closes the result and de-allocates all memory allocated for the arrow result.

* @param result The result to destroy.
*/
DUCKDB_C_API void duckdb_destroy_arrow(duckdb_arrow *result);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

Releases the arrow array stream and de-allocates its memory.

* @param stream_p The arrow array stream to destroy.
*/
DUCKDB_C_API void duckdb_destroy_arrow_stream(duckdb_arrow_stream *stream_p);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

Executes the prepared statement with the given bound parameters, and returns an arrow query result.
Note that after running `duckdb_execute_prepared_arrow`, `duckdb_destroy_arrow` must be called on the result object.

* @param prepared_statement The prepared statement to execute.
* @param out_result The query result.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_execute_prepared_arrow(duckdb_prepared_statement prepared_statement,
                                                        duckdb_arrow *out_result);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

Scans the Arrow stream and creates a view with the given name.

* @param connection The connection on which to execute the scan.
* @param table_name Name of the temporary view to create.
* @param arrow Arrow stream wrapper.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_arrow_scan(duckdb_connection connection, const char *table_name,
                                            duckdb_arrow_stream arrow);

/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

Scans the Arrow array and creates a view with the given name.
Note that after running `duckdb_arrow_array_scan`, `duckdb_destroy_arrow_stream` must be called on the out stream.

* @param connection The connection on which to execute the scan.
* @param table_name Name of the temporary view to create.
* @param arrow_schema Arrow schema wrapper.
* @param arrow_array Arrow array wrapper.
* @param out_stream Output array stream that wraps around the passed schema, for releasing/deleting once done.
* @return `DuckDBSuccess` on success or `DuckDBError` on failure.
*/
DUCKDB_C_API duckdb_state duckdb_arrow_array_scan(duckdb_connection connection, const char *table_name,
                                                  duckdb_arrow_schema arrow_schema, duckdb_arrow_array arrow_array,
                                                  duckdb_arrow_stream *out_stream);

#endif

//===--------------------------------------------------------------------===//
// Threading Information
//===--------------------------------------------------------------------===//

/*!
Execute DuckDB tasks on this thread.

Will return after `max_tasks` have been executed, or if there are no more tasks present.

* @param database The database object to execute tasks for
* @param max_tasks The maximum amount of tasks to execute
*/
DUCKDB_C_API void duckdb_execute_tasks(duckdb_database database, idx_t max_tasks);

/*!
Creates a task state that can be used with duckdb_execute_tasks_state to execute tasks until
`duckdb_finish_execution` is called on the state.

`duckdb_destroy_state` must be called on the result.

* @param database The database object to create the task state for
* @return The task state that can be used with duckdb_execute_tasks_state.
*/
DUCKDB_C_API duckdb_task_state duckdb_create_task_state(duckdb_database database);

/*!
Execute DuckDB tasks on this thread.

The thread will keep on executing tasks forever, until duckdb_finish_execution is called on the state.
Multiple threads can share the same duckdb_task_state.

* @param state The task state of the executor
*/
DUCKDB_C_API void duckdb_execute_tasks_state(duckdb_task_state state);

/*!
Execute DuckDB tasks on this thread.

The thread will keep on executing tasks until either duckdb_finish_execution is called on the state,
max_tasks tasks have been executed or there are no more tasks to be executed.

Multiple threads can share the same duckdb_task_state.

* @param state The task state of the executor
* @param max_tasks The maximum amount of tasks to execute
* @return The amount of tasks that have actually been executed
*/
DUCKDB_C_API idx_t duckdb_execute_n_tasks_state(duckdb_task_state state, idx_t max_tasks);

/*!
Finish execution on a specific task.

* @param state The task state to finish execution
*/
DUCKDB_C_API void duckdb_finish_execution(duckdb_task_state state);

/*!
Check if the provided duckdb_task_state has finished execution

* @param state The task state to inspect
* @return Whether or not duckdb_finish_execution has been called on the task state
*/
DUCKDB_C_API bool duckdb_task_state_is_finished(duckdb_task_state state);

/*!
Destroys the task state returned from duckdb_create_task_state.

Note that this should not be called while there is an active duckdb_execute_tasks_state running
on the task state.

* @param state The task state to clean up
*/
DUCKDB_C_API void duckdb_destroy_task_state(duckdb_task_state state);

/*!
Returns true if the execution of the current query is finished.

* @param con The connection on which to check
*/
DUCKDB_C_API bool duckdb_execution_is_finished(duckdb_connection con);

//===--------------------------------------------------------------------===//
// Streaming Result Interface
//===--------------------------------------------------------------------===//

#ifndef DUCKDB_API_NO_DEPRECATED
/*!
**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.

Fetches a data chunk from the (streaming) duckdb_result. This function should be called repeatedly until the result is
exhausted.

The result must be destroyed with `duckdb_destroy_data_chunk`.

This function can only be used on duckdb_results created with 'duckdb_pending_prepared_streaming'

If this function is used, none of the other result functions can be used and vice versa (i.e. this function cannot be
mixed with the legacy result functions or the materialized result functions).

It is not known beforehand how many chunks will be returned by this result.

* @param result The result object to fetch the data chunk from.
* @return The resulting data chunk. Returns `NULL` if the result has an error.
*/
DUCKDB_C_API duckdb_data_chunk duckdb_stream_fetch_chunk(duckdb_result result);

#endif

/*!
Fetches a data chunk from a duckdb_result. This function should be called repeatedly until the result is exhausted.

The result must be destroyed with `duckdb_destroy_data_chunk`.

It is not known beforehand how many chunks will be returned by this result.

* @param result The result object to fetch the data chunk from.
* @return The resulting data chunk. Returns `NULL` if the result has an error.
*/
DUCKDB_C_API duckdb_data_chunk duckdb_fetch_chunk(duckdb_result result);

//===--------------------------------------------------------------------===//
// Cast Functions
//===--------------------------------------------------------------------===//

/*!
Creates a new cast function object.

* @return The cast function object.
*/
DUCKDB_C_API duckdb_cast_function duckdb_create_cast_function();

/*!
Sets the source type of the cast function.

* @param cast_function The cast function object.
* @param source_type The source type to set.
*/
DUCKDB_C_API void duckdb_cast_function_set_source_type(duckdb_cast_function cast_function,
                                                       duckdb_logical_type source_type);

/*!
Sets the target type of the cast function.

* @param cast_function The cast function object.
* @param target_type The target type to set.
*/
DUCKDB_C_API void duckdb_cast_function_set_target_type(duckdb_cast_function cast_function,
                                                       duckdb_logical_type target_type);

/*!
Sets the "cost" of implicitly casting the source type to the target type using this function.

* @param cast_function The cast function object.
* @param cost The cost to set.
*/
DUCKDB_C_API void duckdb_cast_function_set_implicit_cast_cost(duckdb_cast_function cast_function, int64_t cost);

/*!
Sets the actual cast function to use.

* @param cast_function The cast function object.
* @param function The function to set.
*/
DUCKDB_C_API void duckdb_cast_function_set_function(duckdb_cast_function cast_function,
                                                    duckdb_cast_function_t function);

/*!
Assigns extra information to the cast function that can be fetched during execution, etc.

* @param extra_info The extra information
* @param destroy The callback that will be called to destroy the extra information (if any)
*/
DUCKDB_C_API void duckdb_cast_function_set_extra_info(duckdb_cast_function cast_function, void *extra_info,
                                                      duckdb_delete_callback_t destroy);

/*!
Retrieves the extra info of the function as set in `duckdb_cast_function_set_extra_info`.

* @param info The info object.
* @return The extra info.
*/
DUCKDB_C_API void *duckdb_cast_function_get_extra_info(duckdb_function_info info);

/*!
Get the cast execution mode from the given function info.

* @param info The info object.
* @return The cast mode.
*/
DUCKDB_C_API duckdb_cast_mode duckdb_cast_function_get_cast_mode(duckdb_function_info info);

/*!
Report that an error has occurred while executing the cast function.

* @param info The info object.
* @param error The error message.
*/
DUCKDB_C_API void duckdb_cast_function_set_error(duckdb_function_info info, const char *error);

/*!
Report that an error has occurred while executing the cast function, setting the corresponding output row to NULL.

* @param info The info object.
* @param error The error message.
* @param row The index of the row within the output vector to set to NULL.
* @param output The output vector.
*/
DUCKDB_C_API void duckdb_cast_function_set_row_error(duckdb_function_info info, const char *error, idx_t row,
                                                     duckdb_vector output);

/*!
Registers a cast function within the given connection.

* @param con The connection to use.
* @param cast_function The cast function to register.
* @return Whether or not the registration was successful.
*/
DUCKDB_C_API duckdb_state duckdb_register_cast_function(duckdb_connection con, duckdb_cast_function cast_function);

/*!
Destroys the cast function object.

* @param cast_function The cast function object.
*/
DUCKDB_C_API void duckdb_destroy_cast_function(duckdb_cast_function *cast_function);

//===--------------------------------------------------------------------===//
// Expression Interface
//===--------------------------------------------------------------------===//

/*!
Destroys the expression and de-allocates its memory.

* @param expr A pointer to the expression.
*/
DUCKDB_C_API void duckdb_destroy_expression(duckdb_expression *expr);

/*!
Returns the return type of an expression.

* @param expr The expression.
* @return The return type. Must be destroyed with `duckdb_destroy_logical_type`.
*/
DUCKDB_C_API duckdb_logical_type duckdb_expression_return_type(duckdb_expression expr);

/*!
Returns whether the expression is foldable into a value or not.

* @param expr The expression.
* @return True, if the expression is foldable, else false.
*/
DUCKDB_C_API bool duckdb_expression_is_foldable(duckdb_expression expr);

/*!
Folds an expression creating a folded value.

* @param context The client context.
* @param expr The expression. Must be foldable.
* @param out_value The folded value, if folding was successful. Must be destroyed with `duckdb_destroy_value`.
* @return The error data. Must be destroyed with `duckdb_destroy_error_data`.
*/
DUCKDB_C_API duckdb_error_data duckdb_expression_fold(duckdb_client_context context, duckdb_expression expr,
                                                      duckdb_value *out_value);

#endif

#ifdef __cplusplus
}
#endif
