typedef int64_t monetdbe_cnt;

typedef struct {
 unsigned char day;
 unsigned char month;
 short year;
} monetdbe_data_date;

typedef struct {
 unsigned int ms;
 unsigned char seconds;
 unsigned char minutes;
 unsigned char hours;
} monetdbe_data_time;

typedef struct {
 monetdbe_data_date date;
 monetdbe_data_time time;
} monetdbe_data_timestamp;

typedef struct {
 size_t size;
 char* data;
} monetdbe_data_blob;

typedef enum {
 monetdbe_bool, monetdbe_int8_t, monetdbe_int16_t, monetdbe_int32_t, monetdbe_int64_t,
 {% if HAVE_HGE %}
 monetdbe_int128_t,
 {% endif %}
 monetdbe_size_t, monetdbe_float, monetdbe_double,
 monetdbe_str, monetdbe_blob,
 monetdbe_date, monetdbe_time, monetdbe_timestamp,
 monetdbe_type_unknown
} monetdbe_types;

{% if newer_then_jul2021 %}
typedef struct {
 char* name;
 unsigned int scale;
 unsigned int digits;
} monetdbe_sql_type;
{% endif %}

typedef struct {
 monetdbe_types type;
 {% if newer_then_jul2021 %}
 monetdbe_sql_type sql_type;
 {% endif %}
 void *data;
 size_t count;
 char* name;
} monetdbe_column;

typedef struct {
 size_t nparam;
 monetdbe_types *type;
} monetdbe_statement;

typedef struct {
 monetdbe_cnt nrows;
 size_t ncols;
 char *name;
 monetdbe_cnt last_id;
} monetdbe_result;

typedef void* monetdbe_database;

typedef struct {
 const char *host;
 int port;
 const char *database;
 const char *username;
 const char *password;
 const char *lang;
} monetdbe_remote;

typedef struct {
 const char* port;
 const char* usock;
 const char* usock;
} monetdbe_mapi_server;

typedef struct {
 int memorylimit;
 int querytimeout;
 int sessiontimeout;
 int nr_threads;
 monetdbe_remote* remote;
 monetdbe_mapi_server* mapi_server;
 const char *trace_file;
} monetdbe_options;

{% if newer_then_jul2021 %}
 {% set monetdbe_sql_type = 'monetdbe_sql_type sql_type;' %}
{% endif %}

typedef struct { monetdbe_types type; {{monetdbe_sql_type}} int8_t *data; size_t count; char *name; int8_t null_value; double scale; int (*is_null)(int8_t *value); } monetdbe_column_bool;
typedef struct { monetdbe_types type; {{monetdbe_sql_type}} int8_t *data; size_t count; char *name; int8_t null_value; double scale; int (*is_null)(int8_t *value); } monetdbe_column_int8_t;
typedef struct { monetdbe_types type; {{monetdbe_sql_type}} int16_t *data; size_t count; char *name; int16_t null_value; double scale; int (*is_null)(int16_t *value); } monetdbe_column_int16_t;
typedef struct { monetdbe_types type; {{monetdbe_sql_type}} int32_t *data; size_t count; char *name; int32_t null_value; double scale; int (*is_null)(int32_t *value); } monetdbe_column_int32_t;
typedef struct { monetdbe_types type; {{monetdbe_sql_type}} int64_t *data; size_t count; char *name; int64_t null_value; double scale; int (*is_null)(int64_t *value); } monetdbe_column_int64_t;

typedef struct { monetdbe_types type; {{monetdbe_sql_type}} size_t *data; size_t count; char *name; size_t null_value; double scale; int (*is_null)(size_t *value); } monetdbe_column_size_t;

typedef struct { monetdbe_types type; {{monetdbe_sql_type}} float *data; size_t count; char *name; float null_value; double scale; int (*is_null)(float *value); } monetdbe_column_float;
typedef struct { monetdbe_types type; {{monetdbe_sql_type}} double *data; size_t count; char *name; double null_value; double scale; int (*is_null)(double *value); } monetdbe_column_double;

typedef struct { monetdbe_types type; {{monetdbe_sql_type}} char * *data; size_t count; char *name; char * null_value; double scale; int (*is_null)(char * *value); } monetdbe_column_str;
typedef struct { monetdbe_types type; {{monetdbe_sql_type}} monetdbe_data_blob *data; size_t count; char *name; monetdbe_data_blob null_value; double scale; int (*is_null)(monetdbe_data_blob *value); } monetdbe_column_blob;

typedef struct { monetdbe_types type; {{monetdbe_sql_type}} monetdbe_data_date *data; size_t count; char *name; monetdbe_data_date null_value; double scale; int (*is_null)(monetdbe_data_date *value); } monetdbe_column_date;
typedef struct { monetdbe_types type; {{monetdbe_sql_type}} monetdbe_data_time *data; size_t count; char *name; monetdbe_data_time null_value; double scale; int (*is_null)(monetdbe_data_time *value); } monetdbe_column_time;
typedef struct { monetdbe_types type; {{monetdbe_sql_type}} monetdbe_data_timestamp *data; size_t count; char *name; monetdbe_data_timestamp null_value; double scale; int (*is_null)(monetdbe_data_timestamp *value); } monetdbe_column_timestamp;

extern const char *monetdbe_version(void);

extern int monetdbe_open(monetdbe_database *db, char *url, monetdbe_options *opts);

extern int monetdbe_close(monetdbe_database db);

extern char* monetdbe_error(monetdbe_database db);

extern char* monetdbe_get_autocommit(monetdbe_database dbhdl, int* result);
extern char* monetdbe_set_autocommit(monetdbe_database dbhdl, int value);
extern int monetdbe_in_transaction(monetdbe_database dbhdl);

extern char* monetdbe_query(monetdbe_database dbhdl, char* query, monetdbe_result** result, monetdbe_cnt* affected_rows);
extern char* monetdbe_result_fetch(monetdbe_result *mres, monetdbe_column** res, size_t column_index);
extern char* monetdbe_cleanup_result(monetdbe_database dbhdl, monetdbe_result* result);

{% if newer_then_jul2021 %}
extern char* monetdbe_prepare(monetdbe_database dbhdl, char *query, monetdbe_statement **stmt, monetdbe_result** result);
{% else %}
extern char* monetdbe_prepare(monetdbe_database dbhdl, char *query, monetdbe_statement **stmt);
{% endif %}
extern char* monetdbe_bind(monetdbe_statement *stmt, void *data, size_t parameter_nr);
extern char* monetdbe_execute(monetdbe_statement *stmt, monetdbe_result **result, monetdbe_cnt* affected_rows);
extern char* monetdbe_cleanup_statement(monetdbe_database dbhdl, monetdbe_statement *stmt);

extern char* monetdbe_append(monetdbe_database dbhdl, const char* schema, const char* table, monetdbe_column **input, size_t column_count);
extern const void* monetdbe_null(monetdbe_database dbhdl, monetdbe_types t);

{% if newer_then_jul2021 %}
extern char* monetdbe_get_columns(monetdbe_database dbhdl, const char* schema_name, const char *table_name, size_t *column_count, monetdbe_column **columns);
{% else %}
extern char* monetdbe_get_columns(monetdbe_database dbhdl, const char* schema_name, const char *table_name, size_t *column_count, char ***column_names, int **column_types);
{% endif %}


extern char* monetdbe_dump_database(monetdbe_database dbhdl, const char *backupfile);
extern char* monetdbe_dump_table(monetdbe_database dbhdl, const char *schema_name, const char *table_name, const char *backupfile);
