@ -93,7 +93,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
< description >
< para > Used in SQL templates to escape data which may contain single ticks
< literal > ' < / literal > which are otherwise used to delimit data . < / para >
< para > Example : SELECT foo FROM bar WHERE baz = ' $ { SQL_ESC ( $ { ARG1 } ) } ' < / para >
< para > Example : SELECT foo FROM bar WHERE baz = ' $ { SQL_ESC ( $ { ARG1 } ) } ' < / para >
< / description >
< / function >
* * */
@ -260,7 +260,10 @@ static int acf_odbc_write(struct ast_channel *chan, const char *cmd, char *s, co
}
ast_str_make_space ( & buf , strlen ( query - > sql_write ) * 2 + 300 ) ;
ast_str_make_space ( & insertbuf , strlen ( query - > sql_insert ) * 2 + 300 ) ;
/* We only get here if sql_write is set. sql_insert is optional however. */
if ( query - > sql_insert ) {
ast_str_make_space ( & insertbuf , strlen ( query - > sql_insert ) * 2 + 300 ) ;
}
/* Parse our arguments */
t = value ? ast_strdupa ( value ) : " " ;
@ -294,7 +297,9 @@ static int acf_odbc_write(struct ast_channel *chan, const char *cmd, char *s, co
pbx_builtin_pushvar_helper ( chan , " VALUE " , value ? value : " " ) ;
ast_str_substitute_variables ( & buf , 0 , chan , query - > sql_write ) ;
ast_str_substitute_variables ( & insertbuf , 0 , chan , query - > sql_insert ) ;
if ( query - > sql_insert ) {
ast_str_substitute_variables ( & insertbuf , 0 , chan , query - > sql_insert ) ;
}
if ( bogus_chan ) {
chan = ast_channel_unref ( chan ) ;
@ -345,44 +350,47 @@ static int acf_odbc_write(struct ast_channel *chan, const char *cmd, char *s, co
if ( stmt ) {
SQLRowCount ( stmt , & rows ) ;
}
if ( stmt & & rows = = 0 & & ast_str_strlen ( insertbuf ) ! = 0 ) {
SQLCloseCursor ( stmt ) ;
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
if ( obj & & ! transactional ) {
ast_odbc_release_obj ( obj ) ;
obj = NULL ;
}
for ( transactional = 0 , dsn = 0 ; dsn < 5 ; dsn + + ) {
if ( ! ast_strlen_zero ( query - > writehandle [ dsn ] ) ) {
if ( transactional ) {
/* This can only happen second time through or greater. */
ast_log ( LOG_WARNING , " Transactions do not work well with multiple DSNs for 'writehandle' \n " ) ;
} else if ( obj ) {
ast_odbc_release_obj ( obj ) ;
obj = NULL ;
}
if ( rows ! = 0 ) {
status = " SUCCESS " ;
if ( ( obj = ast_odbc_retrieve_transaction_obj ( chan , query - > writehandle [ dsn ] ) ) ) {
transactional = 1 ;
} else {
obj = ast_odbc_request_obj ( query - > writehandle [ dsn ] , 0 ) ;
transactional = 0 ;
} else if ( query - > sql_insert ) {
if ( obj & & ! transactional ) {
ast_odbc_release_obj ( obj ) ;
obj = NULL ;
}
for ( transactional = 0 , dsn = 0 ; dsn < 5 ; dsn + + ) {
if ( ! ast_strlen_zero ( query - > writehandle [ dsn ] ) ) {
if ( transactional ) {
/* This can only happen second time through or greater. */
ast_log ( LOG_WARNING , " Transactions do not work well with multiple DSNs for 'writehandle' \n " ) ;
} else if ( obj ) {
ast_odbc_release_obj ( obj ) ;
obj = NULL ;
}
if ( ( obj = ast_odbc_retrieve_transaction_obj ( chan , query - > writehandle [ dsn ] ) ) ) {
transactional = 1 ;
} else {
obj = ast_odbc_request_obj ( query - > writehandle [ dsn ] , 0 ) ;
transactional = 0 ;
}
if ( obj ) {
stmt = ast_odbc_direct_execute ( obj , generic_execute , ast_str_buffer ( insertbuf ) ) ;
}
}
if ( obj ) {
stmt = ast_odbc_direct_execute ( obj , generic_execute , ast_str_buffer ( insertbuf ) ) ;
if ( stmt ) {
status = " FAILOVER " ;
SQLRowCount ( stmt , & rows ) ;
SQLCloseCursor ( stmt ) ;
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
break ;
}
}
if ( stmt ) {
status = " FAILOVER " ;
SQLRowCount ( stmt , & rows ) ;
break ;
}
}
} else if ( stmt ) {
status = " SUCCESS " ;
}
AST_RWLIST_UNLOCK ( & queries ) ;
@ -397,10 +405,6 @@ static int acf_odbc_write(struct ast_channel *chan, const char *cmd, char *s, co
pbx_builtin_setvar_helper ( chan , " ODBCSTATUS " , status ) ;
}
if ( stmt ) {
SQLCloseCursor ( stmt ) ;
SQLFreeHandle ( SQL_HANDLE_STMT , stmt ) ;
}
if ( obj & & ! transactional ) {
ast_odbc_release_obj ( obj ) ;
obj = NULL ;
@ -875,15 +879,16 @@ static int free_acf_query(struct acf_odbc_query *query)
static int init_acf_query ( struct ast_config * cfg , char * catg , struct acf_odbc_query * * query )
{
const char * tmp ;
const char * tmp2 ;
int i ;
if ( ! cfg | | ! catg ) {
return EINVAL ;
}
* query = ast_calloc ( 1 , sizeof ( struct acf_odbc_query ) ) ;
if ( ! ( * query ) )
if ( ! ( * query = ast_calloc ( 1 , sizeof ( * * query ) ) ) ) {
return ENOMEM ;
}
if ( ( ( tmp = ast_variable_retrieve ( cfg , catg , " writehandle " ) ) ) | | ( ( tmp = ast_variable_retrieve ( cfg , catg , " dsn " ) ) ) ) {
char * tmp2 = ast_strdupa ( tmp ) ;
@ -913,30 +918,46 @@ static int init_acf_query(struct ast_config *cfg, char *catg, struct acf_odbc_qu
if ( ! ast_strlen_zero ( ( * query ) - > writehandle [ i ] ) )
ast_copy_string ( ( * query ) - > readhandle [ i ] , ( * query ) - > writehandle [ i ] , sizeof ( ( * query ) - > readhandle [ i ] ) ) ;
}
}
}
if ( ( tmp = ast_variable_retrieve ( cfg , catg , " readsql " ) ) )
( * query ) - > sql_read = ast_strdup ( tmp ) ;
else if ( ( tmp = ast_variable_retrieve ( cfg , catg , " read " ) ) ) {
ast_log ( LOG_WARNING , " Parameter 'read' is deprecated for category %s. Please use 'readsql' instead. \n " , catg ) ;
( * query ) - > sql_read = ast_strdup ( tmp ) ;
if ( ( tmp = ast_variable_retrieve ( cfg , catg , " readsql " ) ) | |
( tmp2 = ast_variable_retrieve ( cfg , catg , " read " ) ) ) {
if ( ! tmp ) {
ast_log ( LOG_WARNING , " Parameter 'read' is deprecated for category %s. Please use 'readsql' instead. \n " , catg ) ;
tmp = tmp2 ;
}
if ( * tmp ! = ' \0 ' ) { /* non-empty string */
if ( ! ( ( * query ) - > sql_read = ast_strdup ( tmp ) ) ) {
free_acf_query ( * query ) ;
* query = NULL ;
return ENOMEM ;
}
}
}
if ( ! ast_strlen_zero ( ( * query ) - > sql_read ) & & ast_strlen_zero ( ( * query ) - > readhandle [ 0 ] ) ) {
if ( ( * query ) - > sql_read & & ast_strlen_zero ( ( * query ) - > readhandle [ 0 ] ) ) {
free_acf_query ( * query ) ;
* query = NULL ;
ast_log ( LOG_ERROR , " There is SQL, but no ODBC class to be used for reading: %s \n " , catg ) ;
return EINVAL ;
}
if ( ( tmp = ast_variable_retrieve ( cfg , catg , " writesql " ) ) )
( * query ) - > sql_write = ast_strdup ( tmp ) ;
else if ( ( tmp = ast_variable_retrieve ( cfg , catg , " write " ) ) ) {
ast_log ( LOG_WARNING , " Parameter 'write' is deprecated for category %s. Please use 'writesql' instead. \n " , catg ) ;
( * query ) - > sql_write = ast_strdup ( tmp ) ;
if ( ( tmp = ast_variable_retrieve ( cfg , catg , " writesql " ) ) | |
( tmp2 = ast_variable_retrieve ( cfg , catg , " write " ) ) ) {
if ( ! tmp ) {
ast_log ( LOG_WARNING , " Parameter 'write' is deprecated for category %s. Please use 'writesql' instead. \n " , catg ) ;
tmp = tmp2 ;
}
if ( * tmp ! = ' \0 ' ) { /* non-empty string */
if ( ! ( ( * query ) - > sql_write = ast_strdup ( tmp ) ) ) {
free_acf_query ( * query ) ;
* query = NULL ;
return ENOMEM ;
}
}
}
if ( ! ast_strlen_zero ( ( * query ) - > sql_write ) & & ast_strlen_zero ( ( * query ) - > writehandle [ 0 ] ) ) {
if ( ( * query ) - > sql_write & & ast_strlen_zero ( ( * query ) - > writehandle [ 0 ] ) ) {
free_acf_query ( * query ) ;
* query = NULL ;
ast_log ( LOG_ERROR , " There is SQL, but no ODBC class to be used for writing: %s \n " , catg ) ;
@ -944,7 +965,13 @@ static int init_acf_query(struct ast_config *cfg, char *catg, struct acf_odbc_qu
}
if ( ( tmp = ast_variable_retrieve ( cfg , catg , " insertsql " ) ) ) {
( * query ) - > sql_insert = ast_strdup ( tmp ) ;
if ( * tmp ! = ' \0 ' ) { /* non-empty string */
if ( ! ( ( * query ) - > sql_insert = ast_strdup ( tmp ) ) ) {
free_acf_query ( * query ) ;
* query = NULL ;
return ENOMEM ;
}
}
}
/* Allow escaping of embedded commas in fields to be turned off */
@ -962,7 +989,7 @@ static int init_acf_query(struct ast_config *cfg, char *catg, struct acf_odbc_qu
}
( * query ) - > acf = ast_calloc ( 1 , sizeof ( struct ast_custom_function ) ) ;
if ( ! ( * query ) - > acf ) {
if ( ! ( * query ) - > acf ) {
free_acf_query ( * query ) ;
* query = NULL ;
return ENOMEM ;
@ -983,7 +1010,7 @@ static int init_acf_query(struct ast_config *cfg, char *catg, struct acf_odbc_qu
}
}
if ( ! ( ( * query ) - > acf - > name ) ) {
if ( ! ( * query ) - > acf - > name ) {
free_acf_query ( * query ) ;
* query = NULL ;
return ENOMEM ;
@ -1013,42 +1040,40 @@ static int init_acf_query(struct ast_config *cfg, char *catg, struct acf_odbc_qu
return ENOMEM ;
}
if ( ! ast_strlen_zero ( ( * query ) - > sql_read ) & & ! ast_strlen_zero ( ( * query ) - > sql_write ) ) {
if ( ( * query ) - > sql_read & & ( * query ) - > sql_write ) {
ast_string_field_build ( ( * query ) - > acf , desc ,
" Runs the following query, as defined in func_odbc.conf, performing \n "
" substitution of the arguments into the query as specified by ${ARG1}, \n "
" substitution of the arguments into the query as specified by ${ARG1}, \n "
" ${ARG2}, ... ${ARGn}. When setting the function, the values are provided \n "
" either in whole as ${VALUE} or parsed as ${VAL1}, ${VAL2}, ... ${VALn}. \n "
" %s "
" \n Read: \n %s \n \n Write: \n %s \n %s %s%s" ,
ast_strlen_zero ( ( * query ) - > sql_insert ) ? " " :
" \n Read: \n %s \n \n Write: \n %s %s%s" ,
( * query ) - > sql_insert ?
" If the write query affects no rows, the insert query will be \n "
" performed. \n " ,
" performed. \n " : " " ,
( * query ) - > sql_read ,
( * query ) - > sql_write ,
ast_strlen_zero ( ( * query ) - > sql_insert ) ? " " : " Insert: \n " ,
ast_strlen_zero ( ( * query ) - > sql_insert ) ? " " : ( * query ) - > sql_insert ,
ast_strlen_zero ( ( * query ) - > sql_insert ) ? " " : " \n " ) ;
} else if ( ! ast_strlen_zero ( ( * query ) - > sql_read ) ) {
( * query ) - > sql_insert ? " \n \n Insert: \n " : " " ,
( * query ) - > sql_insert ? ( * query ) - > sql_insert : " " ) ;
} else if ( ( * query ) - > sql_read ) {
ast_string_field_build ( ( * query ) - > acf , desc ,
" Runs the following query, as defined in func_odbc.conf, performing \n "
" substitution of the arguments into the query as specified by ${ARG1}, \n "
" ${ARG2}, ... ${ARGn}. This function may only be read, not set. \n \n SQL: \n %s \n " ,
( * query ) - > sql_read ) ;
} else if ( ! ast_strlen_zero ( ( * query ) - > sql_write ) ) {
ast_string_field_build ( ( * query ) - > acf , desc ,
" Runs the following query, as defined in func_odbc.conf, performing \n "
" substitution of the arguments into the query as specified by ${ARG1}, \n "
" substitution of the arguments into the query as specified by ${ARG1}, \n "
" ${ARG2}, ... ${ARGn}. This function may only be read, not set. \n \n SQL: \n %s " ,
( * query ) - > sql_read ) ;
} else if ( ( * query ) - > sql_write ) {
ast_string_field_build ( ( * query ) - > acf , desc ,
" Runs the following query, as defined in func_odbc.conf, performing \n "
" substitution of the arguments into the query as specified by ${ARG1}, \n "
" ${ARG2}, ... ${ARGn}. The values are provided either in whole as \n "
" ${VALUE} or parsed as ${VAL1}, ${VAL2}, ... ${VALn}. \n "
" This function may only be set. \n %sSQL: \n %s \n %s%s%s " ,
ast_strlen_zero ( ( * query ) - > sql_insert ) ? " " :
" This function may only be set. \n %s \n SQL: \n %s%s%s " ,
( * query ) - > sql_insert ?
" If the write query affects no rows, the insert query will be \n "
" performed. \n " ,
" performed. \n " : " " ,
( * query ) - > sql_write ,
ast_strlen_zero ( ( * query ) - > sql_insert ) ? " " : " Insert: \n " ,
ast_strlen_zero ( ( * query ) - > sql_insert ) ? " " : ( * query ) - > sql_insert ,
ast_strlen_zero ( ( * query ) - > sql_insert ) ? " " : " \n " ) ;
( * query ) - > sql_insert ? " \n \n Insert: \n " : " " ,
( * query ) - > sql_insert ? ( * query ) - > sql_insert : " " ) ;
} else {
free_acf_query ( * query ) ;
* query = NULL ;
@ -1062,15 +1087,11 @@ static int init_acf_query(struct ast_config *cfg, char *catg, struct acf_odbc_qu
return ENOMEM ;
}
if ( ast_strlen_zero ( ( * query ) - > sql_read ) ) {
( * query ) - > acf - > read = NULL ;
} else {
if ( ( * query ) - > sql_read ) {
( * query ) - > acf - > read = acf_odbc_read ;
}
if ( ast_strlen_zero ( ( * query ) - > sql_write ) ) {
( * query ) - > acf - > write = NULL ;
} else {
if ( ( * query ) - > sql_write ) {
( * query ) - > acf - > write = acf_odbc_write ;
}
@ -1142,7 +1163,7 @@ static char *cli_odbc_read(struct ast_cli_entry *e, int cmd, struct ast_cli_args
return CLI_SHOWUSAGE ;
}
if ( ast_strlen_zero ( query - > sql_read ) ) {
if ( ! query - > sql_read ) {
ast_cli ( a - > fd , " The function %s has no readsql parameter. \n " , a - > argv [ 2 ] ) ;
AST_RWLIST_UNLOCK ( & queries ) ;
return CLI_SUCCESS ;
@ -1355,12 +1376,15 @@ static char *cli_odbc_write(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
return CLI_SHOWUSAGE ;
}
if ( ast_strlen_zero ( query - > sql_write ) ) {
if ( ! query - > sql_write ) {
ast_cli ( a - > fd , " The function %s has no writesql parameter. \n " , a - > argv [ 2 ] ) ;
AST_RWLIST_UNLOCK ( & queries ) ;
return CLI_SUCCESS ;
}
/* FIXME: The code below duplicates code found in acf_odbc_write but
* lacks the newer sql_insert additions . */
ast_str_make_space ( & sql , strlen ( query - > sql_write ) * 2 + 300 ) ;
/* Evaluate function */