/* ** Copyright (C) 2001-2024 Zabbix SIA ** ** This program is free software: you can redistribute it and/or modify it under the terms of ** the GNU Affero General Public License as published by the Free Software Foundation, version 3. ** ** This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ** without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ** See the GNU Affero General Public License for more details. ** ** You should have received a copy of the GNU Affero General Public License along with this program. ** If not, see <https://www.gnu.org/licenses/>. **/ #ifndef ZABBIX_ZBXDB_H #define ZABBIX_ZBXDB_H #include "zbxcommon.h" #include "zbxjson.h" #include "zbxdbschema.h" #define ZBX_DB_OK 0 #define ZBX_DB_FAIL -1 #define ZBX_DB_DOWN -2 #define ZBX_DB_TLS_CONNECT_REQUIRED_TXT "required" #define ZBX_DB_TLS_CONNECT_VERIFY_CA_TXT "verify_ca" #define ZBX_DB_TLS_CONNECT_VERIFY_FULL_TXT "verify_full" typedef char **zbx_db_row_t; typedef struct zbx_db_result *zbx_db_result_t; typedef struct zbx_dbconn zbx_dbconn_t; /* database field value */ typedef union { int i32; zbx_uint64_t ui64; double dbl; char *str; } zbx_db_value_t; typedef struct { char *dbhost; char *dbname; char *dbschema; char *dbuser; char *dbpassword; char *dbsocket; char *db_tls_connect; char *db_tls_cert_file; char *db_tls_key_file; char *db_tls_ca_file; char *db_tls_cipher; char *db_tls_cipher_13; unsigned int dbport; int log_slow_queries; int read_only_recoverable; } zbx_db_config_t; #ifdef HAVE_SQLITE3 /* we have to put double % here for sprintf */ # define ZBX_SQL_MOD(x, y) #x "%%" #y #else # define ZBX_SQL_MOD(x, y) "mod(" #x "," #y ")" #endif #ifdef HAVE_SQLITE3 # define ZBX_FOR_UPDATE "" /* SQLite3 does not support "select ... for update" */ #else # define ZBX_FOR_UPDATE " for update" #endif int zbx_db_init(char **error); void zbx_db_deinit(void); typedef enum { ERR_Z3001 = 3001, ERR_Z3002, ERR_Z3003, ERR_Z3004, ERR_Z3005, ERR_Z3006, ERR_Z3007, ERR_Z3008, ERR_Z3009 } zbx_err_codes_t; #ifdef HAVE_POSTGRESQL int zbx_tsdb_get_version(void); #endif #if defined (HAVE_MYSQL) void zbx_mysql_escape_bin(const char *src, char *dst, size_t size); #elif defined(HAVE_POSTGRESQL) void zbx_postgresql_escape_bin(const char *src, char **dst, size_t size); #endif typedef enum { ESCAPE_SEQUENCE_OFF, ESCAPE_SEQUENCE_ON } zbx_escape_sequence_t; #define ZBX_SQL_LIKE_ESCAPE_CHAR '!' char *zbx_db_dyn_escape_like_pattern(const char *src); size_t zbx_db_strlen_n(const char *text_loc, size_t maxlen); #define ZBX_DB_EXTENSION_TIMESCALEDB "timescaledb" #if defined(HAVE_POSTGRESQL) # define ZBX_SUPPORTED_DB_CHARACTER_SET "utf8" #elif defined(HAVE_MYSQL) # define ZBX_DB_STRLIST_DELIM ',' # define ZBX_SUPPORTED_DB_CHARACTER_SET_UTF8 "utf8" # define ZBX_SUPPORTED_DB_CHARACTER_SET_UTF8MB3 "utf8mb3" # define ZBX_SUPPORTED_DB_CHARACTER_SET_UTF8MB4 "utf8mb4" # define ZBX_SUPPORTED_DB_CHARACTER_SET ZBX_SUPPORTED_DB_CHARACTER_SET_UTF8 ","\ ZBX_SUPPORTED_DB_CHARACTER_SET_UTF8MB3 ","\ ZBX_SUPPORTED_DB_CHARACTER_SET_UTF8MB4 # define ZBX_SUPPORTED_DB_COLLATION "utf8_bin,utf8mb3_bin,utf8mb4_bin" #endif typedef enum { /* db version status flags shared with FRONTEND */ DB_VERSION_SUPPORTED, DB_VERSION_LOWER_THAN_MINIMUM, DB_VERSION_HIGHER_THAN_MAXIMUM, DB_VERSION_FAILED_TO_RETRIEVE, DB_VERSION_NOT_SUPPORTED_ERROR, DB_VERSION_NOT_SUPPORTED_WARNING, DB_VERSION_HIGHER_THAN_MAXIMUM_ERROR, DB_VERSION_HIGHER_THAN_MAXIMUM_WARNING } zbx_db_version_status_t; typedef enum { /* db extension error codes shared with FRONTEND */ ZBX_EXT_ERR_UNDEFINED = 0, ZBX_EXT_SUCCEED = 1, /* ZBX_TIMESCALEDB_POSTGRES_TOO_OLD, obsoleted since Zabbix 7.0 */ ZBX_TIMESCALEDB_VERSION_FAILED_TO_RETRIEVE = 3, ZBX_TIMESCALEDB_VERSION_LOWER_THAN_MINIMUM, ZBX_TIMESCALEDB_VERSION_NOT_SUPPORTED, ZBX_TIMESCALEDB_VERSION_HIGHER_THAN_MAXIMUM, ZBX_TIMESCALEDB_LICENSE_NOT_COMMUNITY } zbx_db_ext_err_code_t; struct zbx_db_version_info_t { /* information about database server */ const char *database; zbx_uint32_t current_version; zbx_uint32_t min_version; zbx_uint32_t max_version; zbx_uint32_t min_supported_version; char *friendly_current_version; const char *friendly_min_version; const char *friendly_max_version; const char *friendly_min_supported_version; zbx_db_version_status_t flag; int history_pk; /* information about database server extension */ char *extension; zbx_uint32_t ext_current_version; zbx_uint32_t ext_min_version; zbx_uint32_t ext_max_version; zbx_uint32_t ext_min_supported_version; char *ext_friendly_current_version; const char *ext_friendly_min_version; const char *ext_friendly_max_version; const char *ext_friendly_min_supported_version; zbx_db_version_status_t ext_flag; zbx_db_ext_err_code_t ext_err_code; int history_compressed_chunks; int trends_compressed_chunks; }; #ifdef HAVE_POSTGRESQL void zbx_tsdb_info_extract(struct zbx_db_version_info_t *version_info); void zbx_tsdb_set_compression_availability(int compression_availabile); int zbx_tsdb_get_compression_availability(void); void zbx_tsdb_extract_compressed_chunk_flags(struct zbx_db_version_info_t *version_info); #endif int zbx_db_version_check(const char *database, zbx_uint32_t current_version, zbx_uint32_t min_version, zbx_uint32_t max_version, zbx_uint32_t min_supported_version); void zbx_db_version_json_create(struct zbx_json *json, struct zbx_db_version_info_t *info); #if defined(HAVE_MYSQL) # define ZBX_DB_TIMESTAMP() "unix_timestamp()" # define ZBX_DB_CHAR_LENGTH(str) "char_length(" #str ")" #elif defined(HAVE_POSTGRESQL) # define ZBX_DB_TIMESTAMP() "cast(extract(epoch from now()) as int)" # define ZBX_DB_CHAR_LENGTH(str) "char_length(" #str ")" #else # define ZBX_DB_TIMESTAMP() "cast(strftime('%s', 'now') as integer)" # define ZBX_DB_CHAR_LENGTH(str) "length(" #str ")" #endif #define ZBX_DB_CONNECT_NORMAL 0 #define ZBX_DB_CONNECT_EXIT 1 #define ZBX_DB_CONNECT_ONCE 2 ZBX_PTR_VECTOR_DECL(const_db_field_ptr, const zbx_db_field_t *) ZBX_PTR_VECTOR_DECL(db_value_ptr, zbx_db_value_t *) typedef struct { /* database connection */ zbx_dbconn_t *db; /* the target table */ const zbx_db_table_t *table; /* the fields to insert (pointers to the zbx_db_field_t structures from database schema) */ zbx_vector_const_db_field_ptr_t fields; /* the values rows to insert (pointers to arrays of zbx_db_value_t structures) */ zbx_vector_db_value_ptr_t rows; /* index of autoincrement field */ int autoincrement; /* the last id assigned by autoincrement */ zbx_uint64_t lastid; } zbx_db_insert_t; void zbx_init_library_db(zbx_db_config_t *config); void zbx_deinit_library_db(zbx_db_config_t *config); zbx_dbconn_t *zbx_dbconn_create(void); void zbx_dbconn_free(zbx_dbconn_t *db); int zbx_dbconn_set_connect_options(zbx_dbconn_t *db, int options); void zbx_dbconn_set_autoincrement(zbx_dbconn_t *db, int options); int zbx_dbconn_open(zbx_dbconn_t *db); void zbx_dbconn_close(zbx_dbconn_t *db); int zbx_dbconn_execute(zbx_dbconn_t *db, const char *fmt, ...); int zbx_dbconn_vexecute(zbx_dbconn_t *db, const char *fmt, va_list args); zbx_db_result_t zbx_dbconn_vselect(zbx_dbconn_t *db, const char *fmt, va_list args); zbx_db_result_t zbx_dbconn_select(zbx_dbconn_t *db, const char *fmt, ...); zbx_db_result_t zbx_dbconn_select_n(zbx_dbconn_t *db, const char *query, int n); zbx_db_row_t zbx_db_fetch(zbx_db_result_t result); void zbx_db_free_result(zbx_db_result_t result); int zbx_dbconn_begin(zbx_dbconn_t *db); int zbx_dbconn_commit(zbx_dbconn_t *db); int zbx_dbconn_rollback(zbx_dbconn_t *db); int zbx_dbconn_end(zbx_dbconn_t *db, int ret); zbx_uint64_t zbx_dbconn_get_maxid_num(zbx_dbconn_t *db, const char *tablename, int num); /* bulk insert support */ void zbx_dbconn_prepare_insert_dyn(zbx_dbconn_t *db, zbx_db_insert_t *db_insert, const zbx_db_table_t *table, const zbx_db_field_t * const *fields, int fields_num); void zbx_dbconn_prepare_vinsert(zbx_dbconn_t *db, zbx_db_insert_t *db_insert, const char *table, va_list args); void zbx_dbconn_prepare_insert(zbx_dbconn_t *db, zbx_db_insert_t *db_insert, const char *table, ...); void zbx_db_insert_add_values(zbx_db_insert_t *db_insert, ...); void zbx_db_insert_add_values_dyn(zbx_db_insert_t *db_insert, zbx_db_value_t **values, int values_num); int zbx_db_insert_execute(zbx_db_insert_t *db_insert); void zbx_db_insert_autoincrement(zbx_db_insert_t *db_insert, const char *field_name); zbx_uint64_t zbx_db_insert_get_lastid(zbx_db_insert_t *self); void zbx_db_insert_clean(zbx_db_insert_t *db_insert); void zbx_dbconn_extract_version_info(zbx_dbconn_t *db, struct zbx_db_version_info_t *version_info); const char *zbx_dbconn_last_strerr(zbx_dbconn_t *db); zbx_err_codes_t zbx_dbconn_last_errcode(zbx_dbconn_t *db); zbx_db_config_t *zbx_db_config_create(void); void zbx_db_config_free(zbx_db_config_t *config); int zbx_dbconn_lock_record(zbx_dbconn_t *db, const char *table, zbx_uint64_t id, const char *add_field, zbx_uint64_t add_id); int zbx_dbconn_lock_records(zbx_dbconn_t *db, const char *table, const zbx_vector_uint64_t *ids); int zbx_dbconn_lock_ids(zbx_dbconn_t *db, const char *table_name, const char *field_name, zbx_vector_uint64_t *ids); int zbx_db_config_validate_features(zbx_db_config_t *config, unsigned char program_type); void zbx_db_config_validate(zbx_db_config_t *config); int zbx_dbconn_check_extension(zbx_dbconn_t *db, struct zbx_db_version_info_t *info, int allow_unsupported); #ifdef HAVE_POSTGRESQL void zbx_dbconn_tsdb_extract_compressed_chunk_flags(zbx_dbconn_t *db, struct zbx_db_version_info_t *version_info); void zbx_dbconn_tsdb_info_extract(zbx_dbconn_t *db, struct zbx_db_version_info_t *version_info); int zbx_dbconn_tsdb_get_version(zbx_dbconn_t *db); void zbx_dbconn_tsdb_set_compression_availability(zbx_dbconn_t *db, int compression_availabile); int zbx_dbconn_tsdb_get_compression_availability(zbx_dbconn_t *db); #endif char *zbx_db_dyn_escape_field(const char *table_name, const char *field_name, const char *src); char *zbx_db_dyn_escape_string(const char *src); char *zbx_db_dyn_escape_string_len(const char *src, size_t length); char *zbx_db_dyn_escape_like_pattern(const char *src); void zbx_db_add_condition_alloc(char **sql, size_t *sql_alloc, size_t *sql_offset, const char *fieldname, const zbx_uint64_t *values, const int num); void zbx_db_add_str_condition_alloc(char **sql, size_t *sql_alloc, size_t *sql_offset, const char *fieldname, const char * const *values, const int num); const zbx_db_table_t *zbx_db_get_table(const char *tablename); const zbx_db_field_t *zbx_db_get_field(const zbx_db_table_t *table, const char *fieldname); int zbx_db_validate_field_size(const char *tablename, const char *fieldname, const char *str); #define zbx_db_get_maxid(table) zbx_db_get_maxid_num(table, 1) zbx_uint64_t zbx_db_get_maxid_num(const char *tablename, int num); int zbx_db_get_row_num(zbx_db_result_t result); int zbx_db_is_null(const char *field); #if defined(HAVE_POSTGRESQL) char *zbx_db_get_schema_esc(void); #endif int zbx_dbconn_execute_overflowed_sql(zbx_dbconn_t *db, char **sql, size_t *sql_alloc, size_t *sql_offset); int zbx_dbconn_flush_overflowed_sql(zbx_dbconn_t *db, char *sql, size_t sql_offset); /* compatibility wrappers */ void zbx_db_init_autoincrement_options(void); int zbx_db_connect(int flag); void zbx_db_close(void); void zbx_db_begin(void); int zbx_db_commit(void); void zbx_db_rollback(void); int zbx_db_end(int ret); int zbx_db_execute(const char *fmt, ...); int zbx_db_execute_once(const char *fmt, ...); zbx_db_result_t zbx_db_select(const char *fmt, ...); zbx_db_result_t zbx_db_select_n(const char *query, int n); zbx_uint64_t zbx_db_get_maxid_num(const char *tablename, int num); void zbx_db_insert_prepare_dyn(zbx_db_insert_t *db_insert, const zbx_db_table_t *table, const zbx_db_field_t **fields, int fields_num); void zbx_db_insert_prepare(zbx_db_insert_t *self, const char *table, ...); void zbx_db_extract_version_info(struct zbx_db_version_info_t *version_info); void zbx_tsdb_extract_compressed_chunk_flags(struct zbx_db_version_info_t *version_info); void zbx_tsdb_info_extract(struct zbx_db_version_info_t *version_info); int zbx_tsdb_get_version(void); void zbx_tsdb_set_compression_availability(int compression_availabile); int zbx_tsdb_get_compression_availability(void); const char *zbx_db_last_strerr(void); zbx_err_codes_t zbx_db_last_errcode(void); int zbx_db_lock_record(const char *table, zbx_uint64_t id, const char *add_field, zbx_uint64_t add_id); int zbx_db_lock_records(const char *table, const zbx_vector_uint64_t *ids); int zbx_db_lock_ids(const char *table_name, const char *field_name, zbx_vector_uint64_t *ids); int zbx_db_check_extension(struct zbx_db_version_info_t *info, int allow_unsupported); int zbx_db_flush_overflowed_sql(char *sql, size_t sql_offset); int zbx_db_execute_overflowed_sql(char **sql, size_t *sql_alloc, size_t *sql_offset); #endif