Support schema selection in cdr_adaptive_odbc

Asterisk now supports using ODBC with databases where a single schema must be
selected.  Previously, INSERTs would fail because they did not take into
account extra fields cause by having multiple schemas.  This also corrects
some SQL resource leaks.

(closes issue ASTERISK-17106)
Patch-by: Alexander Frolkin
Patch-by: Tilgnman Lesher


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@353964 65c4cc65-6c06-0410-ace0-fbb531ad65f3
certified/11.2
Kinsey Moore 14 years ago
parent 79979313e8
commit 71a8457d53

@ -35,6 +35,10 @@ func_enum:
differentiate between a failed query and a successful query with 0 results differentiate between a failed query and a successful query with 0 results
matching the specified type. matching the specified type.
CDR:
- cdr_adaptive_odbc now supports specifying a schema so that Asterisk can
connect to databases that use schemas.
Configuration Files: Configuration Files:
- Files listed below have been updated to be more consistent with how Asterisk - Files listed below have been updated to be more consistent with how Asterisk
parses configuration files. This makes configuration files more consistent parses configuration files. This makes configuration files more consistent

@ -72,6 +72,7 @@ struct columns {
struct tables { struct tables {
char *connection; char *connection;
char *table; char *table;
char *schema;
unsigned int usegmtime:1; unsigned int usegmtime:1;
AST_LIST_HEAD_NOLOCK(odbc_columns, columns) columns; AST_LIST_HEAD_NOLOCK(odbc_columns, columns) columns;
AST_RWLIST_ENTRY(tables) list; AST_RWLIST_ENTRY(tables) list;
@ -90,7 +91,8 @@ static int load_config(void)
char columnname[80]; char columnname[80];
char connection[40]; char connection[40];
char table[40]; char table[40];
int lenconnection, lentable, usegmtime = 0; char schema[40];
int lenconnection, lentable, lenschema, usegmtime = 0;
SQLLEN sqlptr; SQLLEN sqlptr;
int res = 0; int res = 0;
SQLHSTMT stmt = NULL; SQLHSTMT stmt = NULL;
@ -132,6 +134,12 @@ static int load_config(void)
ast_copy_string(table, tmp, sizeof(table)); ast_copy_string(table, tmp, sizeof(table));
lentable = strlen(table); lentable = strlen(table);
if (ast_strlen_zero(tmp = ast_variable_retrieve(cfg, catg, "schema"))) {
tmp = "";
}
ast_copy_string(schema, tmp, sizeof(schema));
lenschema = strlen(schema);
res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt); res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Alloc Handle failed on connection '%s'!\n", connection); ast_log(LOG_WARNING, "SQL Alloc Handle failed on connection '%s'!\n", connection);
@ -139,16 +147,19 @@ static int load_config(void)
continue; continue;
} }
res = SQLColumns(stmt, NULL, 0, NULL, 0, (unsigned char *)table, SQL_NTS, (unsigned char *)"%", SQL_NTS); res = SQLColumns(stmt, NULL, 0, lenschema == 0 ? NULL : (unsigned char *)schema, SQL_NTS, (unsigned char *)table, SQL_NTS, (unsigned char *)"%", SQL_NTS);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_ERROR, "Unable to query database columns on connection '%s'. Skipping.\n", connection); ast_log(LOG_ERROR, "Unable to query database columns on connection '%s'. Skipping.\n", connection);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
ast_odbc_release_obj(obj); ast_odbc_release_obj(obj);
continue; continue;
} }
tableptr = ast_calloc(sizeof(char), sizeof(*tableptr) + lenconnection + 1 + lentable + 1); tableptr = ast_calloc(sizeof(char), sizeof(*tableptr) + lenconnection + 1 + lentable + 1 + lenschema + 1);
if (!tableptr) { if (!tableptr) {
ast_log(LOG_ERROR, "Out of memory creating entry for table '%s' on connection '%s'\n", table, connection); ast_log(LOG_ERROR, "Out of memory creating entry for table '%s' on connection '%s'%s%s%s\n", table, connection,
lenschema ? " (schema '" : "", lenschema ? schema : "", lenschema ? "')" : "");
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
ast_odbc_release_obj(obj); ast_odbc_release_obj(obj);
res = -1; res = -1;
break; break;
@ -157,8 +168,10 @@ static int load_config(void)
tableptr->usegmtime = usegmtime; tableptr->usegmtime = usegmtime;
tableptr->connection = (char *)tableptr + sizeof(*tableptr); tableptr->connection = (char *)tableptr + sizeof(*tableptr);
tableptr->table = (char *)tableptr + sizeof(*tableptr) + lenconnection + 1; tableptr->table = (char *)tableptr + sizeof(*tableptr) + lenconnection + 1;
tableptr->schema = (char *)tableptr + sizeof(*tableptr) + lenconnection + 1 + lentable + 1;
ast_copy_string(tableptr->connection, connection, lenconnection + 1); ast_copy_string(tableptr->connection, connection, lenconnection + 1);
ast_copy_string(tableptr->table, table, lentable + 1); ast_copy_string(tableptr->table, table, lentable + 1);
ast_copy_string(tableptr->schema, schema, lenschema + 1);
ast_verb(3, "Found adaptive CDR table %s@%s.\n", tableptr->table, tableptr->connection); ast_verb(3, "Found adaptive CDR table %s@%s.\n", tableptr->table, tableptr->connection);
@ -228,6 +241,7 @@ static int load_config(void)
if (!entry) { if (!entry) {
ast_log(LOG_ERROR, "Out of memory creating entry for column '%s' in table '%s' on connection '%s'\n", columnname, table, connection); ast_log(LOG_ERROR, "Out of memory creating entry for column '%s' in table '%s' on connection '%s'\n", columnname, table, connection);
res = -1; res = -1;
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
break; break;
} }
entry->name = (char *)entry + sizeof(*entry); entry->name = (char *)entry + sizeof(*entry);
@ -376,7 +390,11 @@ static int odbc_log(struct ast_cdr *cdr)
AST_LIST_TRAVERSE(&odbc_tables, tableptr, list) { AST_LIST_TRAVERSE(&odbc_tables, tableptr, list) {
int first = 1; int first = 1;
ast_str_set(&sql, 0, "INSERT INTO %s (", tableptr->table); if (ast_strlen_zero(tableptr->schema)) {
ast_str_set(&sql, 0, "INSERT INTO %s (", tableptr->table);
} else {
ast_str_set(&sql, 0, "INSERT INTO %s.%s (", tableptr->schema, tableptr->table);
}
ast_str_set(&sql2, 0, " VALUES ("); ast_str_set(&sql2, 0, " VALUES (");
/* No need to check the connection now; we'll handle any failure in prepare_and_execute */ /* No need to check the connection now; we'll handle any failure in prepare_and_execute */

@ -28,6 +28,7 @@
;[third] ;[third]
;connection=sqlserver ;connection=sqlserver
;table=AsteriskCDR ;table=AsteriskCDR
;schema=public ; for databases which support schemas
;usegmtime=yes ; defaults to no ;usegmtime=yes ; defaults to no
;alias src => source ;alias src => source
;alias channel => source_channel ;alias channel => source_channel

Loading…
Cancel
Save