* src/odbc/odbc_queries.erl: Support for Microsoft SQL Server as

a database backend (via ODBC).
* src/odbc/ejabberd_odbc.erl: Likewise.
* src/odbc/mssql.sql: Likewise.
* src/odbc/Makefile.in: Likewise.
* src/ejabberd_auth_odbc.erl: Likewise.
* src/mod_offline_odbc.erl: Likewise.
* src/mod_roster_odbc.erl: Likewise.
* src/mod_last_odbc.erl: Likewise.
* src/configure.ac: Likewise
* doc/guide.tex: Likewise.
* doc/introduction.tex: Likewise.
* src/odbc/pg.sql: Minor fix.

SVN Revision: 598
This commit is contained in:
Mickaël Rémond 2006-09-03 15:15:46 +00:00
parent 40c8c8b559
commit d0e2ac9ed2
18 changed files with 3892 additions and 1992 deletions

View File

@ -1,3 +1,19 @@
2006-09-03 Mickael Remond <mickael.remond@process-one.net>
* src/odbc/odbc_queries.erl: Support for Microsoft SQL Server as a
database backend (via ODBC).
* src/odbc/ejabberd_odbc.erl: Likewise.
* src/odbc/mssql.sql: Likewise.
* src/odbc/Makefile.in: Likewise.
* src/ejabberd_auth_odbc.erl: Likewise.
* src/mod_offline_odbc.erl: Likewise.
* src/mod_roster_odbc.erl: Likewise.
* src/mod_last_odbc.erl: Likewise.
* src/configure.ac: Likewise
* doc/guide.tex: Likewise.
* doc/introduction.tex: Likewise.
* src/odbc/pg.sql: Minor fix.
2006-08-28 Mickael Remond <mickael.remond@process-one.net>
* Makefile.in: Fix for MacOSX compilation.

View File

@ -153,6 +153,7 @@ Native MySQL support.
<LI CLASS="li-itemize">Native PostgreSQL support.
<LI CLASS="li-itemize">Mnesia.
<LI CLASS="li-itemize">ODBC data storage support.
<LI CLASS="li-itemize">Microsoft SQL Server support (via ODBC).
</UL>
<LI CLASS="li-itemize">Authentication
<UL CLASS="itemize"><LI CLASS="li-itemize">

View File

@ -92,68 +92,69 @@ BLOCKQUOTE{margin-left:4ex;margin-right:4ex;text-align:left;}
</UL>
<LI CLASS="li-toc"><A HREF="#htoc24">3.2&nbsp;&nbsp;Relational Database Support</A>
<UL CLASS="toc"><LI CLASS="li-toc">
<A HREF="#htoc25">3.2.1&nbsp;&nbsp;Authentication against a relational database</A>
<LI CLASS="li-toc"><A HREF="#htoc26">3.2.2&nbsp;&nbsp;Relational database for other modules</A>
<A HREF="#htoc25">3.2.1&nbsp;&nbsp;Preliminary steps</A>
<LI CLASS="li-toc"><A HREF="#htoc26">3.2.2&nbsp;&nbsp;Authentication against a relational database</A>
<LI CLASS="li-toc"><A HREF="#htoc27">3.2.3&nbsp;&nbsp;Relational database for other modules</A>
</UL>
<LI CLASS="li-toc"><A HREF="#htoc27">3.3&nbsp;&nbsp;Creating an Initial Administrator</A>
<LI CLASS="li-toc"><A HREF="#htoc28">3.4&nbsp;&nbsp;Online Configuration and Monitoring</A>
<LI CLASS="li-toc"><A HREF="#htoc28">3.3&nbsp;&nbsp;Creating an Initial Administrator</A>
<LI CLASS="li-toc"><A HREF="#htoc29">3.4&nbsp;&nbsp;Online Configuration and Monitoring</A>
<UL CLASS="toc"><LI CLASS="li-toc">
<A HREF="#htoc29">3.4.1&nbsp;&nbsp;Web Interface</A>
<LI CLASS="li-toc"><A HREF="#htoc30">3.4.2&nbsp;&nbsp;<TT>ejabberdctl</TT></A>
<A HREF="#htoc30">3.4.1&nbsp;&nbsp;Web Interface</A>
<LI CLASS="li-toc"><A HREF="#htoc31">3.4.2&nbsp;&nbsp;<TT>ejabberdctl</TT></A>
</UL>
</UL>
<LI CLASS="li-toc"><A HREF="#htoc31">4&nbsp;&nbsp;Firewall Settings</A>
<LI CLASS="li-toc"><A HREF="#htoc32">5&nbsp;&nbsp;SRV Records</A>
<LI CLASS="li-toc"><A HREF="#htoc33">6&nbsp;&nbsp;Clustering</A>
<LI CLASS="li-toc"><A HREF="#htoc32">4&nbsp;&nbsp;Firewall Settings</A>
<LI CLASS="li-toc"><A HREF="#htoc33">5&nbsp;&nbsp;SRV Records</A>
<LI CLASS="li-toc"><A HREF="#htoc34">6&nbsp;&nbsp;Clustering</A>
<UL CLASS="toc"><LI CLASS="li-toc">
<A HREF="#htoc34">6.1&nbsp;&nbsp;How it Works</A>
<A HREF="#htoc35">6.1&nbsp;&nbsp;How it Works</A>
<UL CLASS="toc"><LI CLASS="li-toc">
<A HREF="#htoc35">6.1.1&nbsp;&nbsp;Router</A>
<LI CLASS="li-toc"><A HREF="#htoc36">6.1.2&nbsp;&nbsp;Local Router</A>
<LI CLASS="li-toc"><A HREF="#htoc37">6.1.3&nbsp;&nbsp;Session Manager</A>
<LI CLASS="li-toc"><A HREF="#htoc38">6.1.4&nbsp;&nbsp;s2s Manager</A>
<A HREF="#htoc36">6.1.1&nbsp;&nbsp;Router</A>
<LI CLASS="li-toc"><A HREF="#htoc37">6.1.2&nbsp;&nbsp;Local Router</A>
<LI CLASS="li-toc"><A HREF="#htoc38">6.1.3&nbsp;&nbsp;Session Manager</A>
<LI CLASS="li-toc"><A HREF="#htoc39">6.1.4&nbsp;&nbsp;s2s Manager</A>
</UL>
<LI CLASS="li-toc"><A HREF="#htoc39">6.2&nbsp;&nbsp;Clustering Setup</A>
<LI CLASS="li-toc"><A HREF="#htoc40">6.2&nbsp;&nbsp;Clustering Setup</A>
</UL>
<LI CLASS="li-toc"><A HREF="#htoc40">A&nbsp;&nbsp;Built-in Modules</A>
<LI CLASS="li-toc"><A HREF="#htoc41">A&nbsp;&nbsp;Built-in Modules</A>
<UL CLASS="toc"><LI CLASS="li-toc">
<A HREF="#htoc41">A.1&nbsp;&nbsp;Overview</A>
<LI CLASS="li-toc"><A HREF="#htoc42">A.2&nbsp;&nbsp;Common Options</A>
<A HREF="#htoc42">A.1&nbsp;&nbsp;Overview</A>
<LI CLASS="li-toc"><A HREF="#htoc43">A.2&nbsp;&nbsp;Common Options</A>
<UL CLASS="toc"><LI CLASS="li-toc">
<A HREF="#htoc43">A.2.1&nbsp;&nbsp;<TT>iqdisc</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc44">A.2.2&nbsp;&nbsp;<TT>hosts</TT></A>
<A HREF="#htoc44">A.2.1&nbsp;&nbsp;<TT>iqdisc</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc45">A.2.2&nbsp;&nbsp;<TT>hosts</TT></A>
</UL>
<LI CLASS="li-toc"><A HREF="#htoc45">A.3&nbsp;&nbsp;<TT>mod_announce</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc46">A.4&nbsp;&nbsp;<TT>mod_disco</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc47">A.5&nbsp;&nbsp;<TT>mod_echo</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc48">A.6&nbsp;&nbsp;<TT>mod_irc</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc49">A.7&nbsp;&nbsp;<TT>mod_last</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc50">A.8&nbsp;&nbsp;<TT>mod_muc</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc51">A.9&nbsp;&nbsp;<TT>mod_muc_log</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc52">A.10&nbsp;&nbsp;<TT>mod_offline</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc53">A.11&nbsp;&nbsp;<TT>mod_privacy</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc54">A.12&nbsp;&nbsp;<TT>mod_private</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc55">A.13&nbsp;&nbsp;<TT>mod_pubsub</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc56">A.14&nbsp;&nbsp;<TT>mod_register</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc57">A.15&nbsp;&nbsp;<TT>mod_roster</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc58">A.16&nbsp;&nbsp;<TT>mod_service_log</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc59">A.17&nbsp;&nbsp;<TT>mod_shared_roster</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc60">A.18&nbsp;&nbsp;<TT>mod_stats</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc61">A.19&nbsp;&nbsp;<TT>mod_time</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc62">A.20&nbsp;&nbsp;<TT>mod_vcard</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc63">A.21&nbsp;&nbsp;<TT>mod_version</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc46">A.3&nbsp;&nbsp;<TT>mod_announce</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc47">A.4&nbsp;&nbsp;<TT>mod_disco</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc48">A.5&nbsp;&nbsp;<TT>mod_echo</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc49">A.6&nbsp;&nbsp;<TT>mod_irc</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc50">A.7&nbsp;&nbsp;<TT>mod_last</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc51">A.8&nbsp;&nbsp;<TT>mod_muc</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc52">A.9&nbsp;&nbsp;<TT>mod_muc_log</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc53">A.10&nbsp;&nbsp;<TT>mod_offline</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc54">A.11&nbsp;&nbsp;<TT>mod_privacy</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc55">A.12&nbsp;&nbsp;<TT>mod_private</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc56">A.13&nbsp;&nbsp;<TT>mod_pubsub</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc57">A.14&nbsp;&nbsp;<TT>mod_register</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc58">A.15&nbsp;&nbsp;<TT>mod_roster</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc59">A.16&nbsp;&nbsp;<TT>mod_service_log</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc60">A.17&nbsp;&nbsp;<TT>mod_shared_roster</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc61">A.18&nbsp;&nbsp;<TT>mod_stats</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc62">A.19&nbsp;&nbsp;<TT>mod_time</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc63">A.20&nbsp;&nbsp;<TT>mod_vcard</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc64">A.21&nbsp;&nbsp;<TT>mod_version</TT></A>
</UL>
<LI CLASS="li-toc"><A HREF="#htoc64">B&nbsp;&nbsp;Internationalization and Localization</A>
<LI CLASS="li-toc"><A HREF="#htoc65">C&nbsp;&nbsp;Release Notes</A>
<LI CLASS="li-toc"><A HREF="#htoc65">B&nbsp;&nbsp;Internationalization and Localization</A>
<LI CLASS="li-toc"><A HREF="#htoc66">C&nbsp;&nbsp;Release Notes</A>
<UL CLASS="toc"><LI CLASS="li-toc">
<A HREF="#htoc66">C.1&nbsp;&nbsp;ejabberd 0.9</A>
<LI CLASS="li-toc"><A HREF="#htoc67">C.2&nbsp;&nbsp;ejabberd 0.9.1</A>
<LI CLASS="li-toc"><A HREF="#htoc68">C.3&nbsp;&nbsp;ejabberd 0.9.8</A>
<LI CLASS="li-toc"><A HREF="#htoc69">C.4&nbsp;&nbsp;ejabberd 1.0.0</A>
<LI CLASS="li-toc"><A HREF="#htoc70">C.5&nbsp;&nbsp;ejabberd 1.1.0</A>
<LI CLASS="li-toc"><A HREF="#htoc71">C.6&nbsp;&nbsp;ejabberd 1.1.1</A>
<A HREF="#htoc67">C.1&nbsp;&nbsp;ejabberd 0.9</A>
<LI CLASS="li-toc"><A HREF="#htoc68">C.2&nbsp;&nbsp;ejabberd 0.9.1</A>
<LI CLASS="li-toc"><A HREF="#htoc69">C.3&nbsp;&nbsp;ejabberd 0.9.8</A>
<LI CLASS="li-toc"><A HREF="#htoc70">C.4&nbsp;&nbsp;ejabberd 1.0.0</A>
<LI CLASS="li-toc"><A HREF="#htoc71">C.5&nbsp;&nbsp;ejabberd 1.1.0</A>
<LI CLASS="li-toc"><A HREF="#htoc72">C.6&nbsp;&nbsp;ejabberd 1.1.1</A>
</UL>
<LI CLASS="li-toc"><A HREF="#htoc72">D&nbsp;&nbsp;Acknowledgements</A>
<LI CLASS="li-toc"><A HREF="#htoc73">D&nbsp;&nbsp;Acknowledgements</A>
</UL>
<!--TOC section Introduction-->
@ -230,6 +231,7 @@ Native MySQL support.
<LI CLASS="li-itemize">Native PostgreSQL support.
<LI CLASS="li-itemize">Mnesia.
<LI CLASS="li-itemize">ODBC data storage support.
<LI CLASS="li-itemize">Microsoft SQL Server support (via ODBC).
</UL>
<LI CLASS="li-itemize">Authentication
<UL CLASS="itemize"><LI CLASS="li-itemize">
@ -973,9 +975,29 @@ available from:
<H3 CLASS="subsection"><A NAME="htoc24">3.2</A>&nbsp;&nbsp;Relational Database Support</H3><!--SEC END -->
<A NAME="sec:relationaldatabase"></A>
<!--TOC subsubsection Preliminary steps-->
<H4 CLASS="subsubsection"><A NAME="htoc25">3.2.1</A>&nbsp;&nbsp;Preliminary steps</H4><!--SEC END -->
<A NAME="sec:relationaldatabasecompilation"></A>
If you have installed ejabberd using a binary version, the compilation steps
are not needed as they have already been done correctly.<BR>
<BR>
Otherwise, to be able to use ejabberd with a relational database you need to
enable ODBC modules during compilation, even if you want to use ejabberd with
MySQL or PostgreSQL in native mode. The following <TT>configure</TT> command can
be used to enable the relational modules:
<PRE CLASS="verbatim">
./configure --enable-odbc
</PRE>
If you are planning to use Microsoft SQL Server with ODBC, you need to specify
it from the <TT>configure</TT> command before compilation:
<PRE CLASS="verbatim">
./configure --enable-odbc --enable-mssql
</PRE>
<!--TOC subsubsection Authentication against a relational database-->
<H4 CLASS="subsubsection"><A NAME="htoc25">3.2.1</A>&nbsp;&nbsp;Authentication against a relational database</H4><!--SEC END -->
<H4 CLASS="subsubsection"><A NAME="htoc26">3.2.2</A>&nbsp;&nbsp;Authentication against a relational database</H4><!--SEC END -->
<A NAME="sec:relationaldatabaseauth"></A>
ejabberd use its internal Mnesia database as a default. It is however possible
@ -1030,7 +1052,7 @@ available from: <A HREF="http://support.process-one.net/doc/display/MESSENGER/Us
<BR>
<!--TOC subsubsection Relational database for other modules-->
<H4 CLASS="subsubsection"><A NAME="htoc26">3.2.2</A>&nbsp;&nbsp;Relational database for other modules</H4><!--SEC END -->
<H4 CLASS="subsubsection"><A NAME="htoc27">3.2.3</A>&nbsp;&nbsp;Relational database for other modules</H4><!--SEC END -->
<A NAME="sec:relationaldatabaseextra"></A>
It is possible to use a relational database to store pieces of
@ -1047,7 +1069,7 @@ Last connection date and time: Use <TT>mod_last_odbc</TT> instead of
</UL>
<!--TOC subsection Creating an Initial Administrator-->
<H3 CLASS="subsection"><A NAME="htoc27">3.3</A>&nbsp;&nbsp;Creating an Initial Administrator</H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc28">3.3</A>&nbsp;&nbsp;Creating an Initial Administrator</H3><!--SEC END -->
<A NAME="sec:initialadmin"></A>
Before the web interface can be entered to perform administration tasks, an
@ -1079,12 +1101,12 @@ Register an account on your <TT>ejabberd</TT> deployment. An account can be
</OL>
<!--TOC subsection Online Configuration and Monitoring-->
<H3 CLASS="subsection"><A NAME="htoc28">3.4</A>&nbsp;&nbsp;Online Configuration and Monitoring</H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc29">3.4</A>&nbsp;&nbsp;Online Configuration and Monitoring</H3><!--SEC END -->
<A NAME="sec:onlineconfig"></A>
<!--TOC subsubsection Web Interface-->
<H4 CLASS="subsubsection"><A NAME="htoc29">3.4.1</A>&nbsp;&nbsp;Web Interface</H4><!--SEC END -->
<H4 CLASS="subsubsection"><A NAME="htoc30">3.4.1</A>&nbsp;&nbsp;Web Interface</H4><!--SEC END -->
<A NAME="sec:webadm"></A>
@ -1158,7 +1180,7 @@ You can serve the web interface on the same port as the
</PRE></UL>
<!--TOC subsubsection <TT>ejabberdctl</TT>-->
<H4 CLASS="subsubsection"><A NAME="htoc30">3.4.2</A>&nbsp;&nbsp;<TT>ejabberdctl</TT></H4><!--SEC END -->
<H4 CLASS="subsubsection"><A NAME="htoc31">3.4.2</A>&nbsp;&nbsp;<TT>ejabberdctl</TT></H4><!--SEC END -->
<A NAME="sec:ejabberdctl"></A>
It is possible to do some administration operations using the command
@ -1204,7 +1226,7 @@ Additional information:
</DL>
<!--TOC section Firewall Settings-->
<H2 CLASS="section"><A NAME="htoc31">4</A>&nbsp;&nbsp;Firewall Settings</H2><!--SEC END -->
<H2 CLASS="section"><A NAME="htoc32">4</A>&nbsp;&nbsp;Firewall Settings</H2><!--SEC END -->
<A NAME="sec:firewall"></A>
@ -1233,7 +1255,7 @@ You need to take the following TCP ports in mind when configuring your firewall:
<DIV CLASS="center"><HR WIDTH="80%" SIZE=2></DIV></DIV></BLOCKQUOTE>
<!--TOC section SRV Records-->
<H2 CLASS="section"><A NAME="htoc32">5</A>&nbsp;&nbsp;SRV Records</H2><!--SEC END -->
<H2 CLASS="section"><A NAME="htoc33">5</A>&nbsp;&nbsp;SRV Records</H2><!--SEC END -->
<A NAME="sec:srv"></A>
@ -1245,13 +1267,13 @@ General information:
</UL>
<!--TOC section Clustering-->
<H2 CLASS="section"><A NAME="htoc33">6</A>&nbsp;&nbsp;Clustering</H2><!--SEC END -->
<H2 CLASS="section"><A NAME="htoc34">6</A>&nbsp;&nbsp;Clustering</H2><!--SEC END -->
<A NAME="sec:clustering"></A>
<!--TOC subsection How it Works-->
<H3 CLASS="subsection"><A NAME="htoc34">6.1</A>&nbsp;&nbsp;How it Works</H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc35">6.1</A>&nbsp;&nbsp;How it Works</H3><!--SEC END -->
<A NAME="sec:howitworks"></A>
@ -1272,7 +1294,7 @@ router,
</UL>
<!--TOC subsubsection Router-->
<H4 CLASS="subsubsection"><A NAME="htoc35">6.1.1</A>&nbsp;&nbsp;Router</H4><!--SEC END -->
<H4 CLASS="subsubsection"><A NAME="htoc36">6.1.1</A>&nbsp;&nbsp;Router</H4><!--SEC END -->
This module is the main router of Jabber packets on each node. It
@ -1283,7 +1305,7 @@ appropriate process. If not, it is sent to the s2s manager.<BR>
<BR>
<!--TOC subsubsection Local Router-->
<H4 CLASS="subsubsection"><A NAME="htoc36">6.1.2</A>&nbsp;&nbsp;Local Router</H4><!--SEC END -->
<H4 CLASS="subsubsection"><A NAME="htoc37">6.1.2</A>&nbsp;&nbsp;Local Router</H4><!--SEC END -->
This module routes packets which have a destination domain equal to
@ -1293,7 +1315,7 @@ on its content.<BR>
<BR>
<!--TOC subsubsection Session Manager-->
<H4 CLASS="subsubsection"><A NAME="htoc37">6.1.3</A>&nbsp;&nbsp;Session Manager</H4><!--SEC END -->
<H4 CLASS="subsubsection"><A NAME="htoc38">6.1.3</A>&nbsp;&nbsp;Session Manager</H4><!--SEC END -->
This module routes packets to local users. It looks up to which user
@ -1303,7 +1325,7 @@ storage, or bounced back.<BR>
<BR>
<!--TOC subsubsection s2s Manager-->
<H4 CLASS="subsubsection"><A NAME="htoc38">6.1.4</A>&nbsp;&nbsp;s2s Manager</H4><!--SEC END -->
<H4 CLASS="subsubsection"><A NAME="htoc39">6.1.4</A>&nbsp;&nbsp;s2s Manager</H4><!--SEC END -->
This module routes packets to other Jabber servers. First, it
@ -1314,7 +1336,7 @@ serving this connection, otherwise a new connection is opened.<BR>
<BR>
<!--TOC subsection Clustering Setup-->
<H3 CLASS="subsection"><A NAME="htoc39">6.2</A>&nbsp;&nbsp;Clustering Setup</H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc40">6.2</A>&nbsp;&nbsp;Clustering Setup</H3><!--SEC END -->
<A NAME="sec:cluster"></A>
@ -1387,13 +1409,13 @@ domain.<BR>
<!--TOC section Built-in Modules-->
<H2 CLASS="section"><A NAME="htoc40">A</A>&nbsp;&nbsp;Built-in Modules</H2><!--SEC END -->
<H2 CLASS="section"><A NAME="htoc41">A</A>&nbsp;&nbsp;Built-in Modules</H2><!--SEC END -->
<A NAME="sec:modules"></A>
<!--TOC subsection Overview-->
<H3 CLASS="subsection"><A NAME="htoc41">A.1</A>&nbsp;&nbsp;Overview</H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc42">A.1</A>&nbsp;&nbsp;Overview</H3><!--SEC END -->
<A NAME="sec:modoverview"></A>
@ -1605,7 +1627,7 @@ XMPP compliancy.<BR>
<BR>
<!--TOC subsection Common Options-->
<H3 CLASS="subsection"><A NAME="htoc42">A.2</A>&nbsp;&nbsp;Common Options</H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc43">A.2</A>&nbsp;&nbsp;Common Options</H3><!--SEC END -->
<A NAME="sec:modcommonopts"></A>
The following options are used by many modules. Therefore, they are described in
@ -1613,7 +1635,7 @@ this separate section.<BR>
<BR>
<!--TOC subsubsection <TT>iqdisc</TT>-->
<H4 CLASS="subsubsection"><A NAME="htoc43">A.2.1</A>&nbsp;&nbsp;<TT>iqdisc</TT></H4><!--SEC END -->
<H4 CLASS="subsubsection"><A NAME="htoc44">A.2.1</A>&nbsp;&nbsp;<TT>iqdisc</TT></H4><!--SEC END -->
<A NAME="sec:modiqdiscoption"></A>
@ -1647,7 +1669,7 @@ Example:
</PRE>
<!--TOC subsubsection <TT>hosts</TT>-->
<H4 CLASS="subsubsection"><A NAME="htoc44">A.2.2</A>&nbsp;&nbsp;<TT>hosts</TT></H4><!--SEC END -->
<H4 CLASS="subsubsection"><A NAME="htoc45">A.2.2</A>&nbsp;&nbsp;<TT>hosts</TT></H4><!--SEC END -->
<A NAME="sec:modhostsoption"></A>
@ -1686,7 +1708,7 @@ Serving the echo module on one domain:
</PRE></UL>
<!--TOC subsection <TT>mod_announce</TT>-->
<H3 CLASS="subsection"><A NAME="htoc45">A.3</A>&nbsp;&nbsp;<TT>mod_announce</TT></H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc46">A.3</A>&nbsp;&nbsp;<TT>mod_announce</TT></H3><!--SEC END -->
<A NAME="sec:modannounce"></A>
@ -1752,7 +1774,7 @@ Only administrators can send announcements:
</PRE></UL>
<!--TOC subsection <TT>mod_disco</TT>-->
<H3 CLASS="subsection"><A NAME="htoc46">A.4</A>&nbsp;&nbsp;<TT>mod_disco</TT></H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc47">A.4</A>&nbsp;&nbsp;<TT>mod_disco</TT></H3><!--SEC END -->
<A NAME="sec:moddisco"></A>
@ -1804,7 +1826,7 @@ To serve a link to the Jabber User Directory on <TT>jabber.org</TT>:
</PRE></UL>
<!--TOC subsection <TT>mod_echo</TT>-->
<H3 CLASS="subsection"><A NAME="htoc47">A.5</A>&nbsp;&nbsp;<TT>mod_echo</TT></H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc48">A.5</A>&nbsp;&nbsp;<TT>mod_echo</TT></H3><!--SEC END -->
<A NAME="sec:modecho"></A>
@ -1837,7 +1859,7 @@ Mirror, mirror, on the wall, who is the most beautiful
</UL>
<!--TOC subsection <TT>mod_irc</TT>-->
<H3 CLASS="subsection"><A NAME="htoc48">A.6</A>&nbsp;&nbsp;<TT>mod_irc</TT></H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc49">A.6</A>&nbsp;&nbsp;<TT>mod_irc</TT></H3><!--SEC END -->
<A NAME="sec:modirc"></A>
@ -1907,7 +1929,7 @@ In the first example, the IRC transport is available on (all) your
</PRE></UL>
<!--TOC subsection <TT>mod_last</TT>-->
<H3 CLASS="subsection"><A NAME="htoc49">A.7</A>&nbsp;&nbsp;<TT>mod_last</TT></H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc50">A.7</A>&nbsp;&nbsp;<TT>mod_last</TT></H3><!--SEC END -->
<A NAME="sec:modlast"></A>
@ -1924,7 +1946,7 @@ the processing discipline for Last activity (<TT>jabber:iq:last</TT>) IQ queries
</DL>
<!--TOC subsection <TT>mod_muc</TT>-->
<H3 CLASS="subsection"><A NAME="htoc50">A.8</A>&nbsp;&nbsp;<TT>mod_muc</TT></H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc51">A.8</A>&nbsp;&nbsp;<TT>mod_muc</TT></H3><!--SEC END -->
<A NAME="sec:modmuc"></A>
@ -2014,7 +2036,7 @@ In the first example everyone is allowed to use the Multi-User Chat
</PRE></UL>
<!--TOC subsection <TT>mod_muc_log</TT>-->
<H3 CLASS="subsection"><A NAME="htoc51">A.9</A>&nbsp;&nbsp;<TT>mod_muc_log</TT></H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc52">A.9</A>&nbsp;&nbsp;<TT>mod_muc_log</TT></H3><!--SEC END -->
<A NAME="sec:modmuclog"></A>
@ -2086,7 +2108,7 @@ Example configuration:
</PRE>
<!--TOC subsection <TT>mod_offline</TT>-->
<H3 CLASS="subsection"><A NAME="htoc52">A.10</A>&nbsp;&nbsp;<TT>mod_offline</TT></H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc53">A.10</A>&nbsp;&nbsp;<TT>mod_offline</TT></H3><!--SEC END -->
<A NAME="sec:modoffline"></A>
@ -2098,7 +2120,7 @@ online again. Thus it is very similar to how email works. Note that
<BR>
<!--TOC subsection <TT>mod_privacy</TT>-->
<H3 CLASS="subsection"><A NAME="htoc53">A.11</A>&nbsp;&nbsp;<TT>mod_privacy</TT></H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc54">A.11</A>&nbsp;&nbsp;<TT>mod_privacy</TT></H3><!--SEC END -->
<A NAME="sec:modprivacy"></A>
@ -2133,7 +2155,7 @@ the processing discipline for Blocking Communication (<TT>jabber:iq:privacy</TT>
</DL>
<!--TOC subsection <TT>mod_private</TT>-->
<H3 CLASS="subsection"><A NAME="htoc54">A.12</A>&nbsp;&nbsp;<TT>mod_private</TT></H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc55">A.12</A>&nbsp;&nbsp;<TT>mod_private</TT></H3><!--SEC END -->
<A NAME="sec:modprivate"></A>
@ -2152,7 +2174,7 @@ the processing discipline for Private XML Storage (<TT>jabber:iq:private</TT>) I
</DL>
<!--TOC subsection <TT>mod_pubsub</TT>-->
<H3 CLASS="subsection"><A NAME="htoc55">A.13</A>&nbsp;&nbsp;<TT>mod_pubsub</TT></H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc56">A.13</A>&nbsp;&nbsp;<TT>mod_pubsub</TT></H3><!--SEC END -->
<A NAME="sec:modpubsub"></A>
@ -2205,7 +2227,7 @@ Example:
</PRE>
<!--TOC subsection <TT>mod_register</TT>-->
<H3 CLASS="subsection"><A NAME="htoc56">A.14</A>&nbsp;&nbsp;<TT>mod_register</TT></H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc57">A.14</A>&nbsp;&nbsp;<TT>mod_register</TT></H3><!--SEC END -->
<A NAME="sec:modregister"></A>
@ -2262,7 +2284,7 @@ Next example prohibits the registration of too short account names and of
</PRE></UL>
<!--TOC subsection <TT>mod_roster</TT>-->
<H3 CLASS="subsection"><A NAME="htoc57">A.15</A>&nbsp;&nbsp;<TT>mod_roster</TT></H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc58">A.15</A>&nbsp;&nbsp;<TT>mod_roster</TT></H3><!--SEC END -->
<A NAME="sec:modroster"></A>
@ -2276,7 +2298,7 @@ the processing discipline for Roster Management (<TT>jabber:iq:roster</TT>) IQ q
</DL>
<!--TOC subsection <TT>mod_service_log</TT>-->
<H3 CLASS="subsection"><A NAME="htoc58">A.16</A>&nbsp;&nbsp;<TT>mod_service_log</TT></H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc59">A.16</A>&nbsp;&nbsp;<TT>mod_service_log</TT></H3><!--SEC END -->
<A NAME="sec:modservicelog"></A>
@ -2316,7 +2338,7 @@ To log all end user packets to the Bandersnatch service running on
</PRE></UL>
<!--TOC subsection <TT>mod_shared_roster</TT>-->
<H3 CLASS="subsection"><A NAME="htoc59">A.17</A>&nbsp;&nbsp;<TT>mod_shared_roster</TT></H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc60">A.17</A>&nbsp;&nbsp;<TT>mod_shared_roster</TT></H3><!--SEC END -->
<A NAME="sec:modsharedroster"></A>
@ -2443,7 +2465,7 @@ Take the case of a computer club that wants all its members seeing each
</UL>
<!--TOC subsection <TT>mod_stats</TT>-->
<H3 CLASS="subsection"><A NAME="htoc60">A.18</A>&nbsp;&nbsp;<TT>mod_stats</TT></H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc61">A.18</A>&nbsp;&nbsp;<TT>mod_stats</TT></H3><!--SEC END -->
<A NAME="sec:modstats"></A>
@ -2485,7 +2507,7 @@ You can request the number of online users on the current virtual host
</PRE></UL>
<!--TOC subsection <TT>mod_time</TT>-->
<H3 CLASS="subsection"><A NAME="htoc61">A.19</A>&nbsp;&nbsp;<TT>mod_time</TT></H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc62">A.19</A>&nbsp;&nbsp;<TT>mod_time</TT></H3><!--SEC END -->
<A NAME="sec:modtime"></A>
@ -2500,7 +2522,7 @@ the processing discipline for Entity Time (<TT>jabber:iq:time</TT>) IQ queries
</DL>
<!--TOC subsection <TT>mod_vcard</TT>-->
<H3 CLASS="subsection"><A NAME="htoc62">A.20</A>&nbsp;&nbsp;<TT>mod_vcard</TT></H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc63">A.20</A>&nbsp;&nbsp;<TT>mod_vcard</TT></H3><!--SEC END -->
<A NAME="sec:modvcard"></A>
@ -2566,7 +2588,7 @@ In this first situation, search results are limited to twenty items,
</PRE></UL>
<!--TOC subsection <TT>mod_version</TT>-->
<H3 CLASS="subsection"><A NAME="htoc63">A.21</A>&nbsp;&nbsp;<TT>mod_version</TT></H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc64">A.21</A>&nbsp;&nbsp;<TT>mod_version</TT></H3><!--SEC END -->
<A NAME="sec:modversion"></A>
@ -2581,7 +2603,7 @@ the processing discipline for Software Version (<TT>jabber:iq:version</TT>) IQ q
</DL>
<!--TOC section Internationalization and Localization-->
<H2 CLASS="section"><A NAME="htoc64">B</A>&nbsp;&nbsp;Internationalization and Localization</H2><!--SEC END -->
<H2 CLASS="section"><A NAME="htoc65">B</A>&nbsp;&nbsp;Internationalization and Localization</H2><!--SEC END -->
<A NAME="sec:i18nl10n"></A>
@ -2624,13 +2646,13 @@ figure&nbsp;<A HREF="#fig:webadmmainru">3</A> with figure&nbsp;<A HREF="#fig:web
<DIV CLASS="center"><HR WIDTH="80%" SIZE=2></DIV></DIV></BLOCKQUOTE>
<!--TOC section Release Notes-->
<H2 CLASS="section"><A NAME="htoc65">C</A>&nbsp;&nbsp;Release Notes</H2><!--SEC END -->
<H2 CLASS="section"><A NAME="htoc66">C</A>&nbsp;&nbsp;Release Notes</H2><!--SEC END -->
<A NAME="sec:releasenotes"></A>
<!--TOC subsection ejabberd 0.9-->
<H3 CLASS="subsection"><A NAME="htoc66">C.1</A>&nbsp;&nbsp;ejabberd 0.9</H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc67">C.1</A>&nbsp;&nbsp;ejabberd 0.9</H3><!--SEC END -->
<PRE CLASS="verbatim">
Release notes
@ -2724,7 +2746,7 @@ Bugfixes
</PRE>
<!--TOC subsection ejabberd 0.9.1-->
<H3 CLASS="subsection"><A NAME="htoc67">C.2</A>&nbsp;&nbsp;ejabberd 0.9.1</H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc68">C.2</A>&nbsp;&nbsp;ejabberd 0.9.1</H3><!--SEC END -->
<PRE CLASS="verbatim">
Release notes
@ -2792,7 +2814,7 @@ Bugfixes
</PRE>
<!--TOC subsection ejabberd 0.9.8-->
<H3 CLASS="subsection"><A NAME="htoc68">C.3</A>&nbsp;&nbsp;ejabberd 0.9.8</H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc69">C.3</A>&nbsp;&nbsp;ejabberd 0.9.8</H3><!--SEC END -->
<PRE CLASS="verbatim">
Release notes
@ -2897,7 +2919,7 @@ END
</PRE>
<!--TOC subsection ejabberd 1.0.0-->
<H3 CLASS="subsection"><A NAME="htoc69">C.4</A>&nbsp;&nbsp;ejabberd 1.0.0</H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc70">C.4</A>&nbsp;&nbsp;ejabberd 1.0.0</H3><!--SEC END -->
<PRE CLASS="verbatim">
Release Notes
@ -3023,7 +3045,7 @@ END
</PRE>
<!--TOC subsection ejabberd 1.1.0-->
<H3 CLASS="subsection"><A NAME="htoc70">C.5</A>&nbsp;&nbsp;ejabberd 1.1.0</H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc71">C.5</A>&nbsp;&nbsp;ejabberd 1.1.0</H3><!--SEC END -->
<PRE CLASS="verbatim">
Release Notes
@ -3144,7 +3166,7 @@ END
</PRE>
<!--TOC subsection ejabberd 1.1.1-->
<H3 CLASS="subsection"><A NAME="htoc71">C.6</A>&nbsp;&nbsp;ejabberd 1.1.1</H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc72">C.6</A>&nbsp;&nbsp;ejabberd 1.1.1</H3><!--SEC END -->
<PRE CLASS="verbatim">
Release Notes
@ -3269,7 +3291,7 @@ END
</PRE>
<!--TOC section Acknowledgements-->
<H2 CLASS="section"><A NAME="htoc72">D</A>&nbsp;&nbsp;Acknowledgements</H2><!--SEC END -->
<H2 CLASS="section"><A NAME="htoc73">D</A>&nbsp;&nbsp;Acknowledgements</H2><!--SEC END -->
<A NAME="sec:acknowledgements"></A>

View File

@ -860,6 +860,26 @@ available from:
\subsection{Relational Database Support}
\label{sec:relationaldatabase}
\subsubsection{Preliminary steps}
\label{sec:relationaldatabasecompilation}
If you have installed ejabberd using a binary version, the compilation steps
are not needed as they have already been done correctly.
Otherwise, to be able to use ejabberd with a relational database you need to
enable ODBC modules during compilation, even if you want to use ejabberd with
MySQL or PostgreSQL in native mode. The following \term{configure} command can
be used to enable the relational modules:
\begin{verbatim}
./configure --enable-odbc
\end{verbatim}
If you are planning to use Microsoft SQL Server with ODBC, you need to specify
it from the \term{configure} command before compilation:
\begin{verbatim}
./configure --enable-odbc --enable-mssql
\end{verbatim}
\subsubsection{Authentication against a relational database}
\label{sec:relationaldatabaseauth}

View File

@ -100,7 +100,9 @@ Besides common \Jabber{} server features, \ejabberd{} comes with a wide range of
\item Native MySQL support.\new{}
\item Native PostgreSQL support.
\item Mnesia.
\item ODBC data storage support. \moreinfo{ --- ODBC requests can be load balanced between several connections.}
\item ODBC data storage support. \moreinfo{ --- ODBC requests can be load
balanced between several connections.}
\item Microsoft SQL Server support (via ODBC).\new{}
\end{itemize}
\item Authentication
\begin{itemize}

3963
src/configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -37,7 +37,7 @@ AC_MOD_ENABLE(odbc, no)
AC_MOD_ENABLE(ejabberd_zlib, yes)
AC_ARG_ENABLE(roster_gateway_workaround,
[ --enable-roster-gateway-workaround Turn on workaround for processing gateway subscriptions],
[ --enable-roster-gateway-workaround Turn on workaround for processing gateway subscriptions (default: no)],
[case "${enableval}" in
yes) roster_gateway_workaround=true ;;
no) roster_gateway_workaround=false ;;
@ -45,6 +45,15 @@ AC_ARG_ENABLE(roster_gateway_workaround,
esac],[roster_gateway_workaround=false])
AC_SUBST(roster_gateway_workaround)
AC_ARG_ENABLE(mssql,
[ --enable-mssql Use Microsoft SQL Server database (default: no, requires --enable-odbc)],
[case "${enableval}" in
yes) db_type=mssql ;;
no) db_type=generic ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-mssql) ;;
esac],[db_type=generic])
AC_SUBST(db_type)
AC_CONFIG_FILES([Makefile
$make_mod_irc
$make_mod_muc

View File

@ -46,6 +46,7 @@ start() ->
Version = "EJABBERD_VERSION = " ++ ?VERSION ++ "\n",
ExpatDir = "EXPAT_DIR = c:\\progra~1\\expat-1.95.7\n",
OpenSSLDir = "OPENSSL_DIR = c:\\progra~1\\OpenSSL\n",
DBType = "DBTYPE = generic\n", %% 'generic' or 'mssql'
SSLDir = "SSLDIR = " ++ code:lib_dir("ssl") ++ "\n",
StdLibDir = "STDLIBDIR = " ++ code:lib_dir("stdlib") ++ "\n",
@ -58,6 +59,7 @@ start() ->
SSLDir ++
StdLibDir ++
OpenSSLDir ++
DBType ++
ExpatDir ++
ExpatLib ++
ExpatFlag ++

View File

@ -57,10 +57,8 @@ check_password(User, Server, Password) ->
false;
LUser ->
Username = ejabberd_odbc:escape(LUser),
case catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["select password from users "
"where username='", Username, "';"]) of
LServer = jlib:nameprep(Server),
case catch odbc_queries:get_password(LServer, Username) of
{selected, ["password"], [{Password}]} ->
true;
_ ->
@ -74,10 +72,8 @@ check_password(User, Server, Password, StreamID, Digest) ->
false;
LUser ->
Username = ejabberd_odbc:escape(LUser),
case catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["select password from users "
"where username='", Username, "';"]) of
LServer = jlib:nameprep(Server),
case catch odbc_queries:get_password(LServer, Username) of
{selected, ["password"], [{Passwd}]} ->
DigRes = if
Digest /= "" ->
@ -103,11 +99,7 @@ set_password(User, Server, Password) ->
Username = ejabberd_odbc:escape(LUser),
Pass = ejabberd_odbc:escape(Password),
LServer = jlib:nameprep(Server),
catch ejabberd_odbc:sql_transaction(
LServer,
[["delete from users where username='", Username ,"';"],
["insert into users(username, password) "
"values ('", Username, "', '", Pass, "');"]])
catch odbc_queries:set_password_t(LServer, Username, Pass)
end.
@ -118,10 +110,8 @@ try_register(User, Server, Password) ->
LUser ->
Username = ejabberd_odbc:escape(LUser),
Pass = ejabberd_odbc:escape(Password),
case catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["insert into users(username, password) "
"values ('", Username, "', '", Pass, "');"]) of
LServer = jlib:nameprep(Server),
case catch odbc_queries:add_user(LServer, Username, Pass) of
{updated, 1} ->
{atomic, ok};
_ ->
@ -134,9 +124,7 @@ dirty_get_registered_users() ->
get_vh_registered_users(Server) ->
LServer = jlib:nameprep(Server),
case catch ejabberd_odbc:sql_query(
LServer,
"select username from users") of
case catch odbc_queries:list_users(LServer) of
{selected, ["username"], Res} ->
[{U, LServer} || {U} <- Res];
_ ->
@ -149,10 +137,8 @@ get_password(User, Server) ->
false;
LUser ->
Username = ejabberd_odbc:escape(LUser),
case catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["select password from users "
"where username='", Username, "';"]) of
LServer = jlib:nameprep(Server),
case catch odbc_queries:get_password(LServer, Username) of
{selected, ["password"], [{Password}]} ->
Password;
_ ->
@ -166,10 +152,8 @@ get_password_s(User, Server) ->
"";
LUser ->
Username = ejabberd_odbc:escape(LUser),
case catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["select password from users "
"where username='", Username, "';"]) of
LServer = jlib:nameprep(Server),
case catch odbc_queries:get_password(LServer, Username) of
{selected, ["password"], [{Password}]} ->
Password;
_ ->
@ -183,10 +167,8 @@ is_user_exists(User, Server) ->
false;
LUser ->
Username = ejabberd_odbc:escape(LUser),
case catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["select password from users "
"where username='", Username, "';"]) of
LServer = jlib:nameprep(Server),
case catch odbc_queries:get_password(LServer, Username) of
{selected, ["password"], [{_Password}]} ->
true;
_ ->
@ -200,9 +182,8 @@ remove_user(User, Server) ->
error;
LUser ->
Username = ejabberd_odbc:escape(LUser),
catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["delete from users where username='", Username ,"';"]),
LServer = jlib:nameprep(Server),
catch odbc_queries:del_user(LServer, Username),
ejabberd_hooks:run(remove_user, jlib:nameprep(Server),
[User, Server])
end.
@ -216,12 +197,8 @@ remove_user(User, Server, Password) ->
Pass = ejabberd_odbc:escape(Password),
LServer = jlib:nameprep(Server),
F = fun() ->
Result = ejabberd_odbc:sql_query_t(
["select password from users where username='",
Username, "';"]),
ejabberd_odbc:sql_query_t(["delete from users "
"where username='", Username,
"' and password='", Pass, "';"]),
Result = odbc_queries:del_user_return_password(
LServer, Username, Pass),
case Result of
{selected, ["password"], [{Password}]} ->
ejabberd_hooks:run(remove_user, jlib:nameprep(Server),
@ -233,6 +210,6 @@ remove_user(User, Server, Password) ->
not_allowed
end
end,
{atomic, Result } = ejabberd_odbc:transaction(LServer, F),
{atomic, Result} = odbc_queries:transaction(LServer, F),
Result
end.

View File

@ -95,10 +95,7 @@ process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) ->
get_last(IQ, SubEl, LUser, LServer) ->
Username = ejabberd_odbc:escape(LUser),
case catch ejabberd_odbc:sql_query(
LServer,
["select seconds, state from last "
"where username='", Username, "';"]) of
case catch odbc_queries:get_last(LServer, Username) of
{'EXIT', _Reason} ->
IQ#iq{type = error, sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]};
{selected, ["seconds","state"], []} ->
@ -131,16 +128,11 @@ store_last_info(User, Server, TimeStamp, Status) ->
Username = ejabberd_odbc:escape(LUser),
Seconds = ejabberd_odbc:escape(integer_to_list(TimeStamp)),
State = ejabberd_odbc:escape(Status),
%% MREMOND: I think this should be turn into a non transactional behaviour
ejabberd_odbc:sql_transaction(
LServer,
[["delete from last where username='", Username, "';"],
["insert into last(username, seconds, state) "
"values ('", Username, "', '", Seconds, "', '", State, "');"]]).
odbc_queries:set_last_t(LServer, Username, Seconds, State).
remove_user(User, Server) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
Username = ejabberd_odbc:escape(LUser),
ejabberd_odbc:sql_query(LServer,
["delete from last where username='", Username, "';"]).
odbc_queries:del_last(LServer, Username).

View File

@ -65,14 +65,9 @@ loop(Host) ->
ejabberd_odbc:escape(
lists:flatten(
xml:element_to_string(Packet))),
["insert into spool(username, xml) "
"values ('", Username, "', '",
XML,
"');"]
odbc_queries:add_spool_sql(Username, XML)
end, Msgs),
case catch ejabberd_odbc:sql_transaction(
Host,
Query) of
case catch odbc_queries:add_spool(Host, Query) of
{'EXIT', Reason} ->
?ERROR_MSG("~p~n", [Reason]);
_ ->
@ -207,15 +202,7 @@ pop_offline_messages(Ls, User, Server) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
EUser = ejabberd_odbc:escape(LUser),
F = fun() ->
Result = ejabberd_odbc:sql_query_t(
["select username, xml from spool where username='", EUser, "'"
" order by seq;"]),
ejabberd_odbc:sql_query_t(
["delete from spool where username='", EUser, "';"]),
Result
end,
case ejabberd_odbc:sql_transaction(LServer,F) of
case odbc_queries:get_and_del_spool_msg_t(LServer, EUser) of
{atomic, {selected, ["username","xml"], Rs}} ->
Ls ++ lists:flatmap(
fun({_, XML}) ->
@ -245,7 +232,5 @@ remove_user(User, Server) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
Username = ejabberd_odbc:escape(LUser),
ejabberd_odbc:sql_query(
LServer,
["delete from spool where username='", Username, "';"]).
odbc_queries:del_spool_msg(LServer, Username).

View File

@ -122,20 +122,13 @@ process_iq_get(From, To, #iq{sub_el = SubEl} = IQ) ->
get_user_roster(Acc, {LUser, LServer}) ->
Username = ejabberd_odbc:escape(LUser),
case catch ejabberd_odbc:sql_query(
LServer,
["select username, jid, nick, subscription, ask, "
"askmessage, server, subscribe, type from rosterusers "
"where username='", Username, "'"]) of
case catch odbc_queries:get_roster(LServer, Username) of
{selected, ["username", "jid", "nick", "subscription", "ask",
"askmessage", "server", "subscribe", "type"],
Items} when is_list(Items) ->
JIDGroups = case catch ejabberd_odbc:sql_query(
LServer,
["select jid, grp from rostergroups "
"where username='", Username, "'"]) of
{selected, ["jid","grp"],
JGrps} when is_list(JGrps) ->
JIDGroups = case catch odbc_queries:get_roster_jid_groups(LServer, Username) of
{selected, ["jid","grp"], JGrps}
when is_list(JGrps) ->
JGrps;
_ ->
[]
@ -148,10 +141,11 @@ get_user_roster(Acc, {LUser, LServer}) ->
R ->
SJID = jlib:jid_to_string(R#roster.jid),
Groups = lists:flatmap(
fun({S, G}) when S == SJID ->
[G];
(_) ->
[]
fun({S, G}) ->
case jlib:jid_tolower(S) of
SJID -> [G];
_ -> []
end
end, JIDGroups),
[R#roster{groups = Groups}]
end
@ -216,13 +210,7 @@ process_item_set(From, To, {xmlelement, _Name, Attrs, Els}) ->
{selected,
["username", "jid", "nick", "subscription",
"ask", "askmessage", "server", "subscribe", "type"],
Res} =
ejabberd_odbc:sql_query_t(
["select username, jid, nick, subscription, "
"ask, askmessage, server, subscribe, type "
"from rosterusers "
"where username='", Username, "' "
"and jid='", SJID, "'"]),
Res} = odbc_queries:get_roster_by_jid(LServer, Username, SJID),
Item = case Res of
[] ->
#roster{usj = {LUser, LServer, LJID},
@ -239,39 +227,11 @@ process_item_set(From, To, {xmlelement, _Name, Attrs, Els}) ->
Item2 = process_item_els(Item1, Els),
case Item2#roster.subscription of
remove ->
ejabberd_odbc:sql_query_t(
["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"]),
ejabberd_odbc:sql_query_t(
["delete from rostergroups "
" where username='", Username, "' "
" and jid='", SJID, "';"]);
odbc_queries:del_roster(LServer, Username, SJID);
_ ->
ItemVals = record_to_string(Item2),
ItemGroups = groups_to_string(Item2),
ejabberd_odbc:sql_query_t(
["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"]),
ejabberd_odbc:sql_query_t(
["insert into rosterusers("
" username, jid, nick, "
" subscription, ask, "
" askmessage, server, "
" subscribe, type) "
" values ", ItemVals, ";"]),
ejabberd_odbc:sql_query_t(
["delete from rostergroups "
" where username='", Username, "' "
" and jid='", SJID, "';"]),
lists:foreach(fun(ItemGroup) ->
ejabberd_odbc:sql_query_t(
["insert into rostergroups("
" username, jid, grp) "
" values ", ItemGroup, ";"])
end,
ItemGroups)
odbc_queries:update_roster(LServer, Username, SJID, ItemVals, ItemGroups)
end,
%% If the item exist in shared roster, take the
%% subscription information from there:
@ -279,7 +239,7 @@ process_item_set(From, To, {xmlelement, _Name, Attrs, Els}) ->
LServer, Item2, [LServer]),
{Item, Item3}
end,
case ejabberd_odbc:sql_transaction(LServer, F) of
case odbc_queries:sql_transaction(LServer, F) of
{atomic, {OldItem, Item}} ->
push_item(User, LServer, To, Item),
case Item#roster.subscription of
@ -411,11 +371,7 @@ get_subscription_lists(_, User, Server) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
Username = ejabberd_odbc:escape(LUser),
case catch ejabberd_odbc:sql_query(
LServer,
["select username, jid, nick, subscription, ask, "
"askmessage, server, subscribe, type from rosterusers "
"where username='", Username, "'"]) of
case catch odbc_queries:get_roster(LServer, Username) of
{selected, ["username", "jid", "nick", "subscription", "ask",
"askmessage", "server", "subscribe", "type"],
Items} when is_list(Items) ->
@ -460,22 +416,14 @@ process_subscription(Direction, User, Server, JID1, Type, Reason) ->
SJID = ejabberd_odbc:escape(jlib:jid_to_string(LJID)),
F = fun() ->
Item =
case ejabberd_odbc:sql_query_t(
["select username, jid, nick, subscription, ask, "
"askmessage, server, subscribe, type "
"from rosterusers "
"where username='", Username, "' "
"and jid='", SJID, "';"]) of
case odbc_queries:get_roster_by_jid(LServer, Username, SJID) of
{selected,
["username", "jid", "nick", "subscription", "ask",
"askmessage", "server", "subscribe", "type"],
[I]} ->
R = raw_to_record(LServer, I),
Groups =
case ejabberd_odbc:sql_query_t(
["select grp from rostergroups "
"where username='", Username, "' "
"and jid='", SJID, "';"]) of
case odbc_queries:get_roster_groups(LServer, Username, SJID) of
{selected, ["grp"], JGrps} when is_list(JGrps) ->
[JGrp || {JGrp} <- JGrps];
_ ->
@ -521,21 +469,11 @@ process_subscription(Direction, User, Server, JID1, Type, Reason) ->
ask = Pending,
askmessage = AskMessage},
ItemVals = record_to_string(NewItem),
ejabberd_odbc:sql_query_t(
["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"]),
ejabberd_odbc:sql_query_t(
["insert into rosterusers("
" username, jid, nick, "
" subscription, ask, "
" askmessage, server, subscribe, "
" type) "
" values ", ItemVals, ";"]),
odbc_queries:roster_subscribe(LServer, Username, SJID, ItemVals),
{{push, NewItem}, AutoReply}
end
end,
case ejabberd_odbc:sql_transaction(LServer, F) of
case odbc_queries:sql_transaction(LServer, F) of
{atomic, {Push, AutoReply}} ->
case AutoReply of
none ->
@ -662,16 +600,7 @@ remove_user(User, Server) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
Username = ejabberd_odbc:escape(LUser),
ejabberd_odbc:sql_transaction(
LServer,
fun() ->
ejabberd_odbc:sql_query_t(
["delete from rosterusers "
" where username='", Username, "';"]),
ejabberd_odbc:sql_query_t(
["delete from rostergroups "
" where username='", Username, "';"])
end),
odbc_queries:del_user_roster_t(LServer, Username),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -680,7 +609,7 @@ set_items(User, Server, SubEl) ->
{xmlelement, _Name, _Attrs, Els} = SubEl,
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
catch ejabberd_odbc:transaction(
catch odbc_queries:transaction(
LServer,
lists:map(fun(El) ->
process_item_set_t(LUser, LServer, El)
@ -703,31 +632,11 @@ process_item_set_t(LUser, LServer, {xmlelement, _Name, Attrs, Els}) ->
Item2 = process_item_els(Item1, Els),
case Item2#roster.subscription of
remove ->
[["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"],
["delete from rostergroups "
" where username='", Username, "' "
" and jid='", SJID, "';"]];
odbc_queries:del_roster_sql(Username, SJID);
_ ->
ItemVals = record_to_string(Item1),
ItemGroups = groups_to_string(Item2),
[["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"],
["insert into rosterusers("
" username, jid, nick, "
" subscription, ask, "
" askmessage, server, subscribe, "
" type) "
" values ", ItemVals, ";"],
["delete from rostergroups "
" where username='", Username, "' "
" and jid='", SJID, "';"],
[["insert into rostergroups("
" username, jid, grp) "
" values ", ItemGroup, ";"] ||
ItemGroup <- ItemGroups]]
odbc_queries:update_roster_sql(Username, SJID, ItemVals, ItemGroups)
end
end;
process_item_set_t(_LUser, _LServer, _) ->
@ -773,34 +682,24 @@ process_item_attrs_ws(Item, [{Attr, Val} | Attrs]) ->
process_item_attrs_ws(Item, []) ->
Item.
get_in_pending_subscriptions(Ls, User, Server) ->
JID = jlib:make_jid(User, Server, ""),
LUser = JID#jid.luser,
LServer = JID#jid.lserver,
Username = ejabberd_odbc:escape(LUser),
case catch ejabberd_odbc:sql_query(
LServer,
["select username, jid, nick, subscription, ask, "
"askmessage, server, subscribe, type from rosterusers "
"where username='", Username, "'"]) of
case catch odbc_queries:get_roster(LServer, Username) of
{selected, ["username", "jid", "nick", "subscription", "ask",
"askmessage", "server", "subscribe", "type"],
Items} when is_list(Items) ->
Ls ++ lists:map(
fun(R) ->
Message = R#roster.askmessage,
Status = if is_binary(Message) ->
binary_to_list(Message);
true ->
""
end,
{xmlelement, "presence",
[{"from", jlib:jid_to_string(R#roster.jid)},
{"to", jlib:jid_to_string(JID)},
{"type", "subscribe"}],
[{xmlelement, "status", [],
[{xmlcdata, Status}]}]}
[{xmlcdata, Message}]}]}
end,
lists:flatmap(
fun(I) ->
@ -825,11 +724,7 @@ get_jid_info(_, User, Server, JID) ->
LJID = jlib:jid_tolower(JID),
Username = ejabberd_odbc:escape(LUser),
SJID = ejabberd_odbc:escape(jlib:jid_to_string(LJID)),
case catch ejabberd_odbc:sql_query(
LServer,
["select subscription from rosterusers "
"where username='", Username, "' "
"and jid='", SJID, "'"]) of
case catch odbc_queries:get_subscription(LServer, Username, SJID) of
{selected, ["subscription"], [{SSubscription}]} ->
Subscription = case SSubscription of
"B" -> both;
@ -837,11 +732,7 @@ get_jid_info(_, User, Server, JID) ->
"F" -> from;
_ -> none
end,
Groups = case catch ejabberd_odbc:sql_query(
LServer,
["select grp from rostergroups "
"where username='", Username, "' "
"and jid='", SJID, "'"]) of
Groups = case catch odbc_queries:get_roster_group_by_jid(LServer, Username, SJID) of
{selected, ["grp"], JGrps} when is_list(JGrps) ->
[JGrp || {JGrp} <- JGrps];
_ ->
@ -855,11 +746,7 @@ get_jid_info(_, User, Server, JID) ->
{none, []};
true ->
SRJID = ejabberd_odbc:escape(jlib:jid_to_string(LRJID)),
case catch ejabberd_odbc:sql_query(
LServer,
["select subscription from rosterusers "
"where username='", Username, "' "
"and jid='", SRJID, "'"]) of
case catch odbc_queries:get_subscription(LServer, Username, SRJID) of
{selected, ["subscription"], [{SSubscription}]} ->
Subscription = case SSubscription of
"B" -> both;
@ -867,11 +754,7 @@ get_jid_info(_, User, Server, JID) ->
"F" -> from;
_ -> none
end,
Groups = case catch ejabberd_odbc:sql_query(
LServer,
["select grp from rostergroups "
"where username='", Username, "' "
"and jid='", SRJID, "'"]) of
Groups = case catch odbc_queries:get_rostergroup_by_jid(LServer, Username, SRJID) of
{selected, ["grp"], JGrps} when is_list(JGrps) ->
[JGrp || {JGrp} <- JGrps];
_ ->
@ -939,22 +822,26 @@ record_to_string(#roster{us = {User, _Server},
in -> "I";
none -> "N"
end,
["("
"'", Username, "',"
["'", Username, "',"
"'", SJID, "',"
"'", Nick, "',"
"'", SSubscription, "',"
"'", SAsk, "',"
"'", AskMessage, "',"
"'N', '', 'item')"].
"'N', '', 'item'"].
groups_to_string(#roster{us = {User, _Server},
jid = JID,
groups = Groups}) ->
Username = ejabberd_odbc:escape(User),
SJID = ejabberd_odbc:escape(jlib:jid_to_string(jlib:jid_tolower(JID))),
[["("
"'", Username, "',"
"'", SJID, "',"
"'", ejabberd_odbc:escape(Group), "')"] || Group <- Groups].
%% Empty groups do not need to be converted to string to be inserted in
%% the database
lists:foldl(fun([], Acc) -> Acc;
(Group, Acc) ->
String = ["'", Username, "',"
"'", SJID, "',"
"'", ejabberd_odbc:escape(Group), "'"],
[String|Acc] end, [], Groups).

View File

@ -13,12 +13,13 @@ OUTDIR = ..
EFLAGS = -I .. -pz ..
OBJS = \
$(OUTDIR)/ejabberd_odbc.beam \
$(OUTDIR)/ejabberd_odbc_sup.beam
$(OUTDIR)/ejabberd_odbc_sup.beam \
$(OUTDIR)/odbc_queries.beam
all: $(OBJS)
$(OUTDIR)/%.beam: %.erl
@ERLC@ -W $(EFLAGS) -o $(OUTDIR) $<
@ERLC@ -W $(EFLAGS) -D@db_type@ -o $(OUTDIR) $<
clean:

View File

@ -6,7 +6,8 @@ EFLAGS = -I .. -pz ..
OBJS = \
$(OUTDIR)\ejabberd_odbc.beam \
$(OUTDIR)\ejabberd_odbc_sup.beam
$(OUTDIR)\ejabberd_odbc_sup.beam \
$(OUTDIR)\odbc_queries.beam
ALL : $(OBJS)
@ -18,3 +19,7 @@ $(OUTDIR)\ejabberd_odbc.beam : ejabberd_odbc.erl
$(OUTDIR)\ejabberd_odbc_sup.beam : ejabberd_odbc_sup.erl
erlc -W $(EFLAGS) -o $(OUTDIR) ejabberd_odbc_sup.erl
$(OUTDIR)\odbc_queries.beam : odbc_queries.erl
erlc -W $(EFLAGS) -o $(OUTDIR) -D$(DBTYPE) odbc_queries.erl

View File

@ -87,16 +87,7 @@ sql_query_t(Query) ->
%% Escape character that will confuse an SQL engine
escape(S) when is_list(S) ->
[escape(C) || C <- S];
escape($\0) -> "\\0";
escape($\n) -> "\\n";
escape($\t) -> "\\t";
escape($\b) -> "\\b";
escape($\r) -> "\\r";
escape($') -> "\\'";
escape($") -> "\\\"";
escape($\\) -> "\\\\";
escape(C) -> C.
[odbc_queries:escape(C) || C <- S].
%% Escape character that will confuse an SQL engine
%% Percent and underscore only need to be escaped for pattern matching like
@ -105,7 +96,7 @@ escape_like(S) when is_list(S) ->
[escape_like(C) || C <- S];
escape_like($%) -> "\\%";
escape_like($_) -> "\\_";
escape_like(C) -> escape(C).
escape_like(C) -> odbc_queries:escape(C).
%%%----------------------------------------------------------------------

901
src/odbc/mssql.sql Normal file
View File

@ -0,0 +1,901 @@
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
exec sp_dboption N'ejabberd', N'autoclose', N'false'
GO
exec sp_dboption N'ejabberd', N'bulkcopy', N'true'
GO
exec sp_dboption N'ejabberd', N'trunc. log', N'false'
GO
exec sp_dboption N'ejabberd', N'torn page detection', N'true'
GO
exec sp_dboption N'ejabberd', N'read only', N'false'
GO
exec sp_dboption N'ejabberd', N'dbo use', N'false'
GO
exec sp_dboption N'ejabberd', N'single', N'false'
GO
exec sp_dboption N'ejabberd', N'autoshrink', N'false'
GO
exec sp_dboption N'ejabberd', N'ANSI null default', N'false'
GO
exec sp_dboption N'ejabberd', N'recursive triggers', N'false'
GO
exec sp_dboption N'ejabberd', N'ANSI nulls', N'false'
GO
exec sp_dboption N'ejabberd', N'concat null yields null', N'false'
GO
exec sp_dboption N'ejabberd', N'cursor close on commit', N'false'
GO
exec sp_dboption N'ejabberd', N'default to local cursor', N'false'
GO
exec sp_dboption N'ejabberd', N'quoted identifier', N'false'
GO
exec sp_dboption N'ejabberd', N'ANSI warnings', N'false'
GO
exec sp_dboption N'ejabberd', N'auto create statistics', N'true'
GO
exec sp_dboption N'ejabberd', N'auto update statistics', N'true'
GO
use [ejabberd]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[last]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[last]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[rostergroups]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[rostergroups]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[rosterusers]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[rosterusers]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[spool]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[spool]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[users]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[users]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[vcard]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[vcard]
GO
CREATE TABLE [dbo].[last] (
[username] [varchar] (250) NOT NULL ,
[seconds] [varchar] (50) NOT NULL ,
[state] [varchar] (100) NULL ,
[Modify_Date] [datetime] NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[rostergroups] (
[username] [varchar] (250) NOT NULL ,
[jid] [varchar] (250) NOT NULL ,
[grp] [varchar] (100) NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[rosterusers] (
[username] [varchar] (250) NOT NULL ,
[jid] [varchar] (250) NOT NULL ,
[nick] [varchar] (50) NULL ,
[subscription] [char] (1) NOT NULL ,
[ask] [char] (1) NOT NULL ,
[askmessage] [varchar] (250) NULL ,
[server] [char] (1) NOT NULL ,
[subscribe] [varchar] (200) NULL ,
[type] [varchar] (50) NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[spool] (
[id] [numeric](19, 0) IDENTITY (1, 1) NOT NULL ,
[username] [varchar] (250) NOT NULL ,
[xml] [text] NULL ,
[notifyprocessed] [bit] NULL ,
[created] [datetime] NULL ,
[MustDelete] [bit] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE TABLE [dbo].[users] (
[username] [varchar] (250) NOT NULL ,
[password] [varchar] (50) NOT NULL ,
[created] [datetime] NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[vcard] (
[username] [varchar] (250) NOT NULL ,
[full_name] [varchar] (250) NULL ,
[first_name] [varchar] (50) NULL ,
[last_name] [varchar] (50) NULL ,
[nick_name] [varchar] (50) NULL ,
[url] [varchar] (1024) NULL ,
[address1] [varchar] (50) NULL ,
[address2] [varchar] (50) NULL ,
[locality] [varchar] (50) NULL ,
[region] [varchar] (50) NULL ,
[pcode] [varchar] (50) NULL ,
[country] [varchar] (50) NULL ,
[telephone] [varchar] (50) NULL ,
[email] [varchar] (250) NULL ,
[orgname] [varchar] (50) NULL ,
[orgunit] [varchar] (50) NULL ,
[title] [varchar] (50) NULL ,
[role] [varchar] (50) NULL ,
[b_day] [datetime] NULL ,
[descr] [varchar] (500) NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[last] WITH NOCHECK ADD
CONSTRAINT [PK_last] PRIMARY KEY CLUSTERED
(
[username]
) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
ALTER TABLE [dbo].[rostergroups] WITH NOCHECK ADD
CONSTRAINT [PK_rostergroups] PRIMARY KEY CLUSTERED
(
[username],
[jid],
[grp]
) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
ALTER TABLE [dbo].[spool] WITH NOCHECK ADD
CONSTRAINT [PK_spool] PRIMARY KEY CLUSTERED
(
[username],
[id]
) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
ALTER TABLE [dbo].[users] WITH NOCHECK ADD
CONSTRAINT [PK_users] PRIMARY KEY CLUSTERED
(
[username]
) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
ALTER TABLE [dbo].[vcard] WITH NOCHECK ADD
CONSTRAINT [PK_vcard] PRIMARY KEY CLUSTERED
(
[username]
) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE CLUSTERED INDEX [IX_rosterusers_user] ON [dbo].[rosterusers]([username]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
ALTER TABLE [dbo].[last] WITH NOCHECK ADD
CONSTRAINT [DF_last_updated] DEFAULT (getdate()) FOR [Modify_Date]
GO
ALTER TABLE [dbo].[spool] WITH NOCHECK ADD
CONSTRAINT [DF_spool_notifyprocessed] DEFAULT (0) FOR [notifyprocessed],
CONSTRAINT [DF_spool_created] DEFAULT (getdate()) FOR [created],
CONSTRAINT [DF_spool_MustDelete] DEFAULT (0) FOR [MustDelete]
GO
ALTER TABLE [dbo].[users] WITH NOCHECK ADD
CONSTRAINT [DF_users_created] DEFAULT (getdate()) FOR [created]
GO
CREATE INDEX [IX_rostergroups_jid] ON [dbo].[rostergroups]([jid]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IX_rostergroups_user] ON [dbo].[rostergroups]([username]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IX_rosterusers_jid] ON [dbo].[rosterusers]([username], [jid]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IX_spool_user] ON [dbo].[spool]([username]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IX_spool_process] ON [dbo].[spool]([created], [notifyprocessed]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IK_Spool_Del] ON [dbo].[spool]([MustDelete]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IK_Spool_Created] ON [dbo].[spool]([created]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
/*********************************************************/
/** These store procedures are for use with ejabberd **/
/** 1.1 and Microsoft Sql Server 2000 **/
/** **/
/** The stored procedures reduce the need to sql **/
/** compilation of the database and also allow for also **/
/** provide each of database integration. The store **/
/** procedure have been optimized to increase database **/
/** performance and a reduction of 80% in CPU was **/
/** achive over the use of standard sql. **/
/*********************************************************/
/****** Object: StoredProcedure [dbo].[add_roster] ******/
/** Add or update user entries in the roster **/
/*********************************************************/
CREATE PROCEDURE [dbo].[add_roster]
@Username varchar(250),
@JID varchar(250),
@Nick varchar(50),
@Subscription char(1),
@Ask char(1),
@AskMessage varchar(250),
@Server char(1),
@Subscribe varchar(200),
@Type varchar(50),
@Grp varchar(100)
AS
BEGIN
BEGIN TRANSACTION
--- Update Roster if user exist else add roster item
IF EXISTS (SELECT username FROM rosterusers WITH (NOLOCK) WHERE rosterusers.username=@Username AND rosterusers.jid=@JID)
BEGIN
UPDATE rosterusers
SET rosterusers.username=@Username,
rosterusers.jid=@JID,
rosterusers.nick=@Nick,
rosterusers.subscription=@Subscription,
rosterusers.ask=@Ask,
rosterusers.askmessage=@AskMessage,
rosterusers.server=@Server,
rosterusers.subscribe=@Subscribe,
rosterusers.type=@Type
WHERE (rosterusers.username=@Username) AND (rosterusers.jid=@JID);
END
ELSE
BEGIN
INSERT INTO rosterusers
( rosterusers.username,
rosterusers.jid,
rosterusers.nick,
rosterusers.subscription,
rosterusers.ask,
rosterusers.askmessage,
rosterusers.server,
rosterusers.subscribe,
rosterusers.type
)
VALUES
( @Username,
@JID,
@Nick,
@Subscription,
@Ask,
@AskMessage,
@Server,
@Subscribe,
@Type
);
END
--- Update Roster Groups if exist else add group entry
IF NOT EXISTS (SELECT username FROM rostergroups WITH (NOLOCK) WHERE rostergroups.username=@Username AND rostergroups.jid=@JID AND rostergroups.grp=@Grp)
BEGIN
INSERT INTO rostergroups
( rostergroups.username,
rostergroups.jid,
rostergroups.grp
)
VALUES
( @Username,
@JID,
@Grp
);
END
COMMIT
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[add_roster_group] ******/
/** Add or update user group entries in the roster groups **/
/***************************************************************/
CREATE PROCEDURE [dbo].[add_roster_group]
@Username varchar(250),
@JID varchar(250),
@Grp varchar(100)
AS
BEGIN
--- Update Roster Groups if exist else add group
IF NOT EXISTS (SELECT username FROM rostergroups WHERE rostergroups.username=@Username AND rostergroups.jid=@JID AND rostergroups.grp=@Grp)
BEGIN
INSERT INTO rostergroups
( rostergroups.username,
rostergroups.jid,
rostergroups.grp
)
VALUES
( @Username,
@JID,
@Grp
)
END
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[add_roster_user] ******/
/** Add or update user entries in the roster **/
/***************************************************************/
CREATE PROCEDURE [dbo].[add_roster_user]
@Username varchar(250),
@JID varchar(250),
@Nick varchar(50),
@Subscription char(1),
@Ask char(1),
@AskMessage varchar(250),
@Server char(1),
@Subscribe varchar(200),
@Type varchar(50),
@Grp varchar(100) = Null
AS
BEGIN
BEGIN TRANSACTION
--- Update Roster Users if exist of add new user
IF EXISTS (SELECT username FROM rosterusers WHERE rosterusers.username=@Username AND rosterusers.jid=@JID)
BEGIN
UPDATE rosterusers
SET rosterusers.username=@Username,
rosterusers.jid=@JID,
rosterusers.nick=@Nick,
rosterusers.subscription=@Subscription,
rosterusers.ask=@Ask,
rosterusers.askmessage=@AskMessage,
rosterusers.server=@Server,
rosterusers.subscribe=@Subscribe,
rosterusers.type=@Type
WHERE (rosterusers.username=@Username) AND (rosterusers.jid=@JID);
END
ELSE
BEGIN
INSERT INTO rosterusers
( rosterusers.username,
rosterusers.jid,
rosterusers.nick,
rosterusers.subscription,
rosterusers.ask,
rosterusers.askmessage,
rosterusers.server,
rosterusers.subscribe,
rosterusers.type
)
VALUES
( @Username,
@JID,
@Nick,
@Subscription,
@Ask,
@AskMessage,
@Server,
@Subscribe,
@Type
);
END
--- Update Roster Group if exist of add new group
IF @Grp IS NOT NULL
EXECUTE [dbo].[add_roster_group] @Username, @JID, @Grp
COMMIT
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[del_roster_groups] ******/
/** Remove user group entries from the roster groups table **/
/***************************************************************/
CREATE PROCEDURE [dbo].[del_roster_groups]
@Username varchar(250),
@JID varchar(250)
AS
BEGIN
DELETE FROM rostergroups
WITH (ROWLOCK)
WHERE (rostergroups.username = @Username) AND (rostergroups.jid = @JID);
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[add_spool] ******/
/** Add a entry to the spool table **/
/***************************************************************/
CREATE PROCEDURE [dbo].[add_spool]
@Username varchar(250),
@XML varchar(8000)
AS
BEGIN
INSERT INTO spool
( spool.username,
spool.xml
)
VALUES
( @Username,
@XML
)
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[add_user] ******/
/** Add or update user entries to jabber **/
/***************************************************************/
CREATE PROCEDURE [dbo].[add_user]
@Username varchar(200),
@Password varchar(50)
AS
BEGIN
INSERT INTO users
( username,
[password]
)
VALUES
( @Username,
@Password
);
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[set_password] **/
/** Update users password **/
/******************************************************************/
CREATE PROCEDURE [dbo].[set_password]
@Username varchar(200),
@Password varchar(50)
AS
BEGIN
IF EXISTS (SELECT username FROM users WITH (NOLOCK) WHERE username=@Username)
BEGIN
UPDATE users SET username=@Username, password=@Password WHERE username=@Username;
END
ELSE
BEGIN
INSERT INTO users (username, password) VALUES (@Username, @Password);
END
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[get_password] **/
/** Retrive the user password **/
/******************************************************************/
CREATE PROCEDURE [dbo].[get_password]
@Username varchar(200)
AS
BEGIN
SELECT users.password as password
FROM users WITH (NOLOCK)
WHERE username=@Username;
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[clean_spool_msg] ******/
/** Delete messages older that 3 days from spool **/
/***************************************************************/
CREATE PROCEDURE [dbo].[clean_spool_msg]
AS
DECLARE
@dt datetime,
@myRowCount int
BEGIN
-- Delete small amounts because if locks the database table
SET ROWCOUNT 500
SET @myRowCount = 1
WHILE (@myRowCount) > 0
BEGIN
BEGIN TRANSACTION
SELECT @dt = DATEADD(d, -3, GETDATE())
DELETE FROM spool
WITH (ROWLOCK)
WHERE (MustDelete=1) OR (Created < @dt);
SET @myRowCount = @@RowCount
COMMIT
END
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[del_last] ******/
/** Delete an entry from the last table **/
/***************************************************************/
CREATE PROCEDURE [dbo].[del_last]
@Username varchar(250)
AS
BEGIN
DELETE FROM [last]
WITH (ROWLOCK)
WHERE [last].username=@Username;
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[del_roster] ******/
/** Delete an entry from the roster **/
/***************************************************************/
CREATE PROCEDURE [dbo].[del_roster]
@Username varchar(250),
@JID varchar(250)
AS
BEGIN
BEGIN TRANSACTION
DELETE FROM rosterusers
WITH (ROWLOCK)
WHERE (rosterusers.username = @Username) AND (rosterusers.jid = @JID);
DELETE FROM rostergroups
WITH (ROWLOCK)
WHERE (rostergroups.username = @Username) AND (rostergroups.jid = @JID);
COMMIT
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[del_spool_msg] ******/
/** Delete an entry from the spool table **/
/***************************************************************/
CREATE PROCEDURE [dbo].[del_spool_msg]
@Username varchar(250)
AS
BEGIN
DELETE FROM spool
WITH (ROWLOCK)
WHERE spool.username=@Username;
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[del_user] ******/
/** Delete an entry from the user table **/
/***************************************************************/
CREATE PROCEDURE [dbo].[del_user]
@Username varchar(200)
AS
BEGIN
DELETE FROM users
WITH (ROWLOCK)
WHERE username=@Username;
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[del_user_return_password]**/
/** Delete an entry from the user table and return user password **/
/******************************************************************/
CREATE PROCEDURE [dbo].[del_user_return_password]
@Username varchar(250)
AS
DECLARE
@Pwd varchar(50)
BEGIN
EXECUTE @Pwd = dbo.get_password @Username
DELETE FROM users
WITH (ROWLOCK)
WHERE username=@Username
SELECT @Pwd;
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[del_user_roster] **/
/** Delete the users roster **/
/******************************************************************/
CREATE PROCEDURE [dbo].[del_user_roster]
@Username varchar(250)
AS
BEGIN
BEGIN TRANSACTION
DELETE FROM rosterusers
WITH (ROWLOCK)
WHERE rosterusers.username = @Username;
DELETE FROM rostergroups
WITH (ROWLOCK)
WHERE rostergroups.username = @Username;
COMMIT
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[get_and_del_spool_msg] **/
/** Fetch and delete the users offline messages **/
/******************************************************************/
CREATE PROCEDURE [dbo].[get_and_del_spool_msg]
@Username varchar(250)
AS
DECLARE
@vSpool table( username varchar(1),
xml varchar(1))
BEGIN
IF EXISTS (SELECT username FROM spool with (nolock) WHERE spool.username=@Username)
BEGIN
SELECT spool.username AS username,
spool.xml AS xml
FROM spool WITH (NOLOCK)
WHERE spool.username=@Username;
DELETE spool
WITH (ROWLOCK)
WHERE spool.username=@Username
END
ELSE
BEGIN
SELECT * FROM @vSpool;
END
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[get_last] **/
/** Retrive the last user login **/
/******************************************************************/
CREATE PROCEDURE [dbo].[get_last]
@Username varchar(250)
AS
BEGIN
SELECT last.seconds AS seconds,
last.state AS state
FROM last WITH (NOLOCK)
WHERE last.username=@Username;
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[get_roster] **/
/** Retrive the user roster **/
/******************************************************************/
CREATE PROCEDURE [dbo].[get_roster]
@Username varchar(200)
AS
DECLARE
@vRosterusers table( username varchar(1),
jid varchar(1),
nick varchar(1),
subscription varchar(1),
ask varchar(1),
askmessage varchar(1),
server varchar(1),
subscribe varchar(1),
type varchar(1))
BEGIN
IF EXISTS (SELECT username FROM rosterusers with (nolock) WHERE rosterusers.username = @Username)
BEGIN
SELECT rosterusers.username AS username,
rosterusers.jid AS jid,
rosterusers.nick AS nick,
rosterusers.subscription AS subscription,
rosterusers.ask AS ask,
rosterusers.askmessage AS askmessage,
rosterusers.server AS server,
rosterusers.subscribe AS subscribe,
rosterusers.type AS type
FROM rosterusers WITH (NOLOCK)
WHERE rosterusers.username = @Username;
END
ELSE
BEGIN
SELECT * FROM @vRosterusers
END
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[get_roster_by_jid] **/
/** Retrive the user roster via JID **/
/******************************************************************/
CREATE PROCEDURE [dbo].[get_roster_by_jid]
@Username varchar(200),
@JID varchar(250)
AS
DECLARE
@vRosterusers table( username varchar(1),
jid varchar(1),
nick varchar(1),
subscription varchar(1),
ask varchar(1),
askmessage varchar(1),
server varchar(1),
subscribe varchar(1),
type varchar(1))
BEGIN
IF EXISTS (SELECT username FROM rosterusers with (nolock) WHERE (rosterusers.username = @Username) AND (rosterusers.jid = @JID))
BEGIN
SELECT rosterusers.username AS username,
rosterusers.jid AS jid,
rosterusers.nick AS nick,
rosterusers.subscription AS subscription,
rosterusers.ask AS ask,
rosterusers.askmessage AS askmessage,
rosterusers.server AS server,
rosterusers.subscribe AS subscribe,
rosterusers.type AS type
FROM rosterusers WITH (NOLOCK)
WHERE (rosterusers.username = @Username) AND (rosterusers.jid = @JID);
END
ELSE
BEGIN
SELECT * FROM @vRosterusers
END
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[get_roster_jid_groups] **/
/** Retrieve the user roster groups **/
/******************************************************************/
CREATE PROCEDURE [dbo].[get_roster_jid_groups]
@Username varchar(200)
AS
DECLARE
@vrostergroups table( jid varchar(1),
grp varchar(1))
BEGIN
IF EXISTS (SELECT username FROM rostergroups with (nolock) WHERE rostergroups.username = @Username)
BEGIN
SELECT rostergroups.jid AS jid,
rostergroups.grp AS grp
FROM rostergroups WITH (NOLOCK)
WHERE rostergroups.username = @Username;
END
ELSE
BEGIN
SELECT * FROM @vrostergroups
END
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[get_roster_groups] **/
/** Retrive the user roster groups **/
/******************************************************************/
CREATE PROCEDURE [dbo].[get_roster_groups]
@Username varchar(200),
@JID varchar(250)
AS
DECLARE
@vrostergroups table( grp varchar(1))
BEGIN
IF EXISTS (SELECT username FROM rostergroups with (nolock) WHERE rostergroups.username = @Username)
BEGIN
SELECT rostergroups.grp AS grp
FROM rostergroups WITH (NOLOCK)
WHERE (rostergroups.username = @Username) AND (rostergroups.jid = @JID);
END
ELSE
BEGIN
SELECT * FROM @vrostergroups
END
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[get_rostergroup_by_jid] **/
/** Retrive the user roster groups via JID **/
/******************************************************************/
CREATE PROCEDURE [dbo].[get_rostergroup_by_jid]
@Username varchar(250),
@JID varchar(250)
AS
DECLARE
@vrostergroups table(grp varchar(1))
BEGIN
IF EXISTS (SELECT username FROM rostergroups with (nolock) WHERE rostergroups.username=@Username AND rostergroups.jid=@JID)
BEGIN
SELECT rostergroups.grp AS grp
FROM rostergroups WITH (NOLOCK)
WHERE rostergroups.username=@Username AND rostergroups.jid=@JID;
END
ELSE
BEGIN
SELECT * FROM @vrostergroups
END
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[get_subscription] **/
/** Retrive the user subscription requests **/
/******************************************************************/
CREATE PROCEDURE [dbo].[get_subscription]
@Username varchar(250),
@JID varchar(250)
AS
DECLARE
@vrosterusers table( subscription varchar(1))
BEGIN
IF EXISTS (SELECT username FROM rosterusers with (nolock) WHERE rosterusers.username=@Username AND rosterusers.jid=@JID)
BEGIN
SELECT rosterusers.subscription AS subscription
FROM rosterusers WITH (NOLOCK)
WHERE rosterusers.username=@Username AND rosterusers.jid=@JID;
END
ELSE
BEGIN
SELECT * FROM @vrosterusers
END
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[list_users] **/
/** Retrive a list of all users **/
/******************************************************************/
CREATE PROCEDURE [dbo].[list_users]
AS
BEGIN
SELECT users.username AS username FROM users WITH (NOLOCK);
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[set_last] **/
/** Update users last login status **/
/******************************************************************/
CREATE PROCEDURE [dbo].[set_last]
@Username varchar(250),
@Seconds varchar(50),
@State varchar(100)
AS
BEGIN
IF EXISTS (SELECT username FROM [last] WITH (NOLOCK) WHERE username=@Username)
BEGIN
UPDATE [last]
SET [last].username = @Username,
[last].seconds = @Seconds,
[last].state = @State
WHERE last.username=@Username;
END
ELSE
BEGIN
INSERT INTO [last]
( [last].username,
[last].seconds,
[last].state
)
VALUES
( @Username,
@Seconds,
@State
)
END
END
GO

434
src/odbc/odbc_queries.erl Normal file
View File

@ -0,0 +1,434 @@
%% Copyrigh 2006, Process-one
%% This module is intended to take into account relational databases behaviour
%% differences
-module(odbc_queries).
-author("mickael.remond@process-one.net").
-export([get_db_type/0,
sql_transaction/2,
get_last/2,
set_last_t/4,
del_last/2,
get_password/2,
set_password_t/3,
add_user/3,
del_user/2,
del_user_return_password/3,
list_users/1,
add_spool_sql/2,
add_spool/2,
get_and_del_spool_msg_t/2,
del_spool_msg/2,
get_roster/2,
get_roster_jid_groups/2,
get_roster_groups/3,
del_user_roster_t/2,
get_roster_by_jid/3,
get_rostergroup_by_jid/3,
del_roster/3,
del_roster_sql/2,
update_roster/5,
update_roster_sql/4,
roster_subscribe/4,
get_subscription/3,
escape/1]).
%-define(generic, true).
%-define(mssql, true).
%% -----------------
%% Generic queries
-ifdef(generic).
get_db_type() ->
generic.
sql_transaction(LServer, F) ->
ejabberd_odbc:sql_transaction(LServer, F).
get_last(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["select seconds, state from last "
"where username='", Username, "'"]).
set_last_t(LServer, Username, Seconds, State) ->
%% MREMOND: I think this should be turn into a non transactional behaviour
ejabberd_odbc:sql_transaction(
LServer,
[["delete from last where username='", Username, "';"],
["insert into last(username, seconds, state) "
"values ('", Username, "', '", Seconds, "', '", State, "');"]]).
del_last(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["delete from last where username='", Username, "'"]).
get_password(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["select password from users "
"where username='", Username, "';"]).
set_password_t(LServer, Username, Pass) ->
ejabberd_odbc:sql_transaction(
LServer,
[["delete from users where username='", Username ,"';"],
["insert into users(username, password) "
"values ('", Username, "', '", Pass, "');"]]).
add_user(LServer, Username, Pass) ->
ejabberd_odbc:sql_query(
LServer,
["insert into users(username, password) "
"values ('", Username, "', '", Pass, "');"]).
del_user(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["delete from users where username='", Username ,"';"]).
del_user_return_password(_LServer, Username, Pass) ->
ejabberd_odbc:sql_query_t(
["select password from users where username='",
Username, "';"]),
ejabberd_odbc:sql_query_t(["delete from users "
"where username='", Username,
"' and password='", Pass, "';"]).
list_users(LServer) ->
ejabberd_odbc:sql_query(
LServer,
"select username from users").
add_spool_sql(Username, XML) ->
["insert into spool(username, xml) "
"values ('", Username, "', '",
XML,
"');"].
add_spool(LServer, Queries) ->
ejabberd_odbc:sql_transaction(
LServer, Queries).
get_and_del_spool_msg_t(LServer, Username) ->
F = fun() ->
Result = ejabberd_odbc:sql_query_t(
["select username, xml from spool where username='", Username, "'"
" order by seq;"]),
ejabberd_odbc:sql_query_t(
["delete from spool where username='", Username, "';"]),
Result
end,
ejabberd_odbc:sql_transaction(LServer,F).
del_spool_msg(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["delete from spool where username='", Username, "';"]).
get_roster(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["select username, jid, nick, subscription, ask, "
"askmessage, server, subscribe, type from rosterusers "
"where username='", Username, "'"]).
get_roster_jid_groups(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["select jid, grp from rostergroups "
"where username='", Username, "'"]).
get_roster_groups(_LServer, Username, SJID) ->
ejabberd_odbc:sql_query_t(
["select grp from rostergroups "
"where username='", Username, "' "
"and jid='", SJID, "';"]).
del_user_roster_t(LServer, Username) ->
ejabberd_odbc:sql_transaction(
LServer,
fun() ->
ejabberd_odbc:sql_query_t(
["delete from rosterusers "
" where username='", Username, "';"]),
ejabberd_odbc:sql_query_t(
["delete from rostergroups "
" where username='", Username, "';"])
end).
get_roster_by_jid(_LServer, Username, SJID) ->
ejabberd_odbc:sql_query_t(
["select username, jid, nick, subscription, "
"ask, askmessage, server, subscribe, type from rosterusers "
"where username='", Username, "' "
"and jid='", SJID, "';"]).
get_rostergroup_by_jid(LServer, Username, SJID) ->
ejabberd_odbc:sql_query(
LServer,
["select grp from rostergroups "
"where username='", Username, "' "
"and jid='", SJID, "'"]).
del_roster(_LServer, Username, SJID) ->
ejabberd_odbc:sql_query_t(
["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"]),
ejabberd_odbc:sql_query_t(
["delete from rostergroups "
" where username='", Username, "' "
" and jid='", SJID, "';"]).
del_roster_sql(Username, SJID) ->
[["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"],
["delete from rostergroups "
" where username='", Username, "' "
" and jid='", SJID, "';"]].
update_roster(_LServer, Username, SJID, ItemVals, ItemGroups) ->
ejabberd_odbc:sql_query_t(
["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"]),
ejabberd_odbc:sql_query_t(
["insert into rosterusers("
" username, jid, nick, "
" subscription, ask, askmessage, "
" server, subscribe, type) "
" values (", ItemVals, ");"]),
ejabberd_odbc:sql_query_t(
["delete from rostergroups "
" where username='", Username, "' "
" and jid='", SJID, "';"]),
lists:foreach(fun(ItemGroup) ->
ejabberd_odbc:sql_query_t(
["insert into rostergroups("
" username, jid, grp) "
" values (", ItemGroup, ");"])
end,
ItemGroups).
update_roster_sql(Username, SJID, ItemVals, ItemGroups) ->
[["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"],
["insert into rosterusers("
" username, jid, nick, "
" subscription, ask, askmessage"
" server, subscribe, type) "
" values (", ItemVals, ");"],
["delete from rostergroups "
" where username='", Username, "' "
" and jid='", SJID, "';"],
[["insert into rostergroups("
" username, jid, grp) "
" values (", ItemGroup, ");"] ||
ItemGroup <- ItemGroups]].
roster_subscribe(_LServer, Username, SJID, ItemVals) ->
ejabberd_odbc:sql_query_t(
["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"]),
ejabberd_odbc:sql_query_t(
["insert into rosterusers("
" username, jid, nick, "
" subscription, ask, askmessage, "
" server, subscribe, type) "
" values (", ItemVals, ");"]).
get_subscription(LServer, Username, SJID) ->
ejabberd_odbc:sql_query(
LServer,
["select subscription from rosterusers "
"where username='", Username, "' "
"and jid='", SJID, "'"]).
%% Characters to escape
escape($\0) -> "\\0";
escape($\n) -> "\\n";
escape($\t) -> "\\t";
escape($\b) -> "\\b";
escape($\r) -> "\\r";
escape($') -> "\\'";
escape($") -> "\\\"";
escape($\\) -> "\\\\";
escape(C) -> C.
-endif.
%% -----------------
%% MSSQL queries
-ifdef(mssql).
get_db_type() ->
mssql.
sql_transaction(_LServer, F) ->
{atomic, catch F()}.
get_last(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.get_last '", Username, "'"]).
set_last_t(LServer, Username, Seconds, State) ->
Result = ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.set_last '", Username, "', '", Seconds,
"', '", State, "'"]),
{atomic, Result}.
del_last(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.del_last '", Username, "'"]).
get_password(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.get_password '", Username, "'"]).
set_password_t(LServer, Username, Pass) ->
Result = ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.set_password '", Username, "', '", Pass, "'"]),
{atomic, Result}.
add_user(LServer, Username, Pass) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.add_user '", Username, "', '", Pass, "'"]).
del_user(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.del_user '", Username ,"'"]).
del_user_return_password(LServer, Username, Pass) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.del_user_return_password '", Username, "'"]),
Pass.
list_users(LServer) ->
ejabberd_odbc:sql_query(
LServer,
"EXECUTE dbo.list_users").
add_spool_sql(Username, XML) ->
["EXECUTE dbo.add_spool '", Username, "' , '",XML,"'"].
add_spool(LServer, Queries) ->
lists:foreach(fun(Query) ->
ejabberd_odbc:sql_query(LServer, Query)
end,
Queries).
get_and_del_spool_msg_t(LServer, Username) ->
[Result] = case ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.get_and_del_spool_msg '", Username, "'"]) of
Rs when list(Rs) ->
lists:filter(fun({selected, _Header, _Row}) ->
true;
({updated, _N}) ->
false
end,
Rs);
Rs -> [Rs]
end,
{atomic, Result}.
del_spool_msg(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.del_spool_msg '", Username, "'"]).
get_roster(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.get_roster '", Username, "'"]).
get_roster_jid_groups(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.get_roster_jid_groups '", Username, "'"]).
get_roster_groups(LServer, Username, SJID) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.get_roster_groups '", Username, "' , '", SJID, "'"]).
del_user_roster_t(LServer, Username) ->
Result = ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.del_user_roster '", Username, "'"]),
{atomic, Result}.
get_roster_by_jid(LServer, Username, SJID) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.get_roster_by_jid '", Username, "' , '", SJID, "'"]).
get_rostergroup_by_jid(LServer, Username, SJID) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.get_rostergroup_by_jid '", Username, "' , '", SJID, "'"]).
del_roster(LServer, Username, SJID) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.del_roster '", Username, "', '", SJID, "'"]).
del_roster_sql(Username, SJID) ->
["EXECUTE dbo.del_roster '", Username, "', '", SJID, "'"].
update_roster(LServer, Username, SJID, ItemVals, ItemGroups) ->
Query1 = ["EXECUTE dbo.del_roster '", Username, "', '", SJID, "' "],
ejabberd_odbc:sql_query(LServer, lists:flatten(Query1)),
Query2 = ["EXECUTE dbo.add_roster_user ", ItemVals],
ejabberd_odbc:sql_query(LServer, lists:flatten(Query2)),
Query3 = ["EXECUTE dbo.del_roster_groups '", Username, "', '", SJID, "' "],
ejabberd_odbc:sql_query(LServer, lists:flatten(Query3)),
lists:foreach(fun(ItemGroup) ->
Query = ["EXECUTE dbo.add_roster_group ",
ItemGroup],
ejabberd_odbc:sql_query(LServer,
lists:flatten(Query))
end,
ItemGroups).
update_roster_sql(Username, SJID, ItemVals, ItemGroups) ->
["BEGIN TRANSACTION ",
"EXECUTE dbo.del_roster_groups '", Username, "','", SJID, "' ",
"EXECUTE dbo.add_roster_user ", ItemVals, " "] ++
[lists:flatten("EXECUTE dbo.add_roster_group ", ItemGroup, " ")
|| ItemGroup <- ItemGroups] ++
["COMMIT"].
roster_subscribe(LServer, _Username, _SJID, ItemVals) ->
catch ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.add_roster_user ", ItemVals]).
get_subscription(LServer, Username, SJID) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.get_subscription '", Username, "' , '", SJID, "'"]).
%% Characters to escape
escape($\0) -> "\\0";
escape($\t) -> "\\t";
escape($\b) -> "\\b";
escape($\r) -> "\\r";
escape($') -> "\''";
escape($") -> "\\\"";
escape(C) -> C.
-endif.

View File

@ -18,7 +18,7 @@ CREATE TABLE rosterusers (
nick text,
subscription character(1) NOT NULL,
ask character(1) NOT NULL,
askmessage text NOT NULL,
askmessage text,
server character(1) NOT NULL,
subscribe text,
"type" text