diff --git a/CHANGES b/CHANGES index 1609e506e6..26bcb49900 100644 --- a/CHANGES +++ b/CHANGES @@ -159,6 +159,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 2d7f0dfb04..2bcee6ee12 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 30c789e4cc..13fe069261 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.