<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[Freeswitch-trunk][14836] </title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<div id="header">FreeSWITCH Subversion</div>
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://fisheye.freeswitch.org/changelog/FreeSWITCH?cs=14836">14836</a></dd>
<dt>Author</dt> <dd>ledr</dd>
<dt>Date</dt> <dd>2009-09-13 06:31:05 -0500 (Sun, 13 Sep 2009)</dd>
</dl>
<h3>Log Message</h3>
<pre>Initial commit, halfway there, hope to have working version this afternoon</pre>
<h3>Added Paths</h3>
<ul>
<li>freeswitch/trunk/contrib/ledr/c/</li>
<li>freeswitch/trunk/contrib/ledr/c/mod_odbc_query/</li>
<li><a href="#freeswitchtrunkcontribledrcmod_odbc_queryMakefile">freeswitch/trunk/contrib/ledr/c/mod_odbc_query/Makefile</a></li>
<li><a href="#freeswitchtrunkcontribledrcmod_odbc_queryREADME">freeswitch/trunk/contrib/ledr/c/mod_odbc_query/README</a></li>
<li><a href="#freeswitchtrunkcontribledrcmod_odbc_querymod_odbc_queryc">freeswitch/trunk/contrib/ledr/c/mod_odbc_query/mod_odbc_query.c</a></li>
<li><a href="#freeswitchtrunkcontribledrcmod_odbc_querymod_odbc_queryconfxml">freeswitch/trunk/contrib/ledr/c/mod_odbc_query/mod_odbc_query.conf.xml</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="freeswitchtrunkcontribledrcmod_odbc_queryMakefile"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/ledr/c/mod_odbc_query/Makefile (0 => 14836)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/ledr/c/mod_odbc_query/Makefile         (rev 0)
+++ freeswitch/trunk/contrib/ledr/c/mod_odbc_query/Makefile        2009-09-13 11:31:05 UTC (rev 14836)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+BASE=/usr/src/freeswitch/trunk
+include $(BASE)/build/modmake.rules
</ins></span></pre></div>
<a id="freeswitchtrunkcontribledrcmod_odbc_queryREADME"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/ledr/c/mod_odbc_query/README (0 => 14836)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/ledr/c/mod_odbc_query/README         (rev 0)
+++ freeswitch/trunk/contrib/ledr/c/mod_odbc_query/README        2009-09-13 11:31:05 UTC (rev 14836)
</span><span class="lines">@@ -0,0 +1,66 @@
</span><ins>+mod_odbc_query readme
+
+by: Leon de Rooij <leon@toyos.nl>
+
+This module can be used for doing odbc queries from the dialplan.
+
+Usage:
+
+<application name="odbc_query" value="SELECT some_column_name AS target_channel_variable_name FROM some_table_name WHERE 1;"/>
+
+or:
+
+<application name="odbc_query" value="my-query"/>
+
+The module simply checks whether the value contains a space. If it does, then the value will be seen as an SQL query, otherwise it will be seen as a query 'name' that then has to be defined in the modules configuration in the <queries> section like this:
+
+<queries>
+ <query name="my-query" value="SELECT some_column_name AS target_channel_variable_name FROM some_table_name WHERE 1;"/>
+</queries>
+
+The module will do the query and store each returned column name as channel variable name together with its corresponding value.
+
+Another feature is, that if only two columns are returned, which have the column names "name" and "value", then the channel variables will be set according to them. This way you can have the query return multiple rows with different channel variables. If the query returns something else than column-names "name" and "value" and it returns multiple rows, then the channel variables will be overwritten with each iteration of the rows - which is probably useless.
+
+The query may contain ${blah} variables that will be expanded from channel variables before the query is performed.
+
+
+For example:
+
+query: "SELECT foo, bar FROM huk WHERE tilde='kek';"
+
+returns:
+
+foo bar
+----------
+a b
+c d
+
+then the channel variables that will be set are:
+
+foo=c
+bar=d
+
+---
+
+
+query: "SELECT foo AS name, bar AS value FROM huk WHERE tilde='kek';"
+
+returns:
+
+name value
+------------
+a b
+c d
+
+then the channel variables that will be set are:
+
+a=b
+c=d
+
+---
+
+
+So, the first example should only be used when you know that only zero or one row will be returned, and second one if you know zero or more rows will be returned.
+
+If zero rows are returned (in either foo/bar or name/value case) then no channel variables will be set, overwritten or deleted.
</ins></span></pre></div>
<a id="freeswitchtrunkcontribledrcmod_odbc_querymod_odbc_queryc"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/ledr/c/mod_odbc_query/mod_odbc_query.c (0 => 14836)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/ledr/c/mod_odbc_query/mod_odbc_query.c         (rev 0)
+++ freeswitch/trunk/contrib/ledr/c/mod_odbc_query/mod_odbc_query.c        2009-09-13 11:31:05 UTC (rev 14836)
</span><span class="lines">@@ -0,0 +1,158 @@
</span><ins>+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2009, 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):
+ *
+ * Leon de Rooij <leon@toyos.nl>
+ *
+ *
+ * mod_odbc_query.c -- ODBC Query
+ *
+ * Do ODBC queries from the dialplan and store all returned values as channel variables.
+ *
+ */
+#include <switch.h>
+
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_odbc_query_shutdown);
+SWITCH_MODULE_LOAD_FUNCTION(mod_odbc_query_load);
+SWITCH_MODULE_DEFINITION(mod_odbc_query, mod_odbc_query_load, mod_odbc_query_shutdown, NULL);
+
+static struct {
+        switch_odbc_handle_t *master_odbc;
+} globals;
+
+static char* switch_channel_expand_variables_by_pool(switch_memory_pool_t *pool, switch_channel_t *channel, const char *in)
+{
+        char *tmp, *out;
+
+        tmp = switch_channel_expand_variables(channel, in);
+        out = switch_core_strdup(pool, tmp);
+        if (tmp != in) switch_safe_free(tmp);
+
+        return out;
+}
+
+static switch_xml_config_item_t instructions[] = {
+        /* parameter name, type, reloadable, pointer, default value, options structure */
+ SWITCH_CONFIG_ITEM_END()
+};
+
+static switch_status_t do_config(switch_bool_t reload)
+{
+        memset(&globals, 0, sizeof(globals));
+
+        if (switch_xml_config_parse_module_settings("odbc_query.conf", reload, instructions) != SWITCH_STATUS_SUCCESS) {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not open odbc_query.conf\n");
+                return SWITCH_STATUS_FALSE;
+        }
+        
+        return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_STANDARD_API(odbc_query_function)
+{
+        do_config(SWITCH_TRUE);
+        
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static int odbc_query_callback(void *pArg, int argc, char **argv, char **columnName)
+{
+        switch_channel_t *channel = (switch_channel_t *) pArg;
+
+ if ((argc == 2) && (!strcmp(columnName[0], "name")) && (!strcmp(columnName[1], "value"))) {
+                switch_channel_set_variable(channel, argv[0], argv[1]);
+        } else {
+                for (int i = 0; i < argc; i++) {
+                        switch_channel_set_variable(channel, columnName[i], argv[i]);
+                }
+        }
+
+        return 0;
+}
+
+SWITCH_STANDARD_APP(odbc_query_app_function)
+{
+        char *query = NULL;
+        char *expanded_query = NULL;
+        switch_channel_t *channel = switch_core_session_get_channel(session);
+        switch_memory_pool_t *pool = switch_core_session_get_pool(session);
+
+        if (!channel) {
+                return;
+        }
+
+        /* get query from data if it contains space, otherwise get it from <queries> section in configuration */
+        if (strchr(data, ' ')) {
+                query = switch_core_session_strdup(session, data);
+        } else {
+        }
+
+        expanded_query = switch_channel_expand_variables_by_pool(pool, channel, query);
+
+        if (switch_odbc_handle_callback_exec(globals.master_odbc, expanded_query, odbc_query_callback, channel) != SWITCH_ODBC_SUCCESS) {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error running this query: [%s]\n", expanded_query);
+        }
+}
+
+/* Macro expands to: switch_status_t mod_odbc_query_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */
+SWITCH_MODULE_LOAD_FUNCTION(mod_odbc_query_load)
+{
+        switch_api_interface_t *api_interface;
+        switch_application_interface_t *app_interface;
+
+        /* connect my internal structure to the blank pointer passed to me */
+        *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Hello World!\n");
+        
+        do_config(SWITCH_FALSE);
+        
+        SWITCH_ADD_API(api_interface, "odbc_query", "ODBC Query API", odbc_query_function, "syntax");
+        SWITCH_ADD_APP(app_interface, "odbc_query", "Perform an ODBC query", "Perform an ODBC query", odbc_query_app_function, "<query>", SAF_SUPPORT_NOMEDIA);
+
+        /* indicate that the module should continue to be loaded */
+        return SWITCH_STATUS_SUCCESS;
+}
+
+/*
+ Called when the system shuts down
+ Macro expands to: switch_status_t mod_odbc_query_shutdown() */
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_odbc_query_shutdown)
+{
+        /* Cleanup dynamically allocated config settings */
+        switch_xml_config_cleanup(instructions);
+        return SWITCH_STATUS_SUCCESS;
+}
+
+
+/* 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
+ */
</ins></span></pre></div>
<a id="freeswitchtrunkcontribledrcmod_odbc_querymod_odbc_queryconfxml"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/ledr/c/mod_odbc_query/mod_odbc_query.conf.xml (0 => 14836)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/ledr/c/mod_odbc_query/mod_odbc_query.conf.xml         (rev 0)
+++ freeswitch/trunk/contrib/ledr/c/mod_odbc_query/mod_odbc_query.conf.xml        2009-09-13 11:31:05 UTC (rev 14836)
</span><span class="lines">@@ -0,0 +1,21 @@
</span><ins>+<configuration name="odbc_query.conf" description="ODBC Query Module">
+
+ <settings>
+ <param name="odbc-dsn" value="freeswitch:freeswitch:secret"/>
+ </settings>
+
+ <queries>
+ <!-- the ${foo} variable will be expanded from channel variables at query time -->
+ <query name="map-did-users" data="
+ SELECT
+ dir_users.username AS dest_user,
+ dir_domains.name AS dest_domain
+ FROM
+ map_did_users, dir_domains, dir_users
+ WHERE
+ map_did_users.did='${destination_number}' AND
+ dir_users.id = map_did_users.user_id AND
+ dir_domains.id = dir_users.dir_domain_id;"/>
+ </queries>
+
+</configuration>
</ins></span></pre>
</div>
</div>
<div id="footer">See you at ClueCon</div>
</body>
</html>