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