mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
Improve compatibility with various db engine versions
This commit is contained in:
parent
4247501dc6
commit
d4bf29e3ff
@ -41,6 +41,7 @@
|
|||||||
server_host_used = false,
|
server_host_used = false,
|
||||||
used_vars = [],
|
used_vars = [],
|
||||||
use_new_schema,
|
use_new_schema,
|
||||||
|
need_timestamp_pass = false,
|
||||||
need_array_pass = false}).
|
need_array_pass = false}).
|
||||||
|
|
||||||
-define(QUERY_RECORD, "sql_query").
|
-define(QUERY_RECORD, "sql_query").
|
||||||
@ -169,17 +170,24 @@ transform_sql(Arg) ->
|
|||||||
Pos, no_server_host),
|
Pos, no_server_host),
|
||||||
[]
|
[]
|
||||||
end,
|
end,
|
||||||
case ParseRes#state.need_array_pass of
|
case {ParseRes#state.need_array_pass, ParseRes#state.need_timestamp_pass} of
|
||||||
true ->
|
{true, _} ->
|
||||||
{PR1, PR2} = perform_array_pass(ParseRes),
|
{PR1, PR2} = perform_array_pass(ParseRes),
|
||||||
{PRO1, PRO2} = perform_array_pass(ParseResOld),
|
{PRO1, PRO2} = perform_array_pass(ParseResOld),
|
||||||
set_pos(make_schema_check(
|
set_pos(make_schema_check(
|
||||||
erl_syntax:list([erl_syntax:tuple([erl_syntax:atom(pgsql), make_sql_query(PR2)]),
|
erl_syntax:list([erl_syntax:tuple([erl_syntax:atom(pgsql), make_sql_query(PR2, pgsql)]),
|
||||||
erl_syntax:tuple([erl_syntax:atom(any), make_sql_query(PR1)])]),
|
erl_syntax:tuple([erl_syntax:atom(any), make_sql_query(PR1)])]),
|
||||||
erl_syntax:list([erl_syntax:tuple([erl_syntax:atom(pgsql), make_sql_query(PRO2)]),
|
erl_syntax:list([erl_syntax:tuple([erl_syntax:atom(pgsql), make_sql_query(PRO2, pgsql)]),
|
||||||
erl_syntax:tuple([erl_syntax:atom(any), make_sql_query(PRO1)])])),
|
erl_syntax:tuple([erl_syntax:atom(any), make_sql_query(PRO1)])])),
|
||||||
Pos);
|
Pos);
|
||||||
false ->
|
{_, true} ->
|
||||||
|
set_pos(make_schema_check(
|
||||||
|
erl_syntax:list([erl_syntax:tuple([erl_syntax:atom(pgsql), make_sql_query(ParseRes, pgsql)]),
|
||||||
|
erl_syntax:tuple([erl_syntax:atom(any), make_sql_query(ParseRes)])]),
|
||||||
|
erl_syntax:list([erl_syntax:tuple([erl_syntax:atom(pgsql), make_sql_query(ParseResOld, pgsql)]),
|
||||||
|
erl_syntax:tuple([erl_syntax:atom(any), make_sql_query(ParseResOld)])])),
|
||||||
|
Pos);
|
||||||
|
_ ->
|
||||||
set_pos(
|
set_pos(
|
||||||
make_schema_check(
|
make_schema_check(
|
||||||
make_sql_query(ParseRes),
|
make_sql_query(ParseRes),
|
||||||
@ -265,6 +273,8 @@ parse1([$@, $( | S], Acc, State) ->
|
|||||||
[EVar]);
|
[EVar]);
|
||||||
string ->
|
string ->
|
||||||
EVar;
|
EVar;
|
||||||
|
timestamp ->
|
||||||
|
EVar;
|
||||||
boolean ->
|
boolean ->
|
||||||
erl_syntax:application(
|
erl_syntax:application(
|
||||||
erl_syntax:atom(ejabberd_sql),
|
erl_syntax:atom(ejabberd_sql),
|
||||||
@ -295,7 +305,7 @@ parse1([$%, $( | S], Acc, State) ->
|
|||||||
erl_syntax:atom(?ESCAPE_RECORD),
|
erl_syntax:atom(?ESCAPE_RECORD),
|
||||||
erl_syntax:atom(string)),
|
erl_syntax:atom(string)),
|
||||||
[erl_syntax:variable(Name)]),
|
[erl_syntax:variable(Name)]),
|
||||||
State3#state{'query' = [{var, Var},
|
State3#state{'query' = [{var, Var, Type},
|
||||||
{str, "server_host="} |
|
{str, "server_host="} |
|
||||||
State3#state.'query'],
|
State3#state.'query'],
|
||||||
args = [Convert | State3#state.args],
|
args = [Convert | State3#state.args],
|
||||||
@ -327,21 +337,26 @@ parse1([$%, $( | S], Acc, State) ->
|
|||||||
erl_syntax:atom(?ESCAPE_RECORD),
|
erl_syntax:atom(?ESCAPE_RECORD),
|
||||||
erl_syntax:atom(IT2)),
|
erl_syntax:atom(IT2)),
|
||||||
erl_syntax:variable(Name)]),
|
erl_syntax:variable(Name)]),
|
||||||
State2#state{'query' = [[{var, Var}] | State2#state.'query'],
|
State2#state{'query' = [[{var, Var, Type}] | State2#state.'query'],
|
||||||
need_array_pass = true,
|
need_array_pass = true,
|
||||||
args = [[Convert, ConvertArr] | State2#state.args],
|
args = [[Convert, ConvertArr] | State2#state.args],
|
||||||
params = [Var | State2#state.params],
|
params = [Var | State2#state.params],
|
||||||
param_pos = State2#state.param_pos + 1,
|
param_pos = State2#state.param_pos + 1,
|
||||||
used_vars = [Name | State2#state.used_vars]};
|
used_vars = [Name | State2#state.used_vars]};
|
||||||
_ ->
|
_ ->
|
||||||
|
{TS, Type2} = case Type of
|
||||||
|
timestamp -> {true, string};
|
||||||
|
Other -> {State2#state.need_timestamp_pass, Other}
|
||||||
|
end,
|
||||||
Convert =
|
Convert =
|
||||||
erl_syntax:application(
|
erl_syntax:application(
|
||||||
erl_syntax:record_access(
|
erl_syntax:record_access(
|
||||||
erl_syntax:variable(?ESCAPE_VAR),
|
erl_syntax:variable(?ESCAPE_VAR),
|
||||||
erl_syntax:atom(?ESCAPE_RECORD),
|
erl_syntax:atom(?ESCAPE_RECORD),
|
||||||
erl_syntax:atom(Type)),
|
erl_syntax:atom(Type2)),
|
||||||
[erl_syntax:variable(Name)]),
|
[erl_syntax:variable(Name)]),
|
||||||
State2#state{'query' = [{var, Var} | State2#state.'query'],
|
State2#state{'query' = [{var, Var, Type} | State2#state.'query'],
|
||||||
|
need_timestamp_pass = TS,
|
||||||
args = [Convert | State2#state.args],
|
args = [Convert | State2#state.args],
|
||||||
params = [Var | State2#state.params],
|
params = [Var | State2#state.params],
|
||||||
param_pos = State2#state.param_pos + 1,
|
param_pos = State2#state.param_pos + 1,
|
||||||
@ -359,7 +374,7 @@ parse1("%ESCAPE" ++ S, Acc, State) ->
|
|||||||
[]),
|
[]),
|
||||||
Var = State1#state.param_pos,
|
Var = State1#state.param_pos,
|
||||||
State2 =
|
State2 =
|
||||||
State1#state{'query' = [{var, Var} | State1#state.'query'],
|
State1#state{'query' = [{var, Var, string} | State1#state.'query'],
|
||||||
args = [Convert | State1#state.args],
|
args = [Convert | State1#state.args],
|
||||||
params = [Var | State1#state.params],
|
params = [Var | State1#state.params],
|
||||||
param_pos = State1#state.param_pos + 1},
|
param_pos = State1#state.param_pos + 1},
|
||||||
@ -397,6 +412,7 @@ parse_name([$), T | S], Acc, 0, IsArg, State) ->
|
|||||||
$d -> integer;
|
$d -> integer;
|
||||||
$s -> string;
|
$s -> string;
|
||||||
$b -> boolean;
|
$b -> boolean;
|
||||||
|
$t -> timestamp;
|
||||||
$H when IsArg -> host;
|
$H when IsArg -> host;
|
||||||
_ ->
|
_ ->
|
||||||
throw({error, State#state.loc,
|
throw({error, State#state.loc,
|
||||||
@ -420,10 +436,10 @@ make_var(V) ->
|
|||||||
|
|
||||||
perform_array_pass(State) ->
|
perform_array_pass(State) ->
|
||||||
{NQ, PQ, Rest} = lists:foldl(
|
{NQ, PQ, Rest} = lists:foldl(
|
||||||
fun([{var, _} = Var], {N, P, {str, Str} = Prev}) ->
|
fun([{var, _, _} = Var], {N, P, {str, Str} = Prev}) ->
|
||||||
Str2 = re:replace(Str, "(^|\s+)in\s*$", " = any(", [{return, list}]),
|
Str2 = re:replace(Str, "(^|\s+)in\s*$", " = any(", [{return, list}]),
|
||||||
{[Var, Prev | N], [{str, ")"}, Var, {str, Str2} | P], none};
|
{[Var, Prev | N], [{str, ")"}, Var, {str, Str2} | P], none};
|
||||||
([{var, _}], _) ->
|
([{var, _, _}], _) ->
|
||||||
throw({error, State#state.loc, ["List variable not following 'in' operator"]});
|
throw({error, State#state.loc, ["List variable not following 'in' operator"]});
|
||||||
(Other, {N, P, none}) ->
|
(Other, {N, P, none}) ->
|
||||||
{N, P, Other};
|
{N, P, Other};
|
||||||
@ -445,16 +461,27 @@ perform_array_pass(State) ->
|
|||||||
State#state{query = lists:reverse(PQ2), args = lists:reverse(PA), need_array_pass = false}}.
|
State#state{query = lists:reverse(PQ2), args = lists:reverse(PA), need_array_pass = false}}.
|
||||||
|
|
||||||
make_sql_query(State) ->
|
make_sql_query(State) ->
|
||||||
|
make_sql_query(State, unknown).
|
||||||
|
|
||||||
|
make_sql_query(State, Type) ->
|
||||||
Hash = erlang:phash2(State#state{loc = undefined, use_new_schema = true}),
|
Hash = erlang:phash2(State#state{loc = undefined, use_new_schema = true}),
|
||||||
SHash = <<"Q", (integer_to_binary(Hash))/binary>>,
|
SHash = <<"Q", (integer_to_binary(Hash))/binary>>,
|
||||||
Query = pack_query(State#state.'query'),
|
Query = pack_query(State#state.'query'),
|
||||||
EQuery =
|
EQuery =
|
||||||
lists:map(
|
lists:flatmap(
|
||||||
fun({str, S}) ->
|
fun({str, S}) ->
|
||||||
|
[erl_syntax:binary(
|
||||||
|
[erl_syntax:binary_field(
|
||||||
|
erl_syntax:string(S))])];
|
||||||
|
({var, V, timestamp}) when Type == pgsql ->
|
||||||
|
[erl_syntax:binary(
|
||||||
|
[erl_syntax:binary_field(
|
||||||
|
erl_syntax:string("to_timestamp("))]),
|
||||||
|
make_var(V),
|
||||||
erl_syntax:binary(
|
erl_syntax:binary(
|
||||||
[erl_syntax:binary_field(
|
[erl_syntax:binary_field(
|
||||||
erl_syntax:string(S))]);
|
erl_syntax:string(", 'YYYY-MM-DD HH24:MI:SS')"))])];
|
||||||
({var, V}) -> make_var(V)
|
({var, V, _}) -> [make_var(V)]
|
||||||
end, Query),
|
end, Query),
|
||||||
erl_syntax:record_expr(
|
erl_syntax:record_expr(
|
||||||
erl_syntax:atom(?QUERY_RECORD),
|
erl_syntax:atom(?QUERY_RECORD),
|
||||||
@ -709,7 +736,7 @@ make_sql_upsert_pgsql901(Table, ParseRes0) ->
|
|||||||
#state{'query' = [{str, " RETURNING *) "}]},
|
#state{'query' = [{str, " RETURNING *) "}]},
|
||||||
Insert
|
Insert
|
||||||
]),
|
]),
|
||||||
Upsert = make_sql_query(State),
|
Upsert = make_sql_query(State, pgsql),
|
||||||
erl_syntax:application(
|
erl_syntax:application(
|
||||||
erl_syntax:atom(ejabberd_sql),
|
erl_syntax:atom(ejabberd_sql),
|
||||||
erl_syntax:atom(sql_query_t),
|
erl_syntax:atom(sql_query_t),
|
||||||
@ -760,7 +787,7 @@ make_sql_upsert_pgsql905(Table, ParseRes0) ->
|
|||||||
#state{'query' = [{str, ") DO UPDATE SET "}]},
|
#state{'query' = [{str, ") DO UPDATE SET "}]},
|
||||||
Set
|
Set
|
||||||
]),
|
]),
|
||||||
Upsert = make_sql_query(State),
|
Upsert = make_sql_query(State, pgsql),
|
||||||
erl_syntax:application(
|
erl_syntax:application(
|
||||||
erl_syntax:atom(ejabberd_sql),
|
erl_syntax:atom(ejabberd_sql),
|
||||||
erl_syntax:atom(sql_query_t),
|
erl_syntax:atom(sql_query_t),
|
||||||
@ -884,12 +911,12 @@ resolve_vars(ST1, ST2) ->
|
|||||||
end, ST1#state.params),
|
end, ST1#state.params),
|
||||||
NewQuery =
|
NewQuery =
|
||||||
lists:map(
|
lists:map(
|
||||||
fun({var, Var}) ->
|
fun({var, Var, Type}) ->
|
||||||
case dict:find(Var, Map) of
|
case dict:find(Var, Map) of
|
||||||
{ok, New} ->
|
{ok, New} ->
|
||||||
{var, New};
|
{var, New, Type};
|
||||||
error ->
|
error ->
|
||||||
{var, Var}
|
{var, Var, Type}
|
||||||
end;
|
end;
|
||||||
(S) -> S
|
(S) -> S
|
||||||
end, ST1#state.'query'),
|
end, ST1#state.'query'),
|
||||||
|
@ -67,7 +67,7 @@ store_room(LServer, Host, Name, Opts, ChangesHints) ->
|
|||||||
SOpts = misc:term_to_expr(Opts2),
|
SOpts = misc:term_to_expr(Opts2),
|
||||||
Timestamp = case lists:keyfind(hibernation_time, 1, Opts) of
|
Timestamp = case lists:keyfind(hibernation_time, 1, Opts) of
|
||||||
false -> <<"1900-01-01 00:00:00">>;
|
false -> <<"1900-01-01 00:00:00">>;
|
||||||
{_, undefined} -> <<"1900-01-01 00:00:00">>;
|
{_, undefined} -> <<"1970-01-02 00:00:00">>;
|
||||||
{_, Time} -> usec_to_sql_timestamp(Time)
|
{_, Time} -> usec_to_sql_timestamp(Time)
|
||||||
end,
|
end,
|
||||||
F = fun () ->
|
F = fun () ->
|
||||||
@ -77,7 +77,7 @@ store_room(LServer, Host, Name, Opts, ChangesHints) ->
|
|||||||
"!host=%(Host)s",
|
"!host=%(Host)s",
|
||||||
"server_host=%(LServer)s",
|
"server_host=%(LServer)s",
|
||||||
"opts=%(SOpts)s",
|
"opts=%(SOpts)s",
|
||||||
"created_at=%(Timestamp)s"]),
|
"created_at=%(Timestamp)t"]),
|
||||||
case ChangesHints of
|
case ChangesHints of
|
||||||
Changes when is_list(Changes) ->
|
Changes when is_list(Changes) ->
|
||||||
[change_room(Host, Name, Change) || Change <- Changes];
|
[change_room(Host, Name, Change) || Change <- Changes];
|
||||||
@ -191,7 +191,7 @@ get_hibernated_rooms_older_than(LServer, Host, Timestamp) ->
|
|||||||
case catch ejabberd_sql:sql_query(
|
case catch ejabberd_sql:sql_query(
|
||||||
LServer,
|
LServer,
|
||||||
?SQL("select @(name)s, @(opts)s from muc_room"
|
?SQL("select @(name)s, @(opts)s from muc_room"
|
||||||
" where host=%(Host)s and created_at < %(TimestampS)s and created_at > '1900-01-01 00:00:00'")) of
|
" where host=%(Host)s and created_at < %(TimestampS)t and created_at > '1970-01-02 00:00:00'")) of
|
||||||
{selected, RoomOpts} ->
|
{selected, RoomOpts} ->
|
||||||
lists:map(
|
lists:map(
|
||||||
fun({Room, Opts}) ->
|
fun({Room, Opts}) ->
|
||||||
|
Loading…
Reference in New Issue
Block a user