#include <sql.h>
#include <sqlext.h>
#include <sqltypes.h>
Include dependency graph for res_odbc.h:
This graph shows which files directly or indirectly include this file:
Go to the source code of this file.
Data Structures | |
struct | odbc_obj |
Enumerations | |
enum | odbc_status { ODBC_SUCCESS = 0, ODBC_FAIL = -1 } |
Functions | |
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. | |
void | ast_odbc_release_obj (struct odbc_obj *obj) |
Releases an ODBC object previously allocated by odbc_request_obj(). | |
odbc_obj * | ast_odbc_request_obj (const char *name, int check) |
Retrieves a connected ODBC object. | |
int | ast_odbc_sanity_check (struct odbc_obj *obj) |
Checks an ODBC object to ensure it is still connected. | |
int | ast_odbc_smart_execute (struct odbc_obj *obj, SQLHSTMT stmt) |
Executes a prepared statement handle. |
Definition in file res_odbc.h.
enum odbc_status |
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.
obj | The ODBC object | |
prepare_cb | A function callback, which, when called, should return a statement handle prepared, with any necessary parameters or result columns bound. | |
data | A parameter to be passed to the prepare_cb parameter function, indicating which statement handle is to be prepared. |
Definition at line 79 of file res_odbc.c.
References ast_log(), LOG_WARNING, odbc_obj_connect(), and odbc_obj_disconnect().
Referenced by acf_odbc_read(), acf_odbc_write(), config_odbc(), realtime_multi_odbc(), realtime_odbc(), and update_odbc().
00080 { 00081 int res = 0, i, attempt; 00082 SQLINTEGER nativeerror=0, numfields=0; 00083 SQLSMALLINT diagbytes=0; 00084 unsigned char state[10], diagnostic[256]; 00085 SQLHSTMT stmt; 00086 00087 for (attempt = 0; attempt < 2; attempt++) { 00088 /* This prepare callback may do more than just prepare -- it may also 00089 * bind parameters, bind results, etc. The real key, here, is that 00090 * when we disconnect, all handles become invalid for most databases. 00091 * We must therefore redo everything when we establish a new 00092 * connection. */ 00093 stmt = prepare_cb(obj, data); 00094 00095 if (stmt) { 00096 res = SQLExecute(stmt); 00097 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) { 00098 if (res == SQL_ERROR) { 00099 SQLGetDiagField(SQL_HANDLE_STMT, stmt, 1, SQL_DIAG_NUMBER, &numfields, SQL_IS_INTEGER, &diagbytes); 00100 for (i = 0; i < numfields; i++) { 00101 SQLGetDiagRec(SQL_HANDLE_STMT, stmt, i + 1, state, &nativeerror, diagnostic, sizeof(diagnostic), &diagbytes); 00102 ast_log(LOG_WARNING, "SQL Execute returned an error %d: %s: %s (%d)\n", res, state, diagnostic, diagbytes); 00103 if (i > 10) { 00104 ast_log(LOG_WARNING, "Oh, that was good. There are really %d diagnostics?\n", (int)numfields); 00105 break; 00106 } 00107 } 00108 } 00109 00110 ast_log(LOG_WARNING, "SQL Execute error %d! Attempting a reconnect...\n", res); 00111 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00112 stmt = NULL; 00113 00114 obj->up = 0; 00115 /* 00116 * While this isn't the best way to try to correct an error, this won't automatically 00117 * fail when the statement handle invalidates. 00118 */ 00119 /* XXX Actually, it might, if we're using a non-pooled connection. Possible race here. XXX */ 00120 odbc_obj_disconnect(obj); 00121 odbc_obj_connect(obj); 00122 continue; 00123 } 00124 break; 00125 } else { 00126 ast_log(LOG_WARNING, "SQL Prepare failed. Attempting a reconnect...\n"); 00127 odbc_obj_disconnect(obj); 00128 odbc_obj_connect(obj); 00129 } 00130 } 00131 00132 return stmt; 00133 }
void ast_odbc_release_obj | ( | struct odbc_obj * | obj | ) |
Releases an ODBC object previously allocated by odbc_request_obj().
obj | The ODBC object |
Definition at line 375 of file res_odbc.c.
References odbc_obj::used.
Referenced by acf_odbc_read(), acf_odbc_write(), config_odbc(), odbc_register_class(), realtime_multi_odbc(), realtime_odbc(), and update_odbc().
00376 { 00377 /* For pooled connections, this frees the connection to be 00378 * reused. For non-pooled connections, it does nothing. */ 00379 obj->used = 0; 00380 }
struct odbc_obj* ast_odbc_request_obj | ( | const char * | name, | |
int | check | |||
) |
Retrieves a connected ODBC object.
name | The name of the ODBC class for which a connection is needed. | |
check | Whether to ensure that a connection is valid before returning the handle. Usually unnecessary. |
Definition at line 382 of file res_odbc.c.
References ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_destroy(), ast_mutex_init(), ast_odbc_sanity_check(), free, LOG_WARNING, ODBC_FAIL, odbc_obj_connect(), and odbc_obj::used.
Referenced by acf_odbc_read(), acf_odbc_write(), config_odbc(), odbc_register_class(), realtime_multi_odbc(), realtime_odbc(), and update_odbc().
00383 { 00384 struct odbc_obj *obj = NULL; 00385 struct odbc_class *class; 00386 00387 AST_LIST_LOCK(&odbc_list); 00388 AST_LIST_TRAVERSE(&odbc_list, class, list) { 00389 if (!strcmp(class->name, name)) 00390 break; 00391 } 00392 AST_LIST_UNLOCK(&odbc_list); 00393 00394 if (!class) 00395 return NULL; 00396 00397 AST_LIST_LOCK(&class->odbc_obj); 00398 if (class->haspool) { 00399 /* Recycle connections before building another */ 00400 AST_LIST_TRAVERSE(&class->odbc_obj, obj, list) { 00401 if (! obj->used) { 00402 obj->used = 1; 00403 break; 00404 } 00405 } 00406 00407 if (!obj && (class->count < class->limit)) { 00408 class->count++; 00409 obj = ast_calloc(1, sizeof(*obj)); 00410 if (!obj) { 00411 AST_LIST_UNLOCK(&class->odbc_obj); 00412 return NULL; 00413 } 00414 ast_mutex_init(&obj->lock); 00415 obj->parent = class; 00416 if (odbc_obj_connect(obj) == ODBC_FAIL) { 00417 ast_log(LOG_WARNING, "Failed to connect to %s\n", name); 00418 ast_mutex_destroy(&obj->lock); 00419 free(obj); 00420 obj = NULL; 00421 class->count--; 00422 } else { 00423 obj->used = 1; 00424 AST_LIST_INSERT_TAIL(&class->odbc_obj, obj, list); 00425 } 00426 } 00427 } else { 00428 /* Non-pooled connection: multiple modules can use the same connection. */ 00429 AST_LIST_TRAVERSE(&class->odbc_obj, obj, list) { 00430 /* Non-pooled connection: if there is an entry, return it */ 00431 break; 00432 } 00433 00434 if (!obj) { 00435 /* No entry: build one */ 00436 obj = ast_calloc(1, sizeof(*obj)); 00437 if (!obj) { 00438 AST_LIST_UNLOCK(&class->odbc_obj); 00439 return NULL; 00440 } 00441 ast_mutex_init(&obj->lock); 00442 obj->parent = class; 00443 if (odbc_obj_connect(obj) == ODBC_FAIL) { 00444 ast_log(LOG_WARNING, "Failed to connect to %s\n", name); 00445 ast_mutex_destroy(&obj->lock); 00446 free(obj); 00447 obj = NULL; 00448 } else { 00449 AST_LIST_INSERT_HEAD(&class->odbc_obj, obj, list); 00450 } 00451 } 00452 } 00453 AST_LIST_UNLOCK(&class->odbc_obj); 00454 00455 if (obj && check) { 00456 ast_odbc_sanity_check(obj); 00457 } 00458 return obj; 00459 }
int ast_odbc_sanity_check | ( | struct odbc_obj * | obj | ) |
Checks an ODBC object to ensure it is still connected.
obj | The ODBC object |
Definition at line 177 of file res_odbc.c.
References ast_log(), odbc_obj::con, LOG_WARNING, odbc_obj_connect(), odbc_obj_disconnect(), and odbc_obj::up.
Referenced by ast_odbc_request_obj(), and odbc_show_command().
00178 { 00179 char *test_sql = "select 1"; 00180 SQLHSTMT stmt; 00181 int res = 0; 00182 00183 if (obj->up) { 00184 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt); 00185 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00186 obj->up = 0; 00187 } else { 00188 res = SQLPrepare(stmt, (unsigned char *)test_sql, SQL_NTS); 00189 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00190 obj->up = 0; 00191 } else { 00192 res = SQLExecute(stmt); 00193 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00194 obj->up = 0; 00195 } 00196 } 00197 } 00198 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00199 } 00200 00201 if (!obj->up) { /* Try to reconnect! */ 00202 ast_log(LOG_WARNING, "Connection is down attempting to reconnect...\n"); 00203 odbc_obj_disconnect(obj); 00204 odbc_obj_connect(obj); 00205 } 00206 return obj->up; 00207 }
int ast_odbc_smart_execute | ( | struct odbc_obj * | obj, | |
SQLHSTMT | stmt | |||
) |
Executes a prepared statement handle.
obj | The non-NULL result of odbc_request_obj() | |
stmt | The prepared statement handle |
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 135 of file res_odbc.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), odbc_obj::lock, LOG_WARNING, odbc_obj_connect(), odbc_obj_disconnect(), and odbc_obj::up.
00136 { 00137 int res = 0, i; 00138 SQLINTEGER nativeerror=0, numfields=0; 00139 SQLSMALLINT diagbytes=0; 00140 unsigned char state[10], diagnostic[256]; 00141 00142 res = SQLExecute(stmt); 00143 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) { 00144 if (res == SQL_ERROR) { 00145 SQLGetDiagField(SQL_HANDLE_STMT, stmt, 1, SQL_DIAG_NUMBER, &numfields, SQL_IS_INTEGER, &diagbytes); 00146 for (i = 0; i < numfields; i++) { 00147 SQLGetDiagRec(SQL_HANDLE_STMT, stmt, i + 1, state, &nativeerror, diagnostic, sizeof(diagnostic), &diagbytes); 00148 ast_log(LOG_WARNING, "SQL Execute returned an error %d: %s: %s (%d)\n", res, state, diagnostic, diagbytes); 00149 if (i > 10) { 00150 ast_log(LOG_WARNING, "Oh, that was good. There are really %d diagnostics?\n", (int)numfields); 00151 break; 00152 } 00153 } 00154 } 00155 #if 0 00156 /* This is a really bad method of trying to correct a dead connection. It 00157 * only ever really worked with MySQL. It will not work with any other 00158 * database, since most databases prepare their statements on the server, 00159 * and if you disconnect, you invalidate the statement handle. Hence, if 00160 * you disconnect, you're going to fail anyway, whether you try to execute 00161 * a second time or not. 00162 */ 00163 ast_log(LOG_WARNING, "SQL Execute error %d! Attempting a reconnect...\n", res); 00164 ast_mutex_lock(&obj->lock); 00165 obj->up = 0; 00166 ast_mutex_unlock(&obj->lock); 00167 odbc_obj_disconnect(obj); 00168 odbc_obj_connect(obj); 00169 res = SQLExecute(stmt); 00170 #endif 00171 } 00172 00173 return res; 00174 }