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"
Go to the source code of this file.
Data Structures | |
| struct | config_odbc_obj |
| struct | custom_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 | __reg_module (void) |
| static void | __unreg_module (void) |
| 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 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_config * | realtime_multi_odbc (const char *database, const char *table, va_list ap) |
| Excute an Select query and return ast_config list. | |
| static struct ast_variable * | realtime_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 | 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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload_module, } |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct ast_config_engine | odbc_engine |
odbc+odbc plugin for portable configuration engine
Definition in file res_config_odbc.c.
| #define CHECK_SIZE | ( | n | ) |
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 740 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 741 of file res_config_odbc.c.
Referenced by require_odbc().
| #define WARN_TYPE_OR_LENGTH | ( | n | ) |
if (!ast_rq_is_int(type)) { \ warn_type(col, type); \ } else { \ warn_length(col, n); \ }
Referenced by require_odbc().
| static void __reg_module | ( | void | ) | [static] |
Definition at line 935 of file res_config_odbc.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 935 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 656 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.
00657 { 00658 struct ast_variable *new_v; 00659 struct ast_category *cur_cat; 00660 int res = 0; 00661 struct odbc_obj *obj; 00662 char sqlbuf[1024] = ""; 00663 char *sql = sqlbuf; 00664 size_t sqlleft = sizeof(sqlbuf); 00665 unsigned int last_cat_metric = 0; 00666 SQLSMALLINT rowcount = 0; 00667 SQLHSTMT stmt; 00668 char last[128] = ""; 00669 struct config_odbc_obj q; 00670 struct ast_flags loader_flags = { 0 }; 00671 00672 memset(&q, 0, sizeof(q)); 00673 00674 if (!file || !strcmp (file, "res_config_odbc.conf")) 00675 return NULL; /* cant configure myself with myself ! */ 00676 00677 obj = ast_odbc_request_obj(database, 0); 00678 if (!obj) 00679 return NULL; 00680 00681 ast_build_string(&sql, &sqlleft, "SELECT cat_metric, category, var_name, var_val FROM %s ", table); 00682 ast_build_string(&sql, &sqlleft, "WHERE filename='%s' AND commented=0 ", file); 00683 ast_build_string(&sql, &sqlleft, "ORDER BY cat_metric DESC, var_metric ASC, category, var_name "); 00684 q.sql = sqlbuf; 00685 00686 stmt = ast_odbc_prepare_and_execute(obj, config_odbc_prepare, &q); 00687 00688 if (!stmt) { 00689 ast_log(LOG_WARNING, "SQL select error!\n[%s]\n\n", sql); 00690 ast_odbc_release_obj(obj); 00691 return NULL; 00692 } 00693 00694 res = SQLNumResultCols(stmt, &rowcount); 00695 00696 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00697 ast_log(LOG_WARNING, "SQL NumResultCols error!\n[%s]\n\n", sql); 00698 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00699 ast_odbc_release_obj(obj); 00700 return NULL; 00701 } 00702 00703 if (!rowcount) { 00704 ast_log(LOG_NOTICE, "found nothing\n"); 00705 ast_odbc_release_obj(obj); 00706 return cfg; 00707 } 00708 00709 cur_cat = ast_config_get_current_category(cfg); 00710 00711 while ((res = SQLFetch(stmt)) != SQL_NO_DATA) { 00712 if (!strcmp (q.var_name, "#include")) { 00713 if (!ast_config_internal_load(q.var_val, cfg, loader_flags, "", who_asked)) { 00714 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00715 ast_odbc_release_obj(obj); 00716 return NULL; 00717 } 00718 continue; 00719 } 00720 if (strcmp(last, q.category) || last_cat_metric != q.cat_metric) { 00721 cur_cat = ast_category_new(q.category, "", 99999); 00722 if (!cur_cat) { 00723 ast_log(LOG_WARNING, "Out of memory!\n"); 00724 break; 00725 } 00726 strcpy(last, q.category); 00727 last_cat_metric = q.cat_metric; 00728 ast_category_append(cfg, cur_cat); 00729 } 00730 00731 new_v = ast_variable_new(q.var_name, q.var_val, ""); 00732 ast_variable_append(cur_cat, new_v); 00733 } 00734 00735 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00736 ast_odbc_release_obj(obj); 00737 return cfg; 00738 }
| static SQLHSTMT config_odbc_prepare | ( | struct odbc_obj * | obj, | |
| void * | data | |||
| ) | [static] |
Definition at line 629 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().
00630 { 00631 struct config_odbc_obj *q = data; 00632 SQLHSTMT sth; 00633 int res; 00634 00635 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &sth); 00636 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00637 ast_verb(4, "Failure in AllocStatement %d\n", res); 00638 return NULL; 00639 } 00640 00641 res = SQLPrepare(sth, (unsigned char *)q->sql, SQL_NTS); 00642 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00643 ast_verb(4, "Error in PREPARE %d\n", res); 00644 SQLFreeHandle(SQL_HANDLE_STMT, sth); 00645 return NULL; 00646 } 00647 00648 SQLBindCol(sth, 1, SQL_C_ULONG, &q->cat_metric, sizeof(q->cat_metric), &q->err); 00649 SQLBindCol(sth, 2, SQL_C_CHAR, q->category, sizeof(q->category), &q->err); 00650 SQLBindCol(sth, 3, SQL_C_CHAR, q->var_name, sizeof(q->var_name), &q->err); 00651 SQLBindCol(sth, 4, SQL_C_CHAR, q->var_val, sizeof(q->var_val), &q->err); 00652 00653 return sth; 00654 }
| 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.
| 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.
| number | of rows affected | |
| -1 | on failure |
Definition at line 568 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.
00569 { 00570 struct odbc_obj *obj; 00571 SQLHSTMT stmt; 00572 char sql[256]; 00573 SQLLEN rowcount=0; 00574 const char *newparam, *newval; 00575 int res; 00576 va_list aq; 00577 struct custom_prepare_struct cps = { .sql = sql, .extra = lookup }; 00578 00579 va_copy(cps.ap, ap); 00580 va_copy(aq, ap); 00581 00582 if (!table) 00583 return -1; 00584 00585 obj = ast_odbc_request_obj(database, 0); 00586 if (!obj) 00587 return -1; 00588 00589 snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE ", table); 00590 while((newparam = va_arg(aq, const char *))) { 00591 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=? AND ", newparam); 00592 newval = va_arg(aq, const char *); 00593 } 00594 va_end(aq); 00595 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=?", keyfield); 00596 00597 stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps); 00598 00599 if (!stmt) { 00600 ast_odbc_release_obj(obj); 00601 return -1; 00602 } 00603 00604 res = SQLRowCount(stmt, &rowcount); 00605 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00606 ast_odbc_release_obj(obj); 00607 00608 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00609 ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql); 00610 return -1; 00611 } 00612 00613 if (rowcount >= 0) 00614 return (int)rowcount; 00615 00616 return -1; 00617 }
| static int load_module | ( | void | ) | [static] |
Definition at line 919 of file res_config_odbc.c.
References ast_config_engine_register(), and ast_verb.
00920 { 00921 ast_config_engine_register(&odbc_engine); 00922 ast_verb(1, "res_config_odbc loaded.\n"); 00923 return 0; 00924 }
| 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.
| 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.
| 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_strdupa, ast_strip(), ast_strlen_zero(), ast_variable_append(), ast_variable_new(), custom_prepare(), LOG_WARNING, custom_prepare_struct::sql, strcasestr(), strsep(), 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.
| 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.
| 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, strcasestr(), strsep(), 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 926 of file res_config_odbc.c.
| static int require_odbc | ( | const char * | database, | |
| const char * | table, | |||
| va_list | ap | |||
| ) | [static] |
Definition at line 743 of file res_config_odbc.c.
References ast_log(), ast_odbc_find_table(), 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.
00744 { 00745 struct odbc_cache_tables *tableptr = ast_odbc_find_table(database, table); 00746 struct odbc_cache_columns *col; 00747 char *elm; 00748 int type, size; 00749 00750 if (!tableptr) { 00751 return -1; 00752 } 00753 00754 while ((elm = va_arg(ap, char *))) { 00755 type = va_arg(ap, require_type); 00756 size = va_arg(ap, int); 00757 /* Check if the field matches the criteria */ 00758 AST_RWLIST_TRAVERSE(&tableptr->columns, col, list) { 00759 if (strcmp(col->name, elm) == 0) { 00760 /* Type check, first. Some fields are more particular than others */ 00761 switch (col->type) { 00762 case SQL_CHAR: 00763 case SQL_VARCHAR: 00764 case SQL_LONGVARCHAR: 00765 case SQL_WCHAR: 00766 case SQL_WVARCHAR: 00767 case SQL_WLONGVARCHAR: 00768 case SQL_BINARY: 00769 case SQL_VARBINARY: 00770 case SQL_LONGVARBINARY: 00771 case SQL_GUID: 00772 #define CHECK_SIZE(n) \ 00773 if (col->size < n) { \ 00774 warn_length(col, n); \ 00775 } \ 00776 break; 00777 switch (type) { 00778 case RQ_UINTEGER1: CHECK_SIZE(3) /* 255 */ 00779 case RQ_INTEGER1: CHECK_SIZE(4) /* -128 */ 00780 case RQ_UINTEGER2: CHECK_SIZE(5) /* 65535 */ 00781 case RQ_INTEGER2: CHECK_SIZE(6) /* -32768 */ 00782 case RQ_UINTEGER3: /* 16777215 */ 00783 case RQ_INTEGER3: CHECK_SIZE(8) /* -8388608 */ 00784 case RQ_DATE: /* 2008-06-09 */ 00785 case RQ_UINTEGER4: CHECK_SIZE(10) /* 4200000000 */ 00786 case RQ_INTEGER4: CHECK_SIZE(11) /* -2100000000 */ 00787 case RQ_DATETIME: /* 2008-06-09 16:03:47 */ 00788 case RQ_UINTEGER8: CHECK_SIZE(19) /* trust me */ 00789 case RQ_INTEGER8: CHECK_SIZE(20) /* ditto */ 00790 case RQ_FLOAT: 00791 case RQ_CHAR: CHECK_SIZE(size) 00792 } 00793 #undef CHECK_SIZE 00794 break; 00795 case SQL_TYPE_DATE: 00796 if (type != RQ_DATE) { 00797 warn_type(col, type); 00798 } 00799 break; 00800 case SQL_TYPE_TIMESTAMP: 00801 case SQL_TIMESTAMP: 00802 if (type != RQ_DATE && type != RQ_DATETIME) { 00803 warn_type(col, type); 00804 } 00805 break; 00806 case SQL_BIT: 00807 warn_length(col, size); 00808 break; 00809 #define WARN_TYPE_OR_LENGTH(n) \ 00810 if (!ast_rq_is_int(type)) { \ 00811 warn_type(col, type); \ 00812 } else { \ 00813 warn_length(col, n); \ 00814 } 00815 case SQL_TINYINT: 00816 if (type != RQ_UINTEGER1) { 00817 WARN_TYPE_OR_LENGTH(size) 00818 } 00819 break; 00820 case SQL_C_STINYINT: 00821 if (type != RQ_INTEGER1) { 00822 WARN_TYPE_OR_LENGTH(size) 00823 } 00824 break; 00825 case SQL_C_USHORT: 00826 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_UINTEGER2) { 00827 WARN_TYPE_OR_LENGTH(size) 00828 } 00829 break; 00830 case SQL_SMALLINT: 00831 case SQL_C_SSHORT: 00832 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_INTEGER2) { 00833 WARN_TYPE_OR_LENGTH(size) 00834 } 00835 break; 00836 case SQL_C_ULONG: 00837 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && 00838 type != RQ_UINTEGER2 && type != RQ_INTEGER2 && 00839 type != RQ_UINTEGER3 && type != RQ_INTEGER3 && 00840 type != RQ_INTEGER4) { 00841 WARN_TYPE_OR_LENGTH(size) 00842 } 00843 break; 00844 case SQL_INTEGER: 00845 case SQL_C_SLONG: 00846 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && 00847 type != RQ_UINTEGER2 && type != RQ_INTEGER2 && 00848 type != RQ_UINTEGER3 && type != RQ_INTEGER3 && 00849 type != RQ_INTEGER4) { 00850 WARN_TYPE_OR_LENGTH(size) 00851 } 00852 break; 00853 case SQL_C_UBIGINT: 00854 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && 00855 type != RQ_UINTEGER2 && type != RQ_INTEGER2 && 00856 type != RQ_UINTEGER3 && type != RQ_INTEGER3 && 00857 type != RQ_UINTEGER4 && type != RQ_INTEGER4 && 00858 type != RQ_INTEGER8) { 00859 WARN_TYPE_OR_LENGTH(size) 00860 } 00861 break; 00862 case SQL_BIGINT: 00863 case SQL_C_SBIGINT: 00864 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && 00865 type != RQ_UINTEGER2 && type != RQ_INTEGER2 && 00866 type != RQ_UINTEGER3 && type != RQ_INTEGER3 && 00867 type != RQ_UINTEGER4 && type != RQ_INTEGER4 && 00868 type != RQ_INTEGER8) { 00869 WARN_TYPE_OR_LENGTH(size) 00870 } 00871 break; 00872 #undef WARN_TYPE_OR_LENGTH 00873 case SQL_NUMERIC: 00874 case SQL_DECIMAL: 00875 case SQL_FLOAT: 00876 case SQL_REAL: 00877 case SQL_DOUBLE: 00878 if (!ast_rq_is_int(type) && type != RQ_FLOAT) { 00879 warn_type(col, type); 00880 } 00881 break; 00882 default: 00883 ast_log(LOG_WARNING, "Realtime table %s@%s: column type (%d) unrecognized for column '%s'\n", table, database, col->type, elm); 00884 } 00885 break; 00886 } 00887 } 00888 if (!col) { 00889 ast_log(LOG_WARNING, "Realtime table %s@%s requires column '%s', but that column does not exist!\n", table, database, elm); 00890 } 00891 } 00892 va_end(ap); 00893 AST_RWLIST_UNLOCK(&tableptr->columns); 00894 return 0; 00895 }
| static int store_odbc | ( | const char * | database, | |
| const char * | table, | |||
| va_list | ap | |||
| ) | [static] |
Excute an INSERT query.
| 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.
| number | of rows affected | |
| -1 | on failure |
Definition at line 492 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.
00493 { 00494 struct odbc_obj *obj; 00495 SQLHSTMT stmt; 00496 char sql[256]; 00497 char keys[256]; 00498 char vals[256]; 00499 SQLLEN rowcount=0; 00500 const char *newparam, *newval; 00501 int res; 00502 va_list aq; 00503 struct custom_prepare_struct cps = { .sql = sql, .extra = NULL }; 00504 00505 va_copy(cps.ap, ap); 00506 va_copy(aq, ap); 00507 00508 if (!table) 00509 return -1; 00510 00511 obj = ast_odbc_request_obj(database, 0); 00512 if (!obj) 00513 return -1; 00514 00515 newparam = va_arg(aq, const char *); 00516 if (!newparam) { 00517 ast_odbc_release_obj(obj); 00518 return -1; 00519 } 00520 newval = va_arg(aq, const char *); 00521 snprintf(keys, sizeof(keys), "%s", newparam); 00522 ast_copy_string(vals, "?", sizeof(vals)); 00523 while ((newparam = va_arg(aq, const char *))) { 00524 snprintf(keys + strlen(keys), sizeof(keys) - strlen(keys), ", %s", newparam); 00525 snprintf(vals + strlen(vals), sizeof(vals) - strlen(vals), ", ?"); 00526 newval = va_arg(aq, const char *); 00527 } 00528 va_end(aq); 00529 snprintf(sql, sizeof(sql), "INSERT INTO %s (%s) VALUES (%s)", table, keys, vals); 00530 00531 stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps); 00532 00533 if (!stmt) { 00534 ast_odbc_release_obj(obj); 00535 return -1; 00536 } 00537 00538 res = SQLRowCount(stmt, &rowcount); 00539 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00540 ast_odbc_release_obj(obj); 00541 00542 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00543 ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql); 00544 return -1; 00545 } 00546 00547 if (rowcount >= 0) 00548 return (int)rowcount; 00549 00550 return -1; 00551 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 911 of file res_config_odbc.c.
References ast_config_engine_deregister(), and ast_verb.
00912 { 00913 ast_config_engine_deregister(&odbc_engine); 00914 00915 ast_verb(1, "res_config_odbc unloaded.\n"); 00916 return 0; 00917 }
| static int update_odbc | ( | const char * | database, | |
| const char * | table, | |||
| const char * | keyfield, | |||
| const char * | lookup, | |||
| va_list | ap | |||
| ) | [static] |
Excute an UPDATE query.
| 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.
| 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 }
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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload_module, } [static] |
Definition at line 935 of file res_config_odbc.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 935 of file res_config_odbc.c.
struct ast_config_engine odbc_engine [static] |
Definition at line 899 of file res_config_odbc.c.
1.6.1