#include #include "config.h" #include "common.h" #include "db.h" #include "str.h" #include "util.h" #include "hashtable.h" #include "vector.h" #include "log.h" #include "db_DATABASE.h" /** implementation MUST define a function to open connections */ static cp_db_connection *DATABASE_open_conn(cp_data_source *data_source); /** implementation MUST define a function to perform SELECT queries */ static cp_result_set *DATABASE_select(cp_db_connection *_conn, char *query); /** * implementations MUST define a function to perform INSERT, UPDATE or DELETE * queries */ static int DATABASE_update(cp_db_connection *_conn, char *query); /** * implemetations MUST define a function to close database connections */ static int DATABASE_close_conn(cp_db_connection *connection); /** implementations MAY define a function to retrieve result set metadata */ static int DATABASE_fetch_metadata(cp_result_set *result_set); /** * implementations MAY define a function to retrieve result set rows by chunk */ static int DATABASE_fetch_next(cp_result_set *result_set); /** implementations MAY define a function to close an open result set */ static int DATABASE_release_result_set(cp_result_set *result_set); /** * implementations may define a function to escape strings for use in SQL * queries */ static char *DATABASE_escape_string(cp_db_connection *conn, char *str, int len); /** * implementations may define a function to escape binary data for use in SQL * queries */ static char *DATABASE_escape_binary(cp_db_connection *conn, char *str, int len, int *res_len); /** * implementation may define a function to unescape binary data returned by * an SQL query */ static cp_string *DATABASE_unescape_binary(cp_db_connection *conn, char *str); /** * implementations may define a function to create a prepared statement */ static cp_db_statement * DATABASE_prepare_statement(cp_db_connection *conn, int prm_count, cp_field_type *prm_type, char *query); /** * implementations may define a function to execute a prepared statement */ static int DATABASE_execute_statement(cp_db_connection *conn, cp_db_statement *stmt, cp_result_set **result_set, int *lengths, void **prm); /** * implementations may define a function to release implementation specific * allocations made to instantiate a prepared statement */ static void DATABASE_release_statement(cp_db_statement *statement); /** * implementations may define a function to set autocommit mode */ static void DATABASE_set_autocommit(cp_db_connection *conn, int state); /** * implementations may define a function to perform a commit */ static int DATABASE_commit(cp_db_connection *conn); /** * implementations may define a function to perform a rollback */ static int DATABASE_rollback(cp_db_connection *conn); volatile static int initialized = 0; static cp_db_actions *DATABASE_db_actions = NULL; static cp_hashtable *DATABASE_field_type_map = NULL; #define DBNAME "DATABASE" typedef struct _field_type_map { int DATABASE_field_code; int cprops_field_code; } field_type_map; /** add whatever types DATABASE uses */ field_type_map DATABASE2cprops[] = { { DATABASE_TYPE_BOOLEAN, CP_FIELD_TYPE_BOOLEAN }, { DATABASE_TYPE_SHORT, CP_FIELD_TYPE_SHORT }, { DATABASE_TYPE_INT, CP_FIELD_TYPE_INT }, { DATABASE_TYPE_LONG, CP_FIELD_TYPE_LONG }, { DATABASE_TYPE_LONG_LONG, CP_FIELD_TYPE_LONG_LONG }, { DATABASE_TYPE_FLOAT, CP_FIELD_TYPE_FLOAT }, { DATABASE_TYPE_DOUBLE, CP_FIELD_TYPE_DOUBLE }, { DATABASE_TYPE_VARCHAR, CP_FIELD_TYPE_VARCHAR }, { DATABASE_TYPE_BLOB, CP_FIELD_TYPE_BLOB }, { DATABASE_TYPE_DATE, CP_FIELD_TYPE_DATE }, { DATABASE_TYPE_TIME, CP_FIELD_TYPE_TIME }, { DATABASE_TYPE_TIMESTAMP, CP_FIELD_TYPE_TIMESTAMP } }; void cp_DATABASE_shutdown() { if (!initialized) return; initialized = 0; if (DATABASE_db_actions) { cp_db_actions_destroy(DATABASE_db_actions); DATABASE_db_actions = NULL; } if (DATABASE_field_type_map) { cp_hashtable_destroy(DATABASE_field_type_map); DATABASE_field_type_map = NULL; } } static void cp_DATABASE_connection_parameters_delete(cp_DATABASE_connection_parameters *prm) { if (prm) { if (prm->host) free(prm->host); if (prm->login) free(prm->login); if (prm->password) free(prm->password); if (prm->db_name) free(prm->db_name); /* * release additional DATABASE connection parameter fields */ free(prm); } } cp_data_source * cp_DATABASE_data_source(char *host, int port, char *login, char *password, char *db_name /*, ... additional DATABASE connection parameters */) { cp_data_source *data_source; cp_DATABASE_connection_parameters *impl; if (!initialized) cp_dbms_DATABASE_init(); data_source = calloc(1, sizeof(cp_data_source)); if (data_source == NULL) return NULL; data_source->act = DATABASE_db_actions; data_source->prm = calloc(1, sizeof(cp_db_connection_parameters)); if (data_source->prm == NULL) { free(data_source); return NULL; } impl = calloc(1, sizeof(cp_DATABASE_connection_parameters)); if (impl == NULL) { free(data_source->prm); free(data_source); return NULL; } impl->host = host ? strdup(host) : NULL; impl->port = port; impl->login = login ? strdup(login) : NULL; impl->password = password ? strdup(password) : NULL; impl->db_name = db_name ? strdup(db_name) : NULL; /* * assign other DATABASE connection parameters */ data_source->prm->impl = impl; data_source->prm->impl_dtr = (cp_destructor_fn) cp_DATABASE_connection_parameters_delete; return data_source; } cp_data_source * cp_dbms_DATABASE_get_data_source(char *host, int port, char *login, char *password, char *dbname) { return cp_DATABASE_data_source(host, port, login, password, dbname /*, ... other parameters */); } cp_data_source * cp_dbms_DATABASE_get_data_source_prm(char *host, int port, char *login, char *password, char *dbname, cp_hashtable *prm) { return cp_DATABASE_data_source(host, port, login, password, dbname /* , ... other parameters */); } static int DATABASE_close_conn(cp_db_connection *connection) { void *conn = connection->connection; if (conn == NULL) return -1; /* * add code to close DATABASE connection */ return 0; } static int convert_field_type(int field_type) { int *type = cp_hashtable_get(DATABASE_field_type_map, &field_type); return type != NULL ? *type : field_type; } /** convert cp_dbms type to DATABASE type code */ static int cprops2DATABASE(cp_field_type type) { switch(type) { case CP_FIELD_TYPE_BOOLEAN: return DATABASE_TYPE_BOOLEAN; case CP_FIELD_TYPE_CHAR: return DATABASE_TYPE_CHAR; case CP_FIELD_TYPE_SHORT: return DATABASE_TYPE_SHORT; case CP_FIELD_TYPE_INT: return DATABASE_TYPE_INT; case CP_FIELD_TYPE_LONG: return DATABASE_TYPE_LONG; case CP_FIELD_TYPE_LONG_LONG: return DATABASE_TYPE_LONG_LONG; case CP_FIELD_TYPE_FLOAT: return DATABASE_TYPE_FLOAT; case CP_FIELD_TYPE_DOUBLE: return DATABASE_TYPE_DOUBLE; case CP_FIELD_TYPE_VARCHAR: return DATABASE_TYPE_VARCHAR; case CP_FIELD_TYPE_BLOB: return DATABASE_TYPE_BLOB; case CP_FIELD_TYPE_DATE: return DATABASE_TYPE_DATE; case CP_FIELD_TYPE_TIME: return DATABASE_TYPE_TIME; case CP_FIELD_TYPE_TIMESTAMP: return DATABASE_TYPE_TIMESTAMP; default: return -1; } return -1; }