00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "asterisk.h"
00038
00039 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 129764 $")
00040
00041 #include "asterisk/file.h"
00042 #include "asterisk/channel.h"
00043 #include "asterisk/pbx.h"
00044 #include "asterisk/config.h"
00045 #include "asterisk/module.h"
00046 #include "asterisk/lock.h"
00047 #include "asterisk/res_odbc.h"
00048 #include "asterisk/utils.h"
00049
00050 struct custom_prepare_struct {
00051 const char *sql;
00052 const char *extra;
00053 va_list ap;
00054 };
00055
00056 static SQLHSTMT custom_prepare(struct odbc_obj *obj, void *data)
00057 {
00058 int res, x = 1;
00059 struct custom_prepare_struct *cps = data;
00060 const char *newparam, *newval;
00061 SQLHSTMT stmt;
00062 va_list ap;
00063
00064 va_copy(ap, cps->ap);
00065
00066 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
00067 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00068 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
00069 return NULL;
00070 }
00071
00072 res = SQLPrepare(stmt, (unsigned char *)cps->sql, SQL_NTS);
00073 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00074 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", cps->sql);
00075 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00076 return NULL;
00077 }
00078
00079 while ((newparam = va_arg(ap, const char *))) {
00080 newval = va_arg(ap, const char *);
00081 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL);
00082 }
00083 va_end(ap);
00084
00085 if (!ast_strlen_zero(cps->extra))
00086 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(cps->extra), 0, (void *)cps->extra, 0, NULL);
00087 return stmt;
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 static struct ast_variable *realtime_odbc(const char *database, const char *table, va_list ap)
00104 {
00105 struct odbc_obj *obj;
00106 SQLHSTMT stmt;
00107 char sql[1024];
00108 char coltitle[256];
00109 char rowdata[2048];
00110 char *op;
00111 const char *newparam, *newval;
00112 char *stringp;
00113 char *chunk;
00114 SQLSMALLINT collen;
00115 int res;
00116 int x;
00117 struct ast_variable *var=NULL, *prev=NULL;
00118 SQLULEN colsize;
00119 SQLSMALLINT colcount=0;
00120 SQLSMALLINT datatype;
00121 SQLSMALLINT decimaldigits;
00122 SQLSMALLINT nullable;
00123 SQLLEN indicator;
00124 va_list aq;
00125 struct custom_prepare_struct cps = { .sql = sql };
00126
00127 va_copy(cps.ap, ap);
00128 va_copy(aq, ap);
00129
00130 if (!table)
00131 return NULL;
00132
00133 obj = ast_odbc_request_obj(database, 0);
00134
00135 if (!obj) {
00136 ast_log(LOG_ERROR, "No database handle available with the name of '%s' (check res_odbc.conf)\n", database);
00137 return NULL;
00138 }
00139
00140 newparam = va_arg(aq, const char *);
00141 if (!newparam) {
00142 ast_odbc_release_obj(obj);
00143 return NULL;
00144 }
00145 newval = va_arg(aq, const char *);
00146 op = !strchr(newparam, ' ') ? " =" : "";
00147 snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?%s", table, newparam, op,
00148 strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : "");
00149 while((newparam = va_arg(aq, const char *))) {
00150 op = !strchr(newparam, ' ') ? " =" : "";
00151 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?%s", newparam, op,
00152 strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : "");
00153 newval = va_arg(aq, const char *);
00154 }
00155 va_end(aq);
00156
00157 stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
00158
00159 if (!stmt) {
00160 ast_odbc_release_obj(obj);
00161 return NULL;
00162 }
00163
00164 res = SQLNumResultCols(stmt, &colcount);
00165 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00166 ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
00167 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00168 ast_odbc_release_obj(obj);
00169 return NULL;
00170 }
00171
00172 res = SQLFetch(stmt);
00173 if (res == SQL_NO_DATA) {
00174 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00175 ast_odbc_release_obj(obj);
00176 return NULL;
00177 }
00178 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00179 ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
00180 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00181 ast_odbc_release_obj(obj);
00182 return NULL;
00183 }
00184 for (x = 0; x < colcount; x++) {
00185 rowdata[0] = '\0';
00186 collen = sizeof(coltitle);
00187 res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen,
00188 &datatype, &colsize, &decimaldigits, &nullable);
00189 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00190 ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql);
00191 if (var)
00192 ast_variables_destroy(var);
00193 ast_odbc_release_obj(obj);
00194 return NULL;
00195 }
00196
00197 indicator = 0;
00198 res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), &indicator);
00199 if (indicator == SQL_NULL_DATA)
00200 rowdata[0] = '\0';
00201 else if (ast_strlen_zero(rowdata)) {
00202
00203
00204 ast_copy_string(rowdata, " ", sizeof(rowdata));
00205 }
00206
00207 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00208 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
00209 if (var)
00210 ast_variables_destroy(var);
00211 ast_odbc_release_obj(obj);
00212 return NULL;
00213 }
00214 stringp = rowdata;
00215 while(stringp) {
00216 chunk = strsep(&stringp, ";");
00217 if (!ast_strlen_zero(ast_strip(chunk))) {
00218 if (prev) {
00219 prev->next = ast_variable_new(coltitle, chunk, "");
00220 if (prev->next)
00221 prev = prev->next;
00222 } else
00223 prev = var = ast_variable_new(coltitle, chunk, "");
00224 }
00225 }
00226 }
00227
00228
00229 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00230 ast_odbc_release_obj(obj);
00231 return var;
00232 }
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 static struct ast_config *realtime_multi_odbc(const char *database, const char *table, va_list ap)
00249 {
00250 struct odbc_obj *obj;
00251 SQLHSTMT stmt;
00252 char sql[1024];
00253 char coltitle[256];
00254 char rowdata[2048];
00255 const char *initfield=NULL;
00256 char *op;
00257 const char *newparam, *newval;
00258 char *stringp;
00259 char *chunk;
00260 SQLSMALLINT collen;
00261 int res;
00262 int x;
00263 struct ast_variable *var=NULL;
00264 struct ast_config *cfg=NULL;
00265 struct ast_category *cat=NULL;
00266 SQLULEN colsize;
00267 SQLSMALLINT colcount=0;
00268 SQLSMALLINT datatype;
00269 SQLSMALLINT decimaldigits;
00270 SQLSMALLINT nullable;
00271 SQLLEN indicator;
00272 struct custom_prepare_struct cps = { .sql = sql };
00273 va_list aq;
00274
00275 va_copy(cps.ap, ap);
00276 va_copy(aq, ap);
00277
00278 if (!table)
00279 return NULL;
00280
00281 obj = ast_odbc_request_obj(database, 0);
00282 if (!obj)
00283 return NULL;
00284
00285 newparam = va_arg(aq, const char *);
00286 if (!newparam) {
00287 ast_odbc_release_obj(obj);
00288 return NULL;
00289 }
00290 initfield = ast_strdupa(newparam);
00291 if ((op = strchr(initfield, ' ')))
00292 *op = '\0';
00293 newval = va_arg(aq, const char *);
00294 op = !strchr(newparam, ' ') ? " =" : "";
00295 snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?%s", table, newparam, op,
00296 strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : "");
00297 while((newparam = va_arg(aq, const char *))) {
00298 op = !strchr(newparam, ' ') ? " =" : "";
00299 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?%s", newparam, op,
00300 strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : "");
00301 newval = va_arg(aq, const char *);
00302 }
00303 if (initfield)
00304 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield);
00305 va_end(aq);
00306
00307 stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
00308
00309 if (!stmt) {
00310 ast_odbc_release_obj(obj);
00311 return NULL;
00312 }
00313
00314 res = SQLNumResultCols(stmt, &colcount);
00315 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00316 ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
00317 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00318 ast_odbc_release_obj(obj);
00319 return NULL;
00320 }
00321
00322 cfg = ast_config_new();
00323 if (!cfg) {
00324 ast_log(LOG_WARNING, "Out of memory!\n");
00325 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00326 ast_odbc_release_obj(obj);
00327 return NULL;
00328 }
00329
00330 while ((res=SQLFetch(stmt)) != SQL_NO_DATA) {
00331 var = NULL;
00332 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00333 ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
00334 continue;
00335 }
00336 cat = ast_category_new("","",99999);
00337 if (!cat) {
00338 ast_log(LOG_WARNING, "Out of memory!\n");
00339 continue;
00340 }
00341 for (x=0;x<colcount;x++) {
00342 rowdata[0] = '\0';
00343 collen = sizeof(coltitle);
00344 res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen,
00345 &datatype, &colsize, &decimaldigits, &nullable);
00346 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00347 ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql);
00348 ast_category_destroy(cat);
00349 continue;
00350 }
00351
00352 indicator = 0;
00353 res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), &indicator);
00354 if (indicator == SQL_NULL_DATA)
00355 continue;
00356
00357 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00358 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
00359 ast_category_destroy(cat);
00360 continue;
00361 }
00362 stringp = rowdata;
00363 while(stringp) {
00364 chunk = strsep(&stringp, ";");
00365 if (!ast_strlen_zero(ast_strip(chunk))) {
00366 if (initfield && !strcmp(initfield, coltitle))
00367 ast_category_rename(cat, chunk);
00368 var = ast_variable_new(coltitle, chunk, "");
00369 ast_variable_append(cat, var);
00370 }
00371 }
00372 }
00373 ast_category_append(cfg, cat);
00374 }
00375
00376 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00377 ast_odbc_release_obj(obj);
00378 return cfg;
00379 }
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396 static int update_odbc(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)
00397 {
00398 struct odbc_obj *obj;
00399 SQLHSTMT stmt;
00400 char sql[256];
00401 SQLLEN rowcount=0;
00402 const char *newparam, *newval;
00403 int res;
00404 va_list aq;
00405 struct custom_prepare_struct cps = { .sql = sql, .extra = lookup };
00406
00407 va_copy(cps.ap, ap);
00408 va_copy(aq, ap);
00409
00410 if (!table)
00411 return -1;
00412
00413 obj = ast_odbc_request_obj(database, 0);
00414 if (!obj)
00415 return -1;
00416
00417 newparam = va_arg(aq, const char *);
00418 if (!newparam) {
00419 ast_odbc_release_obj(obj);
00420 return -1;
00421 }
00422 newval = va_arg(aq, const char *);
00423 snprintf(sql, sizeof(sql), "UPDATE %s SET %s=?", table, newparam);
00424 while((newparam = va_arg(aq, const char *))) {
00425 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s=?", newparam);
00426 newval = va_arg(aq, const char *);
00427 }
00428 va_end(aq);
00429 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s=?", keyfield);
00430
00431 stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
00432
00433 if (!stmt) {
00434 ast_odbc_release_obj(obj);
00435 return -1;
00436 }
00437
00438 res = SQLRowCount(stmt, &rowcount);
00439 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00440 ast_odbc_release_obj(obj);
00441
00442 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00443 ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql);
00444 return -1;
00445 }
00446
00447 if (rowcount >= 0)
00448 return (int)rowcount;
00449
00450 return -1;
00451 }
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 static int store_odbc(const char *database, const char *table, va_list ap)
00467 {
00468 struct odbc_obj *obj;
00469 SQLHSTMT stmt;
00470 char sql[256];
00471 char keys[256];
00472 char vals[256];
00473 SQLLEN rowcount=0;
00474 const char *newparam, *newval;
00475 int res;
00476 va_list aq;
00477 struct custom_prepare_struct cps = { .sql = sql, .extra = NULL };
00478
00479 va_copy(cps.ap, ap);
00480 va_copy(aq, ap);
00481
00482 if (!table)
00483 return -1;
00484
00485 obj = ast_odbc_request_obj(database, 0);
00486 if (!obj)
00487 return -1;
00488
00489 newparam = va_arg(aq, const char *);
00490 if (!newparam) {
00491 ast_odbc_release_obj(obj);
00492 return -1;
00493 }
00494 newval = va_arg(aq, const char *);
00495 snprintf(keys, sizeof(keys), "%s", newparam);
00496 ast_copy_string(vals, "?", sizeof(vals));
00497 while ((newparam = va_arg(aq, const char *))) {
00498 snprintf(keys + strlen(keys), sizeof(keys) - strlen(keys), ", %s", newparam);
00499 snprintf(vals + strlen(vals), sizeof(vals) - strlen(vals), ", ?");
00500 newval = va_arg(aq, const char *);
00501 }
00502 va_end(aq);
00503 snprintf(sql, sizeof(sql), "INSERT INTO %s (%s) VALUES (%s)", table, keys, vals);
00504
00505 stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
00506
00507 if (!stmt) {
00508 ast_odbc_release_obj(obj);
00509 return -1;
00510 }
00511
00512 res = SQLRowCount(stmt, &rowcount);
00513 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00514 ast_odbc_release_obj(obj);
00515
00516 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00517 ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql);
00518 return -1;
00519 }
00520
00521 if (rowcount >= 0)
00522 return (int)rowcount;
00523
00524 return -1;
00525 }
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542 static int destroy_odbc(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)
00543 {
00544 struct odbc_obj *obj;
00545 SQLHSTMT stmt;
00546 char sql[256];
00547 SQLLEN rowcount=0;
00548 const char *newparam, *newval;
00549 int res;
00550 va_list aq;
00551 struct custom_prepare_struct cps = { .sql = sql, .extra = lookup };
00552
00553 va_copy(cps.ap, ap);
00554 va_copy(aq, ap);
00555
00556 if (!table)
00557 return -1;
00558
00559 obj = ast_odbc_request_obj(database, 0);
00560 if (!obj)
00561 return -1;
00562
00563 snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE ", table);
00564 while((newparam = va_arg(aq, const char *))) {
00565 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=? AND ", newparam);
00566 newval = va_arg(aq, const char *);
00567 }
00568 va_end(aq);
00569 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=?", keyfield);
00570
00571 stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
00572
00573 if (!stmt) {
00574 ast_odbc_release_obj(obj);
00575 return -1;
00576 }
00577
00578 res = SQLRowCount(stmt, &rowcount);
00579 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00580 ast_odbc_release_obj(obj);
00581
00582 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00583 ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql);
00584 return -1;
00585 }
00586
00587 if (rowcount >= 0)
00588 return (int)rowcount;
00589
00590 return -1;
00591 }
00592
00593
00594 struct config_odbc_obj {
00595 char *sql;
00596 unsigned long cat_metric;
00597 char category[128];
00598 char var_name[128];
00599 char var_val[1024];
00600 SQLLEN err;
00601 };
00602
00603 static SQLHSTMT config_odbc_prepare(struct odbc_obj *obj, void *data)
00604 {
00605 struct config_odbc_obj *q = data;
00606 SQLHSTMT sth;
00607 int res;
00608
00609 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &sth);
00610 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00611 ast_verb(4, "Failure in AllocStatement %d\n", res);
00612 return NULL;
00613 }
00614
00615 res = SQLPrepare(sth, (unsigned char *)q->sql, SQL_NTS);
00616 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00617 ast_verb(4, "Error in PREPARE %d\n", res);
00618 SQLFreeHandle(SQL_HANDLE_STMT, sth);
00619 return NULL;
00620 }
00621
00622 SQLBindCol(sth, 1, SQL_C_ULONG, &q->cat_metric, sizeof(q->cat_metric), &q->err);
00623 SQLBindCol(sth, 2, SQL_C_CHAR, q->category, sizeof(q->category), &q->err);
00624 SQLBindCol(sth, 3, SQL_C_CHAR, q->var_name, sizeof(q->var_name), &q->err);
00625 SQLBindCol(sth, 4, SQL_C_CHAR, q->var_val, sizeof(q->var_val), &q->err);
00626
00627 return sth;
00628 }
00629
00630 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)
00631 {
00632 struct ast_variable *new_v;
00633 struct ast_category *cur_cat;
00634 int res = 0;
00635 struct odbc_obj *obj;
00636 char sqlbuf[1024] = "";
00637 char *sql = sqlbuf;
00638 size_t sqlleft = sizeof(sqlbuf);
00639 unsigned int last_cat_metric = 0;
00640 SQLSMALLINT rowcount = 0;
00641 SQLHSTMT stmt;
00642 char last[128] = "";
00643 struct config_odbc_obj q;
00644 struct ast_flags loader_flags = { 0 };
00645
00646 memset(&q, 0, sizeof(q));
00647
00648 if (!file || !strcmp (file, "res_config_odbc.conf"))
00649 return NULL;
00650
00651 obj = ast_odbc_request_obj(database, 0);
00652 if (!obj)
00653 return NULL;
00654
00655 ast_build_string(&sql, &sqlleft, "SELECT cat_metric, category, var_name, var_val FROM %s ", table);
00656 ast_build_string(&sql, &sqlleft, "WHERE filename='%s' AND commented=0 ", file);
00657 ast_build_string(&sql, &sqlleft, "ORDER BY cat_metric DESC, var_metric ASC, category, var_name ");
00658 q.sql = sqlbuf;
00659
00660 stmt = ast_odbc_prepare_and_execute(obj, config_odbc_prepare, &q);
00661
00662 if (!stmt) {
00663 ast_log(LOG_WARNING, "SQL select error!\n[%s]\n\n", sql);
00664 ast_odbc_release_obj(obj);
00665 return NULL;
00666 }
00667
00668 res = SQLNumResultCols(stmt, &rowcount);
00669
00670 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00671 ast_log(LOG_WARNING, "SQL NumResultCols error!\n[%s]\n\n", sql);
00672 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00673 ast_odbc_release_obj(obj);
00674 return NULL;
00675 }
00676
00677 if (!rowcount) {
00678 ast_log(LOG_NOTICE, "found nothing\n");
00679 ast_odbc_release_obj(obj);
00680 return cfg;
00681 }
00682
00683 cur_cat = ast_config_get_current_category(cfg);
00684
00685 while ((res = SQLFetch(stmt)) != SQL_NO_DATA) {
00686 if (!strcmp (q.var_name, "#include")) {
00687 if (!ast_config_internal_load(q.var_val, cfg, loader_flags, "", who_asked)) {
00688 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00689 ast_odbc_release_obj(obj);
00690 return NULL;
00691 }
00692 continue;
00693 }
00694 if (strcmp(last, q.category) || last_cat_metric != q.cat_metric) {
00695 cur_cat = ast_category_new(q.category, "", 99999);
00696 if (!cur_cat) {
00697 ast_log(LOG_WARNING, "Out of memory!\n");
00698 break;
00699 }
00700 strcpy(last, q.category);
00701 last_cat_metric = q.cat_metric;
00702 ast_category_append(cfg, cur_cat);
00703 }
00704
00705 new_v = ast_variable_new(q.var_name, q.var_val, "");
00706 ast_variable_append(cur_cat, new_v);
00707 }
00708
00709 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00710 ast_odbc_release_obj(obj);
00711 return cfg;
00712 }
00713
00714 static struct ast_config_engine odbc_engine = {
00715 .name = "odbc",
00716 .load_func = config_odbc,
00717 .realtime_func = realtime_odbc,
00718 .realtime_multi_func = realtime_multi_odbc,
00719 .store_func = store_odbc,
00720 .destroy_func = destroy_odbc,
00721 .update_func = update_odbc
00722 };
00723
00724 static int unload_module (void)
00725 {
00726 ast_config_engine_deregister(&odbc_engine);
00727 ast_verb(1, "res_config_odbc unloaded.\n");
00728 return 0;
00729 }
00730
00731 static int load_module (void)
00732 {
00733 ast_config_engine_register(&odbc_engine);
00734 ast_verb(1, "res_config_odbc loaded.\n");
00735 return 0;
00736 }
00737
00738 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Realtime ODBC configuration",
00739 .load = load_module,
00740 .unload = unload_module,
00741 );