
###############################################################################
# 
# DuckDB Julia API
# 
# !!!!!!!!!!!!
# WARNING: this file is autogenerated by scripts/generate_c_api_julia.py, manual changes will be overwritten
# !!!!!!!!!!!!
#
###############################################################################

using Base.Libc

if "JULIA_DUCKDB_LIBRARY" in keys(ENV)
    libduckdb = ENV["JULIA_DUCKDB_LIBRARY"]
else
    using DuckDB_jll
end

DUCKDB_API_VERSION = v"1.2.0"


# --------------------------------------------------------------------------------
# Open Connect
# --------------------------------------------------------------------------------

"""
    duckdb_create_instance_cache()

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'.

# Arguments

Returns: `duckdb_instance_cache` The database instance cache.
"""
function duckdb_create_instance_cache()
    return ccall((:duckdb_create_instance_cache, libduckdb), duckdb_instance_cache, ())
end

"""
    duckdb_get_or_create_from_cache(instance_cache, path, out_database, config, out_error)

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

# Arguments
- `instance_cache`: `duckdb_instance_cache` The instance cache in which to create the database, or from which to take the database.
- `path`: `Cstring` Path to the database file on disk. Both `nullptr` and `:memory:` open or retrieve an in-memory database.
- `out_database`: `Ref{duckdb_database}` The resulting cached database.
- `config`: `duckdb_config` (Optional) configuration used to create the database.
- `out_error`: `Ref{Cstring}` If set and the function returns `DuckDBError`, this contains the error message.
Note that the error message must be freed using `duckdb_free`.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_get_or_create_from_cache(instance_cache, path, out_database, config, out_error)
    return ccall(
        (:duckdb_get_or_create_from_cache, libduckdb),
        duckdb_state,
        (duckdb_instance_cache, Cstring, Ref{duckdb_database}, duckdb_config, Ref{Cstring}),
        instance_cache,
        path,
        out_database,
        config,
        out_error
    )
end

"""
    duckdb_destroy_instance_cache(instance_cache)

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

# Arguments
- `instance_cache`: `Ref{duckdb_instance_cache}` The instance cache to destroy.

Returns: `Nothing` 
"""
function duckdb_destroy_instance_cache(instance_cache)
    return ccall((:duckdb_destroy_instance_cache, libduckdb), Cvoid, (Ref{duckdb_instance_cache},), instance_cache)
end

"""
    duckdb_open(path, out_database)

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'.

# Arguments
- `path`: `Cstring` Path to the database file on disk. Both `nullptr` and `:memory:` open an in-memory database.
- `out_database`: `Ref{duckdb_database}` The result database object.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_open(path, out_database)
    return ccall((:duckdb_open, libduckdb), duckdb_state, (Cstring, Ref{duckdb_database}), path, out_database)
end

"""
    duckdb_open_ext(path, out_database, config, out_error)

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'.

# Arguments
- `path`: `Cstring` Path to the database file on disk. Both `nullptr` and `:memory:` open an in-memory database.
- `out_database`: `Ref{duckdb_database}` The result database object.
- `config`: `duckdb_config` (Optional) configuration used to start up the database.
- `out_error`: `Ref{Cstring}` If set and the function returns `DuckDBError`, this contains the error message.
Note that the error message must be freed using `duckdb_free`.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_open_ext(path, out_database, config, out_error)
    return ccall(
        (:duckdb_open_ext, libduckdb),
        duckdb_state,
        (Cstring, Ref{duckdb_database}, duckdb_config, Ref{Cstring}),
        path,
        out_database,
        config,
        out_error
    )
end

"""
    duckdb_close(database)

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.

# Arguments
- `database`: `Ref{duckdb_database}` The database object to shut down.

Returns: `Nothing` 
"""
function duckdb_close(database)
    return ccall((:duckdb_close, libduckdb), Cvoid, (Ref{duckdb_database},), database)
end

"""
    duckdb_connect(database, out_connection)

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'.

# Arguments
- `database`: `duckdb_database` The database file to connect to.
- `out_connection`: `Ref{duckdb_connection}` The result connection object.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_connect(database, out_connection)
    return ccall(
        (:duckdb_connect, libduckdb),
        duckdb_state,
        (duckdb_database, Ref{duckdb_connection}),
        database,
        out_connection
    )
end

"""
    duckdb_interrupt(connection)

Interrupt running query

# Arguments
- `connection`: `duckdb_connection` The connection to interrupt

Returns: `Nothing` 
"""
function duckdb_interrupt(connection)
    return ccall((:duckdb_interrupt, libduckdb), Cvoid, (duckdb_connection,), connection)
end

"""
    duckdb_query_progress(connection)

Get progress of the running query

# Arguments
- `connection`: `duckdb_connection` The working connection

Returns: `duckdb_query_progress_type` -1 if no progress or a percentage of the progress
"""
function duckdb_query_progress(connection)
    return ccall((:duckdb_query_progress, libduckdb), duckdb_query_progress_type, (duckdb_connection,), connection)
end

"""
    duckdb_disconnect(connection)

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

# Arguments
- `connection`: `Ref{duckdb_connection}` The connection to close.

Returns: `Nothing` 
"""
function duckdb_disconnect(connection)
    return ccall((:duckdb_disconnect, libduckdb), Cvoid, (Ref{duckdb_connection},), connection)
end

"""
    duckdb_connection_get_client_context(connection, out_context)

Retrieves the client context of the connection.

# Arguments
- `connection`: `duckdb_connection` The connection.
- `out_context`: `Ref{duckdb_client_context}` The client context of the connection. Must be destroyed with `duckdb_destroy_client_context`.

Returns: `Nothing` 
"""
function duckdb_connection_get_client_context(connection, out_context)
    return ccall(
        (:duckdb_connection_get_client_context, libduckdb),
        Cvoid,
        (duckdb_connection, Ref{duckdb_client_context}),
        connection,
        out_context
    )
end

"""
    duckdb_client_context_get_connection_id(context)

Returns the connection id of the client context.

# Arguments
- `context`: `duckdb_client_context` The client context.

Returns: `idx_t` The connection id of the client context.
"""
function duckdb_client_context_get_connection_id(context)
    return ccall((:duckdb_client_context_get_connection_id, libduckdb), idx_t, (duckdb_client_context,), context)
end

"""
    duckdb_destroy_client_context(context)

Destroys the client context and deallocates its memory.

# Arguments
- `context`: `Ref{duckdb_client_context}` The client context to destroy.

Returns: `Nothing` 
"""
function duckdb_destroy_client_context(context)
    return ccall((:duckdb_destroy_client_context, libduckdb), Cvoid, (Ref{duckdb_client_context},), context)
end

"""
    duckdb_library_version()

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.

# Arguments

Returns: `Cstring` 
"""
function duckdb_library_version()
    return ccall((:duckdb_library_version, libduckdb), Cstring, ())
end

"""
    duckdb_get_table_names(connection, query, qualified)

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

# Arguments
- `connection`: `duckdb_connection` The connection for which to get the table names.
- `query`: `Cstring` The query for which to get the table names.
- `qualified`: `Bool` Returns fully qualified table names (catalog.schema.table), if set to true, else only the (not escaped) table names.

Returns: `duckdb_value` A duckdb_value of type VARCHAR[] containing the (fully qualified) table names of the query. Must be destroyed with duckdb_destroy_value.
"""
function duckdb_get_table_names(connection, query, qualified)
    return ccall(
        (:duckdb_get_table_names, libduckdb),
        duckdb_value,
        (duckdb_connection, Cstring, Bool),
        connection,
        query,
        qualified
    )
end



# --------------------------------------------------------------------------------
# Configuration
# --------------------------------------------------------------------------------

"""
    duckdb_create_config(out_config)

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`.

# Arguments
- `out_config`: `Ref{duckdb_config}` The result configuration object.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_create_config(out_config)
    return ccall((:duckdb_create_config, libduckdb), duckdb_state, (Ref{duckdb_config},), out_config)
end

"""
    duckdb_config_count()

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.

# Arguments

Returns: `Csize_t` The amount of config options available.
"""
function duckdb_config_count()
    return ccall((:duckdb_config_count, libduckdb), Csize_t, ())
end

"""
    duckdb_get_config_flag(index, out_name, out_description)

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.

# Arguments
- `index`: `Csize_t` (1-based index) The index of the configuration option (between 0 and `duckdb_config_count`)
- `out_name`: `Ref{Cstring}` A name of the configuration flag.
- `out_description`: `Ref{Cstring}` A description of the configuration flag.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_get_config_flag(index, out_name, out_description)
    return ccall(
        (:duckdb_get_config_flag, libduckdb),
        duckdb_state,
        (Csize_t, Ref{Cstring}, Ref{Cstring}),
        index - 1,
        out_name,
        out_description
    )
end

"""
    duckdb_set_config(config, name, option)

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.

# Arguments
- `config`: `duckdb_config` The configuration object to set the option on.
- `name`: `Cstring` The name of the configuration flag to set.
- `option`: `Cstring` The value to set the configuration flag to.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_set_config(config, name, option)
    return ccall((:duckdb_set_config, libduckdb), duckdb_state, (duckdb_config, Cstring, Cstring), config, name, option)
end

"""
    duckdb_destroy_config(config)

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

# Arguments
- `config`: `Ref{duckdb_config}` The configuration object to destroy.

Returns: `Nothing` 
"""
function duckdb_destroy_config(config)
    return ccall((:duckdb_destroy_config, libduckdb), Cvoid, (Ref{duckdb_config},), config)
end



# --------------------------------------------------------------------------------
# Query Execution
# --------------------------------------------------------------------------------

"""
    duckdb_query(connection, query, out_result)

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.

# Arguments
- `connection`: `duckdb_connection` The connection to perform the query in.
- `query`: `Cstring` The SQL query to run.
- `out_result`: `Ref{duckdb_result}` The query result.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_query(connection, query, out_result)
    return ccall(
        (:duckdb_query, libduckdb),
        duckdb_state,
        (duckdb_connection, Cstring, Ref{duckdb_result}),
        connection,
        query,
        out_result
    )
end

"""
    duckdb_destroy_result(result)

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

# Arguments
- `result`: `Ref{duckdb_result}` The result to destroy.

Returns: `Nothing` 
"""
function duckdb_destroy_result(result)
    return ccall((:duckdb_destroy_result, libduckdb), Cvoid, (Ref{duckdb_result},), result)
end

"""
    duckdb_column_name(result, col)

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.

# Arguments
- `result`: `Ref{duckdb_result}` The result object to fetch the column name from.
- `col`: `idx_t` (1-based index) The column index.

Returns: `Cstring` The column name of the specified column.
"""
function duckdb_column_name(result, col)
    return ccall((:duckdb_column_name, libduckdb), Cstring, (Ref{duckdb_result}, idx_t), result, col - 1)
end

"""
    duckdb_column_type(result, col)

Returns the column type of the specified column.

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

# Arguments
- `result`: `Ref{duckdb_result}` The result object to fetch the column type from.
- `col`: `idx_t` (1-based index) The column index.

Returns: `DUCKDB_TYPE` The column type of the specified column.
"""
function duckdb_column_type(result, col)
    return ccall((:duckdb_column_type, libduckdb), DUCKDB_TYPE, (Ref{duckdb_result}, idx_t), result, col - 1)
end

"""
    duckdb_result_statement_type(result)

Returns the statement type of the statement that was executed

# Arguments
- `result`: `duckdb_result` The result object to fetch the statement type from.

Returns: `duckdb_statement_type` duckdb_statement_type value or DUCKDB_STATEMENT_TYPE_INVALID
"""
function duckdb_result_statement_type(result)
    return ccall((:duckdb_result_statement_type, libduckdb), duckdb_statement_type, (duckdb_result,), result)
end

"""
    duckdb_column_logical_type(result, col)

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.

# Arguments
- `result`: `Ref{duckdb_result}` The result object to fetch the column type from.
- `col`: `idx_t` (1-based index) The column index.

Returns: `duckdb_logical_type` The logical column type of the specified column.
"""
function duckdb_column_logical_type(result, col)
    return ccall(
        (:duckdb_column_logical_type, libduckdb),
        duckdb_logical_type,
        (Ref{duckdb_result}, idx_t),
        result,
        col - 1
    )
end

"""
    duckdb_column_count(result)

Returns the number of columns present in a the result object.

# Arguments
- `result`: `Ref{duckdb_result}` The result object.

Returns: `idx_t` The number of columns present in the result object.
"""
function duckdb_column_count(result)
    return ccall((:duckdb_column_count, libduckdb), idx_t, (Ref{duckdb_result},), result)
end

"""
    duckdb_row_count(result)

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

Returns the number of rows present in the result object.

# Arguments
- `result`: `Ref{duckdb_result}` The result object.

Returns: `idx_t` The number of rows present in the result object.
"""
function duckdb_row_count(result)
    Base.depwarn("**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.", :duckdb_row_count)
    return ccall((:duckdb_row_count, libduckdb), idx_t, (Ref{duckdb_result},), result)
end

"""
    duckdb_rows_changed(result)

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.

# Arguments
- `result`: `Ref{duckdb_result}` The result object.

Returns: `idx_t` The number of rows changed.
"""
function duckdb_rows_changed(result)
    return ccall((:duckdb_rows_changed, libduckdb), idx_t, (Ref{duckdb_result},), result)
end

"""
    duckdb_column_data(result, col)

**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]);
```

# Arguments
- `result`: `Ref{duckdb_result}` The result object to fetch the column data from.
- `col`: `idx_t` (1-based index) The column index.

Returns: `Ptr{Cvoid}` The column data of the specified column.
"""
function duckdb_column_data(result, col)
    Base.depwarn(
        "**DEPRECATION NOTICE**: **DEPRECATED**: Prefer using `duckdb_result_get_chunk` instead.",
        :duckdb_column_data
    )
    return ccall((:duckdb_column_data, libduckdb), Ptr{Cvoid}, (Ref{duckdb_result}, idx_t), result, col - 1)
end

"""
    duckdb_nullmask_data(result, 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]);
}
```

# Arguments
- `result`: `Ref{duckdb_result}` The result object to fetch the nullmask from.
- `col`: `idx_t` (1-based index) The column index.

Returns: `Ptr{Bool}` The nullmask of the specified column.
"""
function duckdb_nullmask_data(result, col)
    Base.depwarn(
        "**DEPRECATION NOTICE**: **DEPRECATED**: Prefer using `duckdb_result_get_chunk` instead.",
        :duckdb_nullmask_data
    )
    return ccall((:duckdb_nullmask_data, libduckdb), Ptr{Bool}, (Ref{duckdb_result}, idx_t), result, col - 1)
end

"""
    duckdb_result_error(result)

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.

# Arguments
- `result`: `Ref{duckdb_result}` The result object to fetch the error from.

Returns: `Cstring` The error of the result.
"""
function duckdb_result_error(result)
    return ccall((:duckdb_result_error, libduckdb), Cstring, (Ref{duckdb_result},), result)
end

"""
    duckdb_result_error_type(result)

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

# Arguments
- `result`: `Ref{duckdb_result}` The result object to fetch the error from.

Returns: `duckdb_error_type` The error type of the result.
"""
function duckdb_result_error_type(result)
    return ccall((:duckdb_result_error_type, libduckdb), duckdb_error_type, (Ref{duckdb_result},), result)
end



# --------------------------------------------------------------------------------
# Result Functions
# --------------------------------------------------------------------------------

"""
    duckdb_result_get_chunk(result, chunk_index)

**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.

# Arguments
- `result`: `duckdb_result` The result object to fetch the data chunk from.
- `chunk_index`: `idx_t` (1-based index) The chunk index to fetch from.

Returns: `duckdb_data_chunk` The resulting data chunk. Returns `NULL` if the chunk index is out of bounds.
"""
function duckdb_result_get_chunk(result, chunk_index)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_result_get_chunk
    )
    return ccall(
        (:duckdb_result_get_chunk, libduckdb),
        duckdb_data_chunk,
        (duckdb_result, idx_t),
        result,
        chunk_index - 1
    )
end

"""
    duckdb_result_is_streaming(result)

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

Checks if the type of the internal result is StreamQueryResult.

# Arguments
- `result`: `duckdb_result` The result object to check.

Returns: `Bool` Whether or not the result object is of the type StreamQueryResult
"""
function duckdb_result_is_streaming(result)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_result_is_streaming
    )
    return ccall((:duckdb_result_is_streaming, libduckdb), Bool, (duckdb_result,), result)
end

"""
    duckdb_result_chunk_count(result)

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

Returns the number of data chunks present in the result.

# Arguments
- `result`: `duckdb_result` The result object

Returns: `idx_t` Number of data chunks present in the result.
"""
function duckdb_result_chunk_count(result)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_result_chunk_count
    )
    return ccall((:duckdb_result_chunk_count, libduckdb), idx_t, (duckdb_result,), result)
end

"""
    duckdb_result_return_type(result)

Returns the return_type of the given result, or DUCKDB_RETURN_TYPE_INVALID on error

# Arguments
- `result`: `duckdb_result` The result object

Returns: `duckdb_result_type` The return_type
"""
function duckdb_result_return_type(result)
    return ccall((:duckdb_result_return_type, libduckdb), duckdb_result_type, (duckdb_result,), result)
end



# --------------------------------------------------------------------------------
# Safe Fetch Functions
# --------------------------------------------------------------------------------

"""
    duckdb_value_boolean(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `Bool` The boolean value at the specified location, or false if the value cannot be converted.
"""
function duckdb_value_boolean(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_value_boolean
    )
    return ccall((:duckdb_value_boolean, libduckdb), Bool, (Ref{duckdb_result}, idx_t, idx_t), result, col - 1, row - 1)
end

"""
    duckdb_value_int8(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `Int8` The int8_t value at the specified location, or 0 if the value cannot be converted.
"""
function duckdb_value_int8(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_value_int8
    )
    return ccall((:duckdb_value_int8, libduckdb), Int8, (Ref{duckdb_result}, idx_t, idx_t), result, col - 1, row - 1)
end

"""
    duckdb_value_int16(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `Int16` The int16_t value at the specified location, or 0 if the value cannot be converted.
"""
function duckdb_value_int16(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_value_int16
    )
    return ccall((:duckdb_value_int16, libduckdb), Int16, (Ref{duckdb_result}, idx_t, idx_t), result, col - 1, row - 1)
end

"""
    duckdb_value_int32(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `Int32` The int32_t value at the specified location, or 0 if the value cannot be converted.
"""
function duckdb_value_int32(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_value_int32
    )
    return ccall((:duckdb_value_int32, libduckdb), Int32, (Ref{duckdb_result}, idx_t, idx_t), result, col - 1, row - 1)
end

"""
    duckdb_value_int64(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `Int64` The int64_t value at the specified location, or 0 if the value cannot be converted.
"""
function duckdb_value_int64(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_value_int64
    )
    return ccall((:duckdb_value_int64, libduckdb), Int64, (Ref{duckdb_result}, idx_t, idx_t), result, col - 1, row - 1)
end

"""
    duckdb_value_hugeint(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `duckdb_hugeint` The duckdb_hugeint value at the specified location, or 0 if the value cannot be converted.
"""
function duckdb_value_hugeint(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_value_hugeint
    )
    return ccall(
        (:duckdb_value_hugeint, libduckdb),
        duckdb_hugeint,
        (Ref{duckdb_result}, idx_t, idx_t),
        result,
        col - 1,
        row - 1
    )
end

"""
    duckdb_value_uhugeint(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `duckdb_uhugeint` The duckdb_uhugeint value at the specified location, or 0 if the value cannot be converted.
"""
function duckdb_value_uhugeint(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_value_uhugeint
    )
    return ccall(
        (:duckdb_value_uhugeint, libduckdb),
        duckdb_uhugeint,
        (Ref{duckdb_result}, idx_t, idx_t),
        result,
        col - 1,
        row - 1
    )
end

"""
    duckdb_value_decimal(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `duckdb_decimal` The duckdb_decimal value at the specified location, or 0 if the value cannot be converted.
"""
function duckdb_value_decimal(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_value_decimal
    )
    return ccall(
        (:duckdb_value_decimal, libduckdb),
        duckdb_decimal,
        (Ref{duckdb_result}, idx_t, idx_t),
        result,
        col - 1,
        row - 1
    )
end

"""
    duckdb_value_uint8(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `UInt8` The uint8_t value at the specified location, or 0 if the value cannot be converted.
"""
function duckdb_value_uint8(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_value_uint8
    )
    return ccall((:duckdb_value_uint8, libduckdb), UInt8, (Ref{duckdb_result}, idx_t, idx_t), result, col - 1, row - 1)
end

"""
    duckdb_value_uint16(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `UInt16` The uint16_t value at the specified location, or 0 if the value cannot be converted.
"""
function duckdb_value_uint16(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_value_uint16
    )
    return ccall(
        (:duckdb_value_uint16, libduckdb),
        UInt16,
        (Ref{duckdb_result}, idx_t, idx_t),
        result,
        col - 1,
        row - 1
    )
end

"""
    duckdb_value_uint32(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `UInt32` The uint32_t value at the specified location, or 0 if the value cannot be converted.
"""
function duckdb_value_uint32(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_value_uint32
    )
    return ccall(
        (:duckdb_value_uint32, libduckdb),
        UInt32,
        (Ref{duckdb_result}, idx_t, idx_t),
        result,
        col - 1,
        row - 1
    )
end

"""
    duckdb_value_uint64(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `UInt64` The uint64_t value at the specified location, or 0 if the value cannot be converted.
"""
function duckdb_value_uint64(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_value_uint64
    )
    return ccall(
        (:duckdb_value_uint64, libduckdb),
        UInt64,
        (Ref{duckdb_result}, idx_t, idx_t),
        result,
        col - 1,
        row - 1
    )
end

"""
    duckdb_value_float(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `Float32` The float value at the specified location, or 0 if the value cannot be converted.
"""
function duckdb_value_float(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_value_float
    )
    return ccall(
        (:duckdb_value_float, libduckdb),
        Float32,
        (Ref{duckdb_result}, idx_t, idx_t),
        result,
        col - 1,
        row - 1
    )
end

"""
    duckdb_value_double(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `Float64` The double value at the specified location, or 0 if the value cannot be converted.
"""
function duckdb_value_double(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_value_double
    )
    return ccall(
        (:duckdb_value_double, libduckdb),
        Float64,
        (Ref{duckdb_result}, idx_t, idx_t),
        result,
        col - 1,
        row - 1
    )
end

"""
    duckdb_value_date(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `duckdb_date` The duckdb_date value at the specified location, or 0 if the value cannot be converted.
"""
function duckdb_value_date(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_value_date
    )
    return ccall(
        (:duckdb_value_date, libduckdb),
        duckdb_date,
        (Ref{duckdb_result}, idx_t, idx_t),
        result,
        col - 1,
        row - 1
    )
end

"""
    duckdb_value_time(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `duckdb_time` The duckdb_time value at the specified location, or 0 if the value cannot be converted.
"""
function duckdb_value_time(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_value_time
    )
    return ccall(
        (:duckdb_value_time, libduckdb),
        duckdb_time,
        (Ref{duckdb_result}, idx_t, idx_t),
        result,
        col - 1,
        row - 1
    )
end

"""
    duckdb_value_timestamp(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `duckdb_timestamp` The duckdb_timestamp value at the specified location, or 0 if the value cannot be converted.
"""
function duckdb_value_timestamp(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_value_timestamp
    )
    return ccall(
        (:duckdb_value_timestamp, libduckdb),
        duckdb_timestamp,
        (Ref{duckdb_result}, idx_t, idx_t),
        result,
        col - 1,
        row - 1
    )
end

"""
    duckdb_value_interval(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `duckdb_interval` The duckdb_interval value at the specified location, or 0 if the value cannot be converted.
"""
function duckdb_value_interval(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_value_interval
    )
    return ccall(
        (:duckdb_value_interval, libduckdb),
        duckdb_interval,
        (Ref{duckdb_result}, idx_t, idx_t),
        result,
        col - 1,
        row - 1
    )
end

"""
    duckdb_value_varchar(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `Cstring` 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`.
"""
function duckdb_value_varchar(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: **DEPRECATED**: Use duckdb_value_string instead. This function does not work correctly if the string contains null bytes.",
        :duckdb_value_varchar
    )
    return ccall(
        (:duckdb_value_varchar, libduckdb),
        Cstring,
        (Ref{duckdb_result}, idx_t, idx_t),
        result,
        col - 1,
        row - 1
    )
end

"""
    duckdb_value_string(result, col, 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.`

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `duckdb_string` The string value at the specified location. Attempts to cast the result value to string.
"""
function duckdb_value_string(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_value_string
    )
    return ccall(
        (:duckdb_value_string, libduckdb),
        duckdb_string,
        (Ref{duckdb_result}, idx_t, idx_t),
        result,
        col - 1,
        row - 1
    )
end

"""
    duckdb_value_varchar_internal(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `Cstring` 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.
"""
function duckdb_value_varchar_internal(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: **DEPRECATED**: Use duckdb_value_string_internal instead. This function does not work correctly if the string contains",
        :duckdb_value_varchar_internal
    )
    return ccall(
        (:duckdb_value_varchar_internal, libduckdb),
        Cstring,
        (Ref{duckdb_result}, idx_t, idx_t),
        result,
        col - 1,
        row - 1
    )
end

"""
    duckdb_value_string_internal(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `duckdb_string` 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.
"""
function duckdb_value_string_internal(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: **DEPRECATED**: Use duckdb_value_string_internal instead. This function does not work correctly if the string contains",
        :duckdb_value_string_internal
    )
    return ccall(
        (:duckdb_value_string_internal, libduckdb),
        duckdb_string,
        (Ref{duckdb_result}, idx_t, idx_t),
        result,
        col - 1,
        row - 1
    )
end

"""
    duckdb_value_blob(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `duckdb_blob` 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.`
"""
function duckdb_value_blob(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_value_blob
    )
    return ccall(
        (:duckdb_value_blob, libduckdb),
        duckdb_blob,
        (Ref{duckdb_result}, idx_t, idx_t),
        result,
        col - 1,
        row - 1
    )
end

"""
    duckdb_value_is_null(result, col, row)

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

# Arguments
- `result`: `Ref{duckdb_result}` 
- `col`: `idx_t` (1-based index) 
- `row`: `idx_t` (1-based index) 

Returns: `Bool` Returns true if the value at the specified index is NULL, and false otherwise.
"""
function duckdb_value_is_null(result, col, row)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_value_is_null
    )
    return ccall((:duckdb_value_is_null, libduckdb), Bool, (Ref{duckdb_result}, idx_t, idx_t), result, col - 1, row - 1)
end



# --------------------------------------------------------------------------------
# Helpers
# --------------------------------------------------------------------------------

"""
    duckdb_malloc(size)

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

# Arguments
- `size`: `Csize_t` The number of bytes to allocate.

Returns: `Ptr{Cvoid}` A pointer to the allocated memory region.
"""
function duckdb_malloc(size)
    return ccall((:duckdb_malloc, libduckdb), Ptr{Cvoid}, (Csize_t,), size)
end

"""
    duckdb_free(ptr)

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

# Arguments
- `ptr`: `Ptr{Cvoid}` The memory region to de-allocate.

Returns: `Nothing` 
"""
function duckdb_free(ptr)
    return ccall((:duckdb_free, libduckdb), Cvoid, (Ptr{Cvoid},), ptr)
end

"""
    duckdb_vector_size()

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`.

# Arguments

Returns: `idx_t` The vector size.
"""
function duckdb_vector_size()
    return ccall((:duckdb_vector_size, libduckdb), idx_t, ())
end

"""
    duckdb_string_is_inlined(string)

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

# Arguments
- `string`: `duckdb_string_t` 

Returns: `Bool` 
"""
function duckdb_string_is_inlined(string)
    return ccall((:duckdb_string_is_inlined, libduckdb), Bool, (duckdb_string_t,), string)
end

"""
    duckdb_string_t_length(string)

Get the string length of a string_t

# Arguments
- `string`: `duckdb_string_t` The string to get the length of.

Returns: `UInt32` The length.
"""
function duckdb_string_t_length(string)
    return ccall((:duckdb_string_t_length, libduckdb), UInt32, (duckdb_string_t,), string)
end

"""
    duckdb_string_t_data(string)

Get a pointer to the string data of a string_t

# Arguments
- `string`: `Ref{duckdb_string_t}` The string to get the pointer to.

Returns: `Cstring` The pointer.
"""
function duckdb_string_t_data(string)
    return ccall((:duckdb_string_t_data, libduckdb), Cstring, (Ref{duckdb_string_t},), string)
end



# --------------------------------------------------------------------------------
# Date Time Timestamp Helpers
# --------------------------------------------------------------------------------

"""
    duckdb_from_date(date)

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

# Arguments
- `date`: `duckdb_date` The date object, as obtained from a `DUCKDB_TYPE_DATE` column.

Returns: `duckdb_date_struct` The `duckdb_date_struct` with the decomposed elements.
"""
function duckdb_from_date(date)
    return ccall((:duckdb_from_date, libduckdb), duckdb_date_struct, (duckdb_date,), date)
end

"""
    duckdb_to_date(date)

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

# Arguments
- `date`: `duckdb_date_struct` The year, month and date stored in a `duckdb_date_struct`.

Returns: `duckdb_date` The `duckdb_date` element.
"""
function duckdb_to_date(date)
    return ccall((:duckdb_to_date, libduckdb), duckdb_date, (duckdb_date_struct,), date)
end

"""
    duckdb_is_finite_date(date)

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

# Arguments
- `date`: `duckdb_date` The date object, as obtained from a `DUCKDB_TYPE_DATE` column.

Returns: `Bool` True if the date is finite, false if it is ±infinity.
"""
function duckdb_is_finite_date(date)
    return ccall((:duckdb_is_finite_date, libduckdb), Bool, (duckdb_date,), date)
end

"""
    duckdb_from_time(time)

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

# Arguments
- `time`: `duckdb_time` The time object, as obtained from a `DUCKDB_TYPE_TIME` column.

Returns: `duckdb_time_struct` The `duckdb_time_struct` with the decomposed elements.
"""
function duckdb_from_time(time)
    return ccall((:duckdb_from_time, libduckdb), duckdb_time_struct, (duckdb_time,), time)
end

"""
    duckdb_create_time_tz(micros, offset)

Create a `duckdb_time_tz` object from micros and a timezone offset.

# Arguments
- `micros`: `Int64` The microsecond component of the time.
- `offset`: `Int32` The timezone offset component of the time.

Returns: `duckdb_time_tz` The `duckdb_time_tz` element.
"""
function duckdb_create_time_tz(micros, offset)
    return ccall((:duckdb_create_time_tz, libduckdb), duckdb_time_tz, (Int64, Int32), micros, offset)
end

"""
    duckdb_from_time_tz(micros)

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.

# Arguments
- `micros`: `duckdb_time_tz` The time object, as obtained from a `DUCKDB_TYPE_TIME_TZ` column.

Returns: `duckdb_time_tz_struct` 
"""
function duckdb_from_time_tz(micros)
    return ccall((:duckdb_from_time_tz, libduckdb), duckdb_time_tz_struct, (duckdb_time_tz,), micros)
end

"""
    duckdb_to_time(time)

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

# Arguments
- `time`: `duckdb_time_struct` The hour, minute, second and microsecond in a `duckdb_time_struct`.

Returns: `duckdb_time` The `duckdb_time` element.
"""
function duckdb_to_time(time)
    return ccall((:duckdb_to_time, libduckdb), duckdb_time, (duckdb_time_struct,), time)
end

"""
    duckdb_from_timestamp(ts)

Decompose a `duckdb_timestamp` object into a `duckdb_timestamp_struct`.

# Arguments
- `ts`: `duckdb_timestamp` The ts object, as obtained from a `DUCKDB_TYPE_TIMESTAMP` column.

Returns: `duckdb_timestamp_struct` The `duckdb_timestamp_struct` with the decomposed elements.
"""
function duckdb_from_timestamp(ts)
    return ccall((:duckdb_from_timestamp, libduckdb), duckdb_timestamp_struct, (duckdb_timestamp,), ts)
end

"""
    duckdb_to_timestamp(ts)

Re-compose a `duckdb_timestamp` from a duckdb_timestamp_struct.

# Arguments
- `ts`: `duckdb_timestamp_struct` The de-composed elements in a `duckdb_timestamp_struct`.

Returns: `duckdb_timestamp` The `duckdb_timestamp` element.
"""
function duckdb_to_timestamp(ts)
    return ccall((:duckdb_to_timestamp, libduckdb), duckdb_timestamp, (duckdb_timestamp_struct,), ts)
end

"""
    duckdb_is_finite_timestamp(ts)

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

# Arguments
- `ts`: `duckdb_timestamp` The duckdb_timestamp object, as obtained from a `DUCKDB_TYPE_TIMESTAMP` column.

Returns: `Bool` True if the timestamp is finite, false if it is ±infinity.
"""
function duckdb_is_finite_timestamp(ts)
    return ccall((:duckdb_is_finite_timestamp, libduckdb), Bool, (duckdb_timestamp,), ts)
end

"""
    duckdb_is_finite_timestamp_s(ts)

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

# Arguments
- `ts`: `duckdb_timestamp_s` The duckdb_timestamp_s object, as obtained from a `DUCKDB_TYPE_TIMESTAMP_S` column.

Returns: `Bool` True if the timestamp is finite, false if it is ±infinity.
"""
function duckdb_is_finite_timestamp_s(ts)
    return ccall((:duckdb_is_finite_timestamp_s, libduckdb), Bool, (duckdb_timestamp_s,), ts)
end

"""
    duckdb_is_finite_timestamp_ms(ts)

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

# Arguments
- `ts`: `duckdb_timestamp_ms` The duckdb_timestamp_ms object, as obtained from a `DUCKDB_TYPE_TIMESTAMP_MS` column.

Returns: `Bool` True if the timestamp is finite, false if it is ±infinity.
"""
function duckdb_is_finite_timestamp_ms(ts)
    return ccall((:duckdb_is_finite_timestamp_ms, libduckdb), Bool, (duckdb_timestamp_ms,), ts)
end

"""
    duckdb_is_finite_timestamp_ns(ts)

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

# Arguments
- `ts`: `duckdb_timestamp_ns` The duckdb_timestamp_ns object, as obtained from a `DUCKDB_TYPE_TIMESTAMP_NS` column.

Returns: `Bool` True if the timestamp is finite, false if it is ±infinity.
"""
function duckdb_is_finite_timestamp_ns(ts)
    return ccall((:duckdb_is_finite_timestamp_ns, libduckdb), Bool, (duckdb_timestamp_ns,), ts)
end



# --------------------------------------------------------------------------------
# Hugeint Helpers
# --------------------------------------------------------------------------------

"""
    duckdb_hugeint_to_double(val)

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

# Arguments
- `val`: `duckdb_hugeint` The hugeint value.

Returns: `Float64` The converted `double` element.
"""
function duckdb_hugeint_to_double(val)
    return ccall((:duckdb_hugeint_to_double, libduckdb), Float64, (duckdb_hugeint,), val)
end

"""
    duckdb_double_to_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.

# Arguments
- `val`: `Float64` The double value.

Returns: `duckdb_hugeint` The converted `duckdb_hugeint` element.
"""
function duckdb_double_to_hugeint(val)
    return ccall((:duckdb_double_to_hugeint, libduckdb), duckdb_hugeint, (Float64,), val)
end



# --------------------------------------------------------------------------------
# Unsigned Hugeint Helpers
# --------------------------------------------------------------------------------

"""
    duckdb_uhugeint_to_double(val)

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

# Arguments
- `val`: `duckdb_uhugeint` The uhugeint value.

Returns: `Float64` The converted `double` element.
"""
function duckdb_uhugeint_to_double(val)
    return ccall((:duckdb_uhugeint_to_double, libduckdb), Float64, (duckdb_uhugeint,), val)
end

"""
    duckdb_double_to_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.

# Arguments
- `val`: `Float64` The double value.

Returns: `duckdb_uhugeint` The converted `duckdb_uhugeint` element.
"""
function duckdb_double_to_uhugeint(val)
    return ccall((:duckdb_double_to_uhugeint, libduckdb), duckdb_uhugeint, (Float64,), val)
end



# --------------------------------------------------------------------------------
# Decimal Helpers
# --------------------------------------------------------------------------------

"""
    duckdb_double_to_decimal(val, width, scale)

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.

# Arguments
- `val`: `Float64` The double value.
- `width`: `UInt8` 
- `scale`: `UInt8` 

Returns: `duckdb_decimal` The converted `duckdb_decimal` element.
"""
function duckdb_double_to_decimal(val, width, scale)
    return ccall((:duckdb_double_to_decimal, libduckdb), duckdb_decimal, (Float64, UInt8, UInt8), val, width, scale)
end

"""
    duckdb_decimal_to_double(val)

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

# Arguments
- `val`: `duckdb_decimal` The decimal value.

Returns: `Float64` The converted `double` element.
"""
function duckdb_decimal_to_double(val)
    return ccall((:duckdb_decimal_to_double, libduckdb), Float64, (duckdb_decimal,), val)
end



# --------------------------------------------------------------------------------
# Prepared Statements
# --------------------------------------------------------------------------------

"""
    duckdb_prepare(connection, query, out_prepared_statement)

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.

# Arguments
- `connection`: `duckdb_connection` The connection object
- `query`: `Cstring` The SQL query to prepare
- `out_prepared_statement`: `Ref{duckdb_prepared_statement}` The resulting prepared statement object

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_prepare(connection, query, out_prepared_statement)
    return ccall(
        (:duckdb_prepare, libduckdb),
        duckdb_state,
        (duckdb_connection, Cstring, Ref{duckdb_prepared_statement}),
        connection,
        query,
        out_prepared_statement
    )
end

"""
    duckdb_destroy_prepare(prepared_statement)

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

# Arguments
- `prepared_statement`: `Ref{duckdb_prepared_statement}` The prepared statement to destroy.

Returns: `Nothing` 
"""
function duckdb_destroy_prepare(prepared_statement)
    return ccall((:duckdb_destroy_prepare, libduckdb), Cvoid, (Ref{duckdb_prepared_statement},), prepared_statement)
end

"""
    duckdb_prepare_error(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.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` The prepared statement to obtain the error from.

Returns: `Cstring` The error message, or `nullptr` if there is none.
"""
function duckdb_prepare_error(prepared_statement)
    return ccall((:duckdb_prepare_error, libduckdb), Cstring, (duckdb_prepared_statement,), prepared_statement)
end

"""
    duckdb_nparams(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.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` The prepared statement to obtain the number of parameters for.

Returns: `idx_t` 
"""
function duckdb_nparams(prepared_statement)
    return ccall((:duckdb_nparams, libduckdb), idx_t, (duckdb_prepared_statement,), prepared_statement)
end

"""
    duckdb_parameter_name(prepared_statement, index)

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.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` The prepared statement for which to get the parameter name from.
- `index`: `idx_t` 

Returns: `Cstring` 
"""
function duckdb_parameter_name(prepared_statement, index)
    return ccall(
        (:duckdb_parameter_name, libduckdb),
        Cstring,
        (duckdb_prepared_statement, idx_t),
        prepared_statement,
        index
    )
end

"""
    duckdb_param_type(prepared_statement, param_idx)

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.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` The prepared statement.
- `param_idx`: `idx_t` The parameter index.

Returns: `DUCKDB_TYPE` The parameter type
"""
function duckdb_param_type(prepared_statement, param_idx)
    return ccall(
        (:duckdb_param_type, libduckdb),
        DUCKDB_TYPE,
        (duckdb_prepared_statement, idx_t),
        prepared_statement,
        param_idx
    )
end

"""
    duckdb_param_logical_type(prepared_statement, 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`.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` The prepared statement.
- `param_idx`: `idx_t` The parameter index.

Returns: `duckdb_logical_type` The logical type of the parameter
"""
function duckdb_param_logical_type(prepared_statement, param_idx)
    return ccall(
        (:duckdb_param_logical_type, libduckdb),
        duckdb_logical_type,
        (duckdb_prepared_statement, idx_t),
        prepared_statement,
        param_idx
    )
end

"""
    duckdb_clear_bindings(prepared_statement)

Clear the params bind to the prepared statement.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 

Returns: `duckdb_state` 
"""
function duckdb_clear_bindings(prepared_statement)
    return ccall((:duckdb_clear_bindings, libduckdb), duckdb_state, (duckdb_prepared_statement,), prepared_statement)
end

"""
    duckdb_prepared_statement_type(statement)

Returns the statement type of the statement to be executed

# Arguments
- `statement`: `duckdb_prepared_statement` The prepared statement.

Returns: `duckdb_statement_type` duckdb_statement_type value or DUCKDB_STATEMENT_TYPE_INVALID
"""
function duckdb_prepared_statement_type(statement)
    return ccall(
        (:duckdb_prepared_statement_type, libduckdb),
        duckdb_statement_type,
        (duckdb_prepared_statement,),
        statement
    )
end



# --------------------------------------------------------------------------------
# Bind Values To Prepared Statements
# --------------------------------------------------------------------------------

"""
    duckdb_bind_value(prepared_statement, param_idx, val)

Binds a value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `duckdb_value` 

Returns: `duckdb_state` 
"""
function duckdb_bind_value(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_value, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, duckdb_value),
        prepared_statement,
        param_idx,
        val
    )
end

"""
    duckdb_bind_parameter_index(prepared_statement, param_idx_out, name)

Retrieve the index of the parameter for the prepared statement, identified by name

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx_out`: `Ref{idx_t}` 
- `name`: `Cstring` 

Returns: `duckdb_state` 
"""
function duckdb_bind_parameter_index(prepared_statement, param_idx_out, name)
    return ccall(
        (:duckdb_bind_parameter_index, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, Ref{idx_t}, Cstring),
        prepared_statement,
        param_idx_out,
        name
    )
end

"""
    duckdb_bind_boolean(prepared_statement, param_idx, val)

Binds a bool value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `Bool` 

Returns: `duckdb_state` 
"""
function duckdb_bind_boolean(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_boolean, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, Bool),
        prepared_statement,
        param_idx,
        val
    )
end

"""
    duckdb_bind_int8(prepared_statement, param_idx, val)

Binds an int8_t value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `Int8` 

Returns: `duckdb_state` 
"""
function duckdb_bind_int8(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_int8, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, Int8),
        prepared_statement,
        param_idx,
        val
    )
end

"""
    duckdb_bind_int16(prepared_statement, param_idx, val)

Binds an int16_t value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `Int16` 

Returns: `duckdb_state` 
"""
function duckdb_bind_int16(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_int16, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, Int16),
        prepared_statement,
        param_idx,
        val
    )
end

"""
    duckdb_bind_int32(prepared_statement, param_idx, val)

Binds an int32_t value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `Int32` 

Returns: `duckdb_state` 
"""
function duckdb_bind_int32(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_int32, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, Int32),
        prepared_statement,
        param_idx,
        val
    )
end

"""
    duckdb_bind_int64(prepared_statement, param_idx, val)

Binds an int64_t value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `Int64` 

Returns: `duckdb_state` 
"""
function duckdb_bind_int64(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_int64, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, Int64),
        prepared_statement,
        param_idx,
        val
    )
end

"""
    duckdb_bind_hugeint(prepared_statement, param_idx, val)

Binds a duckdb_hugeint value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `duckdb_hugeint` 

Returns: `duckdb_state` 
"""
function duckdb_bind_hugeint(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_hugeint, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, duckdb_hugeint),
        prepared_statement,
        param_idx,
        val
    )
end

"""
    duckdb_bind_uhugeint(prepared_statement, param_idx, val)

Binds a duckdb_uhugeint value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `duckdb_uhugeint` 

Returns: `duckdb_state` 
"""
function duckdb_bind_uhugeint(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_uhugeint, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, duckdb_uhugeint),
        prepared_statement,
        param_idx,
        val
    )
end

"""
    duckdb_bind_decimal(prepared_statement, param_idx, val)

Binds a duckdb_decimal value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `duckdb_decimal` 

Returns: `duckdb_state` 
"""
function duckdb_bind_decimal(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_decimal, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, duckdb_decimal),
        prepared_statement,
        param_idx,
        val
    )
end

"""
    duckdb_bind_uint8(prepared_statement, param_idx, val)

Binds a uint8_t value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `UInt8` 

Returns: `duckdb_state` 
"""
function duckdb_bind_uint8(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_uint8, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, UInt8),
        prepared_statement,
        param_idx,
        val
    )
end

"""
    duckdb_bind_uint16(prepared_statement, param_idx, val)

Binds a uint16_t value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `UInt16` 

Returns: `duckdb_state` 
"""
function duckdb_bind_uint16(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_uint16, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, UInt16),
        prepared_statement,
        param_idx,
        val
    )
end

"""
    duckdb_bind_uint32(prepared_statement, param_idx, val)

Binds a uint32_t value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `UInt32` 

Returns: `duckdb_state` 
"""
function duckdb_bind_uint32(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_uint32, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, UInt32),
        prepared_statement,
        param_idx,
        val
    )
end

"""
    duckdb_bind_uint64(prepared_statement, param_idx, val)

Binds a uint64_t value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `UInt64` 

Returns: `duckdb_state` 
"""
function duckdb_bind_uint64(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_uint64, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, UInt64),
        prepared_statement,
        param_idx,
        val
    )
end

"""
    duckdb_bind_float(prepared_statement, param_idx, val)

Binds a float value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `Float32` 

Returns: `duckdb_state` 
"""
function duckdb_bind_float(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_float, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, Float32),
        prepared_statement,
        param_idx,
        val
    )
end

"""
    duckdb_bind_double(prepared_statement, param_idx, val)

Binds a double value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `Float64` 

Returns: `duckdb_state` 
"""
function duckdb_bind_double(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_double, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, Float64),
        prepared_statement,
        param_idx,
        val
    )
end

"""
    duckdb_bind_date(prepared_statement, param_idx, val)

Binds a duckdb_date value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `duckdb_date` 

Returns: `duckdb_state` 
"""
function duckdb_bind_date(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_date, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, duckdb_date),
        prepared_statement,
        param_idx,
        val
    )
end

"""
    duckdb_bind_time(prepared_statement, param_idx, val)

Binds a duckdb_time value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `duckdb_time` 

Returns: `duckdb_state` 
"""
function duckdb_bind_time(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_time, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, duckdb_time),
        prepared_statement,
        param_idx,
        val
    )
end

"""
    duckdb_bind_timestamp(prepared_statement, param_idx, val)

Binds a duckdb_timestamp value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `duckdb_timestamp` 

Returns: `duckdb_state` 
"""
function duckdb_bind_timestamp(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_timestamp, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, duckdb_timestamp),
        prepared_statement,
        param_idx,
        val
    )
end

"""
    duckdb_bind_timestamp_tz(prepared_statement, param_idx, val)

Binds a duckdb_timestamp value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `duckdb_timestamp` 

Returns: `duckdb_state` 
"""
function duckdb_bind_timestamp_tz(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_timestamp_tz, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, duckdb_timestamp),
        prepared_statement,
        param_idx,
        val
    )
end

"""
    duckdb_bind_interval(prepared_statement, param_idx, val)

Binds a duckdb_interval value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `duckdb_interval` 

Returns: `duckdb_state` 
"""
function duckdb_bind_interval(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_interval, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, duckdb_interval),
        prepared_statement,
        param_idx,
        val
    )
end

"""
    duckdb_bind_varchar(prepared_statement, param_idx, val)

Binds a null-terminated varchar value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `Cstring` 

Returns: `duckdb_state` 
"""
function duckdb_bind_varchar(prepared_statement, param_idx, val)
    return ccall(
        (:duckdb_bind_varchar, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, Cstring),
        prepared_statement,
        param_idx,
        val
    )
end

"""
    duckdb_bind_varchar_length(prepared_statement, param_idx, val, length)

Binds a varchar value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `val`: `Cstring` 
- `length`: `idx_t` 

Returns: `duckdb_state` 
"""
function duckdb_bind_varchar_length(prepared_statement, param_idx, val, length)
    return ccall(
        (:duckdb_bind_varchar_length, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, Cstring, idx_t),
        prepared_statement,
        param_idx,
        val,
        length
    )
end

"""
    duckdb_bind_blob(prepared_statement, param_idx, data, length)

Binds a blob value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 
- `data`: `Ptr{Cvoid}` 
- `length`: `idx_t` 

Returns: `duckdb_state` 
"""
function duckdb_bind_blob(prepared_statement, param_idx, data, length)
    return ccall(
        (:duckdb_bind_blob, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t, Ptr{Cvoid}, idx_t),
        prepared_statement,
        param_idx,
        data,
        length
    )
end

"""
    duckdb_bind_null(prepared_statement, param_idx)

Binds a NULL value to the prepared statement at the specified index.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` 
- `param_idx`: `idx_t` 

Returns: `duckdb_state` 
"""
function duckdb_bind_null(prepared_statement, param_idx)
    return ccall(
        (:duckdb_bind_null, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, idx_t),
        prepared_statement,
        param_idx
    )
end



# --------------------------------------------------------------------------------
# Execute Prepared Statements
# --------------------------------------------------------------------------------

"""
    duckdb_execute_prepared(prepared_statement, out_result)

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`.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` The prepared statement to execute.
- `out_result`: `Ref{duckdb_result}` The query result.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_execute_prepared(prepared_statement, out_result)
    return ccall(
        (:duckdb_execute_prepared, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, Ref{duckdb_result}),
        prepared_statement,
        out_result
    )
end

"""
    duckdb_execute_prepared_streaming(prepared_statement, out_result)

**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`.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` The prepared statement to execute.
- `out_result`: `Ref{duckdb_result}` The query result.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_execute_prepared_streaming(prepared_statement, out_result)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_execute_prepared_streaming
    )
    return ccall(
        (:duckdb_execute_prepared_streaming, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, Ref{duckdb_result}),
        prepared_statement,
        out_result
    )
end



# --------------------------------------------------------------------------------
# Extract Statements
# --------------------------------------------------------------------------------

"""
    duckdb_extract_statements(connection, query, out_extracted_statements)

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.

# Arguments
- `connection`: `duckdb_connection` The connection object
- `query`: `Cstring` The SQL query to extract
- `out_extracted_statements`: `Ref{duckdb_extracted_statements}` The resulting extracted statements object

Returns: `idx_t` The number of extracted statements or 0 on failure.
"""
function duckdb_extract_statements(connection, query, out_extracted_statements)
    return ccall(
        (:duckdb_extract_statements, libduckdb),
        idx_t,
        (duckdb_connection, Cstring, Ref{duckdb_extracted_statements}),
        connection,
        query,
        out_extracted_statements
    )
end

"""
    duckdb_prepare_extracted_statement(connection, extracted_statements, index, out_prepared_statement)

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.

# Arguments
- `connection`: `duckdb_connection` The connection object
- `extracted_statements`: `duckdb_extracted_statements` The extracted statements object
- `index`: `idx_t` (1-based index) The index of the extracted statement to prepare
- `out_prepared_statement`: `Ref{duckdb_prepared_statement}` The resulting prepared statement object

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_prepare_extracted_statement(connection, extracted_statements, index, out_prepared_statement)
    return ccall(
        (:duckdb_prepare_extracted_statement, libduckdb),
        duckdb_state,
        (duckdb_connection, duckdb_extracted_statements, idx_t, Ref{duckdb_prepared_statement}),
        connection,
        extracted_statements,
        index - 1,
        out_prepared_statement
    )
end

"""
    duckdb_extract_statements_error(extracted_statements)

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.

# Arguments
- `extracted_statements`: `duckdb_extracted_statements` The extracted statements to fetch the error from.

Returns: `Cstring` The error of the extracted statements.
"""
function duckdb_extract_statements_error(extracted_statements)
    return ccall(
        (:duckdb_extract_statements_error, libduckdb),
        Cstring,
        (duckdb_extracted_statements,),
        extracted_statements
    )
end

"""
    duckdb_destroy_extracted(extracted_statements)

De-allocates all memory allocated for the extracted statements.

# Arguments
- `extracted_statements`: `Ref{duckdb_extracted_statements}` The extracted statements to destroy.

Returns: `Nothing` 
"""
function duckdb_destroy_extracted(extracted_statements)
    return ccall(
        (:duckdb_destroy_extracted, libduckdb),
        Cvoid,
        (Ref{duckdb_extracted_statements},),
        extracted_statements
    )
end



# --------------------------------------------------------------------------------
# Pending Result Interface
# --------------------------------------------------------------------------------

"""
    duckdb_pending_prepared(prepared_statement, out_result)

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.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` The prepared statement to execute.
- `out_result`: `Ref{duckdb_pending_result}` The pending query result.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_pending_prepared(prepared_statement, out_result)
    return ccall(
        (:duckdb_pending_prepared, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, Ref{duckdb_pending_result}),
        prepared_statement,
        out_result
    )
end

"""
    duckdb_pending_prepared_streaming(prepared_statement, out_result)

**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.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` The prepared statement to execute.
- `out_result`: `Ref{duckdb_pending_result}` The pending query result.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_pending_prepared_streaming(prepared_statement, out_result)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_pending_prepared_streaming
    )
    return ccall(
        (:duckdb_pending_prepared_streaming, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, Ref{duckdb_pending_result}),
        prepared_statement,
        out_result
    )
end

"""
    duckdb_destroy_pending(pending_result)

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

# Arguments
- `pending_result`: `Ref{duckdb_pending_result}` The pending result to destroy.

Returns: `Nothing` 
"""
function duckdb_destroy_pending(pending_result)
    return ccall((:duckdb_destroy_pending, libduckdb), Cvoid, (Ref{duckdb_pending_result},), pending_result)
end

"""
    duckdb_pending_error(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.

# Arguments
- `pending_result`: `duckdb_pending_result` The pending result to fetch the error from.

Returns: `Cstring` The error of the pending result.
"""
function duckdb_pending_error(pending_result)
    return ccall((:duckdb_pending_error, libduckdb), Cstring, (duckdb_pending_result,), pending_result)
end

"""
    duckdb_pending_execute_task(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.

# Arguments
- `pending_result`: `duckdb_pending_result` The pending result to execute a task within.

Returns: `duckdb_pending_state` The state of the pending result after the execution.
"""
function duckdb_pending_execute_task(pending_result)
    return ccall(
        (:duckdb_pending_execute_task, libduckdb),
        duckdb_pending_state,
        (duckdb_pending_result,),
        pending_result
    )
end

"""
    duckdb_pending_execute_check_state(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.

# Arguments
- `pending_result`: `duckdb_pending_result` The pending result.

Returns: `duckdb_pending_state` The state of the pending result.
"""
function duckdb_pending_execute_check_state(pending_result)
    return ccall(
        (:duckdb_pending_execute_check_state, libduckdb),
        duckdb_pending_state,
        (duckdb_pending_result,),
        pending_result
    )
end

"""
    duckdb_execute_pending(pending_result, out_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`.

# Arguments
- `pending_result`: `duckdb_pending_result` The pending result to execute.
- `out_result`: `Ref{duckdb_result}` The result object.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_execute_pending(pending_result, out_result)
    return ccall(
        (:duckdb_execute_pending, libduckdb),
        duckdb_state,
        (duckdb_pending_result, Ref{duckdb_result}),
        pending_result,
        out_result
    )
end

"""
    duckdb_pending_execution_is_finished(pending_state)

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

# Arguments
- `pending_state`: `duckdb_pending_state` The pending state on which to decide whether to finish execution.

Returns: `Bool` Boolean indicating pending execution should be considered finished.
"""
function duckdb_pending_execution_is_finished(pending_state)
    return ccall((:duckdb_pending_execution_is_finished, libduckdb), Bool, (duckdb_pending_state,), pending_state)
end



# --------------------------------------------------------------------------------
# Value Interface
# --------------------------------------------------------------------------------

"""
    duckdb_destroy_value(value)

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

# Arguments
- `value`: `Ref{duckdb_value}` The value to destroy.

Returns: `Nothing` 
"""
function duckdb_destroy_value(value)
    return ccall((:duckdb_destroy_value, libduckdb), Cvoid, (Ref{duckdb_value},), value)
end

"""
    duckdb_create_varchar(text)

Creates a value from a null-terminated string

# Arguments
- `text`: `Cstring` The null-terminated string

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_varchar(text)
    return ccall((:duckdb_create_varchar, libduckdb), duckdb_value, (Cstring,), text)
end

"""
    duckdb_create_varchar_length(text, length)

Creates a value from a string

# Arguments
- `text`: `Cstring` The text
- `length`: `idx_t` The length of the text

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_varchar_length(text, length)
    return ccall((:duckdb_create_varchar_length, libduckdb), duckdb_value, (Cstring, idx_t), text, length)
end

"""
    duckdb_create_bool(input)

Creates a value from a boolean

# Arguments
- `input`: `Bool` The boolean value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_bool(input)
    return ccall((:duckdb_create_bool, libduckdb), duckdb_value, (Bool,), input)
end

"""
    duckdb_create_int8(input)

Creates a value from an int8_t (a tinyint)

# Arguments
- `input`: `Int8` The tinyint value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_int8(input)
    return ccall((:duckdb_create_int8, libduckdb), duckdb_value, (Int8,), input)
end

"""
    duckdb_create_uint8(input)

Creates a value from a uint8_t (a utinyint)

# Arguments
- `input`: `UInt8` The utinyint value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_uint8(input)
    return ccall((:duckdb_create_uint8, libduckdb), duckdb_value, (UInt8,), input)
end

"""
    duckdb_create_int16(input)

Creates a value from an int16_t (a smallint)

# Arguments
- `input`: `Int16` The smallint value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_int16(input)
    return ccall((:duckdb_create_int16, libduckdb), duckdb_value, (Int16,), input)
end

"""
    duckdb_create_uint16(input)

Creates a value from a uint16_t (a usmallint)

# Arguments
- `input`: `UInt16` The usmallint value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_uint16(input)
    return ccall((:duckdb_create_uint16, libduckdb), duckdb_value, (UInt16,), input)
end

"""
    duckdb_create_int32(input)

Creates a value from an int32_t (an integer)

# Arguments
- `input`: `Int32` The integer value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_int32(input)
    return ccall((:duckdb_create_int32, libduckdb), duckdb_value, (Int32,), input)
end

"""
    duckdb_create_uint32(input)

Creates a value from a uint32_t (a uinteger)

# Arguments
- `input`: `UInt32` The uinteger value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_uint32(input)
    return ccall((:duckdb_create_uint32, libduckdb), duckdb_value, (UInt32,), input)
end

"""
    duckdb_create_uint64(input)

Creates a value from a uint64_t (a ubigint)

# Arguments
- `input`: `UInt64` The ubigint value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_uint64(input)
    return ccall((:duckdb_create_uint64, libduckdb), duckdb_value, (UInt64,), input)
end

"""
    duckdb_create_int64(val)

Creates a value from an int64

# Arguments
- `val`: `Int64` 

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_int64(val)
    return ccall((:duckdb_create_int64, libduckdb), duckdb_value, (Int64,), val)
end

"""
    duckdb_create_hugeint(input)

Creates a value from a hugeint

# Arguments
- `input`: `duckdb_hugeint` The hugeint value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_hugeint(input)
    return ccall((:duckdb_create_hugeint, libduckdb), duckdb_value, (duckdb_hugeint,), input)
end

"""
    duckdb_create_uhugeint(input)

Creates a value from a uhugeint

# Arguments
- `input`: `duckdb_uhugeint` The uhugeint value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_uhugeint(input)
    return ccall((:duckdb_create_uhugeint, libduckdb), duckdb_value, (duckdb_uhugeint,), input)
end

"""
    duckdb_create_bignum(input)

Creates a BIGNUM value from a duckdb_bignum

# Arguments
- `input`: `duckdb_bignum` The duckdb_bignum value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_bignum(input)
    return ccall((:duckdb_create_bignum, libduckdb), duckdb_value, (duckdb_bignum,), input)
end

"""
    duckdb_create_decimal(input)

Creates a DECIMAL value from a duckdb_decimal

# Arguments
- `input`: `duckdb_decimal` The duckdb_decimal value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_decimal(input)
    return ccall((:duckdb_create_decimal, libduckdb), duckdb_value, (duckdb_decimal,), input)
end

"""
    duckdb_create_float(input)

Creates a value from a float

# Arguments
- `input`: `Float32` The float value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_float(input)
    return ccall((:duckdb_create_float, libduckdb), duckdb_value, (Float32,), input)
end

"""
    duckdb_create_double(input)

Creates a value from a double

# Arguments
- `input`: `Float64` The double value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_double(input)
    return ccall((:duckdb_create_double, libduckdb), duckdb_value, (Float64,), input)
end

"""
    duckdb_create_date(input)

Creates a value from a date

# Arguments
- `input`: `duckdb_date` The date value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_date(input)
    return ccall((:duckdb_create_date, libduckdb), duckdb_value, (duckdb_date,), input)
end

"""
    duckdb_create_time(input)

Creates a value from a time

# Arguments
- `input`: `duckdb_time` The time value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_time(input)
    return ccall((:duckdb_create_time, libduckdb), duckdb_value, (duckdb_time,), input)
end

"""
    duckdb_create_time_tz_value(value)

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

# Arguments
- `value`: `duckdb_time_tz` The time_tz value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_time_tz_value(value)
    return ccall((:duckdb_create_time_tz_value, libduckdb), duckdb_value, (duckdb_time_tz,), value)
end

"""
    duckdb_create_timestamp(input)

Creates a TIMESTAMP value from a duckdb_timestamp

# Arguments
- `input`: `duckdb_timestamp` The duckdb_timestamp value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_timestamp(input)
    return ccall((:duckdb_create_timestamp, libduckdb), duckdb_value, (duckdb_timestamp,), input)
end

"""
    duckdb_create_timestamp_tz(input)

Creates a TIMESTAMP_TZ value from a duckdb_timestamp

# Arguments
- `input`: `duckdb_timestamp` The duckdb_timestamp value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_timestamp_tz(input)
    return ccall((:duckdb_create_timestamp_tz, libduckdb), duckdb_value, (duckdb_timestamp,), input)
end

"""
    duckdb_create_timestamp_s(input)

Creates a TIMESTAMP_S value from a duckdb_timestamp_s

# Arguments
- `input`: `duckdb_timestamp_s` The duckdb_timestamp_s value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_timestamp_s(input)
    return ccall((:duckdb_create_timestamp_s, libduckdb), duckdb_value, (duckdb_timestamp_s,), input)
end

"""
    duckdb_create_timestamp_ms(input)

Creates a TIMESTAMP_MS value from a duckdb_timestamp_ms

# Arguments
- `input`: `duckdb_timestamp_ms` The duckdb_timestamp_ms value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_timestamp_ms(input)
    return ccall((:duckdb_create_timestamp_ms, libduckdb), duckdb_value, (duckdb_timestamp_ms,), input)
end

"""
    duckdb_create_timestamp_ns(input)

Creates a TIMESTAMP_NS value from a duckdb_timestamp_ns

# Arguments
- `input`: `duckdb_timestamp_ns` The duckdb_timestamp_ns value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_timestamp_ns(input)
    return ccall((:duckdb_create_timestamp_ns, libduckdb), duckdb_value, (duckdb_timestamp_ns,), input)
end

"""
    duckdb_create_interval(input)

Creates a value from an interval

# Arguments
- `input`: `duckdb_interval` The interval value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_interval(input)
    return ccall((:duckdb_create_interval, libduckdb), duckdb_value, (duckdb_interval,), input)
end

"""
    duckdb_create_blob(data, length)

Creates a value from a blob

# Arguments
- `data`: `Ref{UInt8}` The blob data
- `length`: `idx_t` The length of the blob data

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_blob(data, length)
    return ccall((:duckdb_create_blob, libduckdb), duckdb_value, (Ref{UInt8}, idx_t), data, length)
end

"""
    duckdb_create_bit(input)

Creates a BIT value from a duckdb_bit

# Arguments
- `input`: `duckdb_bit` The duckdb_bit value

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_bit(input)
    return ccall((:duckdb_create_bit, libduckdb), duckdb_value, (duckdb_bit,), input)
end

"""
    duckdb_create_uuid(input)

Creates a UUID value from a uhugeint

# Arguments
- `input`: `duckdb_uhugeint` The duckdb_uhugeint containing the UUID

Returns: `duckdb_value` The value. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_uuid(input)
    return ccall((:duckdb_create_uuid, libduckdb), duckdb_value, (duckdb_uhugeint,), input)
end

"""
    duckdb_get_bool(val)

Returns the boolean value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a boolean

Returns: `Bool` A boolean, or false if the value cannot be converted
"""
function duckdb_get_bool(val)
    return ccall((:duckdb_get_bool, libduckdb), Bool, (duckdb_value,), val)
end

"""
    duckdb_get_int8(val)

Returns the int8_t value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a tinyint

Returns: `Int8` A int8_t, or MinValue<int8> if the value cannot be converted
"""
function duckdb_get_int8(val)
    return ccall((:duckdb_get_int8, libduckdb), Int8, (duckdb_value,), val)
end

"""
    duckdb_get_uint8(val)

Returns the uint8_t value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a utinyint

Returns: `UInt8` A uint8_t, or MinValue<uint8> if the value cannot be converted
"""
function duckdb_get_uint8(val)
    return ccall((:duckdb_get_uint8, libduckdb), UInt8, (duckdb_value,), val)
end

"""
    duckdb_get_int16(val)

Returns the int16_t value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a smallint

Returns: `Int16` A int16_t, or MinValue<int16> if the value cannot be converted
"""
function duckdb_get_int16(val)
    return ccall((:duckdb_get_int16, libduckdb), Int16, (duckdb_value,), val)
end

"""
    duckdb_get_uint16(val)

Returns the uint16_t value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a usmallint

Returns: `UInt16` A uint16_t, or MinValue<uint16> if the value cannot be converted
"""
function duckdb_get_uint16(val)
    return ccall((:duckdb_get_uint16, libduckdb), UInt16, (duckdb_value,), val)
end

"""
    duckdb_get_int32(val)

Returns the int32_t value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing an integer

Returns: `Int32` A int32_t, or MinValue<int32> if the value cannot be converted
"""
function duckdb_get_int32(val)
    return ccall((:duckdb_get_int32, libduckdb), Int32, (duckdb_value,), val)
end

"""
    duckdb_get_uint32(val)

Returns the uint32_t value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a uinteger

Returns: `UInt32` A uint32_t, or MinValue<uint32> if the value cannot be converted
"""
function duckdb_get_uint32(val)
    return ccall((:duckdb_get_uint32, libduckdb), UInt32, (duckdb_value,), val)
end

"""
    duckdb_get_int64(val)

Returns the int64_t value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a bigint

Returns: `Int64` A int64_t, or MinValue<int64> if the value cannot be converted
"""
function duckdb_get_int64(val)
    return ccall((:duckdb_get_int64, libduckdb), Int64, (duckdb_value,), val)
end

"""
    duckdb_get_uint64(val)

Returns the uint64_t value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a ubigint

Returns: `UInt64` A uint64_t, or MinValue<uint64> if the value cannot be converted
"""
function duckdb_get_uint64(val)
    return ccall((:duckdb_get_uint64, libduckdb), UInt64, (duckdb_value,), val)
end

"""
    duckdb_get_hugeint(val)

Returns the hugeint value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a hugeint

Returns: `duckdb_hugeint` A duckdb_hugeint, or MinValue<hugeint> if the value cannot be converted
"""
function duckdb_get_hugeint(val)
    return ccall((:duckdb_get_hugeint, libduckdb), duckdb_hugeint, (duckdb_value,), val)
end

"""
    duckdb_get_uhugeint(val)

Returns the uhugeint value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a uhugeint

Returns: `duckdb_uhugeint` A duckdb_uhugeint, or MinValue<uhugeint> if the value cannot be converted
"""
function duckdb_get_uhugeint(val)
    return ccall((:duckdb_get_uhugeint, libduckdb), duckdb_uhugeint, (duckdb_value,), val)
end

"""
    duckdb_get_bignum(val)

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

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a BIGNUM

Returns: `duckdb_bignum` A duckdb_bignum. The `data` field must be destroyed with `duckdb_free`.
"""
function duckdb_get_bignum(val)
    return ccall((:duckdb_get_bignum, libduckdb), duckdb_bignum, (duckdb_value,), val)
end

"""
    duckdb_get_decimal(val)

Returns the duckdb_decimal value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a DECIMAL

Returns: `duckdb_decimal` A duckdb_decimal, or MinValue<decimal> if the value cannot be converted
"""
function duckdb_get_decimal(val)
    return ccall((:duckdb_get_decimal, libduckdb), duckdb_decimal, (duckdb_value,), val)
end

"""
    duckdb_get_float(val)

Returns the float value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a float

Returns: `Float32` A float, or NAN if the value cannot be converted
"""
function duckdb_get_float(val)
    return ccall((:duckdb_get_float, libduckdb), Float32, (duckdb_value,), val)
end

"""
    duckdb_get_double(val)

Returns the double value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a double

Returns: `Float64` A double, or NAN if the value cannot be converted
"""
function duckdb_get_double(val)
    return ccall((:duckdb_get_double, libduckdb), Float64, (duckdb_value,), val)
end

"""
    duckdb_get_date(val)

Returns the date value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a date

Returns: `duckdb_date` A duckdb_date, or MinValue<date> if the value cannot be converted
"""
function duckdb_get_date(val)
    return ccall((:duckdb_get_date, libduckdb), duckdb_date, (duckdb_value,), val)
end

"""
    duckdb_get_time(val)

Returns the time value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a time

Returns: `duckdb_time` A duckdb_time, or MinValue<time> if the value cannot be converted
"""
function duckdb_get_time(val)
    return ccall((:duckdb_get_time, libduckdb), duckdb_time, (duckdb_value,), val)
end

"""
    duckdb_get_time_tz(val)

Returns the time_tz value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a time_tz

Returns: `duckdb_time_tz` A duckdb_time_tz, or MinValue<time_tz> if the value cannot be converted
"""
function duckdb_get_time_tz(val)
    return ccall((:duckdb_get_time_tz, libduckdb), duckdb_time_tz, (duckdb_value,), val)
end

"""
    duckdb_get_timestamp(val)

Returns the TIMESTAMP value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a TIMESTAMP

Returns: `duckdb_timestamp` A duckdb_timestamp, or MinValue<timestamp> if the value cannot be converted
"""
function duckdb_get_timestamp(val)
    return ccall((:duckdb_get_timestamp, libduckdb), duckdb_timestamp, (duckdb_value,), val)
end

"""
    duckdb_get_timestamp_tz(val)

Returns the TIMESTAMP_TZ value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a TIMESTAMP_TZ

Returns: `duckdb_timestamp` A duckdb_timestamp, or MinValue<timestamp_tz> if the value cannot be converted
"""
function duckdb_get_timestamp_tz(val)
    return ccall((:duckdb_get_timestamp_tz, libduckdb), duckdb_timestamp, (duckdb_value,), val)
end

"""
    duckdb_get_timestamp_s(val)

Returns the duckdb_timestamp_s value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a TIMESTAMP_S

Returns: `duckdb_timestamp_s` A duckdb_timestamp_s, or MinValue<timestamp_s> if the value cannot be converted
"""
function duckdb_get_timestamp_s(val)
    return ccall((:duckdb_get_timestamp_s, libduckdb), duckdb_timestamp_s, (duckdb_value,), val)
end

"""
    duckdb_get_timestamp_ms(val)

Returns the duckdb_timestamp_ms value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a TIMESTAMP_MS

Returns: `duckdb_timestamp_ms` A duckdb_timestamp_ms, or MinValue<timestamp_ms> if the value cannot be converted
"""
function duckdb_get_timestamp_ms(val)
    return ccall((:duckdb_get_timestamp_ms, libduckdb), duckdb_timestamp_ms, (duckdb_value,), val)
end

"""
    duckdb_get_timestamp_ns(val)

Returns the duckdb_timestamp_ns value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a TIMESTAMP_NS

Returns: `duckdb_timestamp_ns` A duckdb_timestamp_ns, or MinValue<timestamp_ns> if the value cannot be converted
"""
function duckdb_get_timestamp_ns(val)
    return ccall((:duckdb_get_timestamp_ns, libduckdb), duckdb_timestamp_ns, (duckdb_value,), val)
end

"""
    duckdb_get_interval(val)

Returns the interval value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a interval

Returns: `duckdb_interval` A duckdb_interval, or MinValue<interval> if the value cannot be converted
"""
function duckdb_get_interval(val)
    return ccall((:duckdb_get_interval, libduckdb), duckdb_interval, (duckdb_value,), val)
end

"""
    duckdb_get_value_type(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.

# Arguments
- `val`: `duckdb_value` A duckdb_value

Returns: `duckdb_logical_type` A duckdb_logical_type.
"""
function duckdb_get_value_type(val)
    return ccall((:duckdb_get_value_type, libduckdb), duckdb_logical_type, (duckdb_value,), val)
end

"""
    duckdb_get_blob(val)

Returns the blob value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a blob

Returns: `duckdb_blob` A duckdb_blob
"""
function duckdb_get_blob(val)
    return ccall((:duckdb_get_blob, libduckdb), duckdb_blob, (duckdb_value,), val)
end

"""
    duckdb_get_bit(val)

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

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a BIT

Returns: `duckdb_bit` A duckdb_bit
"""
function duckdb_get_bit(val)
    return ccall((:duckdb_get_bit, libduckdb), duckdb_bit, (duckdb_value,), val)
end

"""
    duckdb_get_uuid(val)

Returns a duckdb_uhugeint representing the UUID value of the given value.

# Arguments
- `val`: `duckdb_value` A duckdb_value containing a UUID

Returns: `duckdb_uhugeint` A duckdb_uhugeint representing the UUID value
"""
function duckdb_get_uuid(val)
    return ccall((:duckdb_get_uuid, libduckdb), duckdb_uhugeint, (duckdb_value,), val)
end

"""
    duckdb_get_varchar(value)

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

# Arguments
- `value`: `duckdb_value` The value

Returns: `Cstring` The string value. This must be destroyed with `duckdb_free`.
"""
function duckdb_get_varchar(value)
    return ccall((:duckdb_get_varchar, libduckdb), Cstring, (duckdb_value,), value)
end

"""
    duckdb_create_struct_value(_type, values)

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

# Arguments
- `_type`: `duckdb_logical_type` The type of the struct
- `values`: `Ref{duckdb_value}` The values for the struct fields

Returns: `duckdb_value` The struct value, or nullptr, if any child type is `DUCKDB_TYPE_ANY` or `DUCKDB_TYPE_INVALID`.
"""
function duckdb_create_struct_value(_type, values)
    return ccall(
        (:duckdb_create_struct_value, libduckdb),
        duckdb_value,
        (duckdb_logical_type, Ref{duckdb_value}),
        _type,
        values
    )
end

"""
    duckdb_create_list_value(_type, values, value_count)

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`.

# Arguments
- `_type`: `duckdb_logical_type` The type of the list
- `values`: `Ref{duckdb_value}` The values for the list
- `value_count`: `idx_t` The number of values in the list

Returns: `duckdb_value` The list value, or nullptr, if the child type is `DUCKDB_TYPE_ANY` or `DUCKDB_TYPE_INVALID`.
"""
function duckdb_create_list_value(_type, values, value_count)
    return ccall(
        (:duckdb_create_list_value, libduckdb),
        duckdb_value,
        (duckdb_logical_type, Ref{duckdb_value}, idx_t),
        _type,
        values,
        value_count
    )
end

"""
    duckdb_create_array_value(_type, values, 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`.

# Arguments
- `_type`: `duckdb_logical_type` The type of the array
- `values`: `Ref{duckdb_value}` The values for the array
- `value_count`: `idx_t` The number of values in the array

Returns: `duckdb_value` The array value, or nullptr, if the child type is `DUCKDB_TYPE_ANY` or `DUCKDB_TYPE_INVALID`.
"""
function duckdb_create_array_value(_type, values, value_count)
    return ccall(
        (:duckdb_create_array_value, libduckdb),
        duckdb_value,
        (duckdb_logical_type, Ref{duckdb_value}, idx_t),
        _type,
        values,
        value_count
    )
end

"""
    duckdb_create_map_value(map_type, keys, values, entry_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`.

# Arguments
- `map_type`: `duckdb_logical_type` The map type
- `keys`: `Ref{duckdb_value}` The keys of the map
- `values`: `Ref{duckdb_value}` The values of the map
- `entry_count`: `idx_t` The number of entrys (key-value pairs) in the map

Returns: `duckdb_value` The map value, or nullptr, if the parameters are invalid.
"""
function duckdb_create_map_value(map_type, keys, values, entry_count)
    return ccall(
        (:duckdb_create_map_value, libduckdb),
        duckdb_value,
        (duckdb_logical_type, Ref{duckdb_value}, Ref{duckdb_value}, idx_t),
        map_type,
        keys,
        values,
        entry_count
    )
end

"""
    duckdb_create_union_value(union_type, tag_index, value)

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

# Arguments
- `union_type`: `duckdb_logical_type` The union type
- `tag_index`: `idx_t` The index of the tag of the union
- `value`: `duckdb_value` The value of the union for that tag

Returns: `duckdb_value` The union value, or nullptr, if the parameters are invalid.
"""
function duckdb_create_union_value(union_type, tag_index, value)
    return ccall(
        (:duckdb_create_union_value, libduckdb),
        duckdb_value,
        (duckdb_logical_type, idx_t, duckdb_value),
        union_type,
        tag_index,
        value
    )
end

"""
    duckdb_get_map_size(value)

Returns the number of elements in a MAP value.

# Arguments
- `value`: `duckdb_value` The MAP value.

Returns: `idx_t` The number of elements in the map.
"""
function duckdb_get_map_size(value)
    return ccall((:duckdb_get_map_size, libduckdb), idx_t, (duckdb_value,), value)
end

"""
    duckdb_get_map_key(value, index)

Returns the MAP key at index as a duckdb_value.

# Arguments
- `value`: `duckdb_value` The MAP value.
- `index`: `idx_t` (1-based index) The index of the key.

Returns: `duckdb_value` The key as a duckdb_value.
"""
function duckdb_get_map_key(value, index)
    return ccall((:duckdb_get_map_key, libduckdb), duckdb_value, (duckdb_value, idx_t), value, index - 1)
end

"""
    duckdb_get_map_value(value, index)

Returns the MAP value at index as a duckdb_value.

# Arguments
- `value`: `duckdb_value` The MAP value.
- `index`: `idx_t` (1-based index) The index of the value.

Returns: `duckdb_value` The value as a duckdb_value.
"""
function duckdb_get_map_value(value, index)
    return ccall((:duckdb_get_map_value, libduckdb), duckdb_value, (duckdb_value, idx_t), value, index - 1)
end

"""
    duckdb_is_null_value(value)

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

# Arguments
- `value`: `duckdb_value` The value to check.

Returns: `Bool` True, if the value's type is SQLNULL, otherwise false.
"""
function duckdb_is_null_value(value)
    return ccall((:duckdb_is_null_value, libduckdb), Bool, (duckdb_value,), value)
end

"""
    duckdb_create_null_value()

Creates a value of type SQLNULL.

# Arguments

Returns: `duckdb_value` The duckdb_value representing SQLNULL. This must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_create_null_value()
    return ccall((:duckdb_create_null_value, libduckdb), duckdb_value, ())
end

"""
    duckdb_get_list_size(value)

Returns the number of elements in a LIST value.

# Arguments
- `value`: `duckdb_value` The LIST value.

Returns: `idx_t` The number of elements in the list.
"""
function duckdb_get_list_size(value)
    return ccall((:duckdb_get_list_size, libduckdb), idx_t, (duckdb_value,), value)
end

"""
    duckdb_get_list_child(value, index)

Returns the LIST child at index as a duckdb_value.

# Arguments
- `value`: `duckdb_value` The LIST value.
- `index`: `idx_t` (1-based index) The index of the child.

Returns: `duckdb_value` The child as a duckdb_value.
"""
function duckdb_get_list_child(value, index)
    return ccall((:duckdb_get_list_child, libduckdb), duckdb_value, (duckdb_value, idx_t), value, index - 1)
end

"""
    duckdb_create_enum_value(_type, value)

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

# Arguments
- `_type`: `duckdb_logical_type` The type of the enum
- `value`: `UInt64` The value for the enum

Returns: `duckdb_value` The enum value, or nullptr.
"""
function duckdb_create_enum_value(_type, value)
    return ccall((:duckdb_create_enum_value, libduckdb), duckdb_value, (duckdb_logical_type, UInt64), _type, value)
end

"""
    duckdb_get_enum_value(value)

Returns the enum value of the given value.

# Arguments
- `value`: `duckdb_value` A duckdb_value containing an enum

Returns: `UInt64` A uint64_t, or MinValue<uint64> if the value cannot be converted
"""
function duckdb_get_enum_value(value)
    return ccall((:duckdb_get_enum_value, libduckdb), UInt64, (duckdb_value,), value)
end

"""
    duckdb_get_struct_child(value, index)

Returns the STRUCT child at index as a duckdb_value.

# Arguments
- `value`: `duckdb_value` The STRUCT value.
- `index`: `idx_t` (1-based index) The index of the child.

Returns: `duckdb_value` The child as a duckdb_value.
"""
function duckdb_get_struct_child(value, index)
    return ccall((:duckdb_get_struct_child, libduckdb), duckdb_value, (duckdb_value, idx_t), value, index - 1)
end

"""
    duckdb_value_to_string(value)

Returns the SQL string representation of the given value.

# Arguments
- `value`: `duckdb_value` A duckdb_value.

Returns: `Cstring` The SQL string representation as a null-terminated string. The result must be freed with `duckdb_free`.
"""
function duckdb_value_to_string(value)
    return ccall((:duckdb_value_to_string, libduckdb), Cstring, (duckdb_value,), value)
end



# --------------------------------------------------------------------------------
# Logical Type Interface
# --------------------------------------------------------------------------------

"""
    duckdb_create_logical_type(_type)

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`.

# Arguments
- `_type`: `DUCKDB_TYPE` The primitive type to create.

Returns: `duckdb_logical_type` The logical type.
"""
function duckdb_create_logical_type(_type)
    return ccall((:duckdb_create_logical_type, libduckdb), duckdb_logical_type, (DUCKDB_TYPE,), _type)
end

"""
    duckdb_logical_type_get_alias(_type)

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

# Arguments
- `_type`: `duckdb_logical_type` The logical type

Returns: `Cstring` The alias or `nullptr`
"""
function duckdb_logical_type_get_alias(_type)
    return ccall((:duckdb_logical_type_get_alias, libduckdb), Cstring, (duckdb_logical_type,), _type)
end

"""
    duckdb_logical_type_set_alias(_type, alias)

Sets the alias of a duckdb_logical_type.

# Arguments
- `_type`: `duckdb_logical_type` The logical type
- `alias`: `Cstring` The alias to set

Returns: `Nothing` 
"""
function duckdb_logical_type_set_alias(_type, alias)
    return ccall((:duckdb_logical_type_set_alias, libduckdb), Cvoid, (duckdb_logical_type, Cstring), _type, alias)
end

"""
    duckdb_create_list_type(_type)

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

# Arguments
- `_type`: `duckdb_logical_type` The child type of the list

Returns: `duckdb_logical_type` The logical type.
"""
function duckdb_create_list_type(_type)
    return ccall((:duckdb_create_list_type, libduckdb), duckdb_logical_type, (duckdb_logical_type,), _type)
end

"""
    duckdb_create_array_type(_type, array_size)

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

# Arguments
- `_type`: `duckdb_logical_type` The child type of the array.
- `array_size`: `idx_t` The number of elements in the array.

Returns: `duckdb_logical_type` The logical type.
"""
function duckdb_create_array_type(_type, array_size)
    return ccall(
        (:duckdb_create_array_type, libduckdb),
        duckdb_logical_type,
        (duckdb_logical_type, idx_t),
        _type,
        array_size
    )
end

"""
    duckdb_create_map_type(key_type, value_type)

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

# Arguments
- `key_type`: `duckdb_logical_type` The map's key type.
- `value_type`: `duckdb_logical_type` The map's value type.

Returns: `duckdb_logical_type` The logical type.
"""
function duckdb_create_map_type(key_type, value_type)
    return ccall(
        (:duckdb_create_map_type, libduckdb),
        duckdb_logical_type,
        (duckdb_logical_type, duckdb_logical_type),
        key_type,
        value_type
    )
end

"""
    duckdb_create_union_type(member_types, member_names, member_count)

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

# Arguments
- `member_types`: `Ref{duckdb_logical_type}` The array of union member types.
- `member_names`: `Ref{Cstring}` The union member names.
- `member_count`: `idx_t` The number of union members.

Returns: `duckdb_logical_type` The logical type.
"""
function duckdb_create_union_type(member_types, member_names, member_count)
    return ccall(
        (:duckdb_create_union_type, libduckdb),
        duckdb_logical_type,
        (Ref{duckdb_logical_type}, Ref{Cstring}, idx_t),
        member_types,
        member_names,
        member_count
    )
end

"""
    duckdb_create_struct_type(member_types, member_names, member_count)

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

# Arguments
- `member_types`: `Ref{duckdb_logical_type}` The array of types of the struct members.
- `member_names`: `Ref{Cstring}` The array of names of the struct members.
- `member_count`: `idx_t` The number of members of the struct.

Returns: `duckdb_logical_type` The logical type.
"""
function duckdb_create_struct_type(member_types, member_names, member_count)
    return ccall(
        (:duckdb_create_struct_type, libduckdb),
        duckdb_logical_type,
        (Ref{duckdb_logical_type}, Ref{Cstring}, idx_t),
        member_types,
        member_names,
        member_count
    )
end

"""
    duckdb_create_enum_type(member_names, member_count)

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

# Arguments
- `member_names`: `Ref{Cstring}` The array of names that the enum should consist of.
- `member_count`: `idx_t` The number of elements that were specified in the array.

Returns: `duckdb_logical_type` The logical type.
"""
function duckdb_create_enum_type(member_names, member_count)
    return ccall(
        (:duckdb_create_enum_type, libduckdb),
        duckdb_logical_type,
        (Ref{Cstring}, idx_t),
        member_names,
        member_count
    )
end

"""
    duckdb_create_decimal_type(width, scale)

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

# Arguments
- `width`: `UInt8` The width of the decimal type
- `scale`: `UInt8` The scale of the decimal type

Returns: `duckdb_logical_type` The logical type.
"""
function duckdb_create_decimal_type(width, scale)
    return ccall((:duckdb_create_decimal_type, libduckdb), duckdb_logical_type, (UInt8, UInt8), width, scale)
end

"""
    duckdb_get_type_id(_type)

Retrieves the enum `duckdb_type` of a `duckdb_logical_type`.

# Arguments
- `_type`: `duckdb_logical_type` The logical type.

Returns: `DUCKDB_TYPE` The `duckdb_type` id.
"""
function duckdb_get_type_id(_type)
    return ccall((:duckdb_get_type_id, libduckdb), DUCKDB_TYPE, (duckdb_logical_type,), _type)
end

"""
    duckdb_decimal_width(_type)

Retrieves the width of a decimal type.

# Arguments
- `_type`: `duckdb_logical_type` The logical type object

Returns: `UInt8` The width of the decimal type
"""
function duckdb_decimal_width(_type)
    return ccall((:duckdb_decimal_width, libduckdb), UInt8, (duckdb_logical_type,), _type)
end

"""
    duckdb_decimal_scale(_type)

Retrieves the scale of a decimal type.

# Arguments
- `_type`: `duckdb_logical_type` The logical type object

Returns: `UInt8` The scale of the decimal type
"""
function duckdb_decimal_scale(_type)
    return ccall((:duckdb_decimal_scale, libduckdb), UInt8, (duckdb_logical_type,), _type)
end

"""
    duckdb_decimal_internal_type(_type)

Retrieves the internal storage type of a decimal type.

# Arguments
- `_type`: `duckdb_logical_type` The logical type object

Returns: `DUCKDB_TYPE` The internal type of the decimal type
"""
function duckdb_decimal_internal_type(_type)
    return ccall((:duckdb_decimal_internal_type, libduckdb), DUCKDB_TYPE, (duckdb_logical_type,), _type)
end

"""
    duckdb_enum_internal_type(_type)

Retrieves the internal storage type of an enum type.

# Arguments
- `_type`: `duckdb_logical_type` The logical type object

Returns: `DUCKDB_TYPE` The internal type of the enum type
"""
function duckdb_enum_internal_type(_type)
    return ccall((:duckdb_enum_internal_type, libduckdb), DUCKDB_TYPE, (duckdb_logical_type,), _type)
end

"""
    duckdb_enum_dictionary_size(_type)

Retrieves the dictionary size of the enum type.

# Arguments
- `_type`: `duckdb_logical_type` The logical type object

Returns: `UInt32` The dictionary size of the enum type
"""
function duckdb_enum_dictionary_size(_type)
    return ccall((:duckdb_enum_dictionary_size, libduckdb), UInt32, (duckdb_logical_type,), _type)
end

"""
    duckdb_enum_dictionary_value(_type, index)

Retrieves the dictionary value at the specified position from the enum.

The result must be freed with `duckdb_free`.

# Arguments
- `_type`: `duckdb_logical_type` The logical type object
- `index`: `idx_t` (1-based index) The index in the dictionary

Returns: `Cstring` The string value of the enum type. Must be freed with `duckdb_free`.
"""
function duckdb_enum_dictionary_value(_type, index)
    return ccall((:duckdb_enum_dictionary_value, libduckdb), Cstring, (duckdb_logical_type, idx_t), _type, index - 1)
end

"""
    duckdb_list_type_child_type(_type)

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

# Arguments
- `_type`: `duckdb_logical_type` The logical type, either LIST or MAP.

Returns: `duckdb_logical_type` The child type of the LIST or MAP type.
"""
function duckdb_list_type_child_type(_type)
    return ccall((:duckdb_list_type_child_type, libduckdb), duckdb_logical_type, (duckdb_logical_type,), _type)
end

"""
    duckdb_array_type_child_type(_type)

Retrieves the child type of the given ARRAY type.

The result must be freed with `duckdb_destroy_logical_type`.

# Arguments
- `_type`: `duckdb_logical_type` The logical type. Must be ARRAY.

Returns: `duckdb_logical_type` The child type of the ARRAY type.
"""
function duckdb_array_type_child_type(_type)
    return ccall((:duckdb_array_type_child_type, libduckdb), duckdb_logical_type, (duckdb_logical_type,), _type)
end

"""
    duckdb_array_type_array_size(_type)

Retrieves the array size of the given array type.

# Arguments
- `_type`: `duckdb_logical_type` The logical type object

Returns: `idx_t` The fixed number of elements the values of this array type can store.
"""
function duckdb_array_type_array_size(_type)
    return ccall((:duckdb_array_type_array_size, libduckdb), idx_t, (duckdb_logical_type,), _type)
end

"""
    duckdb_map_type_key_type(_type)

Retrieves the key type of the given map type.

The result must be freed with `duckdb_destroy_logical_type`.

# Arguments
- `_type`: `duckdb_logical_type` The logical type object

Returns: `duckdb_logical_type` The key type of the map type. Must be destroyed with `duckdb_destroy_logical_type`.
"""
function duckdb_map_type_key_type(_type)
    return ccall((:duckdb_map_type_key_type, libduckdb), duckdb_logical_type, (duckdb_logical_type,), _type)
end

"""
    duckdb_map_type_value_type(_type)

Retrieves the value type of the given map type.

The result must be freed with `duckdb_destroy_logical_type`.

# Arguments
- `_type`: `duckdb_logical_type` The logical type object

Returns: `duckdb_logical_type` The value type of the map type. Must be destroyed with `duckdb_destroy_logical_type`.
"""
function duckdb_map_type_value_type(_type)
    return ccall((:duckdb_map_type_value_type, libduckdb), duckdb_logical_type, (duckdb_logical_type,), _type)
end

"""
    duckdb_struct_type_child_count(_type)

Returns the number of children of a struct type.

# Arguments
- `_type`: `duckdb_logical_type` The logical type object

Returns: `idx_t` The number of children of a struct type.
"""
function duckdb_struct_type_child_count(_type)
    return ccall((:duckdb_struct_type_child_count, libduckdb), idx_t, (duckdb_logical_type,), _type)
end

"""
    duckdb_struct_type_child_name(_type, index)

Retrieves the name of the struct child.

The result must be freed with `duckdb_free`.

# Arguments
- `_type`: `duckdb_logical_type` The logical type object
- `index`: `idx_t` (1-based index) The child index

Returns: `Cstring` The name of the struct type. Must be freed with `duckdb_free`.
"""
function duckdb_struct_type_child_name(_type, index)
    return ccall((:duckdb_struct_type_child_name, libduckdb), Cstring, (duckdb_logical_type, idx_t), _type, index - 1)
end

"""
    duckdb_struct_type_child_type(_type, index)

Retrieves the child type of the given struct type at the specified index.

The result must be freed with `duckdb_destroy_logical_type`.

# Arguments
- `_type`: `duckdb_logical_type` The logical type object
- `index`: `idx_t` (1-based index) The child index

Returns: `duckdb_logical_type` The child type of the struct type. Must be destroyed with `duckdb_destroy_logical_type`.
"""
function duckdb_struct_type_child_type(_type, index)
    return ccall(
        (:duckdb_struct_type_child_type, libduckdb),
        duckdb_logical_type,
        (duckdb_logical_type, idx_t),
        _type,
        index - 1
    )
end

"""
    duckdb_union_type_member_count(_type)

Returns the number of members that the union type has.

# Arguments
- `_type`: `duckdb_logical_type` The logical type (union) object

Returns: `idx_t` The number of members of a union type.
"""
function duckdb_union_type_member_count(_type)
    return ccall((:duckdb_union_type_member_count, libduckdb), idx_t, (duckdb_logical_type,), _type)
end

"""
    duckdb_union_type_member_name(_type, index)

Retrieves the name of the union member.

The result must be freed with `duckdb_free`.

# Arguments
- `_type`: `duckdb_logical_type` The logical type object
- `index`: `idx_t` (1-based index) The child index

Returns: `Cstring` The name of the union member. Must be freed with `duckdb_free`.
"""
function duckdb_union_type_member_name(_type, index)
    return ccall((:duckdb_union_type_member_name, libduckdb), Cstring, (duckdb_logical_type, idx_t), _type, index - 1)
end

"""
    duckdb_union_type_member_type(_type, index)

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

The result must be freed with `duckdb_destroy_logical_type`.

# Arguments
- `_type`: `duckdb_logical_type` The logical type object
- `index`: `idx_t` (1-based index) The child index

Returns: `duckdb_logical_type` The child type of the union member. Must be destroyed with `duckdb_destroy_logical_type`.
"""
function duckdb_union_type_member_type(_type, index)
    return ccall(
        (:duckdb_union_type_member_type, libduckdb),
        duckdb_logical_type,
        (duckdb_logical_type, idx_t),
        _type,
        index - 1
    )
end

"""
    duckdb_destroy_logical_type(_type)

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

# Arguments
- `_type`: `Ref{duckdb_logical_type}` The logical type to destroy.

Returns: `Nothing` 
"""
function duckdb_destroy_logical_type(_type)
    return ccall((:duckdb_destroy_logical_type, libduckdb), Cvoid, (Ref{duckdb_logical_type},), _type)
end

"""
    duckdb_register_logical_type(con, _type, info)

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

# Arguments
- `con`: `duckdb_connection` The connection to use
- `_type`: `duckdb_logical_type` The custom type to register
- `info`: `duckdb_create_type_info` 

Returns: `duckdb_state` Whether or not the registration was successful.
"""
function duckdb_register_logical_type(con, _type, info)
    return ccall(
        (:duckdb_register_logical_type, libduckdb),
        duckdb_state,
        (duckdb_connection, duckdb_logical_type, duckdb_create_type_info),
        con,
        _type,
        info
    )
end



# --------------------------------------------------------------------------------
# Data Chunk Interface
# --------------------------------------------------------------------------------

"""
    duckdb_create_data_chunk(types, column_count)

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

# Arguments
- `types`: `Ref{duckdb_logical_type}` An array of column types. Column types can not contain ANY and INVALID types.
- `column_count`: `idx_t` The number of columns.

Returns: `duckdb_data_chunk` The data chunk.
"""
function duckdb_create_data_chunk(types, column_count)
    return ccall(
        (:duckdb_create_data_chunk, libduckdb),
        duckdb_data_chunk,
        (Ref{duckdb_logical_type}, idx_t),
        types,
        column_count
    )
end

"""
    duckdb_destroy_data_chunk(chunk)

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

# Arguments
- `chunk`: `Ref{duckdb_data_chunk}` The data chunk to destroy.

Returns: `Nothing` 
"""
function duckdb_destroy_data_chunk(chunk)
    return ccall((:duckdb_destroy_data_chunk, libduckdb), Cvoid, (Ref{duckdb_data_chunk},), chunk)
end

"""
    duckdb_data_chunk_reset(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

# Arguments
- `chunk`: `duckdb_data_chunk` The data chunk to reset.

Returns: `Nothing` 
"""
function duckdb_data_chunk_reset(chunk)
    return ccall((:duckdb_data_chunk_reset, libduckdb), Cvoid, (duckdb_data_chunk,), chunk)
end

"""
    duckdb_data_chunk_get_column_count(chunk)

Retrieves the number of columns in a data chunk.

# Arguments
- `chunk`: `duckdb_data_chunk` The data chunk to get the data from

Returns: `idx_t` The number of columns in the data chunk
"""
function duckdb_data_chunk_get_column_count(chunk)
    return ccall((:duckdb_data_chunk_get_column_count, libduckdb), idx_t, (duckdb_data_chunk,), chunk)
end

"""
    duckdb_data_chunk_get_vector(chunk, col_idx)

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.

# Arguments
- `chunk`: `duckdb_data_chunk` The data chunk to get the data from
- `col_idx`: `idx_t` (1-based index) 

Returns: `duckdb_vector` The vector
"""
function duckdb_data_chunk_get_vector(chunk, col_idx)
    return ccall(
        (:duckdb_data_chunk_get_vector, libduckdb),
        duckdb_vector,
        (duckdb_data_chunk, idx_t),
        chunk,
        col_idx - 1
    )
end

"""
    duckdb_data_chunk_get_size(chunk)

Retrieves the current number of tuples in a data chunk.

# Arguments
- `chunk`: `duckdb_data_chunk` The data chunk to get the data from

Returns: `idx_t` The number of tuples in the data chunk
"""
function duckdb_data_chunk_get_size(chunk)
    return ccall((:duckdb_data_chunk_get_size, libduckdb), idx_t, (duckdb_data_chunk,), chunk)
end

"""
    duckdb_data_chunk_set_size(chunk, size)

Sets the current number of tuples in a data chunk.

# Arguments
- `chunk`: `duckdb_data_chunk` The data chunk to set the size in
- `size`: `idx_t` The number of tuples in the data chunk

Returns: `Nothing` 
"""
function duckdb_data_chunk_set_size(chunk, size)
    return ccall((:duckdb_data_chunk_set_size, libduckdb), Cvoid, (duckdb_data_chunk, idx_t), chunk, size)
end



# --------------------------------------------------------------------------------
# Vector Interface
# --------------------------------------------------------------------------------

"""
    duckdb_create_vector(_type, capacity)

Creates a flat vector. Must be destroyed with `duckdb_destroy_vector`.

# Arguments
- `_type`: `duckdb_logical_type` The logical type of the vector.
- `capacity`: `idx_t` The capacity of the vector.

Returns: `duckdb_vector` The vector.
"""
function duckdb_create_vector(_type, capacity)
    return ccall((:duckdb_create_vector, libduckdb), duckdb_vector, (duckdb_logical_type, idx_t), _type, capacity)
end

"""
    duckdb_destroy_vector(vector)

Destroys the vector and de-allocates its memory.

# Arguments
- `vector`: `Ref{duckdb_vector}` A pointer to the vector.

Returns: `Nothing` 
"""
function duckdb_destroy_vector(vector)
    return ccall((:duckdb_destroy_vector, libduckdb), Cvoid, (Ref{duckdb_vector},), vector)
end

"""
    duckdb_vector_get_column_type(vector)

Retrieves the column type of the specified vector.

The result must be destroyed with `duckdb_destroy_logical_type`.

# Arguments
- `vector`: `duckdb_vector` The vector get the data from

Returns: `duckdb_logical_type` The type of the vector
"""
function duckdb_vector_get_column_type(vector)
    return ccall((:duckdb_vector_get_column_type, libduckdb), duckdb_logical_type, (duckdb_vector,), vector)
end

"""
    duckdb_vector_get_data(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.

# Arguments
- `vector`: `duckdb_vector` The vector to get the data from

Returns: `Ptr{Cvoid}` The data pointer
"""
function duckdb_vector_get_data(vector)
    return ccall((:duckdb_vector_get_data, libduckdb), Ptr{Cvoid}, (duckdb_vector,), vector)
end

"""
    duckdb_vector_get_validity(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.

# Arguments
- `vector`: `duckdb_vector` The vector to get the data from

Returns: `Ptr{UInt64}` The pointer to the validity mask, or NULL if no validity mask is present
"""
function duckdb_vector_get_validity(vector)
    return ccall((:duckdb_vector_get_validity, libduckdb), Ptr{UInt64}, (duckdb_vector,), vector)
end

"""
    duckdb_vector_ensure_validity_writable(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.

# Arguments
- `vector`: `duckdb_vector` The vector to alter

Returns: `Nothing` 
"""
function duckdb_vector_ensure_validity_writable(vector)
    return ccall((:duckdb_vector_ensure_validity_writable, libduckdb), Cvoid, (duckdb_vector,), vector)
end

"""
    duckdb_vector_assign_string_element(vector, index, str)

Assigns a string element in the vector at the specified location.

# Arguments
- `vector`: `duckdb_vector` The vector to alter
- `index`: `idx_t` (1-based index) The row position in the vector to assign the string to
- `str`: `Cstring` The null-terminated string

Returns: `Nothing` 
"""
function duckdb_vector_assign_string_element(vector, index, str)
    return ccall(
        (:duckdb_vector_assign_string_element, libduckdb),
        Cvoid,
        (duckdb_vector, idx_t, Cstring),
        vector,
        index - 1,
        str
    )
end

"""
    duckdb_vector_assign_string_element_len(vector, index, str, str_len)

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

# Arguments
- `vector`: `duckdb_vector` The vector to alter
- `index`: `idx_t` (1-based index) The row position in the vector to assign the string to
- `str`: `Ptr{UInt8}` The string
- `str_len`: `idx_t` The length of the string (in bytes)

Returns: `Nothing` 
"""
function duckdb_vector_assign_string_element_len(vector, index, str, str_len)
    return ccall(
        (:duckdb_vector_assign_string_element_len, libduckdb),
        Cvoid,
        (duckdb_vector, idx_t, Ptr{UInt8}, idx_t),
        vector,
        index - 1,
        str,
        str_len
    )
end

"""
    duckdb_list_vector_get_child(vector)

Retrieves the child vector of a list vector.

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

# Arguments
- `vector`: `duckdb_vector` The vector

Returns: `duckdb_vector` The child vector
"""
function duckdb_list_vector_get_child(vector)
    return ccall((:duckdb_list_vector_get_child, libduckdb), duckdb_vector, (duckdb_vector,), vector)
end

"""
    duckdb_list_vector_get_size(vector)

Returns the size of the child vector of the list.

# Arguments
- `vector`: `duckdb_vector` The vector

Returns: `idx_t` The size of the child list
"""
function duckdb_list_vector_get_size(vector)
    return ccall((:duckdb_list_vector_get_size, libduckdb), idx_t, (duckdb_vector,), vector)
end

"""
    duckdb_list_vector_set_size(vector, size)

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

# Arguments
- `vector`: `duckdb_vector` The list vector.
- `size`: `idx_t` The size of the child list.

Returns: `duckdb_state` The duckdb state. Returns DuckDBError if the vector is nullptr.
"""
function duckdb_list_vector_set_size(vector, size)
    return ccall((:duckdb_list_vector_set_size, libduckdb), duckdb_state, (duckdb_vector, idx_t), vector, size)
end

"""
    duckdb_list_vector_reserve(vector, required_capacity)

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

# Arguments
- `vector`: `duckdb_vector` The list vector.
- `required_capacity`: `idx_t` the total capacity to reserve.

Returns: `duckdb_state` The duckdb state. Returns DuckDBError if the vector is nullptr.
"""
function duckdb_list_vector_reserve(vector, required_capacity)
    return ccall(
        (:duckdb_list_vector_reserve, libduckdb),
        duckdb_state,
        (duckdb_vector, idx_t),
        vector,
        required_capacity
    )
end

"""
    duckdb_struct_vector_get_child(vector, index)

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

# Arguments
- `vector`: `duckdb_vector` The vector
- `index`: `idx_t` (1-based index) The child index

Returns: `duckdb_vector` The child vector
"""
function duckdb_struct_vector_get_child(vector, index)
    return ccall((:duckdb_struct_vector_get_child, libduckdb), duckdb_vector, (duckdb_vector, idx_t), vector, index - 1)
end

"""
    duckdb_array_vector_get_child(vector)

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.

# Arguments
- `vector`: `duckdb_vector` The vector

Returns: `duckdb_vector` The child vector
"""
function duckdb_array_vector_get_child(vector)
    return ccall((:duckdb_array_vector_get_child, libduckdb), duckdb_vector, (duckdb_vector,), vector)
end

"""
    duckdb_slice_vector(vector, sel, len)

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.

# Arguments
- `vector`: `duckdb_vector` The vector to slice.
- `sel`: `duckdb_selection_vector` The selection vector.
- `len`: `idx_t` The length of the selection vector.

Returns: `Nothing` 
"""
function duckdb_slice_vector(vector, sel, len)
    return ccall(
        (:duckdb_slice_vector, libduckdb),
        Cvoid,
        (duckdb_vector, duckdb_selection_vector, idx_t),
        vector,
        sel,
        len
    )
end

"""
    duckdb_vector_reference_value(vector, value)

Copies the value from `value` to `vector`.

# Arguments
- `vector`: `duckdb_vector` The receiving vector.
- `value`: `duckdb_value` The value to copy into the vector.

Returns: `Nothing` 
"""
function duckdb_vector_reference_value(vector, value)
    return ccall((:duckdb_vector_reference_value, libduckdb), Cvoid, (duckdb_vector, duckdb_value), vector, value)
end

"""
    duckdb_vector_reference_vector(to_vector, from_vector)

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

# Arguments
- `to_vector`: `duckdb_vector` The receiving vector.
- `from_vector`: `duckdb_vector` The vector to reference.

Returns: `Nothing` 
"""
function duckdb_vector_reference_vector(to_vector, from_vector)
    return ccall(
        (:duckdb_vector_reference_vector, libduckdb),
        Cvoid,
        (duckdb_vector, duckdb_vector),
        to_vector,
        from_vector
    )
end



# --------------------------------------------------------------------------------
# Validity Mask Functions
# --------------------------------------------------------------------------------

"""
    duckdb_validity_row_is_valid(validity, row)

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

# Arguments
- `validity`: `Ref{UInt64}` The validity mask, as obtained through `duckdb_vector_get_validity`
- `row`: `idx_t` (1-based index) The row index

Returns: `Bool` true if the row is valid, false otherwise
"""
function duckdb_validity_row_is_valid(validity, row)
    return ccall((:duckdb_validity_row_is_valid, libduckdb), Bool, (Ref{UInt64}, idx_t), validity, row - 1)
end

"""
    duckdb_validity_set_row_validity(validity, row, valid)

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.

# Arguments
- `validity`: `Ref{UInt64}` The validity mask, as obtained through `duckdb_vector_get_validity`.
- `row`: `idx_t` (1-based index) The row index
- `valid`: `Bool` Whether or not to set the row to valid, or invalid

Returns: `Nothing` 
"""
function duckdb_validity_set_row_validity(validity, row, valid)
    return ccall(
        (:duckdb_validity_set_row_validity, libduckdb),
        Cvoid,
        (Ref{UInt64}, idx_t, Bool),
        validity,
        row - 1,
        valid
    )
end

"""
    duckdb_validity_set_row_invalid(validity, row)

In a validity mask, sets a specific row to invalid.

Equivalent to `duckdb_validity_set_row_validity` with valid set to false.

# Arguments
- `validity`: `Ref{UInt64}` The validity mask
- `row`: `idx_t` (1-based index) The row index

Returns: `Nothing` 
"""
function duckdb_validity_set_row_invalid(validity, row)
    return ccall((:duckdb_validity_set_row_invalid, libduckdb), Cvoid, (Ref{UInt64}, idx_t), validity, row - 1)
end

"""
    duckdb_validity_set_row_valid(validity, row)

In a validity mask, sets a specific row to valid.

Equivalent to `duckdb_validity_set_row_validity` with valid set to true.

# Arguments
- `validity`: `Ref{UInt64}` The validity mask
- `row`: `idx_t` (1-based index) The row index

Returns: `Nothing` 
"""
function duckdb_validity_set_row_valid(validity, row)
    return ccall((:duckdb_validity_set_row_valid, libduckdb), Cvoid, (Ref{UInt64}, idx_t), validity, row - 1)
end



# --------------------------------------------------------------------------------
# Scalar Functions
# --------------------------------------------------------------------------------

"""
    duckdb_create_scalar_function()

Creates a new empty scalar function.

The return value must be destroyed with `duckdb_destroy_scalar_function`.

# Arguments

Returns: `duckdb_scalar_function` The scalar function object.
"""
function duckdb_create_scalar_function()
    return ccall((:duckdb_create_scalar_function, libduckdb), duckdb_scalar_function, ())
end

"""
    duckdb_destroy_scalar_function(scalar_function)

Destroys the given scalar function object.

# Arguments
- `scalar_function`: `Ref{duckdb_scalar_function}` The scalar function to destroy

Returns: `Nothing` 
"""
function duckdb_destroy_scalar_function(scalar_function)
    return ccall((:duckdb_destroy_scalar_function, libduckdb), Cvoid, (Ref{duckdb_scalar_function},), scalar_function)
end

"""
    duckdb_scalar_function_set_name(scalar_function, name)

Sets the name of the given scalar function.

# Arguments
- `scalar_function`: `duckdb_scalar_function` The scalar function
- `name`: `Cstring` The name of the scalar function

Returns: `Nothing` 
"""
function duckdb_scalar_function_set_name(scalar_function, name)
    return ccall(
        (:duckdb_scalar_function_set_name, libduckdb),
        Cvoid,
        (duckdb_scalar_function, Cstring),
        scalar_function,
        name
    )
end

"""
    duckdb_scalar_function_set_varargs(scalar_function, _type)

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

# Arguments
- `scalar_function`: `duckdb_scalar_function` The scalar function.
- `_type`: `duckdb_logical_type` The type of the arguments.

Returns: `Nothing` The parameter type. Cannot contain INVALID.
"""
function duckdb_scalar_function_set_varargs(scalar_function, _type)
    return ccall(
        (:duckdb_scalar_function_set_varargs, libduckdb),
        Cvoid,
        (duckdb_scalar_function, duckdb_logical_type),
        scalar_function,
        _type
    )
end

"""
    duckdb_scalar_function_set_special_handling(scalar_function)

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

# Arguments
- `scalar_function`: `duckdb_scalar_function` The scalar function.

Returns: `Nothing` 
"""
function duckdb_scalar_function_set_special_handling(scalar_function)
    return ccall(
        (:duckdb_scalar_function_set_special_handling, libduckdb),
        Cvoid,
        (duckdb_scalar_function,),
        scalar_function
    )
end

"""
    duckdb_scalar_function_set_volatile(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.

# Arguments
- `scalar_function`: `duckdb_scalar_function` The scalar function.

Returns: `Nothing` 
"""
function duckdb_scalar_function_set_volatile(scalar_function)
    return ccall((:duckdb_scalar_function_set_volatile, libduckdb), Cvoid, (duckdb_scalar_function,), scalar_function)
end

"""
    duckdb_scalar_function_add_parameter(scalar_function, _type)

Adds a parameter to the scalar function.

# Arguments
- `scalar_function`: `duckdb_scalar_function` The scalar function.
- `_type`: `duckdb_logical_type` The parameter type. Cannot contain INVALID.

Returns: `Nothing` 
"""
function duckdb_scalar_function_add_parameter(scalar_function, _type)
    return ccall(
        (:duckdb_scalar_function_add_parameter, libduckdb),
        Cvoid,
        (duckdb_scalar_function, duckdb_logical_type),
        scalar_function,
        _type
    )
end

"""
    duckdb_scalar_function_set_return_type(scalar_function, _type)

Sets the return type of the scalar function.

# Arguments
- `scalar_function`: `duckdb_scalar_function` The scalar function
- `_type`: `duckdb_logical_type` Cannot contain INVALID or ANY.

Returns: `Nothing` 
"""
function duckdb_scalar_function_set_return_type(scalar_function, _type)
    return ccall(
        (:duckdb_scalar_function_set_return_type, libduckdb),
        Cvoid,
        (duckdb_scalar_function, duckdb_logical_type),
        scalar_function,
        _type
    )
end

"""
    duckdb_scalar_function_set_extra_info(scalar_function, extra_info, destroy)

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

# Arguments
- `scalar_function`: `duckdb_scalar_function` The scalar function
- `extra_info`: `Ref{Cvoid}` The extra information
- `destroy`: `duckdb_delete_callback` The callback that will be called to destroy the extra information (if any)

Returns: `Nothing` 
"""
function duckdb_scalar_function_set_extra_info(scalar_function, extra_info, destroy)
    return ccall(
        (:duckdb_scalar_function_set_extra_info, libduckdb),
        Cvoid,
        (duckdb_scalar_function, Ref{Cvoid}, duckdb_delete_callback),
        scalar_function,
        extra_info,
        destroy
    )
end

"""
    duckdb_scalar_function_set_bind(scalar_function, bind)

Sets the (optional) bind function of the scalar function.

# Arguments
- `scalar_function`: `duckdb_scalar_function` The scalar function.
- `bind`: `duckdb_scalar_function_bind` The bind function.

Returns: `Nothing` 
"""
function duckdb_scalar_function_set_bind(scalar_function, bind)
    return ccall(
        (:duckdb_scalar_function_set_bind, libduckdb),
        Cvoid,
        (duckdb_scalar_function, duckdb_scalar_function_bind),
        scalar_function,
        bind
    )
end

"""
    duckdb_scalar_function_set_bind_data(info, bind_data, destroy)

Sets the user-provided bind data in the bind object of the scalar function. 
This object can be retrieved again during execution.

# Arguments
- `info`: `duckdb_bind_info` The bind info of the scalar function.
- `bind_data`: `Ref{Cvoid}` The bind data object.
- `destroy`: `duckdb_delete_callback` The callback to destroy the bind data (if any).

Returns: `Nothing` 
"""
function duckdb_scalar_function_set_bind_data(info, bind_data, destroy)
    return ccall(
        (:duckdb_scalar_function_set_bind_data, libduckdb),
        Cvoid,
        (duckdb_bind_info, Ref{Cvoid}, duckdb_delete_callback),
        info,
        bind_data,
        destroy
    )
end

"""
    duckdb_scalar_function_bind_set_error(info, error)

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

# Arguments
- `info`: `duckdb_bind_info` The bind info object.
- `error`: `Cstring` The error message.

Returns: `Nothing` 
"""
function duckdb_scalar_function_bind_set_error(info, error)
    return ccall((:duckdb_scalar_function_bind_set_error, libduckdb), Cvoid, (duckdb_bind_info, Cstring), info, error)
end

"""
    duckdb_scalar_function_set_function(scalar_function, _function)

Sets the main function of the scalar function.

# Arguments
- `scalar_function`: `duckdb_scalar_function` The scalar function
- `_function`: `duckdb_scalar_function` The function

Returns: `Nothing` 
"""
function duckdb_scalar_function_set_function(scalar_function, _function)
    return ccall(
        (:duckdb_scalar_function_set_function, libduckdb),
        Cvoid,
        (duckdb_scalar_function, duckdb_scalar_function),
        scalar_function,
        _function
    )
end

"""
    duckdb_register_scalar_function(con, scalar_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.

# Arguments
- `con`: `duckdb_connection` The connection to register it in.
- `scalar_function`: `duckdb_scalar_function` The function pointer

Returns: `duckdb_state` Whether or not the registration was successful.
"""
function duckdb_register_scalar_function(con, scalar_function)
    return ccall(
        (:duckdb_register_scalar_function, libduckdb),
        duckdb_state,
        (duckdb_connection, duckdb_scalar_function),
        con,
        scalar_function
    )
end

"""
    duckdb_scalar_function_get_extra_info(info)

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

# Arguments
- `info`: `duckdb_function_info` The info object.

Returns: `Ptr{Cvoid}` The extra info.
"""
function duckdb_scalar_function_get_extra_info(info)
    return ccall((:duckdb_scalar_function_get_extra_info, libduckdb), Ptr{Cvoid}, (duckdb_function_info,), info)
end

"""
    duckdb_scalar_function_bind_get_extra_info(info)

Retrieves the extra info of the function as set in the bind info.

# Arguments
- `info`: `duckdb_bind_info` The info object.

Returns: `Ptr{Cvoid}` The extra info.
"""
function duckdb_scalar_function_bind_get_extra_info(info)
    return ccall((:duckdb_scalar_function_bind_get_extra_info, libduckdb), Ptr{Cvoid}, (duckdb_bind_info,), info)
end

"""
    duckdb_scalar_function_get_bind_data(info)

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

# Arguments
- `info`: `duckdb_function_info` The function info.

Returns: `Ptr{Cvoid}` The bind data object.
"""
function duckdb_scalar_function_get_bind_data(info)
    return ccall((:duckdb_scalar_function_get_bind_data, libduckdb), Ptr{Cvoid}, (duckdb_function_info,), info)
end

"""
    duckdb_scalar_function_get_client_context(info, out_context)

Retrieves the client context of the bind info of a scalar function.

# Arguments
- `info`: `duckdb_bind_info` The bind info object of the scalar function.
- `out_context`: `Ref{duckdb_client_context}` The client context of the bind info. Must be destroyed with `duckdb_destroy_client_context`.

Returns: `Nothing` 
"""
function duckdb_scalar_function_get_client_context(info, out_context)
    return ccall(
        (:duckdb_scalar_function_get_client_context, libduckdb),
        Cvoid,
        (duckdb_bind_info, Ref{duckdb_client_context}),
        info,
        out_context
    )
end

"""
    duckdb_scalar_function_set_error(info, error)

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

# Arguments
- `info`: `duckdb_function_info` The info object.
- `error`: `Cstring` The error message

Returns: `Nothing` 
"""
function duckdb_scalar_function_set_error(info, error)
    return ccall((:duckdb_scalar_function_set_error, libduckdb), Cvoid, (duckdb_function_info, Cstring), info, error)
end

"""
    duckdb_create_scalar_function_set(name)

Creates a new empty scalar function set.

The return value must be destroyed with `duckdb_destroy_scalar_function_set`.

# Arguments
- `name`: `Cstring` 

Returns: `duckdb_scalar_function_set` The scalar function set object.
"""
function duckdb_create_scalar_function_set(name)
    return ccall((:duckdb_create_scalar_function_set, libduckdb), duckdb_scalar_function_set, (Cstring,), name)
end

"""
    duckdb_destroy_scalar_function_set(scalar_function_set)

Destroys the given scalar function set object.

# Arguments
- `scalar_function_set`: `Ref{duckdb_scalar_function_set}` 

Returns: `Nothing` 
"""
function duckdb_destroy_scalar_function_set(scalar_function_set)
    return ccall(
        (:duckdb_destroy_scalar_function_set, libduckdb),
        Cvoid,
        (Ref{duckdb_scalar_function_set},),
        scalar_function_set
    )
end

"""
    duckdb_add_scalar_function_to_set(set, _function)

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.

# Arguments
- `set`: `duckdb_scalar_function_set` The scalar function set
- `_function`: `duckdb_scalar_function` The function to add

Returns: `duckdb_state` 
"""
function duckdb_add_scalar_function_to_set(set, _function)
    return ccall(
        (:duckdb_add_scalar_function_to_set, libduckdb),
        duckdb_state,
        (duckdb_scalar_function_set, duckdb_scalar_function),
        set,
        _function
    )
end

"""
    duckdb_register_scalar_function_set(con, set)

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.

# Arguments
- `con`: `duckdb_connection` The connection to register it in.
- `set`: `duckdb_scalar_function_set` The function set to register

Returns: `duckdb_state` Whether or not the registration was successful.
"""
function duckdb_register_scalar_function_set(con, set)
    return ccall(
        (:duckdb_register_scalar_function_set, libduckdb),
        duckdb_state,
        (duckdb_connection, duckdb_scalar_function_set),
        con,
        set
    )
end



# --------------------------------------------------------------------------------
# Aggregate Functions
# --------------------------------------------------------------------------------

"""
    duckdb_create_aggregate_function()

Creates a new empty aggregate function.

The return value should be destroyed with `duckdb_destroy_aggregate_function`.

# Arguments

Returns: `duckdb_aggregate_function` The aggregate function object.
"""
function duckdb_create_aggregate_function()
    return ccall((:duckdb_create_aggregate_function, libduckdb), duckdb_aggregate_function, ())
end

"""
    duckdb_destroy_aggregate_function(aggregate_function)

Destroys the given aggregate function object.

# Arguments
- `aggregate_function`: `Ref{duckdb_aggregate_function}` 

Returns: `Nothing` 
"""
function duckdb_destroy_aggregate_function(aggregate_function)
    return ccall(
        (:duckdb_destroy_aggregate_function, libduckdb),
        Cvoid,
        (Ref{duckdb_aggregate_function},),
        aggregate_function
    )
end

"""
    duckdb_aggregate_function_set_name(aggregate_function, name)

Sets the name of the given aggregate function.

# Arguments
- `aggregate_function`: `duckdb_aggregate_function` The aggregate function
- `name`: `Cstring` The name of the aggregate function

Returns: `Nothing` 
"""
function duckdb_aggregate_function_set_name(aggregate_function, name)
    return ccall(
        (:duckdb_aggregate_function_set_name, libduckdb),
        Cvoid,
        (duckdb_aggregate_function, Cstring),
        aggregate_function,
        name
    )
end

"""
    duckdb_aggregate_function_add_parameter(aggregate_function, _type)

Adds a parameter to the aggregate function.

# Arguments
- `aggregate_function`: `duckdb_aggregate_function` The aggregate function.
- `_type`: `duckdb_logical_type` The parameter type. Cannot contain INVALID.

Returns: `Nothing` 
"""
function duckdb_aggregate_function_add_parameter(aggregate_function, _type)
    return ccall(
        (:duckdb_aggregate_function_add_parameter, libduckdb),
        Cvoid,
        (duckdb_aggregate_function, duckdb_logical_type),
        aggregate_function,
        _type
    )
end

"""
    duckdb_aggregate_function_set_return_type(aggregate_function, _type)

Sets the return type of the aggregate function.

# Arguments
- `aggregate_function`: `duckdb_aggregate_function` The aggregate function.
- `_type`: `duckdb_logical_type` The return type. Cannot contain INVALID or ANY.

Returns: `Nothing` 
"""
function duckdb_aggregate_function_set_return_type(aggregate_function, _type)
    return ccall(
        (:duckdb_aggregate_function_set_return_type, libduckdb),
        Cvoid,
        (duckdb_aggregate_function, duckdb_logical_type),
        aggregate_function,
        _type
    )
end

"""
    duckdb_aggregate_function_set_functions(aggregate_function, state_size, state_init, update, combine, finalize)

Sets the main functions of the aggregate function.

# Arguments
- `aggregate_function`: `duckdb_aggregate_function` The aggregate function
- `state_size`: `duckdb_aggregate_state_size` state size
- `state_init`: `duckdb_aggregate_init` state init function
- `update`: `duckdb_aggregate_update` update states
- `combine`: `duckdb_aggregate_combine` combine states
- `finalize`: `duckdb_aggregate_finalize` finalize states

Returns: `Nothing` 
"""
function duckdb_aggregate_function_set_functions(aggregate_function, state_size, state_init, update, combine, finalize)
    return ccall(
        (:duckdb_aggregate_function_set_functions, libduckdb),
        Cvoid,
        (
            duckdb_aggregate_function,
            duckdb_aggregate_state_size,
            duckdb_aggregate_init,
            duckdb_aggregate_update,
            duckdb_aggregate_combine,
            duckdb_aggregate_finalize
        ),
        aggregate_function,
        state_size,
        state_init,
        update,
        combine,
        finalize
    )
end

"""
    duckdb_aggregate_function_set_destructor(aggregate_function, destroy)

Sets the state destructor callback of the aggregate function (optional)

# Arguments
- `aggregate_function`: `duckdb_aggregate_function` The aggregate function
- `destroy`: `duckdb_aggregate_destroy` state destroy callback

Returns: `Nothing` 
"""
function duckdb_aggregate_function_set_destructor(aggregate_function, destroy)
    return ccall(
        (:duckdb_aggregate_function_set_destructor, libduckdb),
        Cvoid,
        (duckdb_aggregate_function, duckdb_aggregate_destroy),
        aggregate_function,
        destroy
    )
end

"""
    duckdb_register_aggregate_function(con, aggregate_function)

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.

# Arguments
- `con`: `duckdb_connection` The connection to register it in.
- `aggregate_function`: `duckdb_aggregate_function` 

Returns: `duckdb_state` Whether or not the registration was successful.
"""
function duckdb_register_aggregate_function(con, aggregate_function)
    return ccall(
        (:duckdb_register_aggregate_function, libduckdb),
        duckdb_state,
        (duckdb_connection, duckdb_aggregate_function),
        con,
        aggregate_function
    )
end

"""
    duckdb_aggregate_function_set_special_handling(aggregate_function)

Sets the NULL handling of the aggregate function to SPECIAL_HANDLING.

# Arguments
- `aggregate_function`: `duckdb_aggregate_function` The aggregate function

Returns: `Nothing` 
"""
function duckdb_aggregate_function_set_special_handling(aggregate_function)
    return ccall(
        (:duckdb_aggregate_function_set_special_handling, libduckdb),
        Cvoid,
        (duckdb_aggregate_function,),
        aggregate_function
    )
end

"""
    duckdb_aggregate_function_set_extra_info(aggregate_function, extra_info, destroy)

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

# Arguments
- `aggregate_function`: `duckdb_aggregate_function` The aggregate function
- `extra_info`: `Ref{Cvoid}` The extra information
- `destroy`: `duckdb_delete_callback` The callback that will be called to destroy the extra information (if any)

Returns: `Nothing` 
"""
function duckdb_aggregate_function_set_extra_info(aggregate_function, extra_info, destroy)
    return ccall(
        (:duckdb_aggregate_function_set_extra_info, libduckdb),
        Cvoid,
        (duckdb_aggregate_function, Ref{Cvoid}, duckdb_delete_callback),
        aggregate_function,
        extra_info,
        destroy
    )
end

"""
    duckdb_aggregate_function_get_extra_info(info)

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

# Arguments
- `info`: `duckdb_function_info` The info object

Returns: `Ptr{Cvoid}` The extra info
"""
function duckdb_aggregate_function_get_extra_info(info)
    return ccall((:duckdb_aggregate_function_get_extra_info, libduckdb), Ptr{Cvoid}, (duckdb_function_info,), info)
end

"""
    duckdb_aggregate_function_set_error(info, error)

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

# Arguments
- `info`: `duckdb_function_info` The info object
- `error`: `Cstring` The error message

Returns: `Nothing` 
"""
function duckdb_aggregate_function_set_error(info, error)
    return ccall((:duckdb_aggregate_function_set_error, libduckdb), Cvoid, (duckdb_function_info, Cstring), info, error)
end

"""
    duckdb_create_aggregate_function_set(name)

Creates a new empty aggregate function set.

The return value should be destroyed with `duckdb_destroy_aggregate_function_set`.

# Arguments
- `name`: `Cstring` 

Returns: `duckdb_aggregate_function_set` The aggregate function set object.
"""
function duckdb_create_aggregate_function_set(name)
    return ccall((:duckdb_create_aggregate_function_set, libduckdb), duckdb_aggregate_function_set, (Cstring,), name)
end

"""
    duckdb_destroy_aggregate_function_set(aggregate_function_set)

Destroys the given aggregate function set object.

# Arguments
- `aggregate_function_set`: `Ref{duckdb_aggregate_function_set}` 

Returns: `Nothing` 
"""
function duckdb_destroy_aggregate_function_set(aggregate_function_set)
    return ccall(
        (:duckdb_destroy_aggregate_function_set, libduckdb),
        Cvoid,
        (Ref{duckdb_aggregate_function_set},),
        aggregate_function_set
    )
end

"""
    duckdb_add_aggregate_function_to_set(set, _function)

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.

# Arguments
- `set`: `duckdb_aggregate_function_set` The aggregate function set
- `_function`: `duckdb_aggregate_function` The function to add

Returns: `duckdb_state` 
"""
function duckdb_add_aggregate_function_to_set(set, _function)
    return ccall(
        (:duckdb_add_aggregate_function_to_set, libduckdb),
        duckdb_state,
        (duckdb_aggregate_function_set, duckdb_aggregate_function),
        set,
        _function
    )
end

"""
    duckdb_register_aggregate_function_set(con, set)

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.

# Arguments
- `con`: `duckdb_connection` The connection to register it in.
- `set`: `duckdb_aggregate_function_set` The function set to register

Returns: `duckdb_state` Whether or not the registration was successful.
"""
function duckdb_register_aggregate_function_set(con, set)
    return ccall(
        (:duckdb_register_aggregate_function_set, libduckdb),
        duckdb_state,
        (duckdb_connection, duckdb_aggregate_function_set),
        con,
        set
    )
end



# --------------------------------------------------------------------------------
# Table Functions
# --------------------------------------------------------------------------------

"""
    duckdb_create_table_function()

Creates a new empty table function.

The return value should be destroyed with `duckdb_destroy_table_function`.

# Arguments

Returns: `duckdb_table_function` The table function object.
"""
function duckdb_create_table_function()
    return ccall((:duckdb_create_table_function, libduckdb), duckdb_table_function, ())
end

"""
    duckdb_destroy_table_function(table_function)

Destroys the given table function object.

# Arguments
- `table_function`: `Ref{duckdb_table_function}` The table function to destroy

Returns: `Nothing` 
"""
function duckdb_destroy_table_function(table_function)
    return ccall((:duckdb_destroy_table_function, libduckdb), Cvoid, (Ref{duckdb_table_function},), table_function)
end

"""
    duckdb_table_function_set_name(table_function, name)

Sets the name of the given table function.

# Arguments
- `table_function`: `duckdb_table_function` The table function
- `name`: `Cstring` The name of the table function

Returns: `Nothing` 
"""
function duckdb_table_function_set_name(table_function, name)
    return ccall(
        (:duckdb_table_function_set_name, libduckdb),
        Cvoid,
        (duckdb_table_function, Cstring),
        table_function,
        name
    )
end

"""
    duckdb_table_function_add_parameter(table_function, _type)

Adds a parameter to the table function.

# Arguments
- `table_function`: `duckdb_table_function` The table function.
- `_type`: `duckdb_logical_type` The parameter type. Cannot contain INVALID.

Returns: `Nothing` 
"""
function duckdb_table_function_add_parameter(table_function, _type)
    return ccall(
        (:duckdb_table_function_add_parameter, libduckdb),
        Cvoid,
        (duckdb_table_function, duckdb_logical_type),
        table_function,
        _type
    )
end

"""
    duckdb_table_function_add_named_parameter(table_function, name, _type)

Adds a named parameter to the table function.

# Arguments
- `table_function`: `duckdb_table_function` The table function.
- `name`: `Cstring` The parameter name.
- `_type`: `duckdb_logical_type` The parameter type. Cannot contain INVALID.

Returns: `Nothing` 
"""
function duckdb_table_function_add_named_parameter(table_function, name, _type)
    return ccall(
        (:duckdb_table_function_add_named_parameter, libduckdb),
        Cvoid,
        (duckdb_table_function, Cstring, duckdb_logical_type),
        table_function,
        name,
        _type
    )
end

"""
    duckdb_table_function_set_extra_info(table_function, extra_info, destroy)

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

# Arguments
- `table_function`: `duckdb_table_function` The table function
- `extra_info`: `Ref{Cvoid}` The extra information
- `destroy`: `duckdb_delete_callback` The callback that will be called to destroy the extra information (if any)

Returns: `Nothing` 
"""
function duckdb_table_function_set_extra_info(table_function, extra_info, destroy)
    return ccall(
        (:duckdb_table_function_set_extra_info, libduckdb),
        Cvoid,
        (duckdb_table_function, Ref{Cvoid}, duckdb_delete_callback),
        table_function,
        extra_info,
        destroy
    )
end

"""
    duckdb_table_function_set_bind(table_function, bind)

Sets the bind function of the table function.

# Arguments
- `table_function`: `duckdb_table_function` The table function
- `bind`: `duckdb_table_function_bind` The bind function

Returns: `Nothing` 
"""
function duckdb_table_function_set_bind(table_function, bind)
    return ccall(
        (:duckdb_table_function_set_bind, libduckdb),
        Cvoid,
        (duckdb_table_function, duckdb_table_function_bind),
        table_function,
        bind
    )
end

"""
    duckdb_table_function_set_init(table_function, init)

Sets the init function of the table function.

# Arguments
- `table_function`: `duckdb_table_function` The table function
- `init`: `duckdb_table_function_init` The init function

Returns: `Nothing` 
"""
function duckdb_table_function_set_init(table_function, init)
    return ccall(
        (:duckdb_table_function_set_init, libduckdb),
        Cvoid,
        (duckdb_table_function, duckdb_table_function_init),
        table_function,
        init
    )
end

"""
    duckdb_table_function_set_local_init(table_function, init)

Sets the thread-local init function of the table function.

# Arguments
- `table_function`: `duckdb_table_function` The table function
- `init`: `duckdb_table_function_init` The init function

Returns: `Nothing` 
"""
function duckdb_table_function_set_local_init(table_function, init)
    return ccall(
        (:duckdb_table_function_set_local_init, libduckdb),
        Cvoid,
        (duckdb_table_function, duckdb_table_function_init),
        table_function,
        init
    )
end

"""
    duckdb_table_function_set_function(table_function, _function)

Sets the main function of the table function.

# Arguments
- `table_function`: `duckdb_table_function` The table function
- `_function`: `duckdb_table_function_ptr` The function

Returns: `Nothing` 
"""
function duckdb_table_function_set_function(table_function, _function)
    return ccall(
        (:duckdb_table_function_set_function, libduckdb),
        Cvoid,
        (duckdb_table_function, duckdb_table_function_ptr),
        table_function,
        _function
    )
end

"""
    duckdb_table_function_supports_projection_pushdown(table_function, pushdown)

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.

# Arguments
- `table_function`: `duckdb_table_function` The table function
- `pushdown`: `Bool` True if the table function supports projection pushdown, false otherwise.

Returns: `Nothing` 
"""
function duckdb_table_function_supports_projection_pushdown(table_function, pushdown)
    return ccall(
        (:duckdb_table_function_supports_projection_pushdown, libduckdb),
        Cvoid,
        (duckdb_table_function, Bool),
        table_function,
        pushdown
    )
end

"""
    duckdb_register_table_function(con, _function)

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.

# Arguments
- `con`: `duckdb_connection` The connection to register it in.
- `_function`: `duckdb_table_function` The function pointer

Returns: `duckdb_state` Whether or not the registration was successful.
"""
function duckdb_register_table_function(con, _function)
    return ccall(
        (:duckdb_register_table_function, libduckdb),
        duckdb_state,
        (duckdb_connection, duckdb_table_function),
        con,
        _function
    )
end



# --------------------------------------------------------------------------------
# Table Function Bind
# --------------------------------------------------------------------------------

"""
    duckdb_bind_get_extra_info(info)

Retrieves the extra info of the function as set in `duckdb_table_function_set_extra_info`.

# Arguments
- `info`: `duckdb_bind_info` The info object

Returns: `Ptr{Cvoid}` The extra info
"""
function duckdb_bind_get_extra_info(info)
    return ccall((:duckdb_bind_get_extra_info, libduckdb), Ptr{Cvoid}, (duckdb_bind_info,), info)
end

"""
    duckdb_table_function_get_client_context(info, out_context)

Retrieves the client context of the bind info of a table function.

# Arguments
- `info`: `duckdb_bind_info` The bind info object of the table function.
- `out_context`: `Ref{duckdb_client_context}` The client context of the bind info. Must be destroyed with `duckdb_destroy_client_context`.

Returns: `Nothing`
"""
function duckdb_table_function_get_client_context(info, out_context)
    return ccall(
        (:duckdb_scalar_function_get_client_context, libduckdb),
        Cvoid,
        (duckdb_bind_info, Ref{duckdb_client_context}),
        info,
        out_context
    )
end

"""
    duckdb_bind_add_result_column(info, name, _type)

Adds a result column to the output of the table function.

# Arguments
- `info`: `duckdb_bind_info` The table function's bind info.
- `name`: `Cstring` The column name.
- `_type`: `duckdb_logical_type` The logical column type.

Returns: `Nothing` 
"""
function duckdb_bind_add_result_column(info, name, _type)
    return ccall(
        (:duckdb_bind_add_result_column, libduckdb),
        Cvoid,
        (duckdb_bind_info, Cstring, duckdb_logical_type),
        info,
        name,
        _type
    )
end

"""
    duckdb_bind_get_parameter_count(info)

Retrieves the number of regular (non-named) parameters to the function.

# Arguments
- `info`: `duckdb_bind_info` The info object

Returns: `idx_t` The number of parameters
"""
function duckdb_bind_get_parameter_count(info)
    return ccall((:duckdb_bind_get_parameter_count, libduckdb), idx_t, (duckdb_bind_info,), info)
end

"""
    duckdb_bind_get_parameter(info, index)

Retrieves the parameter at the given index.

The result must be destroyed with `duckdb_destroy_value`.

# Arguments
- `info`: `duckdb_bind_info` The info object
- `index`: `idx_t` The index of the parameter to get

Returns: `duckdb_value` The value of the parameter. Must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_bind_get_parameter(info, index)
    return ccall((:duckdb_bind_get_parameter, libduckdb), duckdb_value, (duckdb_bind_info, idx_t), info, index)
end

"""
    duckdb_bind_get_named_parameter(info, name)

Retrieves a named parameter with the given name.

The result must be destroyed with `duckdb_destroy_value`.

# Arguments
- `info`: `duckdb_bind_info` The info object
- `name`: `Cstring` The name of the parameter

Returns: `duckdb_value` The value of the parameter. Must be destroyed with `duckdb_destroy_value`.
"""
function duckdb_bind_get_named_parameter(info, name)
    return ccall((:duckdb_bind_get_named_parameter, libduckdb), duckdb_value, (duckdb_bind_info, Cstring), info, name)
end

"""
    duckdb_bind_set_bind_data(info, bind_data, destroy)

Sets the user-provided bind data in the bind object of the table function. 
This object can be retrieved again during execution.

# Arguments
- `info`: `duckdb_bind_info` The bind info of the table function.
- `bind_data`: `Ref{Cvoid}` The bind data object.
- `destroy`: `duckdb_delete_callback` The callback to destroy the bind data (if any).

Returns: `Nothing` 
"""
function duckdb_bind_set_bind_data(info, bind_data, destroy)
    return ccall(
        (:duckdb_bind_set_bind_data, libduckdb),
        Cvoid,
        (duckdb_bind_info, Ref{Cvoid}, duckdb_delete_callback),
        info,
        bind_data,
        destroy
    )
end

"""
    duckdb_bind_set_cardinality(info, cardinality, is_exact)

Sets the cardinality estimate for the table function, used for optimization.

# Arguments
- `info`: `duckdb_bind_info` The bind data object.
- `cardinality`: `idx_t` 
- `is_exact`: `Bool` Whether or not the cardinality estimate is exact, or an approximation

Returns: `Nothing` 
"""
function duckdb_bind_set_cardinality(info, cardinality, is_exact)
    return ccall(
        (:duckdb_bind_set_cardinality, libduckdb),
        Cvoid,
        (duckdb_bind_info, idx_t, Bool),
        info,
        cardinality,
        is_exact
    )
end

"""
    duckdb_bind_set_error(info, error)

Report that an error has occurred while calling bind on a table function.

# Arguments
- `info`: `duckdb_bind_info` The info object
- `error`: `Cstring` The error message

Returns: `Nothing` 
"""
function duckdb_bind_set_error(info, error)
    return ccall((:duckdb_bind_set_error, libduckdb), Cvoid, (duckdb_bind_info, Cstring), info, error)
end



# --------------------------------------------------------------------------------
# Table Function Init
# --------------------------------------------------------------------------------

"""
    duckdb_init_get_extra_info(info)

Retrieves the extra info of the function as set in `duckdb_table_function_set_extra_info`.

# Arguments
- `info`: `duckdb_init_info` The info object

Returns: `Ptr{Cvoid}` The extra info
"""
function duckdb_init_get_extra_info(info)
    return ccall((:duckdb_init_get_extra_info, libduckdb), Ptr{Cvoid}, (duckdb_init_info,), info)
end

"""
    duckdb_init_get_bind_data(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.

# Arguments
- `info`: `duckdb_init_info` The info object

Returns: `Ptr{Cvoid}` The bind data object
"""
function duckdb_init_get_bind_data(info)
    return ccall((:duckdb_init_get_bind_data, libduckdb), Ptr{Cvoid}, (duckdb_init_info,), info)
end

"""
    duckdb_init_set_init_data(info, init_data, destroy)

Sets the user-provided init data in the init object. This object can be retrieved again during execution.

# Arguments
- `info`: `duckdb_init_info` The info object
- `init_data`: `Ref{Cvoid}` The init data object.
- `destroy`: `duckdb_delete_callback` The callback that will be called to destroy the init data (if any)

Returns: `Nothing` 
"""
function duckdb_init_set_init_data(info, init_data, destroy)
    return ccall(
        (:duckdb_init_set_init_data, libduckdb),
        Cvoid,
        (duckdb_init_info, Ref{Cvoid}, duckdb_delete_callback),
        info,
        init_data,
        destroy
    )
end

"""
    duckdb_init_get_column_count(info)

Returns the number of projected columns.

This function must be used if projection pushdown is enabled to figure out which columns to emit.

# Arguments
- `info`: `duckdb_init_info` The info object

Returns: `idx_t` The number of projected columns.
"""
function duckdb_init_get_column_count(info)
    return ccall((:duckdb_init_get_column_count, libduckdb), idx_t, (duckdb_init_info,), info)
end

"""
    duckdb_init_get_column_index(info, column_index)

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.

# Arguments
- `info`: `duckdb_init_info` The info object
- `column_index`: `idx_t` (1-based index) The index at which to get the projected column index, from 0..duckdb_init_get_column_count(info)

Returns: `idx_t` The column index of the projected column. (1-based index)
"""
function duckdb_init_get_column_index(info, column_index)
    return ccall((:duckdb_init_get_column_index, libduckdb), idx_t, (duckdb_init_info, idx_t), info, column_index - 1) +
           1
end

"""
    duckdb_init_set_max_threads(info, max_threads)

Sets how many threads can process this table function in parallel (default: 1)

# Arguments
- `info`: `duckdb_init_info` The info object
- `max_threads`: `idx_t` The maximum amount of threads that can process this table function

Returns: `Nothing` 
"""
function duckdb_init_set_max_threads(info, max_threads)
    return ccall((:duckdb_init_set_max_threads, libduckdb), Cvoid, (duckdb_init_info, idx_t), info, max_threads)
end

"""
    duckdb_init_set_error(info, error)

Report that an error has occurred while calling init.

# Arguments
- `info`: `duckdb_init_info` The info object
- `error`: `Cstring` The error message

Returns: `Nothing` 
"""
function duckdb_init_set_error(info, error)
    return ccall((:duckdb_init_set_error, libduckdb), Cvoid, (duckdb_init_info, Cstring), info, error)
end



# --------------------------------------------------------------------------------
# Table Function
# --------------------------------------------------------------------------------

"""
    duckdb_function_get_extra_info(info)

Retrieves the extra info of the function as set in `duckdb_table_function_set_extra_info`.

# Arguments
- `info`: `duckdb_function_info` The info object

Returns: `Ptr{Cvoid}` The extra info
"""
function duckdb_function_get_extra_info(info)
    return ccall((:duckdb_function_get_extra_info, libduckdb), Ptr{Cvoid}, (duckdb_function_info,), info)
end

"""
    duckdb_function_get_bind_data(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.

# Arguments
- `info`: `duckdb_function_info` The function info object.

Returns: `Ptr{Cvoid}` The bind data object.
"""
function duckdb_function_get_bind_data(info)
    return ccall((:duckdb_function_get_bind_data, libduckdb), Ptr{Cvoid}, (duckdb_function_info,), info)
end

"""
    duckdb_function_get_init_data(info)

Gets the init data set by `duckdb_init_set_init_data` during the init.

# Arguments
- `info`: `duckdb_function_info` The info object

Returns: `Ptr{Cvoid}` The init data object
"""
function duckdb_function_get_init_data(info)
    return ccall((:duckdb_function_get_init_data, libduckdb), Ptr{Cvoid}, (duckdb_function_info,), info)
end

"""
    duckdb_function_get_local_init_data(info)

Gets the thread-local init data set by `duckdb_init_set_init_data` during the local_init.

# Arguments
- `info`: `duckdb_function_info` The info object

Returns: `Ptr{Cvoid}` The init data object
"""
function duckdb_function_get_local_init_data(info)
    return ccall((:duckdb_function_get_local_init_data, libduckdb), Ptr{Cvoid}, (duckdb_function_info,), info)
end

"""
    duckdb_function_set_error(info, error)

Report that an error has occurred while executing the function.

# Arguments
- `info`: `duckdb_function_info` The info object
- `error`: `Cstring` The error message

Returns: `Nothing` 
"""
function duckdb_function_set_error(info, error)
    return ccall((:duckdb_function_set_error, libduckdb), Cvoid, (duckdb_function_info, Cstring), info, error)
end



# --------------------------------------------------------------------------------
# Replacement Scans
# --------------------------------------------------------------------------------

"""
    duckdb_add_replacement_scan(db, replacement, extra_data, delete_callback)

Add a replacement scan definition to the specified database.

# Arguments
- `db`: `duckdb_database` The database object to add the replacement scan to
- `replacement`: `duckdb_replacement_callback` The replacement scan callback
- `extra_data`: `Ref{Cvoid}` Extra data that is passed back into the specified callback
- `delete_callback`: `duckdb_delete_callback` The delete callback to call on the extra data, if any

Returns: `Nothing` 
"""
function duckdb_add_replacement_scan(db, replacement, extra_data, delete_callback)
    return ccall(
        (:duckdb_add_replacement_scan, libduckdb),
        Cvoid,
        (duckdb_database, duckdb_replacement_callback, Ref{Cvoid}, duckdb_delete_callback),
        db,
        replacement,
        extra_data,
        delete_callback
    )
end

"""
    duckdb_replacement_scan_set_function_name(info, function_name)

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.

# Arguments
- `info`: `duckdb_replacement_scan_info` The info object
- `function_name`: `Cstring` The function name to substitute.

Returns: `Nothing` 
"""
function duckdb_replacement_scan_set_function_name(info, function_name)
    return ccall(
        (:duckdb_replacement_scan_set_function_name, libduckdb),
        Cvoid,
        (duckdb_replacement_scan_info, Cstring),
        info,
        function_name
    )
end

"""
    duckdb_replacement_scan_add_parameter(info, parameter)

Adds a parameter to the replacement scan function.

# Arguments
- `info`: `duckdb_replacement_scan_info` The info object
- `parameter`: `duckdb_value` The parameter to add.

Returns: `Nothing` 
"""
function duckdb_replacement_scan_add_parameter(info, parameter)
    return ccall(
        (:duckdb_replacement_scan_add_parameter, libduckdb),
        Cvoid,
        (duckdb_replacement_scan_info, duckdb_value),
        info,
        parameter
    )
end

"""
    duckdb_replacement_scan_set_error(info, error)

Report that an error has occurred while executing the replacement scan.

# Arguments
- `info`: `duckdb_replacement_scan_info` The info object
- `error`: `Cstring` The error message

Returns: `Nothing` 
"""
function duckdb_replacement_scan_set_error(info, error)
    return ccall(
        (:duckdb_replacement_scan_set_error, libduckdb),
        Cvoid,
        (duckdb_replacement_scan_info, Cstring),
        info,
        error
    )
end



# --------------------------------------------------------------------------------
# Profiling Info
# --------------------------------------------------------------------------------

"""
    duckdb_get_profiling_info(connection)

Returns the root node of the profiling information. Returns nullptr, if profiling is not enabled.

# Arguments
- `connection`: `duckdb_connection` A connection object.

Returns: `duckdb_profiling_info` A profiling information object.
"""
function duckdb_get_profiling_info(connection)
    return ccall((:duckdb_get_profiling_info, libduckdb), duckdb_profiling_info, (duckdb_connection,), connection)
end

"""
    duckdb_profiling_info_get_value(info, key)

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).

# Arguments
- `info`: `duckdb_profiling_info` A profiling information object.
- `key`: `Cstring` The name of the requested metric.

Returns: `duckdb_value` The value of the metric. Must be freed with `duckdb_destroy_value`
"""
function duckdb_profiling_info_get_value(info, key)
    return ccall(
        (:duckdb_profiling_info_get_value, libduckdb),
        duckdb_value,
        (duckdb_profiling_info, Cstring),
        info,
        key
    )
end

"""
    duckdb_profiling_info_get_metrics(info)

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.

# Arguments
- `info`: `duckdb_profiling_info` A profiling information object.

Returns: `duckdb_value` The key-value metric map as a MAP duckdb_value.
"""
function duckdb_profiling_info_get_metrics(info)
    return ccall((:duckdb_profiling_info_get_metrics, libduckdb), duckdb_value, (duckdb_profiling_info,), info)
end

"""
    duckdb_profiling_info_get_child_count(info)

Returns the number of children in the current profiling info node.

# Arguments
- `info`: `duckdb_profiling_info` A profiling information object.

Returns: `idx_t` The number of children in the current node.
"""
function duckdb_profiling_info_get_child_count(info)
    return ccall((:duckdb_profiling_info_get_child_count, libduckdb), idx_t, (duckdb_profiling_info,), info)
end

"""
    duckdb_profiling_info_get_child(info, index)

Returns the child node at the specified index.

# Arguments
- `info`: `duckdb_profiling_info` A profiling information object.
- `index`: `idx_t` (1-based index) The index of the child node.

Returns: `duckdb_profiling_info` The child node at the specified index.
"""
function duckdb_profiling_info_get_child(info, index)
    return ccall(
        (:duckdb_profiling_info_get_child, libduckdb),
        duckdb_profiling_info,
        (duckdb_profiling_info, idx_t),
        info,
        index - 1
    )
end



# --------------------------------------------------------------------------------
# Appender
# --------------------------------------------------------------------------------

"""
    duckdb_appender_create(connection, schema, table, out_appender)

Creates an appender object.

Note that the object must be destroyed with `duckdb_appender_destroy`.

# Arguments
- `connection`: `duckdb_connection` The connection context to create the appender in.
- `schema`: `Cstring` The schema of the table to append to, or `nullptr` for the default schema.
- `table`: `Cstring` The table name to append to.
- `out_appender`: `Ref{duckdb_appender}` The resulting appender object.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_appender_create(connection, schema, table, out_appender)
    return ccall(
        (:duckdb_appender_create, libduckdb),
        duckdb_state,
        (duckdb_connection, Cstring, Cstring, Ref{duckdb_appender}),
        connection,
        schema,
        table,
        out_appender
    )
end

"""
    duckdb_appender_create_ext(connection, catalog, schema, table, out_appender)

Creates an appender object.

Note that the object must be destroyed with `duckdb_appender_destroy`.

# Arguments
- `connection`: `duckdb_connection` The connection context to create the appender in.
- `catalog`: `Cstring` The catalog of the table to append to, or `nullptr` for the default catalog.
- `schema`: `Cstring` The schema of the table to append to, or `nullptr` for the default schema.
- `table`: `Cstring` The table name to append to.
- `out_appender`: `Ref{duckdb_appender}` The resulting appender object.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_appender_create_ext(connection, catalog, schema, table, out_appender)
    return ccall(
        (:duckdb_appender_create_ext, libduckdb),
        duckdb_state,
        (duckdb_connection, Cstring, Cstring, Cstring, Ref{duckdb_appender}),
        connection,
        catalog,
        schema,
        table,
        out_appender
    )
end

"""
    duckdb_appender_column_count(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.

# Arguments
- `appender`: `duckdb_appender` The appender to get the column count from.

Returns: `idx_t` The number of columns in the data chunks.
"""
function duckdb_appender_column_count(appender)
    return ccall((:duckdb_appender_column_count, libduckdb), idx_t, (duckdb_appender,), appender)
end

"""
    duckdb_appender_column_type(appender, col_idx)

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`.

# Arguments
- `appender`: `duckdb_appender` The appender to get the column type from.
- `col_idx`: `idx_t` (1-based index) The index of the column to get the type of.

Returns: `duckdb_logical_type` The `duckdb_logical_type` of the column.
"""
function duckdb_appender_column_type(appender, col_idx)
    return ccall(
        (:duckdb_appender_column_type, libduckdb),
        duckdb_logical_type,
        (duckdb_appender, idx_t),
        appender,
        col_idx - 1
    )
end

"""
    duckdb_appender_error(appender)

Returns the error message associated with the given 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.

# Arguments
- `appender`: `duckdb_appender` The appender to get the error from.

Returns: `Cstring` The error message, or `nullptr` if there is none.
"""
function duckdb_appender_error(appender)
    return ccall((:duckdb_appender_error, libduckdb), Cstring, (duckdb_appender,), appender)
end

"""
    duckdb_appender_flush(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 to obtain the error message followed by
duckdb_appender_destroy to destroy the invalidated appender.

# Arguments
- `appender`: `duckdb_appender` The appender to flush.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_appender_flush(appender)
    return ccall((:duckdb_appender_flush, libduckdb), duckdb_state, (duckdb_appender,), appender)
end

"""
    duckdb_appender_close(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 to obtain the error message followed by duckdb_appender_destroy to destroy the invalidated
appender.

# Arguments
- `appender`: `duckdb_appender` The appender to flush and close.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_appender_close(appender)
    return ccall((:duckdb_appender_close, libduckdb), duckdb_state, (duckdb_appender,), appender)
end

"""
    duckdb_appender_destroy(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.

# Arguments
- `appender`: `Ref{duckdb_appender}` The appender to flush, close and destroy.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_appender_destroy(appender)
    return ccall((:duckdb_appender_destroy, libduckdb), duckdb_state, (Ref{duckdb_appender},), appender)
end

"""
    duckdb_appender_add_column(appender, name)

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.

# Arguments
- `appender`: `duckdb_appender` The appender to add the column to.
- `name`: `Cstring` 

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_appender_add_column(appender, name)
    return ccall((:duckdb_appender_add_column, libduckdb), duckdb_state, (duckdb_appender, Cstring), appender, name)
end

"""
    duckdb_appender_clear_columns(appender)

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.

# Arguments
- `appender`: `duckdb_appender` The appender to clear the columns from.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_appender_clear_columns(appender)
    return ccall((:duckdb_appender_clear_columns, libduckdb), duckdb_state, (duckdb_appender,), appender)
end

"""
    duckdb_appender_begin_row(appender)

A nop function, provided for backwards compatibility reasons. Does nothing. Only `duckdb_appender_end_row` is required.

# Arguments
- `appender`: `duckdb_appender` 

Returns: `duckdb_state` 
"""
function duckdb_appender_begin_row(appender)
    return ccall((:duckdb_appender_begin_row, libduckdb), duckdb_state, (duckdb_appender,), appender)
end

"""
    duckdb_appender_end_row(appender)

Finish the current row of appends. After end_row is called, the next row can be appended.

# Arguments
- `appender`: `duckdb_appender` The appender.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_appender_end_row(appender)
    return ccall((:duckdb_appender_end_row, libduckdb), duckdb_state, (duckdb_appender,), appender)
end

"""
    duckdb_append_default(appender)

Append a DEFAULT value (NULL if DEFAULT not available for column) to the appender.

# Arguments
- `appender`: `duckdb_appender` 

Returns: `duckdb_state` 
"""
function duckdb_append_default(appender)
    return ccall((:duckdb_append_default, libduckdb), duckdb_state, (duckdb_appender,), appender)
end

"""
    duckdb_append_default_to_chunk(appender, chunk, col, row)

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.

# Arguments
- `appender`: `duckdb_appender` The appender to get the default value from.
- `chunk`: `duckdb_data_chunk` The data chunk to append the default value to.
- `col`: `idx_t` (1-based index) The chunk column index to append the default value to.
- `row`: `idx_t` (1-based index) The chunk row index to append the default value to.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_append_default_to_chunk(appender, chunk, col, row)
    return ccall(
        (:duckdb_append_default_to_chunk, libduckdb),
        duckdb_state,
        (duckdb_appender, duckdb_data_chunk, idx_t, idx_t),
        appender,
        chunk,
        col - 1,
        row - 1
    )
end

"""
    duckdb_append_bool(appender, value)

Append a bool value to the appender.

# Arguments
- `appender`: `duckdb_appender` 
- `value`: `Bool` 

Returns: `duckdb_state` 
"""
function duckdb_append_bool(appender, value)
    return ccall((:duckdb_append_bool, libduckdb), duckdb_state, (duckdb_appender, Bool), appender, value)
end

"""
    duckdb_append_int8(appender, value)

Append an int8_t value to the appender.

# Arguments
- `appender`: `duckdb_appender` 
- `value`: `Int8` 

Returns: `duckdb_state` 
"""
function duckdb_append_int8(appender, value)
    return ccall((:duckdb_append_int8, libduckdb), duckdb_state, (duckdb_appender, Int8), appender, value)
end

"""
    duckdb_append_int16(appender, value)

Append an int16_t value to the appender.

# Arguments
- `appender`: `duckdb_appender` 
- `value`: `Int16` 

Returns: `duckdb_state` 
"""
function duckdb_append_int16(appender, value)
    return ccall((:duckdb_append_int16, libduckdb), duckdb_state, (duckdb_appender, Int16), appender, value)
end

"""
    duckdb_append_int32(appender, value)

Append an int32_t value to the appender.

# Arguments
- `appender`: `duckdb_appender` 
- `value`: `Int32` 

Returns: `duckdb_state` 
"""
function duckdb_append_int32(appender, value)
    return ccall((:duckdb_append_int32, libduckdb), duckdb_state, (duckdb_appender, Int32), appender, value)
end

"""
    duckdb_append_int64(appender, value)

Append an int64_t value to the appender.

# Arguments
- `appender`: `duckdb_appender` 
- `value`: `Int64` 

Returns: `duckdb_state` 
"""
function duckdb_append_int64(appender, value)
    return ccall((:duckdb_append_int64, libduckdb), duckdb_state, (duckdb_appender, Int64), appender, value)
end

"""
    duckdb_append_hugeint(appender, value)

Append a duckdb_hugeint value to the appender.

# Arguments
- `appender`: `duckdb_appender` 
- `value`: `duckdb_hugeint` 

Returns: `duckdb_state` 
"""
function duckdb_append_hugeint(appender, value)
    return ccall((:duckdb_append_hugeint, libduckdb), duckdb_state, (duckdb_appender, duckdb_hugeint), appender, value)
end

"""
    duckdb_append_uint8(appender, value)

Append a uint8_t value to the appender.

# Arguments
- `appender`: `duckdb_appender` 
- `value`: `UInt8` 

Returns: `duckdb_state` 
"""
function duckdb_append_uint8(appender, value)
    return ccall((:duckdb_append_uint8, libduckdb), duckdb_state, (duckdb_appender, UInt8), appender, value)
end

"""
    duckdb_append_uint16(appender, value)

Append a uint16_t value to the appender.

# Arguments
- `appender`: `duckdb_appender` 
- `value`: `UInt16` 

Returns: `duckdb_state` 
"""
function duckdb_append_uint16(appender, value)
    return ccall((:duckdb_append_uint16, libduckdb), duckdb_state, (duckdb_appender, UInt16), appender, value)
end

"""
    duckdb_append_uint32(appender, value)

Append a uint32_t value to the appender.

# Arguments
- `appender`: `duckdb_appender` 
- `value`: `UInt32` 

Returns: `duckdb_state` 
"""
function duckdb_append_uint32(appender, value)
    return ccall((:duckdb_append_uint32, libduckdb), duckdb_state, (duckdb_appender, UInt32), appender, value)
end

"""
    duckdb_append_uint64(appender, value)

Append a uint64_t value to the appender.

# Arguments
- `appender`: `duckdb_appender` 
- `value`: `UInt64` 

Returns: `duckdb_state` 
"""
function duckdb_append_uint64(appender, value)
    return ccall((:duckdb_append_uint64, libduckdb), duckdb_state, (duckdb_appender, UInt64), appender, value)
end

"""
    duckdb_append_uhugeint(appender, value)

Append a duckdb_uhugeint value to the appender.

# Arguments
- `appender`: `duckdb_appender` 
- `value`: `duckdb_uhugeint` 

Returns: `duckdb_state` 
"""
function duckdb_append_uhugeint(appender, value)
    return ccall(
        (:duckdb_append_uhugeint, libduckdb),
        duckdb_state,
        (duckdb_appender, duckdb_uhugeint),
        appender,
        value
    )
end

"""
    duckdb_append_float(appender, value)

Append a float value to the appender.

# Arguments
- `appender`: `duckdb_appender` 
- `value`: `Float32` 

Returns: `duckdb_state` 
"""
function duckdb_append_float(appender, value)
    return ccall((:duckdb_append_float, libduckdb), duckdb_state, (duckdb_appender, Float32), appender, value)
end

"""
    duckdb_append_double(appender, value)

Append a double value to the appender.

# Arguments
- `appender`: `duckdb_appender` 
- `value`: `Float64` 

Returns: `duckdb_state` 
"""
function duckdb_append_double(appender, value)
    return ccall((:duckdb_append_double, libduckdb), duckdb_state, (duckdb_appender, Float64), appender, value)
end

"""
    duckdb_append_date(appender, value)

Append a duckdb_date value to the appender.

# Arguments
- `appender`: `duckdb_appender` 
- `value`: `duckdb_date` 

Returns: `duckdb_state` 
"""
function duckdb_append_date(appender, value)
    return ccall((:duckdb_append_date, libduckdb), duckdb_state, (duckdb_appender, duckdb_date), appender, value)
end

"""
    duckdb_append_time(appender, value)

Append a duckdb_time value to the appender.

# Arguments
- `appender`: `duckdb_appender` 
- `value`: `duckdb_time` 

Returns: `duckdb_state` 
"""
function duckdb_append_time(appender, value)
    return ccall((:duckdb_append_time, libduckdb), duckdb_state, (duckdb_appender, duckdb_time), appender, value)
end

"""
    duckdb_append_timestamp(appender, value)

Append a duckdb_timestamp value to the appender.

# Arguments
- `appender`: `duckdb_appender` 
- `value`: `duckdb_timestamp` 

Returns: `duckdb_state` 
"""
function duckdb_append_timestamp(appender, value)
    return ccall(
        (:duckdb_append_timestamp, libduckdb),
        duckdb_state,
        (duckdb_appender, duckdb_timestamp),
        appender,
        value
    )
end

"""
    duckdb_append_interval(appender, value)

Append a duckdb_interval value to the appender.

# Arguments
- `appender`: `duckdb_appender` 
- `value`: `duckdb_interval` 

Returns: `duckdb_state` 
"""
function duckdb_append_interval(appender, value)
    return ccall(
        (:duckdb_append_interval, libduckdb),
        duckdb_state,
        (duckdb_appender, duckdb_interval),
        appender,
        value
    )
end

"""
    duckdb_append_varchar(appender, val)

Append a varchar value to the appender.

# Arguments
- `appender`: `duckdb_appender` 
- `val`: `Cstring` 

Returns: `duckdb_state` 
"""
function duckdb_append_varchar(appender, val)
    return ccall((:duckdb_append_varchar, libduckdb), duckdb_state, (duckdb_appender, Cstring), appender, val)
end

"""
    duckdb_append_varchar_length(appender, val, length)

Append a varchar value to the appender.

# Arguments
- `appender`: `duckdb_appender` 
- `val`: `Cstring` 
- `length`: `idx_t` 

Returns: `duckdb_state` 
"""
function duckdb_append_varchar_length(appender, val, length)
    return ccall(
        (:duckdb_append_varchar_length, libduckdb),
        duckdb_state,
        (duckdb_appender, Cstring, idx_t),
        appender,
        val,
        length
    )
end

"""
    duckdb_append_blob(appender, data, length)

Append a blob value to the appender.

# Arguments
- `appender`: `duckdb_appender` 
- `data`: `Ref{Cvoid}` 
- `length`: `idx_t` 

Returns: `duckdb_state` 
"""
function duckdb_append_blob(appender, data, length)
    return ccall(
        (:duckdb_append_blob, libduckdb),
        duckdb_state,
        (duckdb_appender, Ref{Cvoid}, idx_t),
        appender,
        data,
        length
    )
end

"""
    duckdb_append_null(appender)

Append a NULL value to the appender (of any type).

# Arguments
- `appender`: `duckdb_appender` 

Returns: `duckdb_state` 
"""
function duckdb_append_null(appender)
    return ccall((:duckdb_append_null, libduckdb), duckdb_state, (duckdb_appender,), appender)
end

"""
    duckdb_append_value(appender, value)

Append a duckdb_value to the appender.

# Arguments
- `appender`: `duckdb_appender` 
- `value`: `duckdb_value` 

Returns: `duckdb_state` 
"""
function duckdb_append_value(appender, value)
    return ccall((:duckdb_append_value, libduckdb), duckdb_state, (duckdb_appender, duckdb_value), appender, value)
end

"""
    duckdb_append_data_chunk(appender, chunk)

Appends a pre-filled data chunk to the specified appender.
 Attempts casting, if the data chunk types do not match the active appender types.

# Arguments
- `appender`: `duckdb_appender` The appender to append to.
- `chunk`: `duckdb_data_chunk` The data chunk to append.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_append_data_chunk(appender, chunk)
    return ccall(
        (:duckdb_append_data_chunk, libduckdb),
        duckdb_state,
        (duckdb_appender, duckdb_data_chunk),
        appender,
        chunk
    )
end



# --------------------------------------------------------------------------------
# Table Description
# --------------------------------------------------------------------------------

"""
    duckdb_table_description_create(connection, schema, table, out)

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`.

# Arguments
- `connection`: `duckdb_connection` The connection context.
- `schema`: `Cstring` The schema of the table, or `nullptr` for the default schema.
- `table`: `Cstring` The table name.
- `out`: `Ref{duckdb_table_description}` The resulting table description object.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_table_description_create(connection, schema, table, out)
    return ccall(
        (:duckdb_table_description_create, libduckdb),
        duckdb_state,
        (duckdb_connection, Cstring, Cstring, Ref{duckdb_table_description}),
        connection,
        schema,
        table,
        out
    )
end

"""
    duckdb_table_description_create_ext(connection, catalog, schema, table, 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`.

# Arguments
- `connection`: `duckdb_connection` The connection context.
- `catalog`: `Cstring` The catalog (database) name of the table, or `nullptr` for the default catalog.
- `schema`: `Cstring` The schema of the table, or `nullptr` for the default schema.
- `table`: `Cstring` The table name.
- `out`: `Ref{duckdb_table_description}` The resulting table description object.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_table_description_create_ext(connection, catalog, schema, table, out)
    return ccall(
        (:duckdb_table_description_create_ext, libduckdb),
        duckdb_state,
        (duckdb_connection, Cstring, Cstring, Cstring, Ref{duckdb_table_description}),
        connection,
        catalog,
        schema,
        table,
        out
    )
end

"""
    duckdb_table_description_destroy(table_description)

Destroy the TableDescription object.

# Arguments
- `table_description`: `Ref{duckdb_table_description}` The table_description to destroy.

Returns: `Nothing` 
"""
function duckdb_table_description_destroy(table_description)
    return ccall(
        (:duckdb_table_description_destroy, libduckdb),
        Cvoid,
        (Ref{duckdb_table_description},),
        table_description
    )
end

"""
    duckdb_table_description_error(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.

# Arguments
- `table_description`: `duckdb_table_description` The table_description to get the error from.

Returns: `Cstring` The error message, or `nullptr` if there is none.
"""
function duckdb_table_description_error(table_description)
    return ccall((:duckdb_table_description_error, libduckdb), Cstring, (duckdb_table_description,), table_description)
end

"""
    duckdb_column_has_default(table_description, index, out)

Check if the column at 'index' index of the table has a DEFAULT expression.

# Arguments
- `table_description`: `duckdb_table_description` The table_description to query.
- `index`: `idx_t` (1-based index) The index of the column to query.
- `out`: `Ref{Bool}` The out-parameter used to store the result.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_column_has_default(table_description, index, out)
    return ccall(
        (:duckdb_column_has_default, libduckdb),
        duckdb_state,
        (duckdb_table_description, idx_t, Ref{Bool}),
        table_description,
        index - 1,
        out
    )
end

"""
    duckdb_table_description_get_column_name(table_description, index)

Obtain the column name at 'index'.
The out result must be destroyed with `duckdb_free`.

# Arguments
- `table_description`: `duckdb_table_description` The table_description to query.
- `index`: `idx_t` (1-based index) The index of the column to query.

Returns: `Cstring` The column name.
"""
function duckdb_table_description_get_column_name(table_description, index)
    return ccall(
        (:duckdb_table_description_get_column_name, libduckdb),
        Cstring,
        (duckdb_table_description, idx_t),
        table_description,
        index - 1
    )
end



# --------------------------------------------------------------------------------
# Arrow Interface
# --------------------------------------------------------------------------------

"""
    duckdb_query_arrow(connection, query, out_result)

**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.

# Arguments
- `connection`: `duckdb_connection` The connection to perform the query in.
- `query`: `Cstring` The SQL query to run.
- `out_result`: `Ref{duckdb_arrow}` The query result.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_query_arrow(connection, query, out_result)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_query_arrow
    )
    return ccall(
        (:duckdb_query_arrow, libduckdb),
        duckdb_state,
        (duckdb_connection, Cstring, Ref{duckdb_arrow}),
        connection,
        query,
        out_result
    )
end

"""
    duckdb_query_arrow_schema(result, out_schema)

**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.

# Arguments
- `result`: `duckdb_arrow` The result to fetch the schema from.
- `out_schema`: `Ref{duckdb_arrow_schema}` The output schema.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_query_arrow_schema(result, out_schema)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_query_arrow_schema
    )
    return ccall(
        (:duckdb_query_arrow_schema, libduckdb),
        duckdb_state,
        (duckdb_arrow, Ref{duckdb_arrow_schema}),
        result,
        out_schema
    )
end

"""
    duckdb_prepared_arrow_schema(prepared, 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.

# Arguments
- `prepared`: `duckdb_prepared_statement` The prepared statement to fetch the schema from.
- `out_schema`: `Ref{duckdb_arrow_schema}` The output schema.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_prepared_arrow_schema(prepared, out_schema)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_prepared_arrow_schema
    )
    return ccall(
        (:duckdb_prepared_arrow_schema, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, Ref{duckdb_arrow_schema}),
        prepared,
        out_schema
    )
end

"""
    duckdb_result_arrow_array(result, chunk, out_array)

**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.

# Arguments
- `result`: `duckdb_result` The result object the data chunk have been fetched from.
- `chunk`: `duckdb_data_chunk` The data chunk to convert.
- `out_array`: `Ref{duckdb_arrow_array}` The output array.

Returns: `Nothing` 
"""
function duckdb_result_arrow_array(result, chunk, out_array)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_result_arrow_array
    )
    return ccall(
        (:duckdb_result_arrow_array, libduckdb),
        Cvoid,
        (duckdb_result, duckdb_data_chunk, Ref{duckdb_arrow_array}),
        result,
        chunk,
        out_array
    )
end

"""
    duckdb_query_arrow_array(result, 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.

# Arguments
- `result`: `duckdb_arrow` The result to fetch the array from.
- `out_array`: `Ref{duckdb_arrow_array}` The output array.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_query_arrow_array(result, out_array)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_query_arrow_array
    )
    return ccall(
        (:duckdb_query_arrow_array, libduckdb),
        duckdb_state,
        (duckdb_arrow, Ref{duckdb_arrow_array}),
        result,
        out_array
    )
end

"""
    duckdb_arrow_column_count(result)

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

Returns the number of columns present in the arrow result object.

# Arguments
- `result`: `duckdb_arrow` The result object.

Returns: `idx_t` The number of columns present in the result object.
"""
function duckdb_arrow_column_count(result)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_arrow_column_count
    )
    return ccall((:duckdb_arrow_column_count, libduckdb), idx_t, (duckdb_arrow,), result)
end

"""
    duckdb_arrow_row_count(result)

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

Returns the number of rows present in the arrow result object.

# Arguments
- `result`: `duckdb_arrow` The result object.

Returns: `idx_t` The number of rows present in the result object.
"""
function duckdb_arrow_row_count(result)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_arrow_row_count
    )
    return ccall((:duckdb_arrow_row_count, libduckdb), idx_t, (duckdb_arrow,), result)
end

"""
    duckdb_arrow_rows_changed(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.

# Arguments
- `result`: `duckdb_arrow` The result object.

Returns: `idx_t` The number of rows changed.
"""
function duckdb_arrow_rows_changed(result)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_arrow_rows_changed
    )
    return ccall((:duckdb_arrow_rows_changed, libduckdb), idx_t, (duckdb_arrow,), result)
end

"""
    duckdb_query_arrow_error(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.

# Arguments
- `result`: `duckdb_arrow` The result object to fetch the error from.

Returns: `Cstring` The error of the result.
"""
function duckdb_query_arrow_error(result)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_query_arrow_error
    )
    return ccall((:duckdb_query_arrow_error, libduckdb), Cstring, (duckdb_arrow,), result)
end

"""
    duckdb_destroy_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.

# Arguments
- `result`: `Ref{duckdb_arrow}` The result to destroy.

Returns: `Nothing` 
"""
function duckdb_destroy_arrow(result)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_destroy_arrow
    )
    return ccall((:duckdb_destroy_arrow, libduckdb), Cvoid, (Ref{duckdb_arrow},), result)
end

"""
    duckdb_destroy_arrow_stream(stream_p)

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

Releases the arrow array stream and de-allocates its memory.

# Arguments
- `stream_p`: `Ref{duckdb_arrow_stream}` The arrow array stream to destroy.

Returns: `Nothing` 
"""
function duckdb_destroy_arrow_stream(stream_p)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_destroy_arrow_stream
    )
    return ccall((:duckdb_destroy_arrow_stream, libduckdb), Cvoid, (Ref{duckdb_arrow_stream},), stream_p)
end

"""
    duckdb_execute_prepared_arrow(prepared_statement, out_result)

**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.

# Arguments
- `prepared_statement`: `duckdb_prepared_statement` The prepared statement to execute.
- `out_result`: `Ref{duckdb_arrow}` The query result.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_execute_prepared_arrow(prepared_statement, out_result)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_execute_prepared_arrow
    )
    return ccall(
        (:duckdb_execute_prepared_arrow, libduckdb),
        duckdb_state,
        (duckdb_prepared_statement, Ref{duckdb_arrow}),
        prepared_statement,
        out_result
    )
end

"""
    duckdb_arrow_scan(connection, table_name, arrow)

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

Scans the Arrow stream and creates a view with the given name.

# Arguments
- `connection`: `duckdb_connection` The connection on which to execute the scan.
- `table_name`: `Cstring` Name of the temporary view to create.
- `arrow`: `duckdb_arrow_stream` Arrow stream wrapper.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_arrow_scan(connection, table_name, arrow)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_arrow_scan
    )
    return ccall(
        (:duckdb_arrow_scan, libduckdb),
        duckdb_state,
        (duckdb_connection, Cstring, duckdb_arrow_stream),
        connection,
        table_name,
        arrow
    )
end

"""
    duckdb_arrow_array_scan(connection, table_name, arrow_schema, arrow_array, out_stream)

**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.

# Arguments
- `connection`: `duckdb_connection` The connection on which to execute the scan.
- `table_name`: `Cstring` Name of the temporary view to create.
- `arrow_schema`: `duckdb_arrow_schema` Arrow schema wrapper.
- `arrow_array`: `duckdb_arrow_array` Arrow array wrapper.
- `out_stream`: `Ref{duckdb_arrow_stream}` Output array stream that wraps around the passed schema, for releasing/deleting once done.

Returns: `duckdb_state` `DuckDBSuccess` on success or `DuckDBError` on failure.
"""
function duckdb_arrow_array_scan(connection, table_name, arrow_schema, arrow_array, out_stream)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_arrow_array_scan
    )
    return ccall(
        (:duckdb_arrow_array_scan, libduckdb),
        duckdb_state,
        (duckdb_connection, Cstring, duckdb_arrow_schema, duckdb_arrow_array, Ref{duckdb_arrow_stream}),
        connection,
        table_name,
        arrow_schema,
        arrow_array,
        out_stream
    )
end



# --------------------------------------------------------------------------------
# Threading Information
# --------------------------------------------------------------------------------

"""
    duckdb_execute_tasks(database, max_tasks)

Execute DuckDB tasks on this thread.

Will return after `max_tasks` have been executed, or if there are no more tasks present.

# Arguments
- `database`: `duckdb_database` The database object to execute tasks for
- `max_tasks`: `idx_t` The maximum amount of tasks to execute

Returns: `Nothing` 
"""
function duckdb_execute_tasks(database, max_tasks)
    return ccall((:duckdb_execute_tasks, libduckdb), Cvoid, (duckdb_database, idx_t), database, max_tasks)
end

"""
    duckdb_create_task_state(database)

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.

# Arguments
- `database`: `duckdb_database` The database object to create the task state for

Returns: `duckdb_task_state` The task state that can be used with duckdb_execute_tasks_state.
"""
function duckdb_create_task_state(database)
    return ccall((:duckdb_create_task_state, libduckdb), duckdb_task_state, (duckdb_database,), database)
end

"""
    duckdb_execute_tasks_state(state)

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.

# Arguments
- `state`: `duckdb_task_state` The task state of the executor

Returns: `Nothing` 
"""
function duckdb_execute_tasks_state(state)
    return ccall((:duckdb_execute_tasks_state, libduckdb), Cvoid, (duckdb_task_state,), state)
end

"""
    duckdb_execute_n_tasks_state(state, max_tasks)

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.

# Arguments
- `state`: `duckdb_task_state` The task state of the executor
- `max_tasks`: `idx_t` The maximum amount of tasks to execute

Returns: `idx_t` The amount of tasks that have actually been executed
"""
function duckdb_execute_n_tasks_state(state, max_tasks)
    return ccall((:duckdb_execute_n_tasks_state, libduckdb), idx_t, (duckdb_task_state, idx_t), state, max_tasks)
end

"""
    duckdb_finish_execution(state)

Finish execution on a specific task.

# Arguments
- `state`: `duckdb_task_state` The task state to finish execution

Returns: `Nothing` 
"""
function duckdb_finish_execution(state)
    return ccall((:duckdb_finish_execution, libduckdb), Cvoid, (duckdb_task_state,), state)
end

"""
    duckdb_task_state_is_finished(state)

Check if the provided duckdb_task_state has finished execution

# Arguments
- `state`: `duckdb_task_state` The task state to inspect

Returns: `Bool` Whether or not duckdb_finish_execution has been called on the task state
"""
function duckdb_task_state_is_finished(state)
    return ccall((:duckdb_task_state_is_finished, libduckdb), Bool, (duckdb_task_state,), state)
end

"""
    duckdb_destroy_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.

# Arguments
- `state`: `duckdb_task_state` The task state to clean up

Returns: `Nothing` 
"""
function duckdb_destroy_task_state(state)
    return ccall((:duckdb_destroy_task_state, libduckdb), Cvoid, (duckdb_task_state,), state)
end

"""
    duckdb_execution_is_finished(con)

Returns true if the execution of the current query is finished.

# Arguments
- `con`: `duckdb_connection` The connection on which to check

Returns: `Bool` 
"""
function duckdb_execution_is_finished(con)
    return ccall((:duckdb_execution_is_finished, libduckdb), Bool, (duckdb_connection,), con)
end



# --------------------------------------------------------------------------------
# Streaming Result Interface
# --------------------------------------------------------------------------------

"""
    duckdb_stream_fetch_chunk(result)

**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.

# Arguments
- `result`: `duckdb_result` The result object to fetch the data chunk from.

Returns: `duckdb_data_chunk` The resulting data chunk. Returns `NULL` if the result has an error.
"""
function duckdb_stream_fetch_chunk(result)
    Base.depwarn(
        "**DEPRECATION NOTICE**: This method is scheduled for removal in a future release.",
        :duckdb_stream_fetch_chunk
    )
    return ccall((:duckdb_stream_fetch_chunk, libduckdb), duckdb_data_chunk, (duckdb_result,), result)
end

"""
    duckdb_fetch_chunk(result)

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.

# Arguments
- `result`: `duckdb_result` The result object to fetch the data chunk from.

Returns: `duckdb_data_chunk` The resulting data chunk. Returns `NULL` if the result has an error.
"""
function duckdb_fetch_chunk(result)
    return ccall((:duckdb_fetch_chunk, libduckdb), duckdb_data_chunk, (duckdb_result,), result)
end



# --------------------------------------------------------------------------------
# Cast Functions
# --------------------------------------------------------------------------------

"""
    duckdb_create_cast_function()

Creates a new cast function object.

# Arguments

Returns: `duckdb_cast_function` The cast function object.
"""
function duckdb_create_cast_function()
    return ccall((:duckdb_create_cast_function, libduckdb), duckdb_cast_function, ())
end

"""
    duckdb_cast_function_set_source_type(cast_function, source_type)

Sets the source type of the cast function.

# Arguments
- `cast_function`: `duckdb_cast_function` The cast function object.
- `source_type`: `duckdb_logical_type` The source type to set.

Returns: `Nothing` 
"""
function duckdb_cast_function_set_source_type(cast_function, source_type)
    return ccall(
        (:duckdb_cast_function_set_source_type, libduckdb),
        Cvoid,
        (duckdb_cast_function, duckdb_logical_type),
        cast_function,
        source_type
    )
end

"""
    duckdb_cast_function_set_target_type(cast_function, target_type)

Sets the target type of the cast function.

# Arguments
- `cast_function`: `duckdb_cast_function` The cast function object.
- `target_type`: `duckdb_logical_type` The target type to set.

Returns: `Nothing` 
"""
function duckdb_cast_function_set_target_type(cast_function, target_type)
    return ccall(
        (:duckdb_cast_function_set_target_type, libduckdb),
        Cvoid,
        (duckdb_cast_function, duckdb_logical_type),
        cast_function,
        target_type
    )
end

"""
    duckdb_cast_function_set_implicit_cast_cost(cast_function, cost)

Sets the \"cost\" of implicitly casting the source type to the target type using this function.

# Arguments
- `cast_function`: `duckdb_cast_function` The cast function object.
- `cost`: `Int64` The cost to set.

Returns: `Nothing` 
"""
function duckdb_cast_function_set_implicit_cast_cost(cast_function, cost)
    return ccall(
        (:duckdb_cast_function_set_implicit_cast_cost, libduckdb),
        Cvoid,
        (duckdb_cast_function, Int64),
        cast_function,
        cost
    )
end

"""
    duckdb_cast_function_set_function(cast_function, _function)

Sets the actual cast function to use.

# Arguments
- `cast_function`: `duckdb_cast_function` The cast function object.
- `_function`: `duckdb_cast_function_ptr` The function to set.

Returns: `Nothing` 
"""
function duckdb_cast_function_set_function(cast_function, _function)
    return ccall(
        (:duckdb_cast_function_set_function, libduckdb),
        Cvoid,
        (duckdb_cast_function, duckdb_cast_function_ptr),
        cast_function,
        _function
    )
end

"""
    duckdb_cast_function_set_extra_info(cast_function, extra_info, destroy)

Assigns extra information to the cast function that can be fetched during execution, etc.

# Arguments
- `cast_function`: `duckdb_cast_function` 
- `extra_info`: `Ref{Cvoid}` The extra information
- `destroy`: `duckdb_delete_callback` The callback that will be called to destroy the extra information (if any)

Returns: `Nothing` 
"""
function duckdb_cast_function_set_extra_info(cast_function, extra_info, destroy)
    return ccall(
        (:duckdb_cast_function_set_extra_info, libduckdb),
        Cvoid,
        (duckdb_cast_function, Ref{Cvoid}, duckdb_delete_callback),
        cast_function,
        extra_info,
        destroy
    )
end

"""
    duckdb_cast_function_get_extra_info(info)

Retrieves the extra info of the function as set in `duckdb_cast_function_set_extra_info`.

# Arguments
- `info`: `duckdb_function_info` The info object.

Returns: `Ptr{Cvoid}` The extra info.
"""
function duckdb_cast_function_get_extra_info(info)
    return ccall((:duckdb_cast_function_get_extra_info, libduckdb), Ptr{Cvoid}, (duckdb_function_info,), info)
end

"""
    duckdb_cast_function_get_cast_mode(info)

Get the cast execution mode from the given function info.

# Arguments
- `info`: `duckdb_function_info` The info object.

Returns: `duckdb_cast_mode` The cast mode.
"""
function duckdb_cast_function_get_cast_mode(info)
    return ccall((:duckdb_cast_function_get_cast_mode, libduckdb), duckdb_cast_mode, (duckdb_function_info,), info)
end

"""
    duckdb_cast_function_set_error(info, error)

Report that an error has occurred while executing the cast function.

# Arguments
- `info`: `duckdb_function_info` The info object.
- `error`: `Cstring` The error message.

Returns: `Nothing` 
"""
function duckdb_cast_function_set_error(info, error)
    return ccall((:duckdb_cast_function_set_error, libduckdb), Cvoid, (duckdb_function_info, Cstring), info, error)
end

"""
    duckdb_cast_function_set_row_error(info, error, row, output)

Report that an error has occurred while executing the cast function, setting the corresponding output row to NULL.

# Arguments
- `info`: `duckdb_function_info` The info object.
- `error`: `Cstring` The error message.
- `row`: `idx_t` (1-based index) The index of the row within the output vector to set to NULL.
- `output`: `duckdb_vector` The output vector.

Returns: `Nothing` 
"""
function duckdb_cast_function_set_row_error(info, error, row, output)
    return ccall(
        (:duckdb_cast_function_set_row_error, libduckdb),
        Cvoid,
        (duckdb_function_info, Cstring, idx_t, duckdb_vector),
        info,
        error,
        row - 1,
        output
    )
end

"""
    duckdb_register_cast_function(con, cast_function)

Registers a cast function within the given connection.

# Arguments
- `con`: `duckdb_connection` The connection to use.
- `cast_function`: `duckdb_cast_function` The cast function to register.

Returns: `duckdb_state` Whether or not the registration was successful.
"""
function duckdb_register_cast_function(con, cast_function)
    return ccall(
        (:duckdb_register_cast_function, libduckdb),
        duckdb_state,
        (duckdb_connection, duckdb_cast_function),
        con,
        cast_function
    )
end

"""
    duckdb_destroy_cast_function(cast_function)

Destroys the cast function object.

# Arguments
- `cast_function`: `Ref{duckdb_cast_function}` The cast function object.

Returns: `Nothing` 
"""
function duckdb_destroy_cast_function(cast_function)
    return ccall((:duckdb_destroy_cast_function, libduckdb), Cvoid, (Ref{duckdb_cast_function},), cast_function)
end





# !!!!!!!!!!!!
# WARNING: this file is autogenerated by scripts/generate_c_api_julia.py, manual changes will be overwritten
# !!!!!!!!!!!!
