14 #include <libfossdbmanager.h>
15 #include <libfossdb.h>
45 #define LOG(level, str, ...) \
47 FILE* logFile = dbManager->logFile; \
49 fprintf(logFile, level ": " str, __VA_ARGS__); \
51 printf(level ": " str, __VA_ARGS__); \
55 #define LOG_ERROR(str, ...) LOG("ERROR", str, __VA_ARGS__)
57 #define LOG_FATAL(str, ...) LOG("FATAL", str, __VA_ARGS__)
61 #define LOG_DEBUG(str, ...) LOG("DEBUG", str, __VA_ARGS__)
63 #define LOG_DEBUG(str, ...) \
74 static void cachedPrepared_free(gpointer ptr)
87 static void noticeReceiver(
void* arg,
const PGresult* res) {
89 char* message = PQresultErrorMessage(res);
92 LOG(
"NOTICE",
"%s", message);
102 fo_dbManager* fo_dbManager_new_withConf(PGconn* dbConnection,
const char* dbConf)
118 result->cachedPrepared = g_hash_table_new_full(
125 result->dbConnection = dbConnection;
126 result->logFile = NULL;
127 result->dbConf = NULL;
128 result->ignoreWarns = 0;
130 PQsetNoticeReceiver(dbConnection, noticeReceiver, result);
166 result = fo_dbManager_new_withConf(newDbConnection,
dbManager->dbConf);
169 LOG_FATAL(
"Can not open connection\n%s\nWhile forking dbManager using config: '%s'\n",
189 dbManager->logFile = fopen(logFileName,
"a");
229 g_hash_table_unref(
dbManager->cachedPrepared);
258 static char* array_print(
char** parameters,
int count)
260 GString* resultCreator = g_string_new(
"{");
262 for (i = 0; i < count; i++)
265 g_string_append(resultCreator,
", ");
266 g_string_append_printf(resultCreator,
"[%d]='%s'", i, parameters[i]);
268 g_string_append(resultCreator,
"}");
269 return g_string_free(resultCreator, FALSE);
277 static void array_free(
char** parameters,
int count)
280 for (i = 0; i < count; i++)
289 param supported[] = {
290 #define ADDSUPPORTED(n, type, fmt) \
292 ADDSUPPORTED(0,
long,
"%ld")
293 ADDSUPPORTED(1,
int, "%d")
294 ADDSUPPORTED(2,
char*, "%
s")
295 ADDSUPPORTED(3,
size_t, "%zu")
296 ADDSUPPORTED(4,
unsigned, "%u")
297 ADDSUPPORTED(5,
unsigned int, "%u")
298 ADDSUPPORTED(6,
unsigned long, "%lu")
310 static inline char** buildStringArray(
int paramCount,
param* params, va_list vars)
312 char** result = malloc(
sizeof(
char*) * paramCount);
314 for (i = 0; i < paramCount; i++)
316 param currentParamDesc = params[i];
317 int type = currentParamDesc.
type;
318 char* format = currentParamDesc.
fmt;
321 #define ADDCASE(n, type) \
324 type t = va_arg(vars, type);\
325 result[i] = g_strdup_printf(format, t);\
333 ADDCASE(5,
unsigned int)
334 ADDCASE(6,
unsigned long)
337 printf(
"internal error on typeid=%d\n", type);
338 array_free(result, i - 1);
361 GString* resultCreator = g_string_new(
"");
362 g_string_append_printf(resultCreator,
363 "{ name: '%s', parameterTypes: [",
364 preparedStatement->name);
366 for (i = 0; i < preparedStatement->paramc; i++)
368 param current = preparedStatement->params[i];
369 if (i > 0) g_string_append(resultCreator,
", ");
370 g_string_append_printf(resultCreator,
374 g_string_append_printf(resultCreator,
"]}");
375 return g_string_free(resultCreator, FALSE);
387 PGresult* queryResult = fo_dbManager_Exec_printf(
dbManager,
"BEGIN");
391 PQclear(queryResult);
405 PGresult* queryResult = fo_dbManager_Exec_printf(
dbManager,
"COMMIT");
409 PQclear(queryResult);
423 PGresult* queryResult = fo_dbManager_Exec_printf(
dbManager,
"ROLLBACK");
427 PQclear(queryResult);
442 return fo_dbManager_exists(
dbManager,
"table", tableName);
458 char* escapedName = fo_dbManager_StringEscape(
dbManager, name);
462 PGresult* queryResult = fo_dbManager_Exec_printf(
464 "select count(*) from information_schema.%ss where %s_catalog='%s' and %s_name='%s'",
473 if (PQntuples(queryResult) == 1)
475 if (atol(PQgetvalue(queryResult, 0, 0)) == 1)
480 PQclear(queryResult);
509 char* sqlQueryString;
510 PGconn* dbConnection =
dbManager->dbConnection;
513 va_start(argptr, sqlQueryStringFormat);
514 sqlQueryString = g_strdup_vprintf(sqlQueryStringFormat, argptr);
516 if (sqlQueryString == NULL)
521 PGresult* result = PQexec(dbConnection, sqlQueryString);
525 LOG_FATAL(
"%sOn: %s\n", PQerrorMessage(dbConnection), sqlQueryString);
526 g_free(sqlQueryString);
530 if (PQresultStatus(result) == PGRES_FATAL_ERROR)
532 LOG_ERROR(
"%sOn: %s\n", PQresultErrorMessage(result), sqlQueryString);
533 g_free(sqlQueryString);
537 g_free(sqlQueryString);
552 size_t length = strlen(
string);
553 char* dest = malloc(2 * length + 1);
556 PQescapeStringConn(
dbManager->dbConnection, dest,
string, length, &err);
575 if (!preparedStatement)
580 va_start(vars, preparedStatement);
581 PGresult* result = fo_dbManager_ExecPreparedv(preparedStatement, vars);
596 if (!preparedStatement)
601 char** parameters = buildStringArray(preparedStatement->paramc, preparedStatement->params, args);
604 PGconn* dbConnection =
dbManager->dbConnection;
607 char* printedStatement = fo_dbManager_printStatement(preparedStatement);
608 char* params = array_print(parameters, preparedStatement->paramc);
609 LOG_DEBUG(
"Exec prepared '%s' with params '%s'\n",
612 g_free(printedStatement);
615 PGresult* result = PQexecPrepared(dbConnection,
616 preparedStatement->name,
617 preparedStatement->paramc,
618 (
const char*
const*) parameters,
625 char* printedStatement = fo_dbManager_printStatement(preparedStatement);
626 char* params = array_print(parameters, preparedStatement->paramc);
627 LOG_FATAL(
"%sExecuting prepared '%s' with params %s\n",
628 PQerrorMessage(dbConnection),
631 g_free(printedStatement);
633 }
else if (PQresultStatus(result) == PGRES_FATAL_ERROR)
635 char* printedStatement = fo_dbManager_printStatement(preparedStatement);
636 char* params = array_print(parameters, preparedStatement->paramc);
637 LOG_ERROR(
"%sExecuting prepared '%s' with params %s\n",
638 PQresultErrorMessage(result),
641 g_free(printedStatement);
648 array_free(parameters, preparedStatement->paramc);
660 static inline int parseParamStr_equals(
const char* a,
const char* b,
size_t bLength)
662 const char* ptrA = a;
663 const char* ptrB = b;
666 while (*ptrA && lenB < bLength)
672 while (isspace(*ptrB) && lenB < bLength)
679 if ((lenB == bLength) || (*ptrB != *ptrA))
686 return (!(*ptrA) && (lenB == bLength));
697 static inline int parseParamStr_set(
const char* type,
size_t length,
param* dest)
699 param* ptr = supported;
702 if (parseParamStr_equals(ptr->
name, type, length))
719 int fo_dbManager_parseParamStr(
const char* paramtypes, GArray** params)
721 *params = g_array_new(TRUE, FALSE,
sizeof(
param));
722 GArray* paramsG = *params;
724 const char* ptr = paramtypes;
725 size_t currentLength = 0;
726 const char* currentStart;
727 const char* nextStart = ptr;
732 while (*ptr && (isspace(*ptr)))
737 while (*ptr && *ptr !=
',')
745 if (ptr == currentStart)
749 while (ptr != currentStart && isspace(*ptr))
758 if (parseParamStr_set(currentStart, currentLength, &next))
760 g_array_append_val(paramsG, next);
779 g_array_set_size(paramsG, 0);
794 int success = fo_dbManager_parseParamStr(paramtypes, ¶msG);
796 statement->paramc = paramsG->len;
797 statement->params = (
param*) g_array_free(paramsG, FALSE);
815 GHashTable* cachedPrepared =
dbManager->cachedPrepared;
820 LOG_DEBUG(
"returning cached statement '%s'\n", cached->name);
826 PGconn* dbConnection =
dbManager->dbConnection;
829 result->name = g_strdup(name);
832 if (parseParamStr(result, paramtypes))
834 PGresult* prepareResult = PQprepare(dbConnection, result->name, query, 0, NULL);
838 char* printedStatement = fo_dbManager_printStatement(result);
839 LOG_FATAL(
"%sPreparing of '%s' AS '%s'\n",
840 PQerrorMessage(dbConnection),
843 free(printedStatement);
847 if (PQresultStatus(prepareResult) != PGRES_COMMAND_OK)
849 char* printedStatement = fo_dbManager_printStatement(result);
850 LOG_ERROR(
"%sPreparing of '%s' AS '%s'\n",
851 PQresultErrorMessage(prepareResult),
854 free(printedStatement);
857 PQclear(prepareResult);
861 LOG_FATAL(
"dbManager could not comprehend parameter types '%s'\n"
862 "Trying to prepare '%s' as '%s'\n", paramtypes, name, query);
868 cachedPrepared_free(result);
872 g_hash_table_insert(cachedPrepared, result->name, result);
int s
The socket that the CLI will use to communicate.
PGconn * fo_dbconnect(char *DBConfFile, char **ErrorBuf)
Connect to a database. The default is Db.conf.
fo_dbManager * dbManager
fo_dbManager object
fo_dbManager_PreparedStatement * fo_dbManager_PrepareStamement_str(fo_dbManager *dbManager, const char *name, const char *query, const char *paramtypes)
Create a prepared statement.
PGresult * fo_dbManager_ExecPrepared(fo_dbManager_PreparedStatement *preparedStatement,...)
Execute a prepared statement.
fo_dbManager * fo_dbManager_new(PGconn *dbConnection)
Create and initialize new fo_dbManager object.
void fo_dbManager_free(fo_dbManager *dbManager)
Un-allocate the memory from a DB manager.
int paramc
Number of paramenters.
param * params
Query parameters.
char * name
Name of the prepared statement.
fo_dbManager * dbManager
DB manager.
PGconn * dbConnection
Postgres database connection object.
GHashTable * cachedPrepared
Hash table of prepared statements.
int ignoreWarns
Set to ignore warnings from logging.
char * dbConf
DB conf file location.
FILE * logFile
FOSSology log file pointer.
int type
Type of parameter, check buildStringArray() for more.
char * fmt
Printf format string for the parameter.
char * name
Name of the parameter.