diff options
author | Alexander Sulfrian <alexander@sulfrian.net> | 2011-12-07 04:45:12 +0100 |
---|---|---|
committer | Alexander Sulfrian <alexander@sulfrian.net> | 2011-12-07 04:45:12 +0100 |
commit | 1ef57f73e7a8d8de32587e27a5b3ed35cf64ac99 (patch) | |
tree | 633401b25524684aafad9d4acbf046801feb5ae6 | |
parent | 5ad2ad18db1413db2872eaa1f956d0cf2fe2477d (diff) | |
download | ts3db_postgres-1ef57f73e7a8d8de32587e27a5b3ed35cf64ac99.tar.gz ts3db_postgres-1ef57f73e7a8d8de32587e27a5b3ed35cf64ac99.tar.xz ts3db_postgres-1ef57f73e7a8d8de32587e27a5b3ed35cf64ac99.zip |
some pg progress
current bug: PQoidValue does not work for serial
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | ts3db.c | 272 |
2 files changed, 205 insertions, 74 deletions
@@ -7,9 +7,10 @@ deps:=$(sources:.c=.d) objects:=$(sources:.c=.o) -32BIT=-m32 -CFLAGS=-fPIC $(32BIT) -g -LDFLAGS=-shared -Wl,-soname,$(TARGET) $(32BIT) +#32BIT=-m32 +CFLAGS=-fPIC $(32BIT) -g -std=c99 +CFLAGS+=-I$(shell pg_config --includedir) +LDFLAGS=-shared -Wl,-soname,$(TARGET) $(32BIT) -lpq ############################################################################## @@ -1,135 +1,265 @@ #include "ts3db.h" +#include <libpq-fe.h> +#include <stdbool.h> + +#define MAX_CONNECTIONS 100 + +typedef struct { + PGconn *conn; + PGresult *result; +} pg_connection; static log_callback log = 0; +static pg_connection connections[MAX_CONNECTIONS]; +static unsigned int connection_count = 0; + +static const char *keywords[] = { "host", "hostaddr", "port", "dbname", + "user", "password", "sslmode", "sslcert", + "sslkey", "sslrootcert", "sslcrl", + "application_name", 0}; + +typedef struct { + char *host; + char *hostaddr; + char *port; + char *dbname; + char *user; + char *password; + char *sslmode; + char *sslcert; + char *sslkey; + char *sslrootcert; + char *sslcrl; + char *application_name; +} pg_settings; + +static pg_settings settings; char *ts3dbplugin_version() { - // returns pointer to "127.0.0.1" in constant table ... strange maybe im mistaken here return "0.1"; } char *ts3dbplugin_name() { - // returns pointer to "MySQL plugin, (c)TeamSpeak Systems GmbH" in constant table - return "My own DB Plugin"; + return "PostgreSQL plugin"; } int ts3dbplugin_disconnect() { - // load zero terminated array of db connections from global variable - // iterate over array elements, call mysql_close on all elements and zero them + log("disconnect", LOG_DEVELOP); + ts3dbplugin_shutdown(); return 0; } void ts3dbplugin_shutdown() { - // same as ts3dbplugin_disconnect() but no return 0 + log("shutdown", LOG_DEVELOP); + unsigned int i; + for (i = 0; i < connection_count; i++) { + PQclear(connections[i].result); + PQfinish(connections[i].conn); + } + + connection_count = 0; } int ts3dbplugin_init(log_callback logging, char *parameter) { - char buf[100]; - log = logging; - log("init called", 5); - int bar = log(0, 4); - sprintf(buf,"%d",bar); - log(buf, 5); - log(parameter, 5); - - // logcallback is saved to global variable - // put pointer do some global structure with offset 12 is saved in variable - // if 2nd parameter or its target is zero "tb3db_mysql.ini" is written to a variable - // else the pointer is saved its length is determined and saved also saved (saved in variables) - // ini file is parsed and values are saved to global variables + settings.host = "localhost"; + settings.hostaddr = ""; + settings.port = ""; + settings.dbname = "ts3"; + settings.user = "ts3"; + settings.password = ""; + settings.sslmode = NULL; + settings.sslcert = NULL; + settings.sslkey = NULL; + settings.sslrootcert = NULL; + settings.sslcrl = NULL; + settings.application_name = "teamspeak3"; + return 0; } int ts3dbplugin_connect(unsigned int *connection_nr) { - log("connect called", 5); - *connection_nr = 1337; + PGconn *conn; + + conn = PQconnectdbParams(keywords, (const char **)&settings, true); + if (PQstatus(conn) != CONNECTION_OK) { + log(PQerrorMessage(conn), LOG_CRITICAL); + return 1280; + } + + *connection_nr = connection_count; + connections[connection_count].conn = conn; + connections[connection_count].result = NULL; + connection_count++; - // only does somthing usefull when there are less than 100 connections in the connection array - // calls mysql_init - // big function is big ... needs work - // seems to returns 0 on succses seems to return 1280 on failure return 0; } -char *ts3dbplugin_getlasterror(unsigned int connection_nr) +PGconn *get_connection(unsigned int connection_nr) +{ + if (connection_nr >= connection_count) { + log("Connection not found.", LOG_ERROR); + return NULL; + } + + return connections[connection_nr].conn; +} + +PGresult *get_last_result(unsigned int connection_nr) { - log("getlasterror called", 5); - char buf[100]; - sprintf(buf,"%d", connection_nr); - log(buf, 5); + if (connection_nr >= connection_count) { + log("Connection not found.", LOG_ERROR); + return NULL; + } - // returns output of mysql_error for the connection of the given connection number - return "nothing"; + return connections[connection_nr].result; } -unsigned int ts3dbplugin_tableexists(unsigned int connection_nr, const char* regex) +void save_last_result(unsigned int connection_nr, PGresult *result) { - log("tableexists called", 5); - char buf[100]; - sprintf(buf,"%d", connection_nr); - log(buf, 5); - log(regex, 5); + if (connection_nr >= connection_count) { + log("Connection not found.", LOG_ERROR); + return; + } + + if (connections[connection_nr].result != NULL) { + PQclear(connections[connection_nr].result); + } + + connections[connection_nr].result = result; +} + +char *ts3dbplugin_getlasterror(unsigned int connection_nr) +{ + log("getlasterror", LOG_DEVELOP); + const PGconn *conn = get_connection(connection_nr); + return PQerrorMessage(conn); +} + +unsigned int ts3dbplugin_tableexists(unsigned int connection_nr, const char* table_name) +{ + log("tableexists", LOG_DEVELOP); + log(table_name, LOG_DEVELOP); + PGconn *conn = get_connection(connection_nr); + const char* const params[] = { table_name }; + PGresult *result; + int tables; + + result = PQexecParams(conn, "select 1 from pg_tables where \ + schemaname='public' and \ + tablename = $1 limit 1;", + 1, NULL, params, NULL, NULL, 0); + + tables = PQntuples(result); + PQclear(result); + + if (tables == 0) { + /* table not exists */ + return 0; + } - // returns 0 when no table is found 1 if it is found return 1; } unsigned long long ts3dbplugin_getmodifiedrowcount(unsigned int connection_nr) { - log("get modified row count", 5); - char buf[100]; - sprintf(buf,"%d", connection_nr); - log(buf, 5); + log("getmodifiedrowcount", LOG_DEVELOP); + PGresult *result = get_last_result(connection_nr); + const char *count = PQcmdTuples(result); + unsigned long long number; - // returns output of mysql_affected_rows for given connection - return 0LL; + sscanf(count, "%llu", &number); + return number; } unsigned long long ts3dbplugin_getlastinsertid(unsigned int connection_nr) { - log("get last inserted id", 5); - char buf[100]; - sprintf(buf,"%d", connection_nr); - log(buf, 5); + log("getlastinsertid", LOG_DEVELOP); + const PGresult *result = get_last_result(connection_nr); + Oid value = PQoidValue(result); + fprintf(stderr, "%llu\n", value); + + if (value == InvalidOid) { + log("0", LOG_DEVELOP); + return 0; + } - // returns output of mysql_insert_id for given connection - return 0LL; + return value; } unsigned int ts3dbplugin_open(unsigned int connection_nr, const char* query, field_callback new_field, value_callback new_value, row_callback new_row, void *context) { - log("open", 5); - char buf[100]; - sprintf(buf,"%d", connection_nr); - log(buf, 5); - log(query, 5); - - // get query result - // if row ends value is 0 - // returns 0 for success or 1280 for fail + log(query, LOG_DEBUG); + + ExecStatusType status; + int col_count, row_count, i, j; + PGconn *conn = get_connection(connection_nr); + PGresult *result = PQexec(conn, query); + save_last_result(connection_nr, result); + + status = PQresultStatus(result); + if (status == PGRES_BAD_RESPONSE || status == PGRES_FATAL_ERROR) { + log(PQresultErrorMessage(result), LOG_ERROR); + return 1280; + } + + if (status == PGRES_NONFATAL_ERROR) { + log(PQresultErrorMessage(result), LOG_WARNING); + } + + col_count = PQnfields(result); + for (i = 0; i < col_count; i++) { + log(PQfname(result, i), LOG_DEBUG); + new_field(i, PQfname(result, i), context); + } + + row_count = PQntuples(result); + for (i = 0; i < row_count; i++) { + log("new row", LOG_DEBUG); + new_row(context); + log("new row done.", LOG_DEBUG); + + for (j = 0; j < col_count; j++) { + if (PQgetisnull(result, i, j) == 1) { + log("<NULL>", LOG_DEBUG); + new_value(j, NULL, context); + } + else { + log(PQgetvalue(result, i, j), LOG_DEBUG); + new_value(j, PQgetvalue(result, i, j), context); + } + } + } + return 0; } unsigned int ts3dbplugin_exec(unsigned int connection_nr, const char* query) { - log("exec", 5); - char buf[100]; - sprintf(buf,"%d", connection_nr); - log(buf, 5); - log(query, 5); - - // form sqlite plugin - // executes querry -> retrys every 200ms if db is locked, busy or when the db shema has changed - // return 1284 if db is full - // when result is SQLITE_OK return 0 - // else do error handling and return 1280 + log(query, LOG_DEVELOP); + + ExecStatusType status; + PGconn *conn = get_connection(connection_nr); + PGresult *result = PQexec(conn, query); + save_last_result(connection_nr, result); + + status = PQresultStatus(result); + if (status == PGRES_BAD_RESPONSE || status == PGRES_FATAL_ERROR) { + log(PQresultErrorMessage(result), LOG_ERROR); + return 1280; + } + + if (status == PGRES_NONFATAL_ERROR) { + log(PQresultErrorMessage(result), LOG_WARNING); + } + return 0; } |