Module erlydb_base

erlydb_base is the base module that all modules that ErlyDB generates extend.

Copyright © Yariv Sadan 2006-2007

Authors: Yariv Sadan (yarivvv@gmail.com) [web site: http://yarivsblog.com].

Description

erlydb_base is the base module that all modules that ErlyDB generates extend.

Generated modules inherit many of erlydb_base's exported functions directly, but some of the functions in erlydb_base undergo changes before they attain their final forms the generated modules. For an exact description of how each function in erlydb_base is used in generated modules, refer to the function's documentation.

You can override some of the default code generation behavior by providing your own implementations for some of erlydb_base's functions in generated modules. This is useful for telling ErlyDB about relations (one-to-many and many-to-many) and mappings between Erlang modules and database tables and fields.

Starting from ErlyWeb 0.6, you can add arbitrary metadata to database fields as well as define specific fields to be read-only. For more information, see fields/0.

Data Types

extras_expr()

abstract datatype: extras_expr()

ErlSQL (see erlsql) statement fragments that appear at the end of the statement, following the 'where' clause (if it exists). Currently, this includes 'order_by' and 'limit' clauses.

Examples:
  {order_by, age}
  {limit, 6, 8}
  [{order_by, [{age, {height, asc}, {gpa, desc}}]}, {limit, 5}]
If you pass the option {allow_unsafe_statements, true} to erlydb:code_gen/3, you can use string and/or binary Extras expressions, but this isn't recommended because it exposes to you SQL injection attacks if you forget to quote your strings.

record()

abstract datatype: record()

An Erlang tuple containing the values for (some of) the fields of a database row, as well as additional data used by ErlyDB. To ensure future compatibility, it is recommended to use the getters and setters ErlyDB adds to generated modules in order to access the record's fields instead of accessing them directly.

where_expr()

abstract datatype: where_expr()

An ErlSQL (see erlsql) statement fragment that defines the conditions in a {where, Conditions} clause.

Examples:
  {age, '=', 34}
  {{name, 'like', "Bob%"}, 'or', {not, {age, '>', 26}}}
If you pass the option {allow_unsafe_statements, true} to erlydb:code_gen/3, you can use string and/or binary Where expressions, but this isn't recommended because it exposes to you SQL injection attacks if you forget to quote your strings.

Function Index

add_related_many_to_many/3Add a related record in a many-to-many relation.
after_delete/1A hook that gets called after a record is deleted.
after_fetch/1A hook that gets called after a record is fetched from the database.
after_save/1A hook that gets called after a record is saved.
aggregate/5ErlyDB uses this function to generate derivative functions in target modules for calculating aggregate values for database fields.
aggregate_related_many_to_many/7This function works as aggregate_related_many_to_one/5, but for modules defining many-to-many relations.
aggregate_related_many_to_one/7Get aggregate statistics about fields from related records in one-to-many relations.
before_delete/1A hook that gets called before a record is deleted.
before_save/1A hook that gets called before a record is saved.
count/1A shortcut for counting all the records for a module.
db_field/2Get the erlydb_field record matching the given field name.
db_field_names/1Get the module's database fields' names as atoms.
db_field_names_bin/1Get the module's database fields' names as binaries.
db_field_names_str/1Get the module's database fields' names as strings.
db_fields/1Get a list of erlydb_field records representing the database fields for the module.
db_num_fields/1Get the number of fields for the module.
db_pk_fields/1Return the list of fields (see @link erlydb_field) for which erlydb_field:key(Field) == primary is true.
db_table/1Get the table name for the module.
decrement/2Equivalent to decrement(Module, Fields, undefined).
decrement/3Similar to increment/3, but decrements the fields' values.
delete/1Delete the record from the database.
delete_all/1Delete all records from the module and return the number of records actually deleted.
delete_id/2Equivalent to delete_where(Module, {id, '=', Id}).
delete_where/2Delete all records matching the Where expressions, and return the number of deleted records.
driver/1Get the driver settings, defined in the call to erlydb:code_gen/3, ErlyDB uses for the module.
field_from_string/2A helper function for converting values encoded as strings to their corresponding Erlang types.
field_to_iolist/1A helper function used for converting field values to iolists.
field_to_iolist/2This function converts standard ErlyDB field values to iolists.
fields/0Return the list of fields that ErlyDB should use for the module.
find/3Find records for the module.
find_first/3Find the first record for the module according to the Where and Extras expressions.
find_id/2Find the record with the given id value.
find_max/4Find up to Max records from the module according to the Where and Extras expressions.
find_range/5Find up to Max records, starting from offset First, according to the Where and Extras expressions.
find_related_many_to_many/5This function works as find_related_many_to_one/4, but for modules defining many-to-many relations.
find_related_many_to_one/5Find the set of related records in a one-to-many relation.
find_related_one_to_many/3Find the related record for a record from a module having a many-to-one relation.
get/2A generic getter function ErlyDB uses to generate getters, e.g.
get_module/1Get the name of the module to which the record belongs.
increment/2Equivalent to increment(Module, Fields, undefined).
increment/3Increment the values for the listed fields in the module's table.
insert/1Insert one or more records into the database.
is_new/1Check if the record has been saved in the database.
is_new/2Set the record's 'is_new' field to the given value.
is_related/3
new/1Create a new record with all fields set to 'undefined'.
new_from_strings/2Equivalent to new_with(Module, Fields, fun field_from_string/2).
new_with/2Create a new record, setting its field values according to the key/value pairs in the Fields property list.
new_with/3Similar to new_with/2, but uses the ToFieldFun to convert property list values to field values before setting them.
relations/0Return the list of relations of the module.
remove_related_many_to_many/3Remove a related record in a many-to-many relation.
remove_related_many_to_many_all/5Remove all related recorded according to a Where and Extras clause in a many-to-many relation.
save/1Save an object by executing a INSERT or UPDATE query.
set/3A generic setter function ErlyDB uses to generate setters, e.g.
set_fields/3Set the record's fields according to the name/value pairs in the property list, e.g.
set_fields/4Set the record's fields using according to the property list name/value pairs, after first converting the values using the ToFieldFun.
set_fields_from_strs/3Equivalent to set_fields(Module, Record, Fields, fun field_from_string/2).
set_related_one_to_many/3Set the foreign key fields of a record from a module having a many-to-one relation to the primary key values of the Other record.
table/0Return the name of the table that holds the records for this module.
to_iolist/2Equivalent to to_iolist(Module, Recs, fun field_to_iolist/2).
to_iolist/3If Recs is a single record, convert each of a record's fields into an iolist and return the list of the converted records.
transaction/2Execute a transaction using the module's driver settings, as defined by the parameters passed to erlydb:code_gen/3.
type_field/0Return the column that identifies the types of the records in a table.
update/2Equivalent to update(Module, Props, undefined).
update/3Execute an UPDATE statement against the module's database table and return the number of rows updated.

Function Details

add_related_many_to_many/3

add_related_many_to_many(JoinTable::atom(), Rec::record(), OtherRec::record() | [record()]) -> {ok, NumAdded} | exit(Err)

Add a related record in a many-to-many relation.

This function isn't meant to be used directly; ErlyDB uses this function to generate special add_[RelatedModule] functions in modules that define many-to-many relations.

For instance, if you had a module 'student' that defined the relation {many_to_many, [class]}, and both 'student' and 'class' had a single primary key field called 'id', ErlyDB would add the function student:add_class(Student, Class) to the 'student' module. This function would insert the row [class:id(Class), student:id(Student)] to the class_student table, where the first column is 'class_id' and the second column is 'student_id'.

If either module has multiple primary key fields, all those fields are mapped to foreign keys in the many-to-many relation table.

after_delete/1

after_delete(X1::{Rec::record(), NumDeleted::integer()}) -> integer()

A hook that gets called after a record is deleted.

By default, this function returns an integer indicating the number of rows deleted.

You can implement this function in the target module to override the default behavior.

after_fetch/1

after_fetch(Rec::record()) -> record()

A hook that gets called after a record is fetched from the database.

By default, this function returns the original record. You can implement this function in the target module to override the default behavior.

after_save/1

after_save(Rec::record()) -> record()

A hook that gets called after a record is saved.

By default, this function returns the original record. You can implement this function in the target module to override the default behavior.

aggregate/5

aggregate(Module::atom(), AggFunc::atom(), Field::atom(), Where::where_expr(), Extras::extras_expr()) -> integer() | float() | exit(Err)

ErlyDB uses this function to generate derivative functions in target modules for calculating aggregate values for database fields. Drivative functions have the form Module:FuncName(Field), where 'Module' is the module name, 'FuncName' is 'count', 'avg', 'sum', 'min', 'max' or 'stddev', and Field is the name of the field. Derivative functions also have variations as described in find/3.

For example, in a module called 'person', ErlyDB would generate the following functions:

    person:count(Field)
    person:count(Field, Where)
    person:count_with(Field, Extras)
    person:count(Field, Where, Extras)
    person:avg(Field)
    ...
where Field can be any field in the person module (such as 'age', 'height', etc.).

See also: find/3.

aggregate_related_many_to_many/7

aggregate_related_many_to_many(OtherModule::atom(), JoinTable::atom(), AggFunc::atom(), Rec::record(), Field::atom(), Where::where_clause(), Extras::extras_clause()) -> [term()] | exit(Err)

This function works as aggregate_related_many_to_one/5, but for modules defining many-to-many relations.

See also: aggregate_related_many_to_one/5.

aggregate_related_many_to_one/7

aggregate_related_many_to_one(OtherModule::atom(), PkFks::term(), AggFunc::atom(), Rec::record(), Field::atom(), Where::where_expr(), Extras::extras_expr()) -> float() | integer() | exit(Err)

Get aggregate statistics about fields from related records in one-to-many relations.

This function isn't meant to be used directly; ErlyDB uses this function to generate special aggregate functions in modules that define one-to-many relations.

For example, if you had a module 'dog' that defined the relation {one_to_many, [bone]}, ErlyDB would add the following functions to the 'dog' module:

  dog:avg_of_bones(Dog, Field)
  dog:avg_of_bones(Dog, Field, Where)
  dog:avg_of_bones_with(Dog, Field, Extras)
  dog:avg_of_bones(Dog, Field, Where, Extras)

where 'Field' is the name of the field in the 'bone' module (e.g. 'size').

ErlyDB generates similar derivatives for all aggregate functions listed in aggregate/5.

See also: aggregate/5.

before_delete/1

before_delete(Rec::record()) -> record()

A hook that gets called before a record is deleted.

By default, this function returns the original record. You can implement this function in the target module to override the default behavior.

before_save/1

before_save(Rec::record()) -> record()

A hook that gets called before a record is saved.

By default, this function returns the original record. You can implement this function in the target module to override the default behavior.

count/1

count(Module::atom()) -> integer() | exit(Err)

A shortcut for counting all the records for a module. In generated modules, this function lets you can call Module:count() instead of Module:count('*').

In generated modules, the 'Module' parameter is omitted.

db_field/2

db_field(Module::atom(), FieldName::string() | atom()) -> erlydb_field() | exit(Err)

Get the erlydb_field record matching the given field name. If the field isn't found, this function exits.

In generated modules, the 'Module' parameter is omitted.

db_field_names/1

db_field_names(FileNames::[atom()]) -> [atom()]

Get the module's database fields' names as atoms.

In generated modules, this function takes 0 parameters.

db_field_names_bin/1

db_field_names_bin(FieldNamesBin::[binary()]) -> [binary()]

Get the module's database fields' names as binaries.

In generated modules, this function takes 0 parameters.

db_field_names_str/1

db_field_names_str(FieldNameStrs::[string()]) -> [string()]

Get the module's database fields' names as strings.

In generated modules, this function takes 0 parameters.

db_fields/1

db_fields(Fields::[erlydb_field()]) -> [erlydb_field()]

Get a list of erlydb_field records representing the database fields for the module.

In generated modules, this function takes 0 parameters.

db_num_fields/1

db_num_fields(NumFields::integer()) -> integer()

Get the number of fields for the module.

In generated modules, this function takes 0 parameters.

db_pk_fields/1

db_pk_fields(Fields::[erlydb_field()]) -> [erlydb_field()]

Return the list of fields (see @link erlydb_field) for which erlydb_field:key(Field) == primary is true.

In generated modules, the 'Fields' parameter is omitted.

db_table/1

db_table(Module::atom()) -> atom()

Get the table name for the module.

decrement/2

decrement(Module, Fields) -> term()

Equivalent to decrement(Module, Fields, undefined).

decrement/3

decrement(Module, Fields, Where) -> term()

Similar to increment/3, but decrements the fields' values.

delete/1

delete(Rec::record()) -> ok | exit(Err)

Delete the record from the database. To facilitate the after_delete hook, this function expects a single record to be deleted.

You can override the return value by implementing the after_delete hook.

delete_all/1

delete_all(Module::atom()) -> NumDeleted::integer() | exit(Err)

Delete all records from the module and return the number of records actually deleted.

Needless to say, use this function with extreme care.

In generated modules, the 'Module' parameter is omitted.

delete_id/2

delete_id(Module::atom(), Id::integer()) -> NumDeleted::integer()

Equivalent to delete_where(Module, {id, '=', Id}).

delete_where/2

delete_where(Module::atom(), Where::where_expr()) -> NumDeleted::integer() | exit(Err)

Delete all records matching the Where expressions, and return the number of deleted records.

In generated modules, the 'Module' parameter is omitted.

driver/1

driver(Driver::term()) -> term()

Get the driver settings, defined in the call to erlydb:code_gen/3, ErlyDB uses for the module.

In generated modules, the 'Driver' parameter is omitted.

field_from_string/2

field_from_string(ErlyDbField::erlydb_field(), Str::list()) -> term() | exit(Err)

A helper function for converting values encoded as strings to their corresponding Erlang types.

This function assumes field values are formatted according to the logic in field_to_iolist/2. In addition, it checks the following ranges:

second: 0-59
minute: 0-59
hour: 0-23
day: 1-31
month: 1-12
year: 1-9999

field_to_iolist/1

field_to_iolist(Val::term()) -> iolist()

Equivalent to field_to_iolist(Val, undefined).

A helper function used for converting field values to iolists.

field_to_iolist/2

field_to_iolist(Val::term, Field::erlydb_field()) -> iolist()

This function converts standard ErlyDB field values to iolists. This is its source code:

 	Type = 	if
         		Field =:= undefined -> undefined;
      			true -> erlydb_field:erl_type(Field)
     		end,
 
   case Val of
  	Bin when is_binary(Bin) -> Val;
  	List when is_list(List) -> Val;
  	Int when is_integer(Int) -> integer_to_list(Val);
  	Float when is_float(Float) -> float_to_list(Val);
 
   {datetime, {{_Year,_Month,_Day},{_Hour,_Minute,_Second}} = DateTime} ->
         format_datetime(DateTime);
   {{_Year,_Month,_Day},{_Hour,_Minute,_Second}} = DateTime when Type =:= datetime ->
         format_datetime(DateTime);
 	{date, {_Year,_Month,_Day} = Date} -> format_date(Date);
   {_Year,_Month,_Day} = Date when Type =:= date -> format_date(Date);
 	{time, {_Hour,_Minute,_Second} = Time}  -> format_time(Time);
   {_Hour,_Minute,_Second} = Time when Type =:= time -> format_time(Time);
 
  	undefined -> [];
  	_Other ->
  	    io_lib:format("~p", [Val])
     end.

fields/0

fields() -> '*' | [atom()]

Return the list of fields that ErlyDB should use for the module. You can override this function to specify which database fields from the table besides the id field should be exposed to records from the module. The '*' atom indicates all fields, which is the default setting.

Starting from ErlyWeb 0.6, you can add arbitrary metadata to each field by describing it as a tuple of the form {FieldName::atom(), Attributes::[term()]}. To retrieve the list of attributes for a field in a given model, you can call erlydb_field:attributes(Model:db_field(FieldName)).

If the list of attributes contains the atom read_only, ErlyDB excludes the field from INSERT and UPDATE statements.

It is also possible to add transient fields which do not exist in the database schema. To add transient fields it is currently necessary to overwrite the fields/0 function with the complete list of persistent fields plus the transient fields in any desired order (which also will be effective in the generated model functions), e.g.:

fields() -> [mydbfield, {mytransientfield, [transient]}, mydbfield2]

Note: You are free to call the fields() function from other modules to create arbitrary field set relations. For example, in a module called 'artist', you could have the function

fields() -> person:fields() ++ [genre, studio]

find/3

find(Module::atom(), Where::where_expr(), Extras::extras_expr()) -> [record()] | exit(Err)

Find records for the module. The Where and Extras clauses are, by default, ErlSQL expressions (see erlsql). Example Where expressions are
{name,'=',"Joe"}
and
{{age,'>',26},'and',{country,like,"Australia"}}

Example Extras expressions are
{limit, 7}
and
[{limit, 4,5}, {order_by, [name, {age, desc}, {height, asc}]}]

The main benefits of using ErlSQL are
- It protects against SQL injection attacks by quoting all string values.
- It simplifies embedding runtime variables in SQL expressions by automatically stringifying values such as numbers, atoms, dates and times.
- It's more efficient than string concatenation because it generates iolists of binaries, which generally consume less memory than strings.

Some drivers (e.g. the MySQL driver), let you use string and binary expressions directly when you pass the {allow_unsafe_statements, true} option to erlydb:code_gen/3. This usage is discouraged, however, because it makes you vulnerable to SQL injection attacks if you don't properly encode all your strings.

During code generation, ErlyDB creates a few derivatives from this function in target modules:

    find()  %% returns all records
    find(Where)
    find_with(Extras)
    find(Where, Extras)

(Note that in generated modules, the 'Module' parameter is omitted.)

ErlyDB creates similar derivatives for all find_x and aggregate functions in erlydb_base (e.g. find_first(), find_first(Where), find_first_with(Extras), find_first(Where, Extras)...).

find_first/3

find_first(Modue::atom(), Where::where_expr(), Extras::extras_expr()) -> record() | undefined | exit(Err)

Find the first record for the module according to the Where and Extras expressions. If no records match the conditions, the function returns 'undefined'.

In generated modules, the 'Module' parameter is omitted.

See also: find/3.

find_id/2

find_id(Module::atom(), Id::term()) -> Rec | exit(Err)

Find the record with the given id value.

In generated modules, the 'Module' parameter is omitted.

find_max/4

find_max(Module::atom(), Max::integer(), Where::where_expr(), Extras::extras_expr()) -> [record()] | exit(Err)

Find up to Max records from the module according to the Where and Extras expressions.

In generated modules, the 'Module' parameter is omitted.

See also: find/3.

find_range/5

find_range(Module::atom(), First::integer(), Max::integer(), Where::where_expr(), Extras::extras_expr()) -> [record()] | exit(Err)

Find up to Max records, starting from offset First, according to the Where and Extras expressions.

In generated modules, the 'Module' parameter is omitted.

See also: find/3.

find_related_many_to_many/5

find_related_many_to_many(OtherModule::atom(), JoinTable::atom(), Rec::record(), Where::where_clause(), Extras::extras_clause()) -> [record()] | exit(Err)

This function works as find_related_many_to_one/4, but for modules defining many-to-many relations.

See also: find_related_many_to_one/4.

find_related_many_to_one/5

find_related_many_to_one(OtherModule::atom(), PkFks::term(), Rec::record(), Where::where_expr(), Extras::extras_expr()) -> [record()] | exit(Err)

Find the set of related records in a one-to-many relation.

This function isn't meant to be used directly; ErlyDB uses this function to generate special 'find' functions in modules that define one-to-many relations.

For example, if you had a module 'dog' that defined the relation {one_to_many, [bone]}, ErlyDB would add the following functions to the 'dog' module:

  dog:bones(Dog)
  dog:bones(Dog, Where)
  dog:bones_with(Dog, Extras)
  dog:bones(Dog, Where, Extras)
 
  dog:bones_first(Dog)
  dog:bones_first(Dog, Where)
  dog:bones_first_with(Dog, Extras)
  dog:bones_first(Dog, Where, Extras)
 
  dog:bones_max(Dog, Max)
  dog:bones_max(Dog, Max, Where)
  dog:bones_max_with(Dog, Max, Extras)
  dog:bones_max(Dog, Max, Where, Extras)
 
  dog:bones_range(Dog, First, Max)
  dog:bones_range(Dog, First, Max, Where)
  dog:bones_range_with(Dog, First, Max, Extras)
  dog:bones_range(Dog, First, Max, Where, Extras)

See also: find/3, find_first/3, find_max/4, find_range/5.

find_related_one_to_many/3

find_related_one_to_many(OtherModule::atom(), PkFkfields::proplist(), Rec::record()) -> record() | exit(Err)

Find the related record for a record from a module having a many-to-one relation.

This function isn't meant to be used directly; ErlyDB uses it to generate special 'find' functions for related records in modules defining many-to-one relations.

For example, if you had a module 'bone' that defined the relation {many_to_one, [dog]}, and 'dog' had a single primary key field called 'id', ErlyDB would add the function bone:dog(Bone) to the 'bone' module. This function would be equivalent to dog:find({id,=',bone:dog_id(Bone)}).'.

This function works as expected when the related module has multiple primary key fields.

get/2

get(Idx::integer(), Rec::record()) -> term()

A generic getter function ErlyDB uses to generate getters, e.g. person:name(Person), for all of a module's database fields.

get_module/1

get_module(Rec::record()) -> atom()

Get the name of the module to which the record belongs.

increment/2

increment(Module, Fields) -> term()

Equivalent to increment(Module, Fields, undefined).

increment/3

increment(Module::atom(), Fields::[atom()], Where::where_expr()) -> NumRowsUpdated::integer()

Increment the values for the listed fields in the module's table. This executes the query

  UPDATE [table] SET [field1] = [field1] + 1, [field2] = [field2] + 1...
  WHERE [where_expr]

insert/1

insert(Rec::record() | [record()]) -> NumInserts::integer() | exit(Err)

Insert one or more records into the database.

If you don't need to get the saved records' auto-generated ids, this function is much more efficient than calling save/1 on each record as this function saves the entire list of records in one INSERT statement.

is_new/1

is_new(Rec::record()) -> boolean()

Check if the record has been saved in the database.

is_new/2

is_new(Rec::record(), Val::boolean()) -> NewRec::record()

Set the record's 'is_new' field to the given value.

is_related/3

is_related(JoinTable, Rec, OtherRec) -> term()

new/1

new(Module::atom()) -> record()

Create a new record with all fields set to 'undefined'.

In generated modules, the 'Module' parameter is omitted.

Generated modules also have the function new/N, where N is the number of fields the module uses (as returned from db_num_fields/0), minus 1 if the module has an 'identity' primary key field, which is initialized by the DBMS. This function lets you create a new record and initialize its fields with a single call. Note that fields that end with '_id' have a special property: they accept either a literal id value, or a record from a related table that has an 'id' primary key. For example, if the 'project' module had the fields 'name' and 'language_id', project:new("ErlyWeb", Erlang) would be equivalent to project:new("ErlyWeb", language:id(Erlang)).

new_from_strings/2

new_from_strings(Module::atom(), Fields::[{atom() | list(), list()}]) -> record() | exit(Err)

Equivalent to new_with(Module, Fields, fun field_from_string/2).

See also: field_from_string/2.

new_with/2

new_with(Module::atom(), Fields::proplist()) -> record() | exit(Err)

Create a new record, setting its field values according to the key/value pairs in the Fields property list.

In generated modules, the 'Module' parameter is omitted.

See also: set_fields/3.

new_with/3

new_with(Module::atom(), Fields::proplist(), ToFieldFun::function()) -> record() | exit(Err)

Similar to new_with/2, but uses the ToFieldFun to convert property list values to field values before setting them. ToFieldFun accepts an erlydb_field record and the original value and returns the new value.

In generated modules, the 'Module' parameter is omitted.

relations/0

relations() -> [{one_to_many, [atom()]} | {many_to_many, [atom()]}]

Return the list of relations of the module. By overriding the function, you can tell ErlyDB what relations the module has. Possible relations are {one_to_many, [atom()]} and {many_to_many, [atom()]}. This function returns a list of such relations.

remove_related_many_to_many/3

remove_related_many_to_many(JoinTable::atom(), Rec::record(), OtherRec::record()) -> NumRemoved::interger() | exit(Err)

Remove a related record in a many-to-many relation.

This function isn't meant to be used directly; ErlyDB uses this function to generate special remove_[RelatedModule] functions in modules that define many-to-many relations.

For instance, if you had a module 'student' that defined the relation {many_to_many, [class]}, and module 'class' and 'student' had a single primary key field called 'id', ErlyDB would add the function student:remove_class(Student, Class) to the 'student' module. This function would remove the row [class:id(Class), student:id(Student)] from the class_student table, where the first column is 'class_id' the second column is 'student_id'.

This function expects a single record to be removed.

remove_related_many_to_many_all/5

remove_related_many_to_many_all(JoinTable::atom(), OtherTable::atom(), Rec::record(), Where::where_clause(), Extras::extras_clause()) -> {ok, NumDeleted} | exit(Err)

Remove all related recorded according to a Where and Extras clause in a many-to-many relation.

This function isn't meant to be used directly; ErlyDB uses this function to generate special remove_all_[RelatedModuleAsPlural] functions in modules that define many-to-many relations.

For instance, if you had a module 'student' that defined the relation {many_to_many, [class]}, and module 'class' and 'student' had a single primary key field called 'id', ErlyDB would add the function student:remove_all_classes(Student, Where, Extras) to the 'student' module. This function would remove [class:id(Class), student:id(Student)] rows from the class_student table according to the Where and Extras clauses.

In addition to student:remove_all_classes/3, ErlyDB would generate additional variations. This would be the full list:

  student:remove_all_classes(Student)
  student:remove_all_classes(Student, Where)
  student:remove_all_classes_with(Student, Extras)
  student:remove_all_classes(Student, Where, Extras)
Limitation: for self-referencing many-to-many relations, all variations accepting a Where clause are currently not generated.

save/1

save(Rec::record()) -> record() | exit(Err)

Save an object by executing a INSERT or UPDATE query. This function returns a modified tuple representing the saved record or throws an exception if an error occurs.

With MySQL, for INSERT statements for records with identity primary keys, this function sets the primary key field to the value returned from calling "SELECT last_insert_id()".

You can override the return value by implementing the after_save hook.

set/3

set(Idx::integer(), Rec::record(), NewVal::term()) -> record()

A generic setter function ErlyDB uses to generate setters, e.g. person:name(Person, NewName), for all of a module's database fields.

set_fields/3

set_fields(Module::atom(), Record::record(), Fields::proplist()) -> record() | exit(Err)

Set the record's fields according to the name/value pairs in the property list, e.g.

  Language1 = language:set_fields(Language, [{name,"Erlang"},
                      {creation_year, 1981}])

The property list can have keys that are either strings or atoms. If a field name doesn't match an existing field for this record, this function exits.

In generated modules, the 'Module' parameter is omitted.

set_fields/4

set_fields(Module::atom(), Record::record(), Fields::proplist(), ToFieldFun::function()) -> record() | exit(Err)

Set the record's fields using according to the property list name/value pairs, after first converting the values using the ToFieldFun. ToFieldFun accepts an erlydb_field record and the original value and returns the new value.

In generated modules, the 'Module' parameter is omitted.

set_fields_from_strs/3

set_fields_from_strs(Module::atom(), Record::record(), Fields::proplist()) -> record() | exit(Err)

Equivalent to set_fields(Module, Record, Fields, fun field_from_string/2).

See also: field_from_string/2.

set_related_one_to_many/3

set_related_one_to_many(Rec::record(), PkFkFields::proplist(), Other::record()) -> record() | exit(Err)

Set the foreign key fields of a record from a module having a many-to-one relation to the primary key values of the Other record.

This function isn't meant to be used directly; ErlyDB uses it to generate special setters for related records in modules that define many-to-one relations.

For example, if you had a module 'bone' that defined the relation {many_to_one, [dog]}, and the 'dog' module had a single primary key field called 'id', ErlyDB would add the function bone:dog(Bone, Dog) to the 'bone' module. This function would be equivalent to bone:dog_id(Bone, dog:id(Dog)), with an extra check to verify that Dog is saved in the database.

If 'dog' had more than one primary key field, this function would set the values for all foreign key fields in the 'bone' record to the values of the 'dog' record's corresponding primary key values.

table/0

table() -> atom()

Return the name of the table that holds the records for this module. By default, the table name is identical to the Module's name, but you can override this to use a different table name.

to_iolist/2

to_iolist(Module::atom(), Recs::record() | [record()]) -> [iolist()] | [[iolist()]]

Equivalent to to_iolist(Module, Recs, fun field_to_iolist/2).

to_iolist/3

to_iolist(Module::atom(), Rec::record() | [Rec::record()], ToIolistFun::to_iolist_function()) -> [iolist()] | [[iolist()]]

If Recs is a single record, convert each of a record's fields into an iolist and return the list of the converted records. If Recs is a list of records, to_iolist is recursively called on each record, and the list of results is returned.

ToIoListFun is a function that accepts an erlydb_field structure and a field value and returns an iolist (see field_to_iolist/2 for an example).

In generated modules, the 'Module' parameter is omitted.

transaction/2

transaction(Module::atom(), Fun::function()) -> {atomic, Result::term()} | {aborted, Details}

Execute a transaction using the module's driver settings, as defined by the parameters passed to erlydb:code_gen/3.

In generated modules, the 'Module' parameter is omitted.

type_field/0

type_field() -> atom()

Return the column that identifies the types of the records in a table. This is useful when storing records from multiple modules in a single table, where each module uses a different subset of fields. If you override this function, in most cases you should also override fields/0.

update/2

update(Module, Props) -> term()

Equivalent to update(Module, Props, undefined).

update/3

update(Module::atom(), Props::proplist(), Where::where_expr()) -> NumUpdated::integer() | exit(Err)

Execute an UPDATE statement against the module's database table and return the number of rows updated.

'Props' is a list of 2 element tuples, where the first element is an atom representing the field's name, and the second value is an ErlSQL expression representing its value.

'Where' is an ErlSQL 'where' expression.

In generated modules, the 'Module' parameter is omitted.

Example: Calling person:update([{name,<<"Jane">>}, {age, {age, '+', 1}}], {id,'=',7}) would yield the statement UPDATE person SET name='Jane', age=age+1 WHERE id=7.

The UPDATE statement is executed in a transactional context.