Module iodb_model_compiler

IDEA Object Database Model Compiler.

See also: iodb_compiler, iodb_model.

Description

IDEA Object Database Model Compiler. Turn IODB Data Models into a regular and fully-featured IODB ActiveRecords.

Example IODB Data Model definition:
  %% Module name. -module (person, []) is accepted too.
  %% In both cases, it's converted to -module (person, [InternalProplist]).
  %% InternalProplist carry all the Model Instance data.
  -module (person).
 
  %% Not mandatory, compiler exports at least
  %% all the generated functions.
  -compile (export_all).
 
  %% Model-wide defaults
  -egtm_map ({'#Common', [
 
    %% MUMPS Global where to save data
    {global, "^Person"},
 
    %% MUMPS Subscripts where to save data
    %% within a ^Person global name.
    %% Atoms that holds the same name as
    %% any of IODB Model field is converted
    %% to value of such a field when querying
    %% database.
    %% So if MyPerson:id () is 5, then MyPerson
    %% object is saved in ^Person("meta",5) subtree.
    {index, ["meta", id]},
 
    %% Default $Piece position and delimiter
    {piece, 1}, {delim, "|"}
  ]}).
 
  %% Field id is index field, so we don't care about piece.
  %% person:id(Obj) access function is automatically generated
  %% so it can be called like MyPerson:id ().
  -egtm_map ({id, [ {global, "^Person"}, {index, ["meta", id]} ]}).
 
  %% Field name holds value that is stored
  %% in global ^Person("meta",id) on first $Piece.
  %% Access function name () is generated too.
  delimited by "|".
  -egtm_map ({name, [ {global, "^Person"}, {index, ["meta", id]}, {piece, 1} ]}).
 
  %% Analogy to name but with piece=2,
  %% access function is surname ().
  -egtm_map ({surname, [ {global, "^Person"}, {index, ["meta", id]}, {piece, 2} ]}).
 
  %% Field age is stored in global name
  %% and index inherited from #Common.
  %% Its value sits at fourth piece (delimited by "|"
  %% what's inherited from #Common too) and
  %% its default value is "24".
  %% Access function is age ().
  -egtm_map ({age, [ {piece, 4}, {default, "24"} ]}).
 
  %% Field email sits in ^Person("meta",id), on fifth piece.
  %% Access function is email ().
  -egtm_map ({email, [ {piece, 5} ]}).
 
  %% Field company_id is a foreign key field.
  %% It holds a value, but as it ends by '_id',
  %% IODB Model Compiler will try to generate
  %% a function two access functions
  %% company_id () and company ().
  %% company_id () returns a value of this field
  %% while company () will try to return an instance
  %% of IODB Model 'company' with a primary key
  %% of 'company_id'.
  %% This field is also interesting because
  %% it is stored in ^Person("meta",id,"%CompanyID") on first $Piece.
  -egtm_map ({company_id, [ {index, ["meta", id, "%CompanyID"]} ]}).
 
  %% Another interesting field that is stored under
  %% ^Person("meta", id, "Text") global tree.
  %% Because it has 'longstring' qualifier,
  %% it is stored in ^Person("meta", id, "Text", Seq) rather.
  %% Longstring qualifier pieces very long data
  %% into sequence of smaller chunks stored in M subtree.
  %% With this, we can easily avoid MUMPS record-size
  %% limits without setting a huge database block-sizes
  %% that are inefficient.
  -egtm_map ({text, [ {index, ["meta", id, "Text"]}, longstring ]}).
 
  %% All fields in form 'index_by_' are intented
  %% to carry no data, but just to make a secondary
  %% search index for our object.
  %% In this case, saving our Model Instance of 'person'
  %% will set ^Person("nameidx",name,id)="".
  %% A special function find_by_name (Name) is automatically
  %% generated by IODB Model Compiler. It will return all
  %% the 'person' objects with the Object:name () equal
  %% to Name argument.
  %% This is MUCH faster than iodb:find or iodb:foreach
  %% since it is implemented as MUMPS $Order over such
  %% an index: egtm_util:foreach ("^Person", ["nameidx", Name]).
  -egtm_map ({index_by_name, [ {global, "^Person"}, {index, ["nameidx", name, id]} ]}).
 
  %% A custom "class" method -- will
  %% be preserved as person:foo (A, B, Obj),
  %% so it can be called as PersonInstance:foo (A, B).
  foo (A, B) -> A+B.
 
  %% Hand-written validation tests.
  %% This is called from generated person:validate() function.
  validation_tests () -> [
    { fun () ->
        case email () of
          undefined -> false;
          Val       ->
            (nomatch =/= re:run (Val,
              "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+"))
        end
      end, "Invalid e-mail address!" },
    { fun () -> (name () =/= "") and (name () =/= undefined) end,
      "Name cannot be empty!" } ].
 
  %% Auto-generated ActiveRecord functions are:
  %%   fieldnames, data_proplist
  %%
  %% The rest is currently inherited from iodb_model.
  %% For example:
  %%   get, set, save, load, exists, drop,
  %%   next, prev, first, last,
  %%   to_proplist, match, validate, ...

This module implements token/form transformation functions passed to IODB Common Compiler iodb_compiler backend.

Based on code and ideas of Evan Miller and his boss_db.

Function Index

compile/1Equivalent to compile(File, []).
compile/2Compile IODB Data Model.
compile_dir/1Equivalent to compile_dir(Path, []).
edoc_module/1Equivalent to edoc_module(File, []).
edoc_module/2Return an edoc_module () for the given Erlang source.
process_tokens/1
trick_out_forms/2

Function Details

compile/1

compile(File) -> any()

Equivalent to compile(File, []).

compile/2

compile(File::string(), Options::compiler_options()) -> {ok, Module::atom()} | {error, Reason::any()}

Compile IODB Data Model.

compile_dir/1

compile_dir(Path) -> any()

Equivalent to compile_dir(Path, []).

edoc_module/1

edoc_module(File) -> any()

Equivalent to edoc_module(File, []).

edoc_module/2

edoc_module(File::string(), Options::compiler_options()) -> {Module::atom(), EDoc::any()}

Return an edoc_module () for the given Erlang source.

process_tokens/1

process_tokens(Tokens) -> any()

trick_out_forms/2

trick_out_forms(Forms, TokenInfo) -> any()


Generated by EDoc, Jun 10 2012, 19:21:56.