Initial core-pgsql support based on native libpq; FS starts and stops without errors using core-pgsql.
This commit is contained in:
parent
0263ce9247
commit
5cb354dddc
|
@ -207,7 +207,8 @@ library_include_HEADERS = \
|
|||
libs/libteletone/src/libteletone.h \
|
||||
libs/libtpl-1.5/src/tpl.h \
|
||||
src/include/switch_limit.h \
|
||||
src/include/switch_odbc.h
|
||||
src/include/switch_odbc.h \
|
||||
src/include/switch_pgsql.h
|
||||
|
||||
nodist_libfreeswitch_la_SOURCES = \
|
||||
src/include/switch_frame.h \
|
||||
|
@ -262,6 +263,7 @@ libfreeswitch_la_SOURCES = \
|
|||
src/switch_config.c \
|
||||
src/switch_time.c \
|
||||
src/switch_odbc.c \
|
||||
src/switch_pgsql.c \
|
||||
src/switch_limit.c \
|
||||
src/g711.c \
|
||||
src/switch_pcm.c \
|
||||
|
|
|
@ -144,6 +144,8 @@
|
|||
|
||||
<param name="rtp-enable-zrtp" value="true"/>
|
||||
|
||||
<!-- Example DSN when using "./configure --enable-core-pgsql-support" -->
|
||||
<!-- <param name="core-db-dsn" value="pgsql;hostaddr=127.0.0.1 dbname=freeswitch user=freeswitch password='' options='-c client_min_messages=NOTICE' application_name='freeswitch'" /> -->
|
||||
<!-- <param name="core-db-dsn" value="dsn:username:password" /> -->
|
||||
<!--
|
||||
Allow to specify the sqlite db at a different location (In this example, move it to ramdrive for
|
||||
|
|
|
@ -213,6 +213,9 @@
|
|||
<!--If you have ODBC support and a working dsn you can use it instead of SQLite-->
|
||||
<!--<param name="odbc-dsn" value="dsn:user:pass"/>-->
|
||||
|
||||
<!-- Or, if you have PGSQL support, you can use that -->
|
||||
<!--<param name="odbc-dsn" value="pgsql;hostaddr=127.0.0.1 dbname=freeswitch user=freeswitch password='' options='-c client_min_messages=NOTICE' application_name='freeswitch'" />-->
|
||||
|
||||
<!--Uncomment to set all inbound calls to no media mode-->
|
||||
<!--<param name="inbound-bypass-media" value="true"/>-->
|
||||
|
||||
|
|
23
configure.in
23
configure.in
|
@ -395,7 +395,30 @@ if test "x$enable_core_odbc_support" != "xno"; then
|
|||
AC_CHECK_LIB([odbc], [SQLDisconnect],, AC_MSG_ERROR([no usable libodbc; please install unixodbc devel package or equivalent]))
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(core-pgsql-support,
|
||||
[AS_HELP_STRING([--enable-core-pgsql-support], [Compile with PGSQL Support])],,[enable_core_pgsql_support="no"])
|
||||
|
||||
if test x"$enable_core_pgsql_support" = x"yes" ; then
|
||||
|
||||
AC_PATH_PROG([PG_CONFIG], [pg_config], [no])
|
||||
if test "$PG_CONFIG" != "no"; then
|
||||
AC_MSG_CHECKING([for PostgreSQL libraries])
|
||||
POSTGRESQL_CFLAGS="`$PG_CONFIG --cflags` -I`$PG_CONFIG --includedir`"
|
||||
POSTGRESQL_CXXFLAGS="`$PG_CONFIG --cppflags` -I`$PG_CONFIG --includedir`"
|
||||
POSTGRESQL_LDFLAGS="`$PG_CONFIG --ldflags` -L`$PG_CONFIG --libdir` -lpq"
|
||||
POSTGRESQL_VERSION=`$PG_CONFIG --version | sed -e 's#PostgreSQL ##'`
|
||||
AC_DEFINE([SWITCH_HAVE_PGSQL], [1], [Define to 1 if PostgreSQL libraries are available])
|
||||
AC_CHECK_LIB([pq], [PQgetvalue],, AC_MSG_ERROR([no usable libpq; please install PostgreSQL devel package or equivalent]))
|
||||
AC_MSG_RESULT([yes])
|
||||
SWITCH_AM_CFLAGS="$POSTGRESQL_CFLAGS $SWITCH_AM_CFLAGS"
|
||||
SWITCH_AM_CXXFLAGS="$POSTGRESQL_CXXFLAGS $SWITCH_AM_CXXFLAGS"
|
||||
SWITCH_AM_LDFLAGS="$POSTGRESQL_LDFLAGS $SWITCH_AM_LDFLAGS"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_FAILURE([Unabled to find pg_config in PATH. Is PostgreSQL installed?])
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(timerfd-wrapper,
|
||||
[AC_HELP_STRING([--enable-timerfd-wrapper],[timerfd is in the kernel but not in your libc])],[enable_timer_fd_wrapper="$enableval"],[enable_timer_fd_wrapper="no"])
|
||||
|
|
|
@ -135,6 +135,7 @@
|
|||
#include "switch_config.h"
|
||||
#include "switch_nat.h"
|
||||
#include "switch_odbc.h"
|
||||
#include "switch_pgsql.h"
|
||||
#include "switch_json.h"
|
||||
#include "switch_limit.h"
|
||||
|
||||
|
|
|
@ -2210,12 +2210,14 @@ typedef enum {
|
|||
|
||||
typedef enum {
|
||||
SCDB_TYPE_CORE_DB,
|
||||
SCDB_TYPE_ODBC
|
||||
SCDB_TYPE_ODBC,
|
||||
SCDB_TYPE_PGSQL
|
||||
} switch_cache_db_handle_type_t;
|
||||
|
||||
typedef union {
|
||||
switch_core_db_t *core_db_dbh;
|
||||
switch_odbc_handle_t *odbc_dbh;
|
||||
switch_pgsql_handle_t *pgsql_dbh;
|
||||
} switch_cache_db_native_handle_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -2228,9 +2230,14 @@ typedef struct {
|
|||
char *pass;
|
||||
} switch_cache_db_odbc_options_t;
|
||||
|
||||
typedef struct {
|
||||
char *dsn;
|
||||
} switch_cache_db_pgsql_options_t;
|
||||
|
||||
typedef union {
|
||||
switch_cache_db_core_db_options_t core_db_options;
|
||||
switch_cache_db_odbc_options_t odbc_options;
|
||||
switch_cache_db_pgsql_options_t pgsql_options;
|
||||
} switch_cache_db_connection_options_t;
|
||||
|
||||
struct switch_cache_db_handle;
|
||||
|
@ -2241,6 +2248,11 @@ static inline const char *switch_cache_db_type_name(switch_cache_db_handle_type_
|
|||
const char *type_str = "INVALID";
|
||||
|
||||
switch (type) {
|
||||
case SCDB_TYPE_PGSQL:
|
||||
{
|
||||
type_str = "PGSQL";
|
||||
}
|
||||
break;
|
||||
case SCDB_TYPE_ODBC:
|
||||
{
|
||||
type_str = "ODBC";
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
* Eliot Gable <egable@gmail.com>
|
||||
*
|
||||
* switch_pgsql.h -- PGSQL Driver
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SWITCH_PGSQL_H
|
||||
#define SWITCH_PGSQL_H
|
||||
|
||||
#include <switch.h>
|
||||
|
||||
#define DEFAULT_PGSQL_RETRIES 120
|
||||
|
||||
SWITCH_BEGIN_EXTERN_C
|
||||
|
||||
struct switch_pgsql_handle;
|
||||
struct switch_pgsql_result;
|
||||
|
||||
|
||||
typedef enum {
|
||||
SWITCH_PGSQL_STATE_INIT,
|
||||
SWITCH_PGSQL_STATE_DOWN,
|
||||
SWITCH_PGSQL_STATE_CONNECTED,
|
||||
SWITCH_PGSQL_STATE_ERROR
|
||||
} switch_pgsql_state_t;
|
||||
|
||||
typedef enum {
|
||||
SWITCH_PGSQL_SUCCESS = 0,
|
||||
SWITCH_PGSQL_FAIL = -1
|
||||
} switch_pgsql_status_t;
|
||||
|
||||
/*!
|
||||
\brief Create a new handle for the PGSQL connection.
|
||||
\param dsn The DSN of the database to connect to. See documentation for PQconnectdb() at
|
||||
http://www.postgresql.org/docs/9.0/static/libpq-connect.html. The DSN *MUST* be
|
||||
prefixed with 'pgsql;' to use the switch_cache_db* functionality. However, the DSN
|
||||
passed to this function directly *MUST NOT* be prefixed with 'pgsql;'.
|
||||
\return Returns a pointer to a newly allocated switch_pgsql_handle_t type or NULL on failure.
|
||||
*/
|
||||
SWITCH_DECLARE(switch_pgsql_handle_t *) switch_pgsql_handle_new(const char *dsn);
|
||||
|
||||
/*!
|
||||
\brief Sets the number of retries if the PGSQL connection fails.
|
||||
\param handle A fully allocated switch_pgsql_handle_t returned from a call to switch_pgsql_handle_new().
|
||||
\param num_retries How many times to retry connecting to the database if this connection fails.
|
||||
*/
|
||||
SWITCH_DECLARE(void) switch_pgsql_set_num_retries(switch_pgsql_handle_t *handle, int num_retries);
|
||||
|
||||
/*!
|
||||
\brief Disconnects a PGSQL connection from the database.
|
||||
\param handle The PGSQL database handle to disconnect.
|
||||
\return Returns SWITCH_PGSQL_SUCCESS or SWITCH_PGSQL_FAIL.
|
||||
*/
|
||||
SWITCH_DECLARE(switch_pgsql_status_t ) switch_pgsql_handle_disconnect(switch_pgsql_handle_t *handle);
|
||||
#if 0
|
||||
) /* Emacs formatting issue */
|
||||
#endif
|
||||
/*!
|
||||
\brief Connect to the database specified by the DSN passed to the switch_pgsql_handle_new() call which
|
||||
initialized this handle.
|
||||
\param The database handle to connect to the database.
|
||||
\return Returns SWITCH_PGSQL_SUCCESS or SWITCH_PGSQL_FAIL.
|
||||
*/
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_connect(switch_pgsql_handle_t *handle);
|
||||
|
||||
/*!
|
||||
*/
|
||||
SWITCH_DECLARE(void) switch_pgsql_handle_destroy(switch_pgsql_handle_t **handlep);
|
||||
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_send_query(switch_pgsql_handle_t *handle, const char* sql);
|
||||
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_cancel_real(const char *file, const char *func, int line, switch_pgsql_handle_t *handle);
|
||||
#define switch_pgsql_cancel(handle) switch_pgsql_cancel_real(__FILE__, (char * )__SWITCH_FUNC__, __LINE__, handle)
|
||||
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_next_result_timed(switch_pgsql_handle_t *handle, switch_pgsql_result_t **result_out, int seconds);
|
||||
#define switch_pgsql_next_result(h, r) switch_pgsql_next_result_timed(h, r, 10000)
|
||||
|
||||
SWITCH_DECLARE(void) switch_pgsql_free_result(switch_pgsql_result_t **result);
|
||||
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_finish_results_real(const char* file, const char *func, int line, switch_pgsql_handle_t *handle);
|
||||
#define switch_pgsql_finish_results(handle) switch_pgsql_finish_results_real(__FILE__, (char * )__SWITCH_FUNC__, __LINE__, handle)
|
||||
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_base(switch_pgsql_handle_t *handle, const char *sql, char **err);
|
||||
|
||||
SWITCH_DECLARE(switch_pgsql_state_t) switch_pgsql_handle_get_state(switch_pgsql_handle_t *handle);
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec(switch_pgsql_handle_t *handle, const char *sql, char **err);
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_string(switch_pgsql_handle_t *handle, const char *sql, char *resbuf, size_t len, char **err);
|
||||
SWITCH_DECLARE(switch_bool_t) switch_pgsql_available(void);
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_SQLSetAutoCommitAttr(switch_pgsql_handle_t *handle, switch_bool_t on);
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_SQLEndTran(switch_pgsql_handle_t *handle, switch_bool_t commit);
|
||||
|
||||
/*!
|
||||
\brief Execute the sql query and issue a callback for each row returned
|
||||
\param file the file from which this function is called
|
||||
\param func the function from which this function is called
|
||||
\param line the line from which this function is called
|
||||
\param handle the PGSQL handle
|
||||
\param sql the sql string to execute
|
||||
\param callback the callback function to execute
|
||||
\param pdata the state data passed on each callback invocation
|
||||
\return SWITCH_STATUS_SUCCESS if the operation was successful
|
||||
\note none
|
||||
*/
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_callback_exec_detailed(const char *file, const char *func, int line, switch_pgsql_handle_t *handle,
|
||||
const char *sql, switch_core_db_callback_func_t callback, void *pdata,
|
||||
char **err);
|
||||
/*!
|
||||
\brief Execute the sql query and issue a callback for each row returned
|
||||
\param handle the PGSQL handle
|
||||
\param sql the sql string to execute
|
||||
\param callback the callback function to execute
|
||||
\param pdata the state data passed on each callback invocation
|
||||
\return SWITCH_STATUS_SUCCESS if the operation was successful
|
||||
\note none
|
||||
*/
|
||||
#define switch_pgsql_handle_callback_exec(handle, sql, callback, pdata, err) \
|
||||
switch_pgsql_handle_callback_exec_detailed(__FILE__, (char * )__SWITCH_FUNC__, __LINE__, \
|
||||
handle, sql, callback, pdata, err)
|
||||
|
||||
|
||||
SWITCH_DECLARE(char *) switch_pgsql_handle_get_error(switch_pgsql_handle_t *handle);
|
||||
|
||||
SWITCH_DECLARE(int) switch_pgsql_handle_affected_rows(switch_pgsql_handle_t *handle);
|
||||
|
||||
SWITCH_END_EXTERN_C
|
||||
#endif
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
|
@ -324,7 +324,7 @@ typedef enum {
|
|||
SCF_CLEAR_SQL = (1 << 17),
|
||||
SCF_THREADED_SYSTEM_EXEC = (1 << 18),
|
||||
SCF_SYNC_CLOCK_REQUESTED = (1 << 19),
|
||||
SCF_CORE_ODBC_REQ = (1 << 20),
|
||||
SCF_CORE_NON_SQLITE_DB_REQ = (1 << 20),
|
||||
SCF_DEBUG_SQL = (1 << 21),
|
||||
SCF_API_EXPANSION = (1 << 22),
|
||||
SCF_SESSION_THREAD_POOL = (1 << 23)
|
||||
|
@ -1833,6 +1833,8 @@ typedef struct switch_buffer switch_buffer_t;
|
|||
typedef struct switch_codec_settings switch_codec_settings_t;
|
||||
typedef struct switch_codec_fmtp switch_codec_fmtp_t;
|
||||
typedef struct switch_odbc_handle switch_odbc_handle_t;
|
||||
typedef struct switch_pgsql_handle switch_pgsql_handle_t;
|
||||
typedef struct switch_pgsql_result switch_pgsql_result_t;
|
||||
|
||||
typedef struct switch_io_routines switch_io_routines_t;
|
||||
typedef struct switch_speech_handle switch_speech_handle_t;
|
||||
|
|
|
@ -94,12 +94,20 @@ static switch_cache_db_handle_t *cidlookup_get_db_handle(void)
|
|||
switch_cache_db_handle_t *dbh = NULL;
|
||||
|
||||
if (!zstr(globals.odbc_dsn)) {
|
||||
options.odbc_options.dsn = globals.odbc_dsn;
|
||||
options.odbc_options.user = globals.odbc_user;
|
||||
options.odbc_options.pass = globals.odbc_pass;
|
||||
char *dsn;
|
||||
if ((dsn = strstr(globals.odbc_dsn, "pgsql;")) != NULL) {
|
||||
options.pgsql_options.dsn = (char*)(dsn + 6);
|
||||
|
||||
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS)
|
||||
dbh = NULL;
|
||||
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_PGSQL, &options) != SWITCH_STATUS_SUCCESS)
|
||||
dbh = NULL;
|
||||
} else {
|
||||
options.odbc_options.dsn = globals.odbc_dsn;
|
||||
options.odbc_options.user = globals.odbc_user;
|
||||
options.odbc_options.pass = globals.odbc_pass;
|
||||
|
||||
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS)
|
||||
dbh = NULL;
|
||||
}
|
||||
}
|
||||
return dbh;
|
||||
}
|
||||
|
@ -112,8 +120,8 @@ static switch_status_t config_callback_dsn(switch_xml_config_item_t *data, const
|
|||
|
||||
switch_cache_db_handle_t *dbh = NULL;
|
||||
|
||||
if (!switch_odbc_available()) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC is not compiled in. Do not configure odbc-dsn parameter!\n");
|
||||
if (!switch_odbc_available() && !switch_pgsql_available()) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC and PGSQL are not compiled in. Do not configure odbc-dsn parameter!\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
|
@ -134,7 +142,7 @@ static switch_status_t config_callback_dsn(switch_xml_config_item_t *data, const
|
|||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connecting to dsn: %s\n", globals.odbc_dsn);
|
||||
|
||||
if (!(dbh = cidlookup_get_db_handle())) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open ODBC Database!\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open Database!\n");
|
||||
switch_goto_status(SWITCH_STATUS_FALSE, done);
|
||||
}
|
||||
}
|
||||
|
@ -195,7 +203,7 @@ static switch_bool_t cidlookup_execute_sql_callback(char *sql, switch_core_db_ca
|
|||
retval = SWITCH_TRUE;
|
||||
}
|
||||
} else {
|
||||
*err = switch_core_sprintf(cbt->pool, "Unable to get ODBC handle. dsn: %s, dbh is %s\n", globals.odbc_dsn, dbh ? "not null" : "null");
|
||||
*err = switch_core_sprintf(cbt->pool, "Unable to get database handle. dsn: %s, dbh is %s\n", globals.odbc_dsn, dbh ? "not null" : "null");
|
||||
}
|
||||
|
||||
switch_cache_db_release_db_handle(&dbh);
|
||||
|
@ -564,7 +572,7 @@ static cid_data_t *do_lookup(switch_memory_pool_t *pool, switch_event_t *event,
|
|||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "caller_id_number", number);
|
||||
|
||||
/* database always wins */
|
||||
if (switch_odbc_available() && globals.odbc_dsn && globals.sql) {
|
||||
if ((switch_odbc_available() || switch_pgsql_available()) && globals.odbc_dsn && globals.sql) {
|
||||
name = do_db_lookup(pool, event, number, globals.sql);
|
||||
if (name) {
|
||||
cid->name = name;
|
||||
|
@ -610,7 +618,7 @@ static cid_data_t *do_lookup(switch_memory_pool_t *pool, switch_event_t *event,
|
|||
switch_assert(cid);
|
||||
}
|
||||
/* append area if we can */
|
||||
if (!cid->area && !skipcitystate && strlen(number) == 11 && number[0] == '1' && switch_odbc_available() && globals.odbc_dsn && globals.citystate_sql) {
|
||||
if (!cid->area && !skipcitystate && strlen(number) == 11 && number[0] == '1' && (switch_odbc_available() || switch_pgsql_available()) && globals.odbc_dsn && globals.citystate_sql) {
|
||||
|
||||
/* yes, this is really area */
|
||||
name = do_db_lookup(pool, event, number, globals.citystate_sql);
|
||||
|
@ -768,7 +776,7 @@ SWITCH_STANDARD_API(cidlookup_function)
|
|||
stream->write_function(stream, " odbc-dsn: %s\n sql: %s\n citystate-sql: %s\n",
|
||||
globals.odbc_dsn ? globals.odbc_dsn : "(null)",
|
||||
globals.sql ? globals.sql : "(null)", globals.citystate_sql ? globals.citystate_sql : "(null)");
|
||||
stream->write_function(stream, " ODBC Compiled: %s\n", switch_odbc_available()? "true" : "false");
|
||||
stream->write_function(stream, " ODBC Compiled: %s; PGSQL Compiled: %s\n", switch_odbc_available() ? "true" : "false", switch_pgsql_available() ? "true" : "false");
|
||||
|
||||
switch_goto_status(SWITCH_STATUS_SUCCESS, done);
|
||||
}
|
||||
|
|
|
@ -92,12 +92,20 @@ switch_cache_db_handle_t *limit_get_db_handle(void)
|
|||
switch_cache_db_handle_t *dbh = NULL;
|
||||
|
||||
if (!zstr(globals.odbc_dsn)) {
|
||||
options.odbc_options.dsn = globals.odbc_dsn;
|
||||
options.odbc_options.user = globals.odbc_user;
|
||||
options.odbc_options.pass = globals.odbc_pass;
|
||||
char *dsn;
|
||||
if ((dsn = strstr(globals.odbc_dsn, "pgsql;")) != NULL) {
|
||||
options.pgsql_options.dsn = (char*)(dsn + 6);
|
||||
|
||||
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS)
|
||||
dbh = NULL;
|
||||
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_PGSQL, &options) != SWITCH_STATUS_SUCCESS)
|
||||
dbh = NULL;
|
||||
} else {
|
||||
options.odbc_options.dsn = globals.odbc_dsn;
|
||||
options.odbc_options.user = globals.odbc_user;
|
||||
options.odbc_options.pass = globals.odbc_pass;
|
||||
|
||||
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS)
|
||||
dbh = NULL;
|
||||
}
|
||||
return dbh;
|
||||
} else {
|
||||
options.core_db_options.db_path = globals.dbname;
|
||||
|
@ -275,7 +283,7 @@ SWITCH_LIMIT_STATUS(limit_status_db)
|
|||
|
||||
/* INIT / Config */
|
||||
|
||||
static switch_xml_config_string_options_t limit_config_dsn = { NULL, 0, "[^:]+:[^:]+:.+" };
|
||||
static switch_xml_config_string_options_t limit_config_dsn = { NULL, 0, "^pgsql;|[^:]+:[^:]+:.+" };
|
||||
|
||||
static switch_xml_config_item_t config_settings[] = {
|
||||
SWITCH_CONFIG_ITEM("odbc-dsn", SWITCH_CONFIG_STRING, 0, &globals.odbc_dsn, NULL, &limit_config_dsn,
|
||||
|
|
|
@ -731,12 +731,20 @@ switch_cache_db_handle_t *fifo_get_db_handle(void)
|
|||
switch_cache_db_handle_t *dbh = NULL;
|
||||
|
||||
if (!zstr(globals.odbc_dsn)) {
|
||||
options.odbc_options.dsn = globals.odbc_dsn;
|
||||
options.odbc_options.user = globals.odbc_user;
|
||||
options.odbc_options.pass = globals.odbc_pass;
|
||||
char *dsn;
|
||||
if ((dsn = strstr(globals.odbc_dsn, "pgsql;")) != NULL) {
|
||||
options.pgsql_options.dsn = (char*)(dsn + 6);
|
||||
|
||||
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS) {
|
||||
dbh = NULL;
|
||||
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_PGSQL, &options) != SWITCH_STATUS_SUCCESS)
|
||||
dbh = NULL;
|
||||
} else {
|
||||
options.odbc_options.dsn = globals.odbc_dsn;
|
||||
options.odbc_options.user = globals.odbc_user;
|
||||
options.odbc_options.pass = globals.odbc_pass;
|
||||
|
||||
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS) {
|
||||
dbh = NULL;
|
||||
}
|
||||
}
|
||||
return dbh;
|
||||
} else {
|
||||
|
@ -4010,7 +4018,7 @@ static switch_status_t load_config(int reload, int del_all)
|
|||
}
|
||||
|
||||
if (!strcasecmp(var, "odbc-dsn") && !zstr(val)) {
|
||||
if (switch_odbc_available()) {
|
||||
if (switch_odbc_available() || switch_pgsql_available()) {
|
||||
switch_set_string(globals.odbc_dsn, val);
|
||||
if ((globals.odbc_user = strchr(globals.odbc_dsn, ':'))) {
|
||||
*globals.odbc_user++ = '\0';
|
||||
|
|
|
@ -167,12 +167,20 @@ switch_cache_db_handle_t *vm_get_db_handle(vm_profile_t *profile)
|
|||
switch_cache_db_handle_t *dbh = NULL;
|
||||
|
||||
if (!zstr(profile->odbc_dsn)) {
|
||||
options.odbc_options.dsn = profile->odbc_dsn;
|
||||
options.odbc_options.user = profile->odbc_user;
|
||||
options.odbc_options.pass = profile->odbc_pass;
|
||||
char *dsn;
|
||||
if ((dsn = strstr(profile->odbc_dsn, "pgsql;")) != NULL) {
|
||||
options.pgsql_options.dsn = (char*)(dsn + 6);
|
||||
|
||||
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS)
|
||||
dbh = NULL;
|
||||
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_PGSQL, &options) != SWITCH_STATUS_SUCCESS)
|
||||
dbh = NULL;
|
||||
} else {
|
||||
options.odbc_options.dsn = profile->odbc_dsn;
|
||||
options.odbc_options.user = profile->odbc_user;
|
||||
options.odbc_options.pass = profile->odbc_pass;
|
||||
|
||||
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS)
|
||||
dbh = NULL;
|
||||
}
|
||||
return dbh;
|
||||
} else {
|
||||
options.core_db_options.db_path = profile->dbname;
|
||||
|
|
|
@ -4414,7 +4414,7 @@ switch_status_t config_sofia(int reload, char *profile_name)
|
|||
sofia_set_flag(profile, TFLAG_CAPTURE);
|
||||
nua_set_params(profile->nua, TPTAG_CAPT(mod_sofia_globals.capture_server), TAG_END());
|
||||
} else if (!strcasecmp(var, "odbc-dsn") && !zstr(val)) {
|
||||
if (switch_odbc_available()) {
|
||||
if (switch_odbc_available() || switch_pgsql_available()) {
|
||||
profile->odbc_dsn = switch_core_strdup(profile->pool, val);
|
||||
if ((profile->odbc_user = strchr(profile->odbc_dsn, ':'))) {
|
||||
*profile->odbc_user++ = '\0';
|
||||
|
|
|
@ -6367,12 +6367,20 @@ switch_cache_db_handle_t *sofia_glue_get_db_handle(sofia_profile_t *profile)
|
|||
switch_cache_db_handle_t *dbh = NULL;
|
||||
|
||||
if (!zstr(profile->odbc_dsn)) {
|
||||
options.odbc_options.dsn = profile->odbc_dsn;
|
||||
options.odbc_options.user = profile->odbc_user;
|
||||
options.odbc_options.pass = profile->odbc_pass;
|
||||
char *dsn;
|
||||
if ((dsn = strstr(profile->odbc_dsn, "pgsql;")) != NULL) {
|
||||
options.pgsql_options.dsn = (char*)(dsn + 6);
|
||||
|
||||
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS)
|
||||
dbh = NULL;
|
||||
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_PGSQL, &options) != SWITCH_STATUS_SUCCESS)
|
||||
dbh = NULL;
|
||||
} else {
|
||||
options.odbc_options.dsn = profile->odbc_dsn;
|
||||
options.odbc_options.user = profile->odbc_user;
|
||||
options.odbc_options.pass = profile->odbc_pass;
|
||||
|
||||
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS)
|
||||
dbh = NULL;
|
||||
}
|
||||
return dbh;
|
||||
} else {
|
||||
options.core_db_options.db_path = profile->dbname;
|
||||
|
|
|
@ -1910,7 +1910,7 @@ static void switch_load_core_config(const char *file)
|
|||
} else if (!strcasecmp(var, "core-db-name") && !zstr(val)) {
|
||||
runtime.dbname = switch_core_strdup(runtime.memory_pool, val);
|
||||
} else if (!strcasecmp(var, "core-db-dsn") && !zstr(val)) {
|
||||
if (switch_odbc_available()) {
|
||||
if (switch_odbc_available() || switch_pgsql_available()) {
|
||||
runtime.odbc_dsn = switch_core_strdup(runtime.memory_pool, val);
|
||||
if ((runtime.odbc_user = strchr(runtime.odbc_dsn, ':'))) {
|
||||
*runtime.odbc_user++ = '\0';
|
||||
|
@ -1919,10 +1919,10 @@ static void switch_load_core_config(const char *file)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC IS NOT AVAILABLE!\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC AND PGSQL ARE NOT AVAILABLE!\n");
|
||||
}
|
||||
} else if (!strcasecmp(var, "core-recovery-db-dsn") && !zstr(val)) {
|
||||
if (switch_odbc_available()) {
|
||||
if (switch_odbc_available() || switch_pgsql_available()) {
|
||||
runtime.recovery_odbc_dsn = switch_core_strdup(runtime.memory_pool, val);
|
||||
if ((runtime.recovery_odbc_user = strchr(runtime.recovery_odbc_dsn, ':'))) {
|
||||
*runtime.recovery_odbc_user++ = '\0';
|
||||
|
@ -1931,10 +1931,10 @@ static void switch_load_core_config(const char *file)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC IS NOT AVAILABLE!\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC AND PGSQL ARE NOT AVAILABLE!\n");
|
||||
}
|
||||
} else if (!strcasecmp(var, "core-odbc-required") && !zstr(val)) {
|
||||
switch_set_flag((&runtime), SCF_CORE_ODBC_REQ);
|
||||
} else if (!strcasecmp(var, "core-non-sqlite-db-required") && !zstr(val)) {
|
||||
switch_set_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ);
|
||||
} else if (!strcasecmp(var, "core-dbtype") && !zstr(val)) {
|
||||
if (!strcasecmp(val, "MSSQL")) {
|
||||
runtime.odbc_dbtype = DBTYPE_MSSQL;
|
||||
|
|
|
@ -190,7 +190,7 @@ SWITCH_DECLARE(switch_status_t) _switch_core_db_handle(switch_cache_db_handle_t
|
|||
}
|
||||
|
||||
if (zstr(runtime.odbc_dsn)) {
|
||||
if (switch_test_flag((&runtime), SCF_CORE_ODBC_REQ)) {
|
||||
if (switch_test_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ)) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
|
@ -202,11 +202,18 @@ SWITCH_DECLARE(switch_status_t) _switch_core_db_handle(switch_cache_db_handle_t
|
|||
r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_CORE_DB, &options, file, func, line);
|
||||
|
||||
} else {
|
||||
options.odbc_options.dsn = runtime.odbc_dsn;
|
||||
options.odbc_options.user = runtime.odbc_user;
|
||||
options.odbc_options.pass = runtime.odbc_pass;
|
||||
char *dsn;
|
||||
if ((dsn = strstr(runtime.odbc_dsn, "pgsql;")) != NULL) {
|
||||
options.pgsql_options.dsn = (char*)(dsn + 6);
|
||||
|
||||
r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_ODBC, &options, file, func, line);
|
||||
r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_PGSQL, &options, file, func, line);
|
||||
} else {
|
||||
options.odbc_options.dsn = runtime.odbc_dsn;
|
||||
options.odbc_options.user = runtime.odbc_user;
|
||||
options.odbc_options.pass = runtime.odbc_pass;
|
||||
|
||||
r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_ODBC, &options, file, func, line);
|
||||
}
|
||||
}
|
||||
|
||||
/* I *think* we can do without this now, if not let me know
|
||||
|
@ -218,6 +225,56 @@ SWITCH_DECLARE(switch_status_t) _switch_core_db_handle(switch_cache_db_handle_t
|
|||
return r;
|
||||
}
|
||||
|
||||
#define SWITCH_CORE_PERSIST_DB "core"
|
||||
/*!
|
||||
\brief Open the default system database
|
||||
*/
|
||||
SWITCH_DECLARE(switch_status_t) _switch_core_persist_db_handle(switch_cache_db_handle_t **dbh, const char *file, const char *func, int line)
|
||||
{
|
||||
switch_cache_db_connection_options_t options = { {0} };
|
||||
switch_status_t r;
|
||||
|
||||
if (!sql_manager.manage) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if (zstr(runtime.odbc_dsn)) {
|
||||
if (switch_test_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ)) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if (runtime.dbname) {
|
||||
options.core_db_options.db_path = runtime.dbname;
|
||||
} else {
|
||||
options.core_db_options.db_path = SWITCH_CORE_PERSIST_DB;
|
||||
}
|
||||
r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_CORE_DB, &options, file, func, line);
|
||||
|
||||
} else {
|
||||
char *dsn;
|
||||
if ((dsn = strstr(runtime.odbc_dsn, "pgsql;")) != NULL) {
|
||||
options.pgsql_options.dsn = (char*)(dsn + 6);
|
||||
|
||||
r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_PGSQL, &options, file, func, line);
|
||||
} else {
|
||||
options.odbc_options.dsn = runtime.odbc_dsn;
|
||||
options.odbc_options.user = runtime.odbc_user;
|
||||
options.odbc_options.pass = runtime.odbc_pass;
|
||||
|
||||
r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_ODBC, &options, file, func, line);
|
||||
}
|
||||
}
|
||||
|
||||
/* I *think* we can do without this now, if not let me know
|
||||
if (r == SWITCH_STATUS_SUCCESS && !(*dbh)->io_mutex) {
|
||||
(*dbh)->io_mutex = sql_manager.io_mutex;
|
||||
}
|
||||
*/
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
#define SWITCH_CORE_RECOVERY_DB "core_recovery"
|
||||
SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_cache_db_handle_t **dbh, const char *file, const char *func, int line)
|
||||
{
|
||||
|
@ -229,7 +286,7 @@ SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_cache_db_
|
|||
}
|
||||
|
||||
if (zstr(runtime.recovery_odbc_dsn)) {
|
||||
if (switch_test_flag((&runtime), SCF_CORE_ODBC_REQ)) {
|
||||
if (switch_test_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ)) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
|
@ -241,11 +298,18 @@ SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_cache_db_
|
|||
r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_CORE_DB, &options, file, func, line);
|
||||
|
||||
} else {
|
||||
options.odbc_options.dsn = runtime.recovery_odbc_dsn;
|
||||
options.odbc_options.user = runtime.recovery_odbc_user;
|
||||
options.odbc_options.pass = runtime.recovery_odbc_pass;
|
||||
char *dsn;
|
||||
if ((dsn = strstr(runtime.recovery_odbc_dsn, "pgsql;")) != NULL) {
|
||||
options.pgsql_options.dsn = (char*)(dsn + 6);
|
||||
|
||||
r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_ODBC, &options, file, func, line);
|
||||
r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_PGSQL, &options, file, func, line);
|
||||
} else {
|
||||
options.odbc_options.dsn = runtime.recovery_odbc_dsn;
|
||||
options.odbc_options.user = runtime.recovery_odbc_user;
|
||||
options.odbc_options.pass = runtime.recovery_odbc_pass;
|
||||
|
||||
r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_ODBC, &options, file, func, line);
|
||||
}
|
||||
}
|
||||
|
||||
/* I *think* we can do without this now, if not let me know
|
||||
|
@ -286,6 +350,11 @@ static void sql_close(time_t prune)
|
|||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Dropping idle DB connection %s\n", dbh->name);
|
||||
|
||||
switch (dbh->type) {
|
||||
case SCDB_TYPE_PGSQL:
|
||||
{
|
||||
switch_pgsql_handle_destroy(&dbh->native_handle.pgsql_dbh);
|
||||
}
|
||||
break;
|
||||
case SCDB_TYPE_ODBC:
|
||||
{
|
||||
switch_odbc_handle_destroy(&dbh->native_handle.odbc_dbh);
|
||||
|
@ -373,8 +442,8 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h
|
|||
uint32_t yield_len = 100000, total_yield = 0;
|
||||
|
||||
const char *db_name = NULL;
|
||||
const char *db_user = NULL;
|
||||
const char *db_pass = NULL;
|
||||
const char *odbc_user = NULL;
|
||||
const char *odbc_pass = NULL;
|
||||
|
||||
while(runtime.max_db_handles && sql_manager.total_handles >= runtime.max_db_handles && sql_manager.total_used_handles >= sql_manager.total_handles) {
|
||||
if (!waiting++) {
|
||||
|
@ -393,18 +462,24 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h
|
|||
}
|
||||
|
||||
switch (type) {
|
||||
case SCDB_TYPE_PGSQL:
|
||||
{
|
||||
db_name = connection_options->odbc_options.dsn;
|
||||
odbc_user = NULL;
|
||||
odbc_pass = NULL;
|
||||
}
|
||||
case SCDB_TYPE_ODBC:
|
||||
{
|
||||
db_name = connection_options->odbc_options.dsn;
|
||||
db_user = connection_options->odbc_options.user;
|
||||
db_pass = connection_options->odbc_options.pass;
|
||||
odbc_user = connection_options->odbc_options.user;
|
||||
odbc_pass = connection_options->odbc_options.pass;
|
||||
}
|
||||
break;
|
||||
case SCDB_TYPE_CORE_DB:
|
||||
{
|
||||
db_name = connection_options->core_db_options.db_path;
|
||||
db_user = "";
|
||||
db_pass = "";
|
||||
odbc_user = NULL;
|
||||
odbc_pass = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -413,8 +488,11 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h
|
|||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
snprintf(db_str, sizeof(db_str) - 1, "db=\"%s\";user=\"%s\";pass=\"%s\"", db_name, db_user, db_pass);
|
||||
if (odbc_user || odbc_pass) {
|
||||
snprintf(db_str, sizeof(db_str) - 1, "db=\"%s\";user=\"%s\";pass=\"%s\"", db_name, odbc_user, odbc_pass);
|
||||
} else {
|
||||
snprintf(db_str, sizeof(db_str) - 1, "db=\"%s\"", db_name);
|
||||
}
|
||||
snprintf(db_callsite_str, sizeof(db_callsite_str) - 1, "%s:%d", file, line);
|
||||
snprintf(thread_str, sizeof(thread_str) - 1, "thread=\"%lu\"", (unsigned long) (intptr_t) self);
|
||||
|
||||
|
@ -424,8 +502,23 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h
|
|||
} else {
|
||||
switch_core_db_t *db = NULL;
|
||||
switch_odbc_handle_t *odbc_dbh = NULL;
|
||||
switch_pgsql_handle_t *pgsql_dbh = NULL;
|
||||
|
||||
switch (type) {
|
||||
case SCDB_TYPE_PGSQL:
|
||||
{
|
||||
if (!switch_pgsql_available()) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failure! PGSQL NOT AVAILABLE! Can't connect to DSN %s\n", connection_options->pgsql_options.dsn);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((pgsql_dbh = switch_pgsql_handle_new(connection_options->pgsql_options.dsn))) {
|
||||
if (switch_pgsql_handle_connect(pgsql_dbh) != SWITCH_PGSQL_SUCCESS) {
|
||||
switch_pgsql_handle_destroy(&pgsql_dbh);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SCDB_TYPE_ODBC:
|
||||
{
|
||||
|
||||
|
@ -454,8 +547,8 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h
|
|||
goto end;
|
||||
}
|
||||
|
||||
if (!db && !odbc_dbh) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failure to connect to %s %s!\n", db?"SQLITE":"ODBC", db?connection_options->core_db_options.db_path:connection_options->odbc_options.dsn);
|
||||
if (!db && !odbc_dbh && !pgsql_dbh) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failure to connect to %s %s!\n", (db ? "SQLITE" : (odbc_dbh ? "ODBC" : "PGSQL")), (db ? connection_options->core_db_options.db_path : (odbc_dbh ? connection_options->odbc_options.dsn : connection_options->pgsql_options.dsn)));
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
@ -466,8 +559,10 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h
|
|||
|
||||
if (db) {
|
||||
new_dbh->native_handle.core_db_dbh = db;
|
||||
} else {
|
||||
} else if (odbc_dbh) {
|
||||
new_dbh->native_handle.odbc_dbh = odbc_dbh;
|
||||
} else {
|
||||
new_dbh->native_handle.pgsql_dbh = pgsql_dbh;
|
||||
}
|
||||
|
||||
add_handle(new_dbh, db_str, db_callsite_str, thread_str);
|
||||
|
@ -499,6 +594,11 @@ static switch_status_t switch_cache_db_execute_sql_real(switch_cache_db_handle_t
|
|||
}
|
||||
|
||||
switch (dbh->type) {
|
||||
case SCDB_TYPE_PGSQL:
|
||||
{
|
||||
status = switch_pgsql_handle_exec(dbh->native_handle.pgsql_dbh, sql, &errmsg);
|
||||
}
|
||||
break;
|
||||
case SCDB_TYPE_ODBC:
|
||||
{
|
||||
status = switch_odbc_handle_exec(dbh->native_handle.odbc_dbh, sql, NULL, &errmsg);
|
||||
|
@ -650,6 +750,11 @@ SWITCH_DECLARE(int) switch_cache_db_affected_rows(switch_cache_db_handle_t *dbh)
|
|||
return switch_odbc_handle_affected_rows(dbh->native_handle.odbc_dbh);
|
||||
}
|
||||
break;
|
||||
case SCDB_TYPE_PGSQL:
|
||||
{
|
||||
return switch_pgsql_handle_affected_rows(dbh->native_handle.pgsql_dbh);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -707,6 +812,11 @@ SWITCH_DECLARE(char *) switch_cache_db_execute_sql2str(switch_cache_db_handle_t
|
|||
status = switch_odbc_handle_exec_string(dbh->native_handle.odbc_dbh, sql, str, len, err);
|
||||
}
|
||||
break;
|
||||
case SCDB_TYPE_PGSQL:
|
||||
{
|
||||
status = switch_pgsql_handle_exec_string(dbh->native_handle.pgsql_dbh, sql, str, len, err);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
end:
|
||||
|
@ -784,16 +894,34 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute_trans(switch_
|
|||
while (begin_retries > 0) {
|
||||
again = 0;
|
||||
|
||||
if (runtime.odbc_dbtype == DBTYPE_DEFAULT) {
|
||||
switch_cache_db_execute_sql_real(dbh, "BEGIN", &errmsg);
|
||||
} else {
|
||||
switch_odbc_status_t result;
|
||||
|
||||
if ((result = switch_odbc_SQLSetAutoCommitAttr(dbh->native_handle.odbc_dbh, 0)) != SWITCH_ODBC_SUCCESS) {
|
||||
char tmp[100];
|
||||
switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to Set AutoCommit Off", result);
|
||||
errmsg = strdup(tmp);
|
||||
switch(dbh->type) {
|
||||
case SCDB_TYPE_CORE_DB:
|
||||
{
|
||||
switch_cache_db_execute_sql_real(dbh, "BEGIN", &errmsg);
|
||||
}
|
||||
break;
|
||||
case SCDB_TYPE_ODBC:
|
||||
{
|
||||
switch_odbc_status_t result;
|
||||
|
||||
if ((result = switch_odbc_SQLSetAutoCommitAttr(dbh->native_handle.odbc_dbh, 0)) != SWITCH_ODBC_SUCCESS) {
|
||||
char tmp[100];
|
||||
switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to Set AutoCommit Off", result);
|
||||
errmsg = strdup(tmp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SCDB_TYPE_PGSQL:
|
||||
{
|
||||
switch_pgsql_status_t result;
|
||||
|
||||
if ((result = switch_pgsql_SQLSetAutoCommitAttr(dbh->native_handle.pgsql_dbh, 0)) != SWITCH_PGSQL_SUCCESS) {
|
||||
char tmp[100];
|
||||
switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to Set AutoCommit Off", result);
|
||||
errmsg = strdup(tmp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (errmsg) {
|
||||
|
@ -807,11 +935,25 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute_trans(switch_
|
|||
errmsg = NULL;
|
||||
|
||||
if (again) {
|
||||
if (runtime.odbc_dbtype == DBTYPE_DEFAULT) {
|
||||
switch_cache_db_execute_sql_real(dbh, "COMMIT", NULL);
|
||||
} else {
|
||||
switch_odbc_SQLEndTran(dbh->native_handle.odbc_dbh, 1);
|
||||
switch_odbc_SQLSetAutoCommitAttr(dbh->native_handle.odbc_dbh, 1);
|
||||
switch(dbh->type) {
|
||||
case SCDB_TYPE_CORE_DB:
|
||||
{
|
||||
switch_cache_db_execute_sql_real(dbh, "COMMIT", NULL);
|
||||
}
|
||||
break;
|
||||
case SCDB_TYPE_ODBC:
|
||||
{
|
||||
switch_odbc_SQLEndTran(dbh->native_handle.odbc_dbh, 1);
|
||||
switch_odbc_SQLSetAutoCommitAttr(dbh->native_handle.odbc_dbh, 1);
|
||||
}
|
||||
break;
|
||||
case SCDB_TYPE_PGSQL:
|
||||
{
|
||||
switch_pgsql_SQLEndTran(dbh->native_handle.pgsql_dbh, 1);
|
||||
switch_pgsql_SQLSetAutoCommitAttr(dbh->native_handle.pgsql_dbh, 1);
|
||||
switch_pgsql_finish_results(dbh->native_handle.pgsql_dbh);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
goto again;
|
||||
|
@ -868,11 +1010,25 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute_trans(switch_
|
|||
|
||||
done:
|
||||
|
||||
if (runtime.odbc_dbtype == DBTYPE_DEFAULT) {
|
||||
switch_cache_db_execute_sql_real(dbh, "COMMIT", NULL);
|
||||
} else {
|
||||
switch_odbc_SQLEndTran(dbh->native_handle.odbc_dbh, 1);
|
||||
switch_odbc_SQLSetAutoCommitAttr(dbh->native_handle.odbc_dbh, 1);
|
||||
switch(dbh->type) {
|
||||
case SCDB_TYPE_CORE_DB:
|
||||
{
|
||||
switch_cache_db_execute_sql_real(dbh, "COMMIT", NULL);
|
||||
}
|
||||
break;
|
||||
case SCDB_TYPE_ODBC:
|
||||
{
|
||||
switch_odbc_SQLEndTran(dbh->native_handle.odbc_dbh, 1);
|
||||
switch_odbc_SQLSetAutoCommitAttr(dbh->native_handle.odbc_dbh, 1);
|
||||
}
|
||||
break;
|
||||
case SCDB_TYPE_PGSQL:
|
||||
{
|
||||
switch_pgsql_SQLEndTran(dbh->native_handle.pgsql_dbh, 1);
|
||||
switch_pgsql_SQLSetAutoCommitAttr(dbh->native_handle.pgsql_dbh, 1);
|
||||
switch_pgsql_finish_results(dbh->native_handle.pgsql_dbh);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!zstr(runtime.core_db_post_trans_execute)) {
|
||||
|
@ -903,6 +1059,11 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_execute_sql_callback(switch_cach
|
|||
|
||||
|
||||
switch (dbh->type) {
|
||||
case SCDB_TYPE_PGSQL:
|
||||
{
|
||||
status = switch_pgsql_handle_callback_exec(dbh->native_handle.pgsql_dbh, sql, callback, pdata, err);
|
||||
}
|
||||
break;
|
||||
case SCDB_TYPE_ODBC:
|
||||
{
|
||||
status = switch_odbc_handle_callback_exec(dbh->native_handle.odbc_dbh, sql, callback, pdata, err);
|
||||
|
@ -951,6 +1112,17 @@ SWITCH_DECLARE(switch_bool_t) switch_cache_db_test_reactive(switch_cache_db_hand
|
|||
if (io_mutex) switch_mutex_lock(io_mutex);
|
||||
|
||||
switch (dbh->type) {
|
||||
case SCDB_TYPE_PGSQL:
|
||||
{
|
||||
if (switch_pgsql_handle_exec(dbh->native_handle.pgsql_dbh, test_sql, NULL) != SWITCH_PGSQL_SUCCESS) {
|
||||
r = SWITCH_FALSE;
|
||||
if (drop_sql) {
|
||||
switch_pgsql_handle_exec(dbh->native_handle.pgsql_dbh, drop_sql, NULL);
|
||||
}
|
||||
switch_pgsql_handle_exec(dbh->native_handle.pgsql_dbh, reactive_sql, NULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SCDB_TYPE_ODBC:
|
||||
{
|
||||
if (switch_odbc_handle_exec(dbh->native_handle.odbc_dbh, test_sql, NULL, NULL) != SWITCH_ODBC_SUCCESS) {
|
||||
|
@ -1057,6 +1229,8 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread,
|
|||
switch_mutex_lock(sql_manager.cond_mutex);
|
||||
|
||||
switch (sql_manager.event_db->type) {
|
||||
case SCDB_TYPE_PGSQL:
|
||||
break;
|
||||
case SCDB_TYPE_ODBC:
|
||||
break;
|
||||
case SCDB_TYPE_CORE_DB:
|
||||
|
@ -2313,7 +2487,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_
|
|||
if (switch_core_db_handle(&sql_manager.dbh) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n");
|
||||
|
||||
if (switch_test_flag((&runtime), SCF_CORE_ODBC_REQ)) {
|
||||
if (switch_test_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failure! ODBC IS REQUIRED!\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
@ -2336,6 +2510,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_
|
|||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Opening DB\n");
|
||||
|
||||
switch (sql_manager.dbh->type) {
|
||||
case SCDB_TYPE_PGSQL:
|
||||
case SCDB_TYPE_ODBC:
|
||||
if (switch_test_flag((&runtime), SCF_CLEAR_SQL)) {
|
||||
char sql[512] = "";
|
||||
|
@ -2376,6 +2551,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_
|
|||
|
||||
|
||||
switch (sql_manager.dbh->type) {
|
||||
case SCDB_TYPE_PGSQL:
|
||||
case SCDB_TYPE_ODBC:
|
||||
{
|
||||
char *err;
|
||||
|
@ -2405,7 +2581,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_
|
|||
runtime.odbc_dsn = NULL;
|
||||
runtime.odbc_user = NULL;
|
||||
runtime.odbc_pass = NULL;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Transactions not supported on your DB, disabling ODBC\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Transactions not supported on your DB, disabling non-SQLite support; using SQLite\n");
|
||||
switch_cache_db_release_db_handle(&sql_manager.dbh);
|
||||
free(err);
|
||||
goto top;
|
||||
|
@ -2536,9 +2712,9 @@ SWITCH_DECLARE(void) switch_core_sqldb_start_thread(void)
|
|||
if (switch_core_recovery_db_handle(&dbh) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n");
|
||||
|
||||
if (switch_test_flag((&runtime), SCF_CORE_ODBC_REQ)) {
|
||||
if (switch_test_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ)) {
|
||||
int arg = 1;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failure! ODBC IS REQUIRED!\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failure! ODBC OR PGSQL IS REQUIRED!\n");
|
||||
switch_core_session_ctl(SCSC_SHUTDOWN_NOW, &arg);
|
||||
}
|
||||
|
||||
|
@ -2562,8 +2738,8 @@ SWITCH_DECLARE(void) switch_core_sqldb_start_thread(void)
|
|||
if (switch_core_db_handle(&sql_manager.dbh) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n");
|
||||
|
||||
if (switch_test_flag((&runtime), SCF_CORE_ODBC_REQ)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failure! ODBC IS REQUIRED!\n");
|
||||
if (switch_test_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failure! ODBC OR PGSQL IS REQUIRED!\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,770 @@
|
|||
/*
|
||||
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
* Eliot Gable <egable@gmail.com>
|
||||
*
|
||||
* switch_pgsql.c -- PGSQL Driver
|
||||
*
|
||||
*/
|
||||
|
||||
#include <switch.h>
|
||||
#include <switch_private.h>
|
||||
|
||||
#ifdef SWITCH_HAVE_PGSQL
|
||||
#include <libpq-fe.h>
|
||||
|
||||
|
||||
struct switch_pgsql_handle {
|
||||
char *dsn;
|
||||
const char *sql;
|
||||
PGconn* con;
|
||||
int sock;
|
||||
switch_pgsql_state_t state;
|
||||
int affected_rows;
|
||||
int num_retries;
|
||||
switch_bool_t auto_commit;
|
||||
switch_bool_t in_txn;
|
||||
};
|
||||
|
||||
struct switch_pgsql_result {
|
||||
PGresult *result;
|
||||
ExecStatusType status;
|
||||
char *err;
|
||||
int rows;
|
||||
int cols;
|
||||
};
|
||||
#endif
|
||||
|
||||
SWITCH_DECLARE(switch_pgsql_handle_t *) switch_pgsql_handle_new(const char *dsn)
|
||||
{
|
||||
#ifdef SWITCH_HAVE_PGSQL
|
||||
switch_pgsql_handle_t *new_handle;
|
||||
|
||||
if (!(new_handle = malloc(sizeof(*new_handle)))) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
memset(new_handle, 0, sizeof(*new_handle));
|
||||
|
||||
if (!(new_handle->dsn = strdup(dsn))) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
new_handle->sock = 0;
|
||||
new_handle->state = SWITCH_PGSQL_STATE_INIT;
|
||||
new_handle->con = NULL;
|
||||
new_handle->affected_rows = 0;
|
||||
new_handle->num_retries = DEFAULT_PGSQL_RETRIES;
|
||||
new_handle->auto_commit = SWITCH_TRUE;
|
||||
new_handle->in_txn = SWITCH_FALSE;
|
||||
|
||||
return new_handle;
|
||||
|
||||
err:
|
||||
if (new_handle) {
|
||||
switch_safe_free(new_handle->dsn);
|
||||
switch_safe_free(new_handle);
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(void) switch_pgsql_set_num_retries(switch_pgsql_handle_t *handle, int num_retries)
|
||||
{
|
||||
#ifdef SWITCH_HAVE_PGSQL
|
||||
if (handle) {
|
||||
handle->num_retries = num_retries;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_disconnect(switch_pgsql_handle_t *handle)
|
||||
{
|
||||
#ifdef SWITCH_HAVE_PGSQL
|
||||
|
||||
if (!handle) {
|
||||
return SWITCH_PGSQL_FAIL;
|
||||
}
|
||||
|
||||
if (handle->state == SWITCH_PGSQL_STATE_CONNECTED) {
|
||||
PQfinish(handle->con);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Disconnected from [%s]\n", handle->dsn);
|
||||
}
|
||||
|
||||
handle->state = SWITCH_PGSQL_STATE_DOWN;
|
||||
|
||||
return SWITCH_PGSQL_SUCCESS;
|
||||
#else
|
||||
return SWITCH_PGSQL_FAIL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef SWITCH_HAVE_PGSQL
|
||||
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_send_query(switch_pgsql_handle_t *handle, const char* sql)
|
||||
{
|
||||
char *err_str;
|
||||
|
||||
if (!PQsendQuery(handle->con, sql)) {
|
||||
err_str = switch_pgsql_handle_get_error(handle);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to send query (%s) to database: %s\n", sql, err_str);
|
||||
switch_pgsql_finish_results(handle);
|
||||
goto error;
|
||||
}
|
||||
handle->sql = sql;
|
||||
|
||||
return SWITCH_PGSQL_SUCCESS;
|
||||
error:
|
||||
return SWITCH_PGSQL_FAIL;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_cancel_real(const char *file, const char *func, int line, switch_pgsql_handle_t *handle)
|
||||
{
|
||||
char err_buf[256];
|
||||
PGcancel *cancel = NULL;
|
||||
switch_pgsql_status_t ret = SWITCH_PGSQL_SUCCESS;
|
||||
|
||||
memset(err_buf, 0, 256);
|
||||
cancel = PQgetCancel(handle->con);
|
||||
if(!PQcancel(cancel, err_buf, 256)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_CRIT, "Failed to cancel long-running query (%s): %s\n", handle->sql, err_buf);
|
||||
ret = SWITCH_PGSQL_FAIL;
|
||||
}
|
||||
PQfreeCancel(cancel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_next_result_timed(switch_pgsql_handle_t *handle, switch_pgsql_result_t **result_out, int msec)
|
||||
{
|
||||
switch_pgsql_result_t *res;
|
||||
switch_time_t start;
|
||||
switch_time_t ctime;
|
||||
unsigned int usec = msec * 1000;
|
||||
char *err_str;
|
||||
fd_set pgset;
|
||||
struct timeval timeout;
|
||||
|
||||
if(!handle) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "**BUG** Null handle passed to switch_pgsql_next_result.\n");
|
||||
return SWITCH_PGSQL_FAIL;
|
||||
}
|
||||
|
||||
/* Try to consume input that might be waiting right away */
|
||||
if (PQconsumeInput(handle->con)) {
|
||||
/* And check to see if we have a full result ready for reading */
|
||||
if (PQisBusy(handle->con)) {
|
||||
|
||||
/* Wait for a result to become available, up to msec milliseconds */
|
||||
start = switch_time_now();
|
||||
while((ctime = switch_time_now()) - start <= usec) {
|
||||
FD_ZERO(&pgset);
|
||||
FD_SET(handle->sock, &pgset);
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 500;
|
||||
|
||||
/* Wait for the PostgreSQL socket to be ready for data reads. */
|
||||
if (select(FD_SETSIZE, &pgset, NULL, NULL, &timeout) > 0) {
|
||||
/* Then try to consume any input waiting. */
|
||||
if (PQconsumeInput(handle->con)) {
|
||||
/* And check to see if we have a full result ready for reading */
|
||||
if (!PQisBusy(handle->con)) {
|
||||
/* If we can pull a full result without blocking, then break this loop */
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* If we had an error trying to consume input, report it and cancel the query. */
|
||||
err_str = switch_pgsql_handle_get_error(handle);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "An error occurred trying to consume input for query (%s): %s\n", handle->sql, err_str);
|
||||
switch_safe_free(err_str);
|
||||
switch_pgsql_cancel(handle);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we broke the loop above because of a timeout, report that and cancel the query. */
|
||||
if (ctime - start > usec) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Query (%s) took too long to complete or database not responding.\n", handle->sql);
|
||||
switch_pgsql_cancel(handle);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
} else {
|
||||
/* If we had an error trying to consume input, report it and cancel the query. */
|
||||
err_str = switch_pgsql_handle_get_error(handle);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "An error occurred trying to consume input for query (%s): %s\n", handle->sql, err_str);
|
||||
switch_safe_free(err_str);
|
||||
switch_pgsql_cancel(handle);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
/* At this point, we know we can read a full result without blocking. */
|
||||
if(!(res = malloc(sizeof(switch_pgsql_result_t)))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Malloc failed!\n");
|
||||
goto error;
|
||||
}
|
||||
memset(res, 0, sizeof(switch_pgsql_result_t));
|
||||
|
||||
|
||||
res->result = PQgetResult(handle->con);
|
||||
if (res->result) {
|
||||
*result_out = res;
|
||||
res->status = PQresultStatus(res->result);
|
||||
switch(res->status) {
|
||||
case PGRES_TUPLES_OK:
|
||||
{
|
||||
res->rows = PQntuples(res->result);
|
||||
handle->affected_rows = res->rows;
|
||||
res->cols = PQnfields(res->result);
|
||||
}
|
||||
break;
|
||||
case PGRES_COPY_OUT:
|
||||
case PGRES_COPY_IN:
|
||||
case PGRES_COMMAND_OK:
|
||||
break;
|
||||
case PGRES_EMPTY_QUERY:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Query (%s) returned PGRES_EMPTY_QUERY\n", handle->sql);
|
||||
case PGRES_BAD_RESPONSE:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Query (%s) returned PGRES_BAD_RESPONSE\n", handle->sql);
|
||||
case PGRES_NONFATAL_ERROR:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Query (%s) returned PGRES_NONFATAL_ERROR\n", handle->sql);
|
||||
case PGRES_FATAL_ERROR:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Query (%s) returned PGRES_FATAL_ERROR\n", handle->sql);
|
||||
res->err = PQresultErrorMessage(res->result);
|
||||
goto error;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
free(res);
|
||||
res = NULL;
|
||||
*result_out = NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
return SWITCH_PGSQL_SUCCESS;
|
||||
error:
|
||||
return SWITCH_PGSQL_FAIL;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(void) switch_pgsql_free_result(switch_pgsql_result_t **result)
|
||||
{
|
||||
if (!*result) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((*result)->result) {
|
||||
PQclear((*result)->result);
|
||||
}
|
||||
free(*result);
|
||||
*result = NULL;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_finish_results_real(const char* file, const char* func, int line, switch_pgsql_handle_t *handle)
|
||||
{
|
||||
switch_pgsql_result_t *res = NULL;
|
||||
switch_pgsql_status_t final_status = SWITCH_PGSQL_SUCCESS;
|
||||
int done = 0;
|
||||
do {
|
||||
switch_pgsql_next_result(handle, &res);
|
||||
if (res && res->err) {
|
||||
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "Error executing query:\n%s\n", res->err);
|
||||
final_status = SWITCH_PGSQL_FAIL;
|
||||
}
|
||||
if (!res) done = 1;
|
||||
switch_pgsql_free_result(&res);
|
||||
} while (!done);
|
||||
return final_status;
|
||||
}
|
||||
|
||||
static int db_is_up(switch_pgsql_handle_t *handle)
|
||||
{
|
||||
int ret = 0;
|
||||
switch_event_t *event;
|
||||
char *err_str = NULL;
|
||||
int max_tries = DEFAULT_PGSQL_RETRIES;
|
||||
int code = 0, recon = 0;
|
||||
|
||||
if (handle) {
|
||||
max_tries = handle->num_retries;
|
||||
if (max_tries < 1)
|
||||
max_tries = DEFAULT_PGSQL_RETRIES;
|
||||
}
|
||||
|
||||
top:
|
||||
|
||||
if (!handle) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No DB Handle\n");
|
||||
goto done;
|
||||
}
|
||||
if (!handle->con) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No DB Connection\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (PQstatus(handle->con) == CONNECTION_BAD) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "PQstatus returned bad connection; reconnecting...\n");
|
||||
handle->state = SWITCH_PGSQL_STATE_ERROR;
|
||||
PQreset(handle->con);
|
||||
if (PQstatus(handle->con) == CONNECTION_BAD) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "PQstatus returned bad connection -- reconnection failed!\n");
|
||||
goto error;
|
||||
}
|
||||
handle->state = SWITCH_PGSQL_STATE_CONNECTED;
|
||||
}
|
||||
|
||||
/* if (!PQsendQuery(handle->con, "SELECT 1")) {
|
||||
code = __LINE__;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(switch_pgsql_next_result(handle, &result) == SWITCH_PGSQL_FAIL) {
|
||||
code = __LINE__;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!result || result->status != PGRES_COMMAND_OK) {
|
||||
code = __LINE__;
|
||||
goto error;
|
||||
}
|
||||
|
||||
switch_pgsql_free_result(&result);
|
||||
switch_pgsql_finish_results(handle);
|
||||
*/
|
||||
ret = 1;
|
||||
goto done;
|
||||
|
||||
error:
|
||||
err_str = switch_pgsql_handle_get_error(handle);
|
||||
|
||||
if (PQstatus(handle->con) == CONNECTION_BAD) {
|
||||
handle->state = SWITCH_PGSQL_STATE_ERROR;
|
||||
PQreset(handle->con);
|
||||
if (PQstatus(handle->con) == CONNECTION_OK) {
|
||||
handle->state = SWITCH_PGSQL_STATE_CONNECTED;
|
||||
recon = SWITCH_PGSQL_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
max_tries--;
|
||||
|
||||
if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Failure-Message", "The sql server is not responding for DSN %s [%s][%d]",
|
||||
switch_str_nil(handle->dsn), switch_str_nil(err_str), code);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "The sql server is not responding for DSN %s [%s][%d]\n",
|
||||
switch_str_nil(handle->dsn), switch_str_nil(err_str), code);
|
||||
|
||||
if (recon == SWITCH_PGSQL_SUCCESS) {
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "The connection has been re-established");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "The connection has been re-established\n");
|
||||
} else {
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "The connection could not be re-established");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "The connection could not be re-established\n");
|
||||
}
|
||||
if (!max_tries) {
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "Giving up!");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Giving up!\n");
|
||||
}
|
||||
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
|
||||
if (!max_tries) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch_safe_free(err_str);
|
||||
switch_yield(1000000);
|
||||
goto top;
|
||||
|
||||
done:
|
||||
|
||||
switch_safe_free(err_str);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_connect(switch_pgsql_handle_t *handle)
|
||||
{
|
||||
#ifdef SWITCH_HAVE_PGSQL
|
||||
if (handle->state == SWITCH_PGSQL_STATE_CONNECTED) {
|
||||
switch_pgsql_handle_disconnect(handle);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Re-connecting %s\n", handle->dsn);
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Connecting %s\n", handle->dsn);
|
||||
|
||||
handle->con = PQconnectdb(handle->dsn);
|
||||
if (PQstatus(handle->con) != CONNECTION_OK) {
|
||||
char *err_str;
|
||||
if ((err_str = switch_pgsql_handle_get_error(handle))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", err_str);
|
||||
switch_safe_free(err_str);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to connect to the database [%s]\n", handle->dsn);
|
||||
switch_pgsql_handle_disconnect(handle);
|
||||
}
|
||||
return SWITCH_PGSQL_FAIL;
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Connected to [%s]\n", handle->dsn);
|
||||
handle->state = SWITCH_PGSQL_STATE_CONNECTED;
|
||||
handle->sock = PQsocket(handle->con);
|
||||
return SWITCH_PGSQL_SUCCESS;
|
||||
#else
|
||||
return SWITCH_PGSQL_FAIL;
|
||||
#endif
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_string(switch_pgsql_handle_t *handle, const char *sql, char *resbuf, size_t len, char **err)
|
||||
{
|
||||
#ifdef SWITCH_HAVE_PGSQL
|
||||
switch_pgsql_status_t sstatus = SWITCH_PGSQL_SUCCESS;
|
||||
char *val = NULL;
|
||||
switch_pgsql_result_t *result = NULL;
|
||||
|
||||
handle->affected_rows = 0;
|
||||
|
||||
if (switch_pgsql_handle_exec_base(handle, sql, err) == SWITCH_PGSQL_FAIL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(switch_pgsql_next_result(handle, &result) == SWITCH_PGSQL_FAIL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!result || result->status != PGRES_COMMAND_OK) {
|
||||
sstatus = SWITCH_PGSQL_FAIL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (handle->affected_rows <= 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
val = PQgetvalue(result->result, 0, 0);
|
||||
strncpy(resbuf, val, len);
|
||||
|
||||
done:
|
||||
|
||||
switch_pgsql_free_result(&result);
|
||||
if (switch_pgsql_finish_results(handle) != SWITCH_PGSQL_SUCCESS) {
|
||||
sstatus = SWITCH_PGSQL_FAIL;
|
||||
}
|
||||
|
||||
return sstatus;
|
||||
error:
|
||||
return SWITCH_PGSQL_FAIL;
|
||||
#else
|
||||
return SWITCH_PGSQL_FAIL;
|
||||
#endif
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_base(switch_pgsql_handle_t *handle, const char *sql, char **err)
|
||||
{
|
||||
#ifdef SWITCH_HAVE_PGSQL
|
||||
char *err_str = NULL;
|
||||
|
||||
handle->affected_rows = 0;
|
||||
|
||||
if (!db_is_up(handle)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database is not up!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (handle->auto_commit == SWITCH_FALSE && handle->in_txn == SWITCH_FALSE) {
|
||||
if (switch_pgsql_send_query(handle, "BEGIN") != SWITCH_PGSQL_SUCCESS) {
|
||||
switch_pgsql_finish_results(handle);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error sending BEGIN!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (switch_pgsql_finish_results(handle) != SWITCH_PGSQL_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error sending BEGIN!\n");
|
||||
goto error;
|
||||
}
|
||||
handle->in_txn = SWITCH_TRUE;
|
||||
}
|
||||
|
||||
if (switch_pgsql_send_query(handle, sql) != SWITCH_PGSQL_SUCCESS) {
|
||||
switch_pgsql_finish_results(handle);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error sending query!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
return SWITCH_PGSQL_SUCCESS;
|
||||
|
||||
error:
|
||||
err_str = switch_pgsql_handle_get_error(handle);
|
||||
|
||||
if (zstr(err_str)) {
|
||||
err_str = strdup((char *)"SQL ERROR!");
|
||||
}
|
||||
|
||||
if (err_str) {
|
||||
if (!switch_stristr("already exists", err_str) && !switch_stristr("duplicate key name", err_str)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str));
|
||||
}
|
||||
if (err) {
|
||||
*err = err_str;
|
||||
} else {
|
||||
free(err_str);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return SWITCH_PGSQL_FAIL;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec(switch_pgsql_handle_t *handle, const char *sql, char **err)
|
||||
{
|
||||
#ifdef SWITCH_HAVE_PGSQL
|
||||
if (switch_pgsql_handle_exec_base(handle, sql, err) == SWITCH_PGSQL_FAIL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return switch_pgsql_finish_results(handle);
|
||||
error:
|
||||
#endif
|
||||
return SWITCH_PGSQL_FAIL;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_callback_exec_detailed(const char *file, const char *func, int line,
|
||||
switch_pgsql_handle_t *handle,
|
||||
const char *sql, switch_core_db_callback_func_t callback, void *pdata,
|
||||
char **err)
|
||||
{
|
||||
#ifdef SWITCH_HAVE_PGSQL
|
||||
char *err_str = NULL;
|
||||
int row = 0, col = 0, err_cnt = 0;
|
||||
switch_pgsql_result_t *result = NULL;
|
||||
|
||||
handle->affected_rows = 0;
|
||||
|
||||
switch_assert(callback != NULL);
|
||||
|
||||
if (switch_pgsql_handle_exec_base(handle, sql, err) == SWITCH_PGSQL_FAIL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (switch_pgsql_next_result(handle, &result) == SWITCH_PGSQL_FAIL) {
|
||||
err_cnt++;
|
||||
err_str = switch_pgsql_handle_get_error(handle);
|
||||
if (result && !zstr(result->err)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(result->err));
|
||||
}
|
||||
if (!zstr(err_str)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str));
|
||||
}
|
||||
switch_safe_free(err_str);
|
||||
err_str = NULL;
|
||||
}
|
||||
|
||||
while (result != NULL) {
|
||||
for (row = 0; row < result->rows; ++row) {
|
||||
char **names;
|
||||
char **vals;
|
||||
|
||||
names = calloc(result->cols, sizeof(*names));
|
||||
vals = calloc(result->cols, sizeof(*vals));
|
||||
|
||||
switch_assert(names && vals);
|
||||
|
||||
for (col = 0; col < result->cols; ++col) {
|
||||
char * tmp;
|
||||
int len;
|
||||
|
||||
tmp = PQfname(result->result, col);
|
||||
if (tmp) {
|
||||
len = strlen(tmp);
|
||||
names[col] = malloc(len+1);
|
||||
strncpy(names[col], tmp, len);
|
||||
|
||||
len = PQgetlength(result->result, row, col);
|
||||
vals[col] = malloc(len+1);
|
||||
tmp = PQgetvalue(result->result, row, col);
|
||||
strncpy(vals[col], tmp, len);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: Column number %d out of range\n", col);
|
||||
}
|
||||
}
|
||||
|
||||
if (callback(pdata, row, vals, names)) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (col = 0; col < result->cols; ++col) {
|
||||
free(names[col]);
|
||||
free(vals[col]);
|
||||
}
|
||||
free(names);
|
||||
free(vals);
|
||||
}
|
||||
if (switch_pgsql_next_result(handle, &result) == SWITCH_PGSQL_FAIL) {
|
||||
err_cnt++;
|
||||
err_str = switch_pgsql_handle_get_error(handle);
|
||||
if (result && !zstr(result->err)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(result->err));
|
||||
}
|
||||
if (!zstr(err_str)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str));
|
||||
}
|
||||
switch_safe_free(err_str);
|
||||
err_str = NULL;
|
||||
}
|
||||
}
|
||||
if (err_cnt) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return SWITCH_PGSQL_SUCCESS;
|
||||
error:
|
||||
#endif
|
||||
return SWITCH_PGSQL_FAIL;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(void) switch_pgsql_handle_destroy(switch_pgsql_handle_t **handlep)
|
||||
{
|
||||
#ifdef SWITCH_HAVE_PGSQL
|
||||
|
||||
switch_pgsql_handle_t *handle = NULL;
|
||||
|
||||
if (!handlep) {
|
||||
return;
|
||||
}
|
||||
handle = *handlep;
|
||||
|
||||
if (handle) {
|
||||
switch_pgsql_handle_disconnect(handle);
|
||||
|
||||
switch_safe_free(handle->dsn);
|
||||
free(handle);
|
||||
}
|
||||
*handlep = NULL;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_pgsql_state_t) switch_pgsql_handle_get_state(switch_pgsql_handle_t *handle)
|
||||
{
|
||||
#ifdef SWITCH_HAVE_PGSQL
|
||||
return handle ? handle->state : SWITCH_PGSQL_STATE_INIT;
|
||||
#else
|
||||
return SWITCH_PGSQL_STATE_ERROR;
|
||||
#endif
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(char *) switch_pgsql_handle_get_error(switch_pgsql_handle_t *handle)
|
||||
{
|
||||
#ifdef SWITCH_HAVE_PGSQL
|
||||
char * err_str;
|
||||
if (!handle) {
|
||||
return NULL;
|
||||
};
|
||||
switch_strdup(err_str, PQerrorMessage(handle->con));
|
||||
return err_str;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(int) switch_pgsql_handle_affected_rows(switch_pgsql_handle_t *handle)
|
||||
{
|
||||
#ifdef SWITCH_HAVE_PGSQL
|
||||
return handle->affected_rows;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_bool_t) switch_pgsql_available(void)
|
||||
{
|
||||
#ifdef SWITCH_HAVE_PGSQL
|
||||
return SWITCH_TRUE;
|
||||
#else
|
||||
return SWITCH_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_SQLSetAutoCommitAttr(switch_pgsql_handle_t *handle, switch_bool_t on)
|
||||
{
|
||||
#ifdef SWITCH_HAVE_PGSQL
|
||||
if (on) {
|
||||
handle->auto_commit = SWITCH_TRUE;
|
||||
} else {
|
||||
handle->auto_commit = SWITCH_FALSE;
|
||||
}
|
||||
return SWITCH_PGSQL_SUCCESS;
|
||||
#else
|
||||
return (switch_pgsql_status_t) SWITCH_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_SQLEndTran(switch_pgsql_handle_t *handle, switch_bool_t commit)
|
||||
{
|
||||
#ifdef SWITCH_HAVE_PGSQL
|
||||
char * err_str = NULL;
|
||||
if (commit) {
|
||||
if(!PQsendQuery(handle->con, "COMMIT")) {
|
||||
err_str = switch_pgsql_handle_get_error(handle);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not commit transaction: %s\n", err_str);
|
||||
switch_safe_free(err_str);
|
||||
return SWITCH_PGSQL_FAIL;
|
||||
}
|
||||
} else {
|
||||
if(!PQsendQuery(handle->con, "ROLLBACK")) {
|
||||
err_str = switch_pgsql_handle_get_error(handle);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not rollback transaction: %s\n", err_str);
|
||||
switch_safe_free(err_str);
|
||||
return SWITCH_PGSQL_FAIL;
|
||||
}
|
||||
}
|
||||
handle->in_txn = SWITCH_FALSE;
|
||||
return SWITCH_PGSQL_SUCCESS;
|
||||
#else
|
||||
return (switch_pgsql_status_t) SWITCH_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
Loading…
Reference in New Issue