25 #include <libfossdbmanager.h> 26 #include <libfossdb.h> 56 #define LOG(level, str, ...) \ 58 FILE* logFile = dbManager->logFile; \ 60 fprintf(logFile, level ": " str, __VA_ARGS__); \ 62 printf(level ": " str, __VA_ARGS__); \ 66 #define LOG_ERROR(str, ...) LOG("ERROR", str, __VA_ARGS__) 68 #define LOG_FATAL(str, ...) LOG("FATAL", str, __VA_ARGS__) 72 #define LOG_DEBUG(str, ...) LOG("DEBUG", str, __VA_ARGS__) 74 #define LOG_DEBUG(str, ...) \ 85 static void cachedPrepared_free(gpointer ptr)
98 static void noticeReceiver(
void* arg,
const PGresult* res) {
100 char* message = PQresultErrorMessage(res);
102 if (!dbManager->ignoreWarns)
103 LOG(
"NOTICE",
"%s", message);
113 fo_dbManager* fo_dbManager_new_withConf(PGconn* dbConnection,
const char* dbConf)
116 dbManager->dbConf = g_strdup(dbConf);
129 result->cachedPrepared = g_hash_table_new_full(
136 result->dbConnection = dbConnection;
137 result->logFile = NULL;
138 result->dbConf = NULL;
139 result->ignoreWarns = 0;
141 PQsetNoticeReceiver(dbConnection, noticeReceiver, result);
174 PGconn* newDbConnection =
fo_dbconnect(dbManager->dbConf, &error);
177 result = fo_dbManager_new_withConf(newDbConnection, dbManager->dbConf);
180 LOG_FATAL(
"Can not open connection\n%s\nWhile forking dbManager using config: '%s'\n",
181 error, dbManager->dbConf);
193 int fo_dbManager_setLogFile(
fo_dbManager* dbManager,
const char* logFileName)
195 if (dbManager->logFile)
196 fclose(dbManager->logFile);
200 dbManager->logFile = fopen(logFileName,
"a");
201 return dbManager->logFile != NULL;
204 dbManager->logFile = NULL;
214 void fo_dbManager_ignoreWarnings(
fo_dbManager* dbManager,
int ignoreWarns)
216 dbManager->ignoreWarns = ignoreWarns;
224 PGconn* fo_dbManager_getWrappedConnection(
fo_dbManager* dbManager)
226 return dbManager->dbConnection;
240 g_hash_table_unref(dbManager->cachedPrepared);
241 if (dbManager->dbConf)
242 free(dbManager->dbConf);
243 if (dbManager->logFile)
244 fclose(dbManager->logFile);
257 PQfinish(dbManager->dbConnection);
269 static char* array_print(
char** parameters,
int count)
271 GString* resultCreator = g_string_new(
"{");
273 for (i = 0; i < count; i++)
276 g_string_append(resultCreator,
", ");
277 g_string_append_printf(resultCreator,
"[%d]='%s'", i, parameters[i]);
279 g_string_append(resultCreator,
"}");
280 return g_string_free(resultCreator, FALSE);
288 static void array_free(
char** parameters,
int count)
291 for (i = 0; i < count; i++)
300 param supported[] = {
301 #define ADDSUPPORTED(n, type, fmt) \ 303 ADDSUPPORTED(0,
long,
"%ld")
304 ADDSUPPORTED(1,
int,
"%d")
305 ADDSUPPORTED(2,
char*,
"%s")
306 ADDSUPPORTED(3,
size_t,
"%zu")
307 ADDSUPPORTED(4,
unsigned,
"%u")
308 ADDSUPPORTED(5,
unsigned int,
"%u")
309 ADDSUPPORTED(6,
unsigned long,
"%lu")
321 static inline char** buildStringArray(
int paramCount,
param*
params, va_list vars)
323 char** result = malloc(
sizeof(
char*) * paramCount);
325 for (i = 0; i < paramCount; i++)
327 param currentParamDesc = params[i];
328 int type = currentParamDesc.
type;
329 char* format = currentParamDesc.
fmt;
332 #define ADDCASE(n, type) \ 335 type t = va_arg(vars, type);\ 336 result[i] = g_strdup_printf(format, t);\ 344 ADDCASE(5,
unsigned int)
345 ADDCASE(6,
unsigned long)
348 printf(
"internal error on typeid=%d\n", type);
349 array_free(result, i - 1);
372 GString* resultCreator = g_string_new(
"");
373 g_string_append_printf(resultCreator,
374 "{ name: '%s', parameterTypes: [",
375 preparedStatement->name);
377 for (i = 0; i < preparedStatement->paramc; i++)
379 param current = preparedStatement->params[i];
380 if (i > 0) g_string_append(resultCreator,
", ");
381 g_string_append_printf(resultCreator,
385 g_string_append_printf(resultCreator,
"]}");
386 return g_string_free(resultCreator, FALSE);
398 PGresult* queryResult = fo_dbManager_Exec_printf(dbManager,
"BEGIN");
402 PQclear(queryResult);
416 PGresult* queryResult = fo_dbManager_Exec_printf(dbManager,
"COMMIT");
420 PQclear(queryResult);
434 PGresult* queryResult = fo_dbManager_Exec_printf(dbManager,
"ROLLBACK");
438 PQclear(queryResult);
451 int fo_dbManager_tableExists(
fo_dbManager* dbManager,
const char* tableName)
453 return fo_dbManager_exists(dbManager,
"table", tableName);
465 int fo_dbManager_exists(
fo_dbManager* dbManager,
const char* type,
const char*
name)
469 char* escapedName = fo_dbManager_StringEscape(dbManager, name);
473 PGresult* queryResult = fo_dbManager_Exec_printf(
475 "select count(*) from information_schema.%ss where %s_catalog='%s' and %s_name='%s'",
477 PQdb(dbManager->dbConnection),
484 if (PQntuples(queryResult) == 1)
486 if (atol(PQgetvalue(queryResult, 0, 0)) == 1)
491 PQclear(queryResult);
518 PGresult* fo_dbManager_Exec_printf(
fo_dbManager* dbManager,
const char* sqlQueryStringFormat, ...)
520 char* sqlQueryString;
521 PGconn* dbConnection = dbManager->dbConnection;
524 va_start(argptr, sqlQueryStringFormat);
525 sqlQueryString = g_strdup_vprintf(sqlQueryStringFormat, argptr);
527 if (sqlQueryString == NULL)
532 PGresult* result = PQexec(dbConnection, sqlQueryString);
536 LOG_FATAL(
"%sOn: %s\n", PQerrorMessage(dbConnection), sqlQueryString);
537 g_free(sqlQueryString);
541 if (PQresultStatus(result) == PGRES_FATAL_ERROR)
543 LOG_ERROR(
"%sOn: %s\n", PQresultErrorMessage(result), sqlQueryString);
544 g_free(sqlQueryString);
548 g_free(sqlQueryString);
561 char* fo_dbManager_StringEscape(
fo_dbManager* dbManager,
const char*
string)
563 size_t length = strlen(
string);
564 char* dest = malloc(2 * length + 1);
567 PQescapeStringConn(dbManager->dbConnection, dest,
string, length, &err);
586 if (!preparedStatement)
591 va_start(vars, preparedStatement);
592 PGresult* result = fo_dbManager_ExecPreparedv(preparedStatement, vars);
607 if (!preparedStatement)
612 char** parameters = buildStringArray(preparedStatement->paramc, preparedStatement->params, args);
615 PGconn* dbConnection = dbManager->dbConnection;
618 char* printedStatement = fo_dbManager_printStatement(preparedStatement);
619 char* params = array_print(parameters, preparedStatement->paramc);
620 LOG_DEBUG(
"Exec prepared '%s' with params '%s'\n",
623 g_free(printedStatement);
626 PGresult* result = PQexecPrepared(dbConnection,
627 preparedStatement->name,
628 preparedStatement->paramc,
629 (
const char*
const*) parameters,
636 char* printedStatement = fo_dbManager_printStatement(preparedStatement);
637 char* params = array_print(parameters, preparedStatement->paramc);
638 LOG_FATAL(
"%sExecuting prepared '%s' with params %s\n",
639 PQerrorMessage(dbConnection),
642 g_free(printedStatement);
644 }
else if (PQresultStatus(result) == PGRES_FATAL_ERROR)
646 char* printedStatement = fo_dbManager_printStatement(preparedStatement);
647 char* params = array_print(parameters, preparedStatement->paramc);
648 LOG_ERROR(
"%sExecuting prepared '%s' with params %s\n",
649 PQresultErrorMessage(result),
652 g_free(printedStatement);
659 array_free(parameters, preparedStatement->paramc);
671 static inline int parseParamStr_equals(
const char* a,
const char* b,
size_t bLength)
673 const char* ptrA = a;
674 const char* ptrB = b;
677 while (*ptrA && lenB < bLength)
683 while (isspace(*ptrB) && lenB < bLength)
690 if ((lenB == bLength) || (*ptrB != *ptrA))
697 return (!(*ptrA) && (lenB == bLength));
708 static inline int parseParamStr_set(
const char* type,
size_t length,
param* dest)
710 param* ptr = supported;
713 if (parseParamStr_equals(ptr->
name, type, length))
730 int fo_dbManager_parseParamStr(
const char* paramtypes, GArray** params)
732 *params = g_array_new(TRUE, FALSE,
sizeof(
param));
733 GArray* paramsG = *
params;
735 const char* ptr = paramtypes;
736 size_t currentLength = 0;
737 const char* currentStart;
738 const char* nextStart = ptr;
743 while (*ptr && (isspace(*ptr)))
748 while (*ptr && *ptr !=
',')
756 if (ptr == currentStart)
760 while (ptr != currentStart && isspace(*ptr))
769 if (parseParamStr_set(currentStart, currentLength, &next))
771 g_array_append_val(paramsG, next);
790 g_array_set_size(paramsG, 0);
805 int success = fo_dbManager_parseParamStr(paramtypes, ¶msG);
807 statement->paramc = paramsG->len;
808 statement->params = (
param*) g_array_free(paramsG, FALSE);
823 fo_dbManager* dbManager,
const char*
name,
const char* query,
const char* paramtypes
826 GHashTable* cachedPrepared = dbManager->cachedPrepared;
831 LOG_DEBUG(
"returning cached statement '%s'\n", cached->name);
837 PGconn* dbConnection = dbManager->dbConnection;
840 result->name = g_strdup(
name);
843 if (parseParamStr(result, paramtypes))
845 PGresult* prepareResult = PQprepare(dbConnection, result->name, query, 0, NULL);
849 char* printedStatement = fo_dbManager_printStatement(result);
850 LOG_FATAL(
"%sPreparing of '%s' AS '%s'\n",
851 PQerrorMessage(dbConnection),
854 free(printedStatement);
858 if (PQresultStatus(prepareResult) != PGRES_COMMAND_OK)
860 char* printedStatement = fo_dbManager_printStatement(result);
861 LOG_ERROR(
"%sPreparing of '%s' AS '%s'\n",
862 PQresultErrorMessage(prepareResult),
865 free(printedStatement);
868 PQclear(prepareResult);
872 LOG_FATAL(
"dbManager could not comprehend parameter types '%s'\n" 873 "Trying to prepare '%s' as '%s'\n", paramtypes,
name, query);
879 cachedPrepared_free(result);
883 g_hash_table_insert(cachedPrepared, result->name, result);
fo_dbManager_PreparedStatement * fo_dbManager_PrepareStamement_str(fo_dbManager *dbManager, const char *name, const char *query, const char *paramtypes)
Create a prepared statement.
char * fmt
Printf format string for the parameter.
fo_dbManager * dbManager
DB manager.
PGresult * fo_dbManager_ExecPrepared(fo_dbManager_PreparedStatement *preparedStatement,...)
Execute a prepared statement.
int ignoreWarns
Set to ignore warnings from logging.
param * params
Query parameters.
char * name
Name of the prepared statement.
char * dbConf
DB conf file location.
fo_dbManager * fo_dbManager_new(PGconn *dbConnection)
Create and initialize new fo_dbManager object.
FILE * logFile
FOSSology log file pointer.
PGconn * dbConnection
Postgres database connection object.
int paramc
Number of paramenters.
char * name
Name of the parameter.
void fo_dbManager_free(fo_dbManager *dbManager)
Un-allocate the memory from a DB manager.
int type
Type of parameter, check buildStringArray() for more.
PGconn * fo_dbconnect(char *DBConfFile, char **ErrorBuf)
Connect to a database. The default is Db.conf.
GHashTable * cachedPrepared
Hash table of prepared statements.