#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 |
Anthony Minessale II <anthmct@yahoo.com>
Definition in file res_config_odbc.c.
#define CHECK_SIZE | ( | n | ) |
#define WARN_TYPE_OR_LENGTH | ( | n | ) |
Value:
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 932 of file res_config_odbc.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 932 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] |
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_prepare(), last, LOG_NOTICE, and LOG_WARNING.
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) |
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 916 of file res_config_odbc.c.
References ast_config_engine_register(), ast_verb, and odbc_engine.
00917 { 00918 ast_config_engine_register(&odbc_engine); 00919 ast_verb(1, "res_config_odbc loaded.\n"); 00920 return 0; 00921 }
static struct ast_config* realtime_multi_odbc | ( | const char * | database, | |
const char * | table, | |||
va_list | ap | |||
) | [static] |
Excute an Select query and return ast_config list.
database | ||
table | ||
ap | list containing one or more field/operator/value set. |
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] |
Excute an SQL query and return ast_variable list.
database | ||
table | ||
ap | list containing one or more field/operator/value set. |
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] |
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_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.
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_BINARY: 00766 case SQL_VARBINARY: 00767 case SQL_LONGVARBINARY: 00768 case SQL_GUID: 00769 #define CHECK_SIZE(n) \ 00770 if (col->size < n) { \ 00771 warn_length(col, n); \ 00772 } \ 00773 break; 00774 switch (type) { 00775 case RQ_UINTEGER1: CHECK_SIZE(3) /* 255 */ 00776 case RQ_INTEGER1: CHECK_SIZE(4) /* -128 */ 00777 case RQ_UINTEGER2: CHECK_SIZE(5) /* 65535 */ 00778 case RQ_INTEGER2: CHECK_SIZE(6) /* -32768 */ 00779 case RQ_UINTEGER3: /* 16777215 */ 00780 case RQ_INTEGER3: CHECK_SIZE(8) /* -8388608 */ 00781 case RQ_DATE: /* 2008-06-09 */ 00782 case RQ_UINTEGER4: CHECK_SIZE(10) /* 4200000000 */ 00783 case RQ_INTEGER4: CHECK_SIZE(11) /* -2100000000 */ 00784 case RQ_DATETIME: /* 2008-06-09 16:03:47 */ 00785 case RQ_UINTEGER8: CHECK_SIZE(19) /* trust me */ 00786 case RQ_INTEGER8: CHECK_SIZE(20) /* ditto */ 00787 case RQ_FLOAT: 00788 case RQ_CHAR: CHECK_SIZE(size) 00789 } 00790 #undef CHECK_SIZE 00791 break; 00792 case SQL_TYPE_DATE: 00793 if (type != RQ_DATE) { 00794 warn_type(col, type); 00795 } 00796 break; 00797 case SQL_TYPE_TIMESTAMP: 00798 case SQL_TIMESTAMP: 00799 if (type != RQ_DATE && type != RQ_DATETIME) { 00800 warn_type(col, type); 00801 } 00802 break; 00803 case SQL_BIT: 00804 warn_length(col, size); 00805 break; 00806 #define WARN_TYPE_OR_LENGTH(n) \ 00807 if (!ast_rq_is_int(type)) { \ 00808 warn_type(col, type); \ 00809 } else { \ 00810 warn_length(col, n); \ 00811 } 00812 case SQL_TINYINT: 00813 if (type != RQ_UINTEGER1) { 00814 WARN_TYPE_OR_LENGTH(size) 00815 } 00816 break; 00817 case SQL_C_STINYINT: 00818 if (type != RQ_INTEGER1) { 00819 WARN_TYPE_OR_LENGTH(size) 00820 } 00821 break; 00822 case SQL_C_USHORT: 00823 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_UINTEGER2) { 00824 WARN_TYPE_OR_LENGTH(size) 00825 } 00826 break; 00827 case SQL_SMALLINT: 00828 case SQL_C_SSHORT: 00829 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_INTEGER2) { 00830 WARN_TYPE_OR_LENGTH(size) 00831 } 00832 break; 00833 case SQL_C_ULONG: 00834 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && 00835 type != RQ_UINTEGER2 && type != RQ_INTEGER2 && 00836 type != RQ_UINTEGER3 && type != RQ_INTEGER3 && 00837 type != RQ_INTEGER4) { 00838 WARN_TYPE_OR_LENGTH(size) 00839 } 00840 break; 00841 case SQL_INTEGER: 00842 case SQL_C_SLONG: 00843 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && 00844 type != RQ_UINTEGER2 && type != RQ_INTEGER2 && 00845 type != RQ_UINTEGER3 && type != RQ_INTEGER3 && 00846 type != RQ_UINTEGER4) { 00847 WARN_TYPE_OR_LENGTH(size) 00848 } 00849 break; 00850 case SQL_C_UBIGINT: 00851 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && 00852 type != RQ_UINTEGER2 && type != RQ_INTEGER2 && 00853 type != RQ_UINTEGER3 && type != RQ_INTEGER3 && 00854 type != RQ_UINTEGER4 && type != RQ_INTEGER4 && 00855 type != RQ_INTEGER8) { 00856 WARN_TYPE_OR_LENGTH(size) 00857 } 00858 break; 00859 case SQL_BIGINT: 00860 case SQL_C_SBIGINT: 00861 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && 00862 type != RQ_UINTEGER2 && type != RQ_INTEGER2 && 00863 type != RQ_UINTEGER3 && type != RQ_INTEGER3 && 00864 type != RQ_UINTEGER4 && type != RQ_INTEGER4 && 00865 type != RQ_UINTEGER8) { 00866 WARN_TYPE_OR_LENGTH(size) 00867 } 00868 break; 00869 #undef WARN_TYPE_OR_LENGTH 00870 case SQL_NUMERIC: 00871 case SQL_DECIMAL: 00872 case SQL_FLOAT: 00873 case SQL_REAL: 00874 case SQL_DOUBLE: 00875 if (!ast_rq_is_int(type) && type != RQ_FLOAT) { 00876 warn_type(col, type); 00877 } 00878 break; 00879 default: 00880 ast_log(LOG_WARNING, "Realtime table %s@%s: column type (%d) unrecognized for column '%s'\n", table, database, col->type, elm); 00881 } 00882 break; 00883 } 00884 } 00885 if (!col) { 00886 ast_log(LOG_WARNING, "Realtime table %s@%s requires column '%s', but that column does not exist!\n", table, database, elm); 00887 } 00888 } 00889 va_end(ap); 00890 AST_RWLIST_UNLOCK(&tableptr->columns); 00891 return 0; 00892 }
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) |
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 908 of file res_config_odbc.c.
References ast_config_engine_deregister(), ast_verb, and odbc_engine.
00909 { 00910 ast_config_engine_deregister(&odbc_engine); 00911 00912 ast_verb(1, "res_config_odbc unloaded.\n"); 00913 return 0; 00914 }
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). |
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 932 of file res_config_odbc.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 932 of file res_config_odbc.c.
struct ast_config_engine odbc_engine [static] |