Asterisk - The Open Source Telephony Project  21.4.1
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"

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)
 Execute 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 void load_config (const char *filename)
 
static int load_module (void)
 
static struct ast_configrealtime_multi_odbc (const char *database, const char *table, const struct ast_variable *fields)
 Execute 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)
 Execute 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)
 Execute 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)
 Execute 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 = "da6642af068ee5e6490c5b1d2cc1d238" , .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 int order_multi_row_results_by_initial_column = 1
 
static const char * res_config_odbc_conf = "res_config_odbc.conf"
 
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

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

Initial SQL query buffer size to allocate.

Definition at line 50 of file res_config_odbc.c.

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

#define WARN_TYPE_OR_LENGTH (   n)
Value:
if (!ast_rq_is_int(type)) { \
warn_type(col, type); \
} else { \
warn_length(col, n); \
}
int ast_rq_is_int(require_type type)
Check if require type is an integer type.

Function Documentation

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

Execute an DELETE query.

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

Returns
number of rows affected
Return values
-1on failure

Definition at line 829 of file res_config_odbc.c.

References 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, ast_variable::name, ast_variable::next, and SQL_BUF_SIZE.

830 {
831  struct odbc_obj *obj;
832  SQLHSTMT stmt;
833  SQLLEN rowcount=0;
834  struct ast_str *sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE);
835  const struct ast_variable *field;
836  int res;
837  struct custom_prepare_struct cps = { .extra = lookup, .fields = fields, };
838  struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
839 
840  if (!table || !sql) {
841  return -1;
842  }
843 
844  obj = ast_odbc_request_obj2(database, connected_flag);
845  if (!obj) {
846  return -1;
847  }
848 
849  ast_str_set(&sql, 0, "DELETE FROM %s WHERE ", table);
850  for (field = fields; field; field = field->next) {
851  ast_str_append(&sql, 0, "%s=? AND ", field->name);
852  }
853  ast_str_append(&sql, 0, "%s=?", keyfield);
854 
855  cps.sql = ast_str_buffer(sql);
856 
857  if (ast_string_field_init(&cps, 256)) {
859  return -1;
860  }
861  stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
863 
864  if (!stmt) {
866  return -1;
867  }
868 
869  res = SQLRowCount(stmt, &rowcount);
870  SQLFreeHandle (SQL_HANDLE_STMT, stmt);
872 
873  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
874  ast_log(LOG_WARNING, "SQL Row Count error! [%s]\n", ast_str_buffer(sql));
875  return -1;
876  }
877 
878  if (rowcount >= 0)
879  return (int)rowcount;
880 
881  return -1;
882 }
#define SQL_BUF_SIZE
struct ast_variable * next
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_odbc_request_obj2(name, check)
Retrieves a connected ODBC object.
Definition: res_odbc.h:106
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:1139
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:1113
ODBC container.
Definition: res_odbc.h:46
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
Support for dynamic strings.
Definition: strings.h:623
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:398
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:909
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
Definition: res_odbc.c:804
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
static struct ast_config* realtime_multi_odbc ( const char *  database,
const char *  table,
const struct ast_variable fields 
)
static

Execute an Select query and return ast_config list.

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

Returns
var on success
Return values
NULLon failure

Definition at line 345 of file res_config_odbc.c.

References ast_category_append(), ast_category_new_anonymous, ast_config_new(), 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_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_variable::name, ast_variable::next, S_OR, and SQL_BUF_SIZE.

346 {
347  struct odbc_obj *obj;
348  SQLHSTMT stmt;
349  char coltitle[256];
350  struct ast_str *sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE);
351  struct ast_str *rowdata = ast_str_thread_get(&rowdata_buf, 128);
352  const char *initfield;
353  char *op;
354  const struct ast_variable *field = fields;
355  char *stringp;
356  char *chunk;
357  SQLSMALLINT collen;
358  int res;
359  int x;
360  struct ast_variable *var=NULL;
361  struct ast_config *cfg=NULL;
362  struct ast_category *cat=NULL;
363  struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
364  SQLULEN colsize;
365  SQLSMALLINT colcount=0;
366  SQLSMALLINT datatype;
367  SQLSMALLINT decimaldigits;
368  SQLSMALLINT nullable;
369  SQLLEN indicator;
370  struct custom_prepare_struct cps = { .fields = fields, };
371 
372  if (!table || !field || !sql || !rowdata) {
373  return NULL;
374  }
375 
376  obj = ast_odbc_request_obj2(database, connected_flag);
377  if (!obj) {
378  return NULL;
379  }
380 
381  initfield = ast_strdupa(field->name);
382  if ((op = strchr(initfield, ' '))) {
383  *op = '\0';
384  }
385 
386  op = !strchr(field->name, ' ') ? " =" : "";
387  ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s ?%s", table, field->name, op,
388  strcasestr(field->name, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\\\'" : "");
389  while ((field = field->next)) {
390  op = !strchr(field->name, ' ') ? " =" : "";
391  ast_str_append(&sql, 0, " AND %s%s ?%s", field->name, op,
392  strcasestr(field->name, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\\\'" : "");
393  }
394 
395  if (order_multi_row_results_by_initial_column) {
396  ast_str_append(&sql, 0, " ORDER BY %s", initfield);
397  }
398 
399  cps.sql = ast_str_buffer(sql);
400 
401  if (ast_string_field_init(&cps, 256)) {
403  return NULL;
404  }
405  stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
407 
408  if (!stmt) {
410  return NULL;
411  }
412 
413  res = SQLNumResultCols(stmt, &colcount);
414  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
415  ast_log(LOG_WARNING, "SQL Column Count error! [%s]\n", ast_str_buffer(sql));
416  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
418  return NULL;
419  }
420 
421  cfg = ast_config_new();
422  if (!cfg) {
423  ast_log(LOG_WARNING, "Out of memory!\n");
424  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
426  return NULL;
427  }
428 
429  while ((res=SQLFetch(stmt)) != SQL_NO_DATA) {
430  var = NULL;
431  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
432  ast_log(LOG_WARNING, "SQL Fetch error! [%s]\n", ast_str_buffer(sql));
433  continue;
434  }
436  if (!cat) {
437  continue;
438  }
439  for (x=0;x<colcount;x++) {
440  colsize = 0;
441  collen = sizeof(coltitle);
442  res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen,
443  &datatype, &colsize, &decimaldigits, &nullable);
444  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
445  ast_log(LOG_WARNING, "SQL Describe Column error! [%s]\n", ast_str_buffer(sql));
446  ast_category_destroy(cat);
447  goto next_sql_fetch;
448  }
449 
450  ast_str_reset(rowdata);
451  indicator = 0;
452 
453  res = SQLGetData(stmt, x + 1, SQL_CHAR, ast_str_buffer(rowdata), ast_str_size(rowdata), &indicator);
454  ast_str_update(rowdata);
455  if (indicator == SQL_NULL_DATA) {
456  continue;
457  }
458 
459  if ((res == SQL_SUCCESS) || (res == SQL_SUCCESS_WITH_INFO)) {
460  if (indicator != ast_str_strlen(rowdata)) {
461  /* If the available space was not enough to contain the row data enlarge and read in the rest */
462  ast_str_make_space(&rowdata, indicator + 1);
463  res = SQLGetData(stmt, x + 1, SQL_CHAR, ast_str_buffer(rowdata) + ast_str_strlen(rowdata),
464  ast_str_size(rowdata) - ast_str_strlen(rowdata), &indicator);
465  ast_str_update(rowdata);
466  }
467  }
468 
469  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
470  ast_log(LOG_WARNING, "SQL Get Data error! [%s]\n", ast_str_buffer(sql));
471  ast_category_destroy(cat);
472  goto next_sql_fetch;
473  }
474  stringp = ast_str_buffer(rowdata);
475  if (!strncmp(coltitle, "@", 1)) {
476  /* The '@' prefix indicates it's a sorcery extended field.
477  * Because ast_load_realtime_fields eliminates empty entries and makes blank (single whitespace)
478  * entries empty and keeps them, the empty or NULL values are encoded
479  * as a string containing a single whitespace. */
480  var = ast_variable_new(coltitle, S_OR(stringp," "), "");
481  ast_variable_append(cat, var);
482  } else {
483  while (stringp) {
484  chunk = strsep(&stringp, ";");
485  if (!ast_strlen_zero(ast_strip(chunk))) {
486  if (strchr(chunk, '^')) {
487  decode_chunk(chunk);
488  }
489  if (!strcmp(initfield, coltitle)) {
490  ast_category_rename(cat, chunk);
491  }
492  var = ast_variable_new(coltitle, chunk, "");
493  ast_variable_append(cat, var);
494  }
495  }
496  }
497  }
498  ast_category_append(cfg, cat);
499 next_sql_fetch:;
500  }
501 
502  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
504  return cfg;
505 }
#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:833
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:742
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_odbc_request_obj2(name, check)
Retrieves a connected ODBC object.
Definition: res_odbc.h:106
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:1139
void ast_category_append(struct ast_config *config, struct ast_category *category)
Appends a category to a config.
Definition: extconf.c:2833
#define ast_category_new_anonymous()
Create a nameless category that is not backed by a file.
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:1113
ODBC container.
Definition: res_odbc.h:46
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: extconf.c:3274
Support for dynamic strings.
Definition: strings.h:623
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:693
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:730
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:398
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:703
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:80
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:909
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
Definition: res_odbc.c:804
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
static struct ast_variable* realtime_odbc ( const char *  database,
const char *  table,
const struct ast_variable fields 
)
static

Execute an SQL query and return ast_variable list.

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

Returns
var on success
Return values
NULLon failure

Definition at line 173 of file res_config_odbc.c.

References 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_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_variables_destroy(), ast_variable::name, ast_variable::next, S_OR, and SQL_BUF_SIZE.

174 {
175  struct odbc_obj *obj;
176  SQLHSTMT stmt;
177  char coltitle[256];
178  struct ast_str *sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE);
179  struct ast_str *rowdata = ast_str_thread_get(&rowdata_buf, 128);
180  char *op;
181  const struct ast_variable *field = fields;
182  char *stringp;
183  char *chunk;
184  SQLSMALLINT collen;
185  int res;
186  int x;
187  struct ast_variable *var=NULL, *prev=NULL;
188  SQLULEN colsize;
189  SQLSMALLINT colcount=0;
190  SQLSMALLINT datatype;
191  SQLSMALLINT decimaldigits;
192  SQLSMALLINT nullable;
193  SQLLEN indicator;
194  struct custom_prepare_struct cps = { .fields = fields, };
195  struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
196 
197  if (!table || !field || !sql || !rowdata) {
198  return NULL;
199  }
200 
201  obj = ast_odbc_request_obj2(database, connected_flag);
202  if (!obj) {
203  ast_log(LOG_ERROR, "No database handle available with the name of '%s' (check res_odbc.conf)\n", database);
204  return NULL;
205  }
206 
207  op = !strchr(field->name, ' ') ? " =" : "";
208  ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s ?%s", table, field->name, op,
209  strcasestr(field->name, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\\\'" : "");
210  while ((field = field->next)) {
211  op = !strchr(field->name, ' ') ? " =" : "";
212  ast_str_append(&sql, 0, " AND %s%s ?%s", field->name, op,
213  strcasestr(field->name, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\\\'" : "");
214  }
215 
216  cps.sql = ast_str_buffer(sql);
217 
218  if (ast_string_field_init(&cps, 256)) {
220  return NULL;
221  }
222  stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
224 
225  if (!stmt) {
227  return NULL;
228  }
229 
230  res = SQLNumResultCols(stmt, &colcount);
231  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
232  ast_log(LOG_WARNING, "SQL Column Count error! [%s]\n", ast_str_buffer(sql));
233  SQLFreeHandle (SQL_HANDLE_STMT, stmt);
235  return NULL;
236  }
237 
238  res = SQLFetch(stmt);
239  if (res == SQL_NO_DATA) {
240  SQLFreeHandle (SQL_HANDLE_STMT, stmt);
242  return NULL;
243  }
244  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
245  ast_log(LOG_WARNING, "SQL Fetch error! [%s]\n", ast_str_buffer(sql));
246  SQLFreeHandle (SQL_HANDLE_STMT, stmt);
248  return NULL;
249  }
250  for (x = 0; x < colcount; x++) {
251  colsize = 0;
252  collen = sizeof(coltitle);
253  res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen,
254  &datatype, &colsize, &decimaldigits, &nullable);
255  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
256  ast_log(LOG_WARNING, "SQL Describe Column error! [%s]\n", ast_str_buffer(sql));
257  if (var)
260  return NULL;
261  }
262 
263  ast_str_reset(rowdata);
264  indicator = 0;
265 
266  res = SQLGetData(stmt, x + 1, SQL_CHAR, ast_str_buffer(rowdata), ast_str_size(rowdata), &indicator);
267  ast_str_update(rowdata);
268  if (indicator == SQL_NULL_DATA) {
269  ast_str_reset(rowdata);
270  } else if (!ast_str_strlen(rowdata)) {
271  /* Because we encode the empty string for a NULL, we will encode
272  * actual empty strings as a string containing a single whitespace. */
273  ast_str_set(&rowdata, -1, "%s", " ");
274  } else if ((res == SQL_SUCCESS) || (res == SQL_SUCCESS_WITH_INFO)) {
275  if (indicator != ast_str_strlen(rowdata)) {
276  /* If the available space was not enough to contain the row data enlarge and read in the rest */
277  ast_str_make_space(&rowdata, indicator + 1);
278  res = SQLGetData(stmt, x + 1, SQL_CHAR, ast_str_buffer(rowdata) + ast_str_strlen(rowdata),
279  ast_str_size(rowdata) - ast_str_strlen(rowdata), &indicator);
280  ast_str_update(rowdata);
281  }
282  }
283 
284  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
285  ast_log(LOG_WARNING, "SQL Get Data error! [%s]\n", ast_str_buffer(sql));
286  if (var)
289  return NULL;
290  }
291 
292  stringp = ast_str_buffer(rowdata);
293  if (!strncmp(coltitle, "@", 1)) {
294  /* The '@' prefix indicates it's a sorcery extended field.
295  * Because ast_load_realtime_fields eliminates empty entries and makes blank (single whitespace)
296  * entries empty and keeps them, the empty or NULL values are encoded
297  * as a string containing a single whitespace. */
298  if (prev) {
299  prev->next = ast_variable_new(coltitle, S_OR(stringp," "), "");
300  if (prev->next) {
301  prev = prev->next;
302  }
303  } else {
304  prev = var = ast_variable_new(coltitle, S_OR(stringp," "), "");
305  }
306  } else {
307  while (stringp) {
308  chunk = strsep(&stringp, ";");
309  if (!ast_strlen_zero(ast_strip(chunk))) {
310  if (strchr(chunk, '^')) {
311  decode_chunk(chunk);
312  }
313  if (prev) {
314  prev->next = ast_variable_new(coltitle, chunk, "");
315  if (prev->next) {
316  prev = prev->next;
317  }
318  } else {
319  prev = var = ast_variable_new(coltitle, chunk, "");
320  }
321  }
322  }
323  }
324  }
325 
326  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
328  return var;
329 }
#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:833
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:742
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_odbc_request_obj2(name, check)
Retrieves a connected ODBC object.
Definition: res_odbc.h:106
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:1139
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:1113
ODBC container.
Definition: res_odbc.h:46
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
Support for dynamic strings.
Definition: strings.h:623
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:693
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:730
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:398
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:703
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:80
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:909
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
Definition: res_odbc.c:804
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
static int store_odbc ( const char *  database,
const char *  table,
const struct ast_variable fields 
)
static

Execute an INSERT query.

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

Returns
number of rows affected
Return values
-1on failure

Definition at line 746 of file res_config_odbc.c.

References 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, ast_variable::name, ast_variable::next, and SQL_BUF_SIZE.

747 {
748  struct odbc_obj *obj;
749  SQLHSTMT stmt;
750  SQLLEN rowcount=0;
751  const struct ast_variable *field = fields;
752  struct ast_str *keys;
753  struct ast_str *vals;
754  struct ast_str *sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE);
755  int res;
756  struct custom_prepare_struct cps = { .fields = fields, };
757  struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
758 
759  keys = ast_str_create(SQL_BUF_SIZE / 2);
760  vals = ast_str_create(SQL_BUF_SIZE / 4);
761  if (!table || !field || !keys || !vals || !sql) {
762  ast_free(vals);
763  ast_free(keys);
764  return -1;
765  }
766 
767  obj = ast_odbc_request_obj2(database, connected_flag);
768  if (!obj) {
769  ast_free(vals);
770  ast_free(keys);
771  return -1;
772  }
773 
774  ast_str_set(&keys, 0, "%s", field->name);
775  ast_str_set(&vals, 0, "?");
776  while ((field = field->next)) {
777  ast_str_append(&keys, 0, ", %s", field->name);
778  ast_str_append(&vals, 0, ", ?");
779  }
780  ast_str_set(&sql, 0, "INSERT INTO %s (%s) VALUES (%s)",
781  table, ast_str_buffer(keys), ast_str_buffer(vals));
782 
783  ast_free(vals);
784  ast_free(keys);
785  cps.sql = ast_str_buffer(sql);
786 
787  if (ast_string_field_init(&cps, 256)) {
789  return -1;
790  }
791  stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
793 
794  if (!stmt) {
796  return -1;
797  }
798 
799  res = SQLRowCount(stmt, &rowcount);
800  SQLFreeHandle (SQL_HANDLE_STMT, stmt);
802 
803  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
804  ast_log(LOG_WARNING, "SQL Row Count error! [%s]\n", ast_str_buffer(sql));
805  return -1;
806  }
807 
808  if (rowcount >= 0)
809  return (int)rowcount;
810 
811  return -1;
812 }
#define SQL_BUF_SIZE
struct ast_variable * next
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_odbc_request_obj2(name, check)
Retrieves a connected ODBC object.
Definition: res_odbc.h:106
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:1139
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:1113
ODBC container.
Definition: res_odbc.h:46
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
Support for dynamic strings.
Definition: strings.h:623
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:398
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:909
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
Definition: res_odbc.c:804
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
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,lookup_fields
update_fieldslist 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.

Returns
number of rows affected
Return values
-1on failure

Definition at line 680 of file res_config_odbc.c.

References 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(), and SQL_BUF_SIZE.

681 {
682  struct odbc_obj *obj;
683  SQLHSTMT stmt;
684  struct update2_prepare_struct ups = {
685  .database = database,
686  .table = table,
687  .lookup_fields = lookup_fields,
688  .update_fields = update_fields,
689  };
690  struct ast_str *sql;
691  int res;
692  SQLLEN rowcount = 0;
693 
694  ups.tableptr = ast_odbc_find_table(database, table);
695  if (!ups.tableptr) {
696  ast_log(LOG_ERROR, "Could not retrieve metadata for table '%s@%s'. Update will fail!\n", table, database);
697  return -1;
698  }
699 
700  if (!(obj = ast_odbc_request_obj(database, 0))) {
701  ast_odbc_release_table(ups.tableptr);
702  return -1;
703  }
704 
705  if (!(stmt = ast_odbc_prepare_and_execute(obj, update2_prepare, &ups))) {
707  ast_odbc_release_table(ups.tableptr);
708  return -1;
709  }
710 
711  /* We don't need the table anymore */
712  ast_odbc_release_table(ups.tableptr);
713 
714  res = SQLRowCount(stmt, &rowcount);
715  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
717 
718  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
719  /* Since only a single thread can access this memory, we can retrieve what would otherwise be lost. */
720  sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE);
721  ast_assert(sql != NULL);
722  ast_log(LOG_WARNING, "SQL Row Count error! [%s]\n", ast_str_buffer(sql));
723  return -1;
724  }
725 
726  if (rowcount >= 0) {
727  return (int) rowcount;
728  }
729 
730  return -1;
731 }
#define SQL_BUF_SIZE
#define ast_odbc_release_table(ptr)
Release a table returned from ast_odbc_find_table.
Definition: res_odbc.h:219
#define ast_odbc_request_obj(name, check)
Get a ODBC connection object.
Definition: res_odbc.h:120
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
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:232
Support for dynamic strings.
Definition: strings.h:623
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:398
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:909
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
Definition: res_odbc.c:804
static int update_odbc ( const char *  database,
const char *  table,
const char *  keyfield,
const char *  lookup,
const struct ast_variable fields 
)
static

Execute an UPDATE query.

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

Returns
number of rows affected
Return values
-1on failure

Definition at line 522 of file res_config_odbc.c.

References 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_variable::name, ast_variable::next, SQL_BUF_SIZE, and ast_variable::value.

523 {
524  struct odbc_obj *obj;
525  SQLHSTMT stmt;
526  SQLLEN rowcount=0;
527  struct ast_str *sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE);
528  const struct ast_variable *field = fields;
529  int res, count = 0, paramcount = 0;
530  struct custom_prepare_struct cps = { .extra = lookup, .fields = fields, };
531  struct odbc_cache_tables *tableptr;
532  struct odbc_cache_columns *column = NULL;
533  struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
534 
535  if (!table || !field || !keyfield || !sql) {
536  return -1;
537  }
538 
539  tableptr = ast_odbc_find_table(database, table);
540  if (!(obj = ast_odbc_request_obj2(database, connected_flag))) {
541  ast_odbc_release_table(tableptr);
542  return -1;
543  }
544 
545  if (tableptr && !ast_odbc_find_column(tableptr, keyfield)) {
546  ast_log(LOG_WARNING, "Key field '%s' does not exist in table '%s@%s'. Update will fail\n", keyfield, table, database);
547  }
548 
549  ast_str_set(&sql, 0, "UPDATE %s SET ", table);
550  while (field) {
551  if ((tableptr && (column = ast_odbc_find_column(tableptr, field->name))) || count >= 64) {
552  if (paramcount++) {
553  ast_str_append(&sql, 0, ", ");
554  }
555  /* NULL test for non-text columns */
556  if (count < 64 && ast_strlen_zero(field->value) && column->nullable && !is_text(column)) {
557  ast_str_append(&sql, 0, "%s=NULL", field->name);
558  cps.skip |= (1LL << count);
559  } else {
560  /* Value is not an empty string, or column is of text type, or we couldn't fit any more into cps.skip (count >= 64 ?!). */
561  ast_str_append(&sql, 0, "%s=?", field->name);
562  }
563  } else { /* the column does not exist in the table */
564  cps.skip |= (1LL << count);
565  }
566  ++count;
567  field = field->next;
568  }
569  ast_str_append(&sql, 0, " WHERE %s=?", keyfield);
570  ast_odbc_release_table(tableptr);
571 
572  cps.sql = ast_str_buffer(sql);
573 
574  if (ast_string_field_init(&cps, 256)) {
576  return -1;
577  }
578  stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
580 
581  if (!stmt) {
583  return -1;
584  }
585 
586  res = SQLRowCount(stmt, &rowcount);
587  SQLFreeHandle (SQL_HANDLE_STMT, stmt);
589 
590  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
591  ast_log(LOG_WARNING, "SQL Row Count error! [%s]\n", ast_str_buffer(sql));
592  return -1;
593  }
594 
595  if (rowcount >= 0) {
596  return (int) rowcount;
597  }
598 
599  return -1;
600 }
#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:219
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_odbc_request_obj2(name, check)
Retrieves a connected ODBC object.
Definition: res_odbc.h:106
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:1139
These structures are used for adaptive capabilities.
Definition: res_odbc.h:59
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:1113
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:332
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
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:232
Support for dynamic strings.
Definition: strings.h:623
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:398
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:909
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
Definition: res_odbc.c:804
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374