50#define SQL_BUF_SIZE    1024 
   68#define ENCODE_CHUNK(buffer, s) \ 
   70        char *eptr = buffer; \ 
   71        const char *vptr = s; \ 
   72        for (; *vptr && eptr < buffer + sizeof(buffer); vptr++) { \ 
   73            if (strchr("^;", *vptr)) { \ 
   75                snprintf(eptr, buffer + sizeof(buffer) - eptr, "^%02hhX", *vptr); \ 
   81        if (eptr < buffer + sizeof(buffer)) { \ 
   84            buffer[sizeof(buffer) - 1] = '\0'; \ 
 
   90    for (; *chunk; chunk++) {
 
   91        if (*chunk == 
'^' && strchr(
"0123456789ABCDEF", chunk[1]) && strchr(
"0123456789ABCDEF", chunk[2])) {
 
   92            sscanf(chunk + 1, 
"%02hhX", (
unsigned char *)chunk);
 
   93            memmove(chunk + 1, chunk + 3, strlen(chunk + 3) + 1);
 
 
  100    return column->
type == SQL_CHAR || column->
type == SQL_VARCHAR || column->
type == SQL_LONGVARCHAR
 
  101        || column->
type == SQL_WCHAR || column->
type == SQL_WVARCHAR || column->
type == SQL_WLONGVARCHAR;
 
 
  106    int res, x = 1, count = 0;
 
  109    char encodebuf[1024];
 
  112    res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
 
  113    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  121    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  122        if (res == SQL_ERROR) {
 
  126        SQLFreeHandle (SQL_HANDLE_STMT, stmt);
 
  130    for (field = cps->
fields; field; field = field->
next) {
 
  131        const char *newval = field->
value;
 
  133        if ((1LL << count++) & cps->
skip) {
 
  134            ast_debug(1, 
"Skipping field '%s'='%s' (%llo/%llo)\n", field->
name, newval, 1ULL << (count - 1), cps->
skip);
 
  137        ast_debug(1, 
"Parameter %d ('%s') = '%s'\n", x, field->
name, newval);
 
  138        if (strchr(newval, 
';') || strchr(newval, 
'^')) {
 
  143        SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (
void *)newval, 0, 
NULL);
 
  147        const char *newval = cps->
extra;
 
  148        ast_debug(1, 
"Parameter %d = '%s'\n", x, newval);
 
  149        if (strchr(newval, 
';') || strchr(newval, 
'^')) {
 
  154        SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (
void *)newval, 0, 
NULL);
 
 
  190    SQLSMALLINT colcount=0;
 
  191    SQLSMALLINT datatype;
 
  192    SQLSMALLINT decimaldigits;
 
  193    SQLSMALLINT nullable;
 
  198    if (!table || !field || !sql || !rowdata) {
 
  204        ast_log(
LOG_ERROR, 
"No database handle available with the name of '%s' (check res_odbc.conf)\n", database);
 
  208    op = !strchr(field->
name, 
' ') ? 
" =" : 
"";
 
  209    ast_str_set(&sql, 0, 
"SELECT * FROM %s WHERE %s%s ?%s", table, field->
name, op,
 
  211    while ((field = field->
next)) {
 
  212        op = !strchr(field->
name, 
' ') ? 
" =" : 
"";
 
  231    res = SQLNumResultCols(stmt, &colcount);
 
  232    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  234        SQLFreeHandle (SQL_HANDLE_STMT, stmt);
 
  239    res = SQLFetch(stmt);
 
  240    if (res == SQL_NO_DATA) {
 
  245        SQLFreeHandle (SQL_HANDLE_STMT, stmt);
 
  249    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  251        SQLFreeHandle (SQL_HANDLE_STMT, stmt);
 
  255    for (x = 0; x < colcount; x++) {
 
  257        collen = 
sizeof(coltitle);
 
  258        res = SQLDescribeCol(stmt, x + 1, (
unsigned char *)coltitle, 
sizeof(coltitle), &collen,
 
  259                    &datatype, &colsize, &decimaldigits, &nullable);
 
  260        if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  279        } 
else if ((res == SQL_SUCCESS) || (res == SQL_SUCCESS_WITH_INFO)) {
 
  289        if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  298        if (!strncmp(coltitle, 
"@", 1)) {
 
  313                chunk = 
strsep(&stringp, 
";");
 
  315                    if (strchr(chunk, 
'^')) {
 
  331    SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
 
  357    const char *initfield;
 
  370    SQLSMALLINT colcount=0;
 
  371    SQLSMALLINT datatype;
 
  372    SQLSMALLINT decimaldigits;
 
  373    SQLSMALLINT nullable;
 
  377    if (!table || !field || !
sql || !rowdata) {
 
  387    if ((op = strchr(initfield, 
' '))) {
 
  391    op = !strchr(field->
name, 
' ') ? 
" =" : 
"";
 
  394    while ((field = field->
next)) {
 
  395        op = !strchr(field->
name, 
' ') ? 
" =" : 
"";
 
  418    res = SQLNumResultCols(stmt, &colcount);
 
  419    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  421        SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
  429        SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
  434    while ((res=SQLFetch(stmt)) != SQL_NO_DATA) {
 
  436        if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  444        for (x=0;x<colcount;x++) {
 
  446            collen = 
sizeof(coltitle);
 
  447            res = SQLDescribeCol(stmt, x + 1, (
unsigned char *)coltitle, 
sizeof(coltitle), &collen,
 
  448                        &datatype, &colsize, &decimaldigits, &nullable);
 
  449            if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  464            if ((res == SQL_SUCCESS) || (res == SQL_SUCCESS_WITH_INFO)) {
 
  474            if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  480            if (!strncmp(coltitle, 
"@", 1)) {
 
  489                    chunk = 
strsep(&stringp, 
";");
 
  491                        if (strchr(chunk, 
'^')) {
 
  494                        if (!strcmp(initfield, coltitle)) {
 
  507    SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
 
  534    int res, count = 0, paramcount = 0;
 
  540    if (!table || !field || !keyfield || !sql) {
 
  551        ast_log(
LOG_WARNING, 
"Key field '%s' does not exist in table '%s@%s'.  Update will fail\n", keyfield, table, database);
 
  563                cps.
skip |= (1LL << count);
 
  569            cps.
skip |= (1LL << count);
 
  591    res = SQLRowCount(stmt, &rowcount);
 
  592    SQLFreeHandle (SQL_HANDLE_STMT, stmt);
 
  595    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  601        return (
int) rowcount;
 
 
  617    int res, x = 1, 
first = 1;
 
  627    res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
 
  628    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  638            SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(field->
name), 0, (
void *)field->
value, 0, 
NULL);
 
  651            SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
  655        SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(field->
value), 0, (
void *)field->
value, 0, 
NULL);
 
  660    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  661        if (res == SQL_ERROR) {
 
  665        SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
 
  701        ast_log(
LOG_ERROR, 
"Could not retrieve metadata for table '%s@%s'. Update will fail!\n", table, database);
 
  719    res = SQLRowCount(stmt, &rowcount);
 
  720    SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
  723    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  732        return (
int) rowcount;
 
 
  766    if (!table || !field || !
keys || !vals || !sql) {
 
  781    while ((field = field->
next)) {
 
  785    ast_str_set(&sql, 0, 
"INSERT INTO %s (%s) VALUES (%s)",
 
  804    res = SQLRowCount(stmt, &rowcount);
 
  805    SQLFreeHandle (SQL_HANDLE_STMT, stmt);
 
  808    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  814        return (
int)rowcount;
 
 
  834static int destroy_odbc(
const char *database, 
const char *table, 
const char *keyfield, 
const char *lookup, 
const struct ast_variable *fields)
 
  845    if (!table || !sql) {
 
  854    ast_str_set(&sql, 0, 
"DELETE FROM %s WHERE ", table);
 
  855    for (field = fields; field; field = field->
next) {
 
  874    res = SQLRowCount(stmt, &rowcount);
 
  875    SQLFreeHandle (SQL_HANDLE_STMT, stmt);
 
  878    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  884        return (
int)rowcount;
 
 
  906    res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &sth);
 
  907    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  908        ast_verb(4, 
"Failure in AllocStatement %d\n", res);
 
  913    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  914        ast_verb(4, 
"Error in PREPARE %d\n", res);
 
  915        SQLFreeHandle(SQL_HANDLE_STMT, sth);
 
 
  930    res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &sth);
 
  931    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  932        ast_verb(4, 
"Failure in AllocStatement %d\n", res);
 
  937    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  938        ast_verb(4, 
"Error in PREPARE %d\n", res);
 
  939        SQLFreeHandle(SQL_HANDLE_STMT, sth);
 
 
  958    unsigned int last_cat_metric = 0;
 
  959    SQLSMALLINT rowcount = 0;
 
  966    memset(&q, 0, 
sizeof(q));
 
  976    ast_str_set(&sql, 0, 
"SELECT MAX(LENGTH(var_val)) FROM %s WHERE filename='%s'",
 
  987    res = SQLNumResultCols(stmt, &rowcount);
 
  989    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  991        SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
 1003    if (SQLFetch(stmt) == SQL_NO_DATA) {
 
 1004        ast_log(
LOG_NOTICE, 
"Failed to determine maximum length of a configuration value\n");
 
 1005        SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
 1011    SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
 1013    ast_str_set(&sql, 0, 
"SELECT cat_metric, category, var_name, var_val FROM %s ", table);
 
 1014    ast_str_append(&sql, 0, 
"WHERE filename='%s' AND commented=0 ", file);
 
 1015    ast_str_append(&sql, 0, 
"ORDER BY cat_metric DESC, var_metric ASC, category, var_name ");
 
 1021        ast_log(
LOG_WARNING, 
"Could not create buffer for reading in configuration values for '%s'\n", file);
 
 1034    res = SQLNumResultCols(stmt, &rowcount);
 
 1036    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
 1038        SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
 1053    while ((res = SQLFetch(stmt)) != SQL_NO_DATA) {
 
 1054        if (!strcmp (q.
var_name, 
"#include")) {
 
 1056                SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
 1077    SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
 
 1083#define warn_length(col, size)  ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' is not long enough to contain realtime data (needs %d)\n", table, database, col->name, size) 
 1084#define warn_type(col, type)    ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' is of the incorrect type (%d) to contain the required realtime data\n", table, database, col->name, col->type) 
 1086static int require_odbc(
const char *database, 
const char *table, va_list ap)
 
 1097    while ((elm = va_arg(ap, 
char *))) {
 
 1099        size = va_arg(ap, 
int);
 
 1102            if (strcmp(col->
name, elm) == 0) {
 
 1104                switch (col->
type) {
 
 1107                case SQL_LONGVARCHAR:
 
 1108#ifdef HAVE_ODBC_WCHAR 
 1111                case SQL_WLONGVARCHAR:
 
 1115                case SQL_LONGVARBINARY:
 
 1117#define CHECK_SIZE(n) \ 
 1118                        if (col->size < n) {      \ 
 1119                            warn_length(col, n);  \ 
 1145                case SQL_TYPE_TIMESTAMP:
 
 1155#define WARN_TYPE_OR_LENGTH(n)  \ 
 1156                        if (!ast_rq_is_int(type)) {  \ 
 1157                            warn_type(col, type);    \ 
 1159                            warn_length(col, n);  \ 
 1166                case SQL_C_STINYINT:
 
 1218#undef WARN_TYPE_OR_LENGTH 
 1229                    ast_log(
LOG_WARNING, 
"Realtime table %s@%s: column type (%d) unrecognized for column '%s'\n", table, database, col->
type, elm);
 
 1235            ast_log(
LOG_WARNING, 
"Realtime table %s@%s requires column '%s', but that column does not exist!\n", table, database, elm);
 
 
 1311    .
requires = 
"extconfig,res_odbc",
 
static int load_config(void)
struct sla_ringing_trunk * first
struct sla_ringing_trunk * last
char * strsep(char **str, const char *delims)
char * strcasestr(const char *, const char *)
Asterisk main include file. File version handling, generic pbx functions.
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_malloc(len)
A wrapper for malloc()
static const char config[]
General Asterisk PBX channel definitions.
Generic File Format Support. Should be included by clients of the file handling routines....
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
void ast_category_rename(struct ast_category *cat, const char *name)
#define CONFIG_STATUS_FILEMISSING
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
void ast_category_append(struct ast_config *config, struct ast_category *category)
Appends a category to a config.
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
#define ast_category_new_anonymous()
Create a nameless category that is not backed by a file.
#define ast_variable_new(name, value, filename)
int ast_config_engine_deregister(struct ast_config_engine *del)
Deregister config engine.
struct ast_category * ast_config_get_current_category(const struct ast_config *cfg)
Retrieve the current category name being built.
#define CONFIG_STATUS_FILEINVALID
void ast_category_destroy(struct ast_category *cat)
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
int ast_rq_is_int(require_type type)
Check if require type is an integer type.
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
require_type
Types used in ast_realtime_require_field.
struct ast_config * ast_config_internal_load(const char *configfile, struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl_file, const char *who_asked)
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
#define CONFIG_RT_NOT_FOUND
#define ast_category_new_dynamic(name)
Create a category that is not backed by a file.
int ast_config_engine_register(struct ast_config_engine *newconfig)
Register config engine.
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
#define AST_RWLIST_TRAVERSE
Asterisk locking-related definitions:
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODPRI_REALTIME_DRIVER
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
Core PBX routines and definitions.
static struct ast_config * config_odbc(const char *database, const char *table, const char *file, struct ast_config *cfg, struct ast_flags flags, const char *sugg_incl, const char *who_asked)
static struct ast_config_engine odbc_engine
static struct ast_variable * realtime_odbc(const char *database, const char *table, const struct ast_variable *fields)
Execute an SQL query and return ast_variable list.
#define warn_length(col, size)
static SQLHSTMT length_determination_odbc_prepare(struct odbc_obj *obj, void *data)
static void decode_chunk(char *chunk)
static int require_odbc(const char *database, const char *table, va_list ap)
#define ENCODE_CHUNK(buffer, s)
static int order_multi_row_results_by_initial_column
static SQLHSTMT update2_prepare(struct odbc_obj *obj, void *data)
static int update_odbc(const char *database, const char *table, const char *keyfield, const char *lookup, const struct ast_variable *fields)
Execute an UPDATE query.
static int is_text(const struct odbc_cache_columns *column)
static int reload_module(void)
static struct ast_config * realtime_multi_odbc(const char *database, const char *table, const struct ast_variable *fields)
Execute an Select query and return ast_config list.
static SQLHSTMT custom_prepare(struct odbc_obj *obj, void *data)
static int update2_odbc(const char *database, const char *table, const struct ast_variable *lookup_fields, const struct ast_variable *update_fields)
Execute an UPDATE query.
static int unload_odbc(const char *a, const char *b)
#define warn_type(col, type)
static int load_module(void)
static SQLHSTMT config_odbc_prepare(struct odbc_obj *obj, void *data)
static const char * res_config_odbc_conf
static int unload_module(void)
static int store_odbc(const char *database, const char *table, const struct ast_variable *fields)
Execute an INSERT query.
static int destroy_odbc(const char *database, const char *table, const char *keyfield, const char *lookup, const struct ast_variable *fields)
Execute an DELETE query.
#define WARN_TYPE_OR_LENGTH(n)
int ast_odbc_prepare(struct odbc_obj *obj, SQLHSTMT *stmt, const char *sql)
Prepares a SQL query on a statement.
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
struct odbc_cache_tables * ast_odbc_find_table(const char *database, const char *tablename)
Find or create an entry describing the table specified.
int ast_odbc_clear_cache(const char *database, const char *tablename)
Remove a cache entry from memory This function may be called to clear entries created and cached by t...
struct odbc_cache_columns * ast_odbc_find_column(struct odbc_cache_tables *table, const char *colname)
Find a column entry within a cached table structure.
#define ast_odbc_release_table(ptr)
Release a table returned from ast_odbc_find_table.
struct ast_str * ast_odbc_print_errors(SQLSMALLINT handle_type, SQLHANDLE handle, const char *operation)
Shortcut for printing errors to logs after a failed SQL operation.
int ast_odbc_backslash_is_escape(struct odbc_obj *obj)
Checks if the database natively supports backslash as an escape character.
#define ast_odbc_request_obj2(name, check)
Retrieves a connected ODBC object.
SQLHSTMT ast_odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT(*prepare_cb)(struct odbc_obj *obj, void *data), void *data)
Prepares, executes, and returns the resulting statement handle.
#define ast_odbc_request_obj(name, check)
Get a ODBC connection object.
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
#define AST_STRING_FIELD(name)
Declare a string field.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
size_t attribute_pure ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
static force_inline int attribute_pure ast_strlen_zero(const char *s)
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
#define ast_str_make_space(buf, new_len)
void ast_str_update(struct ast_str *buf)
Update the length of the buffer, after using ast_str merely as a buffer.
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
size_t attribute_pure ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Configuration engine structure, used to define realtime drivers.
Structure used to handle boolean flags.
Support for dynamic strings.
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
unsigned long var_val_size
const ast_string_field encoding[256]
const struct ast_variable * fields
These structures are used for adaptive capabilities.
struct odbc_cache_columns::@272 list
struct odbc_cache_tables::_columns columns
const struct ast_variable * lookup_fields
const struct ast_variable * update_fields
struct odbc_cache_tables * tableptr
#define AST_THREADSTORAGE(name)
Define a thread storage variable.