2015-12-15 16:11:29 +01:00
|
|
|
%%%----------------------------------------------------------------------
|
2016-04-20 11:27:32 +02:00
|
|
|
%%% File : pubsub_db_sql.erl
|
2015-12-15 16:11:29 +01:00
|
|
|
%%% Author : Pablo Polvorin <pablo.polvorin@process-one.net>
|
|
|
|
%%% Purpose : Provide helpers for PubSub ODBC backend
|
|
|
|
%%% Created : 7 Aug 2009 by Pablo Polvorin <pablo.polvorin@process-one.net>
|
2009-08-07 10:26:47 +02:00
|
|
|
%%%
|
|
|
|
%%%
|
2021-01-27 16:55:25 +01:00
|
|
|
%%% ejabberd, Copyright (C) 2002-2021 ProcessOne
|
2009-08-07 10:26:47 +02:00
|
|
|
%%%
|
2015-12-15 16:11:29 +01:00
|
|
|
%%% This program is free software; you can redistribute it and/or
|
|
|
|
%%% modify it under the terms of the GNU General Public License as
|
|
|
|
%%% published by the Free Software Foundation; either version 2 of the
|
|
|
|
%%% License, or (at your option) any later version.
|
|
|
|
%%%
|
|
|
|
%%% This program is distributed in the hope that it will be useful,
|
|
|
|
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
%%% General Public License for more details.
|
|
|
|
%%%
|
|
|
|
%%% You should have received a copy of the GNU General Public License along
|
|
|
|
%%% with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
%%%
|
|
|
|
%%%----------------------------------------------------------------------
|
|
|
|
|
2016-04-20 11:27:32 +02:00
|
|
|
-module(pubsub_db_sql).
|
2013-03-14 10:33:02 +01:00
|
|
|
|
2017-08-03 15:34:01 +02:00
|
|
|
|
2009-08-07 10:26:47 +02:00
|
|
|
-author("pablo.polvorin@process-one.net").
|
|
|
|
|
|
|
|
-include("pubsub.hrl").
|
2017-08-03 15:34:01 +02:00
|
|
|
-include("ejabberd_sql_pt.hrl").
|
2009-08-07 10:26:47 +02:00
|
|
|
|
2013-03-14 10:33:02 +01:00
|
|
|
-export([add_subscription/1, read_subscription/1,
|
2015-04-08 17:12:05 +02:00
|
|
|
delete_subscription/1, update_subscription/1]).
|
2017-08-03 15:34:01 +02:00
|
|
|
-export([export/1]).
|
2009-08-07 10:26:47 +02:00
|
|
|
|
2020-12-18 20:26:11 +01:00
|
|
|
-spec read_subscription(SubID :: mod_pubsub:subId()) -> {ok, #pubsub_subscription{}} | notfound.
|
2009-08-07 10:26:47 +02:00
|
|
|
read_subscription(SubID) ->
|
2013-03-14 10:33:02 +01:00
|
|
|
case
|
2019-12-16 04:52:06 +01:00
|
|
|
ejabberd_sql:sql_query_t(
|
|
|
|
?SQL("select @(opt_name)s, @(opt_value)s from pubsub_subscription_opt where subid = %(SubID)s"))
|
2015-04-08 17:12:05 +02:00
|
|
|
of
|
2019-12-16 04:52:06 +01:00
|
|
|
{selected, []} ->
|
2015-04-08 17:12:05 +02:00
|
|
|
notfound;
|
2019-12-16 04:52:06 +01:00
|
|
|
{selected, Options} ->
|
2015-04-08 17:12:05 +02:00
|
|
|
{ok,
|
|
|
|
#pubsub_subscription{subid = SubID,
|
2016-04-20 11:27:32 +02:00
|
|
|
options = lists:map(fun subscription_opt_from_sql/1, Options)}}
|
2013-03-14 10:33:02 +01:00
|
|
|
end.
|
2009-08-07 10:26:47 +02:00
|
|
|
|
2020-12-18 20:26:11 +01:00
|
|
|
-spec delete_subscription(SubID :: mod_pubsub:subId()) -> ok.
|
2009-08-07 10:26:47 +02:00
|
|
|
delete_subscription(SubID) ->
|
2019-12-16 04:52:06 +01:00
|
|
|
ejabberd_sql:sql_query_t(
|
|
|
|
?SQL("delete from pubsub_subscription_opt "
|
|
|
|
"where subid = %(SubID)s")),
|
2013-03-14 10:33:02 +01:00
|
|
|
ok.
|
|
|
|
|
2020-06-02 21:20:50 +02:00
|
|
|
-spec update_subscription(#pubsub_subscription{}) -> ok .
|
2015-04-08 17:12:05 +02:00
|
|
|
update_subscription(#pubsub_subscription{subid = SubId} = Sub) ->
|
2013-03-14 10:33:02 +01:00
|
|
|
delete_subscription(SubId), add_subscription(Sub).
|
|
|
|
|
2020-06-02 21:20:50 +02:00
|
|
|
-spec add_subscription(#pubsub_subscription{}) -> ok.
|
2015-04-08 17:12:05 +02:00
|
|
|
add_subscription(#pubsub_subscription{subid = SubId, options = Opts}) ->
|
2019-12-16 04:52:06 +01:00
|
|
|
lists:foreach(
|
|
|
|
fun(Opt) ->
|
|
|
|
{OdbcOptName, OdbcOptValue} = subscription_opt_to_sql(Opt),
|
|
|
|
ejabberd_sql:sql_query_t(
|
|
|
|
?SQL("insert into pubsub_subscription_opt(subid, "
|
|
|
|
"opt_name, opt_value) values "
|
|
|
|
"(%(SubId)s, %(OdbcOptName)s, %(OdbcOptValue)s)"))
|
|
|
|
end,
|
|
|
|
Opts),
|
2013-03-14 10:33:02 +01:00
|
|
|
ok.
|
|
|
|
|
2019-12-16 04:52:06 +01:00
|
|
|
subscription_opt_from_sql({<<"DELIVER">>, Value}) ->
|
2016-04-20 11:27:32 +02:00
|
|
|
{deliver, sql_to_boolean(Value)};
|
2019-12-16 04:52:06 +01:00
|
|
|
subscription_opt_from_sql({<<"DIGEST">>, Value}) ->
|
2016-04-20 11:27:32 +02:00
|
|
|
{digest, sql_to_boolean(Value)};
|
2019-12-16 04:52:06 +01:00
|
|
|
subscription_opt_from_sql({<<"DIGEST_FREQUENCY">>, Value}) ->
|
2016-04-20 11:27:32 +02:00
|
|
|
{digest_frequency, sql_to_integer(Value)};
|
2019-12-16 04:52:06 +01:00
|
|
|
subscription_opt_from_sql({<<"EXPIRE">>, Value}) ->
|
2016-04-20 11:27:32 +02:00
|
|
|
{expire, sql_to_timestamp(Value)};
|
2019-12-16 04:52:06 +01:00
|
|
|
subscription_opt_from_sql({<<"INCLUDE_BODY">>, Value}) ->
|
2016-04-20 11:27:32 +02:00
|
|
|
{include_body, sql_to_boolean(Value)};
|
2009-08-07 10:26:47 +02:00
|
|
|
%%TODO: might be > than 1 show_values value??.
|
|
|
|
%% need to use compact all in only 1 opt.
|
2019-12-16 04:52:06 +01:00
|
|
|
subscription_opt_from_sql({<<"SHOW_VALUES">>, Value}) ->
|
2013-03-14 10:33:02 +01:00
|
|
|
{show_values, Value};
|
2019-12-16 04:52:06 +01:00
|
|
|
subscription_opt_from_sql({<<"SUBSCRIPTION_TYPE">>, Value}) ->
|
2013-03-14 10:33:02 +01:00
|
|
|
{subscription_type,
|
2015-04-08 17:12:05 +02:00
|
|
|
case Value of
|
|
|
|
<<"items">> -> items;
|
|
|
|
<<"nodes">> -> nodes
|
|
|
|
end};
|
2019-12-16 04:52:06 +01:00
|
|
|
subscription_opt_from_sql({<<"SUBSCRIPTION_DEPTH">>, Value}) ->
|
2013-03-14 10:33:02 +01:00
|
|
|
{subscription_depth,
|
2015-04-08 17:12:05 +02:00
|
|
|
case Value of
|
|
|
|
<<"all">> -> all;
|
2016-04-20 11:27:32 +02:00
|
|
|
N -> sql_to_integer(N)
|
2015-04-08 17:12:05 +02:00
|
|
|
end}.
|
2009-08-07 10:26:47 +02:00
|
|
|
|
2016-04-20 11:27:32 +02:00
|
|
|
subscription_opt_to_sql({deliver, Bool}) ->
|
|
|
|
{<<"DELIVER">>, boolean_to_sql(Bool)};
|
|
|
|
subscription_opt_to_sql({digest, Bool}) ->
|
|
|
|
{<<"DIGEST">>, boolean_to_sql(Bool)};
|
|
|
|
subscription_opt_to_sql({digest_frequency, Int}) ->
|
|
|
|
{<<"DIGEST_FREQUENCY">>, integer_to_sql(Int)};
|
|
|
|
subscription_opt_to_sql({expire, Timestamp}) ->
|
|
|
|
{<<"EXPIRE">>, timestamp_to_sql(Timestamp)};
|
|
|
|
subscription_opt_to_sql({include_body, Bool}) ->
|
|
|
|
{<<"INCLUDE_BODY">>, boolean_to_sql(Bool)};
|
|
|
|
subscription_opt_to_sql({show_values, Values}) ->
|
2013-03-14 10:33:02 +01:00
|
|
|
{<<"SHOW_VALUES">>, Values};
|
2016-04-20 11:27:32 +02:00
|
|
|
subscription_opt_to_sql({subscription_type, Type}) ->
|
2013-03-14 10:33:02 +01:00
|
|
|
{<<"SUBSCRIPTION_TYPE">>,
|
2015-04-08 17:12:05 +02:00
|
|
|
case Type of
|
|
|
|
items -> <<"items">>;
|
|
|
|
nodes -> <<"nodes">>
|
|
|
|
end};
|
2016-04-20 11:27:32 +02:00
|
|
|
subscription_opt_to_sql({subscription_depth, Depth}) ->
|
2013-03-14 10:33:02 +01:00
|
|
|
{<<"SUBSCRIPTION_DEPTH">>,
|
2015-04-08 17:12:05 +02:00
|
|
|
case Depth of
|
|
|
|
all -> <<"all">>;
|
2016-04-20 11:27:32 +02:00
|
|
|
N -> integer_to_sql(N)
|
2015-04-08 17:12:05 +02:00
|
|
|
end}.
|
2009-08-07 10:26:47 +02:00
|
|
|
|
2016-11-24 13:06:06 +01:00
|
|
|
integer_to_sql(N) -> integer_to_binary(N).
|
2013-03-14 10:33:02 +01:00
|
|
|
|
2016-04-20 11:27:32 +02:00
|
|
|
boolean_to_sql(true) -> <<"1">>;
|
|
|
|
boolean_to_sql(false) -> <<"0">>.
|
2009-08-07 10:26:47 +02:00
|
|
|
|
2016-11-13 08:44:53 +01:00
|
|
|
timestamp_to_sql(T) -> xmpp_util:encode_timestamp(T).
|
2009-08-07 10:26:47 +02:00
|
|
|
|
2016-09-24 22:34:28 +02:00
|
|
|
sql_to_integer(N) -> binary_to_integer(N).
|
2013-03-14 10:33:02 +01:00
|
|
|
|
2016-04-20 11:27:32 +02:00
|
|
|
sql_to_boolean(B) -> B == <<"1">>.
|
2009-08-07 10:26:47 +02:00
|
|
|
|
2016-11-13 08:44:53 +01:00
|
|
|
sql_to_timestamp(T) -> xmpp_util:decode_timestamp(T).
|
2017-08-03 15:34:01 +02:00
|
|
|
|
|
|
|
export(_Server) ->
|
2017-11-13 17:34:37 +01:00
|
|
|
[{pubsub_node,
|
|
|
|
fun(_Host, #pubsub_node{nodeid = {Host, Node}, id = Nidx,
|
|
|
|
parents = Parents, type = Type,
|
|
|
|
options = Options}) ->
|
|
|
|
H = node_flat_sql:encode_host(Host),
|
|
|
|
Parent = case Parents of
|
|
|
|
[] -> <<>>;
|
|
|
|
[First | _] -> First
|
|
|
|
end,
|
|
|
|
[?SQL("delete from pubsub_node where nodeid=%(Nidx)d;"),
|
|
|
|
?SQL("delete from pubsub_node_option where nodeid=%(Nidx)d;"),
|
|
|
|
?SQL("delete from pubsub_node_owner where nodeid=%(Nidx)d;"),
|
|
|
|
?SQL("delete from pubsub_state where nodeid=%(Nidx)d;"),
|
|
|
|
?SQL("delete from pubsub_item where nodeid=%(Nidx)d;"),
|
2018-01-19 13:10:14 +01:00
|
|
|
?SQL("insert into pubsub_node(host,node,nodeid,parent,plugin)"
|
2017-11-13 17:34:37 +01:00
|
|
|
" values (%(H)s, %(Node)s, %(Nidx)d, %(Parent)s, %(Type)s);")]
|
|
|
|
++ lists:map(
|
|
|
|
fun ({Key, Value}) ->
|
|
|
|
SKey = iolist_to_binary(atom_to_list(Key)),
|
|
|
|
SValue = misc:term_to_expr(Value),
|
|
|
|
?SQL("insert into pubsub_node_option(nodeid,name,val)"
|
|
|
|
" values (%(Nidx)d, %(SKey)s, %(SValue)s);")
|
|
|
|
end, Options);
|
|
|
|
(_Host, _R) ->
|
|
|
|
[]
|
|
|
|
end},
|
|
|
|
{pubsub_state,
|
|
|
|
fun(_Host, #pubsub_state{stateid = {JID, Nidx},
|
|
|
|
affiliation = Affiliation,
|
|
|
|
subscriptions = Subscriptions}) ->
|
|
|
|
J = jid:encode(JID),
|
|
|
|
S = node_flat_sql:encode_subscriptions(Subscriptions),
|
|
|
|
A = node_flat_sql:encode_affiliation(Affiliation),
|
|
|
|
[?SQL("insert into pubsub_state(nodeid,jid,affiliation,subscriptions)"
|
|
|
|
" values (%(Nidx)d, %(J)s, %(A)s, %(S)s);")];
|
|
|
|
(_Host, _R) ->
|
|
|
|
[]
|
|
|
|
end},
|
|
|
|
{pubsub_item,
|
|
|
|
fun(_Host, #pubsub_item{itemid = {ItemId, Nidx},
|
|
|
|
creation = {C, _},
|
|
|
|
modification = {M, JID},
|
|
|
|
payload = Payload}) ->
|
|
|
|
P = jid:encode(JID),
|
|
|
|
XML = str:join([fxml:element_to_binary(X) || X<-Payload], <<>>),
|
|
|
|
SM = encode_now(M),
|
|
|
|
SC = encode_now(C),
|
|
|
|
[?SQL("insert into pubsub_item(itemid,nodeid,creation,modification,publisher,payload)"
|
|
|
|
" values (%(ItemId)s, %(Nidx)d, %(SC)s, %(SM)s, %(P)s, %(XML)s);")];
|
|
|
|
(_Host, _R) ->
|
|
|
|
[]
|
|
|
|
end}].
|
|
|
|
|
|
|
|
encode_now({T1, T2, T3}) ->
|
|
|
|
<<(misc:i2l(T1, 6))/binary, ":",
|
|
|
|
(misc:i2l(T2, 6))/binary, ":",
|
|
|
|
(misc:i2l(T3, 6))/binary>>.
|