我不完全理解记录如何与Mnesia一起使用,以及更改记录类型的影响是什么。以下是示例:
Erlang/OTP 17 [erts-6.2] [source] [64-bit] [async-threads:10] [kernel-poll:false]
Eshell V6.2 (abort with ^G)
1> c(test).
{ok,test}
2> mnesia:start().
ok
3> test:reset_db().
{atomic,ok}
4> test:add_sensor("1a0",12,erlang:now()).
{atomic,ok}
5> test:add_sensor("1a1",10,erlang:now()).
{atomic,ok}
6> test:list_sensors().
[{sensors,"1a0",12,{1484,392274,122051}},
{sensors,"1a1",10,{1484,392280,673175}}]
7> test:list_sensors_id().
["1a0","1a1"]
所以这一切都有意义 - 我们创建了一个表(test:reset_db),其中包含“sensors”类型的记录,并添加了两个传感器(test:add_sensor)。我们看到两种“传感器”类型的记录。现在让我们修改表格:
8> test:update_db().
{atomic,ok}
9> test:list_sensors().
[{sensors_new,"1a0",12,{1484,392274,122051},0},
{sensors_new,"1a1",10,{1484,392280,673175},0}]
10> test:list_sensors_id().
["1a0","1a1"]
11> q().
ok
所以这是我没有得到的部分 - 我们更新了我们的表(test:update_db),所以现在我们有“sensors_new”记录类型的“sensors”表 - 这与我们在test上看到的一致:list_sensors,但我没有得到的是为什么测试:list_sensors_id()仍然有效? #sensors_new.name和#sensorss.id之间是否有映射? Erlang / Mnesia如何知道翻译后“X#sensorss.id”和“X#sensors_new.name”是同一个字段?或者我错过了什么?
-include_lib("stdlib/include/qlc.hrl").
-module(test).
-compile(export_all).
-record(sensors,{id,val,update}).
-record(sensors_new,{name,val,update,type}).
reset_db() ->
mnesia:delete_table(sensors),
mnesia:create_table(sensors, [{attributes, record_info(fields, sensors)}]).
update_db() ->
Transformer = fun(X) when is_record(X, sensors) ->
#sensors_new{name = X#sensors.id,
val = X#sensors.val,
update = X#sensors.update,
type = 0} end,
{atomic, ok} = mnesia:transform_table(sensors,Transformer,record_info(fields, sensors_new),sensors_new).
add_sensor(Id, Val, Update) ->
Row = #sensors{id=Id, val=Val, update=Update},
F = fun() ->
mnesia:write(Row)
end,
mnesia:transaction(F).
list_sensors() ->
do(qlc:q([X || X <-mnesia:table(sensors)])).
list_sensors_id() ->
do(qlc:q([X#sensors.id || X <-mnesia:table(sensors)])).
do(Q) ->
F = fun() -> qlc:e(Q) end,
{atomic, Val} = mnesia:transaction(F),
Val.
答案 0 :(得分:0)
首先快速回顾:Erlang中的记录只是元组的语法糖,记录名称作为第一个元素添加。当您访问记录N
中的R
字段时,Erlang实际上将其转换为使用element(N+1, R)
。在此示例中,#sensors.id
和#sensors_new.name
都提供相同的2
值,因此访问其中任何一个都只是element(2, R)
。
现在默认情况下,通过错误的类型访问记录的字段应该会失败(除非两个记录具有相同的名称)。如果变量Foo
绑定到#sensors
类型的记录,但您尝试通过#sensors_new
访问某些内容,例如Foo#sensors_new.name
,则通常会抛出badrecord
1}}错误,像这样:
4> Foo = #sensors{id="bar"}.
#sensors{id = "bar"}
5> Foo#sensors_new.name.
** exception error: {badrecord,sensors_new}
但是,使用QLC时似乎 that check is bypassed (QLC解析转换在no_strict_record_tests
中传递,禁用“严格”记录字段访问测试)。如果我不得不猜测,我会说这是一个优化,并假设如果您交换了支持记录,就不会使用相同的QLC。