Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Functions | Variables
res_config_odbc.c File Reference

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"
#include "asterisk/stringfields.h"
Include dependency graph for res_config_odbc.c:

Go to the source code of this file.

Data Structures

struct  config_odbc_obj
 
struct  custom_prepare_struct
 
struct  update2_prepare_struct
 

Macros

#define CHECK_SIZE(n)
 
#define ENCODE_CHUNK(buffer, s)
 
#define SQL_BUF_SIZE   1024
 
#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_rowdata_buf (void)
 
static void __init_sql_buf (void)
 
static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static struct ast_configconfig_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, const struct ast_variable *fields)
 Excute an DELETE query. More...
 
static int is_text (const struct odbc_cache_columns *column)
 
static SQLHSTMT length_determination_odbc_prepare (struct odbc_obj *obj, void *data)
 
static int load_module (void)
 
static struct ast_configrealtime_multi_odbc (const char *database, const char *table, const struct ast_variable *fields)
 Excute an Select query and return ast_config list. More...
 
static struct ast_variablerealtime_odbc (const char *database, const char *table, const struct ast_variable *fields)
 Excute an SQL query and return ast_variable list. More...
 
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, const struct ast_variable *fields)
 Excute an INSERT query. More...
 
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, const struct ast_variable *lookup_fields, const struct ast_variable *update_fields)
 Execute an UPDATE query. More...
 
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, const struct ast_variable *fields)
 Excute an UPDATE query. More...
 

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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_REALTIME_DRIVER, .requires = "extconfig,res_odbc", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_config_engine odbc_engine
 
static struct ast_threadstorage rowdata_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_rowdata_buf , .custom_init = NULL , }
 
static struct ast_threadstorage sql_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_sql_buf , .custom_init = NULL , }
 

Detailed Description

odbc+odbc plugin for portable configuration engine

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Anthony Minessale II anthm.nosp@m.ct@y.nosp@m.ahoo..nosp@m.com

Definition in file res_config_odbc.c.

Macro Definition Documentation

◆ CHECK_SIZE

#define CHECK_SIZE (   n)
Value:
if (col->size < n) { \
warn_length(col, n); \
} \
break;

Referenced by require_odbc().

◆ ENCODE_CHUNK

#define ENCODE_CHUNK (   buffer,
 
)

Definition at line 65 of file res_config_odbc.c.

Referenced by custom_prepare().

◆ SQL_BUF_SIZE

#define SQL_BUF_SIZE   1024

Initial SQL query buffer size to allocate.

Definition at line 50 of file res_config_odbc.c.

Referenced by config_odbc(), destroy_odbc(), realtime_multi_odbc(), realtime_odbc(), store_odbc(), update2_odbc(), update2_prepare(), and update_odbc().

◆ warn_length

#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 1073 of file res_config_odbc.c.

Referenced by require_odbc().

◆ warn_type

#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 1074 of file res_config_odbc.c.

Referenced by require_odbc().

◆ WARN_TYPE_OR_LENGTH

#define WARN_TYPE_OR_LENGTH (   n)
Value:
if (!ast_rq_is_int(type)) { \
warn_type(col, type); \
} else { \
warn_length(col, n); \
}
static const char type[]
Definition: chan_ooh323.c:109
int ast_rq_is_int(require_type type)
Check if require type is an integer type.

Referenced by require_odbc().

Function Documentation

◆ __init_rowdata_buf()

static void __init_rowdata_buf ( void  )
static

Definition at line 53 of file res_config_odbc.c.

55 {

◆ __init_sql_buf()

static void __init_sql_buf ( void  )
static

Definition at line 52 of file res_config_odbc.c.

55 {

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1277 of file res_config_odbc.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1277 of file res_config_odbc.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 1277 of file res_config_odbc.c.

◆ config_odbc()

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 941 of file res_config_odbc.c.

References ast_category_append(), ast_category_new_dynamic, ast_config_get_current_category(), ast_config_internal_load(), ast_free, ast_log, ast_malloc, ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj2, ast_str_append(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_variable_append(), ast_variable_new, config_odbc_obj::cat_metric, config_odbc_obj::category, config_odbc_prepare(), last, length_determination_odbc_prepare(), LOG_NOTICE, LOG_WARNING, NULL, RES_ODBC_CONNECTED, config_odbc_obj::sql, sql_buf, SQL_BUF_SIZE, config_odbc_obj::var_name, config_odbc_obj::var_val, and config_odbc_obj::var_val_size.

942 {
943  struct ast_variable *new_v;
944  struct ast_category *cur_cat;
945  int res = 0;
946  struct odbc_obj *obj;
948  unsigned int last_cat_metric = 0;
949  SQLSMALLINT rowcount = 0;
950  SQLHSTMT stmt;
951  char last[128] = "";
952  struct config_odbc_obj q;
953  struct ast_flags loader_flags = { 0 };
954  struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
955 
956  memset(&q, 0, sizeof(q));
957 
958  if (!file || !strcmp (file, "res_config_odbc.conf") || !sql) {
959  return NULL; /* cant configure myself with myself ! */
960  }
961 
962  obj = ast_odbc_request_obj2(database, connected_flag);
963  if (!obj)
964  return NULL;
965 
966  ast_str_set(&sql, 0, "SELECT MAX(LENGTH(var_val)) FROM %s WHERE filename='%s'",
967  table, file);
968  q.sql = ast_str_buffer(sql);
969 
971  if (!stmt) {
972  ast_log(LOG_WARNING, "SQL select error! [%s]\n", ast_str_buffer(sql));
974  return NULL;
975  }
976 
977  res = SQLNumResultCols(stmt, &rowcount);
978 
979  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
980  ast_log(LOG_WARNING, "SQL NumResultCols error! [%s]\n", ast_str_buffer(sql));
981  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
983  return NULL;
984  }
985 
986  if (!rowcount) {
987  ast_log(LOG_NOTICE, "found nothing\n");
989  return cfg;
990  }
991 
992  /* There will be only one result for this, the maximum length of a variable value */
993  if (SQLFetch(stmt) == SQL_NO_DATA) {
994  ast_log(LOG_NOTICE, "Failed to determine maximum length of a configuration value\n");
995  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
997  return NULL;
998  }
999 
1000  /* Reset stuff to a fresh state for the actual query which will retrieve all configuration */
1001  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1002 
1003  ast_str_set(&sql, 0, "SELECT cat_metric, category, var_name, var_val FROM %s ", table);
1004  ast_str_append(&sql, 0, "WHERE filename='%s' AND commented=0 ", file);
1005  ast_str_append(&sql, 0, "ORDER BY cat_metric DESC, var_metric ASC, category, var_name ");
1006  q.sql = ast_str_buffer(sql);
1007 
1008  q.var_val_size += 1;
1009  q.var_val = ast_malloc(q.var_val_size);
1010  if (!q.var_val) {
1011  ast_log(LOG_WARNING, "Could not create buffer for reading in configuration values for '%s'\n", file);
1012  ast_odbc_release_obj(obj);
1013  return NULL;
1014  }
1015 
1017  if (!stmt) {
1018  ast_log(LOG_WARNING, "SQL select error! [%s]\n", ast_str_buffer(sql));
1019  ast_odbc_release_obj(obj);
1020  ast_free(q.var_val);
1021  return NULL;
1022  }
1023 
1024  res = SQLNumResultCols(stmt, &rowcount);
1025 
1026  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
1027  ast_log(LOG_WARNING, "SQL NumResultCols error! [%s]\n", ast_str_buffer(sql));
1028  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1029  ast_odbc_release_obj(obj);
1030  ast_free(q.var_val);
1031  return NULL;
1032  }
1033 
1034  if (!rowcount) {
1035  ast_log(LOG_NOTICE, "found nothing\n");
1036  ast_odbc_release_obj(obj);
1037  ast_free(q.var_val);
1038  return cfg;
1039  }
1040 
1041  cur_cat = ast_config_get_current_category(cfg);
1042 
1043  while ((res = SQLFetch(stmt)) != SQL_NO_DATA) {
1044  if (!strcmp (q.var_name, "#include")) {
1045  if (!ast_config_internal_load(q.var_val, cfg, loader_flags, "", who_asked)) {
1046  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1047  ast_odbc_release_obj(obj);
1048  ast_free(q.var_val);
1049  return NULL;
1050  }
1051  continue;
1052  }
1053  if (strcmp(last, q.category) || last_cat_metric != q.cat_metric) {
1054  cur_cat = ast_category_new_dynamic(q.category);
1055  if (!cur_cat) {
1056  break;
1057  }
1058  strcpy(last, q.category);
1059  last_cat_metric = q.cat_metric;
1060  ast_category_append(cfg, cur_cat);
1061  }
1062 
1063  new_v = ast_variable_new(q.var_name, q.var_val, "");
1064  ast_variable_append(cur_cat, new_v);
1065  }
1066 
1067  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1068  ast_odbc_release_obj(obj);
1069  ast_free(q.var_val);
1070  return cfg;
1071 }
static SQLHSTMT config_odbc_prepare(struct odbc_obj *obj, void *data)
#define SQL_BUF_SIZE
static SQLHSTMT length_determination_odbc_prepare(struct odbc_obj *obj, void *data)
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
Structure for variables, used for configurations and for channel variables.
struct ast_category * ast_config_get_current_category(const struct ast_config *cfg)
Retrieve the current category name being built.
Definition: extconf.c:2783
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
#define ast_odbc_request_obj2(a, b)
Definition: res_odbc.h:121
#define NULL
Definition: resample.c:96
struct ast_config * ast_config_internal_load(const char *configfile, struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl_file, const char *who_asked)
Definition: main/config.c:3112
static char * table
Definition: cdr_odbc.c:58
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
#define ast_log
Definition: astobj2.c:42
ODBC container.
Definition: res_odbc.h:46
struct sla_ringing_trunk * last
Definition: app_meetme.c:1092
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
#define ast_variable_new(name, value, filename)
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
#define LOG_NOTICE
Definition: logger.h:263
#define ast_free(a)
Definition: astmm.h:182
static struct ast_threadstorage sql_buf
#define ast_category_new_dynamic(name)
Create a category that is not backed by a file.
Structure used to handle boolean flags.
Definition: utils.h:199
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition: extconf.c:1178
void ast_category_append(struct ast_config *config, struct ast_category *cat)
Appends a category to a config.
Definition: extconf.c:2835
SQLHSTMT ast_odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT(*prepare_cb)(struct odbc_obj *obj, void *data), void *data)
Prepares, executes, and returns the resulting statement handle.
Definition: res_odbc.c:407
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:861
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
Definition: res_odbc.c:813

◆ config_odbc_prepare()

static SQLHSTMT config_odbc_prepare ( struct odbc_obj obj,
void *  data 
)
static

Definition at line 914 of file res_config_odbc.c.

References ast_odbc_prepare(), ast_verb, config_odbc_obj::cat_metric, config_odbc_obj::category, odbc_obj::con, config_odbc_obj::err, NULL, config_odbc_obj::sql, config_odbc_obj::var_name, config_odbc_obj::var_val, and config_odbc_obj::var_val_size.

Referenced by config_odbc().

915 {
916  struct config_odbc_obj *q = data;
917  SQLHSTMT sth;
918  int res;
919 
920  res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &sth);
921  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
922  ast_verb(4, "Failure in AllocStatement %d\n", res);
923  return NULL;
924  }
925 
926  res = ast_odbc_prepare(obj, sth, q->sql);
927  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
928  ast_verb(4, "Error in PREPARE %d\n", res);
929  SQLFreeHandle(SQL_HANDLE_STMT, sth);
930  return NULL;
931  }
932 
933  SQLBindCol(sth, 1, SQL_C_ULONG, &q->cat_metric, sizeof(q->cat_metric), &q->err);
934  SQLBindCol(sth, 2, SQL_C_CHAR, q->category, sizeof(q->category), &q->err);
935  SQLBindCol(sth, 3, SQL_C_CHAR, q->var_name, sizeof(q->var_name), &q->err);
936  SQLBindCol(sth, 4, SQL_C_CHAR, q->var_val, q->var_val_size, &q->err);
937 
938  return sth;
939 }
SQLHDBC con
Definition: res_odbc.h:47
unsigned long cat_metric
int ast_odbc_prepare(struct odbc_obj *obj, SQLHSTMT *stmt, const char *sql)
Prepares a SQL query on a statement.
Definition: res_odbc.c:463
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
unsigned long var_val_size

◆ custom_prepare()

static SQLHSTMT custom_prepare ( struct odbc_obj obj,
void *  data 
)
static

Definition at line 101 of file res_config_odbc.c.

References ast_debug, ast_log, ast_odbc_prepare(), ast_odbc_print_errors(), ast_string_field_set, ast_strlen_zero, odbc_obj::con, ENCODE_CHUNK, custom_prepare_struct::encoding, custom_prepare_struct::extra, custom_prepare_struct::fields, LOG_WARNING, ast_variable::name, ast_variable::next, NULL, custom_prepare_struct::skip, custom_prepare_struct::sql, and ast_variable::value.

Referenced by destroy_odbc(), realtime_multi_odbc(), realtime_odbc(), store_odbc(), and update_odbc().

102 {
103  int res, x = 1, count = 0;
104  struct custom_prepare_struct *cps = data;
105  const struct ast_variable *field;
106  char encodebuf[1024];
107  SQLHSTMT stmt;
108 
109  res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
110  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
111  ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
112  return NULL;
113  }
114 
115  ast_debug(1, "Skip: %llu; SQL: %s\n", cps->skip, cps->sql);
116 
117  res = ast_odbc_prepare(obj, stmt, cps->sql);
118  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
119  if (res == SQL_ERROR) {
120  ast_odbc_print_errors(SQL_HANDLE_STMT, stmt, "SQL Prepare");
121  }
122  ast_log(LOG_WARNING, "SQL Prepare failed! [%s]\n", cps->sql);
123  SQLFreeHandle (SQL_HANDLE_STMT, stmt);
124  return NULL;
125  }
126 
127  for (field = cps->fields; field; field = field->next) {
128  const char *newval = field->value;
129 
130  if ((1LL << count++) & cps->skip) {
131  ast_debug(1, "Skipping field '%s'='%s' (%llo/%llo)\n", field->name, newval, 1ULL << (count - 1), cps->skip);
132  continue;
133  }
134  ast_debug(1, "Parameter %d ('%s') = '%s'\n", x, field->name, newval);
135  if (strchr(newval, ';') || strchr(newval, '^')) {
136  ENCODE_CHUNK(encodebuf, newval);
137  ast_string_field_set(cps, encoding[x], encodebuf);
138  newval = cps->encoding[x];
139  }
140  SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL);
141  }
142 
143  if (!ast_strlen_zero(cps->extra)) {
144  const char *newval = cps->extra;
145  ast_debug(1, "Parameter %d = '%s'\n", x, newval);
146  if (strchr(newval, ';') || strchr(newval, '^')) {
147  ENCODE_CHUNK(encodebuf, newval);
148  ast_string_field_set(cps, encoding[x], encodebuf);
149  newval = cps->encoding[x];
150  }
151  SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL);
152  }
153 
154  return stmt;
155 }
SQLHDBC con
Definition: res_odbc.h:47
struct ast_variable * next
#define LOG_WARNING
Definition: logger.h:274
int ast_odbc_prepare(struct odbc_obj *obj, SQLHSTMT *stmt, const char *sql)
Prepares a SQL query on a statement.
Definition: res_odbc.c:463
Structure for variables, used for configurations and for channel variables.
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
const struct ast_variable * fields
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct ast_str * ast_odbc_print_errors(SQLSMALLINT handle_type, SQLHANDLE handle, const char *operation)
Shortcut for printing errors to logs after a failed SQL operation.
Definition: res_odbc.c:524
const ast_string_field encoding[256]
static char * encoding
Definition: cdr_pgsql.c:74
#define ENCODE_CHUNK(buffer, s)
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514
unsigned long long skip

◆ decode_chunk()

static void decode_chunk ( char *  chunk)
static

Definition at line 85 of file res_config_odbc.c.

Referenced by realtime_multi_odbc(), and realtime_odbc().

86 {
87  for (; *chunk; chunk++) {
88  if (*chunk == '^' && strchr("0123456789ABCDEF", chunk[1]) && strchr("0123456789ABCDEF", chunk[2])) {
89  sscanf(chunk + 1, "%02hhX", (unsigned char *)chunk);
90  memmove(chunk + 1, chunk + 3, strlen(chunk + 3) + 1);
91  }
92  }
93 }

◆ destroy_odbc()

static int destroy_odbc ( const char *  database,
const char *  table,
const char *  keyfield,
const char *  lookup,
const struct ast_variable fields 
)
static

Excute an DELETE query.

Parameters
database
table
keyfieldwhere clause field
lookupvalue of field for where clause
aplist 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.

Return values
numberof rows affected
-1on failure

Definition at line 824 of file res_config_odbc.c.

References ast_log, ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj2, ast_str_append(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_string_field_free_memory, ast_string_field_init, custom_prepare(), custom_prepare_struct::extra, custom_prepare_struct::fields, LOG_WARNING, ast_variable::name, ast_variable::next, RES_ODBC_CONNECTED, custom_prepare_struct::sql, sql_buf, and SQL_BUF_SIZE.

825 {
826  struct odbc_obj *obj;
827  SQLHSTMT stmt;
828  SQLLEN rowcount=0;
830  const struct ast_variable *field;
831  int res;
832  struct custom_prepare_struct cps = { .extra = lookup, .fields = fields, };
833  struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
834 
835  if (!table || !sql) {
836  return -1;
837  }
838 
839  obj = ast_odbc_request_obj2(database, connected_flag);
840  if (!obj) {
841  return -1;
842  }
843 
844  ast_str_set(&sql, 0, "DELETE FROM %s WHERE ", table);
845  for (field = fields; field; field = field->next) {
846  ast_str_append(&sql, 0, "%s=? AND ", field->name);
847  }
848  ast_str_append(&sql, 0, "%s=?", keyfield);
849 
850  cps.sql = ast_str_buffer(sql);
851 
852  if (ast_string_field_init(&cps, 256)) {
854  return -1;
855  }
856  stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
858 
859  if (!stmt) {
861  return -1;
862  }
863 
864  res = SQLRowCount(stmt, &rowcount);
865  SQLFreeHandle (SQL_HANDLE_STMT, stmt);
867 
868  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
869  ast_log(LOG_WARNING, "SQL Row Count error! [%s]\n", ast_str_buffer(sql));
870  return -1;
871  }
872 
873  if (rowcount >= 0)
874  return (int)rowcount;
875 
876  return -1;
877 }
#define SQL_BUF_SIZE
struct ast_variable * next
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
Structure for variables, used for configurations and for channel variables.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
#define ast_odbc_request_obj2(a, b)
Definition: res_odbc.h:121
const struct ast_variable * fields
static char * table
Definition: cdr_odbc.c:58
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
#define ast_log
Definition: astobj2.c:42
ODBC container.
Definition: res_odbc.h:46
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static SQLHSTMT custom_prepare(struct odbc_obj *obj, void *data)
static struct ast_threadstorage sql_buf
Structure used to handle boolean flags.
Definition: utils.h:199
SQLHSTMT ast_odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT(*prepare_cb)(struct odbc_obj *obj, void *data), void *data)
Prepares, executes, and returns the resulting statement handle.
Definition: res_odbc.c:407
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:861
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
Definition: res_odbc.c:813
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368

◆ is_text()

static int is_text ( const struct odbc_cache_columns column)
inlinestatic

Definition at line 95 of file res_config_odbc.c.

References odbc_cache_columns::type.

Referenced by update_odbc().

96 {
97  return column->type == SQL_CHAR || column->type == SQL_VARCHAR || column->type == SQL_LONGVARCHAR
98  || column->type == SQL_WCHAR || column->type == SQL_WVARCHAR || column->type == SQL_WLONGVARCHAR;
99 }
SQLSMALLINT type
Definition: res_odbc.h:61

◆ length_determination_odbc_prepare()

static SQLHSTMT length_determination_odbc_prepare ( struct odbc_obj obj,
void *  data 
)
static

Definition at line 890 of file res_config_odbc.c.

References ast_odbc_prepare(), ast_verb, odbc_obj::con, config_odbc_obj::err, NULL, config_odbc_obj::sql, and config_odbc_obj::var_val_size.

Referenced by config_odbc().

891 {
892  struct config_odbc_obj *q = data;
893  SQLHSTMT sth;
894  int res;
895 
896  res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &sth);
897  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
898  ast_verb(4, "Failure in AllocStatement %d\n", res);
899  return NULL;
900  }
901 
902  res = ast_odbc_prepare(obj, sth, q->sql);
903  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
904  ast_verb(4, "Error in PREPARE %d\n", res);
905  SQLFreeHandle(SQL_HANDLE_STMT, sth);
906  return NULL;
907  }
908 
909  SQLBindCol(sth, 1, SQL_C_ULONG, &q->var_val_size, sizeof(q->var_val_size), &q->err);
910 
911  return sth;
912 }
SQLHDBC con
Definition: res_odbc.h:47
int ast_odbc_prepare(struct odbc_obj *obj, SQLHSTMT *stmt, const char *sql)
Prepares a SQL query on a statement.
Definition: res_odbc.c:463
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
unsigned long var_val_size

◆ load_module()

static int load_module ( void  )
static

Definition at line 1258 of file res_config_odbc.c.

References ast_config_engine_register().

Referenced by reload_module().

1259 {
1261 
1262  return 0;
1263 }
int ast_config_engine_register(struct ast_config_engine *newconfig)
Register config engine.
Definition: main/config.c:2990
static struct ast_config_engine odbc_engine

◆ realtime_multi_odbc()

static struct ast_config* realtime_multi_odbc ( const char *  database,
const char *  table,
const struct ast_variable fields 
)
static

Excute an Select query and return ast_config list.

Parameters
database
table
aplist 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.

Return values
varon success
NULLon failure

Definition at line 342 of file res_config_odbc.c.

References ast_category_append(), ast_category_destroy(), ast_category_new_anonymous, 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_str_append(), ast_str_buffer(), ast_str_make_space, ast_str_reset(), ast_str_set(), ast_str_size(), ast_str_strlen(), ast_str_thread_get(), ast_str_update(), 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(), custom_prepare_struct::fields, indicator, LOG_WARNING, ast_variable::name, ast_variable::next, NULL, RES_ODBC_CONNECTED, rowdata_buf, S_OR, custom_prepare_struct::sql, sql_buf, SQL_BUF_SIZE, strcasestr(), strsep(), and var.

343 {
344  struct odbc_obj *obj;
345  SQLHSTMT stmt;
346  char coltitle[256];
348  struct ast_str *rowdata = ast_str_thread_get(&rowdata_buf, 128);
349  const char *initfield;
350  char *op;
351  const struct ast_variable *field = fields;
352  char *stringp;
353  char *chunk;
354  SQLSMALLINT collen;
355  int res;
356  int x;
357  struct ast_variable *var=NULL;
358  struct ast_config *cfg=NULL;
359  struct ast_category *cat=NULL;
360  struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
361  SQLULEN colsize;
362  SQLSMALLINT colcount=0;
363  SQLSMALLINT datatype;
364  SQLSMALLINT decimaldigits;
365  SQLSMALLINT nullable;
366  SQLLEN indicator;
367  struct custom_prepare_struct cps = { .fields = fields, };
368 
369  if (!table || !field || !sql || !rowdata) {
370  return NULL;
371  }
372 
373  obj = ast_odbc_request_obj2(database, connected_flag);
374  if (!obj) {
375  return NULL;
376  }
377 
378  initfield = ast_strdupa(field->name);
379  if ((op = strchr(initfield, ' '))) {
380  *op = '\0';
381  }
382 
383  op = !strchr(field->name, ' ') ? " =" : "";
384  ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s ?%s", table, field->name, op,
385  strcasestr(field->name, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\\\'" : "");
386  while ((field = field->next)) {
387  op = !strchr(field->name, ' ') ? " =" : "";
388  ast_str_append(&sql, 0, " AND %s%s ?%s", field->name, op,
389  strcasestr(field->name, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\\\'" : "");
390  }
391  ast_str_append(&sql, 0, " ORDER BY %s", initfield);
392 
393  cps.sql = ast_str_buffer(sql);
394 
395  if (ast_string_field_init(&cps, 256)) {
397  return NULL;
398  }
399  stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
401 
402  if (!stmt) {
404  return NULL;
405  }
406 
407  res = SQLNumResultCols(stmt, &colcount);
408  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
409  ast_log(LOG_WARNING, "SQL Column Count error! [%s]\n", ast_str_buffer(sql));
410  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
412  return NULL;
413  }
414 
415  cfg = ast_config_new();
416  if (!cfg) {
417  ast_log(LOG_WARNING, "Out of memory!\n");
418  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
420  return NULL;
421  }
422 
423  while ((res=SQLFetch(stmt)) != SQL_NO_DATA) {
424  var = NULL;
425  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
426  ast_log(LOG_WARNING, "SQL Fetch error! [%s]\n", ast_str_buffer(sql));
427  continue;
428  }
430  if (!cat) {
431  continue;
432  }
433  for (x=0;x<colcount;x++) {
434  colsize = 0;
435  collen = sizeof(coltitle);
436  res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen,
437  &datatype, &colsize, &decimaldigits, &nullable);
438  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
439  ast_log(LOG_WARNING, "SQL Describe Column error! [%s]\n", ast_str_buffer(sql));
441  goto next_sql_fetch;
442  }
443 
444  ast_str_reset(rowdata);
445  indicator = 0;
446 
447  res = SQLGetData(stmt, x + 1, SQL_CHAR, ast_str_buffer(rowdata), ast_str_size(rowdata), &indicator);
448  ast_str_update(rowdata);
449  if (indicator == SQL_NULL_DATA) {
450  continue;
451  }
452 
453  if ((res == SQL_SUCCESS) || (res == SQL_SUCCESS_WITH_INFO)) {
454  if (indicator != ast_str_strlen(rowdata)) {
455  /* If the available space was not enough to contain the row data enlarge and read in the rest */
456  ast_str_make_space(&rowdata, indicator + 1);
457  res = SQLGetData(stmt, x + 1, SQL_CHAR, ast_str_buffer(rowdata) + ast_str_strlen(rowdata),
458  ast_str_size(rowdata) - ast_str_strlen(rowdata), &indicator);
459  ast_str_update(rowdata);
460  }
461  }
462 
463  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
464  ast_log(LOG_WARNING, "SQL Get Data error! [%s]\n", ast_str_buffer(sql));
466  goto next_sql_fetch;
467  }
468  stringp = ast_str_buffer(rowdata);
469  if (!strncmp(coltitle, "@", 1)) {
470  /* The '@' prefix indicates it's a sorcery extended field.
471  * Because ast_load_realtime_fields eliminates empty entries and makes blank (single whitespace)
472  * entries empty and keeps them, the empty or NULL values are encoded
473  * as a string containing a single whitespace. */
474  var = ast_variable_new(coltitle, S_OR(stringp," "), "");
475  ast_variable_append(cat, var);
476  } else {
477  while (stringp) {
478  chunk = strsep(&stringp, ";");
479  if (!ast_strlen_zero(ast_strip(chunk))) {
480  if (strchr(chunk, '^')) {
481  decode_chunk(chunk);
482  }
483  if (!strcmp(initfield, coltitle)) {
484  ast_category_rename(cat, chunk);
485  }
486  var = ast_variable_new(coltitle, chunk, "");
487  ast_variable_append(cat, var);
488  }
489  }
490  }
491  }
492  ast_category_append(cfg, cat);
493 next_sql_fetch:;
494  }
495 
496  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
498  return cfg;
499 }
#define SQL_BUF_SIZE
struct ast_variable * next
int ast_odbc_backslash_is_escape(struct odbc_obj *obj)
Checks if the database natively supports backslash as an escape character.
Definition: res_odbc.c:842
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:699
#define LOG_WARNING
Definition: logger.h:274
static int indicator
#define ast_str_make_space(buf, new_len)
Definition: strings.h:780
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
Structure for variables, used for configurations and for channel variables.
#define var
Definition: ast_expr2f.c:614
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
#define ast_odbc_request_obj2(a, b)
Definition: res_odbc.h:121
#define NULL
Definition: resample.c:96
void ast_category_destroy(struct ast_category *cat)
Definition: extconf.c:2847
#define ast_strlen_zero(foo)
Definition: strings.h:52
const struct ast_variable * fields
#define ast_category_new_anonymous()
Create a nameless category that is not backed by a file.
static char * table
Definition: cdr_odbc.c:58
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
void ast_category_rename(struct ast_category *cat, const char *name)
Definition: main/config.c:1362
#define ast_log
Definition: astobj2.c:42
ODBC container.
Definition: res_odbc.h:46
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:219
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define ast_variable_new(name, value, filename)
static struct ast_threadstorage rowdata_buf
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: extconf.c:3276
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static SQLHSTMT custom_prepare(struct odbc_obj *obj, void *data)
char * strcasestr(const char *, const char *)
static struct ast_threadstorage sql_buf
Structure used to handle boolean flags.
Definition: utils.h:199
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition: extconf.c:1178
void ast_category_append(struct ast_config *config, struct ast_category *cat)
Appends a category to a config.
Definition: extconf.c:2835
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:653
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:688
SQLHSTMT ast_odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT(*prepare_cb)(struct odbc_obj *obj, void *data), void *data)
Prepares, executes, and returns the resulting statement handle.
Definition: res_odbc.c:407
char * strsep(char **str, const char *delims)
void ast_str_update(struct ast_str *buf)
Update the length of the buffer, after using ast_str merely as a buffer.
Definition: strings.h:663
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
static void decode_chunk(char *chunk)
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:861
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
Definition: res_odbc.c:813
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368

◆ realtime_odbc()

static struct ast_variable* realtime_odbc ( const char *  database,
const char *  table,
const struct ast_variable fields 
)
static

Excute an SQL query and return ast_variable list.

Parameters
database
table
aplist 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.

Return values
varon success
NULLon failure

Definition at line 170 of file res_config_odbc.c.

References ast_log, ast_odbc_backslash_is_escape(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj2, ast_str_append(), ast_str_buffer(), ast_str_make_space, ast_str_reset(), ast_str_set(), ast_str_size(), ast_str_strlen(), ast_str_thread_get(), ast_str_update(), ast_string_field_free_memory, ast_string_field_init, ast_strip(), ast_strlen_zero, ast_variable_new, ast_variables_destroy(), custom_prepare(), decode_chunk(), custom_prepare_struct::fields, indicator, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, NULL, RES_ODBC_CONNECTED, rowdata_buf, S_OR, custom_prepare_struct::sql, sql_buf, SQL_BUF_SIZE, strcasestr(), strsep(), and var.

171 {
172  struct odbc_obj *obj;
173  SQLHSTMT stmt;
174  char coltitle[256];
176  struct ast_str *rowdata = ast_str_thread_get(&rowdata_buf, 128);
177  char *op;
178  const struct ast_variable *field = fields;
179  char *stringp;
180  char *chunk;
181  SQLSMALLINT collen;
182  int res;
183  int x;
184  struct ast_variable *var=NULL, *prev=NULL;
185  SQLULEN colsize;
186  SQLSMALLINT colcount=0;
187  SQLSMALLINT datatype;
188  SQLSMALLINT decimaldigits;
189  SQLSMALLINT nullable;
190  SQLLEN indicator;
191  struct custom_prepare_struct cps = { .fields = fields, };
192  struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
193 
194  if (!table || !field || !sql || !rowdata) {
195  return NULL;
196  }
197 
198  obj = ast_odbc_request_obj2(database, connected_flag);
199  if (!obj) {
200  ast_log(LOG_ERROR, "No database handle available with the name of '%s' (check res_odbc.conf)\n", database);
201  return NULL;
202  }
203 
204  op = !strchr(field->name, ' ') ? " =" : "";
205  ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s ?%s", table, field->name, op,
206  strcasestr(field->name, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\\\'" : "");
207  while ((field = field->next)) {
208  op = !strchr(field->name, ' ') ? " =" : "";
209  ast_str_append(&sql, 0, " AND %s%s ?%s", field->name, op,
210  strcasestr(field->name, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\\\'" : "");
211  }
212 
213  cps.sql = ast_str_buffer(sql);
214 
215  if (ast_string_field_init(&cps, 256)) {
217  return NULL;
218  }
219  stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
221 
222  if (!stmt) {
224  return NULL;
225  }
226 
227  res = SQLNumResultCols(stmt, &colcount);
228  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
229  ast_log(LOG_WARNING, "SQL Column Count error! [%s]\n", ast_str_buffer(sql));
230  SQLFreeHandle (SQL_HANDLE_STMT, stmt);
232  return NULL;
233  }
234 
235  res = SQLFetch(stmt);
236  if (res == SQL_NO_DATA) {
237  SQLFreeHandle (SQL_HANDLE_STMT, stmt);
239  return NULL;
240  }
241  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
242  ast_log(LOG_WARNING, "SQL Fetch error! [%s]\n", ast_str_buffer(sql));
243  SQLFreeHandle (SQL_HANDLE_STMT, stmt);
245  return NULL;
246  }
247  for (x = 0; x < colcount; x++) {
248  colsize = 0;
249  collen = sizeof(coltitle);
250  res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen,
251  &datatype, &colsize, &decimaldigits, &nullable);
252  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
253  ast_log(LOG_WARNING, "SQL Describe Column error! [%s]\n", ast_str_buffer(sql));
254  if (var)
257  return NULL;
258  }
259 
260  ast_str_reset(rowdata);
261  indicator = 0;
262 
263  res = SQLGetData(stmt, x + 1, SQL_CHAR, ast_str_buffer(rowdata), ast_str_size(rowdata), &indicator);
264  ast_str_update(rowdata);
265  if (indicator == SQL_NULL_DATA) {
266  ast_str_reset(rowdata);
267  } else if (!ast_str_strlen(rowdata)) {
268  /* Because we encode the empty string for a NULL, we will encode
269  * actual empty strings as a string containing a single whitespace. */
270  ast_str_set(&rowdata, -1, "%s", " ");
271  } else if ((res == SQL_SUCCESS) || (res == SQL_SUCCESS_WITH_INFO)) {
272  if (indicator != ast_str_strlen(rowdata)) {
273  /* If the available space was not enough to contain the row data enlarge and read in the rest */
274  ast_str_make_space(&rowdata, indicator + 1);
275  res = SQLGetData(stmt, x + 1, SQL_CHAR, ast_str_buffer(rowdata) + ast_str_strlen(rowdata),
276  ast_str_size(rowdata) - ast_str_strlen(rowdata), &indicator);
277  ast_str_update(rowdata);
278  }
279  }
280 
281  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
282  ast_log(LOG_WARNING, "SQL Get Data error! [%s]\n", ast_str_buffer(sql));
283  if (var)
286  return NULL;
287  }
288 
289  stringp = ast_str_buffer(rowdata);
290  if (!strncmp(coltitle, "@", 1)) {
291  /* The '@' prefix indicates it's a sorcery extended field.
292  * Because ast_load_realtime_fields eliminates empty entries and makes blank (single whitespace)
293  * entries empty and keeps them, the empty or NULL values are encoded
294  * as a string containing a single whitespace. */
295  if (prev) {
296  prev->next = ast_variable_new(coltitle, S_OR(stringp," "), "");
297  if (prev->next) {
298  prev = prev->next;
299  }
300  } else {
301  prev = var = ast_variable_new(coltitle, S_OR(stringp," "), "");
302  }
303  } else {
304  while (stringp) {
305  chunk = strsep(&stringp, ";");
306  if (!ast_strlen_zero(ast_strip(chunk))) {
307  if (strchr(chunk, '^')) {
308  decode_chunk(chunk);
309  }
310  if (prev) {
311  prev->next = ast_variable_new(coltitle, chunk, "");
312  if (prev->next) {
313  prev = prev->next;
314  }
315  } else {
316  prev = var = ast_variable_new(coltitle, chunk, "");
317  }
318  }
319  }
320  }
321  }
322 
323  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
325  return var;
326 }
#define SQL_BUF_SIZE
struct ast_variable * next
int ast_odbc_backslash_is_escape(struct odbc_obj *obj)
Checks if the database natively supports backslash as an escape character.
Definition: res_odbc.c:842
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:699
#define LOG_WARNING
Definition: logger.h:274
static int indicator
#define ast_str_make_space(buf, new_len)
Definition: strings.h:780
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
Structure for variables, used for configurations and for channel variables.
#define var
Definition: ast_expr2f.c:614
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
#define ast_odbc_request_obj2(a, b)
Definition: res_odbc.h:121
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
const struct ast_variable * fields
static char * table
Definition: cdr_odbc.c:58
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
#define ast_log
Definition: astobj2.c:42
ODBC container.
Definition: res_odbc.h:46
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:219
#define ast_variable_new(name, value, filename)
static struct ast_threadstorage rowdata_buf
#define LOG_ERROR
Definition: logger.h:285
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static SQLHSTMT custom_prepare(struct odbc_obj *obj, void *data)
char * strcasestr(const char *, const char *)
static struct ast_threadstorage sql_buf
Structure used to handle boolean flags.
Definition: utils.h:199
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:653
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:688
SQLHSTMT ast_odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT(*prepare_cb)(struct odbc_obj *obj, void *data), void *data)
Prepares, executes, and returns the resulting statement handle.
Definition: res_odbc.c:407
char * strsep(char **str, const char *delims)
void ast_str_update(struct ast_str *buf)
Update the length of the buffer, after using ast_str merely as a buffer.
Definition: strings.h:663
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
static void decode_chunk(char *chunk)
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:861
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
Definition: res_odbc.c:813
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368

◆ reload_module()

static int reload_module ( void  )
static

◆ require_odbc()

static int require_odbc ( const char *  database,
const char *  table,
va_list  ap 
)
static

Definition at line 1076 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, 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.

1077 {
1078  struct odbc_cache_tables *tableptr = ast_odbc_find_table(database, table);
1079  struct odbc_cache_columns *col;
1080  char *elm;
1081  int type, size;
1082 
1083  if (!tableptr) {
1084  return -1;
1085  }
1086 
1087  while ((elm = va_arg(ap, char *))) {
1088  type = va_arg(ap, require_type);
1089  size = va_arg(ap, int);
1090  /* Check if the field matches the criteria */
1091  AST_RWLIST_TRAVERSE(&tableptr->columns, col, list) {
1092  if (strcmp(col->name, elm) == 0) {
1093  /* Type check, first. Some fields are more particular than others */
1094  switch (col->type) {
1095  case SQL_CHAR:
1096  case SQL_VARCHAR:
1097  case SQL_LONGVARCHAR:
1098 #ifdef HAVE_ODBC_WCHAR
1099  case SQL_WCHAR:
1100  case SQL_WVARCHAR:
1101  case SQL_WLONGVARCHAR:
1102 #endif
1103  case SQL_BINARY:
1104  case SQL_VARBINARY:
1105  case SQL_LONGVARBINARY:
1106  case SQL_GUID:
1107 #define CHECK_SIZE(n) \
1108  if (col->size < n) { \
1109  warn_length(col, n); \
1110  } \
1111  break;
1112  switch (type) {
1113  case RQ_UINTEGER1: CHECK_SIZE(3) /* 255 */
1114  case RQ_INTEGER1: CHECK_SIZE(4) /* -128 */
1115  case RQ_UINTEGER2: CHECK_SIZE(5) /* 65535 */
1116  case RQ_INTEGER2: CHECK_SIZE(6) /* -32768 */
1117  case RQ_UINTEGER3: /* 16777215 */
1118  case RQ_INTEGER3: CHECK_SIZE(8) /* -8388608 */
1119  case RQ_DATE: /* 2008-06-09 */
1120  case RQ_UINTEGER4: CHECK_SIZE(10) /* 4200000000 */
1121  case RQ_INTEGER4: CHECK_SIZE(11) /* -2100000000 */
1122  case RQ_DATETIME: /* 2008-06-09 16:03:47 */
1123  case RQ_UINTEGER8: CHECK_SIZE(19) /* trust me */
1124  case RQ_INTEGER8: CHECK_SIZE(20) /* ditto */
1125  case RQ_FLOAT:
1126  case RQ_CHAR: CHECK_SIZE(size)
1127  }
1128 #undef CHECK_SIZE
1129  break;
1130  case SQL_TYPE_DATE:
1131  if (type != RQ_DATE) {
1132  warn_type(col, type);
1133  }
1134  break;
1135  case SQL_TYPE_TIMESTAMP:
1136  case SQL_TIMESTAMP:
1137  if (type != RQ_DATE && type != RQ_DATETIME) {
1138  warn_type(col, type);
1139  }
1140  break;
1141  case SQL_BIT:
1142  warn_length(col, size);
1143  break;
1144 #define WARN_TYPE_OR_LENGTH(n) \
1145  if (!ast_rq_is_int(type)) { \
1146  warn_type(col, type); \
1147  } else { \
1148  warn_length(col, n); \
1149  }
1150  case SQL_TINYINT:
1151  if (type != RQ_UINTEGER1) {
1152  WARN_TYPE_OR_LENGTH(size)
1153  }
1154  break;
1155  case SQL_C_STINYINT:
1156  if (type != RQ_INTEGER1) {
1157  WARN_TYPE_OR_LENGTH(size)
1158  }
1159  break;
1160  case SQL_C_USHORT:
1161  if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_UINTEGER2) {
1162  WARN_TYPE_OR_LENGTH(size)
1163  }
1164  break;
1165  case SQL_SMALLINT:
1166  case SQL_C_SSHORT:
1167  if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_INTEGER2) {
1168  WARN_TYPE_OR_LENGTH(size)
1169  }
1170  break;
1171  case SQL_C_ULONG:
1172  if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
1173  type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
1174  type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
1175  type != RQ_INTEGER4) {
1176  WARN_TYPE_OR_LENGTH(size)
1177  }
1178  break;
1179  case SQL_INTEGER:
1180  case SQL_C_SLONG:
1181  if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
1182  type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
1183  type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
1184  type != RQ_INTEGER4) {
1185  WARN_TYPE_OR_LENGTH(size)
1186  }
1187  break;
1188  case SQL_C_UBIGINT:
1189  if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
1190  type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
1191  type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
1192  type != RQ_UINTEGER4 && type != RQ_INTEGER4 &&
1193  type != RQ_INTEGER8) {
1194  WARN_TYPE_OR_LENGTH(size)
1195  }
1196  break;
1197  case SQL_BIGINT:
1198  case SQL_C_SBIGINT:
1199  if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
1200  type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
1201  type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
1202  type != RQ_UINTEGER4 && type != RQ_INTEGER4 &&
1203  type != RQ_INTEGER8) {
1204  WARN_TYPE_OR_LENGTH(size)
1205  }
1206  break;
1207 #undef WARN_TYPE_OR_LENGTH
1208  case SQL_NUMERIC:
1209  case SQL_DECIMAL:
1210  case SQL_FLOAT:
1211  case SQL_REAL:
1212  case SQL_DOUBLE:
1213  if (!ast_rq_is_int(type) && type != RQ_FLOAT) {
1214  warn_type(col, type);
1215  }
1216  break;
1217  default:
1218  ast_log(LOG_WARNING, "Realtime table %s@%s: column type (%d) unrecognized for column '%s'\n", table, database, col->type, elm);
1219  }
1220  break;
1221  }
1222  }
1223  if (!col) {
1224  ast_log(LOG_WARNING, "Realtime table %s@%s requires column '%s', but that column does not exist!\n", table, database, elm);
1225  }
1226  }
1227  AST_RWLIST_UNLOCK(&tableptr->columns);
1228  return 0;
1229 }
require_type
Types used in ast_realtime_require_field.
static const char type[]
Definition: chan_ooh323.c:109
#define CHECK_SIZE(n)
#define LOG_WARNING
Definition: logger.h:274
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
These structures are used for adaptive capabilities.
Definition: res_odbc.h:59
static char * table
Definition: cdr_odbc.c:58
#define ast_log
Definition: astobj2.c:42
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
struct odbc_cache_tables * ast_odbc_find_table(const char *database, const char *tablename)
Find or create an entry describing the table specified.
Definition: res_odbc.c:241
#define warn_length(col, size)
SQLINTEGER size
Definition: res_odbc.h:62
#define WARN_TYPE_OR_LENGTH(n)
#define warn_type(col, type)
SQLSMALLINT type
Definition: res_odbc.h:61
int ast_rq_is_int(require_type type)
Check if require type is an integer type.
struct odbc_cache_tables::_columns columns

◆ store_odbc()

static int store_odbc ( const char *  database,
const char *  table,
const struct ast_variable fields 
)
static

Excute an INSERT query.

Parameters
database
table
aplist 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.

Return values
numberof rows affected
-1on failure

Definition at line 741 of file res_config_odbc.c.

References ast_free, ast_log, ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj2, ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_set(), ast_str_thread_get(), ast_string_field_free_memory, ast_string_field_init, custom_prepare(), custom_prepare_struct::fields, keys, LOG_WARNING, ast_variable::name, ast_variable::next, RES_ODBC_CONNECTED, custom_prepare_struct::sql, sql_buf, and SQL_BUF_SIZE.

742 {
743  struct odbc_obj *obj;
744  SQLHSTMT stmt;
745  SQLLEN rowcount=0;
746  const struct ast_variable *field = fields;
747  struct ast_str *keys;
748  struct ast_str *vals;
750  int res;
751  struct custom_prepare_struct cps = { .fields = fields, };
752  struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
753 
754  keys = ast_str_create(SQL_BUF_SIZE / 2);
755  vals = ast_str_create(SQL_BUF_SIZE / 4);
756  if (!table || !field || !keys || !vals || !sql) {
757  ast_free(vals);
758  ast_free(keys);
759  return -1;
760  }
761 
762  obj = ast_odbc_request_obj2(database, connected_flag);
763  if (!obj) {
764  ast_free(vals);
765  ast_free(keys);
766  return -1;
767  }
768 
769  ast_str_set(&keys, 0, "%s", field->name);
770  ast_str_set(&vals, 0, "?");
771  while ((field = field->next)) {
772  ast_str_append(&keys, 0, ", %s", field->name);
773  ast_str_append(&vals, 0, ", ?");
774  }
775  ast_str_set(&sql, 0, "INSERT INTO %s (%s) VALUES (%s)",
776  table, ast_str_buffer(keys), ast_str_buffer(vals));
777 
778  ast_free(vals);
779  ast_free(keys);
780  cps.sql = ast_str_buffer(sql);
781 
782  if (ast_string_field_init(&cps, 256)) {
784  return -1;
785  }
786  stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
788 
789  if (!stmt) {
791  return -1;
792  }
793 
794  res = SQLRowCount(stmt, &rowcount);
795  SQLFreeHandle (SQL_HANDLE_STMT, stmt);
797 
798  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
799  ast_log(LOG_WARNING, "SQL Row Count error! [%s]\n", ast_str_buffer(sql));
800  return -1;
801  }
802 
803  if (rowcount >= 0)
804  return (int)rowcount;
805 
806  return -1;
807 }
#define SQL_BUF_SIZE
struct ast_variable * next
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
Structure for variables, used for configurations and for channel variables.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
#define ast_odbc_request_obj2(a, b)
Definition: res_odbc.h:121
const struct ast_variable * fields
static char * table
Definition: cdr_odbc.c:58
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
#define ast_log
Definition: astobj2.c:42
ODBC container.
Definition: res_odbc.h:46
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static SQLHSTMT custom_prepare(struct odbc_obj *obj, void *data)
#define ast_free(a)
Definition: astmm.h:182
static struct ast_threadstorage sql_buf
Structure used to handle boolean flags.
Definition: utils.h:199
SQLHSTMT ast_odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT(*prepare_cb)(struct odbc_obj *obj, void *data), void *data)
Prepares, executes, and returns the resulting statement handle.
Definition: res_odbc.c:407
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:861
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
Definition: res_odbc.c:813
static struct keys keys
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1251 of file res_config_odbc.c.

References ast_config_engine_deregister().

Referenced by reload_module().

1252 {
1254 
1255  return 0;
1256 }
int ast_config_engine_deregister(struct ast_config_engine *del)
Deregister config engine.
Definition: main/config.c:3006
static struct ast_config_engine odbc_engine

◆ unload_odbc()

static int unload_odbc ( const char *  a,
const char *  b 
)
static

Definition at line 1233 of file res_config_odbc.c.

References ast_odbc_clear_cache().

1234 {
1235  return ast_odbc_clear_cache(a, b);
1236 }
int ast_odbc_clear_cache(const char *database, const char *tablename)
Remove a cache entry from memory This function may be called to clear entries created and cached by t...
Definition: res_odbc.c:352
static struct test_val b
static struct test_val a

◆ update2_odbc()

static int update2_odbc ( const char *  database,
const char *  table,
const struct ast_variable lookup_fields,
const struct ast_variable update_fields 
)
static

Execute an UPDATE query.

Parameters
database
table
aplist 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.

Return values
numberof rows affected
-1on failure

Definition at line 675 of file res_config_odbc.c.

References ast_assert, ast_log, ast_odbc_find_table(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_release_table, ast_odbc_request_obj, ast_str_buffer(), ast_str_thread_get(), update2_prepare_struct::database, LOG_ERROR, LOG_WARNING, update2_prepare_struct::lookup_fields, NULL, custom_prepare_struct::sql, sql_buf, SQL_BUF_SIZE, table, update2_prepare_struct::tableptr, update2_prepare(), and update2_prepare_struct::update_fields.

676 {
677  struct odbc_obj *obj;
678  SQLHSTMT stmt;
679  struct update2_prepare_struct ups = {
680  .database = database,
681  .table = table,
682  .lookup_fields = lookup_fields,
683  .update_fields = update_fields,
684  };
685  struct ast_str *sql;
686  int res;
687  SQLLEN rowcount = 0;
688 
689  ups.tableptr = ast_odbc_find_table(database, table);
690  if (!ups.tableptr) {
691  ast_log(LOG_ERROR, "Could not retrieve metadata for table '%s@%s'. Update will fail!\n", table, database);
692  return -1;
693  }
694 
695  if (!(obj = ast_odbc_request_obj(database, 0))) {
697  return -1;
698  }
699 
700  if (!(stmt = ast_odbc_prepare_and_execute(obj, update2_prepare, &ups))) {
703  return -1;
704  }
705 
706  /* We don't need the table anymore */
708 
709  res = SQLRowCount(stmt, &rowcount);
710  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
712 
713  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
714  /* Since only a single thread can access this memory, we can retrieve what would otherwise be lost. */
716  ast_assert(sql != NULL);
717  ast_log(LOG_WARNING, "SQL Row Count error! [%s]\n", ast_str_buffer(sql));
718  return -1;
719  }
720 
721  if (rowcount >= 0) {
722  return (int) rowcount;
723  }
724 
725  return -1;
726 }
#define SQL_BUF_SIZE
#define ast_odbc_release_table(ptr)
Release a table returned from ast_odbc_find_table.
Definition: res_odbc.h:216
struct odbc_cache_tables * tableptr
static SQLHSTMT update2_prepare(struct odbc_obj *obj, void *data)
const struct ast_variable * update_fields
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
static char * table
Definition: cdr_odbc.c:58
#define ast_log
Definition: astobj2.c:42
ODBC container.
Definition: res_odbc.h:46
struct odbc_cache_tables * ast_odbc_find_table(const char *database, const char *tablename)
Find or create an entry describing the table specified.
Definition: res_odbc.c:241
#define LOG_ERROR
Definition: logger.h:285
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
#define ast_odbc_request_obj(a, b)
Definition: res_odbc.h:122
static struct ast_threadstorage sql_buf
SQLHSTMT ast_odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT(*prepare_cb)(struct odbc_obj *obj, void *data), void *data)
Prepares, executes, and returns the resulting statement handle.
Definition: res_odbc.c:407
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:861
const struct ast_variable * lookup_fields
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
Definition: res_odbc.c:813

◆ update2_prepare()

static SQLHSTMT update2_prepare ( struct odbc_obj obj,
void *  data 
)
static

Definition at line 604 of file res_config_odbc.c.

References ast_log, ast_odbc_find_column(), ast_odbc_prepare(), ast_odbc_print_errors(), 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, update2_prepare_struct::lookup_fields, ast_variable::name, ast_variable::next, NULL, sql_buf, SQL_BUF_SIZE, update2_prepare_struct::table, update2_prepare_struct::tableptr, update2_prepare_struct::update_fields, and ast_variable::value.

Referenced by update2_odbc().

605 {
606  int res, x = 1, first = 1;
607  struct update2_prepare_struct *ups = data;
608  const struct ast_variable *field;
610  SQLHSTMT stmt;
611 
612  if (!sql) {
613  return NULL;
614  }
615 
616  res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
617  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
618  ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
619  return NULL;
620  }
621 
622  ast_str_set(&sql, 0, "UPDATE %s SET ", ups->table);
623 
624  for (field = ups->update_fields; field; field = field->next) {
625  if (ast_odbc_find_column(ups->tableptr, field->name)) {
626  ast_str_append(&sql, 0, "%s%s=? ", first ? "" : ", ", field->name);
627  SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(field->name), 0, (void *)field->value, 0, NULL);
628  first = 0;
629  } else {
630  ast_log(LOG_NOTICE, "Not updating column '%s' in '%s@%s' because that column does not exist!\n", field->name, ups->table, ups->database);
631  }
632  }
633 
634  ast_str_append(&sql, 0, "WHERE");
635  first = 1;
636 
637  for (field = ups->lookup_fields; field; field = field->next) {
638  if (!ast_odbc_find_column(ups->tableptr, field->name)) {
639  ast_log(LOG_ERROR, "One or more of the criteria columns '%s' on '%s@%s' for this update does not exist!\n", field->name, ups->table, ups->database);
640  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
641  return NULL;
642  }
643  ast_str_append(&sql, 0, "%s %s=?", first ? "" : " AND", field->name);
644  SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(field->value), 0, (void *)field->value, 0, NULL);
645  first = 0;
646  }
647 
648  res = ast_odbc_prepare(obj, stmt, ast_str_buffer(sql));
649  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
650  if (res == SQL_ERROR) {
651  ast_odbc_print_errors(SQL_HANDLE_STMT, stmt, "SQL Prepare");
652  }
653  ast_log(LOG_WARNING, "SQL Prepare failed! [%s]\n", ast_str_buffer(sql));
654  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
655  return NULL;
656  }
657 
658  return stmt;
659 }
#define SQL_BUF_SIZE
SQLHDBC con
Definition: res_odbc.h:47
struct ast_variable * next
struct odbc_cache_tables * tableptr
const struct ast_variable * update_fields
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
int ast_odbc_prepare(struct odbc_obj *obj, SQLHSTMT *stmt, const char *sql)
Prepares a SQL query on a statement.
Definition: res_odbc.c:463
Structure for variables, used for configurations and for channel variables.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
#define NULL
Definition: resample.c:96
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
#define ast_log
Definition: astobj2.c:42
struct odbc_cache_columns * ast_odbc_find_column(struct odbc_cache_tables *table, const char *colname)
Find a column entry within a cached table structure.
Definition: res_odbc.c:341
struct ast_str * ast_odbc_print_errors(SQLSMALLINT handle_type, SQLHANDLE handle, const char *operation)
Shortcut for printing errors to logs after a failed SQL operation.
Definition: res_odbc.c:524
#define LOG_ERROR
Definition: logger.h:285
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
struct sla_ringing_trunk * first
Definition: app_meetme.c:1092
#define LOG_NOTICE
Definition: logger.h:263
static struct ast_threadstorage sql_buf
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:861
const struct ast_variable * lookup_fields

◆ update_odbc()

static int update_odbc ( const char *  database,
const char *  table,
const char *  keyfield,
const char *  lookup,
const struct ast_variable fields 
)
static

Excute an UPDATE query.

Parameters
database
table
keyfieldwhere clause field
lookupvalue of field for where clause
aplist 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.

Return values
numberof rows affected
-1on failure

Definition at line 516 of file res_config_odbc.c.

References 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_str_append(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_string_field_free_memory, ast_string_field_init, ast_strlen_zero, custom_prepare(), custom_prepare_struct::extra, custom_prepare_struct::fields, is_text(), LOG_WARNING, ast_variable::name, ast_variable::next, NULL, odbc_cache_columns::nullable, RES_ODBC_CONNECTED, custom_prepare_struct::skip, custom_prepare_struct::sql, sql_buf, SQL_BUF_SIZE, and ast_variable::value.

517 {
518  struct odbc_obj *obj;
519  SQLHSTMT stmt;
520  SQLLEN rowcount=0;
522  const struct ast_variable *field = fields;
523  int res, count = 0, paramcount = 0;
524  struct custom_prepare_struct cps = { .extra = lookup, .fields = fields, };
525  struct odbc_cache_tables *tableptr;
526  struct odbc_cache_columns *column = NULL;
527  struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
528 
529  if (!table || !field || !keyfield || !sql) {
530  return -1;
531  }
532 
533  tableptr = ast_odbc_find_table(database, table);
534  if (!(obj = ast_odbc_request_obj2(database, connected_flag))) {
535  ast_odbc_release_table(tableptr);
536  return -1;
537  }
538 
539  if (tableptr && !ast_odbc_find_column(tableptr, keyfield)) {
540  ast_log(LOG_WARNING, "Key field '%s' does not exist in table '%s@%s'. Update will fail\n", keyfield, table, database);
541  }
542 
543  ast_str_set(&sql, 0, "UPDATE %s SET ", table);
544  while (field) {
545  if ((tableptr && (column = ast_odbc_find_column(tableptr, field->name))) || count >= 64) {
546  if (paramcount++) {
547  ast_str_append(&sql, 0, ", ");
548  }
549  /* NULL test for non-text columns */
550  if (count < 64 && ast_strlen_zero(field->value) && column->nullable && !is_text(column)) {
551  ast_str_append(&sql, 0, "%s=NULL", field->name);
552  cps.skip |= (1LL << count);
553  } else {
554  /* Value is not an empty string, or column is of text type, or we couldn't fit any more into cps.skip (count >= 64 ?!). */
555  ast_str_append(&sql, 0, "%s=?", field->name);
556  }
557  } else { /* the column does not exist in the table */
558  cps.skip |= (1LL << count);
559  }
560  ++count;
561  field = field->next;
562  }
563  ast_str_append(&sql, 0, " WHERE %s=?", keyfield);
564  ast_odbc_release_table(tableptr);
565 
566  cps.sql = ast_str_buffer(sql);
567 
568  if (ast_string_field_init(&cps, 256)) {
570  return -1;
571  }
572  stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
574 
575  if (!stmt) {
577  return -1;
578  }
579 
580  res = SQLRowCount(stmt, &rowcount);
581  SQLFreeHandle (SQL_HANDLE_STMT, stmt);
583 
584  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
585  ast_log(LOG_WARNING, "SQL Row Count error! [%s]\n", ast_str_buffer(sql));
586  return -1;
587  }
588 
589  if (rowcount >= 0) {
590  return (int) rowcount;
591  }
592 
593  return -1;
594 }
#define SQL_BUF_SIZE
struct ast_variable * next
#define ast_odbc_release_table(ptr)
Release a table returned from ast_odbc_find_table.
Definition: res_odbc.h:216
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
Structure for variables, used for configurations and for channel variables.
SQLSMALLINT nullable
Definition: res_odbc.h:65
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
#define ast_odbc_request_obj2(a, b)
Definition: res_odbc.h:121
#define NULL
Definition: resample.c:96
These structures are used for adaptive capabilities.
Definition: res_odbc.h:59
#define ast_strlen_zero(foo)
Definition: strings.h:52
const struct ast_variable * fields
static char * table
Definition: cdr_odbc.c:58
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
#define ast_log
Definition: astobj2.c:42
ODBC container.
Definition: res_odbc.h:46
struct odbc_cache_columns * ast_odbc_find_column(struct odbc_cache_tables *table, const char *colname)
Find a column entry within a cached table structure.
Definition: res_odbc.c:341
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
struct odbc_cache_tables * ast_odbc_find_table(const char *database, const char *tablename)
Find or create an entry describing the table specified.
Definition: res_odbc.c:241
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static SQLHSTMT custom_prepare(struct odbc_obj *obj, void *data)
static struct ast_threadstorage sql_buf
Structure used to handle boolean flags.
Definition: utils.h:199
SQLHSTMT ast_odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT(*prepare_cb)(struct odbc_obj *obj, void *data), void *data)
Prepares, executes, and returns the resulting statement handle.
Definition: res_odbc.c:407
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:861
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
Definition: res_odbc.c:813
static int is_text(const struct odbc_cache_columns *column)
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368
unsigned long long skip

Variable Documentation

◆ __mod_info

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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_REALTIME_DRIVER, .requires = "extconfig,res_odbc", }
static

Definition at line 1277 of file res_config_odbc.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1277 of file res_config_odbc.c.

◆ odbc_engine

struct ast_config_engine odbc_engine
static

Definition at line 1238 of file res_config_odbc.c.

◆ rowdata_buf

struct ast_threadstorage rowdata_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_rowdata_buf , .custom_init = NULL , }
static

Definition at line 53 of file res_config_odbc.c.

Referenced by realtime_multi_odbc(), and realtime_odbc().

◆ sql_buf

struct ast_threadstorage sql_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_sql_buf , .custom_init = NULL , }
static