summaryrefslogtreecommitdiff
path: root/res/res_config_pgsql.c
diff options
context:
space:
mode:
Diffstat (limited to 'res/res_config_pgsql.c')
-rw-r--r--res/res_config_pgsql.c365
1 files changed, 240 insertions, 125 deletions
diff --git a/res/res_config_pgsql.c b/res/res_config_pgsql.c
index f7c1f3a6a..fe672bf62 100644
--- a/res/res_config_pgsql.c
+++ b/res/res_config_pgsql.c
@@ -42,6 +42,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/cli.h"
AST_MUTEX_DEFINE_STATIC(pgsql_lock);
+AST_THREADSTORAGE(sql_buf);
+AST_THREADSTORAGE(findtable_buf);
+AST_THREADSTORAGE(where_buf);
+AST_THREADSTORAGE(escapebuf_buf);
#define RES_CONFIG_PGSQL_CONF "res_pgsql.conf"
@@ -59,7 +63,7 @@ struct columns {
};
struct tables {
- ast_mutex_t lock;
+ ast_rwlock_t lock;
AST_LIST_HEAD_NOLOCK(psql_columns, columns) columns;
AST_LIST_ENTRY(tables) list;
char name[0];
@@ -87,15 +91,24 @@ static struct ast_cli_entry cli_realtime[] = {
AST_CLI_DEFINE(handle_cli_realtime_pgsql_cache, "Shows cached tables within the PostgreSQL realtime driver"),
};
+#define ESCAPE_STRING(buffer, stringname) \
+ do { \
+ int len; \
+ if ((len = strlen(stringname)) > (buffer->len - 1) / 2) { \
+ ast_str_make_space(&buffer, len * 2 + 1); \
+ } \
+ PQescapeStringConn(pgsqlConn, buffer->str, stringname, len, &pgresult); \
+ } while (0)
+
static void destroy_table(struct tables *table)
{
struct columns *column;
- ast_mutex_lock(&table->lock);
+ ast_rwlock_wrlock(&table->lock);
while ((column = AST_LIST_REMOVE_HEAD(&table->columns, list))) {
ast_free(column);
}
- ast_mutex_unlock(&table->lock);
- ast_mutex_destroy(&table->lock);
+ ast_rwlock_unlock(&table->lock);
+ ast_rwlock_destroy(&table->lock);
ast_free(table);
}
@@ -103,7 +116,7 @@ static struct tables *find_table(const char *tablename)
{
struct columns *column;
struct tables *table;
- struct ast_str *sql = ast_str_create(330);
+ struct ast_str *sql = ast_str_thread_get(&findtable_buf, 330);
char *pgerror;
PGresult *result;
char *fname, *ftype, *flen, *fnotnull, *fdef;
@@ -113,7 +126,7 @@ static struct tables *find_table(const char *tablename)
AST_LIST_TRAVERSE(&psql_tables, table, list) {
if (!strcasecmp(table->name, tablename)) {
ast_debug(1, "Found table in cache; now locking\n");
- ast_mutex_lock(&table->lock);
+ ast_rwlock_rdlock(&table->lock);
ast_debug(1, "Lock cached table; now returning\n");
AST_LIST_UNLOCK(&psql_tables);
return table;
@@ -140,9 +153,9 @@ static struct tables *find_table(const char *tablename)
return NULL;
}
strcpy(table->name, tablename); /* SAFE */
- ast_mutex_init(&table->lock);
+ ast_rwlock_init(&table->lock);
AST_LIST_HEAD_INIT_NOLOCK(&table->columns);
-
+
rows = PQntuples(result);
for (i = 0; i < rows; i++) {
fname = PQgetvalue(result, i, 0);
@@ -186,23 +199,39 @@ static struct tables *find_table(const char *tablename)
PQclear(result);
AST_LIST_INSERT_TAIL(&psql_tables, table, list);
- ast_mutex_lock(&table->lock);
+ ast_rwlock_rdlock(&table->lock);
AST_LIST_UNLOCK(&psql_tables);
return table;
}
-static struct ast_variable *realtime_pgsql(const char *database, const char *table, va_list ap)
+#define release_table(table) ast_rwlock_unlock(&(table)->lock);
+
+static struct columns *find_column(struct tables *t, const char *colname)
+{
+ struct columns *column;
+
+ /* Check that the column exists in the table */
+ AST_LIST_TRAVERSE(&t->columns, column, list) {
+ if (strcmp(column->name, colname) == 0) {
+ return column;
+ }
+ }
+ return NULL;
+}
+
+static struct ast_variable *realtime_pgsql(const char *database, const char *tablename, va_list ap)
{
PGresult *result = NULL;
- int num_rows = 0, pgerror;
- char sql[256], escapebuf[513];
+ int num_rows = 0, pgresult;
+ struct ast_str *sql = ast_str_thread_get(&sql_buf, 100);
+ struct ast_str *escapebuf = ast_str_thread_get(&escapebuf_buf, 100);
char *stringp;
char *chunk;
char *op;
const char *newparam, *newval;
struct ast_variable *var = NULL, *prev = NULL;
- if (!table) {
+ if (!tablename) {
ast_log(LOG_WARNING, "PostgreSQL RealTime: No table specified.\n");
return NULL;
}
@@ -216,7 +245,7 @@ static struct ast_variable *realtime_pgsql(const char *database, const char *tab
if (pgsqlConn) {
PQfinish(pgsqlConn);
pgsqlConn = NULL;
- };
+ }
return NULL;
}
@@ -224,15 +253,14 @@ static struct ast_variable *realtime_pgsql(const char *database, const char *tab
If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
op = strchr(newparam, ' ') ? "" : " =";
- PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror);
- if (pgerror) {
+ ESCAPE_STRING(escapebuf, newval);
+ if (pgresult) {
ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval);
va_end(ap);
return NULL;
}
- snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op,
- escapebuf);
+ ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s '%s'", tablename, newparam, op, escapebuf->str);
while ((newparam = va_arg(ap, const char *))) {
newval = va_arg(ap, const char *);
if (!strchr(newparam, ' '))
@@ -240,15 +268,14 @@ static struct ast_variable *realtime_pgsql(const char *database, const char *tab
else
op = "";
- PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror);
- if (pgerror) {
+ ESCAPE_STRING(escapebuf, newval);
+ if (pgresult) {
ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval);
va_end(ap);
return NULL;
}
- snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam,
- op, escapebuf);
+ ast_str_append(&sql, 0, " AND %s%s '%s'", newparam, op, escapebuf->str);
}
va_end(ap);
@@ -259,10 +286,10 @@ static struct ast_variable *realtime_pgsql(const char *database, const char *tab
return NULL;
}
- if (!(result = PQexec(pgsqlConn, sql))) {
+ if (!(result = PQexec(pgsqlConn, sql->str))) {
ast_log(LOG_WARNING,
- "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
- ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql);
+ "PostgreSQL RealTime: Failed to query '%s@%s'. Check debug for more info.\n", tablename, database);
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str);
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
ast_mutex_unlock(&pgsql_lock);
return NULL;
@@ -272,8 +299,8 @@ static struct ast_variable *realtime_pgsql(const char *database, const char *tab
&& result_status != PGRES_TUPLES_OK
&& result_status != PGRES_NONFATAL_ERROR) {
ast_log(LOG_WARNING,
- "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
- ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql);
+ "PostgreSQL RealTime: Failed to query '%s@%s'. Check debug for more info.\n", tablename, database);
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str);
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n",
PQresultErrorMessage(result), PQresStatus(result_status));
ast_mutex_unlock(&pgsql_lock);
@@ -281,7 +308,7 @@ static struct ast_variable *realtime_pgsql(const char *database, const char *tab
}
}
- ast_debug(1, "PostgreSQL RealTime: Result=%p Query: %s\n", result, sql);
+ ast_debug(1, "PostgreSQL RealTime: Result=%p Query: %s\n", result, sql->str);
if ((num_rows = PQntuples(result)) > 0) {
int i = 0;
@@ -318,7 +345,7 @@ static struct ast_variable *realtime_pgsql(const char *database, const char *tab
}
ast_free(fieldnames);
} else {
- ast_debug(1, "Postgresql RealTime: Could not find any rows in table %s.\n", table);
+ ast_debug(1, "Postgresql RealTime: Could not find any rows in table %s@%s.\n", tablename, database);
}
ast_mutex_unlock(&pgsql_lock);
@@ -330,8 +357,9 @@ static struct ast_variable *realtime_pgsql(const char *database, const char *tab
static struct ast_config *realtime_multi_pgsql(const char *database, const char *table, va_list ap)
{
PGresult *result = NULL;
- int num_rows = 0, pgerror;
- char sql[256], escapebuf[513];
+ int num_rows = 0, pgresult;
+ struct ast_str *sql = ast_str_thread_get(&sql_buf, 100);
+ struct ast_str *escapebuf = ast_str_thread_get(&escapebuf_buf, 100);
const char *initfield = NULL;
char *stringp;
char *chunk;
@@ -358,7 +386,7 @@ static struct ast_config *realtime_multi_pgsql(const char *database, const char
if (pgsqlConn) {
PQfinish(pgsqlConn);
pgsqlConn = NULL;
- };
+ }
return NULL;
}
@@ -375,15 +403,14 @@ static struct ast_config *realtime_multi_pgsql(const char *database, const char
else
op = "";
- PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror);
- if (pgerror) {
+ ESCAPE_STRING(escapebuf, newval);
+ if (pgresult) {
ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval);
va_end(ap);
return NULL;
}
- snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op,
- escapebuf);
+ ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, escapebuf->str);
while ((newparam = va_arg(ap, const char *))) {
newval = va_arg(ap, const char *);
if (!strchr(newparam, ' '))
@@ -391,19 +418,18 @@ static struct ast_config *realtime_multi_pgsql(const char *database, const char
else
op = "";
- PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror);
- if (pgerror) {
+ ESCAPE_STRING(escapebuf, newval);
+ if (pgresult) {
ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval);
va_end(ap);
return NULL;
}
- snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam,
- op, escapebuf);
+ ast_str_append(&sql, 0, " AND %s%s '%s'", newparam, op, escapebuf->str);
}
if (initfield) {
- snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield);
+ ast_str_append(&sql, 0, " ORDER BY %s", initfield);
}
va_end(ap);
@@ -415,10 +441,10 @@ static struct ast_config *realtime_multi_pgsql(const char *database, const char
return NULL;
}
- if (!(result = PQexec(pgsqlConn, sql))) {
+ if (!(result = PQexec(pgsqlConn, sql->str))) {
ast_log(LOG_WARNING,
- "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
- ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql);
+ "PostgreSQL RealTime: Failed to query %s@%s. Check debug for more info.\n", table, database);
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str);
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
ast_mutex_unlock(&pgsql_lock);
return NULL;
@@ -428,8 +454,8 @@ static struct ast_config *realtime_multi_pgsql(const char *database, const char
&& result_status != PGRES_TUPLES_OK
&& result_status != PGRES_NONFATAL_ERROR) {
ast_log(LOG_WARNING,
- "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
- ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql);
+ "PostgreSQL RealTime: Failed to query %s@%s. Check debug for more info.\n", table, database);
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str);
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n",
PQresultErrorMessage(result), PQresStatus(result_status));
ast_mutex_unlock(&pgsql_lock);
@@ -437,7 +463,7 @@ static struct ast_config *realtime_multi_pgsql(const char *database, const char
}
}
- ast_debug(1, "PostgreSQL RealTime: Result=%p Query: %s\n", result, sql);
+ ast_debug(1, "PostgreSQL RealTime: Result=%p Query: %s\n", result, sql->str);
if ((num_rows = PQntuples(result)) > 0) {
int numFields = PQnfields(result);
@@ -490,22 +516,20 @@ static int update_pgsql(const char *database, const char *tablename, const char
const char *lookup, va_list ap)
{
PGresult *result = NULL;
- int numrows = 0, pgerror;
- char escapebuf[513];
+ int numrows = 0, pgresult;
const char *newparam, *newval;
- struct ast_str *sql = ast_str_create(100);
+ struct ast_str *sql = ast_str_thread_get(&sql_buf, 100);
+ struct ast_str *escapebuf = ast_str_thread_get(&escapebuf_buf, 100);
struct tables *table;
struct columns *column = NULL;
if (!tablename) {
ast_log(LOG_WARNING, "PostgreSQL RealTime: No table specified.\n");
- ast_free(sql);
return -1;
}
if (!(table = find_table(tablename))) {
ast_log(LOG_ERROR, "Table '%s' does not exist!!\n", tablename);
- ast_free(sql);
return -1;
}
@@ -518,9 +542,8 @@ static int update_pgsql(const char *database, const char *tablename, const char
if (pgsqlConn) {
PQfinish(pgsqlConn);
pgsqlConn = NULL;
- };
- ast_mutex_unlock(&table->lock);
- ast_free(sql);
+ }
+ release_table(table);
return -1;
}
@@ -533,62 +556,51 @@ static int update_pgsql(const char *database, const char *tablename, const char
if (!column) {
ast_log(LOG_ERROR, "PostgreSQL RealTime: Updating on column '%s', but that column does not exist within the table '%s'!\n", newparam, tablename);
- ast_mutex_unlock(&table->lock);
- ast_free(sql);
+ release_table(table);
return -1;
}
/* Create the first part of the query using the first parameter/value pairs we just extracted
If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
- PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror);
- if (pgerror) {
+ ESCAPE_STRING(escapebuf, newval);
+ if (pgresult) {
ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval);
va_end(ap);
- ast_mutex_unlock(&table->lock);
- ast_free(sql);
+ release_table(table);
return -1;
}
- ast_str_set(&sql, 0, "UPDATE %s SET %s = '%s'", tablename, newparam, escapebuf);
+ ast_str_set(&sql, 0, "UPDATE %s SET %s = '%s'", tablename, newparam, escapebuf->str);
while ((newparam = va_arg(ap, const char *))) {
newval = va_arg(ap, const char *);
- /* If the column is not within the table, then skip it */
- AST_LIST_TRAVERSE(&table->columns, column, list) {
- if (strcmp(column->name, newparam) == 0) {
- break;
- }
- }
-
- if (!column) {
+ if (!find_column(table, newparam)) {
ast_log(LOG_WARNING, "Attempted to update column '%s' in table '%s', but column does not exist!\n", newparam, tablename);
continue;
}
- PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror);
- if (pgerror) {
+ ESCAPE_STRING(escapebuf, newval);
+ if (pgresult) {
ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval);
va_end(ap);
- ast_mutex_unlock(&table->lock);
- ast_free(sql);
+ release_table(table);
return -1;
}
- ast_str_append(&sql, 0, ", %s = '%s'", newparam, escapebuf);
+ ast_str_append(&sql, 0, ", %s = '%s'", newparam, escapebuf->str);
}
va_end(ap);
- ast_mutex_unlock(&table->lock);
+ release_table(table);
- PQescapeStringConn(pgsqlConn, escapebuf, lookup, (sizeof(escapebuf) - 1) / 2, &pgerror);
- if (pgerror) {
+ ESCAPE_STRING(escapebuf, lookup);
+ if (pgresult) {
ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", lookup);
va_end(ap);
- ast_free(sql);
return -1;
}
- ast_str_append(&sql, 0, " WHERE %s = '%s'", keyfield, escapebuf);
+ ast_str_append(&sql, 0, " WHERE %s = '%s'", keyfield, escapebuf->str);
ast_debug(1, "PostgreSQL RealTime: Update SQL: %s\n", sql->str);
@@ -596,7 +608,6 @@ static int update_pgsql(const char *database, const char *tablename, const char
ast_mutex_lock(&pgsql_lock);
if (!pgsql_reconnect(database)) {
ast_mutex_unlock(&pgsql_lock);
- ast_free(sql);
return -1;
}
@@ -642,22 +653,145 @@ static int update_pgsql(const char *database, const char *tablename, const char
return -1;
}
-#define ESCAPE_STRING(buffer, stringname) \
- do { \
- int len; \
- if ((len = strlen(stringname)) > (buffer->len - 1) / 2) { \
- ast_str_make_space(&buffer, len * 2 + 1); \
- } \
- PQescapeStringConn(pgsqlConn, buffer->str, stringname, len, &pgresult); \
- } while (0)
+static int update2_pgsql(const char *database, const char *tablename, va_list ap)
+{
+ PGresult *result = NULL;
+ int numrows = 0, pgresult, first = 1;
+ struct ast_str *escapebuf = ast_str_thread_get(&escapebuf_buf, 16);
+ const char *newparam, *newval;
+ struct ast_str *sql = ast_str_thread_get(&sql_buf, 100);
+ struct ast_str *where = ast_str_thread_get(&where_buf, 100);
+ struct tables *table;
+
+ if (!tablename) {
+ ast_log(LOG_WARNING, "PostgreSQL RealTime: No table specified.\n");
+ return -1;
+ }
+
+ if (!escapebuf || !sql || !where) {
+ /* Memory error, already handled */
+ return -1;
+ }
+
+ if (!(table = find_table(tablename))) {
+ ast_log(LOG_ERROR, "Table '%s' does not exist!!\n", tablename);
+ return -1;
+ }
+
+ ast_str_set(&sql, 0, "UPDATE %s SET ", tablename);
+ ast_str_set(&where, 0, "WHERE");
+
+ while ((newparam = va_arg(ap, const char *))) {
+ if (!find_column(table, newparam)) {
+ ast_log(LOG_ERROR, "Attempted to update based on criteria column '%s' (%s@%s), but that column does not exist!\n", newparam, tablename, database);
+ release_table(table);
+ return -1;
+ }
+
+ newval = va_arg(ap, const char *);
+ ESCAPE_STRING(escapebuf, newval);
+ if (pgresult) {
+ ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval);
+ release_table(table);
+ ast_free(sql);
+ return -1;
+ }
+ ast_str_append(&where, 0, "%s %s='%s'", first ? "" : " AND", newparam, escapebuf->str);
+ first = 0;
+ }
+
+ if (first) {
+ ast_log(LOG_WARNING,
+ "PostgreSQL RealTime: Realtime update requires at least 1 parameter and 1 value to search on.\n");
+ if (pgsqlConn) {
+ PQfinish(pgsqlConn);
+ pgsqlConn = NULL;
+ }
+ release_table(table);
+ return -1;
+ }
+
+ /* Now retrieve the columns to update */
+ first = 1;
+ while ((newparam = va_arg(ap, const char *))) {
+ newval = va_arg(ap, const char *);
+
+ /* If the column is not within the table, then skip it */
+ if (!find_column(table, newparam)) {
+ ast_log(LOG_NOTICE, "Attempted to update column '%s' in table '%s@%s', but column does not exist!\n", newparam, tablename, database);
+ continue;
+ }
+
+ ESCAPE_STRING(escapebuf, newval);
+ if (pgresult) {
+ ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval);
+ release_table(table);
+ ast_free(sql);
+ return -1;
+ }
+
+ ast_str_append(&sql, 0, "%s %s='%s'", first ? "" : ",", newparam, escapebuf->str);
+ }
+ release_table(table);
+
+ ast_str_append(&sql, 0, " %s", where->str);
+
+ ast_debug(1, "PostgreSQL RealTime: Update SQL: %s\n", sql->str);
+
+ /* We now have our complete statement; connect to the server and execute it. */
+ ast_mutex_lock(&pgsql_lock);
+ if (!pgsql_reconnect(database)) {
+ ast_mutex_unlock(&pgsql_lock);
+ return -1;
+ }
+
+ if (!(result = PQexec(pgsqlConn, sql->str))) {
+ ast_log(LOG_WARNING,
+ "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str);
+ ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
+ ast_mutex_unlock(&pgsql_lock);
+ return -1;
+ } else {
+ ExecStatusType result_status = PQresultStatus(result);
+ if (result_status != PGRES_COMMAND_OK
+ && result_status != PGRES_TUPLES_OK
+ && result_status != PGRES_NONFATAL_ERROR) {
+ ast_log(LOG_WARNING,
+ "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str);
+ ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n",
+ PQresultErrorMessage(result), PQresStatus(result_status));
+ ast_mutex_unlock(&pgsql_lock);
+ return -1;
+ }
+ }
+
+ numrows = atoi(PQcmdTuples(result));
+ ast_mutex_unlock(&pgsql_lock);
+
+ ast_debug(1, "PostgreSQL RealTime: Updated %d rows on table: %s\n", numrows, tablename);
+
+ /* From http://dev.pgsql.com/doc/pgsql/en/pgsql-affected-rows.html
+ * An integer greater than zero indicates the number of rows affected
+ * Zero indicates that no records were updated
+ * -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.)
+ */
+
+ if (numrows >= 0) {
+ return (int) numrows;
+ }
+
+ return -1;
+}
static int store_pgsql(const char *database, const char *table, va_list ap)
{
PGresult *result = NULL;
Oid insertid;
- struct ast_str *buf = ast_str_create(256);
- struct ast_str *sql1 = ast_str_create(256);
- struct ast_str *sql2 = ast_str_create(256);
+ struct ast_str *buf = ast_str_thread_get(&escapebuf_buf, 256);
+ struct ast_str *sql1 = ast_str_thread_get(&sql_buf, 256);
+ struct ast_str *sql2 = ast_str_thread_get(&where_buf, 256);
int pgresult;
const char *newparam, *newval;
@@ -710,9 +844,6 @@ static int store_pgsql(const char *database, const char *table, va_list ap)
ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql1->str);
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
ast_mutex_unlock(&pgsql_lock);
- ast_free(sql1);
- ast_free(sql2);
- ast_free(buf);
return -1;
} else {
ExecStatusType result_status = PQresultStatus(result);
@@ -725,18 +856,12 @@ static int store_pgsql(const char *database, const char *table, va_list ap)
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n",
PQresultErrorMessage(result), PQresStatus(result_status));
ast_mutex_unlock(&pgsql_lock);
- ast_free(sql1);
- ast_free(sql2);
- ast_free(buf);
return -1;
}
}
insertid = PQoidValue(result);
ast_mutex_unlock(&pgsql_lock);
- ast_free(sql1);
- ast_free(sql2);
- ast_free(buf);
ast_debug(1, "PostgreSQL RealTime: row inserted on table: %s, id: %u\n", table, insertid);
@@ -757,8 +882,8 @@ static int destroy_pgsql(const char *database, const char *table, const char *ke
PGresult *result = NULL;
int numrows = 0;
int pgresult;
- struct ast_str *sql = ast_str_create(256);
- struct ast_str *buf1 = ast_str_create(60), *buf2 = ast_str_create(60);
+ struct ast_str *sql = ast_str_thread_get(&sql_buf, 256);
+ struct ast_str *buf1 = ast_str_thread_get(&where_buf, 60), *buf2 = ast_str_thread_get(&escapebuf_buf, 60);
const char *newparam, *newval;
if (!table) {
@@ -810,9 +935,6 @@ static int destroy_pgsql(const char *database, const char *table, const char *ke
ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str);
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
ast_mutex_unlock(&pgsql_lock);
- ast_free(buf1);
- ast_free(buf2);
- ast_free(sql);
return -1;
} else {
ExecStatusType result_status = PQresultStatus(result);
@@ -825,18 +947,12 @@ static int destroy_pgsql(const char *database, const char *table, const char *ke
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n",
PQresultErrorMessage(result), PQresStatus(result_status));
ast_mutex_unlock(&pgsql_lock);
- ast_free(buf1);
- ast_free(buf2);
- ast_free(sql);
return -1;
}
}
numrows = atoi(PQcmdTuples(result));
ast_mutex_unlock(&pgsql_lock);
- ast_free(buf1);
- ast_free(buf2);
- ast_free(sql);
ast_debug(1, "PostgreSQL RealTime: Deleted %d rows on table: %s\n", numrows, table);
@@ -861,9 +977,7 @@ static struct ast_config *config_pgsql(const char *database, const char *table,
long num_rows;
struct ast_variable *new_v;
struct ast_category *cur_cat = NULL;
- char sqlbuf[1024] = "";
- char *sql = sqlbuf;
- size_t sqlleft = sizeof(sqlbuf);
+ struct ast_str *sql = ast_str_thread_get(&sql_buf, 100);
char last[80] = "";
int last_cat_metric = 0;
@@ -874,11 +988,11 @@ static struct ast_config *config_pgsql(const char *database, const char *table,
return NULL;
}
- ast_build_string(&sql, &sqlleft, "SELECT category, var_name, var_val, cat_metric FROM %s ", table);
- ast_build_string(&sql, &sqlleft, "WHERE filename='%s' and commented=0", file);
- ast_build_string(&sql, &sqlleft, "ORDER BY cat_metric DESC, var_metric ASC, category, var_name ");
+ ast_str_set(&sql, 0, "SELECT category, var_name, var_val, cat_metric FROM %s "
+ "WHERE filename='%s' and commented=0"
+ "ORDER BY cat_metric DESC, var_metric ASC, category, var_name ", table, file);
- ast_debug(1, "PostgreSQL RealTime: Static SQL: %s\n", sqlbuf);
+ ast_debug(1, "PostgreSQL RealTime: Static SQL: %s\n", sql->str);
/* We now have our complete statement; Lets connect to the server and execute it. */
ast_mutex_lock(&pgsql_lock);
@@ -887,10 +1001,10 @@ static struct ast_config *config_pgsql(const char *database, const char *table,
return NULL;
}
- if (!(result = PQexec(pgsqlConn, sqlbuf))) {
+ if (!(result = PQexec(pgsqlConn, sql->str))) {
ast_log(LOG_WARNING,
- "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
- ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql);
+ "PostgreSQL RealTime: Failed to query '%s@%s'. Check debug for more info.\n", table, database);
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str);
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn));
ast_mutex_unlock(&pgsql_lock);
return NULL;
@@ -901,7 +1015,7 @@ static struct ast_config *config_pgsql(const char *database, const char *table,
&& result_status != PGRES_NONFATAL_ERROR) {
ast_log(LOG_WARNING,
"PostgreSQL RealTime: Failed to query database. Check debug for more info.\n");
- ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql);
+ ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str);
ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n",
PQresultErrorMessage(result), PQresStatus(result_status));
ast_mutex_unlock(&pgsql_lock);
@@ -1067,7 +1181,7 @@ static int require_pgsql(const char *database, const char *tablename, va_list ap
}
}
}
- ast_mutex_unlock(&table->lock);
+ release_table(table);
return res;
}
@@ -1101,6 +1215,7 @@ static struct ast_config_engine pgsql_engine = {
.store_func = store_pgsql,
.destroy_func = destroy_pgsql,
.update_func = update_pgsql,
+ .update2_func = update2_pgsql,
.require_func = require_pgsql,
.unload_func = unload_pgsql,
};
@@ -1353,7 +1468,7 @@ static char *handle_cli_realtime_pgsql_cache(struct ast_cli_entry *e, int cmd, s
AST_LIST_TRAVERSE(&cur->columns, col, list) {
ast_cli(a->fd, "%-20.20s %-20.20s %3d %-8.8s\n", col->name, col->type, col->len, col->notnull ? "NOT NULL" : "");
}
- ast_mutex_unlock(&cur->lock);
+ release_table(cur);
} else {
ast_cli(a->fd, "No such table '%s'\n", a->argv[4]);
}