Asterisk - The Open Source Telephony Project  21.4.1
Data Structures | Macros | Enumerations | Functions
res_odbc.h File Reference

ODBC resource manager. More...

#include <sql.h>
#include <sqlext.h>
#include <sqltypes.h>
#include "asterisk/linkedlists.h"
#include "asterisk/strings.h"

Go to the source code of this file.

Data Structures

struct  odbc_cache_tables::_columns
 
struct  odbc_cache_columns
 These structures are used for adaptive capabilities. More...
 
struct  odbc_cache_tables
 
struct  odbc_obj
 ODBC container. More...
 

Macros

#define ast_odbc_release_table(ptr)   if (ptr) { AST_RWLIST_UNLOCK(&(ptr)->columns); }
 Release a table returned from ast_odbc_find_table.
 
#define ast_odbc_request_obj(name, check)   _ast_odbc_request_obj(name, check, __FILE__, __PRETTY_FUNCTION__, __LINE__)
 Get a ODBC connection object. More...
 
#define ast_odbc_request_obj2(name, check)   _ast_odbc_request_obj2(name, check, __FILE__, __PRETTY_FUNCTION__, __LINE__)
 Retrieves a connected ODBC object. More...
 

Enumerations

enum  { RES_ODBC_SANITY_CHECK = (1 << 0), RES_ODBC_INDEPENDENT_CONNECTION = (1 << 1), RES_ODBC_CONNECTED = (1 << 2) }
 Flags for use with. More...
 
enum  odbc_status { ODBC_SUCCESS =0, ODBC_FAIL =-1 }
 

Functions

struct odbc_obj_ast_odbc_request_obj (const char *name, int check, const char *file, const char *function, int lineno)
 
struct odbc_obj_ast_odbc_request_obj2 (const char *name, struct ast_flags flags, const char *file, const char *function, int lineno)
 
SQLRETURN ast_odbc_ast_str_SQLGetData (struct ast_str **buf, int pmaxlen, SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLLEN *StrLen_or_Ind)
 Wrapper for SQLGetData to use with dynamic strings. More...
 
int ast_odbc_backslash_is_escape (struct odbc_obj *obj)
 Checks if the database natively supports backslash as an escape character. More...
 
unsigned int ast_odbc_class_get_forcecommit (struct odbc_class *class)
 Get the transaction forcecommit setting for an ODBC class.
 
unsigned int ast_odbc_class_get_isolation (struct odbc_class *class)
 Get the transaction isolation setting for an ODBC class.
 
const char * ast_odbc_class_get_name (struct odbc_class *class)
 Get the name of an ODBC class.
 
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 the ast_odbc_find_table() API call. More...
 
SQLHSTMT ast_odbc_direct_execute (struct odbc_obj *obj, SQLHSTMT(*exec_cb)(struct odbc_obj *obj, void *data), void *data)
 Executes an non prepared statement and returns the resulting statement handle. More...
 
SQLRETURN ast_odbc_execute_sql (struct odbc_obj *obj, SQLHSTMT *stmt, const char *sql)
 Execute a unprepared SQL query. More...
 
struct odbc_cache_columnsast_odbc_find_column (struct odbc_cache_tables *table, const char *colname)
 Find a column entry within a cached table structure. More...
 
struct odbc_cache_tablesast_odbc_find_table (const char *database, const char *tablename)
 Find or create an entry describing the table specified. More...
 
unsigned int ast_odbc_get_max_connections (const char *name)
 Return the current configured maximum number of connections for a class.
 
const char * ast_odbc_isolation2text (int iso)
 Convert from numeric transaction isolation values to their textual counterparts.
 
int ast_odbc_prepare (struct odbc_obj *obj, SQLHSTMT *stmt, const char *sql)
 Prepares a SQL query on a statement. More...
 
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. More...
 
struct ast_strast_odbc_print_errors (SQLSMALLINT handle_type, SQLHANDLE handle, const char *operation)
 Shortcut for printing errors to logs after a failed SQL operation. More...
 
void ast_odbc_release_obj (struct odbc_obj *obj)
 Releases an ODBC object previously allocated by ast_odbc_request_obj() More...
 
int ast_odbc_sanity_check (struct odbc_obj *obj)
 Checks an ODBC object to ensure it is still connected. More...
 
int ast_odbc_smart_execute (struct odbc_obj *obj, SQLHSTMT stmt)
 Executes a prepared statement handle. More...
 
int ast_odbc_text2isolation (const char *txt)
 Convert from textual transaction isolation values to their numeric constants.
 

Detailed Description

ODBC resource manager.

Definition in file res_odbc.h.

Macro Definition Documentation

#define ast_odbc_request_obj (   name,
  check 
)    _ast_odbc_request_obj(name, check, __FILE__, __PRETTY_FUNCTION__, __LINE__)

Get a ODBC connection object.

The "check" parameter is leftover from an earlier implementation where database connections were cached by res_odbc. Since connections are managed by unixODBC now, this parameter is only kept around for API compatibility.

Parameters
nameThe name of the res_odbc.conf section describing the database to connect to
checkunused
Returns
A connection to the database. Call ast_odbc_release_obj() when finished.

Definition at line 120 of file res_odbc.h.

Referenced by ast_odbc_find_table(), create_dsn(), get_dsn(), get_odbc_obj(), and update2_odbc().

#define ast_odbc_request_obj2 (   name,
  check 
)    _ast_odbc_request_obj2(name, check, __FILE__, __PRETTY_FUNCTION__, __LINE__)

Retrieves a connected ODBC object.

Deprecated:

This is only around for backwards-compatibility with older versions of Asterisk.

Definition at line 106 of file res_odbc.h.

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

Enumeration Type Documentation

anonymous enum

Flags for use with.

See also
ast_odbc_request_obj2

Definition at line 39 of file res_odbc.h.

39  {
40  RES_ODBC_SANITY_CHECK = (1 << 0),
41  RES_ODBC_INDEPENDENT_CONNECTION = (1 << 1),
42  RES_ODBC_CONNECTED = (1 << 2),
43 };

Function Documentation

SQLRETURN ast_odbc_ast_str_SQLGetData ( struct ast_str **  buf,
int  pmaxlen,
SQLHSTMT  StatementHandle,
SQLUSMALLINT  ColumnNumber,
SQLSMALLINT  TargetType,
SQLLEN *  StrLen_or_Ind 
)

Wrapper for SQLGetData to use with dynamic strings.

Parameters
bufAddress of the pointer to the ast_str structure.
pmaxlenThe maximum size of the resulting string, or 0 for no limit.
StatementHandleThe statement handle from which to retrieve data.
ColumnNumberColumn number (1-based offset) for which to retrieve data.
TargetTypeThe SQL constant indicating what kind of data is to be retrieved (usually SQL_CHAR)
StrLen_or_IndA pointer to a length indicator, specifying the total length of data.

Definition at line 498 of file res_odbc.c.

References ast_str_buffer(), ast_str_size(), and ast_str_update().

499 {
500  SQLRETURN res;
501 
502  if (pmaxlen == 0) {
503  if (SQLGetData(StatementHandle, ColumnNumber, TargetType, ast_str_buffer(*buf), 0, StrLen_or_Ind) == SQL_SUCCESS_WITH_INFO) {
504  ast_str_make_space(buf, *StrLen_or_Ind + 1);
505  }
506  } else if (pmaxlen > 0) {
507  ast_str_make_space(buf, pmaxlen);
508  }
509  res = SQLGetData(StatementHandle, ColumnNumber, TargetType, ast_str_buffer(*buf), ast_str_size(*buf), StrLen_or_Ind);
510  ast_str_update(*buf);
511 
512  return res;
513 }
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
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
int ast_odbc_backslash_is_escape ( struct odbc_obj obj)

Checks if the database natively supports backslash as an escape character.

Parameters
objThe ODBC object
Return values
1if backslash is a native escape character
0if an ESCAPE clause is needed to support '\'

Definition at line 833 of file res_odbc.c.

References odbc_class::backslash_is_escape, and odbc_obj::parent.

Referenced by realtime_multi_odbc(), and realtime_odbc().

834 {
835  return obj->parent->backslash_is_escape;
836 }
struct odbc_class * parent
Definition: res_odbc.h:48
unsigned int backslash_is_escape
Definition: res_odbc.c:74
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 the ast_odbc_find_table() API call.

Parameters
databaseName of an ODBC class (used to ensure like-named tables in different databases are not confused)
tablenameTablename for which a cached record should be removed
Return values
0if the cache entry was removed.
-1if no matching entry was found.
Since
1.6.1

Definition at line 343 of file res_odbc.c.

References AST_LIST_REMOVE_CURRENT, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

344 {
345  struct odbc_cache_tables *tableptr;
346 
348  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&odbc_tables, tableptr, list) {
349  if (strcmp(tableptr->connection, database) == 0 && strcmp(tableptr->table, tablename) == 0) {
351  destroy_table_cache(tableptr);
352  break;
353  }
354  }
355  AST_RWLIST_TRAVERSE_SAFE_END
357  return tableptr ? 0 : -1;
358 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
SQLHSTMT ast_odbc_direct_execute ( struct odbc_obj obj,
SQLHSTMT(*)(struct odbc_obj *obj, void *data)  exec_cb,
void *  data 
)

Executes an non prepared statement and returns the resulting statement handle.

Parameters
objThe ODBC object
exec_cbA function callback, which, when called, should return a statement handle with result columns bound.
dataA parameter to be passed to the exec_cb parameter function, indicating which statement handle is to be prepared.
Returns
a statement handle
Return values
NULLon error

Definition at line 360 of file res_odbc.c.

References ast_tvdiff_ms(), ast_tvnow(), odbc_class::lock, odbc_class::logging, odbc_class::longest_query_execution_time, odbc_obj::parent, odbc_class::slowquerylimit, odbc_obj::sql_text, and odbc_class::sql_text.

Referenced by acf_odbc_write(), and connection_dead().

361 {
362  struct timeval start;
363  SQLHSTMT stmt;
364 
365  if (obj->parent->logging) {
366  start = ast_tvnow();
367  }
368 
369  stmt = exec_cb(obj, data);
370 
371  if (obj->parent->logging) {
372  long execution_time = ast_tvdiff_ms(ast_tvnow(), start);
373 
374  if (obj->parent->slowquerylimit && execution_time > obj->parent->slowquerylimit) {
375  ast_log(LOG_WARNING, "SQL query '%s' took %ld milliseconds to execute on class '%s', this may indicate a database problem\n",
376  obj->sql_text, execution_time, obj->parent->name);
377  }
378 
379  ast_mutex_lock(&obj->parent->lock);
380  if (execution_time > obj->parent->longest_query_execution_time || !obj->parent->sql_text) {
381  obj->parent->longest_query_execution_time = execution_time;
382  /* Due to the callback nature of the res_odbc API it's not possible to ensure that
383  * the SQL text is removed from the connection in all cases, so only if it becomes the
384  * new longest executing query do we steal the SQL text. In other cases what will happen
385  * is that the SQL text will be freed if the connection is released back to the class or
386  * if a new query is done on the connection.
387  */
388  ast_free(obj->parent->sql_text);
389  obj->parent->sql_text = obj->sql_text;
390  obj->sql_text = NULL;
391  }
392  ast_mutex_unlock(&obj->parent->lock);
393  }
394 
395  return stmt;
396 }
ast_mutex_t lock
Definition: res_odbc.c:86
char * sql_text
Definition: res_odbc.c:100
unsigned int logging
Definition: res_odbc.c:92
unsigned int slowquerylimit
Definition: res_odbc.c:102
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
struct odbc_class * parent
Definition: res_odbc.h:48
char * sql_text
Definition: res_odbc.h:54
long longest_query_execution_time
Definition: res_odbc.c:98
SQLRETURN ast_odbc_execute_sql ( struct odbc_obj obj,
SQLHSTMT *  stmt,
const char *  sql 
)

Execute a unprepared SQL query.

Parameters
objThe ODBC object
stmtThe statement
sqlThe SQL query
Note
This should be used in place of SQLExecDirect

Definition at line 469 of file res_odbc.c.

References ast_atomic_fetchadd_int(), ast_strdup, odbc_class::logging, odbc_obj::parent, odbc_class::queries_executed, and odbc_obj::sql_text.

Referenced by execute().

470 {
471  if (obj->parent->logging) {
472  ast_free(obj->sql_text);
473  obj->sql_text = ast_strdup(sql);
475  }
476 
477  return SQLExecDirect(stmt, (unsigned char *)sql, SQL_NTS);
478 }
unsigned int logging
Definition: res_odbc.c:92
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:757
struct odbc_class * parent
Definition: res_odbc.h:48
char * sql_text
Definition: res_odbc.h:54
int queries_executed
Definition: res_odbc.c:96
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.

Parameters
tableCached table structure, as returned from ast_odbc_find_table()
colnameThe column name requested
Returns
A structure describing the column type, or NULL, if the column is not found.
Since
1.6.1

Definition at line 332 of file res_odbc.c.

Referenced by update_odbc().

333 {
334  struct odbc_cache_columns *col;
335  AST_RWLIST_TRAVERSE(&table->columns, col, list) {
336  if (strcasecmp(col->name, colname) == 0) {
337  return col;
338  }
339  }
340  return NULL;
341 }
These structures are used for adaptive capabilities.
Definition: res_odbc.h:59
struct odbc_cache_tables* ast_odbc_find_table ( const char *  database,
const char *  tablename 
)

Find or create an entry describing the table specified.

Parameters
databaseName of an ODBC class on which to query the table
tablenameTablename to describe
Returns
A structure describing the table layout.
Return values
NULLif the table is not found or another error occurs. When a structure is returned, the contained columns list will be rdlock'ed, to ensure that it will be retained in memory. The information will be cached until a reload event or when ast_odbc_clear_cache() is called with the relevant parameters.
Since
1.6.1

XXX This creates a connection and disconnects it. In some situations, the caller of this function has its own connection and could donate it to this function instead of needing to create another one.

XXX The automatic readlock of the columns is awkward. It's done because it's possible for multiple threads to have references to the table, and the table is not refcounted. Possible changes here would be

  • Eliminate the table cache entirely. The use of ast_odbc_find_table() is generally questionable. The only real good use right now is from ast_realtime_require_field() in order to make sure the DB has the expected columns in it. Since that is only used sparingly, the need to cache tables is questionable. Instead, the table structure can be fetched from the DB directly each time, resulting in a single owner of the data.
  • Make odbc_cache_tables a refcounted object.

Definition at line 232 of file res_odbc.c.

References ast_calloc, ast_debug, AST_LIST_INSERT_TAIL, ast_odbc_release_obj(), ast_odbc_request_obj, AST_RWLIST_HEAD_INIT, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, and odbc_obj::con.

Referenced by update2_odbc(), and update_odbc().

233 {
234  struct odbc_cache_tables *tableptr;
235  struct odbc_cache_columns *entry;
236  char columnname[80];
237  SQLLEN sqlptr;
238  SQLHSTMT stmt = NULL;
239  int res = 0, error = 0;
240  struct odbc_obj *obj;
241 
243  AST_RWLIST_TRAVERSE(&odbc_tables, tableptr, list) {
244  if (strcmp(tableptr->connection, database) == 0 && strcmp(tableptr->table, tablename) == 0) {
245  break;
246  }
247  }
248  if (tableptr) {
249  AST_RWLIST_RDLOCK(&tableptr->columns);
251  return tableptr;
252  }
253 
254  if (!(obj = ast_odbc_request_obj(database, 0))) {
255  ast_log(LOG_WARNING, "Unable to retrieve database handle for table description '%s@%s'\n", tablename, database);
257  return NULL;
258  }
259 
260  /* Table structure not already cached; build it now. */
261  do {
262  res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
263  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
264  ast_log(LOG_WARNING, "SQL Alloc Handle failed on connection '%s'!\n", database);
265  break;
266  }
267 
268  res = SQLColumns(stmt, NULL, 0, NULL, 0, (unsigned char *)tablename, SQL_NTS, (unsigned char *)"%", SQL_NTS);
269  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
270  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
271  ast_log(LOG_ERROR, "Unable to query database columns on connection '%s'.\n", database);
272  break;
273  }
274 
275  if (!(tableptr = ast_calloc(sizeof(char), sizeof(*tableptr) + strlen(database) + 1 + strlen(tablename) + 1))) {
276  ast_log(LOG_ERROR, "Out of memory creating entry for table '%s' on connection '%s'\n", tablename, database);
277  break;
278  }
279 
280  tableptr->connection = (char *)tableptr + sizeof(*tableptr);
281  tableptr->table = (char *)tableptr + sizeof(*tableptr) + strlen(database) + 1;
282  strcpy(tableptr->connection, database); /* SAFE */
283  strcpy(tableptr->table, tablename); /* SAFE */
284  AST_RWLIST_HEAD_INIT(&(tableptr->columns));
285 
286  while ((res = SQLFetch(stmt)) != SQL_NO_DATA && res != SQL_ERROR) {
287  SQLGetData(stmt, 4, SQL_C_CHAR, columnname, sizeof(columnname), &sqlptr);
288 
289  if (!(entry = ast_calloc(sizeof(char), sizeof(*entry) + strlen(columnname) + 1))) {
290  ast_log(LOG_ERROR, "Out of memory creating entry for column '%s' in table '%s' on connection '%s'\n", columnname, tablename, database);
291  error = 1;
292  break;
293  }
294  entry->name = (char *)entry + sizeof(*entry);
295  strcpy(entry->name, columnname);
296 
297  SQLGetData(stmt, 5, SQL_C_SHORT, &entry->type, sizeof(entry->type), NULL);
298  SQLGetData(stmt, 7, SQL_C_LONG, &entry->size, sizeof(entry->size), NULL);
299  SQLGetData(stmt, 9, SQL_C_SHORT, &entry->decimals, sizeof(entry->decimals), NULL);
300  SQLGetData(stmt, 10, SQL_C_SHORT, &entry->radix, sizeof(entry->radix), NULL);
301  SQLGetData(stmt, 11, SQL_C_SHORT, &entry->nullable, sizeof(entry->nullable), NULL);
302  SQLGetData(stmt, 16, SQL_C_LONG, &entry->octetlen, sizeof(entry->octetlen), NULL);
303 
304  /* Specification states that the octenlen should be the maximum number of bytes
305  * returned in a char or binary column, but it seems that some drivers just set
306  * it to NULL. (Bad Postgres! No biscuit!) */
307  if (entry->octetlen == 0) {
308  entry->octetlen = entry->size;
309  }
310 
311  ast_debug(3, "Found %s column with type %hd with len %ld, octetlen %ld, and numlen (%hd,%hd)\n", entry->name, entry->type, (long) entry->size, (long) entry->octetlen, entry->decimals, entry->radix);
312  /* Insert column info into column list */
313  AST_LIST_INSERT_TAIL(&(tableptr->columns), entry, list);
314  }
315  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
316 
317  AST_RWLIST_INSERT_TAIL(&odbc_tables, tableptr, list);
318  AST_RWLIST_RDLOCK(&(tableptr->columns));
319  break;
320  } while (1);
321 
323 
324  if (error) {
325  destroy_table_cache(tableptr);
326  tableptr = NULL;
327  }
329  return tableptr;
330 }
SQLHDBC con
Definition: res_odbc.h:47
#define ast_odbc_request_obj(name, check)
Get a ODBC connection object.
Definition: res_odbc.h:120
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
#define AST_RWLIST_HEAD_INIT(head)
Initializes an rwlist head structure.
Definition: linkedlists.h:639
These structures are used for adaptive capabilities.
Definition: res_odbc.h:59
ODBC container.
Definition: res_odbc.h:46
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_debug(level,...)
Log a DEBUG message.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
Definition: search.h:40
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
int ast_odbc_prepare ( struct odbc_obj obj,
SQLHSTMT *  stmt,
const char *  sql 
)

Prepares a SQL query on a statement.

Parameters
objThe ODBC object
stmtThe statement
sqlThe SQL query
Note
This should be used in place of SQLPrepare

Definition at line 454 of file res_odbc.c.

References ast_atomic_fetchadd_int(), ast_strdup, odbc_class::logging, odbc_obj::parent, odbc_class::prepares_executed, and odbc_obj::sql_text.

455 {
456  if (obj->parent->logging) {
457  /* It is possible for this connection to be reused without being
458  * released back to the class, so we free what may already exist
459  * and place the new SQL in.
460  */
461  ast_free(obj->sql_text);
462  obj->sql_text = ast_strdup(sql);
464  }
465 
466  return SQLPrepare(stmt, (unsigned char *)sql, SQL_NTS);
467 }
unsigned int logging
Definition: res_odbc.c:92
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:757
int prepares_executed
Definition: res_odbc.c:94
struct odbc_class * parent
Definition: res_odbc.h:48
char * sql_text
Definition: res_odbc.h:54
SQLHSTMT ast_odbc_prepare_and_execute ( struct odbc_obj obj,
SQLHSTMT(*)(struct odbc_obj *obj, void *data)  prepare_cb,
void *  data 
)

Prepares, executes, and returns the resulting statement handle.

Parameters
objThe ODBC object
prepare_cbA function callback, which, when called, should return a statement handle prepared, with any necessary parameters or result columns bound.
dataA parameter to be passed to the prepare_cb parameter function, indicating which statement handle is to be prepared.
Returns
a statement handle
Return values
NULLon error

Definition at line 398 of file res_odbc.c.

References ast_atomic_fetchadd_int(), ast_odbc_print_errors(), ast_tvdiff_ms(), ast_tvnow(), odbc_class::lock, odbc_class::logging, odbc_class::longest_query_execution_time, odbc_obj::parent, odbc_class::queries_executed, odbc_class::slowquerylimit, odbc_obj::sql_text, and odbc_class::sql_text.

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

399 {
400  struct timeval start;
401  int res = 0;
402  SQLHSTMT stmt;
403 
404  if (obj->parent->logging) {
405  start = ast_tvnow();
406  }
407 
408  /* This prepare callback may do more than just prepare -- it may also
409  * bind parameters, bind results, etc. The real key, here, is that
410  * when we disconnect, all handles become invalid for most databases.
411  * We must therefore redo everything when we establish a new
412  * connection. */
413  stmt = prepare_cb(obj, data);
414  if (!stmt) {
415  return NULL;
416  }
417 
418  res = SQLExecute(stmt);
419  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) {
420  if (res == SQL_ERROR) {
421  ast_odbc_print_errors(SQL_HANDLE_STMT, stmt, "SQL Execute");
422  }
423 
424  ast_log(LOG_WARNING, "SQL Execute error %d!\n", res);
425  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
426  stmt = NULL;
427  } else if (obj->parent->logging) {
428  long execution_time = ast_tvdiff_ms(ast_tvnow(), start);
429 
430  if (obj->parent->slowquerylimit && execution_time > obj->parent->slowquerylimit) {
431  ast_log(LOG_WARNING, "SQL query '%s' took %ld milliseconds to execute on class '%s', this may indicate a database problem\n",
432  obj->sql_text, execution_time, obj->parent->name);
433  }
434 
435  ast_mutex_lock(&obj->parent->lock);
436 
437  /* If this takes the record on longest query execution time, update the parent class
438  * with the information.
439  */
440  if (execution_time > obj->parent->longest_query_execution_time || !obj->parent->sql_text) {
441  obj->parent->longest_query_execution_time = execution_time;
442  ast_free(obj->parent->sql_text);
443  obj->parent->sql_text = obj->sql_text;
444  obj->sql_text = NULL;
445  }
446  ast_mutex_unlock(&obj->parent->lock);
447 
449  }
450 
451  return stmt;
452 }
ast_mutex_t lock
Definition: res_odbc.c:86
char * sql_text
Definition: res_odbc.c:100
unsigned int logging
Definition: res_odbc.c:92
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:515
unsigned int slowquerylimit
Definition: res_odbc.c:102
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:757
struct odbc_class * parent
Definition: res_odbc.h:48
char * sql_text
Definition: res_odbc.h:54
int queries_executed
Definition: res_odbc.c:96
long longest_query_execution_time
Definition: res_odbc.c:98
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.

Parameters
handle_typeThe type of SQL handle on which to gather diagnostics
handleThe SQL handle to gather diagnostics from
operationThe name of the failed operation.
Returns
The error string that was printed to the logs

Definition at line 515 of file res_odbc.c.

References ast_str_append(), ast_str_reset(), ast_str_strlen(), and ast_str_thread_get().

Referenced by ast_odbc_prepare_and_execute(), and ast_odbc_smart_execute().

516 {
517  struct ast_str *errors = ast_str_thread_get(&errors_buf, 16);
518  SQLINTEGER nativeerror = 0;
519  SQLSMALLINT diagbytes = 0;
520  SQLSMALLINT i;
521  unsigned char state[10];
522  unsigned char diagnostic[256];
523 
524  ast_str_reset(errors);
525  i = 0;
526  while (SQLGetDiagRec(handle_type, handle, ++i, state, &nativeerror,
527  diagnostic, sizeof(diagnostic), &diagbytes) == SQL_SUCCESS) {
528  ast_str_append(&errors, 0, "%s%s", ast_str_strlen(errors) ? "," : "", state);
529  ast_log(LOG_WARNING, "%s returned an error: %s: %s\n", operation, state, diagnostic);
530  /* XXX Why is this here? */
531  if (i > 10) {
532  ast_log(LOG_WARNING, "There are more than 10 diagnostic records! Ignore the rest.\n");
533  break;
534  }
535  }
536 
537  return errors;
538 }
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
Support for dynamic strings.
Definition: strings.h:623
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
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()

Parameters
objThe ODBC object

Definition at line 804 of file res_odbc.c.

References ao2_ref, ast_debug, AST_LIST_INSERT_HEAD, odbc_obj::parent, and odbc_obj::sql_text.

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

805 {
806  struct odbc_class *class = obj->parent;
807 
808  ast_debug(2, "Releasing ODBC handle %p into pool\n", obj);
809 
810  /* The odbc_obj only holds a reference to the class when it is
811  * actively being used. This guarantees no circular reference
812  * between odbc_class and odbc_obj. Since it is being released
813  * we also release our class reference. If a reload occurred before
814  * the class will go away automatically once all odbc_obj are
815  * released back.
816  */
817  obj->parent = NULL;
818 
819  /* Free the SQL text so that the next user of this connection has
820  * a fresh start.
821  */
822  ast_free(obj->sql_text);
823  obj->sql_text = NULL;
824 
825  ast_mutex_lock(&class->lock);
826  AST_LIST_INSERT_HEAD(&class->connections, obj, list);
827  ast_cond_signal(&class->cond);
828  ast_mutex_unlock(&class->lock);
829 
830  ao2_ref(class, -1);
831 }
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ast_debug(level,...)
Log a DEBUG message.
struct odbc_class * parent
Definition: res_odbc.h:48
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
char * sql_text
Definition: res_odbc.h:54
int ast_odbc_sanity_check ( struct odbc_obj obj)

Checks an ODBC object to ensure it is still connected.

Parameters
objThe ODBC object
Return values
0if connected
-1otherwise.
int ast_odbc_smart_execute ( struct odbc_obj obj,
SQLHSTMT  stmt 
)

Executes a prepared statement handle.

Parameters
objThe non-NULL result of odbc_request_obj()
stmtThe prepared statement handle
Return values
0on success
-1on failure

This function was originally designed simply to execute a prepared statement handle and to retry if the initial execution failed. Unfortunately, it did this by disconnecting and reconnecting the database handle which on most databases causes the statement handle to become invalid. Therefore, this method has been deprecated in favor of odbc_prepare_and_execute() which allows the statement to be prepared multiple times, if necessary, in case of a loss of connection.

This function really only ever worked with MySQL, where the statement handle is not prepared on the server. If you are not using MySQL, you should avoid it.

Definition at line 480 of file res_odbc.c.

References ast_atomic_fetchadd_int(), ast_odbc_print_errors(), odbc_class::logging, odbc_obj::parent, and odbc_class::queries_executed.

481 {
482  int res = 0;
483 
484  res = SQLExecute(stmt);
485  if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) {
486  if (res == SQL_ERROR) {
487  ast_odbc_print_errors(SQL_HANDLE_STMT, stmt, "SQL Execute");
488  }
489  }
490 
491  if (obj->parent->logging) {
493  }
494 
495  return res;
496 }
unsigned int logging
Definition: res_odbc.c:92
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:515
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:757
struct odbc_class * parent
Definition: res_odbc.h:48
int queries_executed
Definition: res_odbc.c:96