424 char varname[15], rowcount[12] =
"-1";
426 int res, x, y, buflen = 0, escapecommas, rowlimit = 1, multirow = 0,
dsn, bogus_chan = 0;
430 SQLHSTMT stmt = NULL;
431 SQLSMALLINT colcount=0;
433 SQLSMALLINT collength;
437 const char *
status =
"FAILURE";
439 if (!sql || !colnames) {
450 if (!strcmp(query->acf->name, cmd)) {
478 for (x = 0; x <
args.argc; x++) {
479 snprintf(varname,
sizeof(varname),
"ARG%d", x + 1);
489 for (x = 0; x <
args.argc; x++) {
490 snprintf(varname,
sizeof(varname),
"ARG%d", x + 1);
498 if (!(resultset =
ast_calloc(1,
sizeof(*resultset)))) {
505 if (query->rowlimit) {
506 rowlimit = query->rowlimit;
511 }
else if (!bogus_chan) {
512 if (query->rowlimit > 1) {
513 rowlimit = query->rowlimit;
514 if (!(resultset =
ast_calloc(1,
sizeof(*resultset)))) {
555 res = SQLNumResultCols(stmt, &colcount);
556 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
558 SQLCloseCursor(stmt);
559 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
570 res = SQLFetch(stmt);
571 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
573 if (res == SQL_NO_DATA) {
581 status =
"FETCHERROR";
583 SQLCloseCursor(stmt);
584 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
598 for (y = 0; y < rowlimit; y++) {
600 for (x = 0; x < colcount; x++) {
607 SQLCloseCursor(stmt);
608 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
622 res = SQLDescribeCol(stmt, x + 1, (
unsigned char *)colname,
sizeof(colname), &collength, NULL, &maxcol, NULL, NULL);
623 ast_debug(3,
"Got collength of %d and maxcol of %d for column '%s' (offset %d)\n", (
int)collength, (
int)maxcol, colname, x);
624 if (((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) || collength == 0) {
625 snprintf(colname,
sizeof(colname),
"field%d", x);
640 SQLCloseCursor(stmt);
641 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
652 strcpy((
char *)resultset +
sizeof(*resultset),
ast_str_buffer(colnames));
656 buflen = strlen(buf);
658 if (indicator == SQL_NULL_DATA) {
664 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
680 if (escapecommas && (ptrcoldata[i] ==
'\\' || ptrcoldata[i] ==
',')) {
681 buf[buflen++] =
'\\';
683 buf[buflen++] = ptrcoldata[i];
685 if (buflen >=
len - 2) {
689 if (ptrcoldata[i] ==
'\0') {
695 ast_debug(2,
"buf is now set to '%s'\n", buf);
697 ast_debug(2,
"buf is now set to '%s'\n", buf);
700 row =
ast_calloc(1,
sizeof(*row) + buflen + 1);
702 ast_log(
LOG_ERROR,
"Unable to allocate space for more rows in this resultset.\n");
706 strcpy((
char *)row +
sizeof(*row), buf);
710 res = SQLFetch(stmt);
711 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
712 if (res != SQL_NO_DATA) {
724 snprintf(rowcount,
sizeof(rowcount),
"%d", y);
733 snprintf(buf,
len,
"%d", uid);
748 ast_log(
LOG_ERROR,
"Rows retrieved, but unable to store it in the channel. Results fail.\n");
750 SQLCloseCursor(stmt);
751 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
758 odbc_store->
data = resultset;
764 SQLCloseCursor(stmt);
765 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
768 if (resultset && !multirow) {
#define ast_channel_lock(chan)
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
#define ast_channel_unref(c)
Decrease channel reference count.
#define ast_test_flag(p, flag)
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
static struct ast_threadstorage sql_buf
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
char * ast_str_append_escapecommas(struct ast_str **buf, ssize_t maxlen, const char *src, size_t maxsrc)
Append a non-NULL terminated substring to the end of a dynamic string, with escaping of commas...
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Structure for a data store object.
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
void pbx_builtin_pushvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, without removing any previously set value...
static SQLHSTMT generic_execute(struct odbc_obj *obj, void *data)
#define ast_verb(level,...)
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
#define ast_debug(level,...)
Log a DEBUG message.
static struct ast_datastore_info odbc_info
int ast_str_make_space(struct ast_str **buf, size_t new_len)
static force_inline int attribute_pure ast_strlen_zero(const char *s)
#define AST_RWLIST_TRAVERSE
static struct ast_threadstorage coldata_buf
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
static int acf_fetch(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
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.
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
static void odbc_datastore_free(void *data)
#define ast_channel_unlock(chan)
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
#define ast_odbc_request_obj(a, b)
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define ast_realloc(a, b)
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.
#define AST_APP_ARG(name)
Define an application argument.
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
struct ast_channel * ast_dummy_channel_alloc(void)
Create a fake channel structure.
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
static struct ast_threadstorage colnames_buf
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.