Skip to content
Snippets Groups Projects
func_odbc.c 53.6 KiB
Newer Older
 * Asterisk -- An open source telephony toolkit.
 * Copyright (c) 2005, 2006 Tilghman Lesher
 * Copyright (c) 2008, 2009 Digium, Inc.
 *
 * Tilghman Lesher <func_odbc__200508@the-tilghman.com>
 *
 * See http://www.asterisk.org for more information about
 * the Asterisk project. Please do not directly contact
 * any of the maintainers of this project for assistance;
 * the project provides a web site, mailing lists and IRC
 * channels for your use.
 *
 * This program is free software, distributed under the terms of
 * the GNU General Public License Version 2. See the LICENSE file
 * at the top of the source tree.
/*!
 * \file
 *
 * \brief ODBC lookups
 *
 * \author Tilghman Lesher <func_odbc__200508@the-tilghman.com>
Olle Johansson's avatar
Olle Johansson committed
 *
 * \ingroup functions
	<depend>res_odbc</depend>
	<support_level>core</support_level>
#include "asterisk/module.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/res_odbc.h"
#include "asterisk/res_odbc_transaction.h"
#include "asterisk/cli.h"
/*** DOCUMENTATION
	<function name="ODBC_FETCH" language="en_US">
		<synopsis>
			Fetch a row from a multirow query.
		</synopsis>
		<syntax>
			<parameter name="result-id" required="true" />
		</syntax>
		<description>
			<para>For queries which are marked as mode=multirow, the original
			query returns a <replaceable>result-id</replaceable> from which results
			may be fetched.  This function implements the actual fetch of the results.</para>
			<para>This also sets <variable>ODBC_FETCH_STATUS</variable>.</para>
			<variablelist>
				<variable name="ODBC_FETCH_STATUS">
					<value name="SUCESS">
						If rows are available.
					</value>
					<value name="FAILURE">
						If no rows are available.
					</value>
				</variable>
			</variablelist>
		</description>
	</function>
	<application name="ODBCFinish" language="en_US">
		<synopsis>
			Clear the resultset of a sucessful multirow query.
		</synopsis>
		<syntax>
			<parameter name="result-id" required="true" />
		</syntax>
		<description>
			<para>For queries which are marked as mode=multirow, this will clear
			any remaining rows of the specified resultset.</para>
		</description>
	</application>
	<function name="SQL_ESC" language="en_US">
		<synopsis>
			Escapes single ticks for use in SQL statements.
		</synopsis>
		<syntax>
			<parameter name="string" required="true" />
		</syntax>
		<description>
			<para>Used in SQL templates to escape data which may contain single ticks
			<literal>'</literal> which are otherwise used to delimit data.</para>
			<example title="Escape example">
			 SELECT foo FROM bar WHERE baz='${SQL_ESC(${ARG1})}'
			</example>
		</description>
	</function>
	<function name="SQL_ESC_BACKSLASHES" language="en_US">
		<synopsis>
			Escapes backslashes for use in SQL statements.
		</synopsis>
		<syntax>
			<parameter name="string" required="true" />
		</syntax>
		<description>
			<para>Used in SQL templates to escape data which may contain backslashes
			<literal>\</literal> which are otherwise used to escape data.</para>
			<example title="Escape with backslashes example">
			SELECT foo FROM bar WHERE baz='${SQL_ESC(${SQL_ESC_BACKSLASHES(${ARG1})})}'
			</example>
static char *config = "func_odbc.conf";

#define DEFAULT_SINGLE_DB_CONNECTION 0

static int single_db_connection;

AST_RWLOCK_DEFINE_STATIC(single_db_connection_lock);

enum odbc_option_flags {
	OPT_ESCAPECOMMAS =	(1 << 0),
	OPT_MULTIROW     =	(1 << 1),
struct acf_odbc_query {
	char readhandle[5][30];
	char writehandle[5][30];
	struct ast_custom_function *acf;
};

static void odbc_datastore_free(void *data);

static const struct ast_datastore_info odbc_info = {
	.type = "FUNC_ODBC",
	.destroy = odbc_datastore_free,
};

/* For storing each result row */
struct odbc_datastore_row {
	AST_LIST_ENTRY(odbc_datastore_row) list;
	char data[0];
};

/* For storing each result set */
struct odbc_datastore {
	AST_LIST_HEAD(, odbc_datastore_row);
	char names[0];
};

/*! \brief Data source name
 *
 * This holds data that pertains to a DSN
 */
struct dsn {
	/*! A connection to the database */
	struct odbc_obj *connection;
	/*! The name of the DSN as defined in res_odbc.conf */
	char name[0];
};

#define DSN_BUCKETS 37

struct ao2_container *dsns;

static int dsn_hash(const void *obj, const int flags)
{
	const struct dsn *object;
	const char *key;

	switch (flags & OBJ_SEARCH_MASK) {
	case OBJ_SEARCH_KEY:
		key = obj;
		break;
	case OBJ_SEARCH_OBJECT:
		object = obj;
		key = object->name;
		break;
	default:
		ast_assert(0);
		return 0;
	}
	return ast_str_hash(key);
}

static int dsn_cmp(void *obj, void *arg, int flags)
{
	const struct dsn *object_left = obj;
Loading
Loading full blame...