Fri Nov 12 12:07:55 2010

Asterisk developer's documentation


res_config_odbc.c File Reference

odbc+odbc plugin for portable configuration engine More...

#include "asterisk.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/res_odbc.h"
#include "asterisk/utils.h"
Include dependency graph for res_config_odbc.c:

Go to the source code of this file.

Data Structures

struct  config_odbc_obj
struct  custom_prepare_struct
struct  update2_prepare_struct

Defines

#define CHECK_SIZE(n)
#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)
#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)
#define WARN_TYPE_OR_LENGTH(n)

Functions

static void __init_sql_buf (void)
static void __reg_module (void)
static void __unreg_module (void)
static struct ast_configconfig_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 SQLHSTMT config_odbc_prepare (struct odbc_obj *obj, void *data)
static SQLHSTMT custom_prepare (struct odbc_obj *obj, void *data)
static int destroy_odbc (const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)
 Excute an DELETE query.
static int load_module (void)
static struct ast_configrealtime_multi_odbc (const char *database, const char *table, va_list ap)
 Excute an Select query and return ast_config list.
static struct ast_variablerealtime_odbc (const char *database, const char *table, va_list ap)
 Excute an SQL query and return ast_variable list.
static int reload_module (void)
static int require_odbc (const char *database, const char *table, va_list ap)
static int store_odbc (const char *database, const char *table, va_list ap)
 Excute an INSERT query.
static int unload_module (void)
static int update2_odbc (const char *database, const char *table, va_list ap)
 Execute an UPDATE query.
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, va_list ap)
 Excute an UPDATE query.

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "Realtime ODBC configuration" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload_module, }
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_config_engine odbc_engine
static struct ast_threadstorage sql_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_sql_buf , .custom_init = NULL , }

Detailed Description

odbc+odbc plugin for portable configuration engine

Author:
Mark Spencer <markster@digium.com>
Anthony Minessale II <anthmct@yahoo.com>

Definition in file res_config_odbc.c.


Define Documentation

#define CHECK_SIZE (  ) 
Value:
if (col->size < n) {      \
                     warn_length(col, n);  \
                  }                         \
                  break;

Referenced by require_odbc().

#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)

Definition at line 881 of file res_config_odbc.c.

Referenced by require_odbc().

#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)

Definition at line 882 of file res_config_odbc.c.

Referenced by require_odbc().

#define WARN_TYPE_OR_LENGTH (  ) 
Value:
if (!ast_rq_is_int(type)) {  \
                     warn_type(col, type);    \
                  } else {                     \
                     warn_length(col, n);  \
                  }

Referenced by require_odbc().


Function Documentation

static void __init_sql_buf ( void   )  [static]

Definition at line 48 of file res_config_odbc.c.

00050 {

static void __reg_module ( void   )  [static]

Definition at line 1079 of file res_config_odbc.c.

static void __unreg_module ( void   )  [static]

Definition at line 1079 of file res_config_odbc.c.

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, read]

Definition at line 797 of file res_config_odbc.c.

References ast_build_string(), ast_category_append(), ast_category_new(), ast_config_get_current_category(), ast_config_internal_load(), ast_log(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj(), ast_variable_append(), ast_variable_new(), config_odbc_obj::cat_metric, config_odbc_obj::category, config_odbc_prepare(), last, LOG_NOTICE, LOG_WARNING, config_odbc_obj::sql, config_odbc_obj::var_name, and config_odbc_obj::var_val.

00798 {
00799    struct ast_variable *new_v;
00800    struct ast_category *cur_cat;
00801    int res = 0;
00802    struct odbc_obj *obj;
00803    char sqlbuf[1024] = "";
00804    char *sql = sqlbuf;
00805    size_t sqlleft = sizeof(sqlbuf);
00806    unsigned int last_cat_metric = 0;
00807    SQLSMALLINT rowcount = 0;
00808    SQLHSTMT stmt;
00809    char last[128] = "";
00810    struct config_odbc_obj q;
00811    struct ast_flags loader_flags = { 0 };
00812 
00813    memset(&q, 0, sizeof(q));
00814 
00815    if (!file || !strcmp (file, "res_config_odbc.conf"))
00816       return NULL;      /* cant configure myself with myself ! */
00817 
00818    obj = ast_odbc_request_obj(database, 0);
00819    if (!obj)
00820       return NULL;
00821 
00822    ast_build_string(&sql, &sqlleft, "SELECT cat_metric, category, var_name, var_val FROM %s ", table);
00823    ast_build_string(&sql, &sqlleft, "WHERE filename='%s' AND commented=0 ", file);
00824    ast_build_string(&sql, &sqlleft, "ORDER BY cat_metric DESC, var_metric ASC, category, var_name ");
00825    q.sql = sqlbuf;
00826 
00827    stmt = ast_odbc_prepare_and_execute(obj, config_odbc_prepare, &q);
00828 
00829    if (!stmt) {
00830       ast_log(LOG_WARNING, "SQL select error!\n[%s]\n\n", sql);
00831       ast_odbc_release_obj(obj);
00832       return NULL;
00833    }
00834 
00835    res = SQLNumResultCols(stmt, &rowcount);
00836 
00837    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00838       ast_log(LOG_WARNING, "SQL NumResultCols error!\n[%s]\n\n", sql);
00839       SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00840       ast_odbc_release_obj(obj);
00841       return NULL;
00842    }
00843 
00844    if (!rowcount) {
00845       ast_log(LOG_NOTICE, "found nothing\n");
00846       ast_odbc_release_obj(obj);
00847       return cfg;
00848    }
00849 
00850    cur_cat = ast_config_get_current_category(cfg);
00851 
00852    while ((res = SQLFetch(stmt)) != SQL_NO_DATA) {
00853       if (!strcmp (q.var_name, "#include")) {
00854          if (!ast_config_internal_load(q.var_val, cfg, loader_flags, "", who_asked)) {
00855             SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00856             ast_odbc_release_obj(obj);
00857             return NULL;
00858          }
00859          continue;
00860       } 
00861       if (strcmp(last, q.category) || last_cat_metric != q.cat_metric) {
00862          cur_cat = ast_category_new(q.category, "", 99999);
00863          if (!cur_cat) {
00864             ast_log(LOG_WARNING, "Out of memory!\n");
00865             break;
00866          }
00867          strcpy(last, q.category);
00868          last_cat_metric   = q.cat_metric;
00869          ast_category_append(cfg, cur_cat);
00870       }
00871 
00872       new_v = ast_variable_new(q.var_name, q.var_val, "");
00873       ast_variable_append(cur_cat, new_v);
00874    }
00875 
00876    SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00877    ast_odbc_release_obj(obj);
00878    return cfg;
00879 }

static SQLHSTMT config_odbc_prepare ( struct odbc_obj obj,
void *  data 
) [static]

Definition at line 770 of file res_config_odbc.c.

References ast_verb, config_odbc_obj::cat_metric, config_odbc_obj::category, odbc_obj::con, config_odbc_obj::err, config_odbc_obj::sql, config_odbc_obj::var_name, and config_odbc_obj::var_val.

Referenced by config_odbc().

00771 {
00772    struct config_odbc_obj *q = data;
00773    SQLHSTMT sth;
00774    int res;
00775 
00776    res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &sth);
00777    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00778       ast_verb(4, "Failure in AllocStatement %d\n", res);
00779       return NULL;
00780    }
00781 
00782    res = SQLPrepare(sth, (unsigned char *)q->sql, SQL_NTS);
00783    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00784       ast_verb(4, "Error in PREPARE %d\n", res);
00785       SQLFreeHandle(SQL_HANDLE_STMT, sth);
00786       return NULL;
00787    }
00788 
00789    SQLBindCol(sth, 1, SQL_C_ULONG, &q->cat_metric, sizeof(q->cat_metric), &q->err);
00790    SQLBindCol(sth, 2, SQL_C_CHAR, q->category, sizeof(q->category), &q->err);
00791    SQLBindCol(sth, 3, SQL_C_CHAR, q->var_name, sizeof(q->var_name), &q->err);
00792    SQLBindCol(sth, 4, SQL_C_CHAR, q->var_val, sizeof(q->var_val), &q->err);
00793 
00794    return sth;
00795 }

static SQLHSTMT custom_prepare ( struct odbc_obj obj,
void *  data 
) [static]

Definition at line 57 of file res_config_odbc.c.

References custom_prepare_struct::ap, ast_debug, ast_log(), ast_strlen_zero(), odbc_obj::con, custom_prepare_struct::extra, LOG_WARNING, custom_prepare_struct::skip, and custom_prepare_struct::sql.

Referenced by destroy_odbc(), realtime_multi_odbc(), realtime_odbc(), store_odbc(), and update_odbc().

00058 {
00059    int res, x = 1, count = 0;
00060    struct custom_prepare_struct *cps = data;
00061    const char *newparam, *newval;
00062    SQLHSTMT stmt;
00063    va_list ap;
00064 
00065    va_copy(ap, cps->ap);
00066 
00067    res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
00068    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00069       ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
00070       return NULL;
00071    }
00072 
00073    ast_debug(1, "Skip: %lld; SQL: %s\n", cps->skip, cps->sql);
00074 
00075    res = SQLPrepare(stmt, (unsigned char *)cps->sql, SQL_NTS);
00076    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00077       ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", cps->sql);
00078       SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00079       return NULL;
00080    }
00081 
00082    while ((newparam = va_arg(ap, const char *))) {
00083       newval = va_arg(ap, const char *);
00084       if ((1LL << count++) & cps->skip) {
00085          ast_debug(1, "Skipping field '%s'='%s' (%llo/%llo)\n", newparam, newval, 1LL << (count - 1), cps->skip);
00086          continue;
00087       }
00088       ast_debug(1, "Parameter %d ('%s') = '%s'\n", x, newparam, newval);
00089       SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL);
00090    }
00091    va_end(ap);
00092 
00093    if (!ast_strlen_zero(cps->extra))
00094       SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(cps->extra), 0, (void *)cps->extra, 0, NULL);
00095    return stmt;
00096 }

static int destroy_odbc ( const char *  database,
const char *  table,
const char *  keyfield,
const char *  lookup,
va_list  ap 
) [static]

Excute an DELETE query.

Parameters:
database 
table 
keyfield where clause field
lookup value of field for where clause
ap list containing one or more field/value set(s)

Delete a row from a database table, prepare the sql statement using keyfield and lookup control the number of records to change. Additional params to match rows are stored in ap list. Sub-in the values to the prepared statement and execute it.

Return values:
number of rows affected
-1 on failure

Definition at line 709 of file res_config_odbc.c.

References custom_prepare_struct::ap, ast_log(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj(), custom_prepare(), LOG_WARNING, and custom_prepare_struct::sql.

00710 {
00711    struct odbc_obj *obj;
00712    SQLHSTMT stmt;
00713    char sql[256];
00714    SQLLEN rowcount=0;
00715    const char *newparam, *newval;
00716    int res;
00717    va_list aq;
00718    struct custom_prepare_struct cps = { .sql = sql, .extra = lookup };
00719 
00720    va_copy(cps.ap, ap);
00721    va_copy(aq, ap);
00722    
00723    if (!table)
00724       return -1;
00725 
00726    obj = ast_odbc_request_obj(database, 0);
00727    if (!obj)
00728       return -1;
00729 
00730    snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE ", table);
00731    while((newparam = va_arg(aq, const char *))) {
00732       snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=? AND ", newparam);
00733       newval = va_arg(aq, const char *);
00734    }
00735    va_end(aq);
00736    snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=?", keyfield);
00737 
00738    stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
00739 
00740    if (!stmt) {
00741       ast_odbc_release_obj(obj);
00742       return -1;
00743    }
00744 
00745    res = SQLRowCount(stmt, &rowcount);
00746    SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00747    ast_odbc_release_obj(obj);
00748 
00749    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00750       ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql);
00751       return -1;
00752    }
00753 
00754    if (rowcount >= 0)
00755       return (int)rowcount;
00756 
00757    return -1;
00758 }

static int load_module ( void   )  [static]

Definition at line 1063 of file res_config_odbc.c.

References ast_config_engine_register(), and ast_verb.

01064 {
01065    ast_config_engine_register(&odbc_engine);
01066    ast_verb(1, "res_config_odbc loaded.\n");
01067    return 0;
01068 }

static struct ast_config* realtime_multi_odbc ( const char *  database,
const char *  table,
va_list  ap 
) [static, read]

Excute an Select query and return ast_config list.

Parameters:
database 
table 
ap list containing one or more field/operator/value set.

Select database and preform query on table, prepare the sql statement Sub-in the values to the prepared statement and execute it. Execute this prepared query against several ODBC connected databases. Return results as an ast_config variable.

Return values:
var on success
NULL on failure

Definition at line 256 of file res_config_odbc.c.

References custom_prepare_struct::ap, ast_category_append(), ast_category_destroy(), ast_category_new(), ast_category_rename(), ast_config_new(), ast_log(), ast_odbc_backslash_is_escape(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj(), ast_strip(), ast_strlen_zero(), ast_variable_append(), ast_variable_new(), custom_prepare(), LOG_WARNING, custom_prepare_struct::sql, and var.

00257 {
00258    struct odbc_obj *obj;
00259    SQLHSTMT stmt;
00260    char sql[1024];
00261    char coltitle[256];
00262    char rowdata[2048];
00263    const char *initfield=NULL;
00264    char *op;
00265    const char *newparam, *newval;
00266    char *stringp;
00267    char *chunk;
00268    SQLSMALLINT collen;
00269    int res;
00270    int x;
00271    struct ast_variable *var=NULL;
00272    struct ast_config *cfg=NULL;
00273    struct ast_category *cat=NULL;
00274    SQLULEN colsize;
00275    SQLSMALLINT colcount=0;
00276    SQLSMALLINT datatype;
00277    SQLSMALLINT decimaldigits;
00278    SQLSMALLINT nullable;
00279    SQLLEN indicator;
00280    struct custom_prepare_struct cps = { .sql = sql };
00281    va_list aq;
00282 
00283    va_copy(cps.ap, ap);
00284    va_copy(aq, ap);
00285 
00286    if (!table)
00287       return NULL;
00288 
00289    obj = ast_odbc_request_obj(database, 0);
00290    if (!obj)
00291       return NULL;
00292 
00293    newparam = va_arg(aq, const char *);
00294    if (!newparam)  {
00295       ast_odbc_release_obj(obj);
00296       return NULL;
00297    }
00298    initfield = ast_strdupa(newparam);
00299    if ((op = strchr(initfield, ' '))) 
00300       *op = '\0';
00301    newval = va_arg(aq, const char *);
00302    op = !strchr(newparam, ' ') ? " =" : "";
00303    snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?%s", table, newparam, op,
00304       strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : "");
00305    while((newparam = va_arg(aq, const char *))) {
00306       op = !strchr(newparam, ' ') ? " =" : "";
00307       snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?%s", newparam, op,
00308          strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : "");
00309       newval = va_arg(aq, const char *);
00310    }
00311    if (initfield)
00312       snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield);
00313    va_end(aq);
00314 
00315    stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
00316 
00317    if (!stmt) {
00318       ast_odbc_release_obj(obj);
00319       return NULL;
00320    }
00321 
00322    res = SQLNumResultCols(stmt, &colcount);
00323    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00324       ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
00325       SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00326       ast_odbc_release_obj(obj);
00327       return NULL;
00328    }
00329 
00330    cfg = ast_config_new();
00331    if (!cfg) {
00332       ast_log(LOG_WARNING, "Out of memory!\n");
00333       SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00334       ast_odbc_release_obj(obj);
00335       return NULL;
00336    }
00337 
00338    while ((res=SQLFetch(stmt)) != SQL_NO_DATA) {
00339       var = NULL;
00340       if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00341          ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
00342          continue;
00343       }
00344       cat = ast_category_new("","",99999);
00345       if (!cat) {
00346          ast_log(LOG_WARNING, "Out of memory!\n");
00347          continue;
00348       }
00349       for (x=0;x<colcount;x++) {
00350          rowdata[0] = '\0';
00351          collen = sizeof(coltitle);
00352          res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen, 
00353                   &datatype, &colsize, &decimaldigits, &nullable);
00354          if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00355             ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql);
00356             ast_category_destroy(cat);
00357             continue;
00358          }
00359 
00360          indicator = 0;
00361          res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), &indicator);
00362          if (indicator == SQL_NULL_DATA)
00363             continue;
00364 
00365          if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00366             ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
00367             ast_category_destroy(cat);
00368             continue;
00369          }
00370          stringp = rowdata;
00371          while(stringp) {
00372             chunk = strsep(&stringp, ";");
00373             if (!ast_strlen_zero(ast_strip(chunk))) {
00374                if (initfield && !strcmp(initfield, coltitle))
00375                   ast_category_rename(cat, chunk);
00376                var = ast_variable_new(coltitle, chunk, "");
00377                ast_variable_append(cat, var);
00378             }
00379          }
00380       }
00381       ast_category_append(cfg, cat);
00382    }
00383 
00384    SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00385    ast_odbc_release_obj(obj);
00386    return cfg;
00387 }

static struct ast_variable* realtime_odbc ( const char *  database,
const char *  table,
va_list  ap 
) [static, read]

Excute an SQL query and return ast_variable list.

Parameters:
database 
table 
ap list containing one or more field/operator/value set.

Select database and preform query on table, prepare the sql statement Sub-in the values to the prepared statement and execute it. Return results as a ast_variable list.

Return values:
var on success
NULL on failure

Definition at line 111 of file res_config_odbc.c.

References custom_prepare_struct::ap, ast_copy_string(), ast_log(), ast_odbc_backslash_is_escape(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj(), ast_strip(), ast_strlen_zero(), ast_variable_new(), ast_variables_destroy(), custom_prepare(), LOG_ERROR, LOG_WARNING, custom_prepare_struct::sql, and var.

00112 {
00113    struct odbc_obj *obj;
00114    SQLHSTMT stmt;
00115    char sql[1024];
00116    char coltitle[256];
00117    char rowdata[2048];
00118    char *op;
00119    const char *newparam, *newval;
00120    char *stringp;
00121    char *chunk;
00122    SQLSMALLINT collen;
00123    int res;
00124    int x;
00125    struct ast_variable *var=NULL, *prev=NULL;
00126    SQLULEN colsize;
00127    SQLSMALLINT colcount=0;
00128    SQLSMALLINT datatype;
00129    SQLSMALLINT decimaldigits;
00130    SQLSMALLINT nullable;
00131    SQLLEN indicator;
00132    va_list aq;
00133    struct custom_prepare_struct cps = { .sql = sql };
00134 
00135    va_copy(cps.ap, ap);
00136    va_copy(aq, ap);
00137 
00138    if (!table)
00139       return NULL;
00140 
00141    obj = ast_odbc_request_obj(database, 0);
00142 
00143    if (!obj) {
00144       ast_log(LOG_ERROR, "No database handle available with the name of '%s' (check res_odbc.conf)\n", database);
00145       return NULL;
00146    }
00147 
00148    newparam = va_arg(aq, const char *);
00149    if (!newparam) {
00150       ast_odbc_release_obj(obj);
00151       return NULL;
00152    }
00153    newval = va_arg(aq, const char *);
00154    op = !strchr(newparam, ' ') ? " =" : "";
00155    snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?%s", table, newparam, op,
00156       strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : "");
00157    while((newparam = va_arg(aq, const char *))) {
00158       op = !strchr(newparam, ' ') ? " =" : "";
00159       snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?%s", newparam, op,
00160          strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : "");
00161       newval = va_arg(aq, const char *);
00162    }
00163    va_end(aq);
00164 
00165    stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
00166 
00167    if (!stmt) {
00168       ast_odbc_release_obj(obj);
00169       return NULL;
00170    }
00171 
00172    res = SQLNumResultCols(stmt, &colcount);
00173    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00174       ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
00175       SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00176       ast_odbc_release_obj(obj);
00177       return NULL;
00178    }
00179 
00180    res = SQLFetch(stmt);
00181    if (res == SQL_NO_DATA) {
00182       SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00183       ast_odbc_release_obj(obj);
00184       return NULL;
00185    }
00186    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00187       ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
00188       SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00189       ast_odbc_release_obj(obj);
00190       return NULL;
00191    }
00192    for (x = 0; x < colcount; x++) {
00193       rowdata[0] = '\0';
00194       collen = sizeof(coltitle);
00195       res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen, 
00196                &datatype, &colsize, &decimaldigits, &nullable);
00197       if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00198          ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql);
00199          if (var)
00200             ast_variables_destroy(var);
00201          ast_odbc_release_obj(obj);
00202          return NULL;
00203       }
00204 
00205       indicator = 0;
00206       res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), &indicator);
00207       if (indicator == SQL_NULL_DATA)
00208          rowdata[0] = '\0';
00209       else if (ast_strlen_zero(rowdata)) {
00210          /* Because we encode the empty string for a NULL, we will encode
00211           * actual empty strings as a string containing a single whitespace. */
00212          ast_copy_string(rowdata, " ", sizeof(rowdata));
00213       }
00214 
00215       if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00216          ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
00217          if (var)
00218             ast_variables_destroy(var);
00219          ast_odbc_release_obj(obj);
00220          return NULL;
00221       }
00222       stringp = rowdata;
00223       while(stringp) {
00224          chunk = strsep(&stringp, ";");
00225          if (!ast_strlen_zero(ast_strip(chunk))) {
00226             if (prev) {
00227                prev->next = ast_variable_new(coltitle, chunk, "");
00228                if (prev->next)
00229                   prev = prev->next;
00230             } else 
00231                prev = var = ast_variable_new(coltitle, chunk, "");
00232          }
00233       }
00234    }
00235 
00236 
00237    SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00238    ast_odbc_release_obj(obj);
00239    return var;
00240 }

static int reload_module ( void   )  [static]

Definition at line 1070 of file res_config_odbc.c.

01071 {
01072    return 0;
01073 }

static int require_odbc ( const char *  database,
const char *  table,
va_list  ap 
) [static]

Definition at line 884 of file res_config_odbc.c.

References ast_log(), ast_odbc_find_table(), ast_rq_is_int(), AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CHECK_SIZE, odbc_cache_tables::columns, odbc_cache_columns::list, LOG_WARNING, odbc_cache_columns::name, RQ_CHAR, RQ_DATE, RQ_DATETIME, RQ_FLOAT, RQ_INTEGER1, RQ_INTEGER2, RQ_INTEGER3, RQ_INTEGER4, RQ_INTEGER8, RQ_UINTEGER1, RQ_UINTEGER2, RQ_UINTEGER3, RQ_UINTEGER4, RQ_UINTEGER8, odbc_cache_columns::size, odbc_cache_columns::type, type, warn_length, warn_type, and WARN_TYPE_OR_LENGTH.

00885 {
00886    struct odbc_cache_tables *tableptr = ast_odbc_find_table(database, table);
00887    struct odbc_cache_columns *col;
00888    char *elm;
00889    int type, size;
00890 
00891    if (!tableptr) {
00892       return -1;
00893    }
00894 
00895    while ((elm = va_arg(ap, char *))) {
00896       type = va_arg(ap, require_type);
00897       size = va_arg(ap, int);
00898       /* Check if the field matches the criteria */
00899       AST_RWLIST_TRAVERSE(&tableptr->columns, col, list) {
00900          if (strcmp(col->name, elm) == 0) {
00901             /* Type check, first.  Some fields are more particular than others */
00902             switch (col->type) {
00903             case SQL_CHAR:
00904             case SQL_VARCHAR:
00905             case SQL_LONGVARCHAR:
00906 #ifdef HAVE_ODBC_WCHAR
00907             case SQL_WCHAR:
00908             case SQL_WVARCHAR:
00909             case SQL_WLONGVARCHAR:
00910 #endif
00911             case SQL_BINARY:
00912             case SQL_VARBINARY:
00913             case SQL_LONGVARBINARY:
00914             case SQL_GUID:
00915 #define CHECK_SIZE(n) \
00916                   if (col->size < n) {      \
00917                      warn_length(col, n);  \
00918                   }                         \
00919                   break;
00920                switch (type) {
00921                case RQ_UINTEGER1: CHECK_SIZE(3)  /*         255 */
00922                case RQ_INTEGER1:  CHECK_SIZE(4)  /*        -128 */
00923                case RQ_UINTEGER2: CHECK_SIZE(5)  /*       65535 */
00924                case RQ_INTEGER2:  CHECK_SIZE(6)  /*      -32768 */
00925                case RQ_UINTEGER3:                /*    16777215 */
00926                case RQ_INTEGER3:  CHECK_SIZE(8)  /*    -8388608 */
00927                case RQ_DATE:                     /*  2008-06-09 */
00928                case RQ_UINTEGER4: CHECK_SIZE(10) /*  4200000000 */
00929                case RQ_INTEGER4:  CHECK_SIZE(11) /* -2100000000 */
00930                case RQ_DATETIME:                 /* 2008-06-09 16:03:47 */
00931                case RQ_UINTEGER8: CHECK_SIZE(19) /* trust me    */
00932                case RQ_INTEGER8:  CHECK_SIZE(20) /* ditto       */
00933                case RQ_FLOAT:
00934                case RQ_CHAR:      CHECK_SIZE(size)
00935                }
00936 #undef CHECK_SIZE
00937                break;
00938             case SQL_TYPE_DATE:
00939                if (type != RQ_DATE) {
00940                   warn_type(col, type);
00941                }
00942                break;
00943             case SQL_TYPE_TIMESTAMP:
00944             case SQL_TIMESTAMP:
00945                if (type != RQ_DATE && type != RQ_DATETIME) {
00946                   warn_type(col, type);
00947                }
00948                break;
00949             case SQL_BIT:
00950                warn_length(col, size);
00951                break;
00952 #define WARN_TYPE_OR_LENGTH(n)   \
00953                   if (!ast_rq_is_int(type)) {  \
00954                      warn_type(col, type);    \
00955                   } else {                     \
00956                      warn_length(col, n);  \
00957                   }
00958             case SQL_TINYINT:
00959                if (type != RQ_UINTEGER1) {
00960                   WARN_TYPE_OR_LENGTH(size)
00961                }
00962                break;
00963             case SQL_C_STINYINT:
00964                if (type != RQ_INTEGER1) {
00965                   WARN_TYPE_OR_LENGTH(size)
00966                }
00967                break;
00968             case SQL_C_USHORT:
00969                if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_UINTEGER2) {
00970                   WARN_TYPE_OR_LENGTH(size)
00971                }
00972                break;
00973             case SQL_SMALLINT:
00974             case SQL_C_SSHORT:
00975                if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_INTEGER2) {
00976                   WARN_TYPE_OR_LENGTH(size)
00977                }
00978                break;
00979             case SQL_C_ULONG:
00980                if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
00981                   type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
00982                   type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
00983                   type != RQ_INTEGER4) {
00984                   WARN_TYPE_OR_LENGTH(size)
00985                }
00986                break;
00987             case SQL_INTEGER:
00988             case SQL_C_SLONG:
00989                if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
00990                   type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
00991                   type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
00992                   type != RQ_INTEGER4) {
00993                   WARN_TYPE_OR_LENGTH(size)
00994                }
00995                break;
00996             case SQL_C_UBIGINT:
00997                if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
00998                   type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
00999                   type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
01000                   type != RQ_UINTEGER4 && type != RQ_INTEGER4 &&
01001                   type != RQ_INTEGER8) {
01002                   WARN_TYPE_OR_LENGTH(size)
01003                }
01004                break;
01005             case SQL_BIGINT:
01006             case SQL_C_SBIGINT:
01007                if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
01008                   type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
01009                   type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
01010                   type != RQ_UINTEGER4 && type != RQ_INTEGER4 &&
01011                   type != RQ_INTEGER8) {
01012                   WARN_TYPE_OR_LENGTH(size)
01013                }
01014                break;
01015 #undef WARN_TYPE_OR_LENGTH
01016             case SQL_NUMERIC:
01017             case SQL_DECIMAL:
01018             case SQL_FLOAT:
01019             case SQL_REAL:
01020             case SQL_DOUBLE:
01021                if (!ast_rq_is_int(type) && type != RQ_FLOAT) {
01022                   warn_type(col, type);
01023                }
01024                break;
01025             default:
01026                ast_log(LOG_WARNING, "Realtime table %s@%s: column type (%d) unrecognized for column '%s'\n", table, database, col->type, elm);
01027             }
01028             break;
01029          }
01030       }
01031       if (!col) {
01032          ast_log(LOG_WARNING, "Realtime table %s@%s requires column '%s', but that column does not exist!\n", table, database, elm);
01033       }
01034    }
01035    va_end(ap);
01036    AST_RWLIST_UNLOCK(&tableptr->columns);
01037    return 0;
01038 }

static int store_odbc ( const char *  database,
const char *  table,
va_list  ap 
) [static]

Excute an INSERT query.

Parameters:
database 
table 
ap list containing one or more field/value set(s)

Insert a new record into database table, prepare the sql statement. All values to be changed are stored in ap list. Sub-in the values to the prepared statement and execute it.

Return values:
number of rows affected
-1 on failure

Definition at line 633 of file res_config_odbc.c.

References custom_prepare_struct::ap, ast_copy_string(), ast_log(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj(), custom_prepare(), LOG_WARNING, and custom_prepare_struct::sql.

00634 {
00635    struct odbc_obj *obj;
00636    SQLHSTMT stmt;
00637    char sql[256];
00638    char keys[256];
00639    char vals[256];
00640    SQLLEN rowcount=0;
00641    const char *newparam, *newval;
00642    int res;
00643    va_list aq;
00644    struct custom_prepare_struct cps = { .sql = sql, .extra = NULL };
00645 
00646    va_copy(cps.ap, ap);
00647    va_copy(aq, ap);
00648    
00649    if (!table)
00650       return -1;
00651 
00652    obj = ast_odbc_request_obj(database, 0);
00653    if (!obj)
00654       return -1;
00655 
00656    newparam = va_arg(aq, const char *);
00657    if (!newparam)  {
00658       ast_odbc_release_obj(obj);
00659       return -1;
00660    }
00661    newval = va_arg(aq, const char *);
00662    snprintf(keys, sizeof(keys), "%s", newparam);
00663    ast_copy_string(vals, "?", sizeof(vals));
00664    while ((newparam = va_arg(aq, const char *))) {
00665       snprintf(keys + strlen(keys), sizeof(keys) - strlen(keys), ", %s", newparam);
00666       snprintf(vals + strlen(vals), sizeof(vals) - strlen(vals), ", ?");
00667       newval = va_arg(aq, const char *);
00668    }
00669    va_end(aq);
00670    snprintf(sql, sizeof(sql), "INSERT INTO %s (%s) VALUES (%s)", table, keys, vals);
00671 
00672    stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
00673 
00674    if (!stmt) {
00675       ast_odbc_release_obj(obj);
00676       return -1;
00677    }
00678 
00679    res = SQLRowCount(stmt, &rowcount);
00680    SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00681    ast_odbc_release_obj(obj);
00682 
00683    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00684       ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql);
00685       return -1;
00686    }
00687 
00688    if (rowcount >= 0)
00689       return (int)rowcount;
00690 
00691    return -1;
00692 }

static int unload_module ( void   )  [static]

Definition at line 1055 of file res_config_odbc.c.

References ast_config_engine_deregister(), and ast_verb.

01056 {
01057    ast_config_engine_deregister(&odbc_engine);
01058 
01059    ast_verb(1, "res_config_odbc unloaded.\n");
01060    return 0;
01061 }

static int update2_odbc ( const char *  database,
const char *  table,
va_list  ap 
) [static]

Execute an UPDATE query.

Parameters:
database 
table 
ap list containing one or more field/value set(s).

Update a database table, preparing the sql statement from a list of key/value pairs specified in ap. The lookup pairs are specified first and are separated from the update pairs by a sentinel value. Sub-in the values to the prepared statement and execute it.

Return values:
number of rows affected
-1 on failure

Definition at line 582 of file res_config_odbc.c.

References update2_prepare_struct::ap, ast_log(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj(), ast_str_buffer(), ast_str_thread_get(), update2_prepare_struct::database, LOG_WARNING, sql_buf, and update2_prepare().

00583 {
00584    struct odbc_obj *obj;
00585    SQLHSTMT stmt;
00586    struct update2_prepare_struct ups = { .database = database, .table = table, };
00587    struct ast_str *sql;
00588    int res;
00589    SQLLEN rowcount = 0;
00590 
00591    va_copy(ups.ap, ap);
00592 
00593    if (!(obj = ast_odbc_request_obj(database, 0))) {
00594       return -1;
00595    }
00596 
00597    if (!(stmt = ast_odbc_prepare_and_execute(obj, update2_prepare, &ups))) {
00598       ast_odbc_release_obj(obj);
00599       return -1;
00600    }
00601 
00602    res = SQLRowCount(stmt, &rowcount);
00603    SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00604    ast_odbc_release_obj(obj);
00605 
00606    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00607       /* Since only a single thread can access this memory, we can retrieve what would otherwise be lost. */
00608       sql = ast_str_thread_get(&sql_buf, 16);
00609       ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n", ast_str_buffer(sql));
00610       return -1;
00611    }
00612 
00613    if (rowcount >= 0) {
00614       return (int)rowcount;
00615    }
00616 
00617    return -1;
00618 }

static SQLHSTMT update2_prepare ( struct odbc_obj obj,
void *  data 
) [static]

Definition at line 485 of file res_config_odbc.c.

References update2_prepare_struct::ap, ast_log(), ast_odbc_find_column(), ast_odbc_find_table(), ast_odbc_release_table, ast_str_append(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), odbc_obj::con, update2_prepare_struct::database, first, LOG_ERROR, LOG_NOTICE, LOG_WARNING, sql_buf, and update2_prepare_struct::table.

Referenced by update2_odbc().

00486 {
00487    int res, x = 1, first = 1;
00488    struct update2_prepare_struct *ups = data;
00489    const char *newparam, *newval;
00490    struct ast_str *sql = ast_str_thread_get(&sql_buf, 16);
00491    SQLHSTMT stmt;
00492    va_list ap;
00493    struct odbc_cache_tables *tableptr = ast_odbc_find_table(ups->database, ups->table);
00494    struct odbc_cache_columns *column;
00495 
00496    if (!sql) {
00497       if (tableptr) {
00498          ast_odbc_release_table(tableptr);
00499       }
00500       return NULL;
00501    }
00502 
00503    if (!tableptr) {
00504       ast_log(LOG_ERROR, "Could not retrieve metadata for table '%s@%s'.  Update will fail!\n", ups->table, ups->database);
00505       return NULL;
00506    }
00507 
00508    res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
00509    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00510       ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
00511       ast_odbc_release_table(tableptr);
00512       return NULL;
00513    }
00514 
00515    ast_str_set(&sql, 0, "UPDATE %s SET ", ups->table);
00516 
00517    /* Start by finding the second set of parameters */
00518    va_copy(ap, ups->ap);
00519 
00520    while ((newparam = va_arg(ap, const char *))) {
00521       newval = va_arg(ap, const char *);
00522    }
00523 
00524    while ((newparam = va_arg(ap, const char *))) {
00525       newval = va_arg(ap, const char *);
00526       if ((column = ast_odbc_find_column(tableptr, newparam))) {
00527          ast_str_append(&sql, 0, "%s%s=? ", first ? "" : ", ", newparam);
00528          SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL);
00529          first = 0;
00530       } else {
00531          ast_log(LOG_NOTICE, "Not updating column '%s' in '%s@%s' because that column does not exist!\n", newparam, ups->table, ups->database);
00532       }
00533    }
00534    va_end(ap);
00535 
00536    /* Restart search, because we need to add the search parameters */
00537    va_copy(ap, ups->ap);
00538    ast_str_append(&sql, 0, "WHERE");
00539    first = 1;
00540 
00541    while ((newparam = va_arg(ap, const char *))) {
00542       newval = va_arg(ap, const char *);
00543       if (!(column = ast_odbc_find_column(tableptr, newparam))) {
00544          ast_log(LOG_ERROR, "One or more of the criteria columns '%s' on '%s@%s' for this update does not exist!\n", newparam, ups->table, ups->database);
00545          ast_odbc_release_table(tableptr);
00546          SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00547          return NULL;
00548       }
00549       ast_str_append(&sql, 0, "%s %s=?", first ? "" : " AND", newparam);
00550       SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL);
00551       first = 0;
00552    }
00553    va_end(ap);
00554 
00555    /* Done with the table metadata */
00556    ast_odbc_release_table(tableptr);
00557 
00558    res = SQLPrepare(stmt, (unsigned char *)ast_str_buffer(sql), SQL_NTS);
00559    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00560       ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", ast_str_buffer(sql));
00561       SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00562       return NULL;
00563    }
00564 
00565    return stmt;
00566 }

static int update_odbc ( const char *  database,
const char *  table,
const char *  keyfield,
const char *  lookup,
va_list  ap 
) [static]

Excute an UPDATE query.

Parameters:
database 
table 
keyfield where clause field
lookup value of field for where clause
ap list containing one or more field/value set(s).

Update a database table, prepare the sql statement using keyfield and lookup control the number of records to change. All values to be changed are stored in ap list. Sub-in the values to the prepared statement and execute it.

Return values:
number of rows affected
-1 on failure

Definition at line 404 of file res_config_odbc.c.

References custom_prepare_struct::ap, ast_log(), ast_odbc_find_column(), ast_odbc_find_table(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_release_table, ast_odbc_request_obj(), custom_prepare(), LOG_WARNING, custom_prepare_struct::skip, and custom_prepare_struct::sql.

00405 {
00406    struct odbc_obj *obj;
00407    SQLHSTMT stmt;
00408    char sql[256];
00409    SQLLEN rowcount=0;
00410    const char *newparam, *newval;
00411    int res, count = 1;
00412    va_list aq;
00413    struct custom_prepare_struct cps = { .sql = sql, .extra = lookup };
00414    struct odbc_cache_tables *tableptr = ast_odbc_find_table(database, table);
00415    struct odbc_cache_columns *column;
00416 
00417    va_copy(cps.ap, ap);
00418    va_copy(aq, ap);
00419    
00420    if (!table) {
00421       ast_odbc_release_table(tableptr);
00422       return -1;
00423    }
00424 
00425    obj = ast_odbc_request_obj(database, 0);
00426    if (!obj) {
00427       ast_odbc_release_table(tableptr);
00428       return -1;
00429    }
00430 
00431    newparam = va_arg(aq, const char *);
00432    if (!newparam)  {
00433       ast_odbc_release_obj(obj);
00434       ast_odbc_release_table(tableptr);
00435       return -1;
00436    }
00437    newval = va_arg(aq, const char *);
00438 
00439    if (tableptr && !(column = ast_odbc_find_column(tableptr, newparam))) {
00440       ast_log(LOG_WARNING, "Key field '%s' does not exist in table '%s@%s'.  Update will fail\n", newparam, table, database);
00441    }
00442 
00443    snprintf(sql, sizeof(sql), "UPDATE %s SET %s=?", table, newparam);
00444    while((newparam = va_arg(aq, const char *))) {
00445       newval = va_arg(aq, const char *);
00446       if ((tableptr && (column = ast_odbc_find_column(tableptr, newparam))) || count > 63) {
00447          snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s=?", newparam);
00448       } else { /* the column does not exist in the table */
00449          cps.skip |= (1LL << count);
00450       }
00451       count++;
00452    }
00453    va_end(aq);
00454    snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s=?", keyfield);
00455    ast_odbc_release_table(tableptr);
00456 
00457    stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
00458 
00459    if (!stmt) {
00460       ast_odbc_release_obj(obj);
00461       return -1;
00462    }
00463 
00464    res = SQLRowCount(stmt, &rowcount);
00465    SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00466    ast_odbc_release_obj(obj);
00467 
00468    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00469       ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql);
00470       return -1;
00471    }
00472 
00473    if (rowcount >= 0)
00474       return (int)rowcount;
00475 
00476    return -1;
00477 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "Realtime ODBC configuration" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload_module, } [static]

Definition at line 1079 of file res_config_odbc.c.

Definition at line 1079 of file res_config_odbc.c.

struct ast_config_engine odbc_engine [static]

Definition at line 1042 of file res_config_odbc.c.

struct ast_threadstorage sql_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_sql_buf , .custom_init = NULL , } [static]

Definition at line 48 of file res_config_odbc.c.

Referenced by update2_odbc(), and update2_prepare().


Generated by  doxygen 1.6.2