如何从 MongooseIM 模块 运行 查询
How to run queries from MongooseIM module
我正在尝试制作 MongooseIM 模块,它将以 offline_message_hook 触发,为用户计算离线存储中待处理消息的数量,并通过 GET 方法将其发送到 URL。下面是我的代码。
send_notice(From, To, Packet) ->
Type = xml:get_tag_attr_s(list_to_binary("type"), Packet),
Body = xml:get_path_s(Packet, [{elem, list_to_binary("body")}, cdata]),
PostUrl = "http://myurl.com/",
Count = count_msg(To),
GetParam = "?count=",
FullUrl = PostUrl ++ GetParam ++ Count,
?DEBUG("POST URL : ~s",[FullUrl]),
if (Type == <<"chat">>) and (Body /= <<"">>) ->
Sep = "&",
Post = [
"alert=", url_encode(binary_to_list(Body)), Sep,
"badge=", url_encode("+1"), Sep,
% "sound=", Sound, Sep,
"channel=", To#jid.luser, Sep,
"info[from]=", From#jid.luser, Sep],
% "auth_token=", Token],
?INFO_MSG("Sending post request to ~s with body \"~s\"", [FullUrl, Post]),
httpc:request(post, {binary_to_list(FullUrl), [], "application/x-www-form-urlencoded", list_to_binary(Post)},[],[]),
ok;
true ->
ok
end.
count_msg(To) ->
Username = To#jid.luser,
LServer = To#jid.lserver,
Count = ejabberd_odbc:sql_query(
LServer,
["select count(*) from offline_message "
"where username='", Username, "';"]),
?DEBUG("Count = ~s",[Count]),
Count.
当我 运行 它时,我得到以下错误
2015-03-09 16:37:11.598 [debug] <0.763.0>@mod_zeropush:count_msg:102 FORMAT ERROR: "Count = ~s" [{selected,[<<"count">>],[{<<"5">>}]}]
["select count(*) from offline_message where username='",<<"reader">>,"';"]
2015-03-09 16:37:11.599 [debug] <0.763.0>@mod_zeropush:send_notice:72 FORMAT ERROR: "POST URL : ~s" [[104,116,116,112,58,47,47,107,107,104,97,110,46,100,108,99,119,111,114,108,100,119,105,100,101,46,99,111,109,47,63,99,111,117,110,116,61|{selected,[<<"count">>],[{<<"5">>}]}]]
2015-03-09 16:37:11.599 [info] <0.763.0>@mod_zeropush:send_notice:84 FORMAT ERROR: "Sending post request to ~s with body \"~s\"" [[104,116,116,112,58,47,47,107,107,104,97,110,46,100,108,99,119,111,114,108,100,119,105,100,101,46,99,111,109,47,63,99,111,117,110,116,61|{selected,[<<"count">>],[{<<"5">>}]}],["alert=","xxx","&","badge=","%2B1","&","channel=",<<"reader">>,"&","info[from]=",<<"kkhan">>,"&"]]
2015-03-09 16:37:11.602 [error] <0.763.0>@ejabberd_hooks:run1:240 {badarg,[{erlang,binary_to_list,[[104,116,116,112,58,47,47,107,107,104,97,110,46,100,108,99,119,111,114,108,100,119,105,100,101,46,99,111,109,47,63,99,111,117,110,116,61|{selected,[<<"count">>],[{<<"5">>}]}]],[]},{mod_zeropush,send_notice,3,[{file,"src/mod_zeropush.erl"},{line,86}]},{safely,apply,3,[{file,"src/safely.erl"},{line,19}]},{ejabberd_hooks,run1,3,[{file,"src/ejabberd_hooks.erl"},{line,236}]},{ejabberd_sm,route,3,[{file,"src/ejabberd_sm.erl"},{line,108}]},{ejabberd_local,route,3,[{file,"src/ejabberd_local.erl"},{line,139}]},{ejabberd_router,route,3,[{file,"src/ejabberd_router.erl"},{line,78}]},{ejabberd_c2s,session_established2,2,[{file,"src/ejabberd_c2s.erl"},{line,1098}]}]}
在 erlang 中获取 SQL 查询结果的正确方法是什么? httpc:request 期望什么格式?
您得到的错误不完全是 SQL 或 MongooseIM 特定的错误。它们是 io_lib:format/2
或类似字符串格式化函数的错误使用。
这个错误:
2015-03-09 16:37:11.598 [debug] <0.763.0>@mod_zeropush:count_msg:102 FORMAT ERROR: "Count = ~s" [{selected,[<<"count">>],[{<<"5">>}]}]
涉及:
?DEBUG("Count = ~s", [Count])
但是 Count
既不是字符串,也不是二进制,也不是 iolist,也不是原子(只有这些类型可以使用 ~s
- 字符串格式化字符打印;参考 man io
function format/3
).
要使用默认的 Erlang 术语语法打印复杂术语,请使用 ~p
或 ~w
.
你所有的 FORMAT ERROR
错误都是这种类型 - 你为你传入的数据类型使用了错误的格式说明符。
好的,那么SQL查询结果的格式是什么?它打印在错误行之一中:
{selected, [<<"count">>], [{<<"5">>}]}
这是您在 SQL shell 中得到的简单音译(这个例子来自我在 PostgreSQL 中随机 table ):
> SELECT count(*) FROM conversation_state;
count
-------
2
(1 row)
这是来自 Erlang shell 的等效 运行:
> ejabberd_odbc:sql_query(<<"localhost">>, ["SELECT count(*) FROM conversation_state;"]).
{selected,[<<"count">>],[{<<"2">>}]}
所以结果总是一个三元组;第一个元素是 selected
(或 inserted
、updated
... 取决于查询);第二个元素是 headers 列的列表(这里只有一列 count
);第三个元素是一个元组列表,其中每个元组对应于结果集中的一行。 rows-as-tuples 的元素与列 headers.
的顺序相同
关于上一个错误:
2015-03-09 16:37:11.602 [error] <0.763.0>@ejabberd_hooks:run1:240 {badarg,[{erlang,binary_to_list,[[104,116,116,112,58,47,47,107,107,104,97,110,46,100,108,99,119,111,114,108,100,119,105,100,101,46,99,111,109,47,63,99,111,117,110,116,61|{selected,[<<"count">>],[{<<"5">>}]}]],[]},{mod_zeropush,send_notice,3,[{file,"src/mod_zeropush.erl"},{line,86}]},{safely,apply,3,[{file,"src/safely.erl"},{line,19}]},{ejabberd_hooks,run1,3,[{file,"src/ejabberd_hooks.erl"},{line,236}]},{ejabberd_sm,route,3,[{file,"src/ejabberd_sm.erl"},{line,108}]},{ejabberd_local,route,3,[{file,"src/ejabberd_local.erl"},{line,139}]},{ejabberd_router,route,3,[{file,"src/ejabberd_router.erl"},{line,78}]},{ejabberd_c2s,session_established2,2,[{file,"src/ejabberd_c2s.erl"},{line,1098}]}]}
您正在尝试将使用 FullUrl = PostUrl ++ GetParam ++ Count
创建的列表传递给 erlang:binary_to_list/1
。顾名思义,此函数接受二进制文件,而不是列表。 Erlang 是 动态的,但是强类型的 并且几乎没有隐式类型转换。正确解压缩 SQL 查询的结果,return 只是来自 count_msg
的数字,并从中构建 HTTP 请求 URL。
我正在尝试制作 MongooseIM 模块,它将以 offline_message_hook 触发,为用户计算离线存储中待处理消息的数量,并通过 GET 方法将其发送到 URL。下面是我的代码。
send_notice(From, To, Packet) ->
Type = xml:get_tag_attr_s(list_to_binary("type"), Packet),
Body = xml:get_path_s(Packet, [{elem, list_to_binary("body")}, cdata]),
PostUrl = "http://myurl.com/",
Count = count_msg(To),
GetParam = "?count=",
FullUrl = PostUrl ++ GetParam ++ Count,
?DEBUG("POST URL : ~s",[FullUrl]),
if (Type == <<"chat">>) and (Body /= <<"">>) ->
Sep = "&",
Post = [
"alert=", url_encode(binary_to_list(Body)), Sep,
"badge=", url_encode("+1"), Sep,
% "sound=", Sound, Sep,
"channel=", To#jid.luser, Sep,
"info[from]=", From#jid.luser, Sep],
% "auth_token=", Token],
?INFO_MSG("Sending post request to ~s with body \"~s\"", [FullUrl, Post]),
httpc:request(post, {binary_to_list(FullUrl), [], "application/x-www-form-urlencoded", list_to_binary(Post)},[],[]),
ok;
true ->
ok
end.
count_msg(To) ->
Username = To#jid.luser,
LServer = To#jid.lserver,
Count = ejabberd_odbc:sql_query(
LServer,
["select count(*) from offline_message "
"where username='", Username, "';"]),
?DEBUG("Count = ~s",[Count]),
Count.
当我 运行 它时,我得到以下错误
2015-03-09 16:37:11.598 [debug] <0.763.0>@mod_zeropush:count_msg:102 FORMAT ERROR: "Count = ~s" [{selected,[<<"count">>],[{<<"5">>}]}]
["select count(*) from offline_message where username='",<<"reader">>,"';"]
2015-03-09 16:37:11.599 [debug] <0.763.0>@mod_zeropush:send_notice:72 FORMAT ERROR: "POST URL : ~s" [[104,116,116,112,58,47,47,107,107,104,97,110,46,100,108,99,119,111,114,108,100,119,105,100,101,46,99,111,109,47,63,99,111,117,110,116,61|{selected,[<<"count">>],[{<<"5">>}]}]]
2015-03-09 16:37:11.599 [info] <0.763.0>@mod_zeropush:send_notice:84 FORMAT ERROR: "Sending post request to ~s with body \"~s\"" [[104,116,116,112,58,47,47,107,107,104,97,110,46,100,108,99,119,111,114,108,100,119,105,100,101,46,99,111,109,47,63,99,111,117,110,116,61|{selected,[<<"count">>],[{<<"5">>}]}],["alert=","xxx","&","badge=","%2B1","&","channel=",<<"reader">>,"&","info[from]=",<<"kkhan">>,"&"]]
2015-03-09 16:37:11.602 [error] <0.763.0>@ejabberd_hooks:run1:240 {badarg,[{erlang,binary_to_list,[[104,116,116,112,58,47,47,107,107,104,97,110,46,100,108,99,119,111,114,108,100,119,105,100,101,46,99,111,109,47,63,99,111,117,110,116,61|{selected,[<<"count">>],[{<<"5">>}]}]],[]},{mod_zeropush,send_notice,3,[{file,"src/mod_zeropush.erl"},{line,86}]},{safely,apply,3,[{file,"src/safely.erl"},{line,19}]},{ejabberd_hooks,run1,3,[{file,"src/ejabberd_hooks.erl"},{line,236}]},{ejabberd_sm,route,3,[{file,"src/ejabberd_sm.erl"},{line,108}]},{ejabberd_local,route,3,[{file,"src/ejabberd_local.erl"},{line,139}]},{ejabberd_router,route,3,[{file,"src/ejabberd_router.erl"},{line,78}]},{ejabberd_c2s,session_established2,2,[{file,"src/ejabberd_c2s.erl"},{line,1098}]}]}
在 erlang 中获取 SQL 查询结果的正确方法是什么? httpc:request 期望什么格式?
您得到的错误不完全是 SQL 或 MongooseIM 特定的错误。它们是 io_lib:format/2
或类似字符串格式化函数的错误使用。
这个错误:
2015-03-09 16:37:11.598 [debug] <0.763.0>@mod_zeropush:count_msg:102 FORMAT ERROR: "Count = ~s" [{selected,[<<"count">>],[{<<"5">>}]}]
涉及:
?DEBUG("Count = ~s", [Count])
但是 Count
既不是字符串,也不是二进制,也不是 iolist,也不是原子(只有这些类型可以使用 ~s
- 字符串格式化字符打印;参考 man io
function format/3
).
要使用默认的 Erlang 术语语法打印复杂术语,请使用 ~p
或 ~w
.
你所有的 FORMAT ERROR
错误都是这种类型 - 你为你传入的数据类型使用了错误的格式说明符。
好的,那么SQL查询结果的格式是什么?它打印在错误行之一中:
{selected, [<<"count">>], [{<<"5">>}]}
这是您在 SQL shell 中得到的简单音译(这个例子来自我在 PostgreSQL 中随机 table ):
> SELECT count(*) FROM conversation_state;
count
-------
2
(1 row)
这是来自 Erlang shell 的等效 运行:
> ejabberd_odbc:sql_query(<<"localhost">>, ["SELECT count(*) FROM conversation_state;"]).
{selected,[<<"count">>],[{<<"2">>}]}
所以结果总是一个三元组;第一个元素是 selected
(或 inserted
、updated
... 取决于查询);第二个元素是 headers 列的列表(这里只有一列 count
);第三个元素是一个元组列表,其中每个元组对应于结果集中的一行。 rows-as-tuples 的元素与列 headers.
关于上一个错误:
2015-03-09 16:37:11.602 [error] <0.763.0>@ejabberd_hooks:run1:240 {badarg,[{erlang,binary_to_list,[[104,116,116,112,58,47,47,107,107,104,97,110,46,100,108,99,119,111,114,108,100,119,105,100,101,46,99,111,109,47,63,99,111,117,110,116,61|{selected,[<<"count">>],[{<<"5">>}]}]],[]},{mod_zeropush,send_notice,3,[{file,"src/mod_zeropush.erl"},{line,86}]},{safely,apply,3,[{file,"src/safely.erl"},{line,19}]},{ejabberd_hooks,run1,3,[{file,"src/ejabberd_hooks.erl"},{line,236}]},{ejabberd_sm,route,3,[{file,"src/ejabberd_sm.erl"},{line,108}]},{ejabberd_local,route,3,[{file,"src/ejabberd_local.erl"},{line,139}]},{ejabberd_router,route,3,[{file,"src/ejabberd_router.erl"},{line,78}]},{ejabberd_c2s,session_established2,2,[{file,"src/ejabberd_c2s.erl"},{line,1098}]}]}
您正在尝试将使用 FullUrl = PostUrl ++ GetParam ++ Count
创建的列表传递给 erlang:binary_to_list/1
。顾名思义,此函数接受二进制文件,而不是列表。 Erlang 是 动态的,但是强类型的 并且几乎没有隐式类型转换。正确解压缩 SQL 查询的结果,return 只是来自 count_msg
的数字,并从中构建 HTTP 请求 URL。