Erlang/OTP Forums

Author Message

<  Erlang questions mailing list  ~  mnesia:transform_table(Tab, Fun, NewAttributeList)

andreas
Posted: Thu Jul 06, 2006 5:46 pm Reply with quote
User Joined: 03 Jul 2006 Posts: 17
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
View user's profile Send private message
Guest
Posted: Thu Jul 06, 2006 9:58 pm Reply with quote
Guest
Here's a hack (sorry!) It obviously applies the tuple definition of
records that you've already mentioned in your message.

-module(mt).
-export([test/0]).

-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@rbeers-power-mac-g4)44> mt:test().
ok
(mt@rbeers-power-mac-g4)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

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



On 7/6/06, Trap Exit <trapexit.erlang-questions@erlang-consulting.com> 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 www.trapexit.org
>
> Read this topic online here: http://trapexit.erlang-consulting.com/forum/viewtopic.php?p=135#135
>
Post recived frommailinglist
tobbe
Posted: Thu Jul 06, 2006 10:05 pm Reply with quote
User Joined: 19 Jan 2005 Posts: 274 Location: Stockholm, Sweden
Trap Exit 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

Yes!

--Tobbe

> * None of the above.
>
>
> Regards,
> Andreas Hillqvist
> _________________________________________________________
> Post sent from www.trapexit.org
>
> Read this topic online here: http://trapexit.erlang-consulting.com/forum/viewtopic.php?p=135#135
>

Post recived frommailinglist
View user's profile Send private message Send e-mail Visit poster's website
Guest
Posted: Thu Jul 06, 2006 10:34 pm Reply with quote
Guest
Hi Andreas,

On 06 Jul 2006, at 7:46 PM, Trap Exit wrote:

>
> The problem is that I have been thought to to assume that records
> are tuples.

Your assumption is correct.

> 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.

The record definition is not stored in a/the database. Mnesia
translates the record tuple into an internal format based on the
schema of the table. The purpose of the transform function is to give
you an opportunity of changing this schema and at the same time to
update all the old records to the new specification. If your function
does not change the records to the new format, they will still be
stored in mnesia in the old format, with the additional problem that
your new record definition and mnesia's is now out of sync. The
moment you change the record definition and recompile, all your code
will understand the new format. But mnesia won't. This is the purpose
of the transform functions.

> * When changeing the recodord defintion for at mnesia table change
> the record name, or

No. use the same record name.

> * Use the tuple definition of records. The code will only be used
> once so who cares, or

You will probably have to, as when you run this function *your*
definition has already changed, but mnesia's has not. Match on the
old record as a tuple and populate the new record. Something like this:

{record, A, B, C} = OldRecord,
NewRecord = #record{a = A, b = B, c = C, d = 123},
NewRecord.

Rudolph van Graan

Telecommunications Specialist
Pattern Matched Technologies

E-Mail: rvg@patternmatched.com
Mobile: +27 83 390 7767
Fax: +27 12 667 5342
Web: www.patternmatched.com
Post recived frommailinglist
uwiger
Posted: Fri Jul 07, 2006 7:53 am Reply with quote
User Joined: 03 Jul 2006 Posts: 604 Location: Sweden
Andreas Hillqvist wrote:
>
> 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.

The unwritten rule is that during upgrade - code_change() functions
and mnesia:transform_table() - one breaks the record abstraction
and treats the old records as tuples, like Rudolph and Tobbe suggested.

BR,
Ulf W
Post recived frommailinglist
View user's profile Send private message Visit poster's website

Display posts from previous:  

All times are GMT
Page 1 of 1
This forum is locked: you cannot post, reply to, or edit topics.

Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum