summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Sulfrian <alexander@sulfrian.net>2011-12-07 04:45:12 +0100
committerAlexander Sulfrian <alexander@sulfrian.net>2011-12-07 04:45:12 +0100
commit1ef57f73e7a8d8de32587e27a5b3ed35cf64ac99 (patch)
tree633401b25524684aafad9d4acbf046801feb5ae6
parent5ad2ad18db1413db2872eaa1f956d0cf2fe2477d (diff)
downloadts3db_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--Makefile7
-rw-r--r--ts3db.c272
2 files changed, 205 insertions, 74 deletions
diff --git a/Makefile b/Makefile
index 14ec492..5309c21 100644
--- a/Makefile
+++ b/Makefile
@@ -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
##############################################################################
diff --git a/ts3db.c b/ts3db.c
index 9f45ac4..e6e1848 100644
--- a/ts3db.c
+++ b/ts3db.c
@@ -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;
}