summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRodrigo Ramírez Norambuena <decipher.hk@gmail.com>2015-05-01 23:14:31 -0400
committerRodrigo Ramírez Norambuena <decipher.hk@gmail.com>2015-05-05 07:59:12 -0400
commitcb79b8ab8070b9ebd2c162128ed555f2d3c2f718 (patch)
tree3f61ad2d4664a696004bf388b6c0afd5c324ab62
parent32eb812b28ffc1745e08cb507d8c4409d3ed297a (diff)
cel_pgsql: Add support for setting schema
Add feature to set optional schema parameter on configuration file via 'schema' setting. Fix query to get columns from table while considering schema. If in the database there exists two tables with same name in distinct schemas it will return an error when inserting record. ASTERISK-24967 #close Change-Id: I691fd2cbc277fcba10e615f5884f8de5d8152f2c
-rw-r--r--CHANGES4
-rw-r--r--cel/cel_pgsql.c62
-rw-r--r--configs/samples/cel_pgsql.conf.sample2
3 files changed, 59 insertions, 9 deletions
diff --git a/CHANGES b/CHANGES
index 1753be663..8a9727a9d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -153,6 +153,10 @@ cel_pgsql
* Added a new option, 'usegmtime', which causes timestamps in CEL events
to be logged in GMT.
+ * Added support to set schema where located the table cel. This settings is
+ configurable for cel_pgsql via the 'schema' in configuration file
+ cel_pgsql.conf.
+
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 13.3.0 to Asterisk 13.4.0 ------------
------------------------------------------------------------------------------
diff --git a/cel/cel_pgsql.c b/cel/cel_pgsql.c
index 2d7f0dfb0..2bcee6ee1 100644
--- a/cel/cel_pgsql.c
+++ b/cel/cel_pgsql.c
@@ -60,6 +60,8 @@ ASTERISK_REGISTER_FILE()
#define PGSQL_BACKEND_NAME "CEL PGSQL backend"
+#define PGSQL_MIN_VERSION_SCHEMA 70300
+
static char *config = "cel_pgsql.conf";
static char *pghostname;
@@ -69,6 +71,7 @@ static char *pgpassword;
static char *pgappname;
static char *pgdbport;
static char *table;
+static char *schema;
static int connected = 0;
static int maxsize = 512, maxsize2 = 512;
@@ -418,6 +421,10 @@ static int my_unload_module(void)
ast_free(table);
table = NULL;
}
+ if (schema) {
+ ast_free(schema);
+ schema = NULL;
+ }
while ((current = AST_RWLIST_REMOVE_HEAD(&psql_columns, list))) {
ast_free(current);
}
@@ -521,6 +528,16 @@ static int process_my_load_module(struct ast_config *cfg)
} else {
usegmtime = 0;
}
+ if (!(tmp = ast_variable_retrieve(cfg, "global", "schema"))) {
+ tmp = "";
+ }
+ if (schema) {
+ ast_free(schema);
+ }
+ if (!(schema = ast_strdup(tmp))) {
+ ast_log(LOG_WARNING,"PostgreSQL Ran out of memory copying schema info\n");
+ return AST_MODULE_LOAD_DECLINE;
+ }
if (option_debug) {
if (ast_strlen_zero(pghostname)) {
ast_debug(3, "cel_pgsql: using default unix socket\n");
@@ -538,23 +555,50 @@ static int process_my_load_module(struct ast_config *cfg)
pgsql_reconnect();
if (PQstatus(conn) != CONNECTION_BAD) {
- char sqlcmd[512];
- char *fname, *ftype, *flen, *fnotnull, *fdef;
- char *tableptr;
- int i, rows;
+ char sqlcmd[768];
+ char *fname, *ftype, *flen, *fnotnull, *fdef, *tablename, *tmp_tablename;
+ int i, rows, version;
ast_debug(1, "Successfully connected to PostgreSQL database.\n");
connected = 1;
+ version = PQserverVersion(conn);
/* Remove any schema name from the table */
- if ((tableptr = strrchr(table, '.'))) {
- tableptr++;
+ if ((tmp_tablename = strrchr(table, '.'))) {
+ tmp_tablename++;
} else {
- tableptr = table;
+ tmp_tablename = table;
+ }
+ tablename = ast_alloca(strlen(tmp_tablename) * 2 + 1);
+ PQescapeStringConn(conn, tablename, tmp_tablename, strlen(tmp_tablename), NULL);
+ if (version >= PGSQL_MIN_VERSION_SCHEMA) {
+ char *schemaname;
+ int lenschema;
+ lenschema = strlen(schema);
+ schemaname = ast_alloca(lenschema * 2 + 1);
+ PQescapeStringConn(conn, schemaname, schema, lenschema, NULL);
+
+ snprintf(sqlcmd, sizeof(sqlcmd),
+ "SELECT a.attname, t.typname, a.attlen, a.attnotnull, d.adsrc, a.atttypmod "
+ "FROM (((pg_catalog.pg_class c INNER JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace "
+ "AND c.relname = '%s' AND n.nspname = %s%s%s) "
+ "INNER JOIN pg_catalog.pg_attribute a ON ("
+ "NOT a.attisdropped) AND a.attnum > 0 AND a.attrelid = c.oid) "
+ "INNER JOIN pg_catalog.pg_type t ON t.oid = a.atttypid) "
+ "LEFT OUTER JOIN pg_attrdef d ON a.atthasdef AND d.adrelid = a.attrelid "
+ "AND d.adnum = a.attnum "
+ "ORDER BY n.nspname, c.relname, attnum",
+ tablename,
+ lenschema == 0 ? "" : "'", lenschema == 0 ? "current_schema()" : schemaname, lenschema == 0 ? "" : "'");
+ } else {
+ snprintf(sqlcmd, sizeof(sqlcmd),
+ "SELECT a.attname, t.typname, a.attlen, a.attnotnull, d.adsrc, a.atttypmod "
+ "FROM pg_class c, pg_type t, pg_attribute a "
+ "LEFT OUTER JOIN pg_attrdef d ON a.atthasdef AND d.adrelid = a.attrelid "
+ "AND d.adnum = a.attnum WHERE c.oid = a.attrelid AND a.atttypid = t.oid "
+ "AND (a.attnum > 0) AND c.relname = '%s' ORDER BY c.relname, attnum", tablename);
}
-
/* Query the columns */
- snprintf(sqlcmd, sizeof(sqlcmd), "select a.attname, t.typname, a.attlen, a.attnotnull, d.adsrc from pg_class c, pg_type t, pg_attribute a left outer join pg_attrdef d on a.atthasdef and d.adrelid = a.attrelid and d.adnum = a.attnum where c.oid = a.attrelid and a.atttypid = t.oid and (a.attnum > 0) and c.relname = '%s' order by c.relname, attnum", tableptr);
result = PQexec(conn, sqlcmd);
if (PQresultStatus(result) != PGRES_TUPLES_OK) {
pgerror = PQresultErrorMessage(result);
diff --git a/configs/samples/cel_pgsql.conf.sample b/configs/samples/cel_pgsql.conf.sample
index 30c789e4c..13fe06926 100644
--- a/configs/samples/cel_pgsql.conf.sample
+++ b/configs/samples/cel_pgsql.conf.sample
@@ -68,4 +68,6 @@
;password=password
;user=postgres
;table=cel ;SQL table where CEL's will be inserted
+;schema=public ;Schema where CEL's table is located. Optional parameter.
+ ;If schema support is present the default value used will be current_schema().
;appname=asterisk ; Postgres application_name support (optional). Whitespace not allowed.