mnesia:transform_table(Tab, Fun, NewAttributeList)

RCB rcbeerman@REDACTED
Thu Jul 6 23:41:55 CEST 2006

Here's a hack (sorry!)   It obviously applies the tuple definition of
records that you've already mentioned in your message.


-define(URNAME, user).

user_record_v1(Uid, Uname, Upwd) ->
    {?URNAME, Uid, Uname, Upwd}.

user_record_v2(Uid, Uname, Upwd, Email) ->
    {?URNAME, Uid, Uname, Upwd, Email}.

test() ->
    RecV1 = [uid, uname, upassword],
    RecV2 = [uid, uname, upassword, uemail],

    {atomic, ok} = mnesia:create_table(?URNAME, [{attributes, RecV1}]),

    ok = mnesia:dirty_write(user_record_v1(1, "john doe", "password")),
    ok = mnesia:dirty_write(user_record_v1(2, "jane doe", "password")),

    {atomic, ok} = mnesia:transform_table(?URNAME,
        fun({_, Uid, Uname, Upwd}) ->
            user_record_v2(Uid, Uname, Upwd, none)
        end, RecV2, ?URNAME),

    ok = mnesia:dirty_write(user_record_v2(3, "baby joe", "password3", none)).

(mt@REDACTED)44> mt:test().
(mt@REDACTED)45> ets:tab2list(user).
[{user,1,"john doe","password",none},
 {user,2,"jane doe","password",none},
 {user,3,"baby joe","password3",none}]

I suppose you could take your application offline, apply a conversion
tool like this one (_after making a physical backup_ :->), and then
push and start a new version of your software which uses the new
'user' record in the source.    YMMV.

Alternatively, a somewhat common pattern that can be applied is...

-record(user, {id, urec}).
-record(urec1, {username, password}).
-record(urec2, {username, password, email}).

#user{id = 1234, urec=#urec2{username = "John", password = "pw", email = none}}.

You can then use run-time pattern matching on urec if you wish to have
both record types to coexist in your table.   By doing this, the name
of the record does not change, nor does the primary key, but the
actual payload can mutate along with your application's needs.   There
are some definite drawbacks to this, but it might make table
transformation a little less involved.

Good luck,

Rich Beerman
Cupertino, California
mobile: 408/221-2444
fax: 408/255-7944

On 7/6/06, Trap Exit <trapexit.erlang-questions@REDACTED> wrote:
> Hi, folks.
> I have a mnesia table where I am about to change the definition of the record which it is based on.
> I have found the mnesia:transform_table/3 and mnesia:transform_table/4 functions. I know how to implement this if I use tuples in the funs that transform the objects in the table.
> fun({user, UserId, UserName, UserPassword}) ->
>     UserEMail = none,
>     {user, UserId, UserName, UserPassword, UserEMail}.
> The problem is that I have been thought to to assume that records are tuples.
> You cant have a record name with two definitions, if you have diffrent name, you will have to enter the new recordnam into the databas.
> So, how should one procede?
> * When changeing the recodord defintion for at mnesia table change the record name, or
> * Use the tuple definition of records. The code will only be used once so who cares, or
> * None of the above.
> Regards,
> Andreas Hillqvist
> _________________________________________________________
> Post sent from
> Read this topic online here:

More information about the erlang-questions mailing list