Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:00:53 2007

Asterisk developer's documentation :: Codename Pineapple


res_config_odbc.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * Copyright (C) 2004 - 2005 Anthony Minessale II <anthmct@yahoo.com>
00009  *
00010  * See http://www.asterisk.org for more information about
00011  * the Asterisk project. Please do not directly contact
00012  * any of the maintainers of this project for assistance;
00013  * the project provides a web site, mailing lists and IRC
00014  * channels for your use.
00015  *
00016  * This program is free software, distributed under the terms of
00017  * the GNU General Public License Version 2. See the LICENSE file
00018  * at the top of the source tree.
00019  */
00020 
00021 /*! \file
00022  *
00023  * \brief odbc+odbc plugin for portable configuration engine
00024  *
00025  * \author Mark Spencer <markster@digium.com>
00026  * \author Anthony Minessale II <anthmct@yahoo.com>
00027  *
00028  * \arg http://www.unixodbc.org
00029  */
00030 
00031 /*** MODULEINFO
00032    <depend>unixodbc</depend>
00033  ***/
00034 
00035 #include "asterisk.h"
00036 
00037 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 49808 $")
00038 
00039 #include <stdio.h>
00040 #include <stdlib.h>
00041 #include <unistd.h>
00042 #include <string.h>
00043 
00044 #include "asterisk/file.h"
00045 #include "asterisk/logger.h"
00046 #include "asterisk/channel.h"
00047 #include "asterisk/pbx.h"
00048 #include "asterisk/config.h"
00049 #include "asterisk/module.h"
00050 #include "asterisk/lock.h"
00051 #include "asterisk/options.h"
00052 #include "asterisk/res_odbc.h"
00053 #include "asterisk/utils.h"
00054 
00055 static struct ast_variable *realtime_odbc(const char *database, const char *table, va_list ap)
00056 {
00057    struct odbc_obj *obj;
00058    SQLHSTMT stmt;
00059    char sql[1024];
00060    char coltitle[256];
00061    char rowdata[2048];
00062    char *op;
00063    const char *newparam, *newval;
00064    char *stringp;
00065    char *chunk;
00066    SQLSMALLINT collen;
00067    int res;
00068    int x;
00069    struct ast_variable *var=NULL, *prev=NULL;
00070    SQLULEN colsize;
00071    SQLSMALLINT colcount=0;
00072    SQLSMALLINT datatype;
00073    SQLSMALLINT decimaldigits;
00074    SQLSMALLINT nullable;
00075    SQLLEN indicator;
00076    va_list aq;
00077    
00078    va_copy(aq, ap);
00079    
00080    
00081    if (!table)
00082       return NULL;
00083 
00084    obj = ast_odbc_request_obj(database, 0);
00085    if (!obj)
00086       return NULL;
00087 
00088    res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt);
00089    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00090       ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
00091       ast_odbc_release_obj(obj);
00092       return NULL;
00093    }
00094 
00095    newparam = va_arg(aq, const char *);
00096    if (!newparam)  {
00097       SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00098       ast_odbc_release_obj(obj);
00099       return NULL;
00100    }
00101    newval = va_arg(aq, const char *);
00102    if (!strchr(newparam, ' ')) op = " ="; else op = "";
00103    snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?", table, newparam, op);
00104    while((newparam = va_arg(aq, const char *))) {
00105       if (!strchr(newparam, ' ')) op = " ="; else op = "";
00106       snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?", newparam, op);
00107       newval = va_arg(aq, const char *);
00108    }
00109    va_end(aq);
00110    res = SQLPrepare(stmt, (unsigned char *)sql, SQL_NTS);
00111    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00112       ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
00113       SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00114       ast_odbc_release_obj(obj);
00115       return NULL;
00116    }
00117    
00118    /* Now bind the parameters */
00119    x = 1;
00120 
00121    while((newparam = va_arg(ap, const char *))) {
00122       newval = va_arg(ap, const char *);
00123       SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL);
00124    }
00125    
00126    res = ast_odbc_smart_execute(obj, stmt);
00127 
00128    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00129       ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
00130       SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00131       ast_odbc_release_obj(obj);
00132       return NULL;
00133    }
00134 
00135    res = SQLNumResultCols(stmt, &colcount);
00136    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00137       ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
00138       SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00139       ast_odbc_release_obj(obj);
00140       return NULL;
00141    }
00142 
00143    res = SQLFetch(stmt);
00144    if (res == SQL_NO_DATA) {
00145       SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00146       ast_odbc_release_obj(obj);
00147                 return NULL;
00148    }
00149    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00150       ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
00151       SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00152       ast_odbc_release_obj(obj);
00153       return NULL;
00154    }
00155    for (x = 0; x < colcount; x++) {
00156       rowdata[0] = '\0';
00157       collen = sizeof(coltitle);
00158       res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen, 
00159                &datatype, &colsize, &decimaldigits, &nullable);
00160       if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00161          ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql);
00162          if (var)
00163             ast_variables_destroy(var);
00164          ast_odbc_release_obj(obj);
00165          return NULL;
00166       }
00167 
00168       indicator = 0;
00169       res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), &indicator);
00170       if (indicator == SQL_NULL_DATA)
00171          rowdata[0] = '\0';
00172       else if (ast_strlen_zero(rowdata)) {
00173          /* Because we encode the empty string for a NULL, we will encode
00174           * actual empty strings as a string containing a single whitespace. */
00175          ast_copy_string(rowdata, " ", sizeof(rowdata));
00176       }
00177 
00178       if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00179          ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
00180          if (var)
00181             ast_variables_destroy(var);
00182          ast_odbc_release_obj(obj);
00183          return NULL;
00184       }
00185       stringp = rowdata;
00186       while(stringp) {
00187          chunk = strsep(&stringp, ";");
00188          if (prev) {
00189             prev->next = ast_variable_new(coltitle, chunk);
00190             if (prev->next)
00191                prev = prev->next;
00192          } else 
00193             prev = var = ast_variable_new(coltitle, chunk);
00194       }
00195    }
00196 
00197 
00198    SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00199    ast_odbc_release_obj(obj);
00200    return var;
00201 }
00202 
00203 static struct ast_config *realtime_multi_odbc(const char *database, const char *table, va_list ap)
00204 {
00205    struct odbc_obj *obj;
00206    SQLHSTMT stmt;
00207    char sql[1024];
00208    char coltitle[256];
00209    char rowdata[2048];
00210    const char *initfield=NULL;
00211    char *op;
00212    const char *newparam, *newval;
00213    char *stringp;
00214    char *chunk;
00215    SQLSMALLINT collen;
00216    int res;
00217    int x;
00218    struct ast_variable *var=NULL;
00219    struct ast_config *cfg=NULL;
00220    struct ast_category *cat=NULL;
00221    struct ast_realloca ra;
00222    SQLULEN colsize;
00223    SQLSMALLINT colcount=0;
00224    SQLSMALLINT datatype;
00225    SQLSMALLINT decimaldigits;
00226    SQLSMALLINT nullable;
00227    SQLLEN indicator;
00228 
00229    va_list aq;
00230    va_copy(aq, ap);
00231    
00232    
00233    if (!table)
00234       return NULL;
00235    memset(&ra, 0, sizeof(ra));
00236 
00237    obj = ast_odbc_request_obj(database, 0);
00238    if (!obj)
00239       return NULL;
00240 
00241    res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt);
00242    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00243       ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
00244       ast_odbc_release_obj(obj);
00245       return NULL;
00246    }
00247 
00248    newparam = va_arg(aq, const char *);
00249    if (!newparam)  {
00250       SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00251       ast_odbc_release_obj(obj);
00252       return NULL;
00253    }
00254    initfield = ast_strdupa(newparam);
00255    if ((op = strchr(initfield, ' '))) 
00256       *op = '\0';
00257    newval = va_arg(aq, const char *);
00258    if (!strchr(newparam, ' ')) op = " ="; else op = "";
00259    snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?", table, newparam, op);
00260    while((newparam = va_arg(aq, const char *))) {
00261       if (!strchr(newparam, ' ')) op = " ="; else op = "";
00262       snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?", newparam, op);
00263       newval = va_arg(aq, const char *);
00264    }
00265    if (initfield)
00266       snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield);
00267    va_end(aq);
00268    res = SQLPrepare(stmt, (unsigned char *)sql, SQL_NTS);
00269    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00270       ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
00271       SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00272       ast_odbc_release_obj(obj);
00273       return NULL;
00274    }
00275    
00276    /* Now bind the parameters */
00277    x = 1;
00278 
00279    while((newparam = va_arg(ap, const char *))) {
00280       newval = va_arg(ap, const char *);
00281       SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL);
00282    }
00283       
00284    res = ast_odbc_smart_execute(obj, stmt);
00285 
00286    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00287       ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
00288       SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00289       ast_odbc_release_obj(obj);
00290       return NULL;
00291    }
00292 
00293    res = SQLNumResultCols(stmt, &colcount);
00294    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00295       ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
00296       SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00297       ast_odbc_release_obj(obj);
00298       return NULL;
00299    }
00300 
00301    cfg = ast_config_new();
00302    if (!cfg) {
00303       ast_log(LOG_WARNING, "Out of memory!\n");
00304       SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00305       ast_odbc_release_obj(obj);
00306       return NULL;
00307    }
00308 
00309    while ((res=SQLFetch(stmt)) != SQL_NO_DATA) {
00310       var = NULL;
00311       if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00312          ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
00313          continue;
00314       }
00315       cat = ast_category_new("");
00316       if (!cat) {
00317          ast_log(LOG_WARNING, "Out of memory!\n");
00318          continue;
00319       }
00320       for (x=0;x<colcount;x++) {
00321          rowdata[0] = '\0';
00322          collen = sizeof(coltitle);
00323          res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen, 
00324                   &datatype, &colsize, &decimaldigits, &nullable);
00325          if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00326             ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql);
00327             ast_category_destroy(cat);
00328             continue;
00329          }
00330 
00331          indicator = 0;
00332          res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), &indicator);
00333          if (indicator == SQL_NULL_DATA)
00334             continue;
00335 
00336          if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00337             ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
00338             ast_category_destroy(cat);
00339             continue;
00340          }
00341          stringp = rowdata;
00342          while(stringp) {
00343             chunk = strsep(&stringp, ";");
00344             if (!ast_strlen_zero(ast_strip(chunk))) {
00345                if (initfield && !strcmp(initfield, coltitle))
00346                   ast_category_rename(cat, chunk);
00347                var = ast_variable_new(coltitle, chunk);
00348                ast_variable_append(cat, var);
00349             }
00350          }
00351       }
00352       ast_category_append(cfg, cat);
00353    }
00354 
00355    SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00356    ast_odbc_release_obj(obj);
00357    return cfg;
00358 }
00359 
00360 static int update_odbc(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)
00361 {
00362    struct odbc_obj *obj;
00363    SQLHSTMT stmt;
00364    char sql[256];
00365    SQLLEN rowcount=0;
00366    const char *newparam, *newval;
00367    int res;
00368    int x;
00369    va_list aq;
00370    
00371    va_copy(aq, ap);
00372    
00373    if (!table)
00374       return -1;
00375 
00376    obj = ast_odbc_request_obj(database, 0);
00377    if (!obj)
00378       return -1;
00379 
00380    res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt);
00381    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00382       ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
00383       ast_odbc_release_obj(obj);
00384       return -1;
00385    }
00386 
00387    newparam = va_arg(aq, const char *);
00388    if (!newparam)  {
00389       SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00390       ast_odbc_release_obj(obj);
00391       return -1;
00392    }
00393    newval = va_arg(aq, const char *);
00394    snprintf(sql, sizeof(sql), "UPDATE %s SET %s=?", table, newparam);
00395    while((newparam = va_arg(aq, const char *))) {
00396       snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s=?", newparam);
00397       newval = va_arg(aq, const char *);
00398    }
00399    va_end(aq);
00400    snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s=?", keyfield);
00401    
00402    res = SQLPrepare(stmt, (unsigned char *)sql, SQL_NTS);
00403    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00404       ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
00405       SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00406       ast_odbc_release_obj(obj);
00407       return -1;
00408    }
00409    
00410    /* Now bind the parameters */
00411    x = 1;
00412 
00413    while((newparam = va_arg(ap, const char *))) {
00414       newval = va_arg(ap, const char *);
00415       SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL);
00416    }
00417       
00418    SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(lookup), 0, (void *)lookup, 0, NULL);
00419 
00420    res = ast_odbc_smart_execute(obj, stmt);
00421 
00422    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00423       ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
00424       SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00425       ast_odbc_release_obj(obj);
00426       return -1;
00427    }
00428 
00429    res = SQLRowCount(stmt, &rowcount);
00430    SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00431    ast_odbc_release_obj(obj);
00432 
00433    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00434       ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql);
00435       return -1;
00436    }
00437 
00438    if (rowcount >= 0)
00439       return (int)rowcount;
00440 
00441    return -1;
00442 }
00443 
00444 struct config_odbc_obj {
00445    char *sql;
00446    unsigned long id;
00447    unsigned long cat_metric;
00448    unsigned long var_metric;
00449    unsigned long commented;
00450    char filename[128];
00451    char category[128];
00452    char var_name[128];
00453    char var_val[1024]; /* changed from 128 to 1024 via bug 8251 */
00454    SQLLEN err;
00455 };
00456 
00457 static SQLHSTMT config_odbc_prepare(struct odbc_obj *obj, void *data)
00458 {
00459    struct config_odbc_obj *q = data;
00460    SQLHSTMT sth;
00461    int res;
00462 
00463    res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &sth);
00464    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00465       if (option_verbose > 3)
00466          ast_verbose( VERBOSE_PREFIX_4 "Failure in AllocStatement %d\n", res);
00467       return NULL;
00468    }
00469 
00470    res = SQLPrepare(sth, (unsigned char *)q->sql, SQL_NTS);
00471    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00472       if (option_verbose > 3)
00473          ast_verbose( VERBOSE_PREFIX_4 "Error in PREPARE %d\n", res);
00474       SQLFreeHandle(SQL_HANDLE_STMT, sth);
00475       return NULL;
00476    }
00477 
00478    SQLBindCol(sth, 1, SQL_C_ULONG, &q->id, sizeof(q->id), &q->err);
00479    SQLBindCol(sth, 2, SQL_C_ULONG, &q->cat_metric, sizeof(q->cat_metric), &q->err);
00480    SQLBindCol(sth, 3, SQL_C_ULONG, &q->var_metric, sizeof(q->var_metric), &q->err);
00481    SQLBindCol(sth, 4, SQL_C_ULONG, &q->commented, sizeof(q->commented), &q->err);
00482    SQLBindCol(sth, 5, SQL_C_CHAR, q->filename, sizeof(q->filename), &q->err);
00483    SQLBindCol(sth, 6, SQL_C_CHAR, q->category, sizeof(q->category), &q->err);
00484    SQLBindCol(sth, 7, SQL_C_CHAR, q->var_name, sizeof(q->var_name), &q->err);
00485    SQLBindCol(sth, 8, SQL_C_CHAR, q->var_val, sizeof(q->var_val), &q->err);
00486 
00487    return sth;
00488 }
00489 
00490 static struct ast_config *config_odbc(const char *database, const char *table, const char *file, struct ast_config *cfg, int withcomments)
00491 {
00492    struct ast_variable *new_v;
00493    struct ast_category *cur_cat;
00494    int res = 0;
00495    struct odbc_obj *obj;
00496    char sql[255] = "";
00497    unsigned int last_cat_metric = 0;
00498    SQLSMALLINT rowcount=0;
00499    SQLHSTMT stmt;
00500    char last[128] = "";
00501    struct config_odbc_obj q;
00502 
00503    memset(&q, 0, sizeof(q));
00504 
00505    if (!file || !strcmp (file, "res_config_odbc.conf"))
00506       return NULL;      /* cant configure myself with myself ! */
00507 
00508    obj = ast_odbc_request_obj(database, 0);
00509    if (!obj)
00510       return NULL;
00511 
00512    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);
00513    q.sql = sql;
00514 
00515    stmt = ast_odbc_prepare_and_execute(obj, config_odbc_prepare, &q);
00516 
00517    if (!stmt) {
00518       ast_log(LOG_WARNING, "SQL select error!\n[%s]\n\n", sql);
00519       ast_odbc_release_obj(obj);
00520       return NULL;
00521    }
00522 
00523    res = SQLNumResultCols(stmt, &rowcount);
00524 
00525    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00526       ast_log(LOG_WARNING, "SQL NumResultCols error!\n[%s]\n\n", sql);
00527       SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00528       ast_odbc_release_obj(obj);
00529       return NULL;
00530    }
00531 
00532    if (!rowcount) {
00533       ast_log(LOG_NOTICE, "found nothing\n");
00534       ast_odbc_release_obj(obj);
00535       return cfg;
00536    }
00537 
00538    cur_cat = ast_config_get_current_category(cfg);
00539 
00540    while ((res = SQLFetch(stmt)) != SQL_NO_DATA) {
00541       if (!strcmp (q.var_name, "#include")) {
00542          if (!ast_config_internal_load(q.var_val, cfg, 0)) {
00543             SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00544             ast_odbc_release_obj(obj);
00545             return NULL;
00546          }
00547          continue;
00548       } 
00549       if (strcmp(last, q.category) || last_cat_metric != q.cat_metric) {
00550          cur_cat = ast_category_new(q.category);
00551          if (!cur_cat) {
00552             ast_log(LOG_WARNING, "Out of memory!\n");
00553             break;
00554          }
00555          strcpy(last, q.category);
00556          last_cat_metric   = q.cat_metric;
00557          ast_category_append(cfg, cur_cat);
00558       }
00559 
00560       new_v = ast_variable_new(q.var_name, q.var_val);
00561       ast_variable_append(cur_cat, new_v);
00562    }
00563 
00564    SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00565    ast_odbc_release_obj(obj);
00566    return cfg;
00567 }
00568 
00569 static struct ast_config_engine odbc_engine = {
00570    .name = "odbc",
00571    .load_func = config_odbc,
00572    .realtime_func = realtime_odbc,
00573    .realtime_multi_func = realtime_multi_odbc,
00574    .update_func = update_odbc
00575 };
00576 
00577 static int unload_module (void)
00578 {
00579    ast_module_user_hangup_all();
00580    ast_config_engine_deregister(&odbc_engine);
00581    if (option_verbose)
00582       ast_verbose("res_config_odbc unloaded.\n");
00583    return 0;
00584 }
00585 
00586 static int load_module (void)
00587 {
00588    ast_config_engine_register(&odbc_engine);
00589    if (option_verbose)
00590       ast_verbose("res_config_odbc loaded.\n");
00591    return 0;
00592 }
00593 
00594 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "ODBC Configuration",
00595       .load = load_module,
00596       .unload = unload_module,
00597       );

Asterisk is a trademark for Digium, inc.. | Edvina.net | Asterisk.org | This documentation was generated with Doxygen