Wednesday, June 13, 2012

Erland mnesia db access and testing

Tuesday, June 12, 2012

Erlang modules that provide a TAP testing client library.

Etap-program testing lib

 etap is a collection of Erlang modules that provide a TAP testing client library. These modules allow developers to create extensive and comprehensive tests covering many aspects of application and module development. This includes simple assertions, exceptions, the application behavior and event web requests. This library was originally written by Jeremy wall.

Sunday, June 10, 2012

Erlang: tv:start(). - no window pops up - solution

Original page...
 
> I tried tv:start/0 and toolbar:start/0: nothing happend:
>  1) tv:start just returned a PID... nothing more
>  2) toolbar:start was silent for some time and than returned:
>        ** exception exit: {startup_timeout,toolbar}
>             in function  toolbar:init_ok/1

It turns out (tcl/)tk wasn't installed on those systems in question.
After "sudo apt-get -y install tk-dev" tv and toolbar are working! - boris

Wednesday, June 6, 2012

Erlang and mnesia select

This is copied from Erlang and mnesia:select

 

Here is an example from the official Erlang docs. The query returns the name of each male person aged more then 30.
MatchHead = #person{name='$1', sex=male, age='$2', _='_'},
Guard = {'>', '$2', 30},
Result = '$1',
mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),
Criterias are expressed with $ and the whole thing becomes quite convulted for anything more complicated.
Furthermore it is impossible to do what would be basic operations in other database engines, like sorting the results.
But, a module exists that makes queries better legible . QLC that stands for Query List Comprehension. It supports Mnesia, ETS and DETS.
Here is the previous query, rewritten:
Query = qlc:q([Person#person.name || Person <- mnesia:table(Tab), Person#person.sex == male, Person#person.age > 30]),
In this case the query is expressed as a list comprehension. Criterias are written in a comprehensible manner in the second par of the list comprehension.
If you want to execute this query in Mnesia, you have to do so in a transaction.
-include_lib("stdlib/include/qlc.hrl")
Transaction = fun() ->
    Query = qlc:q([Person#person.name || Person <- mnesia:table(Tab), Person#person.sex == male, Person#person.age > 30]),
    qlc:eval(Query)
end,
mnesia:transaction(Transaction),
To efficiently sort the result, qlc provides qlc:sort.
-include_lib("stdlib/include/qlc.hrl")
Transaction = fun() ->
    Query = qlc:q([Person#person.name || Person <- mnesia:table(Tab), Person#person.sex == male, Person#person.age > 30]),
    Order = fun(A, B) ->
        B#person.age > A#person.age
    end,
    qlc:eval(qlc:sort(Query, [order, Order]))
end,
mnesia:transaction(Transaction),

Erlang and the query interface for tables

See QLC query interface for more details

MODULE

qlc

MODULE SUMMARY

Query Interface to Mnesia, ETS, Dets, etc

DESCRIPTION


The qlc module provides a query interface to Mnesia, ETS, Dets and other data structures that implement an iterator style traversal of objects.

Overview

The qlc module implements a query interface to QLC tables. Typical QLC tables are ETS, Dets, and Mnesia tables. There is also support for user defined tables, see the Implementing a QLC table section. A query is stated using Query List Comprehensions (QLCs). The answers to a query are determined by data in QLC tables that fulfill the constraints expressed by the QLCs of the query. QLCs are similar to ordinary list comprehensions as described in the Erlang Reference Manual and Programming Examples except that variables introduced in patterns cannot be used in list expressions. In fact, in the absence of optimizations and options such as cache and unique (see below), every QLC free of QLC tables evaluates to the same list of answers as the identical ordinary list comprehension.
While ordinary list comprehensions evaluate to lists, calling qlc:q/1,2 returns a Query Handle. To obtain all the answers to a query, qlc:eval/1,2 should be called with the query handle as first argument. Query handles are essentially functional objects ("funs") created in the module calling q/1,2. As the funs refer to the module's code, one should be careful not to keep query handles too long if the module's code is to be replaced. Code replacement is described in the Erlang Reference Manual. The list of answers can also be traversed in chunks by use of a Query Cursor. Query cursors are created by calling qlc:cursor/1,2 with a query handle as first argument. Query cursors are essentially Erlang processes. One answer at a time is sent from the query cursor process to the process that created the cursor.

Syntax

How to convert code to HTML for your blog

SimpleCode has a code to HTML convertor.


Enter normal (X)HTML in their markup box. Press "Process" and it will spit out entity-encoded markup suitable for examples. Use spaces in increments of two for nesting indents.

How to convert code to HTML for your blog.

Erlang and mnesia example

There is an mnesia example at the following url:

http://www.erlang.org/doc/apps/mnesia/Mnesia_chap2.html#id64245

However, the example code is incomplete.

So I added copied some of the Erlang examples functions and created some new functions to use on the DB.

Some of the functions from the page below do not seem to work (all_*).

%-----------------------------------------------------------------
%company.erl
% compile in the shell with
% > c(company).
%-----------------------------------------------------------------

-module(company). 
-export([
init/0,
insert_emp/3,
mk_projs/2,
mk_project/2,
raise/2,
all_females/0,
all_males/0,
raise_females/1,
over_write/2,
read_employee/1,
read_employee_table/2,
read_emp1/2
]).

-include_lib("stdlib/include/qlc.hrl").
-include("company.hrl").

%%----------------------------------------

init()                             ->
    mnesia:create_table(employee,
                        [{attributes, record_info(fields, employee)}]),
    mnesia:create_table(dept,
                        [{attributes, record_info(fields, dept)}]),
    mnesia:create_table(project,
                        [{attributes, record_info(fields, project)}]),
    mnesia:create_table(manager, [{type, bag},
                                  {attributes, record_info(fields, manager)}]),
    mnesia:create_table(at_dep,
[{attributes, record_info(fields, at_dep)}]),
    mnesia:create_table(in_proj, [{type, bag},
                                  {attributes, record_info(fields, in_proj)}]).

%%----------------------------------------

insert_emp(Emp, DeptId, ProjNames) ->
    Ename = Emp#employee.name,
    Fun = fun() ->
                  mnesia:write(Emp),
                  AtDep = #at_dep{emp = Ename, dept_id = DeptId},
                  mnesia:write(AtDep),
                  mk_projs(Ename, ProjNames)
          end,
    mnesia:transaction(Fun).

%%----------------------------------------

mk_projs(Ename, [ProjName|Tail])   ->
    mnesia:write(#in_proj{emp = Ename, proj_name = ProjName}),
    mk_projs(Ename, Tail);
mk_projs(_, [])                    -> ok.

%%----------------------------------------

mk_project(ProjName, ProjNumber)   ->
    mnesia:write(#project{name = ProjName, number = ProjNumber}).

%%----------------------------------------

raise(Eno, Raise)                  ->
    F = fun() ->
                [E] = mnesia:read(employee, Eno, write),
                Salary = E#employee.salary + Raise,
                New = E#employee{salary = Salary},
                mnesia:write(New)
        end,
    mnesia:transaction(F).

%%----------------------------------------

all_males()                        ->
    F = fun() ->
Male = #employee{sex = male, name = '$1', _ = '_'},
mnesia:select(employee, [{Male, [], ['$1']}])
        end,
    mnesia:transaction(F).

%%----------------------------------------

all_females()                      ->
    F = fun() ->
Female = #employee{sex = female, name = '$1', _ = '_'},
mnesia:select(employee, [{Female, [], ['$1']}])
        end,
    mnesia:transaction(F).

%%----------------------------------------

raise_females(Amount)              ->
    F = fun() ->
                Q = qlc:q([E || E <- mnesia:table(employee),
                                E#employee.sex == female]),
Fs = qlc:e(Q),
                over_write(Fs, Amount)
        end,
    mnesia:transaction(F).

%%----------------------------------------

over_write([E|Tail], Amount)       ->
    Salary = E#employee.salary + Amount,
    New = E#employee{salary = Salary},
    mnesia:write(New),
    1 + over_write(Tail, Amount);
over_write([], _)                  ->   0.

%%----------------------------------------

read_employee(Eno)                  ->
Fun = fun() ->
    mnesia:read({employee,Eno})
    end,
  {atomic,[Row]}=mnesia:transaction(Fun),
  io:format("~p~n",[Row#employee.name]).

%%----------------------------------------

read_employee_table(Table,Eno) ->
    mnesia:read({Table,Eno})
    .

%read_employee_name(Eno, Table, Field) ->
%  {atomic,[Row]}=mnesia:transaction(read_employee_table(Table, Eno)),
%  io:format("~p~n",[RowTable.Field]).
%

read_emp1(Eno, Field)                  ->
Fun = fun() ->
    mnesia:read({employee,Eno})
    end,
  {atomic,[Row]}=mnesia:transaction(Fun),
  io:format("~p~n",[Row#employee.Field]).



%  io:format("~p~n",[Row#employee.emp_no]).
% mnesia:read(employee, Eno, write).

%%----------------------------------------

%Fun = fun() ->
%   mnesia:read({employee,115018})
%   end,
% {atomic,[Row]}=mnesia:transaction(Fun),
% io:format("~p~n",[Row#employee.emp_no]).




%-----------------------------------------------------------------
%company.hrl
% compile in the shell with
% > rr("company").
%-----------------------------------------------------------------

-record(employee, {emp_no,
                   name,
                   salary,
                   sex,
                   phone,
                   room_no}).

-record(dept, {id,
               name}).

-record(project, {name,
                  number}).


-record(manager, {emp,
                  dept}).

-record(at_dep, {emp,
                 dept_id}).

-record(in_proj, {emp,
                  proj_name}).

 

%-----------------------------------------------------------------
% company_sample.erl
% compile in the shell with
% > c(company_sample).
%-----------------------------------------------------------------

 erl -mnesia dir '"/tmp/Mnesia.Company"'

mnesia:create_schema([node()]).
mnesia:start().
c(company.erl).
rr("company.hrl").
company:init().
mnesia:info().

%Employees
Emp0  = #employee{emp_no = 104465, name = "Johnson Torbjorn",  salary =  1, sex = male,   phone = 99184, room_no = {242,038}}, company:insert_emp(Emp0, 'B/SFR', [otp]).
Emp1  = #employee{emp_no = 107912, name = "Carlsson Tuula",    salary =  2, sex = female, phone = 94556, room_no = {242,056}}, company:insert_emp(Emp1, 'B/SFR', [otp]).
Emp2  = #employee{emp_no = 114872, name = "Dacker Bjarne",     salary =  3, sex = male,   phone = 99415, room_no = {221,035}}, company:insert_emp(Emp2, 'B/SFR', [otp]).
Emp3  = #employee{emp_no = 104531, name = "Nilsson Hans",      salary =  3, sex = male,   phone = 99495, room_no = {222,026}}, company:insert_emp(Emp3, 'B/SFR', [otp]).
Emp4  = #employee{emp_no = 104659, name = "Tornkvist Torbjorn",salary =  2, sex = male,   phone = 99514, room_no = {222,022}}, company:insert_emp(Emp4, 'B/SFR', [otp]).
Emp5  = #employee{emp_no = 104732, name = "Wikstrom Claes",    salary =  2, sex = male,   phone = 99586, room_no = {221,015}}, company:insert_emp(Emp5, 'B/SFR', [otp]).
Emp6  = #employee{emp_no = 117716, name = "Fedoriw Anna",      salary =  1, sex = female, phone = 99143, room_no = {221,031}}, company:insert_emp(Emp6, 'B/SFR', [otp]).
Emp7  = #employee{emp_no = 115018, name = "Mattsson Hakan",    salary =  3, sex = male,   phone = 99251, room_no = {203,348}}, company:insert_emp(Emp7, 'B/SFR', [otp]).    

%company:all_females();
%company:all_males();

% %Dept
%
%         {dept, 'B/SF',  "Open Telecom Platform"}.
%         {dept, 'B/SFP', "OTP - Product Development"}.
%         {dept, 'B/SFR', "Computer Science Laboratory"}.
%     
%

% %Projects
%company:mk_project(erlang       , 1).
%company:mk_project(otp          , 2).
%company:mk_project(beam         , 3).
%company:mk_project(mnesia       , 5).
%company:mk_project(wolf         , 6).
%company:mk_project(documentation, 7).
%company:mk_project(www          , 8).

%     
%
% % The above three tables, titled employees, dept, and projects, are the tables which are made up of real records.
% % The following database content is stored in the tables which is built on relationships.
% % These tables are titled manager, at_dep, and in_proj.
%
% %Manager
%
%         {manager, 104465, 'B/SF'}.
%         {manager, 104465, 'B/SFP'}.
%         {manager, 114872, 'B/SFR'}.
%     
%
% %At_dep
%
%         {at_dep, 104465, 'B/SF'}.
%         {at_dep, 107912, 'B/SF'}.
%         {at_dep, 114872, 'B/SFR'}.
%         {at_dep, 104531, 'B/SFR'}.
%         {at_dep, 104659, 'B/SFR'}.
%         {at_dep, 104732, 'B/SFR'}.
%         {at_dep, 117716, 'B/SFP'}.
%         {at_dep, 115018, 'B/SFP'}.
%     
%
% %In_proj
%
%         {in_proj, 104465, otp}.
%         {in_proj, 107912, otp}.
%         {in_proj, 114872, otp}.
%         {in_proj, 104531, otp}.
%         {in_proj, 104531, mnesia}.
%         {in_proj, 104545, wolf}.
%         {in_proj, 104659, otp}.
%         {in_proj, 104659, wolf}.
%         {in_proj, 104732, otp}.
%         {in_proj, 104732, mnesia}.
%         {in_proj, 104732, erlang}.
%         {in_proj, 117716, otp}.
%         {in_proj, 117716, documentation}.
%         {in_proj, 115018, otp}.
%         {in_proj, 115018, mnesia}.
%     
% otp = "otp".
% Emp  = #employee{emp_no= 104732,                     
%                             name = klacke,
%                             salary = 7,
%                             sex = male,
%                             phone = 98108,
%                             room_no = {221, 015}},
%          insert_emp(Me, 'B/SFR', [otp]).




Erlang How tos...

http://www.trapexit.org/Category:HowTo

Tuesday, June 5, 2012

Erlang and the mnesia DB

Shows how to use mnesia with Erlang records.

http://ciarang.com/posts/getting-started-with-mnesia

Up and running with Emacs, Erlang, and Distel

How to set up emacs erlang-mode


http://parijatmishra.wordpress.com/2008/08/15/up-and-running-with-emacs-erlang-and-distel/



Monday, June 4, 2012

Erlang recipes

Learning a bit about Erlang now. Found this interesting page with recipes for common tasks.

http://www.trapexit.org/Category:CookBook