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 |
| struct | update2_prepare_struct |
Defines | |
| #define | CHECK_SIZE(n) |
| #define | warn_length(col, size) ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' is not long enough to contain realtime data (needs %d)\n", table, database, col->name, size) |
| #define | warn_type(col, type) ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' is of the incorrect type (%d) to contain the required realtime data\n", table, database, col->name, col->type) |
| #define | WARN_TYPE_OR_LENGTH(n) |
Functions | |
| static void | __init_sql_buf (void) |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| static struct ast_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 | update2_odbc (const char *database, const char *table, va_list ap) |
| Execute an UPDATE query. | |
| static SQLHSTMT | update2_prepare (struct odbc_obj *obj, void *data) |
| static int | update_odbc (const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap) |
| Excute an UPDATE query. | |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "Realtime ODBC configuration" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload_module, } |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct ast_config_engine | odbc_engine |
| static struct ast_threadstorage | sql_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_sql_buf , .custom_init = NULL , } |
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 881 of file res_config_odbc.c.
Referenced by require_odbc().
| #define warn_type | ( | col, | |||
| type | ) | ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' is of the incorrect type (%d) to contain the required realtime data\n", table, database, col->name, col->type) |
Definition at line 882 of file res_config_odbc.c.
Referenced by require_odbc().
| #define WARN_TYPE_OR_LENGTH | ( | n | ) |
if (!ast_rq_is_int(type)) { \ warn_type(col, type); \ } else { \ warn_length(col, n); \ }
Referenced by require_odbc().
| static void __init_sql_buf | ( | void | ) | [static] |
Definition at line 48 of file res_config_odbc.c.
| static void __reg_module | ( | void | ) | [static] |
Definition at line 1079 of file res_config_odbc.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 1079 of file res_config_odbc.c.
| static struct ast_config* config_odbc | ( | const char * | database, | |
| const char * | table, | |||
| const char * | file, | |||
| struct ast_config * | cfg, | |||
| struct ast_flags | flags, | |||
| const char * | sugg_incl, | |||
| const char * | who_asked | |||
| ) | [static, read] |
Definition at line 797 of file res_config_odbc.c.
References ast_build_string(), ast_category_append(), ast_category_new(), ast_config_get_current_category(), ast_config_internal_load(), ast_log(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj(), ast_variable_append(), ast_variable_new(), config_odbc_obj::cat_metric, config_odbc_obj::category, config_odbc_prepare(), last, LOG_NOTICE, LOG_WARNING, config_odbc_obj::sql, config_odbc_obj::var_name, and config_odbc_obj::var_val.
00798 { 00799 struct ast_variable *new_v; 00800 struct ast_category *cur_cat; 00801 int res = 0; 00802 struct odbc_obj *obj; 00803 char sqlbuf[1024] = ""; 00804 char *sql = sqlbuf; 00805 size_t sqlleft = sizeof(sqlbuf); 00806 unsigned int last_cat_metric = 0; 00807 SQLSMALLINT rowcount = 0; 00808 SQLHSTMT stmt; 00809 char last[128] = ""; 00810 struct config_odbc_obj q; 00811 struct ast_flags loader_flags = { 0 }; 00812 00813 memset(&q, 0, sizeof(q)); 00814 00815 if (!file || !strcmp (file, "res_config_odbc.conf")) 00816 return NULL; /* cant configure myself with myself ! */ 00817 00818 obj = ast_odbc_request_obj(database, 0); 00819 if (!obj) 00820 return NULL; 00821 00822 ast_build_string(&sql, &sqlleft, "SELECT cat_metric, category, var_name, var_val FROM %s ", table); 00823 ast_build_string(&sql, &sqlleft, "WHERE filename='%s' AND commented=0 ", file); 00824 ast_build_string(&sql, &sqlleft, "ORDER BY cat_metric DESC, var_metric ASC, category, var_name "); 00825 q.sql = sqlbuf; 00826 00827 stmt = ast_odbc_prepare_and_execute(obj, config_odbc_prepare, &q); 00828 00829 if (!stmt) { 00830 ast_log(LOG_WARNING, "SQL select error!\n[%s]\n\n", sql); 00831 ast_odbc_release_obj(obj); 00832 return NULL; 00833 } 00834 00835 res = SQLNumResultCols(stmt, &rowcount); 00836 00837 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00838 ast_log(LOG_WARNING, "SQL NumResultCols error!\n[%s]\n\n", sql); 00839 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00840 ast_odbc_release_obj(obj); 00841 return NULL; 00842 } 00843 00844 if (!rowcount) { 00845 ast_log(LOG_NOTICE, "found nothing\n"); 00846 ast_odbc_release_obj(obj); 00847 return cfg; 00848 } 00849 00850 cur_cat = ast_config_get_current_category(cfg); 00851 00852 while ((res = SQLFetch(stmt)) != SQL_NO_DATA) { 00853 if (!strcmp (q.var_name, "#include")) { 00854 if (!ast_config_internal_load(q.var_val, cfg, loader_flags, "", who_asked)) { 00855 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00856 ast_odbc_release_obj(obj); 00857 return NULL; 00858 } 00859 continue; 00860 } 00861 if (strcmp(last, q.category) || last_cat_metric != q.cat_metric) { 00862 cur_cat = ast_category_new(q.category, "", 99999); 00863 if (!cur_cat) { 00864 ast_log(LOG_WARNING, "Out of memory!\n"); 00865 break; 00866 } 00867 strcpy(last, q.category); 00868 last_cat_metric = q.cat_metric; 00869 ast_category_append(cfg, cur_cat); 00870 } 00871 00872 new_v = ast_variable_new(q.var_name, q.var_val, ""); 00873 ast_variable_append(cur_cat, new_v); 00874 } 00875 00876 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00877 ast_odbc_release_obj(obj); 00878 return cfg; 00879 }
| static SQLHSTMT config_odbc_prepare | ( | struct odbc_obj * | obj, | |
| void * | data | |||
| ) | [static] |
Definition at line 770 of file res_config_odbc.c.
References ast_verb, config_odbc_obj::cat_metric, config_odbc_obj::category, odbc_obj::con, config_odbc_obj::err, config_odbc_obj::sql, config_odbc_obj::var_name, and config_odbc_obj::var_val.
Referenced by config_odbc().
00771 { 00772 struct config_odbc_obj *q = data; 00773 SQLHSTMT sth; 00774 int res; 00775 00776 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &sth); 00777 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00778 ast_verb(4, "Failure in AllocStatement %d\n", res); 00779 return NULL; 00780 } 00781 00782 res = SQLPrepare(sth, (unsigned char *)q->sql, SQL_NTS); 00783 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00784 ast_verb(4, "Error in PREPARE %d\n", res); 00785 SQLFreeHandle(SQL_HANDLE_STMT, sth); 00786 return NULL; 00787 } 00788 00789 SQLBindCol(sth, 1, SQL_C_ULONG, &q->cat_metric, sizeof(q->cat_metric), &q->err); 00790 SQLBindCol(sth, 2, SQL_C_CHAR, q->category, sizeof(q->category), &q->err); 00791 SQLBindCol(sth, 3, SQL_C_CHAR, q->var_name, sizeof(q->var_name), &q->err); 00792 SQLBindCol(sth, 4, SQL_C_CHAR, q->var_val, sizeof(q->var_val), &q->err); 00793 00794 return sth; 00795 }
| static SQLHSTMT custom_prepare | ( | struct odbc_obj * | obj, | |
| void * | data | |||
| ) | [static] |
Definition at line 57 of file res_config_odbc.c.
References custom_prepare_struct::ap, ast_debug, ast_log(), ast_strlen_zero(), odbc_obj::con, custom_prepare_struct::extra, LOG_WARNING, custom_prepare_struct::skip, and custom_prepare_struct::sql.
Referenced by destroy_odbc(), realtime_multi_odbc(), realtime_odbc(), store_odbc(), and update_odbc().
00058 { 00059 int res, x = 1, count = 0; 00060 struct custom_prepare_struct *cps = data; 00061 const char *newparam, *newval; 00062 SQLHSTMT stmt; 00063 va_list ap; 00064 00065 va_copy(ap, cps->ap); 00066 00067 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt); 00068 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00069 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n"); 00070 return NULL; 00071 } 00072 00073 ast_debug(1, "Skip: %lld; SQL: %s\n", cps->skip, cps->sql); 00074 00075 res = SQLPrepare(stmt, (unsigned char *)cps->sql, SQL_NTS); 00076 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00077 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", cps->sql); 00078 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00079 return NULL; 00080 } 00081 00082 while ((newparam = va_arg(ap, const char *))) { 00083 newval = va_arg(ap, const char *); 00084 if ((1LL << count++) & cps->skip) { 00085 ast_debug(1, "Skipping field '%s'='%s' (%llo/%llo)\n", newparam, newval, 1LL << (count - 1), cps->skip); 00086 continue; 00087 } 00088 ast_debug(1, "Parameter %d ('%s') = '%s'\n", x, newparam, newval); 00089 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL); 00090 } 00091 va_end(ap); 00092 00093 if (!ast_strlen_zero(cps->extra)) 00094 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(cps->extra), 0, (void *)cps->extra, 0, NULL); 00095 return stmt; 00096 }
| static int destroy_odbc | ( | const char * | database, | |
| const char * | table, | |||
| const char * | keyfield, | |||
| const char * | lookup, | |||
| va_list | ap | |||
| ) | [static] |
Excute an DELETE query.
| 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 709 of file res_config_odbc.c.
References custom_prepare_struct::ap, ast_log(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj(), custom_prepare(), LOG_WARNING, and custom_prepare_struct::sql.
00710 { 00711 struct odbc_obj *obj; 00712 SQLHSTMT stmt; 00713 char sql[256]; 00714 SQLLEN rowcount=0; 00715 const char *newparam, *newval; 00716 int res; 00717 va_list aq; 00718 struct custom_prepare_struct cps = { .sql = sql, .extra = lookup }; 00719 00720 va_copy(cps.ap, ap); 00721 va_copy(aq, ap); 00722 00723 if (!table) 00724 return -1; 00725 00726 obj = ast_odbc_request_obj(database, 0); 00727 if (!obj) 00728 return -1; 00729 00730 snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE ", table); 00731 while((newparam = va_arg(aq, const char *))) { 00732 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=? AND ", newparam); 00733 newval = va_arg(aq, const char *); 00734 } 00735 va_end(aq); 00736 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=?", keyfield); 00737 00738 stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps); 00739 00740 if (!stmt) { 00741 ast_odbc_release_obj(obj); 00742 return -1; 00743 } 00744 00745 res = SQLRowCount(stmt, &rowcount); 00746 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00747 ast_odbc_release_obj(obj); 00748 00749 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00750 ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql); 00751 return -1; 00752 } 00753 00754 if (rowcount >= 0) 00755 return (int)rowcount; 00756 00757 return -1; 00758 }
| static int load_module | ( | void | ) | [static] |
Definition at line 1063 of file res_config_odbc.c.
References ast_config_engine_register(), and ast_verb.
01064 { 01065 ast_config_engine_register(&odbc_engine); 01066 ast_verb(1, "res_config_odbc loaded.\n"); 01067 return 0; 01068 }
| static struct ast_config* realtime_multi_odbc | ( | const char * | database, | |
| const char * | table, | |||
| va_list | ap | |||
| ) | [static, read] |
Excute an Select query and return ast_config list.
| 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_strip(), ast_strlen_zero(), ast_variable_append(), ast_variable_new(), custom_prepare(), LOG_WARNING, custom_prepare_struct::sql, and var.
00257 { 00258 struct odbc_obj *obj; 00259 SQLHSTMT stmt; 00260 char sql[1024]; 00261 char coltitle[256]; 00262 char rowdata[2048]; 00263 const char *initfield=NULL; 00264 char *op; 00265 const char *newparam, *newval; 00266 char *stringp; 00267 char *chunk; 00268 SQLSMALLINT collen; 00269 int res; 00270 int x; 00271 struct ast_variable *var=NULL; 00272 struct ast_config *cfg=NULL; 00273 struct ast_category *cat=NULL; 00274 SQLULEN colsize; 00275 SQLSMALLINT colcount=0; 00276 SQLSMALLINT datatype; 00277 SQLSMALLINT decimaldigits; 00278 SQLSMALLINT nullable; 00279 SQLLEN indicator; 00280 struct custom_prepare_struct cps = { .sql = sql }; 00281 va_list aq; 00282 00283 va_copy(cps.ap, ap); 00284 va_copy(aq, ap); 00285 00286 if (!table) 00287 return NULL; 00288 00289 obj = ast_odbc_request_obj(database, 0); 00290 if (!obj) 00291 return NULL; 00292 00293 newparam = va_arg(aq, const char *); 00294 if (!newparam) { 00295 ast_odbc_release_obj(obj); 00296 return NULL; 00297 } 00298 initfield = ast_strdupa(newparam); 00299 if ((op = strchr(initfield, ' '))) 00300 *op = '\0'; 00301 newval = va_arg(aq, const char *); 00302 op = !strchr(newparam, ' ') ? " =" : ""; 00303 snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?%s", table, newparam, op, 00304 strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : ""); 00305 while((newparam = va_arg(aq, const char *))) { 00306 op = !strchr(newparam, ' ') ? " =" : ""; 00307 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?%s", newparam, op, 00308 strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : ""); 00309 newval = va_arg(aq, const char *); 00310 } 00311 if (initfield) 00312 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield); 00313 va_end(aq); 00314 00315 stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps); 00316 00317 if (!stmt) { 00318 ast_odbc_release_obj(obj); 00319 return NULL; 00320 } 00321 00322 res = SQLNumResultCols(stmt, &colcount); 00323 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00324 ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql); 00325 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00326 ast_odbc_release_obj(obj); 00327 return NULL; 00328 } 00329 00330 cfg = ast_config_new(); 00331 if (!cfg) { 00332 ast_log(LOG_WARNING, "Out of memory!\n"); 00333 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00334 ast_odbc_release_obj(obj); 00335 return NULL; 00336 } 00337 00338 while ((res=SQLFetch(stmt)) != SQL_NO_DATA) { 00339 var = NULL; 00340 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00341 ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); 00342 continue; 00343 } 00344 cat = ast_category_new("","",99999); 00345 if (!cat) { 00346 ast_log(LOG_WARNING, "Out of memory!\n"); 00347 continue; 00348 } 00349 for (x=0;x<colcount;x++) { 00350 rowdata[0] = '\0'; 00351 collen = sizeof(coltitle); 00352 res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen, 00353 &datatype, &colsize, &decimaldigits, &nullable); 00354 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00355 ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql); 00356 ast_category_destroy(cat); 00357 continue; 00358 } 00359 00360 indicator = 0; 00361 res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), &indicator); 00362 if (indicator == SQL_NULL_DATA) 00363 continue; 00364 00365 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00366 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); 00367 ast_category_destroy(cat); 00368 continue; 00369 } 00370 stringp = rowdata; 00371 while(stringp) { 00372 chunk = strsep(&stringp, ";"); 00373 if (!ast_strlen_zero(ast_strip(chunk))) { 00374 if (initfield && !strcmp(initfield, coltitle)) 00375 ast_category_rename(cat, chunk); 00376 var = ast_variable_new(coltitle, chunk, ""); 00377 ast_variable_append(cat, var); 00378 } 00379 } 00380 } 00381 ast_category_append(cfg, cat); 00382 } 00383 00384 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00385 ast_odbc_release_obj(obj); 00386 return cfg; 00387 }
| static struct ast_variable* realtime_odbc | ( | const char * | database, | |
| const char * | table, | |||
| va_list | ap | |||
| ) | [static, read] |
Excute an SQL query and return ast_variable list.
| 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, and var.
00112 { 00113 struct odbc_obj *obj; 00114 SQLHSTMT stmt; 00115 char sql[1024]; 00116 char coltitle[256]; 00117 char rowdata[2048]; 00118 char *op; 00119 const char *newparam, *newval; 00120 char *stringp; 00121 char *chunk; 00122 SQLSMALLINT collen; 00123 int res; 00124 int x; 00125 struct ast_variable *var=NULL, *prev=NULL; 00126 SQLULEN colsize; 00127 SQLSMALLINT colcount=0; 00128 SQLSMALLINT datatype; 00129 SQLSMALLINT decimaldigits; 00130 SQLSMALLINT nullable; 00131 SQLLEN indicator; 00132 va_list aq; 00133 struct custom_prepare_struct cps = { .sql = sql }; 00134 00135 va_copy(cps.ap, ap); 00136 va_copy(aq, ap); 00137 00138 if (!table) 00139 return NULL; 00140 00141 obj = ast_odbc_request_obj(database, 0); 00142 00143 if (!obj) { 00144 ast_log(LOG_ERROR, "No database handle available with the name of '%s' (check res_odbc.conf)\n", database); 00145 return NULL; 00146 } 00147 00148 newparam = va_arg(aq, const char *); 00149 if (!newparam) { 00150 ast_odbc_release_obj(obj); 00151 return NULL; 00152 } 00153 newval = va_arg(aq, const char *); 00154 op = !strchr(newparam, ' ') ? " =" : ""; 00155 snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?%s", table, newparam, op, 00156 strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : ""); 00157 while((newparam = va_arg(aq, const char *))) { 00158 op = !strchr(newparam, ' ') ? " =" : ""; 00159 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?%s", newparam, op, 00160 strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : ""); 00161 newval = va_arg(aq, const char *); 00162 } 00163 va_end(aq); 00164 00165 stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps); 00166 00167 if (!stmt) { 00168 ast_odbc_release_obj(obj); 00169 return NULL; 00170 } 00171 00172 res = SQLNumResultCols(stmt, &colcount); 00173 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00174 ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql); 00175 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00176 ast_odbc_release_obj(obj); 00177 return NULL; 00178 } 00179 00180 res = SQLFetch(stmt); 00181 if (res == SQL_NO_DATA) { 00182 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00183 ast_odbc_release_obj(obj); 00184 return NULL; 00185 } 00186 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00187 ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); 00188 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00189 ast_odbc_release_obj(obj); 00190 return NULL; 00191 } 00192 for (x = 0; x < colcount; x++) { 00193 rowdata[0] = '\0'; 00194 collen = sizeof(coltitle); 00195 res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen, 00196 &datatype, &colsize, &decimaldigits, &nullable); 00197 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00198 ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql); 00199 if (var) 00200 ast_variables_destroy(var); 00201 ast_odbc_release_obj(obj); 00202 return NULL; 00203 } 00204 00205 indicator = 0; 00206 res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), &indicator); 00207 if (indicator == SQL_NULL_DATA) 00208 rowdata[0] = '\0'; 00209 else if (ast_strlen_zero(rowdata)) { 00210 /* Because we encode the empty string for a NULL, we will encode 00211 * actual empty strings as a string containing a single whitespace. */ 00212 ast_copy_string(rowdata, " ", sizeof(rowdata)); 00213 } 00214 00215 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00216 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); 00217 if (var) 00218 ast_variables_destroy(var); 00219 ast_odbc_release_obj(obj); 00220 return NULL; 00221 } 00222 stringp = rowdata; 00223 while(stringp) { 00224 chunk = strsep(&stringp, ";"); 00225 if (!ast_strlen_zero(ast_strip(chunk))) { 00226 if (prev) { 00227 prev->next = ast_variable_new(coltitle, chunk, ""); 00228 if (prev->next) 00229 prev = prev->next; 00230 } else 00231 prev = var = ast_variable_new(coltitle, chunk, ""); 00232 } 00233 } 00234 } 00235 00236 00237 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00238 ast_odbc_release_obj(obj); 00239 return var; 00240 }
| static int reload_module | ( | void | ) | [static] |
Definition at line 1070 of file res_config_odbc.c.
| static int require_odbc | ( | const char * | database, | |
| const char * | table, | |||
| va_list | ap | |||
| ) | [static] |
Definition at line 884 of file res_config_odbc.c.
References ast_log(), ast_odbc_find_table(), ast_rq_is_int(), AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CHECK_SIZE, odbc_cache_tables::columns, odbc_cache_columns::list, LOG_WARNING, odbc_cache_columns::name, RQ_CHAR, RQ_DATE, RQ_DATETIME, RQ_FLOAT, RQ_INTEGER1, RQ_INTEGER2, RQ_INTEGER3, RQ_INTEGER4, RQ_INTEGER8, RQ_UINTEGER1, RQ_UINTEGER2, RQ_UINTEGER3, RQ_UINTEGER4, RQ_UINTEGER8, odbc_cache_columns::size, odbc_cache_columns::type, type, warn_length, warn_type, and WARN_TYPE_OR_LENGTH.
00885 { 00886 struct odbc_cache_tables *tableptr = ast_odbc_find_table(database, table); 00887 struct odbc_cache_columns *col; 00888 char *elm; 00889 int type, size; 00890 00891 if (!tableptr) { 00892 return -1; 00893 } 00894 00895 while ((elm = va_arg(ap, char *))) { 00896 type = va_arg(ap, require_type); 00897 size = va_arg(ap, int); 00898 /* Check if the field matches the criteria */ 00899 AST_RWLIST_TRAVERSE(&tableptr->columns, col, list) { 00900 if (strcmp(col->name, elm) == 0) { 00901 /* Type check, first. Some fields are more particular than others */ 00902 switch (col->type) { 00903 case SQL_CHAR: 00904 case SQL_VARCHAR: 00905 case SQL_LONGVARCHAR: 00906 #ifdef HAVE_ODBC_WCHAR 00907 case SQL_WCHAR: 00908 case SQL_WVARCHAR: 00909 case SQL_WLONGVARCHAR: 00910 #endif 00911 case SQL_BINARY: 00912 case SQL_VARBINARY: 00913 case SQL_LONGVARBINARY: 00914 case SQL_GUID: 00915 #define CHECK_SIZE(n) \ 00916 if (col->size < n) { \ 00917 warn_length(col, n); \ 00918 } \ 00919 break; 00920 switch (type) { 00921 case RQ_UINTEGER1: CHECK_SIZE(3) /* 255 */ 00922 case RQ_INTEGER1: CHECK_SIZE(4) /* -128 */ 00923 case RQ_UINTEGER2: CHECK_SIZE(5) /* 65535 */ 00924 case RQ_INTEGER2: CHECK_SIZE(6) /* -32768 */ 00925 case RQ_UINTEGER3: /* 16777215 */ 00926 case RQ_INTEGER3: CHECK_SIZE(8) /* -8388608 */ 00927 case RQ_DATE: /* 2008-06-09 */ 00928 case RQ_UINTEGER4: CHECK_SIZE(10) /* 4200000000 */ 00929 case RQ_INTEGER4: CHECK_SIZE(11) /* -2100000000 */ 00930 case RQ_DATETIME: /* 2008-06-09 16:03:47 */ 00931 case RQ_UINTEGER8: CHECK_SIZE(19) /* trust me */ 00932 case RQ_INTEGER8: CHECK_SIZE(20) /* ditto */ 00933 case RQ_FLOAT: 00934 case RQ_CHAR: CHECK_SIZE(size) 00935 } 00936 #undef CHECK_SIZE 00937 break; 00938 case SQL_TYPE_DATE: 00939 if (type != RQ_DATE) { 00940 warn_type(col, type); 00941 } 00942 break; 00943 case SQL_TYPE_TIMESTAMP: 00944 case SQL_TIMESTAMP: 00945 if (type != RQ_DATE && type != RQ_DATETIME) { 00946 warn_type(col, type); 00947 } 00948 break; 00949 case SQL_BIT: 00950 warn_length(col, size); 00951 break; 00952 #define WARN_TYPE_OR_LENGTH(n) \ 00953 if (!ast_rq_is_int(type)) { \ 00954 warn_type(col, type); \ 00955 } else { \ 00956 warn_length(col, n); \ 00957 } 00958 case SQL_TINYINT: 00959 if (type != RQ_UINTEGER1) { 00960 WARN_TYPE_OR_LENGTH(size) 00961 } 00962 break; 00963 case SQL_C_STINYINT: 00964 if (type != RQ_INTEGER1) { 00965 WARN_TYPE_OR_LENGTH(size) 00966 } 00967 break; 00968 case SQL_C_USHORT: 00969 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_UINTEGER2) { 00970 WARN_TYPE_OR_LENGTH(size) 00971 } 00972 break; 00973 case SQL_SMALLINT: 00974 case SQL_C_SSHORT: 00975 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_INTEGER2) { 00976 WARN_TYPE_OR_LENGTH(size) 00977 } 00978 break; 00979 case SQL_C_ULONG: 00980 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && 00981 type != RQ_UINTEGER2 && type != RQ_INTEGER2 && 00982 type != RQ_UINTEGER3 && type != RQ_INTEGER3 && 00983 type != RQ_INTEGER4) { 00984 WARN_TYPE_OR_LENGTH(size) 00985 } 00986 break; 00987 case SQL_INTEGER: 00988 case SQL_C_SLONG: 00989 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && 00990 type != RQ_UINTEGER2 && type != RQ_INTEGER2 && 00991 type != RQ_UINTEGER3 && type != RQ_INTEGER3 && 00992 type != RQ_INTEGER4) { 00993 WARN_TYPE_OR_LENGTH(size) 00994 } 00995 break; 00996 case SQL_C_UBIGINT: 00997 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && 00998 type != RQ_UINTEGER2 && type != RQ_INTEGER2 && 00999 type != RQ_UINTEGER3 && type != RQ_INTEGER3 && 01000 type != RQ_UINTEGER4 && type != RQ_INTEGER4 && 01001 type != RQ_INTEGER8) { 01002 WARN_TYPE_OR_LENGTH(size) 01003 } 01004 break; 01005 case SQL_BIGINT: 01006 case SQL_C_SBIGINT: 01007 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && 01008 type != RQ_UINTEGER2 && type != RQ_INTEGER2 && 01009 type != RQ_UINTEGER3 && type != RQ_INTEGER3 && 01010 type != RQ_UINTEGER4 && type != RQ_INTEGER4 && 01011 type != RQ_INTEGER8) { 01012 WARN_TYPE_OR_LENGTH(size) 01013 } 01014 break; 01015 #undef WARN_TYPE_OR_LENGTH 01016 case SQL_NUMERIC: 01017 case SQL_DECIMAL: 01018 case SQL_FLOAT: 01019 case SQL_REAL: 01020 case SQL_DOUBLE: 01021 if (!ast_rq_is_int(type) && type != RQ_FLOAT) { 01022 warn_type(col, type); 01023 } 01024 break; 01025 default: 01026 ast_log(LOG_WARNING, "Realtime table %s@%s: column type (%d) unrecognized for column '%s'\n", table, database, col->type, elm); 01027 } 01028 break; 01029 } 01030 } 01031 if (!col) { 01032 ast_log(LOG_WARNING, "Realtime table %s@%s requires column '%s', but that column does not exist!\n", table, database, elm); 01033 } 01034 } 01035 va_end(ap); 01036 AST_RWLIST_UNLOCK(&tableptr->columns); 01037 return 0; 01038 }
| static int store_odbc | ( | const char * | database, | |
| const char * | table, | |||
| va_list | ap | |||
| ) | [static] |
Excute an INSERT query.
| 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 633 of file res_config_odbc.c.
References custom_prepare_struct::ap, ast_copy_string(), ast_log(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj(), custom_prepare(), LOG_WARNING, and custom_prepare_struct::sql.
00634 { 00635 struct odbc_obj *obj; 00636 SQLHSTMT stmt; 00637 char sql[256]; 00638 char keys[256]; 00639 char vals[256]; 00640 SQLLEN rowcount=0; 00641 const char *newparam, *newval; 00642 int res; 00643 va_list aq; 00644 struct custom_prepare_struct cps = { .sql = sql, .extra = NULL }; 00645 00646 va_copy(cps.ap, ap); 00647 va_copy(aq, ap); 00648 00649 if (!table) 00650 return -1; 00651 00652 obj = ast_odbc_request_obj(database, 0); 00653 if (!obj) 00654 return -1; 00655 00656 newparam = va_arg(aq, const char *); 00657 if (!newparam) { 00658 ast_odbc_release_obj(obj); 00659 return -1; 00660 } 00661 newval = va_arg(aq, const char *); 00662 snprintf(keys, sizeof(keys), "%s", newparam); 00663 ast_copy_string(vals, "?", sizeof(vals)); 00664 while ((newparam = va_arg(aq, const char *))) { 00665 snprintf(keys + strlen(keys), sizeof(keys) - strlen(keys), ", %s", newparam); 00666 snprintf(vals + strlen(vals), sizeof(vals) - strlen(vals), ", ?"); 00667 newval = va_arg(aq, const char *); 00668 } 00669 va_end(aq); 00670 snprintf(sql, sizeof(sql), "INSERT INTO %s (%s) VALUES (%s)", table, keys, vals); 00671 00672 stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps); 00673 00674 if (!stmt) { 00675 ast_odbc_release_obj(obj); 00676 return -1; 00677 } 00678 00679 res = SQLRowCount(stmt, &rowcount); 00680 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00681 ast_odbc_release_obj(obj); 00682 00683 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00684 ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql); 00685 return -1; 00686 } 00687 00688 if (rowcount >= 0) 00689 return (int)rowcount; 00690 00691 return -1; 00692 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 1055 of file res_config_odbc.c.
References ast_config_engine_deregister(), and ast_verb.
01056 { 01057 ast_config_engine_deregister(&odbc_engine); 01058 01059 ast_verb(1, "res_config_odbc unloaded.\n"); 01060 return 0; 01061 }
| static int update2_odbc | ( | const char * | database, | |
| const char * | table, | |||
| va_list | ap | |||
| ) | [static] |
Execute an UPDATE query.
| database | ||
| table | ||
| ap | list containing one or more field/value set(s). |
Update a database table, preparing the sql statement from a list of key/value pairs specified in ap. The lookup pairs are specified first and are separated from the update pairs by a sentinel value. Sub-in the values to the prepared statement and execute it.
| number | of rows affected | |
| -1 | on failure |
Definition at line 582 of file res_config_odbc.c.
References update2_prepare_struct::ap, ast_log(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj(), ast_str_buffer(), ast_str_thread_get(), update2_prepare_struct::database, LOG_WARNING, sql_buf, and update2_prepare().
00583 { 00584 struct odbc_obj *obj; 00585 SQLHSTMT stmt; 00586 struct update2_prepare_struct ups = { .database = database, .table = table, }; 00587 struct ast_str *sql; 00588 int res; 00589 SQLLEN rowcount = 0; 00590 00591 va_copy(ups.ap, ap); 00592 00593 if (!(obj = ast_odbc_request_obj(database, 0))) { 00594 return -1; 00595 } 00596 00597 if (!(stmt = ast_odbc_prepare_and_execute(obj, update2_prepare, &ups))) { 00598 ast_odbc_release_obj(obj); 00599 return -1; 00600 } 00601 00602 res = SQLRowCount(stmt, &rowcount); 00603 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00604 ast_odbc_release_obj(obj); 00605 00606 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00607 /* Since only a single thread can access this memory, we can retrieve what would otherwise be lost. */ 00608 sql = ast_str_thread_get(&sql_buf, 16); 00609 ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n", ast_str_buffer(sql)); 00610 return -1; 00611 } 00612 00613 if (rowcount >= 0) { 00614 return (int)rowcount; 00615 } 00616 00617 return -1; 00618 }
| static SQLHSTMT update2_prepare | ( | struct odbc_obj * | obj, | |
| void * | data | |||
| ) | [static] |
Definition at line 485 of file res_config_odbc.c.
References update2_prepare_struct::ap, ast_log(), ast_odbc_find_column(), ast_odbc_find_table(), ast_odbc_release_table, ast_str_append(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), odbc_obj::con, update2_prepare_struct::database, first, LOG_ERROR, LOG_NOTICE, LOG_WARNING, sql_buf, and update2_prepare_struct::table.
Referenced by update2_odbc().
00486 { 00487 int res, x = 1, first = 1; 00488 struct update2_prepare_struct *ups = data; 00489 const char *newparam, *newval; 00490 struct ast_str *sql = ast_str_thread_get(&sql_buf, 16); 00491 SQLHSTMT stmt; 00492 va_list ap; 00493 struct odbc_cache_tables *tableptr = ast_odbc_find_table(ups->database, ups->table); 00494 struct odbc_cache_columns *column; 00495 00496 if (!sql) { 00497 if (tableptr) { 00498 ast_odbc_release_table(tableptr); 00499 } 00500 return NULL; 00501 } 00502 00503 if (!tableptr) { 00504 ast_log(LOG_ERROR, "Could not retrieve metadata for table '%s@%s'. Update will fail!\n", ups->table, ups->database); 00505 return NULL; 00506 } 00507 00508 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt); 00509 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00510 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n"); 00511 ast_odbc_release_table(tableptr); 00512 return NULL; 00513 } 00514 00515 ast_str_set(&sql, 0, "UPDATE %s SET ", ups->table); 00516 00517 /* Start by finding the second set of parameters */ 00518 va_copy(ap, ups->ap); 00519 00520 while ((newparam = va_arg(ap, const char *))) { 00521 newval = va_arg(ap, const char *); 00522 } 00523 00524 while ((newparam = va_arg(ap, const char *))) { 00525 newval = va_arg(ap, const char *); 00526 if ((column = ast_odbc_find_column(tableptr, newparam))) { 00527 ast_str_append(&sql, 0, "%s%s=? ", first ? "" : ", ", newparam); 00528 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL); 00529 first = 0; 00530 } else { 00531 ast_log(LOG_NOTICE, "Not updating column '%s' in '%s@%s' because that column does not exist!\n", newparam, ups->table, ups->database); 00532 } 00533 } 00534 va_end(ap); 00535 00536 /* Restart search, because we need to add the search parameters */ 00537 va_copy(ap, ups->ap); 00538 ast_str_append(&sql, 0, "WHERE"); 00539 first = 1; 00540 00541 while ((newparam = va_arg(ap, const char *))) { 00542 newval = va_arg(ap, const char *); 00543 if (!(column = ast_odbc_find_column(tableptr, newparam))) { 00544 ast_log(LOG_ERROR, "One or more of the criteria columns '%s' on '%s@%s' for this update does not exist!\n", newparam, ups->table, ups->database); 00545 ast_odbc_release_table(tableptr); 00546 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00547 return NULL; 00548 } 00549 ast_str_append(&sql, 0, "%s %s=?", first ? "" : " AND", newparam); 00550 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL); 00551 first = 0; 00552 } 00553 va_end(ap); 00554 00555 /* Done with the table metadata */ 00556 ast_odbc_release_table(tableptr); 00557 00558 res = SQLPrepare(stmt, (unsigned char *)ast_str_buffer(sql), SQL_NTS); 00559 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00560 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", ast_str_buffer(sql)); 00561 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00562 return NULL; 00563 } 00564 00565 return stmt; 00566 }
| static int update_odbc | ( | const char * | database, | |
| const char * | table, | |||
| const char * | keyfield, | |||
| const char * | lookup, | |||
| va_list | ap | |||
| ) | [static] |
Excute an UPDATE query.
| 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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload_module, } [static] |
Definition at line 1079 of file res_config_odbc.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1079 of file res_config_odbc.c.
struct ast_config_engine odbc_engine [static] |
Definition at line 1042 of file res_config_odbc.c.
struct ast_threadstorage sql_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_sql_buf , .custom_init = NULL , } [static] |
Definition at line 48 of file res_config_odbc.c.
Referenced by update2_odbc(), and update2_prepare().
1.6.2