#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"
#include "asterisk/stringfields.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 void | decode_chunk (char *chunk) |
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 | unload_odbc (const char *a, const char *b) |
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_LOAD_ORDER , .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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_REALTIME_DRIVER, } |
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 , } |
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 __init_sql_buf | ( | void | ) | [static] |
static void __reg_module | ( | void | ) | [static] |
Definition at line 1193 of file res_config_odbc.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 1193 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 905 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_obj2, ast_variable_append(), ast_variable_new(), config_odbc_prepare(), last, LOG_NOTICE, LOG_WARNING, and RES_ODBC_CONNECTED.
00906 { 00907 struct ast_variable *new_v; 00908 struct ast_category *cur_cat; 00909 int res = 0; 00910 struct odbc_obj *obj; 00911 char sqlbuf[1024] = ""; 00912 char *sql = sqlbuf; 00913 size_t sqlleft = sizeof(sqlbuf); 00914 unsigned int last_cat_metric = 0; 00915 SQLSMALLINT rowcount = 0; 00916 SQLHSTMT stmt; 00917 char last[128] = ""; 00918 struct config_odbc_obj q; 00919 struct ast_flags loader_flags = { 0 }; 00920 struct ast_flags connected_flag = { RES_ODBC_CONNECTED }; 00921 00922 memset(&q, 0, sizeof(q)); 00923 00924 if (!file || !strcmp (file, "res_config_odbc.conf")) 00925 return NULL; /* cant configure myself with myself ! */ 00926 00927 obj = ast_odbc_request_obj2(database, connected_flag); 00928 if (!obj) 00929 return NULL; 00930 00931 ast_build_string(&sql, &sqlleft, "SELECT cat_metric, category, var_name, var_val FROM %s ", table); 00932 ast_build_string(&sql, &sqlleft, "WHERE filename='%s' AND commented=0 ", file); 00933 ast_build_string(&sql, &sqlleft, "ORDER BY cat_metric DESC, var_metric ASC, category, var_name "); 00934 q.sql = sqlbuf; 00935 00936 stmt = ast_odbc_prepare_and_execute(obj, config_odbc_prepare, &q); 00937 00938 if (!stmt) { 00939 ast_log(LOG_WARNING, "SQL select error!\n[%s]\n\n", sql); 00940 ast_odbc_release_obj(obj); 00941 return NULL; 00942 } 00943 00944 res = SQLNumResultCols(stmt, &rowcount); 00945 00946 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00947 ast_log(LOG_WARNING, "SQL NumResultCols error!\n[%s]\n\n", sql); 00948 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00949 ast_odbc_release_obj(obj); 00950 return NULL; 00951 } 00952 00953 if (!rowcount) { 00954 ast_log(LOG_NOTICE, "found nothing\n"); 00955 ast_odbc_release_obj(obj); 00956 return cfg; 00957 } 00958 00959 cur_cat = ast_config_get_current_category(cfg); 00960 00961 while ((res = SQLFetch(stmt)) != SQL_NO_DATA) { 00962 if (!strcmp (q.var_name, "#include")) { 00963 if (!ast_config_internal_load(q.var_val, cfg, loader_flags, "", who_asked)) { 00964 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00965 ast_odbc_release_obj(obj); 00966 return NULL; 00967 } 00968 continue; 00969 } 00970 if (strcmp(last, q.category) || last_cat_metric != q.cat_metric) { 00971 cur_cat = ast_category_new(q.category, "", 99999); 00972 if (!cur_cat) { 00973 ast_log(LOG_WARNING, "Out of memory!\n"); 00974 break; 00975 } 00976 strcpy(last, q.category); 00977 last_cat_metric = q.cat_metric; 00978 ast_category_append(cfg, cur_cat); 00979 } 00980 00981 new_v = ast_variable_new(q.var_name, q.var_val, ""); 00982 ast_variable_append(cur_cat, new_v); 00983 } 00984 00985 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00986 ast_odbc_release_obj(obj); 00987 return cfg; 00988 }
static SQLHSTMT config_odbc_prepare | ( | struct odbc_obj * | obj, | |
void * | data | |||
) | [static] |
Definition at line 878 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().
00879 { 00880 struct config_odbc_obj *q = data; 00881 SQLHSTMT sth; 00882 int res; 00883 00884 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &sth); 00885 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00886 ast_verb(4, "Failure in AllocStatement %d\n", res); 00887 return NULL; 00888 } 00889 00890 res = SQLPrepare(sth, (unsigned char *)q->sql, SQL_NTS); 00891 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00892 ast_verb(4, "Error in PREPARE %d\n", res); 00893 SQLFreeHandle(SQL_HANDLE_STMT, sth); 00894 return NULL; 00895 } 00896 00897 SQLBindCol(sth, 1, SQL_C_ULONG, &q->cat_metric, sizeof(q->cat_metric), &q->err); 00898 SQLBindCol(sth, 2, SQL_C_CHAR, q->category, sizeof(q->category), &q->err); 00899 SQLBindCol(sth, 3, SQL_C_CHAR, q->var_name, sizeof(q->var_name), &q->err); 00900 SQLBindCol(sth, 4, SQL_C_CHAR, q->var_val, sizeof(q->var_val), &q->err); 00901 00902 return sth; 00903 }
static SQLHSTMT custom_prepare | ( | struct odbc_obj * | obj, | |
void * | data | |||
) | [static] |
Definition at line 72 of file res_config_odbc.c.
References custom_prepare_struct::ap, ast_debug, ast_log(), ast_string_field_set, ast_strlen_zero(), odbc_obj::con, custom_prepare_struct::encoding, encoding, 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().
00073 { 00074 int res, x = 1, count = 0; 00075 struct custom_prepare_struct *cps = data; 00076 const char *newparam, *newval; 00077 char encodebuf[1024]; 00078 SQLHSTMT stmt; 00079 va_list ap; 00080 00081 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt); 00082 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00083 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n"); 00084 return NULL; 00085 } 00086 00087 ast_debug(1, "Skip: %lld; SQL: %s\n", cps->skip, cps->sql); 00088 00089 res = SQLPrepare(stmt, (unsigned char *)cps->sql, SQL_NTS); 00090 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00091 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", cps->sql); 00092 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00093 return NULL; 00094 } 00095 00096 va_copy(ap, cps->ap); 00097 while ((newparam = va_arg(ap, const char *))) { 00098 newval = va_arg(ap, const char *); 00099 if ((1LL << count++) & cps->skip) { 00100 ast_debug(1, "Skipping field '%s'='%s' (%llo/%llo)\n", newparam, newval, 1LL << (count - 1), cps->skip); 00101 continue; 00102 } 00103 ast_debug(1, "Parameter %d ('%s') = '%s'\n", x, newparam, newval); 00104 if (strchr(newval, ';') || strchr(newval, '^')) { 00105 char *eptr = encodebuf; 00106 const char *vptr = newval; 00107 for (; *vptr && eptr < encodebuf + sizeof(encodebuf); vptr++) { 00108 if (strchr("^;", *vptr)) { 00109 /* We use ^XX, instead of %XX because '%' is a special character in SQL */ 00110 snprintf(eptr, encodebuf + sizeof(encodebuf) - eptr, "^%02hhX", *vptr); 00111 eptr += 3; 00112 } else { 00113 *eptr++ = *vptr; 00114 } 00115 } 00116 if (eptr < encodebuf + sizeof(encodebuf)) { 00117 *eptr = '\0'; 00118 } else { 00119 encodebuf[sizeof(encodebuf) - 1] = '\0'; 00120 } 00121 ast_string_field_set(cps, encoding[x], encodebuf); 00122 newval = cps->encoding[x]; 00123 } 00124 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL); 00125 } 00126 va_end(ap); 00127 00128 if (!ast_strlen_zero(cps->extra)) 00129 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(cps->extra), 0, (void *)cps->extra, 0, NULL); 00130 return stmt; 00131 }
static void decode_chunk | ( | char * | chunk | ) | [static] |
Definition at line 62 of file res_config_odbc.c.
Referenced by realtime_multi_odbc(), and realtime_odbc().
00063 { 00064 for (; *chunk; chunk++) { 00065 if (*chunk == '^' && strchr("0123456789ABCDEF", chunk[1]) && strchr("0123456789ABCDEF", chunk[2])) { 00066 sscanf(chunk + 1, "%02hhX", chunk); 00067 memmove(chunk + 1, chunk + 3, strlen(chunk + 3) + 1); 00068 } 00069 } 00070 }
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 813 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_obj2, custom_prepare(), LOG_WARNING, RES_ODBC_CONNECTED, and custom_prepare_struct::sql.
00814 { 00815 struct odbc_obj *obj; 00816 SQLHSTMT stmt; 00817 char sql[256]; 00818 SQLLEN rowcount=0; 00819 const char *newparam; 00820 int res; 00821 va_list aq; 00822 struct custom_prepare_struct cps = { .sql = sql, .extra = lookup }; 00823 struct ast_flags connected_flag = { RES_ODBC_CONNECTED }; 00824 00825 if (!table) { 00826 return -1; 00827 } 00828 00829 obj = ast_odbc_request_obj2(database, connected_flag); 00830 if (!obj) { 00831 return -1; 00832 } 00833 00834 snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE ", table); 00835 00836 va_copy(aq, ap); 00837 while((newparam = va_arg(aq, const char *))) { 00838 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=? AND ", newparam); 00839 va_arg(aq, const char *); 00840 } 00841 va_end(aq); 00842 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=?", keyfield); 00843 00844 va_copy(cps.ap, ap); 00845 stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps); 00846 va_end(cps.ap); 00847 00848 if (!stmt) { 00849 ast_odbc_release_obj(obj); 00850 return -1; 00851 } 00852 00853 res = SQLRowCount(stmt, &rowcount); 00854 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00855 ast_odbc_release_obj(obj); 00856 00857 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00858 ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql); 00859 return -1; 00860 } 00861 00862 if (rowcount >= 0) 00863 return (int)rowcount; 00864 00865 return -1; 00866 }
static int load_module | ( | void | ) | [static] |
Definition at line 1176 of file res_config_odbc.c.
References ast_config_engine_register(), ast_verb, and odbc_engine.
01177 { 01178 ast_config_engine_register(&odbc_engine); 01179 ast_verb(1, "res_config_odbc loaded.\n"); 01180 return 0; 01181 }
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 313 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_obj2, ast_strdupa, ast_string_field_free_memory, ast_string_field_init, ast_strip(), ast_strlen_zero(), ast_variable_append(), ast_variable_new(), custom_prepare(), decode_chunk(), LOG_WARNING, RES_ODBC_CONNECTED, custom_prepare_struct::sql, strcasestr(), strsep(), and var.
00314 { 00315 struct odbc_obj *obj; 00316 SQLHSTMT stmt; 00317 char sql[1024]; 00318 char coltitle[256]; 00319 char rowdata[2048]; 00320 const char *initfield; 00321 char *op; 00322 const char *newparam; 00323 char *stringp; 00324 char *chunk; 00325 SQLSMALLINT collen; 00326 int res; 00327 int x; 00328 struct ast_variable *var=NULL; 00329 struct ast_config *cfg=NULL; 00330 struct ast_category *cat=NULL; 00331 struct ast_flags connected_flag = { RES_ODBC_CONNECTED }; 00332 SQLULEN colsize; 00333 SQLSMALLINT colcount=0; 00334 SQLSMALLINT datatype; 00335 SQLSMALLINT decimaldigits; 00336 SQLSMALLINT nullable; 00337 SQLLEN indicator; 00338 struct custom_prepare_struct cps = { .sql = sql }; 00339 va_list aq; 00340 00341 if (!table || ast_string_field_init(&cps, 256)) { 00342 return NULL; 00343 } 00344 00345 00346 obj = ast_odbc_request_obj2(database, connected_flag); 00347 if (!obj) { 00348 ast_string_field_free_memory(&cps); 00349 return NULL; 00350 } 00351 00352 va_copy(aq, ap); 00353 newparam = va_arg(aq, const char *); 00354 if (!newparam) { 00355 va_end(aq); 00356 ast_odbc_release_obj(obj); 00357 ast_string_field_free_memory(&cps); 00358 return NULL; 00359 } 00360 00361 initfield = ast_strdupa(newparam); 00362 if ((op = strchr(initfield, ' '))) { 00363 *op = '\0'; 00364 } 00365 00366 va_arg(aq, const char *); 00367 op = !strchr(newparam, ' ') ? " =" : ""; 00368 snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?%s", table, newparam, op, 00369 strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : ""); 00370 while((newparam = va_arg(aq, const char *))) { 00371 op = !strchr(newparam, ' ') ? " =" : ""; 00372 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?%s", newparam, op, 00373 strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : ""); 00374 va_arg(aq, const char *); 00375 } 00376 va_end(aq); 00377 00378 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield); 00379 00380 va_copy(cps.ap, ap); 00381 stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps); 00382 va_end(cps.ap); 00383 00384 if (!stmt) { 00385 ast_odbc_release_obj(obj); 00386 ast_string_field_free_memory(&cps); 00387 return NULL; 00388 } 00389 00390 res = SQLNumResultCols(stmt, &colcount); 00391 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00392 ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql); 00393 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00394 ast_odbc_release_obj(obj); 00395 ast_string_field_free_memory(&cps); 00396 return NULL; 00397 } 00398 00399 cfg = ast_config_new(); 00400 if (!cfg) { 00401 ast_log(LOG_WARNING, "Out of memory!\n"); 00402 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00403 ast_odbc_release_obj(obj); 00404 ast_string_field_free_memory(&cps); 00405 return NULL; 00406 } 00407 00408 while ((res=SQLFetch(stmt)) != SQL_NO_DATA) { 00409 var = NULL; 00410 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00411 ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); 00412 continue; 00413 } 00414 cat = ast_category_new("","",99999); 00415 if (!cat) { 00416 ast_log(LOG_WARNING, "Out of memory!\n"); 00417 continue; 00418 } 00419 for (x=0;x<colcount;x++) { 00420 rowdata[0] = '\0'; 00421 colsize = 0; 00422 collen = sizeof(coltitle); 00423 res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen, 00424 &datatype, &colsize, &decimaldigits, &nullable); 00425 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00426 ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql); 00427 ast_category_destroy(cat); 00428 goto next_sql_fetch; 00429 } 00430 00431 indicator = 0; 00432 res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), &indicator); 00433 if (indicator == SQL_NULL_DATA) 00434 continue; 00435 00436 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00437 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); 00438 ast_category_destroy(cat); 00439 goto next_sql_fetch; 00440 } 00441 stringp = rowdata; 00442 while (stringp) { 00443 chunk = strsep(&stringp, ";"); 00444 if (!ast_strlen_zero(ast_strip(chunk))) { 00445 if (strchr(chunk, '^')) { 00446 decode_chunk(chunk); 00447 } 00448 if (!strcmp(initfield, coltitle)) { 00449 ast_category_rename(cat, chunk); 00450 } 00451 var = ast_variable_new(coltitle, chunk, ""); 00452 ast_variable_append(cat, var); 00453 } 00454 } 00455 } 00456 ast_category_append(cfg, cat); 00457 next_sql_fetch:; 00458 } 00459 00460 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00461 ast_odbc_release_obj(obj); 00462 ast_string_field_free_memory(&cps); 00463 return cfg; 00464 }
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 146 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_obj2, ast_string_field_free_memory, ast_string_field_init, ast_strip(), ast_strlen_zero(), ast_variable_new(), ast_variables_destroy(), custom_prepare(), decode_chunk(), LOG_ERROR, LOG_WARNING, RES_ODBC_CONNECTED, custom_prepare_struct::sql, strcasestr(), strsep(), and var.
00147 { 00148 struct odbc_obj *obj; 00149 SQLHSTMT stmt; 00150 char sql[1024]; 00151 char coltitle[256]; 00152 char rowdata[2048]; 00153 char *op; 00154 const char *newparam; 00155 char *stringp; 00156 char *chunk; 00157 SQLSMALLINT collen; 00158 int res; 00159 int x; 00160 struct ast_variable *var=NULL, *prev=NULL; 00161 SQLULEN colsize; 00162 SQLSMALLINT colcount=0; 00163 SQLSMALLINT datatype; 00164 SQLSMALLINT decimaldigits; 00165 SQLSMALLINT nullable; 00166 SQLLEN indicator; 00167 va_list aq; 00168 struct custom_prepare_struct cps = { .sql = sql }; 00169 struct ast_flags connected_flag = { RES_ODBC_CONNECTED }; 00170 00171 if (ast_string_field_init(&cps, 256)) { 00172 return NULL; 00173 } 00174 00175 if (!table) { 00176 ast_string_field_free_memory(&cps); 00177 return NULL; 00178 } 00179 00180 obj = ast_odbc_request_obj2(database, connected_flag); 00181 00182 if (!obj) { 00183 ast_log(LOG_ERROR, "No database handle available with the name of '%s' (check res_odbc.conf)\n", database); 00184 ast_string_field_free_memory(&cps); 00185 return NULL; 00186 } 00187 00188 va_copy(aq, ap); 00189 newparam = va_arg(aq, const char *); 00190 if (!newparam) { 00191 va_end(aq); 00192 ast_odbc_release_obj(obj); 00193 ast_string_field_free_memory(&cps); 00194 return NULL; 00195 } 00196 va_arg(aq, const char *); 00197 op = !strchr(newparam, ' ') ? " =" : ""; 00198 snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?%s", table, newparam, op, 00199 strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : ""); 00200 while((newparam = va_arg(aq, const char *))) { 00201 op = !strchr(newparam, ' ') ? " =" : ""; 00202 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?%s", newparam, op, 00203 strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : ""); 00204 va_arg(aq, const char *); 00205 } 00206 va_end(aq); 00207 00208 va_copy(cps.ap, ap); 00209 stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps); 00210 va_end(cps.ap); 00211 00212 if (!stmt) { 00213 ast_odbc_release_obj(obj); 00214 ast_string_field_free_memory(&cps); 00215 return NULL; 00216 } 00217 00218 res = SQLNumResultCols(stmt, &colcount); 00219 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00220 ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql); 00221 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00222 ast_odbc_release_obj(obj); 00223 ast_string_field_free_memory(&cps); 00224 return NULL; 00225 } 00226 00227 res = SQLFetch(stmt); 00228 if (res == SQL_NO_DATA) { 00229 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00230 ast_odbc_release_obj(obj); 00231 ast_string_field_free_memory(&cps); 00232 return NULL; 00233 } 00234 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00235 ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); 00236 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00237 ast_odbc_release_obj(obj); 00238 ast_string_field_free_memory(&cps); 00239 return NULL; 00240 } 00241 for (x = 0; x < colcount; x++) { 00242 rowdata[0] = '\0'; 00243 colsize = 0; 00244 collen = sizeof(coltitle); 00245 res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen, 00246 &datatype, &colsize, &decimaldigits, &nullable); 00247 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00248 ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql); 00249 if (var) 00250 ast_variables_destroy(var); 00251 ast_odbc_release_obj(obj); 00252 ast_string_field_free_memory(&cps); 00253 return NULL; 00254 } 00255 00256 indicator = 0; 00257 res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), &indicator); 00258 if (indicator == SQL_NULL_DATA) 00259 rowdata[0] = '\0'; 00260 else if (ast_strlen_zero(rowdata)) { 00261 /* Because we encode the empty string for a NULL, we will encode 00262 * actual empty strings as a string containing a single whitespace. */ 00263 ast_copy_string(rowdata, " ", sizeof(rowdata)); 00264 } 00265 00266 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00267 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); 00268 if (var) 00269 ast_variables_destroy(var); 00270 ast_odbc_release_obj(obj); 00271 return NULL; 00272 } 00273 stringp = rowdata; 00274 while (stringp) { 00275 chunk = strsep(&stringp, ";"); 00276 if (!ast_strlen_zero(ast_strip(chunk))) { 00277 if (strchr(chunk, '^')) { 00278 decode_chunk(chunk); 00279 } 00280 if (prev) { 00281 prev->next = ast_variable_new(coltitle, chunk, ""); 00282 if (prev->next) { 00283 prev = prev->next; 00284 } 00285 } else { 00286 prev = var = ast_variable_new(coltitle, chunk, ""); 00287 } 00288 } 00289 } 00290 } 00291 00292 00293 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00294 ast_odbc_release_obj(obj); 00295 ast_string_field_free_memory(&cps); 00296 return var; 00297 }
static int reload_module | ( | void | ) | [static] |
static int require_odbc | ( | const char * | database, | |
const char * | table, | |||
va_list | ap | |||
) | [static] |
Definition at line 993 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.
00994 { 00995 struct odbc_cache_tables *tableptr = ast_odbc_find_table(database, table); 00996 struct odbc_cache_columns *col; 00997 char *elm; 00998 int type, size; 00999 01000 if (!tableptr) { 01001 return -1; 01002 } 01003 01004 while ((elm = va_arg(ap, char *))) { 01005 type = va_arg(ap, require_type); 01006 size = va_arg(ap, int); 01007 /* Check if the field matches the criteria */ 01008 AST_RWLIST_TRAVERSE(&tableptr->columns, col, list) { 01009 if (strcmp(col->name, elm) == 0) { 01010 /* Type check, first. Some fields are more particular than others */ 01011 switch (col->type) { 01012 case SQL_CHAR: 01013 case SQL_VARCHAR: 01014 case SQL_LONGVARCHAR: 01015 #ifdef HAVE_ODBC_WCHAR 01016 case SQL_WCHAR: 01017 case SQL_WVARCHAR: 01018 case SQL_WLONGVARCHAR: 01019 #endif 01020 case SQL_BINARY: 01021 case SQL_VARBINARY: 01022 case SQL_LONGVARBINARY: 01023 case SQL_GUID: 01024 #define CHECK_SIZE(n) \ 01025 if (col->size < n) { \ 01026 warn_length(col, n); \ 01027 } \ 01028 break; 01029 switch (type) { 01030 case RQ_UINTEGER1: CHECK_SIZE(3) /* 255 */ 01031 case RQ_INTEGER1: CHECK_SIZE(4) /* -128 */ 01032 case RQ_UINTEGER2: CHECK_SIZE(5) /* 65535 */ 01033 case RQ_INTEGER2: CHECK_SIZE(6) /* -32768 */ 01034 case RQ_UINTEGER3: /* 16777215 */ 01035 case RQ_INTEGER3: CHECK_SIZE(8) /* -8388608 */ 01036 case RQ_DATE: /* 2008-06-09 */ 01037 case RQ_UINTEGER4: CHECK_SIZE(10) /* 4200000000 */ 01038 case RQ_INTEGER4: CHECK_SIZE(11) /* -2100000000 */ 01039 case RQ_DATETIME: /* 2008-06-09 16:03:47 */ 01040 case RQ_UINTEGER8: CHECK_SIZE(19) /* trust me */ 01041 case RQ_INTEGER8: CHECK_SIZE(20) /* ditto */ 01042 case RQ_FLOAT: 01043 case RQ_CHAR: CHECK_SIZE(size) 01044 } 01045 #undef CHECK_SIZE 01046 break; 01047 case SQL_TYPE_DATE: 01048 if (type != RQ_DATE) { 01049 warn_type(col, type); 01050 } 01051 break; 01052 case SQL_TYPE_TIMESTAMP: 01053 case SQL_TIMESTAMP: 01054 if (type != RQ_DATE && type != RQ_DATETIME) { 01055 warn_type(col, type); 01056 } 01057 break; 01058 case SQL_BIT: 01059 warn_length(col, size); 01060 break; 01061 #define WARN_TYPE_OR_LENGTH(n) \ 01062 if (!ast_rq_is_int(type)) { \ 01063 warn_type(col, type); \ 01064 } else { \ 01065 warn_length(col, n); \ 01066 } 01067 case SQL_TINYINT: 01068 if (type != RQ_UINTEGER1) { 01069 WARN_TYPE_OR_LENGTH(size) 01070 } 01071 break; 01072 case SQL_C_STINYINT: 01073 if (type != RQ_INTEGER1) { 01074 WARN_TYPE_OR_LENGTH(size) 01075 } 01076 break; 01077 case SQL_C_USHORT: 01078 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_UINTEGER2) { 01079 WARN_TYPE_OR_LENGTH(size) 01080 } 01081 break; 01082 case SQL_SMALLINT: 01083 case SQL_C_SSHORT: 01084 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_INTEGER2) { 01085 WARN_TYPE_OR_LENGTH(size) 01086 } 01087 break; 01088 case SQL_C_ULONG: 01089 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && 01090 type != RQ_UINTEGER2 && type != RQ_INTEGER2 && 01091 type != RQ_UINTEGER3 && type != RQ_INTEGER3 && 01092 type != RQ_INTEGER4) { 01093 WARN_TYPE_OR_LENGTH(size) 01094 } 01095 break; 01096 case SQL_INTEGER: 01097 case SQL_C_SLONG: 01098 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && 01099 type != RQ_UINTEGER2 && type != RQ_INTEGER2 && 01100 type != RQ_UINTEGER3 && type != RQ_INTEGER3 && 01101 type != RQ_INTEGER4) { 01102 WARN_TYPE_OR_LENGTH(size) 01103 } 01104 break; 01105 case SQL_C_UBIGINT: 01106 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && 01107 type != RQ_UINTEGER2 && type != RQ_INTEGER2 && 01108 type != RQ_UINTEGER3 && type != RQ_INTEGER3 && 01109 type != RQ_UINTEGER4 && type != RQ_INTEGER4 && 01110 type != RQ_INTEGER8) { 01111 WARN_TYPE_OR_LENGTH(size) 01112 } 01113 break; 01114 case SQL_BIGINT: 01115 case SQL_C_SBIGINT: 01116 if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && 01117 type != RQ_UINTEGER2 && type != RQ_INTEGER2 && 01118 type != RQ_UINTEGER3 && type != RQ_INTEGER3 && 01119 type != RQ_UINTEGER4 && type != RQ_INTEGER4 && 01120 type != RQ_INTEGER8) { 01121 WARN_TYPE_OR_LENGTH(size) 01122 } 01123 break; 01124 #undef WARN_TYPE_OR_LENGTH 01125 case SQL_NUMERIC: 01126 case SQL_DECIMAL: 01127 case SQL_FLOAT: 01128 case SQL_REAL: 01129 case SQL_DOUBLE: 01130 if (!ast_rq_is_int(type) && type != RQ_FLOAT) { 01131 warn_type(col, type); 01132 } 01133 break; 01134 default: 01135 ast_log(LOG_WARNING, "Realtime table %s@%s: column type (%d) unrecognized for column '%s'\n", table, database, col->type, elm); 01136 } 01137 break; 01138 } 01139 } 01140 if (!col) { 01141 ast_log(LOG_WARNING, "Realtime table %s@%s requires column '%s', but that column does not exist!\n", table, database, elm); 01142 } 01143 } 01144 AST_RWLIST_UNLOCK(&tableptr->columns); 01145 return 0; 01146 }
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 731 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_obj2, custom_prepare(), LOG_WARNING, RES_ODBC_CONNECTED, and custom_prepare_struct::sql.
00732 { 00733 struct odbc_obj *obj; 00734 SQLHSTMT stmt; 00735 char sql[256]; 00736 char keys[256]; 00737 char vals[256]; 00738 SQLLEN rowcount=0; 00739 const char *newparam; 00740 int res; 00741 va_list aq; 00742 struct custom_prepare_struct cps = { .sql = sql, .extra = NULL }; 00743 struct ast_flags connected_flag = { RES_ODBC_CONNECTED }; 00744 00745 if (!table) { 00746 return -1; 00747 } 00748 00749 obj = ast_odbc_request_obj2(database, connected_flag); 00750 if (!obj) { 00751 return -1; 00752 } 00753 00754 va_copy(aq, ap); 00755 00756 newparam = va_arg(aq, const char *); 00757 if (!newparam) { 00758 va_end(aq); 00759 ast_odbc_release_obj(obj); 00760 return -1; 00761 } 00762 va_arg(aq, const char *); 00763 snprintf(keys, sizeof(keys), "%s", newparam); 00764 ast_copy_string(vals, "?", sizeof(vals)); 00765 while ((newparam = va_arg(aq, const char *))) { 00766 snprintf(keys + strlen(keys), sizeof(keys) - strlen(keys), ", %s", newparam); 00767 snprintf(vals + strlen(vals), sizeof(vals) - strlen(vals), ", ?"); 00768 va_arg(aq, const char *); 00769 } 00770 va_end(aq); 00771 snprintf(sql, sizeof(sql), "INSERT INTO %s (%s) VALUES (%s)", table, keys, vals); 00772 00773 00774 va_copy(cps.ap, ap); 00775 stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps); 00776 va_end(cps.ap); 00777 00778 if (!stmt) { 00779 ast_odbc_release_obj(obj); 00780 return -1; 00781 } 00782 00783 res = SQLRowCount(stmt, &rowcount); 00784 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00785 ast_odbc_release_obj(obj); 00786 00787 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00788 ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql); 00789 return -1; 00790 } 00791 00792 if (rowcount >= 0) 00793 return (int)rowcount; 00794 00795 return -1; 00796 }
static int unload_module | ( | void | ) | [static] |
Definition at line 1168 of file res_config_odbc.c.
References ast_config_engine_deregister(), ast_verb, and odbc_engine.
01169 { 01170 ast_config_engine_deregister(&odbc_engine); 01171 01172 ast_verb(1, "res_config_odbc unloaded.\n"); 01173 return 0; 01174 }
static int unload_odbc | ( | const char * | a, | |
const char * | b | |||
) | [static] |
Definition at line 1150 of file res_config_odbc.c.
References ast_odbc_clear_cache().
01151 { 01152 return ast_odbc_clear_cache(a, b); 01153 }
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). |
number | of rows affected | |
-1 | on failure |
Definition at line 679 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().
00680 { 00681 struct odbc_obj *obj; 00682 SQLHSTMT stmt; 00683 struct update2_prepare_struct ups = { .database = database, .table = table, }; 00684 struct ast_str *sql; 00685 int res; 00686 SQLLEN rowcount = 0; 00687 00688 if (!(obj = ast_odbc_request_obj(database, 0))) { 00689 return -1; 00690 } 00691 00692 va_copy(ups.ap, ap); 00693 if (!(stmt = ast_odbc_prepare_and_execute(obj, update2_prepare, &ups))) { 00694 va_end(ups.ap); 00695 ast_odbc_release_obj(obj); 00696 return -1; 00697 } 00698 va_end(ups.ap); 00699 00700 res = SQLRowCount(stmt, &rowcount); 00701 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00702 ast_odbc_release_obj(obj); 00703 00704 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00705 /* Since only a single thread can access this memory, we can retrieve what would otherwise be lost. */ 00706 sql = ast_str_thread_get(&sql_buf, 16); 00707 ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n", ast_str_buffer(sql)); 00708 return -1; 00709 } 00710 00711 if (rowcount >= 0) { 00712 return (int)rowcount; 00713 } 00714 00715 return -1; 00716 }
static SQLHSTMT update2_prepare | ( | struct odbc_obj * | obj, | |
void * | data | |||
) | [static] |
Definition at line 581 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().
00582 { 00583 int res, x = 1, first = 1; 00584 struct update2_prepare_struct *ups = data; 00585 const char *newparam, *newval; 00586 struct ast_str *sql = ast_str_thread_get(&sql_buf, 16); 00587 SQLHSTMT stmt; 00588 va_list ap; 00589 struct odbc_cache_tables *tableptr = ast_odbc_find_table(ups->database, ups->table); 00590 00591 if (!sql) { 00592 if (tableptr) { 00593 ast_odbc_release_table(tableptr); 00594 } 00595 return NULL; 00596 } 00597 00598 if (!tableptr) { 00599 ast_log(LOG_ERROR, "Could not retrieve metadata for table '%s@%s'. Update will fail!\n", ups->table, ups->database); 00600 return NULL; 00601 } 00602 00603 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt); 00604 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00605 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n"); 00606 ast_odbc_release_table(tableptr); 00607 return NULL; 00608 } 00609 00610 ast_str_set(&sql, 0, "UPDATE %s SET ", ups->table); 00611 00612 /* Start by finding the second set of parameters */ 00613 va_copy(ap, ups->ap); 00614 00615 while ((newparam = va_arg(ap, const char *))) { 00616 newval = va_arg(ap, const char *); 00617 } 00618 00619 while ((newparam = va_arg(ap, const char *))) { 00620 newval = va_arg(ap, const char *); 00621 if (ast_odbc_find_column(tableptr, newparam)) { 00622 ast_str_append(&sql, 0, "%s%s=? ", first ? "" : ", ", newparam); 00623 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL); 00624 first = 0; 00625 } else { 00626 ast_log(LOG_NOTICE, "Not updating column '%s' in '%s@%s' because that column does not exist!\n", newparam, ups->table, ups->database); 00627 } 00628 } 00629 va_end(ap); 00630 00631 ast_str_append(&sql, 0, "WHERE"); 00632 first = 1; 00633 00634 /* Restart search, because we need to add the search parameters */ 00635 va_copy(ap, ups->ap); 00636 00637 while ((newparam = va_arg(ap, const char *))) { 00638 newval = va_arg(ap, const char *); 00639 if (!ast_odbc_find_column(tableptr, newparam)) { 00640 va_end(ap); 00641 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); 00642 ast_odbc_release_table(tableptr); 00643 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00644 return NULL; 00645 } 00646 ast_str_append(&sql, 0, "%s %s=?", first ? "" : " AND", newparam); 00647 SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL); 00648 first = 0; 00649 } 00650 va_end(ap); 00651 00652 /* Done with the table metadata */ 00653 ast_odbc_release_table(tableptr); 00654 00655 res = SQLPrepare(stmt, (unsigned char *)ast_str_buffer(sql), SQL_NTS); 00656 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00657 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", ast_str_buffer(sql)); 00658 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00659 return NULL; 00660 } 00661 00662 return stmt; 00663 }
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 481 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_obj2, ast_string_field_free_memory, ast_string_field_init, ast_strlen_zero(), custom_prepare(), LOG_WARNING, odbc_cache_columns::nullable, RES_ODBC_CONNECTED, custom_prepare_struct::skip, custom_prepare_struct::sql, and odbc_cache_columns::type.
00482 { 00483 struct odbc_obj *obj; 00484 SQLHSTMT stmt; 00485 char sql[256]; 00486 SQLLEN rowcount=0; 00487 const char *newparam; 00488 int res, count = 1; 00489 va_list aq; 00490 struct custom_prepare_struct cps = { .sql = sql, .extra = lookup }; 00491 struct odbc_cache_tables *tableptr; 00492 struct odbc_cache_columns *column = NULL; 00493 struct ast_flags connected_flag = { RES_ODBC_CONNECTED }; 00494 00495 if (!table) { 00496 return -1; 00497 } 00498 00499 if (ast_string_field_init(&cps, 256)) { 00500 return -1; 00501 } 00502 00503 tableptr = ast_odbc_find_table(database, table); 00504 if (!(obj = ast_odbc_request_obj2(database, connected_flag))) { 00505 ast_odbc_release_table(tableptr); 00506 ast_string_field_free_memory(&cps); 00507 return -1; 00508 } 00509 00510 va_copy(aq, ap); 00511 newparam = va_arg(aq, const char *); 00512 if (!newparam) { 00513 va_end(aq); 00514 ast_odbc_release_obj(obj); 00515 ast_odbc_release_table(tableptr); 00516 ast_string_field_free_memory(&cps); 00517 return -1; 00518 } 00519 va_arg(aq, const char *); 00520 00521 if (tableptr && !ast_odbc_find_column(tableptr, newparam)) { 00522 ast_log(LOG_WARNING, "Key field '%s' does not exist in table '%s@%s'. Update will fail\n", newparam, table, database); 00523 } 00524 00525 snprintf(sql, sizeof(sql), "UPDATE %s SET %s=?", table, newparam); 00526 while((newparam = va_arg(aq, const char *))) { 00527 va_arg(aq, const char *); 00528 if ((tableptr && (column = ast_odbc_find_column(tableptr, newparam))) || count > 63) { 00529 /* NULL test for integer-based columns */ 00530 if (ast_strlen_zero(newparam) && tableptr && column && column->nullable && count < 64 && 00531 (column->type == SQL_INTEGER || column->type == SQL_BIGINT || 00532 column->type == SQL_SMALLINT || column->type == SQL_TINYINT || 00533 column->type == SQL_NUMERIC || column->type == SQL_DECIMAL)) { 00534 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s=NULL", newparam); 00535 cps.skip |= (1LL << count); 00536 } else { 00537 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s=?", newparam); 00538 } 00539 } else { /* the column does not exist in the table */ 00540 cps.skip |= (1LL << count); 00541 } 00542 count++; 00543 } 00544 va_end(aq); 00545 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s=?", keyfield); 00546 ast_odbc_release_table(tableptr); 00547 00548 va_copy(cps.ap, ap); 00549 stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps); 00550 va_end(cps.ap); 00551 00552 if (!stmt) { 00553 ast_odbc_release_obj(obj); 00554 ast_string_field_free_memory(&cps); 00555 return -1; 00556 } 00557 00558 res = SQLRowCount(stmt, &rowcount); 00559 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00560 ast_odbc_release_obj(obj); 00561 ast_string_field_free_memory(&cps); 00562 00563 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00564 ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql); 00565 return -1; 00566 } 00567 00568 if (rowcount >= 0) { 00569 return (int) rowcount; 00570 } 00571 00572 return -1; 00573 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_REALTIME_DRIVER, } [static] |
Definition at line 1193 of file res_config_odbc.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1193 of file res_config_odbc.c.
struct ast_config_engine odbc_engine [static] |
Definition at line 1155 of file res_config_odbc.c.
Referenced by load_module(), and unload_module().
struct ast_threadstorage sql_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_sql_buf , .custom_init = NULL , } [static] |
Definition at line 50 of file res_config_odbc.c.