mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-20 16:15:59 +01:00
Use the first unique index as a primary key in ejabberd_sql_schema
This commit is contained in:
parent
4ea46c5765
commit
b0a9b58958
@ -53,7 +53,8 @@
|
|||||||
|
|
||||||
|
|
||||||
-record(sql_index, {columns,
|
-record(sql_index, {columns,
|
||||||
unique = false :: boolean()}).
|
unique = false :: boolean(),
|
||||||
|
meta = #{}}).
|
||||||
-record(sql_column, {name :: binary(),
|
-record(sql_column, {name :: binary(),
|
||||||
type,
|
type,
|
||||||
default = false,
|
default = false,
|
||||||
|
@ -351,12 +351,11 @@ guess_version(Host, Schemas) ->
|
|||||||
fun(Schema) ->
|
fun(Schema) ->
|
||||||
lists:all(
|
lists:all(
|
||||||
fun(Table) ->
|
fun(Table) ->
|
||||||
Table2 = filter_table_sh(Table),
|
|
||||||
CurrentColumns =
|
CurrentColumns =
|
||||||
get_table_schema(
|
get_table_schema(
|
||||||
Host, Table2#sql_table.name),
|
Host, Table#sql_table.name),
|
||||||
check_columns_compatibility(
|
check_columns_compatibility(
|
||||||
Table2#sql_table.columns,
|
Table#sql_table.columns,
|
||||||
CurrentColumns)
|
CurrentColumns)
|
||||||
end, Schema#sql_schema.tables)
|
end, Schema#sql_schema.tables)
|
||||||
end, Schemas),
|
end, Schemas),
|
||||||
@ -568,6 +567,56 @@ format_create_index(mysql, _DBVersion, Table, Index) ->
|
|||||||
end, Index#sql_index.columns)),
|
end, Index#sql_index.columns)),
|
||||||
<<");">>].
|
<<");">>].
|
||||||
|
|
||||||
|
format_primary_key(mysql, _DBVersion, Table) ->
|
||||||
|
case lists:filter(
|
||||||
|
fun(#sql_index{meta = #{primary_key := true}}) -> true;
|
||||||
|
(_) -> false
|
||||||
|
end, Table#sql_table.indices) of
|
||||||
|
[] -> [];
|
||||||
|
[I] ->
|
||||||
|
[[<<" ">>,
|
||||||
|
<<"PRIMARY KEY (">>,
|
||||||
|
lists:join(
|
||||||
|
<<", ">>,
|
||||||
|
lists:map(
|
||||||
|
fun(Col) ->
|
||||||
|
format_mysql_index_column(Table, Col)
|
||||||
|
end, I#sql_index.columns)),
|
||||||
|
<<")">>]]
|
||||||
|
end;
|
||||||
|
format_primary_key(_DBType, _DBVersion, Table) ->
|
||||||
|
case lists:filter(
|
||||||
|
fun(#sql_index{meta = #{primary_key := true}}) -> true;
|
||||||
|
(_) -> false
|
||||||
|
end, Table#sql_table.indices) of
|
||||||
|
[] -> [];
|
||||||
|
[I] ->
|
||||||
|
[[<<" ">>,
|
||||||
|
<<"PRIMARY KEY (">>,
|
||||||
|
lists:join(<<", ">>, I#sql_index.columns),
|
||||||
|
<<")">>]]
|
||||||
|
end.
|
||||||
|
|
||||||
|
format_add_primary_key(sqlite = DBType, DBVersion, Table, Index) ->
|
||||||
|
format_create_index(DBType, DBVersion, Table, Index);
|
||||||
|
format_add_primary_key(mysql, _DBVersion, Table, Index) ->
|
||||||
|
TableName = Table#sql_table.name,
|
||||||
|
[<<"ALTER TABLE ">>, TableName, <<" ADD PRIMARY KEY (">>,
|
||||||
|
lists:join(
|
||||||
|
<<", ">>,
|
||||||
|
Index#sql_index.columns),
|
||||||
|
<<");">>];
|
||||||
|
format_add_primary_key(_DBType, _DBVersion, Table, Index) ->
|
||||||
|
TableName = Table#sql_table.name,
|
||||||
|
[<<"ALTER TABLE ">>, TableName, <<" ADD PRIMARY KEY (">>,
|
||||||
|
lists:join(
|
||||||
|
<<", ">>,
|
||||||
|
lists:map(
|
||||||
|
fun(Col) ->
|
||||||
|
format_mysql_index_column(Table, Col)
|
||||||
|
end, Index#sql_index.columns)),
|
||||||
|
<<");">>].
|
||||||
|
|
||||||
format_create_table(pgsql = DBType, DBVersion, Table) ->
|
format_create_table(pgsql = DBType, DBVersion, Table) ->
|
||||||
TableName = Table#sql_table.name,
|
TableName = Table#sql_table.name,
|
||||||
[iolist_to_binary(
|
[iolist_to_binary(
|
||||||
@ -576,13 +625,18 @@ format_create_table(pgsql = DBType, DBVersion, Table) ->
|
|||||||
<<",\n">>,
|
<<",\n">>,
|
||||||
lists:map(
|
lists:map(
|
||||||
fun(C) -> format_column_def(DBType, DBVersion, C) end,
|
fun(C) -> format_column_def(DBType, DBVersion, C) end,
|
||||||
Table#sql_table.columns)),
|
Table#sql_table.columns) ++
|
||||||
|
format_primary_key(DBType, DBVersion, Table)),
|
||||||
<<"\n);\n">>])] ++
|
<<"\n);\n">>])] ++
|
||||||
lists:map(
|
lists:flatmap(
|
||||||
fun(I) ->
|
fun(#sql_index{meta = #{primary_key := true}}) ->
|
||||||
iolist_to_binary(
|
[];
|
||||||
[format_create_index(DBType, DBVersion, Table, I),
|
(#sql_index{meta = #{ignore := true}}) ->
|
||||||
<<"\n">>])
|
[];
|
||||||
|
(I) ->
|
||||||
|
[iolist_to_binary(
|
||||||
|
[format_create_index(DBType, DBVersion, Table, I),
|
||||||
|
<<"\n">>])]
|
||||||
end,
|
end,
|
||||||
Table#sql_table.indices);
|
Table#sql_table.indices);
|
||||||
format_create_table(sqlite = DBType, DBVersion, Table) ->
|
format_create_table(sqlite = DBType, DBVersion, Table) ->
|
||||||
@ -593,13 +647,18 @@ format_create_table(sqlite = DBType, DBVersion, Table) ->
|
|||||||
<<",\n">>,
|
<<",\n">>,
|
||||||
lists:map(
|
lists:map(
|
||||||
fun(C) -> format_column_def(DBType, DBVersion, C) end,
|
fun(C) -> format_column_def(DBType, DBVersion, C) end,
|
||||||
Table#sql_table.columns)),
|
Table#sql_table.columns) ++
|
||||||
|
format_primary_key(DBType, DBVersion, Table)),
|
||||||
<<"\n);\n">>])] ++
|
<<"\n);\n">>])] ++
|
||||||
lists:map(
|
lists:flatmap(
|
||||||
fun(I) ->
|
fun(#sql_index{meta = #{primary_key := true}}) ->
|
||||||
iolist_to_binary(
|
[];
|
||||||
[format_create_index(DBType, DBVersion, Table, I),
|
(#sql_index{meta = #{ignore := true}}) ->
|
||||||
<<"\n">>])
|
[];
|
||||||
|
(I) ->
|
||||||
|
[iolist_to_binary(
|
||||||
|
[format_create_index(DBType, DBVersion, Table, I),
|
||||||
|
<<"\n">>])]
|
||||||
end,
|
end,
|
||||||
Table#sql_table.indices);
|
Table#sql_table.indices);
|
||||||
format_create_table(mysql = DBType, DBVersion, Table) ->
|
format_create_table(mysql = DBType, DBVersion, Table) ->
|
||||||
@ -610,13 +669,18 @@ format_create_table(mysql = DBType, DBVersion, Table) ->
|
|||||||
<<",\n">>,
|
<<",\n">>,
|
||||||
lists:map(
|
lists:map(
|
||||||
fun(C) -> format_column_def(DBType, DBVersion, C) end,
|
fun(C) -> format_column_def(DBType, DBVersion, C) end,
|
||||||
Table#sql_table.columns)),
|
Table#sql_table.columns) ++
|
||||||
|
format_primary_key(DBType, DBVersion, Table)),
|
||||||
<<"\n) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\n">>])] ++
|
<<"\n) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\n">>])] ++
|
||||||
lists:map(
|
lists:flatmap(
|
||||||
fun(I) ->
|
fun(#sql_index{meta = #{primary_key := true}}) ->
|
||||||
iolist_to_binary(
|
[];
|
||||||
[format_create_index(DBType, DBVersion, Table, I),
|
(#sql_index{meta = #{ignore := true}}) ->
|
||||||
<<"\n">>])
|
[];
|
||||||
|
(I) ->
|
||||||
|
[iolist_to_binary(
|
||||||
|
[format_create_index(DBType, DBVersion, Table, I),
|
||||||
|
<<"\n">>])]
|
||||||
end,
|
end,
|
||||||
Table#sql_table.indices).
|
Table#sql_table.indices).
|
||||||
%format_create_table(DBType, _DBVersion, Table) ->
|
%format_create_table(DBType, _DBVersion, Table) ->
|
||||||
@ -644,12 +708,11 @@ create_table(Host, Table) ->
|
|||||||
create_tables(Host, Module, Schema) ->
|
create_tables(Host, Module, Schema) ->
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(Table) ->
|
fun(Table) ->
|
||||||
Table2 = filter_table_sh(Table),
|
Res = create_table(Host, Table),
|
||||||
Res = create_table(Host, Table2),
|
|
||||||
case Res of
|
case Res of
|
||||||
{error, Error} ->
|
{error, Error} ->
|
||||||
?ERROR_MSG("Failed to create table ~s: ~p",
|
?ERROR_MSG("Failed to create table ~s: ~p",
|
||||||
[Table2#sql_table.name, Error]),
|
[Table#sql_table.name, Error]),
|
||||||
error(Error);
|
error(Error);
|
||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
@ -677,9 +740,60 @@ should_update_schema(Host) ->
|
|||||||
false
|
false
|
||||||
end.
|
end.
|
||||||
|
|
||||||
update_schema(Host, Module, Schemas) ->
|
preprocess_table(Host, Table) ->
|
||||||
|
Table1 = filter_table_sh(Table),
|
||||||
|
ImplicitPK =
|
||||||
|
case ejabberd_option:sql_type(Host) of
|
||||||
|
pgsql -> false;
|
||||||
|
sqlite ->
|
||||||
|
case lists:keyfind(bigserial, #sql_column.type,
|
||||||
|
Table1#sql_table.columns) of
|
||||||
|
false -> false;
|
||||||
|
#sql_column{name = Name} -> {ok, Name}
|
||||||
|
end;
|
||||||
|
mysql ->
|
||||||
|
case lists:keyfind(bigserial, #sql_column.type,
|
||||||
|
Table1#sql_table.columns) of
|
||||||
|
false -> false;
|
||||||
|
#sql_column{name = Name} -> {ok, Name}
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
Indices =
|
||||||
|
case ImplicitPK of
|
||||||
|
false ->
|
||||||
|
{Inds, _} =
|
||||||
|
lists:mapfoldl(
|
||||||
|
fun(#sql_index{unique = true} = I, false) ->
|
||||||
|
{I#sql_index{
|
||||||
|
meta = (I#sql_index.meta)#{primary_key => true}},
|
||||||
|
true};
|
||||||
|
(I, Acc) ->
|
||||||
|
{I, Acc}
|
||||||
|
end, false, Table1#sql_table.indices),
|
||||||
|
Inds;
|
||||||
|
{ok, CN} ->
|
||||||
|
lists:map(
|
||||||
|
fun(#sql_index{columns = [CN1]} = I) when CN == CN1 ->
|
||||||
|
I#sql_index{
|
||||||
|
meta = (I#sql_index.meta)#{ignore => true}};
|
||||||
|
(I) -> I
|
||||||
|
end,
|
||||||
|
Table1#sql_table.indices)
|
||||||
|
end,
|
||||||
|
Table1#sql_table{indices = Indices}.
|
||||||
|
|
||||||
|
preprocess_schemas(Host, Schemas) ->
|
||||||
|
lists:map(
|
||||||
|
fun(Schema) ->
|
||||||
|
Schema#sql_schema{
|
||||||
|
tables = lists:map(fun(T) -> preprocess_table(Host, T) end,
|
||||||
|
Schema#sql_schema.tables)}
|
||||||
|
end, Schemas).
|
||||||
|
|
||||||
|
update_schema(Host, Module, RawSchemas) ->
|
||||||
case should_update_schema(Host) of
|
case should_update_schema(Host) of
|
||||||
true ->
|
true ->
|
||||||
|
Schemas = preprocess_schemas(Host, RawSchemas),
|
||||||
Version = get_current_version(Host, Module, Schemas),
|
Version = get_current_version(Host, Module, Schemas),
|
||||||
LastSchema = lists:max(Schemas),
|
LastSchema = lists:max(Schemas),
|
||||||
LastVersion = LastSchema#sql_schema.version,
|
LastVersion = LastSchema#sql_schema.version,
|
||||||
@ -730,7 +844,7 @@ do_update_schema(Host, Module, Schema) ->
|
|||||||
<<" DEFAULT ">>,
|
<<" DEFAULT ">>,
|
||||||
Default, <<";\n">>]] ++
|
Default, <<";\n">>]] ++
|
||||||
case Column#sql_column.default of
|
case Column#sql_column.default of
|
||||||
false ->
|
false when DBType /= sqlite ->
|
||||||
[[<<"ALTER TABLE ">>,
|
[[<<"ALTER TABLE ">>,
|
||||||
TableName,
|
TableName,
|
||||||
<<" ALTER COLUMN ">>,
|
<<" ALTER COLUMN ">>,
|
||||||
@ -779,45 +893,57 @@ do_update_schema(Host, Module, Schema) ->
|
|||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
end;
|
end;
|
||||||
({create_index, TableName, Columns}) ->
|
({create_index, TableName, Columns1}) ->
|
||||||
{value, Table1} =
|
Columns =
|
||||||
lists:keysearch(
|
|
||||||
TableName, #sql_table.name, Schema#sql_schema.tables),
|
|
||||||
{value, Index1} =
|
|
||||||
lists:keysearch(
|
|
||||||
Columns, #sql_index.columns, Table1#sql_table.indices),
|
|
||||||
Table = filter_table_sh(Table1),
|
|
||||||
Index =
|
|
||||||
case ejabberd_sql:use_new_schema() of
|
case ejabberd_sql:use_new_schema() of
|
||||||
true ->
|
true ->
|
||||||
Index1;
|
Columns1;
|
||||||
false ->
|
false ->
|
||||||
Index1#sql_index{
|
lists:delete(
|
||||||
columns =
|
<<"server_host">>, Columns1)
|
||||||
lists:delete(
|
|
||||||
<<"server_host">>, Index1#sql_index.columns)
|
|
||||||
}
|
|
||||||
end,
|
end,
|
||||||
Res =
|
{value, Table} =
|
||||||
ejabberd_sql:sql_query(
|
lists:keysearch(
|
||||||
Host,
|
TableName, #sql_table.name, Schema#sql_schema.tables),
|
||||||
fun(DBType, DBVersion) ->
|
{value, Index} =
|
||||||
SQL1 = format_create_index(
|
lists:keysearch(
|
||||||
DBType, DBVersion, Table, Index),
|
Columns, #sql_index.columns, Table#sql_table.indices),
|
||||||
SQL = iolist_to_binary(SQL1),
|
case Index#sql_index.meta of
|
||||||
?INFO_MSG("Create index ~s/~p:~n~s~n",
|
#{ignore := true} -> ok;
|
||||||
[Table#sql_table.name,
|
|
||||||
Index#sql_index.columns,
|
|
||||||
SQL]),
|
|
||||||
ejabberd_sql:sql_query_t(SQL)
|
|
||||||
end),
|
|
||||||
case Res of
|
|
||||||
{error, Error} ->
|
|
||||||
?ERROR_MSG("Failed to update table ~s: ~p",
|
|
||||||
[TableName, Error]),
|
|
||||||
error(Error);
|
|
||||||
_ ->
|
_ ->
|
||||||
ok
|
Res =
|
||||||
|
ejabberd_sql:sql_query(
|
||||||
|
Host,
|
||||||
|
fun(DBType, DBVersion) ->
|
||||||
|
case Index#sql_index.meta of
|
||||||
|
#{primary_key := true} ->
|
||||||
|
SQL1 = format_add_primary_key(
|
||||||
|
DBType, DBVersion, Table, Index),
|
||||||
|
SQL = iolist_to_binary(SQL1),
|
||||||
|
?INFO_MSG("Add primary key ~s/~p:~n~s~n",
|
||||||
|
[Table#sql_table.name,
|
||||||
|
Index#sql_index.columns,
|
||||||
|
SQL]),
|
||||||
|
ejabberd_sql:sql_query_t(SQL);
|
||||||
|
_ ->
|
||||||
|
SQL1 = format_create_index(
|
||||||
|
DBType, DBVersion, Table, Index),
|
||||||
|
SQL = iolist_to_binary(SQL1),
|
||||||
|
?INFO_MSG("Create index ~s/~p:~n~s~n",
|
||||||
|
[Table#sql_table.name,
|
||||||
|
Index#sql_index.columns,
|
||||||
|
SQL]),
|
||||||
|
ejabberd_sql:sql_query_t(SQL)
|
||||||
|
end
|
||||||
|
end),
|
||||||
|
case Res of
|
||||||
|
{error, Error} ->
|
||||||
|
?ERROR_MSG("Failed to update table ~s: ~p",
|
||||||
|
[TableName, Error]),
|
||||||
|
error(Error);
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
|
end
|
||||||
end;
|
end;
|
||||||
({drop_index, TableName, Columns1}) ->
|
({drop_index, TableName, Columns1}) ->
|
||||||
Columns =
|
Columns =
|
||||||
@ -888,7 +1014,9 @@ test() ->
|
|||||||
#sql_column{name = <<"type">>, type = text},
|
#sql_column{name = <<"type">>, type = text},
|
||||||
#sql_column{name = <<"created_at">>, type = timestamp,
|
#sql_column{name = <<"created_at">>, type = timestamp,
|
||||||
default = true}],
|
default = true}],
|
||||||
indices = [#sql_index{
|
indices = [#sql_index{columns = [<<"id">>],
|
||||||
|
unique = true},
|
||||||
|
#sql_index{
|
||||||
columns = [<<"server_host">>, <<"username">>, <<"timestamp">>]},
|
columns = [<<"server_host">>, <<"username">>, <<"timestamp">>]},
|
||||||
#sql_index{
|
#sql_index{
|
||||||
columns = [<<"server_host">>, <<"username">>, <<"peer">>]},
|
columns = [<<"server_host">>, <<"username">>, <<"peer">>]},
|
||||||
@ -905,7 +1033,8 @@ test() ->
|
|||||||
[<<"server_host">>, <<"origin_id">>]},
|
[<<"server_host">>, <<"origin_id">>]},
|
||||||
{drop_index, <<"archive2">>,
|
{drop_index, <<"archive2">>,
|
||||||
[<<"server_host">>, <<"origin_id">>]},
|
[<<"server_host">>, <<"origin_id">>]},
|
||||||
{drop_column, <<"archive2">>, <<"origin_id">>}
|
{drop_column, <<"archive2">>, <<"origin_id">>},
|
||||||
|
{create_index, <<"archive2">>, [<<"id">>]}
|
||||||
]},
|
]},
|
||||||
#sql_schema{
|
#sql_schema{
|
||||||
version = 1,
|
version = 1,
|
||||||
|
Loading…
Reference in New Issue
Block a user