mirror of
https://github.com/haiwen/ccnet-server.git
synced 2025-04-28 10:33:20 +00:00
360 lines
10 KiB
C
360 lines
10 KiB
C
|
#include "common.h"
|
||
|
|
||
|
#include "db-wrapper.h"
|
||
|
#include "mysql-db-ops.h"
|
||
|
#include "sqlite-db-ops.h"
|
||
|
#include "pgsql-db-ops.h"
|
||
|
|
||
|
typedef struct DBOperations {
|
||
|
void (*db_conn_pool_free) (DBConnPool *);
|
||
|
DBConnection* (*get_db_connection) (DBConnPool *, GError **);
|
||
|
void (*db_connection_close) (DBConnection *);
|
||
|
gboolean (*db_connection_execute) (DBConnection *, const char *, GError **);
|
||
|
ResultSet* (*db_connection_execute_query) (DBConnection *, const char *, GError **);
|
||
|
gboolean (*result_set_next) (ResultSet *, GError **);
|
||
|
const char* (*result_set_get_string) (ResultSet *, int, GError **);
|
||
|
void (*result_set_free) (ResultSet *);
|
||
|
int (*result_set_get_column_count) (ResultSet *);
|
||
|
DBStmt* (*db_connection_prepare_statement) (DBConnection *, const char *, GError **);
|
||
|
gboolean (*db_stmt_set_int) (DBStmt *, int, int, GError **);
|
||
|
gboolean (*db_stmt_set_int64) (DBStmt *, int, gint64, GError **);
|
||
|
gboolean (*db_stmt_set_string) (DBStmt *, int, const char *, GError **);
|
||
|
gboolean (*db_stmt_execute) (DBStmt *, GError **);
|
||
|
ResultSet* (*db_stmt_execute_query) (DBStmt *, GError **);
|
||
|
void (*db_stmt_free) (DBStmt *);
|
||
|
gboolean (*db_connection_begin_transaction) (DBConnection *, GError **);
|
||
|
gboolean (*db_connection_commit) (DBConnection *, GError **);
|
||
|
gboolean (*db_connection_rollback) (DBConnection *, GError **);
|
||
|
} DBOperations;
|
||
|
|
||
|
static DBOperations db_ops;
|
||
|
|
||
|
/* DB Connection Pool. */
|
||
|
|
||
|
DBConnPool *
|
||
|
db_conn_pool_new_mysql (const char *host,
|
||
|
const char *user,
|
||
|
const char *password,
|
||
|
unsigned int port,
|
||
|
const char *db_name,
|
||
|
const char *unix_socket,
|
||
|
gboolean use_ssl,
|
||
|
const char *charset,
|
||
|
int max_connections)
|
||
|
{
|
||
|
db_ops.db_conn_pool_free = mysql_db_conn_pool_free;
|
||
|
db_ops.get_db_connection = mysql_get_db_connection;
|
||
|
db_ops.db_connection_close = mysql_db_connection_close;
|
||
|
db_ops.db_connection_execute = mysql_db_connection_execute;
|
||
|
db_ops.db_connection_execute_query = mysql_execute_query;
|
||
|
db_ops.result_set_next = mysql_result_set_next;
|
||
|
db_ops.result_set_get_string = mysql_result_set_get_string;
|
||
|
db_ops.result_set_free = mysql_result_set_free;
|
||
|
db_ops.result_set_get_column_count = mysql_result_set_get_column_count;
|
||
|
db_ops.db_connection_prepare_statement = mysql_prepare_statement;
|
||
|
db_ops.db_stmt_set_int = mysql_stmt_set_int;
|
||
|
db_ops.db_stmt_set_int64 = mysql_stmt_set_int64;
|
||
|
db_ops.db_stmt_set_string = mysql_stmt_set_string;
|
||
|
db_ops.db_stmt_execute = mysql_db_stmt_execute;
|
||
|
db_ops.db_stmt_execute_query = mysql_db_stmt_execute_query;
|
||
|
db_ops.db_stmt_free = mysql_db_stmt_free;
|
||
|
db_ops.db_connection_begin_transaction = mysql_db_begin_transaction;
|
||
|
db_ops.db_connection_commit = mysql_db_commit;
|
||
|
db_ops.db_connection_rollback = mysql_db_rollback;
|
||
|
|
||
|
return mysql_db_conn_pool_new (host, user, password, port, db_name, unix_socket,
|
||
|
use_ssl, charset, max_connections);
|
||
|
}
|
||
|
|
||
|
DBConnPool *
|
||
|
db_conn_pool_new_pgsql (const char *host,
|
||
|
const char *user,
|
||
|
const char *password,
|
||
|
const char *db_name,
|
||
|
const char *unix_socket)
|
||
|
{
|
||
|
db_ops.db_conn_pool_free = pgsql_db_conn_pool_free;
|
||
|
db_ops.get_db_connection = pgsql_get_db_connection;
|
||
|
db_ops.db_connection_close = pgsql_db_connection_close;
|
||
|
db_ops.db_connection_execute = pgsql_db_connection_execute;
|
||
|
db_ops.db_connection_execute_query = pgsql_execute_query;
|
||
|
db_ops.result_set_next = pgsql_result_set_next;
|
||
|
db_ops.result_set_get_string = pgsql_result_set_get_string;
|
||
|
db_ops.result_set_free = pgsql_result_set_free;
|
||
|
db_ops.result_set_get_column_count = pgsql_result_set_get_column_count;
|
||
|
db_ops.db_connection_prepare_statement = pgsql_prepare_statement;
|
||
|
db_ops.db_stmt_set_int = pgsql_stmt_set_int;
|
||
|
db_ops.db_stmt_set_int64 = pgsql_stmt_set_int64;
|
||
|
db_ops.db_stmt_set_string = pgsql_stmt_set_string;
|
||
|
db_ops.db_stmt_execute = pgsql_db_stmt_execute;
|
||
|
db_ops.db_stmt_execute_query = pgsql_db_stmt_execute_query;
|
||
|
db_ops.db_stmt_free = pgsql_db_stmt_free;
|
||
|
db_ops.db_connection_begin_transaction = pgsql_db_begin_transaction;
|
||
|
db_ops.db_connection_commit = pgsql_db_commit;
|
||
|
db_ops.db_connection_rollback = pgsql_db_rollback;
|
||
|
|
||
|
return pgsql_db_conn_pool_new (host, user, password, db_name, unix_socket);
|
||
|
}
|
||
|
|
||
|
DBConnPool *
|
||
|
db_conn_pool_new_sqlite (const char *db_path, int max_connections)
|
||
|
{
|
||
|
db_ops.db_conn_pool_free = sqlite_db_conn_pool_free;
|
||
|
db_ops.get_db_connection = sqlite_get_db_connection;
|
||
|
db_ops.db_connection_close = sqlite_db_connection_close;
|
||
|
db_ops.db_connection_execute = sqlite_db_connection_execute;
|
||
|
db_ops.db_connection_execute_query = sqlite_execute_query;
|
||
|
db_ops.result_set_next = sqlite_result_set_next;
|
||
|
db_ops.result_set_get_string = sqlite_result_set_get_string;
|
||
|
db_ops.result_set_free = sqlite_result_set_free;
|
||
|
db_ops.result_set_get_column_count = sqlite_result_set_get_column_count;
|
||
|
db_ops.db_connection_prepare_statement = sqlite_prepare_statement;
|
||
|
db_ops.db_stmt_set_int = sqlite_stmt_set_int;
|
||
|
db_ops.db_stmt_set_int64 = sqlite_stmt_set_int64;
|
||
|
db_ops.db_stmt_set_string = sqlite_stmt_set_string;
|
||
|
db_ops.db_stmt_execute = sqlite_db_stmt_execute;
|
||
|
db_ops.db_stmt_execute_query = sqlite_db_stmt_execute_query;
|
||
|
db_ops.db_stmt_free = sqlite_db_stmt_free;
|
||
|
db_ops.db_connection_begin_transaction = sqlite_db_begin_transaction;
|
||
|
db_ops.db_connection_commit = sqlite_db_commit;
|
||
|
db_ops.db_connection_rollback = sqlite_db_rollback;
|
||
|
|
||
|
return sqlite_db_conn_pool_new (db_path, max_connections);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
db_conn_pool_free (DBConnPool *pool)
|
||
|
{
|
||
|
return db_ops.db_conn_pool_free (pool);
|
||
|
}
|
||
|
|
||
|
/* DB Connections. */
|
||
|
|
||
|
DBConnection *
|
||
|
db_conn_pool_get_connection (DBConnPool *pool, GError **error)
|
||
|
{
|
||
|
return db_ops.get_db_connection (pool, error);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
db_connection_clear (DBConnection *conn)
|
||
|
{
|
||
|
result_set_free (conn->result_set);
|
||
|
|
||
|
db_stmt_free (conn->stmt);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
db_connection_close (DBConnection *conn)
|
||
|
{
|
||
|
if (!conn)
|
||
|
return;
|
||
|
|
||
|
db_connection_clear (conn);
|
||
|
|
||
|
db_ops.db_connection_close (conn);
|
||
|
}
|
||
|
|
||
|
gboolean
|
||
|
db_connection_execute (DBConnection *conn, const char *sql, GError **error)
|
||
|
{
|
||
|
return db_ops.db_connection_execute (conn, sql, error);
|
||
|
}
|
||
|
|
||
|
/* Result Sets. */
|
||
|
|
||
|
void
|
||
|
result_set_free (ResultSet *r)
|
||
|
{
|
||
|
if (!r)
|
||
|
return;
|
||
|
|
||
|
return db_ops.result_set_free (r);
|
||
|
}
|
||
|
|
||
|
ResultSet *
|
||
|
db_connection_execute_query (DBConnection *conn, const char *sql, GError **error)
|
||
|
{
|
||
|
ResultSet *result_set;
|
||
|
|
||
|
if (conn->result_set) {
|
||
|
result_set_free (conn->result_set);
|
||
|
conn->result_set = NULL;
|
||
|
}
|
||
|
|
||
|
result_set = db_ops.db_connection_execute_query (conn, sql, error);
|
||
|
|
||
|
if (result_set)
|
||
|
conn->result_set = result_set;
|
||
|
|
||
|
return result_set;
|
||
|
}
|
||
|
|
||
|
gboolean
|
||
|
result_set_next (ResultSet *r, GError **error)
|
||
|
{
|
||
|
return db_ops.result_set_next (r, error);
|
||
|
}
|
||
|
|
||
|
const char *
|
||
|
result_set_get_string (ResultSet *r, int idx, GError **error)
|
||
|
{
|
||
|
return db_ops.result_set_get_string (r, idx, error);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
result_set_get_int (ResultSet *r, int idx, GError **error)
|
||
|
{
|
||
|
const char *str;
|
||
|
char *e;
|
||
|
int ret;
|
||
|
|
||
|
str = db_ops.result_set_get_string (r, idx, error);
|
||
|
if (*error) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (!str) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
errno = 0;
|
||
|
ret = strtol (str, &e, 10);
|
||
|
if (errno || (e == str)) {
|
||
|
g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE,
|
||
|
"Number conversion failed.");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
gint64
|
||
|
result_set_get_int64 (ResultSet *r, int idx, GError **error)
|
||
|
{
|
||
|
const char *str;
|
||
|
char *e;
|
||
|
gint64 ret;
|
||
|
|
||
|
str = db_ops.result_set_get_string (r, idx, error);
|
||
|
if (*error) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (!str) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
errno = 0;
|
||
|
ret = strtoll (str, &e, 10);
|
||
|
if (errno || (e == str)) {
|
||
|
g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE,
|
||
|
"Number conversion failed.");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
result_set_get_column_count (ResultSet *r)
|
||
|
{
|
||
|
return db_ops.result_set_get_column_count (r);
|
||
|
}
|
||
|
|
||
|
/* Prepared Statements. */
|
||
|
|
||
|
DBStmt *
|
||
|
db_connection_prepare_statement (DBConnection *conn, const char *sql, GError **error)
|
||
|
{
|
||
|
DBStmt *stmt;
|
||
|
|
||
|
if (conn->stmt) {
|
||
|
db_stmt_free (conn->stmt);
|
||
|
conn->stmt = NULL;
|
||
|
}
|
||
|
|
||
|
stmt = db_ops.db_connection_prepare_statement (conn, sql, error);
|
||
|
|
||
|
if (stmt)
|
||
|
conn->stmt = stmt;
|
||
|
|
||
|
return stmt;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
db_stmt_set_int (DBStmt *stmt, int idx, int x, GError **error)
|
||
|
{
|
||
|
return db_ops.db_stmt_set_int (stmt, idx, x, error);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
db_stmt_set_int64 (DBStmt *stmt, int idx, gint64 x, GError **error)
|
||
|
{
|
||
|
return db_ops.db_stmt_set_int64 (stmt, idx, x, error);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
db_stmt_set_string (DBStmt *stmt, int idx, const char *s, GError **error)
|
||
|
{
|
||
|
return db_ops.db_stmt_set_string (stmt, idx, s, error);
|
||
|
}
|
||
|
|
||
|
gboolean
|
||
|
db_stmt_execute (DBStmt *stmt, GError **error)
|
||
|
{
|
||
|
return db_ops.db_stmt_execute (stmt, error);
|
||
|
}
|
||
|
|
||
|
ResultSet *
|
||
|
db_stmt_execute_query (DBStmt *stmt, GError **error)
|
||
|
{
|
||
|
ResultSet *result_set;
|
||
|
|
||
|
if (stmt->result_set) {
|
||
|
result_set_free (stmt->result_set);
|
||
|
stmt->result_set = NULL;
|
||
|
}
|
||
|
|
||
|
result_set = db_ops.db_stmt_execute_query (stmt, error);
|
||
|
|
||
|
if (result_set)
|
||
|
stmt->result_set = result_set;
|
||
|
|
||
|
return result_set;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
db_stmt_free (DBStmt *stmt)
|
||
|
{
|
||
|
if (!stmt)
|
||
|
return;
|
||
|
|
||
|
if (stmt->result_set)
|
||
|
result_set_free (stmt->result_set);
|
||
|
|
||
|
return db_ops.db_stmt_free (stmt);
|
||
|
}
|
||
|
|
||
|
/* Transactions. */
|
||
|
|
||
|
gboolean
|
||
|
db_connection_begin_transaction (DBConnection *conn, GError **error)
|
||
|
{
|
||
|
return db_ops.db_connection_begin_transaction (conn, error);
|
||
|
}
|
||
|
|
||
|
gboolean
|
||
|
db_connection_commit (DBConnection *conn, GError **error)
|
||
|
{
|
||
|
return db_ops.db_connection_commit (conn, error);
|
||
|
}
|
||
|
|
||
|
gboolean
|
||
|
db_connection_rollback (DBConnection *conn, GError **error)
|
||
|
{
|
||
|
db_connection_clear (conn);
|
||
|
|
||
|
return db_ops.db_connection_rollback (conn, error);
|
||
|
}
|