Copyright © Matthew Pflueger 2007
Authors: Matthew Pflueger (matthew.pflueger@gmail.com).
This module implements the Mnesia driver for ErlyDB.
This is an internal ErlyDB module that you normally shouldn't have to
use directly. For most situations, all you have to know
about this module is the options you can pass to start/1, which
is called by erlydb:start/2. Currently (Erlyweb 0.6), no options are
recognized/used.
Introduction
Conventions
Types
Example
What's Not Supported
Mnesia is Erlang's distributed DataBase Management System (DBMS). Please read the Mnesia Reference Manual for more information about Mnesia.
This driver executes Erlsql queries against Mnesia. Most Erlsql queries are dynamically converted into Query List Comprehension (QLC) expressions before execution. Please see the qlc module documentation for more information on QLC. Please read the Erlsql documentation for more information on Erlsql.
This driver does not add relational support to Mnesia (constraints, cascades, etc). Some relational support for Mnesia has been implemented by Ulf Wiger in the user contribution rdbms (see http://erlang.org/user.html). For more information visit http://ulf.wiger.net/rdbms/doc/rdbms.html. You can download a more recent version of rdbms at http://ulf.wiger.net/rdbms/download/.
The driver uses a table named 'counter' for auto-incrementing (identity) primary key columns. (only valid for set or ordered-set tables). The 'counter' table must be created using the following:
mnesia:create_table(counter, [{disc_copies, [node()]}, {attributes, [key, counter]}])
The key column will contain table names of the mnesia tables utilizing identity columns. The counter contains the value of the last used identity (serial integer). The counter is updated using:
mnesia:dirty_update_counter(counter, Table, 1)
You can initialize/start the identity of a particular table by executing the above statement with an arbitrary number (greater than 0). The above operation is atomic (the function name is misleading). Please read the Mnesia docs for more information. The use of the 'counter' table is currently not customizable but that will hopefully change soon.
All columns named 'id' or ending with 'id' are treated as integers. If the column named 'id' is the first attribute (column) in the mnesia table, then it is also treated as an auto-incrementing identity column.
This driver stores all fields as binary unless the field name ends with id and in that case the field is treated as an integer (as discussed above). This can be customized by utilizing the user_properties for a mnesia table. The driver will do a limited amount of type conversion utilizing these properties. The driver will recognize user_properties for a field if defined in the following format:
{Field, {Type, Modifier}, Null, Key, Default, Extra, MnesiaType}
where Field is an atom and must be the same as the field (attribute) name, Type through Extra is are as defined in erlydb_field:new/6 MnesiaType is the type to store the field as in mnesia.
Currently, only the following values for MnesiaType are recognized:
atom, list, binary, integer, float, datetime, date, time, undefined
The erlydb_mnesia driver will attempt to convert field values into the specified type before insertion/update/query of the record in mnesia... If the MnesiaType has a value of undefined then no type conversion is attempted for the field.
Given the following record:
-record(person, {myid, type, name, age, country, office, department, genre, instrument, created_on})
Create a Mnesia table with types for the driver using:
{atomic, ok} = mnesia:create_table(person, [ {disc_copies, [node()]}, {attributes, record_info(fields, person)}, {user_properties, [{myid, {integer, undefined}, false, primary, undefined, identity, integer}, {type, {varchar, undefined}, false, undefined, undefined, undefined, atom}, {age, {integer, undefined}, true, undefined, undefined, undefined, integer}, {created_on, {datetime, undefined}, true, undefined, undefined, undefined, undefined}]}])
Note the following: 1) The primary key column is called myid and is an auto-incrementing integer column. This is the same as if the column had been named 'id'. 2) The type and age columns have customized types. The driver will try to convert all values inserted into the table into the specified types. 3) The created_on column is defined as a datetime for Erlyweb but is of type undefined for the Mnesia driver. This means that no type conversion will be attempted for the created_on column resulting in a Erlang datetime tuple to be stored in the column {{Year, Month, Day}, {Hour, Minute, Second}} or {datetime, {{Year, Month, Day},{Hour,Minute,Second}}} depending on how you create the record (creating a record from strings will result in the tuple beginning with datetime). 4) Changing the user property for the created_on column to specify a mnesia type of datetime like {created_on, {datetime, undefined}, true, undefined, undefined, undefined, datetime} will result in the erlang date time tuple {{Year,Month,Day},{Hour,Minute,Second}} to be stored regardless of how the record was created (ie. it will strip the redundant datetime atom from the tuple
See test/erlydb/erlydb_mnesia_schema for more examples of how to create mnesia tables with user_properties...
| get_last_insert_id/2 | Get the id of the last inserted record. |
| get_metadata/1 | Get the table names and fields for the database. |
| q/1 | |
| q/2 | |
| select/2 | Execute a statement against Mnesia. |
| select_as/3 | Execute a statement for records belonging to the given module, returning all rows with additional data to support higher-level ErlyDB features. |
| start/0 | |
| start/1 | Start the Mnesia driver using the options property list. |
| transaction/2 | Execute a group of statements in a transaction. |
| update/2 | Execute a update to Mnesia. |
get_last_insert_id(Table::atom(), Options::options()) -> term()
Get the id of the last inserted record.
get_metadata(Options::proplist()) -> gb_trees()
Get the table names and fields for the database.
select(Statement::statement(), Options::options()) -> {ok, Rows::list()} | {error, Error}
Execute a statement against Mnesia.
select_as(Module::atom(), Statement::statement(), Options::options()) -> {ok, Rows} | {error, Error}
Execute a statement for records belonging to the given module, returning all rows with additional data to support higher-level ErlyDB features.
start(StartOptions::proplist()) -> ok | {error, Error}
Start the Mnesia driver using the options property list. Currently, no options are recognized.
transaction(Fun::function(), Options::options()) -> {atomic, Result} | {aborted, Reason}
Execute a group of statements in a transaction. Fun is the function that implements the transaction. Fun can contain an arbitrary sequence of calls to the erlydb_mnesia's query functions. If Fun crashes or returns or throws 'error' or {error, Err}, the transaction is automatically rolled back.
update(Statement::statement(), Options::options()) -> {ok, NumAffected} | {error, Err}
Execute a update to Mnesia.