diff options
author | tilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b> | 2009-10-06 19:34:48 +0000 |
---|---|---|
committer | tilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b> | 2009-10-06 19:34:48 +0000 |
commit | 044c9a62f408b242c8222c1300aa9fe2fb5104ce (patch) | |
tree | 426036085bfb17b935d18eff20d89138e16dc666 /res | |
parent | 5b0a9d55dd20c8213904febe8dead36cdc27a649 (diff) |
Recorded merge of revisions 222309 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk
........
r222309 | tilghman | 2009-10-06 14:31:39 -0500 (Tue, 06 Oct 2009) | 10 lines
Change schema query to involve the use of an optional schema parameter.
This change is done in such a way as to allow the driver to continue to
function with older databases which don't have these features.
(closes issue #16000)
Reported by: jamicque
Patches:
20091002__issue16000.diff.txt uploaded by tilghman (license 14)
20091002__issue16000__1.6.1.diff.txt uploaded by tilghman (license 14)
Tested by: jamicque
........
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.1@222310 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'res')
-rw-r--r-- | res/res_config_pgsql.c | 76 |
1 files changed, 69 insertions, 7 deletions
diff --git a/res/res_config_pgsql.c b/res/res_config_pgsql.c index faef10a12..4fa8f27ee 100644 --- a/res/res_config_pgsql.c +++ b/res/res_config_pgsql.c @@ -46,6 +46,8 @@ AST_MUTEX_DEFINE_STATIC(pgsql_lock); #define RES_CONFIG_PGSQL_CONF "res_pgsql.conf" PGconn *pgsqlConn = NULL; +static int version; +#define has_schema_support (version > 70300 ? 1 : 0) #define MAX_DB_OPTION_SIZE 64 @@ -99,7 +101,7 @@ static void destroy_table(struct tables *table) ast_free(table); } -static struct tables *find_table(const char *tablename) +static struct tables *find_table(const char *orig_tablename) { struct columns *column; struct tables *table; @@ -111,7 +113,7 @@ static struct tables *find_table(const char *tablename) AST_LIST_LOCK(&psql_tables); AST_LIST_TRAVERSE(&psql_tables, table, list) { - if (!strcasecmp(table->name, tablename)) { + if (!strcasecmp(table->name, orig_tablename)) { ast_debug(1, "Found table in cache; now locking\n"); ast_mutex_lock(&table->lock); ast_debug(1, "Lock cached table; now returning\n"); @@ -120,10 +122,69 @@ static struct tables *find_table(const char *tablename) } } - ast_debug(1, "Table '%s' not found in cache, querying now\n", tablename); + ast_debug(1, "Table '%s' not found in cache, querying now\n", orig_tablename); /* Not found, scan the table */ - ast_str_set(&sql, 0, "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); + if (has_schema_support) { + char *schemaname, *tablename; + if (strchr(orig_tablename, '.')) { + schemaname = ast_strdupa(orig_tablename); + tablename = strchr(schemaname, '.'); + *tablename++ = '\0'; + } else { + schemaname = ""; + tablename = ast_strdupa(orig_tablename); + } + + /* Escape special characters in schemaname */ + if (strchr(schemaname, '\\') || strchr(schemaname, '\'')) { + char *tmp = schemaname, *ptr; + + ptr = schemaname = alloca(strlen(tmp) * 2 + 1); + for (; *tmp; tmp++) { + if (strchr("\\'", *tmp)) { + *ptr++ = *tmp; + } + *ptr++ = *tmp; + } + *ptr = '\0'; + } + /* Escape special characters in tablename */ + if (strchr(tablename, '\\') || strchr(tablename, '\'')) { + char *tmp = tablename, *ptr; + + ptr = tablename = alloca(strlen(tmp) * 2 + 1); + for (; *tmp; tmp++) { + if (strchr("\\'", *tmp)) { + *ptr++ = *tmp; + } + *ptr++ = *tmp; + } + *ptr = '\0'; + } + + ast_str_set(&sql, 0, "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, + ast_strlen_zero(schemaname) ? "" : "'", ast_strlen_zero(schemaname) ? "current_schema()" : schemaname, ast_strlen_zero(schemaname) ? "" : "'"); + } else { + /* Escape special characters in tablename */ + if (strchr(orig_tablename, '\\') || strchr(orig_tablename, '\'')) { + const char *tmp = orig_tablename; + char *ptr; + + orig_tablename = ptr = alloca(strlen(tmp) * 2 + 1); + for (; *tmp; tmp++) { + if (strchr("\\'", *tmp)) { + *ptr++ = *tmp; + } + *ptr++ = *tmp; + } + *ptr = '\0'; + } + + ast_str_set(&sql, 0, "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", orig_tablename); + } + result = PQexec(pgsqlConn, sql->str); ast_debug(1, "Query of table structure complete. Now retrieving results.\n"); if (PQresultStatus(result) != PGRES_TUPLES_OK) { @@ -134,12 +195,12 @@ static struct tables *find_table(const char *tablename) return NULL; } - if (!(table = ast_calloc(1, sizeof(*table) + strlen(tablename) + 1))) { + if (!(table = ast_calloc(1, sizeof(*table) + strlen(orig_tablename) + 1))) { ast_log(LOG_ERROR, "Unable to allocate memory for new table structure\n"); AST_LIST_UNLOCK(&psql_tables); return NULL; } - strcpy(table->name, tablename); /* SAFE */ + strcpy(table->name, orig_tablename); /* SAFE */ ast_mutex_init(&table->lock); AST_LIST_HEAD_INIT_NOLOCK(&table->columns); @@ -153,7 +214,7 @@ static struct tables *find_table(const char *tablename) ast_verb(4, "Found column '%s' of type '%s'\n", fname, ftype); if (!(column = ast_calloc(1, sizeof(*column) + strlen(fname) + strlen(ftype) + 2))) { - ast_log(LOG_ERROR, "Unable to allocate column element for %s, %s\n", tablename, fname); + ast_log(LOG_ERROR, "Unable to allocate column element for %s, %s\n", orig_tablename, fname); destroy_table(table); AST_LIST_UNLOCK(&psql_tables); return NULL; @@ -1292,6 +1353,7 @@ static int pgsql_reconnect(const char *database) if (pgsqlConn && PQstatus(pgsqlConn) == CONNECTION_OK) { ast_debug(1, "PostgreSQL RealTime: Successfully connected to database.\n"); connect_time = time(NULL); + version = PQserverVersion(pgsqlConn); return 1; } else { ast_log(LOG_ERROR, |