Mod_muc - mnesia:dirty_select need help

Hi

New to erlang and have been thrown in at the deep end. I'm making some modifications for the initial service discovery for mod_muc.erl

I have a mysql table containing location details, the table has three fields - name, lon and lat

The idea is to discover only those rooms within an certain radius based on GPS position

I have a working odbc query and have it returning the following (moded) result set

[{"world"},{"world1"},{"test1"}]

The rooms are discovered with the following query inside get_vh_rooms(Host)

mnesia:dirty_select(muc_online_room,

[{#muc_online_room{name_host = '$1', _ = '_'},
[{'==', {element, 2, '$1'},Host}],
['$_']}]).

This grabs all Rooms

If I change it to

mnesia:dirty_select(muc_online_room,

[{#muc_online_room{name_host = '$1', _ = '_'},
[{'==', {element, 1, '$1'},"world"}],
['$_']}]).

It will grab only the room called world and I can extend the pattern to grab more than one room. However I need to do it generically without hard-coding the room names.

So could anyone advise me on how traverse a list of rooms and pass the values to an mnesia query.

It SHOULD be easy but I've had less than 7 days experience of erlang.

I envision it as something like this

mnesia:dirty_select(muc_online_room,

[{#muc_online_room{name_host = '$1', _ = '_'},
[{'==', {element, 1, '$1'},MyRoom}],
['$_']}]).

Where MyRoom corresponds to each element of the list above but I have no idea how to traverse it and dynamically generate the pattern to pass to mnesia

Thanks in advance

You can specify a list of

You can specify a list of matches in your match spec to be passed to mnesia:dirty_select:

[{#muc_online_room{name_host = '$1', _ = '_'}, [{'==', {element, 1, '$1'}, Room}], ['$_']} || {Room} <- Rooms]

where Rooms is a list of rooms returned by your ODBC query. It is effectively the same as something like:

mnesia:dirty_select(muc_online_room,
  [{#muc_online_room{name_host = '$1', _ = '_'}, [{'==', {element, 1, '$1'}, "world"}], ['$_']},
   {#muc_online_room{name_host = '$1', _ = '_'}, [{'==', {element, 1, '$1'}, "world1"}], ['$_']},
   {#muc_online_room{name_host = '$1', _ = '_'}, [{'==', {element, 1, '$1'}, "test1"}], ['$_']}]).

I can't vouch for the performance of a very long list of matches though, so test it with a long list.

Hi Thanks for the reply I

Hi

Thanks for the reply

I figured it out. The problem was generating the list in the first place. I ended up with the code below that "appears" to work

make_results({selected, ["name"], Items}) ->
[make_result(Item) || Item <- Items] .

%% Execute the ODBC query and parse the result set
Results = ejabberd_odbc:sql_query("suse1.local", ["SELECT name FROM loc"]),
ListOfRooms = make_results(Results),

RoomString1 = [],

ListOfPatterns = lists:map(fun(X) ->
RoomString2 = [{#muc_online_room{name_host = '$1', _ = '_'},
[{'==', {element, 1, '$1'}, X }],
['$_']}],
string:concat(RoomString1,RoomString2)
end, ListOfRooms),
Pattern = lists:merge(ListOfPatterns),

mnesia:dirty_select(muc_online_room,Pattern).

And the revised

And the revised version

make_results({selected, ["name"], Items}) ->
[make_result(Item) || Item <- Items] .

make_result({Name}) ->
[{#muc_online_room{name_host = '$1', _ = '_'},
[{'==', {element, 1, '$1'}, Name }],
['$_']}].

Results = ejabberd_odbc:sql_query("suse1.local", ["SELECT name FROM location"]),
ListOfRooms = make_results(Results),
Pattern = lists:merge(ListOfRooms),
mnesia:dirty_select(muc_online_room,Pattern).

Syndicate content