2004-06-11 00:12:35 +00:00
/*
2005-09-14 20:46:50 +00:00
* Asterisk - - An open source telephony toolkit .
2004-06-11 00:12:35 +00:00
*
2005-01-21 07:06:25 +00:00
* Copyright ( C ) 1999 - 2005 , Digium , Inc .
2004-06-11 00:12:35 +00:00
*
2004-10-05 06:46:11 +00:00
* Mark Spencer < markster @ digium . com >
2004-06-11 00:12:35 +00:00
*
2005-01-21 07:06:25 +00:00
* Copyright ( C ) 2004 - 2005 Anthony Minessale II < anthmct @ yahoo . com >
2005-09-14 20:46:50 +00:00
*
* See http : //www.asterisk.org for more information about
* the Asterisk project . Please do not directly contact
* any of the maintainers of this project for assistance ;
* the project provides a web site , mailing lists and IRC
* channels for your use .
*
* This program is free software , distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree .
*/
2005-10-24 20:12:06 +00:00
/*! \file
2005-09-14 20:46:50 +00:00
*
2005-10-24 20:12:06 +00:00
* \ brief odbc + odbc plugin for portable configuration engine
2005-09-14 20:46:50 +00:00
*
2005-12-30 21:18:06 +00:00
* \ author Mark Spencer < markster @ digium . com >
* \ author Anthony Minessale II < anthmct @ yahoo . com >
*
* \ arg http : //www.unixodbc.org
2004-06-11 00:12:35 +00:00
*/
2005-11-08 19:47:56 +00:00
# include <stdio.h>
2005-06-06 22:12:19 +00:00
# include <stdlib.h>
# include <unistd.h>
# include <string.h>
# include "asterisk.h"
ASTERISK_FILE_VERSION ( __FILE__ , " $Revision$ " )
2005-04-21 06:02:45 +00:00
# include "asterisk/file.h"
# include "asterisk/logger.h"
# include "asterisk/channel.h"
# include "asterisk/pbx.h"
# include "asterisk/config.h"
# include "asterisk/module.h"
# include "asterisk/lock.h"
# include "asterisk/options.h"
# include "asterisk/res_odbc.h"
# include "asterisk/utils.h"
2004-06-11 00:12:35 +00:00
LOCAL_USER_DECL ;
2004-10-07 19:57:50 +00:00
static struct ast_variable * realtime_odbc ( const char * database , const char * table , va_list ap )
2004-07-08 20:16:28 +00:00
{
2006-04-18 18:16:32 +00:00
struct odbc_obj * obj ;
2004-10-05 06:46:11 +00:00
SQLHSTMT stmt ;
2004-11-22 05:03:03 +00:00
char sql [ 1024 ] ;
2004-10-05 06:46:11 +00:00
char coltitle [ 256 ] ;
char rowdata [ 2048 ] ;
2004-11-22 05:03:03 +00:00
char * op ;
2004-10-07 19:57:50 +00:00
const char * newparam , * newval ;
2004-10-05 06:46:11 +00:00
char * stringp ;
char * chunk ;
SQLSMALLINT collen ;
int res ;
int x ;
struct ast_variable * var = NULL , * prev = NULL ;
SQLULEN colsize ;
SQLSMALLINT colcount = 0 ;
SQLSMALLINT datatype ;
SQLSMALLINT decimaldigits ;
SQLSMALLINT nullable ;
2005-04-22 01:59:53 +00:00
SQLINTEGER indicator ;
2004-10-07 19:57:50 +00:00
va_list aq ;
va_copy ( aq , ap ) ;
2004-10-05 06:46:11 +00:00
if ( ! table )
return NULL ;
2006-04-18 18:16:32 +00:00
obj = odbc_request_obj ( database , 0 ) ;
2004-10-05 06:46:11 +00:00
if ( ! obj )
return NULL ;
res = SQLAllocHandle ( SQL_HANDLE_STMT , obj - > con , & stmt ) ;
if ( ( res ! = SQL_SUCCESS ) & & ( res ! = SQL_SUCCESS_WITH_INFO ) ) {
ast_log ( LOG_WARNING , " SQL Alloc Handle failed! \n " ) ;
2006-04-18 18:16:32 +00:00
odbc_release_obj ( obj ) ;
2004-10-05 06:46:11 +00:00
return NULL ;
}
2004-10-07 19:57:50 +00:00
newparam = va_arg ( aq , const char * ) ;
if ( ! newparam ) {
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
2006-04-18 18:16:32 +00:00
odbc_release_obj ( obj ) ;
2004-10-07 19:57:50 +00:00
return NULL ;
}
newval = va_arg ( aq , const char * ) ;
2004-11-22 18:39:40 +00:00
if ( ! strchr ( newparam , ' ' ) ) op = " = " ; else op = " " ;
snprintf ( sql , sizeof ( sql ) , " SELECT * FROM %s WHERE %s%s ? " , table , newparam , op ) ;
2004-10-07 19:57:50 +00:00
while ( ( newparam = va_arg ( aq , const char * ) ) ) {
2004-11-22 18:39:40 +00:00
if ( ! strchr ( newparam , ' ' ) ) op = " = " ; else op = " " ;
snprintf ( sql + strlen ( sql ) , sizeof ( sql ) - strlen ( sql ) , " AND %s%s ? " , newparam , op ) ;
2004-10-07 19:57:50 +00:00
newval = va_arg ( aq , const char * ) ;
}
va_end ( aq ) ;
2006-03-01 17:53:05 +00:00
res = SQLPrepare ( stmt , ( unsigned char * ) sql , SQL_NTS ) ;
2004-10-05 06:46:11 +00:00
if ( ( res ! = SQL_SUCCESS ) & & ( res ! = SQL_SUCCESS_WITH_INFO ) ) {
ast_log ( LOG_WARNING , " SQL Prepare failed![%s] \n " , sql ) ;
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
2006-04-18 18:16:32 +00:00
odbc_release_obj ( obj ) ;
2004-10-05 06:46:11 +00:00
return NULL ;
}
2004-10-07 19:57:50 +00:00
/* Now bind the parameters */
x = 1 ;
2004-10-05 06:46:11 +00:00
2004-10-07 19:57:50 +00:00
while ( ( newparam = va_arg ( ap , const char * ) ) ) {
newval = va_arg ( ap , const char * ) ;
SQLBindParameter ( stmt , x + + , SQL_PARAM_INPUT , SQL_C_CHAR , SQL_CHAR , strlen ( newval ) , 0 , ( void * ) newval , 0 , NULL ) ;
}
2005-02-17 16:31:08 +00:00
res = odbc_smart_execute ( obj , stmt ) ;
2004-10-05 06:46:11 +00:00
if ( ( res ! = SQL_SUCCESS ) & & ( res ! = SQL_SUCCESS_WITH_INFO ) ) {
ast_log ( LOG_WARNING , " SQL Execute error! \n [%s] \n \n " , sql ) ;
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
2006-04-18 18:16:32 +00:00
odbc_release_obj ( obj ) ;
2004-10-05 06:46:11 +00:00
return NULL ;
}
2005-10-31 21:31:25 +00:00
res = SQLNumResultCols ( stmt , & colcount ) ;
2004-10-05 06:46:11 +00:00
if ( ( res ! = SQL_SUCCESS ) & & ( res ! = SQL_SUCCESS_WITH_INFO ) ) {
2005-10-31 21:31:25 +00:00
ast_log ( LOG_WARNING , " SQL Column Count error! \n [%s] \n \n " , sql ) ;
2004-10-05 06:46:11 +00:00
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
2006-04-18 18:16:32 +00:00
odbc_release_obj ( obj ) ;
2004-10-05 06:46:11 +00:00
return NULL ;
}
2005-10-31 21:31:25 +00:00
res = SQLFetch ( stmt ) ;
if ( res = = SQL_NO_DATA ) {
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
2006-04-18 18:16:32 +00:00
odbc_release_obj ( obj ) ;
2005-10-31 21:31:25 +00:00
return NULL ;
}
2004-10-05 06:46:11 +00:00
if ( ( res ! = SQL_SUCCESS ) & & ( res ! = SQL_SUCCESS_WITH_INFO ) ) {
2005-10-31 21:31:25 +00:00
ast_log ( LOG_WARNING , " SQL Fetch error! \n [%s] \n \n " , sql ) ;
2004-10-05 06:46:11 +00:00
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
2006-04-18 18:16:32 +00:00
odbc_release_obj ( obj ) ;
2004-10-05 06:46:11 +00:00
return NULL ;
}
2006-04-18 18:16:32 +00:00
for ( x = 0 ; x < colcount ; x + + ) {
2005-10-31 21:31:25 +00:00
rowdata [ 0 ] = ' \0 ' ;
collen = sizeof ( coltitle ) ;
2006-03-01 17:53:05 +00:00
res = SQLDescribeCol ( stmt , x + 1 , ( unsigned char * ) coltitle , sizeof ( coltitle ) , & collen ,
2005-10-31 21:31:25 +00:00
& datatype , & colsize , & decimaldigits , & nullable ) ;
2004-10-05 06:46:11 +00:00
if ( ( res ! = SQL_SUCCESS ) & & ( res ! = SQL_SUCCESS_WITH_INFO ) ) {
2005-10-31 21:31:25 +00:00
ast_log ( LOG_WARNING , " SQL Describe Column error! \n [%s] \n \n " , sql ) ;
if ( var )
ast_variables_destroy ( var ) ;
2006-04-18 18:16:32 +00:00
odbc_release_obj ( obj ) ;
2004-10-05 06:46:11 +00:00
return NULL ;
}
2005-04-22 01:59:53 +00:00
2005-10-31 21:31:25 +00:00
indicator = 0 ;
res = SQLGetData ( stmt , x + 1 , SQL_CHAR , rowdata , sizeof ( rowdata ) , & indicator ) ;
if ( indicator = = SQL_NULL_DATA )
continue ;
2005-04-22 01:59:53 +00:00
2005-10-31 21:31:25 +00:00
if ( ( res ! = SQL_SUCCESS ) & & ( res ! = SQL_SUCCESS_WITH_INFO ) ) {
ast_log ( LOG_WARNING , " SQL Get Data error! \n [%s] \n \n " , sql ) ;
if ( var )
ast_variables_destroy ( var ) ;
2006-04-18 18:16:32 +00:00
odbc_release_obj ( obj ) ;
2005-10-31 21:31:25 +00:00
return NULL ;
}
stringp = rowdata ;
while ( stringp ) {
chunk = strsep ( & stringp , " ; " ) ;
2005-11-08 01:55:31 +00:00
if ( ! ast_strlen_zero ( ast_strip ( chunk ) ) ) {
2005-10-31 21:31:25 +00:00
if ( prev ) {
prev - > next = ast_variable_new ( coltitle , chunk ) ;
if ( prev - > next )
prev = prev - > next ;
2004-10-05 06:46:11 +00:00
} else
2005-01-25 06:10:20 +00:00
prev = var = ast_variable_new ( coltitle , chunk ) ;
2004-10-05 06:46:11 +00:00
}
}
}
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
2006-04-18 18:16:32 +00:00
odbc_release_obj ( obj ) ;
2004-10-05 06:46:11 +00:00
return var ;
}
2004-11-23 17:58:59 +00:00
static struct ast_config * realtime_multi_odbc ( const char * database , const char * table , va_list ap )
{
2006-04-18 18:16:32 +00:00
struct odbc_obj * obj ;
2004-11-23 17:58:59 +00:00
SQLHSTMT stmt ;
char sql [ 1024 ] ;
char coltitle [ 256 ] ;
char rowdata [ 2048 ] ;
2004-11-24 03:07:08 +00:00
const char * initfield = NULL ;
2004-11-23 17:58:59 +00:00
char * op ;
const char * newparam , * newval ;
char * stringp ;
char * chunk ;
SQLSMALLINT collen ;
int res ;
int x ;
2005-01-25 06:10:20 +00:00
struct ast_variable * var = NULL ;
2004-11-23 17:58:59 +00:00
struct ast_config * cfg = NULL ;
struct ast_category * cat = NULL ;
2005-01-20 04:53:17 +00:00
struct ast_realloca ra ;
2004-11-23 17:58:59 +00:00
SQLULEN colsize ;
SQLSMALLINT colcount = 0 ;
SQLSMALLINT datatype ;
SQLSMALLINT decimaldigits ;
SQLSMALLINT nullable ;
2005-04-22 01:59:53 +00:00
SQLINTEGER indicator ;
2005-01-20 04:53:17 +00:00
2004-11-23 17:58:59 +00:00
va_list aq ;
va_copy ( aq , ap ) ;
if ( ! table )
return NULL ;
2005-01-20 04:53:17 +00:00
memset ( & ra , 0 , sizeof ( ra ) ) ;
2004-11-23 17:58:59 +00:00
2006-04-18 18:16:32 +00:00
obj = odbc_request_obj ( database , 0 ) ;
2004-11-23 17:58:59 +00:00
if ( ! obj )
return NULL ;
res = SQLAllocHandle ( SQL_HANDLE_STMT , obj - > con , & stmt ) ;
if ( ( res ! = SQL_SUCCESS ) & & ( res ! = SQL_SUCCESS_WITH_INFO ) ) {
ast_log ( LOG_WARNING , " SQL Alloc Handle failed! \n " ) ;
2006-04-18 18:16:32 +00:00
odbc_release_obj ( obj ) ;
2004-11-23 17:58:59 +00:00
return NULL ;
}
newparam = va_arg ( aq , const char * ) ;
if ( ! newparam ) {
2006-04-18 18:16:32 +00:00
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
odbc_release_obj ( obj ) ;
2004-11-23 17:58:59 +00:00
return NULL ;
}
2004-11-24 03:07:08 +00:00
initfield = ast_strdupa ( newparam ) ;
if ( initfield & & ( op = strchr ( initfield , ' ' ) ) )
* op = ' \0 ' ;
2004-11-23 17:58:59 +00:00
newval = va_arg ( aq , const char * ) ;
if ( ! strchr ( newparam , ' ' ) ) op = " = " ; else op = " " ;
snprintf ( sql , sizeof ( sql ) , " SELECT * FROM %s WHERE %s%s ? " , table , newparam , op ) ;
while ( ( newparam = va_arg ( aq , const char * ) ) ) {
if ( ! strchr ( newparam , ' ' ) ) op = " = " ; else op = " " ;
snprintf ( sql + strlen ( sql ) , sizeof ( sql ) - strlen ( sql ) , " AND %s%s ? " , newparam , op ) ;
newval = va_arg ( aq , const char * ) ;
}
2004-11-24 03:07:08 +00:00
if ( initfield )
snprintf ( sql + strlen ( sql ) , sizeof ( sql ) - strlen ( sql ) , " ORDER BY %s " , initfield ) ;
2004-11-23 17:58:59 +00:00
va_end ( aq ) ;
2006-03-01 17:53:05 +00:00
res = SQLPrepare ( stmt , ( unsigned char * ) sql , SQL_NTS ) ;
2004-11-23 17:58:59 +00:00
if ( ( res ! = SQL_SUCCESS ) & & ( res ! = SQL_SUCCESS_WITH_INFO ) ) {
ast_log ( LOG_WARNING , " SQL Prepare failed![%s] \n " , sql ) ;
2006-04-18 18:16:32 +00:00
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
odbc_release_obj ( obj ) ;
2004-11-23 17:58:59 +00:00
return NULL ;
}
/* Now bind the parameters */
x = 1 ;
while ( ( newparam = va_arg ( ap , const char * ) ) ) {
newval = va_arg ( ap , const char * ) ;
SQLBindParameter ( stmt , x + + , SQL_PARAM_INPUT , SQL_C_CHAR , SQL_CHAR , strlen ( newval ) , 0 , ( void * ) newval , 0 , NULL ) ;
}
2005-02-17 16:31:08 +00:00
res = odbc_smart_execute ( obj , stmt ) ;
2004-11-23 17:58:59 +00:00
if ( ( res ! = SQL_SUCCESS ) & & ( res ! = SQL_SUCCESS_WITH_INFO ) ) {
ast_log ( LOG_WARNING , " SQL Execute error! \n [%s] \n \n " , sql ) ;
2006-04-18 18:16:32 +00:00
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
odbc_release_obj ( obj ) ;
2004-11-23 17:58:59 +00:00
return NULL ;
}
res = SQLNumResultCols ( stmt , & colcount ) ;
if ( ( res ! = SQL_SUCCESS ) & & ( res ! = SQL_SUCCESS_WITH_INFO ) ) {
ast_log ( LOG_WARNING , " SQL Column Count error! \n [%s] \n \n " , sql ) ;
2006-04-18 18:16:32 +00:00
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
odbc_release_obj ( obj ) ;
2004-11-23 17:58:59 +00:00
return NULL ;
}
2005-01-25 06:10:20 +00:00
cfg = ast_config_new ( ) ;
if ( ! cfg ) {
ast_log ( LOG_WARNING , " Out of memory! \n " ) ;
2006-04-18 18:16:32 +00:00
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
odbc_release_obj ( obj ) ;
2005-01-25 06:10:20 +00:00
return NULL ;
}
2005-10-31 21:31:25 +00:00
while ( ( res = SQLFetch ( stmt ) ) ! = SQL_NO_DATA ) {
2004-11-23 17:58:59 +00:00
var = NULL ;
if ( ( res ! = SQL_SUCCESS ) & & ( res ! = SQL_SUCCESS_WITH_INFO ) ) {
ast_log ( LOG_WARNING , " SQL Fetch error! \n [%s] \n \n " , sql ) ;
continue ;
}
2005-01-25 06:10:20 +00:00
cat = ast_category_new ( " " ) ;
if ( ! cat ) {
ast_log ( LOG_WARNING , " Out of memory! \n " ) ;
continue ;
}
2004-11-23 17:58:59 +00:00
for ( x = 0 ; x < colcount ; x + + ) {
rowdata [ 0 ] = ' \0 ' ;
collen = sizeof ( coltitle ) ;
2006-03-01 17:53:05 +00:00
res = SQLDescribeCol ( stmt , x + 1 , ( unsigned char * ) coltitle , sizeof ( coltitle ) , & collen ,
2004-11-23 17:58:59 +00:00
& datatype , & colsize , & decimaldigits , & nullable ) ;
if ( ( res ! = SQL_SUCCESS ) & & ( res ! = SQL_SUCCESS_WITH_INFO ) ) {
ast_log ( LOG_WARNING , " SQL Describe Column error! \n [%s] \n \n " , sql ) ;
2005-01-25 06:10:20 +00:00
ast_category_destroy ( cat ) ;
2004-11-23 17:58:59 +00:00
continue ;
}
2005-04-22 01:59:53 +00:00
indicator = 0 ;
res = SQLGetData ( stmt , x + 1 , SQL_CHAR , rowdata , sizeof ( rowdata ) , & indicator ) ;
if ( indicator = = SQL_NULL_DATA )
continue ;
2004-11-23 17:58:59 +00:00
if ( ( res ! = SQL_SUCCESS ) & & ( res ! = SQL_SUCCESS_WITH_INFO ) ) {
ast_log ( LOG_WARNING , " SQL Get Data error! \n [%s] \n \n " , sql ) ;
2005-01-25 06:10:20 +00:00
ast_category_destroy ( cat ) ;
2004-11-23 17:58:59 +00:00
continue ;
}
stringp = rowdata ;
while ( stringp ) {
chunk = strsep ( & stringp , " ; " ) ;
2005-11-08 01:55:31 +00:00
if ( ! ast_strlen_zero ( ast_strip ( chunk ) ) ) {
2005-01-25 06:10:20 +00:00
if ( initfield & & ! strcmp ( initfield , coltitle ) )
ast_category_rename ( cat , chunk ) ;
var = ast_variable_new ( coltitle , chunk ) ;
ast_variable_append ( cat , var ) ;
2004-11-23 17:58:59 +00:00
}
}
2004-11-24 03:07:08 +00:00
}
2005-01-25 06:10:20 +00:00
ast_category_append ( cfg , cat ) ;
2004-11-23 17:58:59 +00:00
}
2006-04-18 18:16:32 +00:00
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
odbc_release_obj ( obj ) ;
2004-11-23 17:58:59 +00:00
return cfg ;
}
2004-10-05 06:46:11 +00:00
static int update_odbc ( const char * database , const char * table , const char * keyfield , const char * lookup , va_list ap )
{
2006-04-18 18:16:32 +00:00
struct odbc_obj * obj ;
2004-10-05 06:46:11 +00:00
SQLHSTMT stmt ;
char sql [ 256 ] ;
SQLLEN rowcount = 0 ;
const char * newparam , * newval ;
int res ;
int x ;
va_list aq ;
va_copy ( aq , ap ) ;
if ( ! table )
return - 1 ;
2006-04-18 18:16:32 +00:00
obj = odbc_request_obj ( database , 0 ) ;
2004-10-05 06:46:11 +00:00
if ( ! obj )
return - 1 ;
res = SQLAllocHandle ( SQL_HANDLE_STMT , obj - > con , & stmt ) ;
if ( ( res ! = SQL_SUCCESS ) & & ( res ! = SQL_SUCCESS_WITH_INFO ) ) {
ast_log ( LOG_WARNING , " SQL Alloc Handle failed! \n " ) ;
2006-04-18 18:16:32 +00:00
odbc_release_obj ( obj ) ;
2004-10-05 06:46:11 +00:00
return - 1 ;
}
newparam = va_arg ( aq , const char * ) ;
if ( ! newparam ) {
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
2006-04-18 18:16:32 +00:00
odbc_release_obj ( obj ) ;
2004-10-05 06:46:11 +00:00
return - 1 ;
}
newval = va_arg ( aq , const char * ) ;
snprintf ( sql , sizeof ( sql ) , " UPDATE %s SET %s=? " , table , newparam ) ;
while ( ( newparam = va_arg ( aq , const char * ) ) ) {
snprintf ( sql + strlen ( sql ) , sizeof ( sql ) - strlen ( sql ) , " , %s=? " , newparam ) ;
newval = va_arg ( aq , const char * ) ;
}
va_end ( aq ) ;
snprintf ( sql + strlen ( sql ) , sizeof ( sql ) - strlen ( sql ) , " WHERE %s=? " , keyfield ) ;
2006-03-01 17:53:05 +00:00
res = SQLPrepare ( stmt , ( unsigned char * ) sql , SQL_NTS ) ;
2004-10-05 06:46:11 +00:00
if ( ( res ! = SQL_SUCCESS ) & & ( res ! = SQL_SUCCESS_WITH_INFO ) ) {
ast_log ( LOG_WARNING , " SQL Prepare failed![%s] \n " , sql ) ;
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
2006-04-18 18:16:32 +00:00
odbc_release_obj ( obj ) ;
2004-10-05 06:46:11 +00:00
return - 1 ;
}
/* Now bind the parameters */
x = 1 ;
while ( ( newparam = va_arg ( ap , const char * ) ) ) {
newval = va_arg ( ap , const char * ) ;
SQLBindParameter ( stmt , x + + , SQL_PARAM_INPUT , SQL_C_CHAR , SQL_CHAR , strlen ( newval ) , 0 , ( void * ) newval , 0 , NULL ) ;
}
SQLBindParameter ( stmt , x + + , SQL_PARAM_INPUT , SQL_C_CHAR , SQL_CHAR , strlen ( lookup ) , 0 , ( void * ) lookup , 0 , NULL ) ;
2005-02-17 16:31:08 +00:00
res = odbc_smart_execute ( obj , stmt ) ;
2004-10-05 06:46:11 +00:00
if ( ( res ! = SQL_SUCCESS ) & & ( res ! = SQL_SUCCESS_WITH_INFO ) ) {
ast_log ( LOG_WARNING , " SQL Execute error! \n [%s] \n \n " , sql ) ;
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
2006-04-18 18:16:32 +00:00
odbc_release_obj ( obj ) ;
2004-10-05 06:46:11 +00:00
return - 1 ;
}
res = SQLRowCount ( stmt , & rowcount ) ;
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
2006-04-18 18:16:32 +00:00
odbc_release_obj ( obj ) ;
2004-10-05 06:46:11 +00:00
if ( ( res ! = SQL_SUCCESS ) & & ( res ! = SQL_SUCCESS_WITH_INFO ) ) {
ast_log ( LOG_WARNING , " SQL Row Count error! \n [%s] \n \n " , sql ) ;
return - 1 ;
}
2006-04-18 18:16:32 +00:00
if ( rowcount > = 0 )
return ( int ) rowcount ;
2005-04-22 03:29:03 +00:00
2004-10-05 06:46:11 +00:00
return - 1 ;
}
2006-04-18 18:16:32 +00:00
struct config_odbc_obj {
char * sql ;
unsigned long id ;
unsigned long cat_metric ;
unsigned long var_metric ;
unsigned long commented ;
char filename [ 128 ] ;
char category [ 128 ] ;
char var_name [ 128 ] ;
char var_val [ 128 ] ;
SQLINTEGER err ;
} ;
static SQLHSTMT config_odbc_prepare ( struct odbc_obj * obj , void * data )
{
struct config_odbc_obj * q = data ;
SQLHSTMT sth ;
int res ;
res = SQLAllocHandle ( SQL_HANDLE_STMT , obj - > con , & sth ) ;
if ( ( res ! = SQL_SUCCESS ) & & ( res ! = SQL_SUCCESS_WITH_INFO ) ) {
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " Failure in AllocStatement %d \n " , res ) ;
return NULL ;
}
res = SQLPrepare ( sth , ( unsigned char * ) q - > sql , SQL_NTS ) ;
if ( ( res ! = SQL_SUCCESS ) & & ( res ! = SQL_SUCCESS_WITH_INFO ) ) {
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " Error in PREPARE %d \n " , res ) ;
SQLFreeHandle ( SQL_HANDLE_STMT , sth ) ;
return NULL ;
}
SQLBindCol ( sth , 1 , SQL_C_ULONG , & q - > id , sizeof ( q - > id ) , & q - > err ) ;
SQLBindCol ( sth , 2 , SQL_C_ULONG , & q - > cat_metric , sizeof ( q - > cat_metric ) , & q - > err ) ;
SQLBindCol ( sth , 3 , SQL_C_ULONG , & q - > var_metric , sizeof ( q - > var_metric ) , & q - > err ) ;
SQLBindCol ( sth , 4 , SQL_C_ULONG , & q - > commented , sizeof ( q - > commented ) , & q - > err ) ;
SQLBindCol ( sth , 5 , SQL_C_CHAR , q - > filename , sizeof ( q - > filename ) , & q - > err ) ;
SQLBindCol ( sth , 6 , SQL_C_CHAR , q - > category , sizeof ( q - > category ) , & q - > err ) ;
SQLBindCol ( sth , 7 , SQL_C_CHAR , q - > var_name , sizeof ( q - > var_name ) , & q - > err ) ;
SQLBindCol ( sth , 8 , SQL_C_CHAR , q - > var_val , sizeof ( q - > var_val ) , & q - > err ) ;
return sth ;
}
2005-01-25 06:10:20 +00:00
static struct ast_config * config_odbc ( const char * database , const char * table , const char * file , struct ast_config * cfg )
2004-10-05 06:46:11 +00:00
{
2005-01-25 06:10:20 +00:00
struct ast_variable * new_v ;
struct ast_category * cur_cat ;
2004-10-05 06:46:11 +00:00
int res = 0 ;
2006-04-18 18:16:32 +00:00
struct odbc_obj * obj ;
char sql [ 255 ] = " " ;
unsigned int last_cat_metric = 0 ;
2004-07-13 22:53:17 +00:00
SQLSMALLINT rowcount = 0 ;
2004-07-08 20:16:28 +00:00
SQLHSTMT stmt ;
2005-01-25 06:10:20 +00:00
char last [ 128 ] = " " ;
2006-04-18 18:16:32 +00:00
struct config_odbc_obj q ;
memset ( & q , 0 , sizeof ( q ) ) ;
2004-07-08 20:16:28 +00:00
if ( ! file | | ! strcmp ( file , " res_config_odbc.conf " ) )
2004-12-18 22:04:07 +00:00
return NULL ; /* cant configure myself with myself ! */
2004-07-08 20:16:28 +00:00
2006-04-18 18:16:32 +00:00
obj = odbc_request_obj ( database , 0 ) ;
2004-07-08 20:16:28 +00:00
if ( ! obj )
return NULL ;
2004-10-05 06:46:11 +00:00
snprintf ( sql , sizeof ( sql ) , " SELECT * FROM %s WHERE filename='%s' and commented=0 ORDER BY filename,cat_metric desc,var_metric asc,category,var_name,var_val,id " , table , file ) ;
2006-04-18 18:16:32 +00:00
q . sql = sql ;
2004-07-08 20:16:28 +00:00
2006-04-18 18:16:32 +00:00
stmt = odbc_prepare_and_execute ( obj , config_odbc_prepare , & q ) ;
if ( ! stmt ) {
ast_log ( LOG_WARNING , " SQL select error! \n [%s] \n \n " , sql ) ;
odbc_release_obj ( obj ) ;
2004-07-08 20:16:28 +00:00
return NULL ;
2004-06-11 00:12:35 +00:00
}
2006-04-18 18:16:32 +00:00
res = SQLNumResultCols ( stmt , & rowcount ) ;
2004-06-11 00:12:35 +00:00
2004-07-08 20:16:28 +00:00
if ( ( res ! = SQL_SUCCESS ) & & ( res ! = SQL_SUCCESS_WITH_INFO ) ) {
2006-04-18 18:16:32 +00:00
ast_log ( LOG_WARNING , " SQL NumResultCols error! \n [%s] \n \n " , sql ) ;
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
odbc_release_obj ( obj ) ;
2004-10-05 06:46:11 +00:00
return NULL ;
}
2005-01-25 06:10:20 +00:00
if ( ! rowcount ) {
2006-04-18 18:16:32 +00:00
ast_log ( LOG_NOTICE , " found nothing \n " ) ;
odbc_release_obj ( obj ) ;
2005-01-25 06:10:20 +00:00
return cfg ;
}
2004-07-08 20:16:28 +00:00
2005-01-25 06:10:20 +00:00
cur_cat = ast_config_get_current_category ( cfg ) ;
2004-07-08 20:16:28 +00:00
2005-01-25 06:10:20 +00:00
while ( ( res = SQLFetch ( stmt ) ) ! = SQL_NO_DATA ) {
2006-04-18 18:16:32 +00:00
if ( ! strcmp ( q . var_name , " #include " ) ) {
if ( ! ast_config_internal_load ( q . var_val , cfg ) ) {
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
odbc_release_obj ( obj ) ;
2005-01-25 06:10:20 +00:00
return NULL ;
2004-07-08 20:16:28 +00:00
}
2005-01-25 06:10:20 +00:00
continue ;
}
2006-04-18 18:16:32 +00:00
if ( strcmp ( last , q . category ) | | last_cat_metric ! = q . cat_metric ) {
cur_cat = ast_category_new ( q . category ) ;
2005-01-25 06:10:20 +00:00
if ( ! cur_cat ) {
ast_log ( LOG_WARNING , " Out of memory! \n " ) ;
break ;
}
2006-04-18 18:16:32 +00:00
strcpy ( last , q . category ) ;
last_cat_metric = q . cat_metric ;
2005-01-25 06:10:20 +00:00
ast_category_append ( cfg , cur_cat ) ;
2004-07-08 20:16:28 +00:00
}
2006-04-18 18:16:32 +00:00
new_v = ast_variable_new ( q . var_name , q . var_val ) ;
2005-01-25 06:10:20 +00:00
ast_variable_append ( cur_cat , new_v ) ;
2004-07-08 20:16:28 +00:00
}
2004-06-11 00:12:35 +00:00
2006-04-18 18:16:32 +00:00
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
odbc_release_obj ( obj ) ;
2005-01-25 06:10:20 +00:00
return cfg ;
2004-07-08 20:16:28 +00:00
}
2004-06-11 00:12:35 +00:00
2005-01-25 06:10:20 +00:00
static struct ast_config_engine odbc_engine = {
. name = " odbc " ,
. load_func = config_odbc ,
. realtime_func = realtime_odbc ,
. realtime_multi_func = realtime_multi_odbc ,
. update_func = update_odbc
} ;
2006-04-14 14:08:19 +00:00
static int unload_module ( void * mod )
2004-06-11 00:12:35 +00:00
{
2006-04-14 14:08:19 +00:00
ast_hangup_localusers ( mod ) ;
2005-01-25 06:10:20 +00:00
ast_config_engine_deregister ( & odbc_engine ) ;
2004-10-05 06:46:11 +00:00
if ( option_verbose )
ast_verbose ( " res_config_odbc unloaded. \n " ) ;
2004-06-11 00:12:35 +00:00
return 0 ;
}
2006-04-14 14:08:19 +00:00
static int load_module ( void * mod )
2004-06-11 00:12:35 +00:00
{
2005-01-25 06:10:20 +00:00
ast_config_engine_register ( & odbc_engine ) ;
2004-10-05 06:46:11 +00:00
if ( option_verbose )
ast_verbose ( " res_config_odbc loaded. \n " ) ;
2004-06-11 00:12:35 +00:00
return 0 ;
}
2006-04-14 14:08:19 +00:00
static const char * description ( void )
2004-06-11 00:12:35 +00:00
{
2006-04-11 10:01:00 +00:00
return " ODBC Configuration " ;
2004-06-11 00:12:35 +00:00
}
2006-04-14 14:08:19 +00:00
static const char * key ( void )
2004-06-11 00:12:35 +00:00
{
2004-07-08 20:16:28 +00:00
return ASTERISK_GPL_KEY ;
2004-06-11 00:12:35 +00:00
}
2006-04-14 14:08:19 +00:00
STD_MOD ( MOD_0 | NO_USECOUNT | NO_UNLOAD , NULL , NULL , NULL ) ;