NAME
DBIx::DataModel::Doc::Reference - General reference for DBIx::DataModel
DOCUMENTATION CONTEXT
This chapter is part of the DBIx::DataModel
manual.
DESCRIPTION
WARNING : Version 2 of DBIx::DataModel
is a major refactoring from versions 1.*, with a number of incompatible changes in the API (classes renamed, arguments renamed or reorganized, etc. -- see DBIx::DataModel::Doc::Delta_2.0). The documentation below has not been fully updated yet to reflect these changes.
This chapter is the detailed description of DBIx::DataModels
methods for creating and using schemas.
Automatic schema generation from external sources is not covered here; see DBIx::DataModel::Schema::Generator.
Detailed use of statements is not covered here either, because explicit programming of the various statement phases (sqlize, prepare, bind, execute, etc.) is seldom needed. If you want to finely tune these operations, read the DESIGN section of the manual (purpose, lifecycle, etc.), and the DBIx::DataModel::Statement page.
GENERAL CONVENTION
Methods listed below for declaring schema, tables, associations, etc. come in two flavours :
a "front-end" method, starting with an uppercase letter, that uses positional parameters. This version is prefered for conciseness and for backwards compatibility.
a "back-end" method, called
define_schema
,define_table
, etc., that uses named parameters. This version is prefered for completeness.
The invocant for front-end methods can be either the Schema class name, or the meta-schema instance. The invocant for back-end methods must be the meta-schema instance.
META-SCHEMA DECLARATION
Schema() / define_schema()
# front-end method
my $schema_class = DBIx::DataModel->Schema($schema_name, %options);
# or (back-end method)
my $meta_schema
= DBIx::DataModel->define_schema(class => $schema_name, %options);
Creates a new Perl class of name $schema_name
that represents a database schema. That class inherits from DBIx::DataModel::Schema. At the same time, an instance of DBIx::DataModel::Meta::Schema is also created, for holding meta-information about that schema (for example lists of classes, associations, types, etc. that will be declared within the schema).
The front-end and back-end method illustrated above are both just a façade; they merely call "new" in DBIx::DataModel::Meta::Schema, where the real work is performed. Schema()
returns the created class, while define_schema()
returns the meta-schema instance.
Possible %options
are :
- class
-
Name of the Perl schema class to be created.
- isa
-
Parent class(es) for that schema class (scalar or arrayref). The default parent is DBIx::DataModel::Schema.
- auto_insert_columns
-
A hashref specifying columns to be automatically inserted in every table. See "define_auto_insert_columns()".
- auto_update_columns
-
A hashref specifying columns to be automatically updated in every table. See "define_auto_update_columns()".
- no_update_columns
-
A hashref specifying columns to be automatically ignored in insert/update operations, for every table. See "define_no_update_columns()".
- sql_no_inner_after_left_join
-
An optional boolean; if true, a LEFT OUTER JOIN in a multi-steps join specification will force all subsequent joins to be also LEFT. For example in the fake datamodel used in the rest of this documentation, a join like
HR->join(qw/Employee activities department)->...
would be interpreted as
T_Employee LEFT OUTER JOIN T_Activity ON ... LEFT OUTER JOIN T_Department ON ...
even if the association betwen
Activity
andDepartment
is many-to-one (so theoretically this would result in a INNER JOIN by default). - table_parent, join_parent
-
Optional application-specific classes, to be used instead of the builtin classes, as parents for tables and joins declared in this schema.
- table_metaclass, join_metaclass, association_metaclass, path_metaclass, type_metaclass
-
Optional application-specific classes, to be used instead of the builtin metaclasses, for instanciating meta-objects declared in this schema, .
- statement_class
-
Optional application-specific class to be used instead of the builtin class DBIx::DataModel::Statement for instanciating statements.
META-SCHEMA POPULATION (DECLARING TABLES, ASSOCIATIONS, etc.)
This chapter deals with all methods that will populate the structure of a meta-schema : declaring tables, associations, types, navigation methods, etc. Such objects are defined statically and will not change during program execution.
By contrast, the "SCHEMA PARAMETERS" chapter deals with properties specific to each schema instance, such as database connection, debugging properties, etc.
Table() / define_table()
# front-end method
$schema_class->Table($class_name, $db_name, @primary_key, \%options);
# or (back-end method)
$meta_schema->define_table(%options);
Creates a new Perl class of name $class_name
that represents a database table. The new class inherits from the table_parent
declared in the schema (by default : DBIx::DataModel::Source::Table). At the same time, an instance of the table_metaclass
is also created (b< default : DBIx::DataModel::Meta::Source::Table), for holding meta-information about that table (database name, primary key, paths to other tables, etc.).
Both methods illustrated above call the "new" in DBIx::DataModel::Source::Table constructor, where the real work is performed. They return the $schema
or $meta_schema
on which they were invoked.
Possible %options
are :
- class => $string
-
Name of the class to be created. If
$class_name
contains no::
, then the schema name is prepended to it (so the new table class is created in the namespace of the schema, which is a recommended best practice). - db_name => $string
-
SQL name of the database table or view that will be accessed through this class. Actually, it might be any SQL clause, like for example
Table1 t1 INNER JOIN Table2 t2 ON t1.fk=t2.pk
; see the "View()" method below. - primary_key => $string | \@array
-
Name of the column (or list of columns) that hold the primary key for that table.
- default_columns => $string
-
Whatever will be injected into SELECT statements, when no
-columns
parameter is explicitly supplied. The default is'*'
. - where => \%hash | \@array
-
An optional reference to a WHERE condition, in SQL::Abstract::More format. That condition will be automatically injected into every SELECT statement on this table. When working with regular tables, this parameter is always empty; it is only useful for declaring
DBIx::DataModel
views (see the "View()" method below). - parents => [$parent1, ...]
-
List of meta-tables from which this table will inherit. This can be useful if your database supports table inheritance (like for example PostgreSQL), and you want to reflect the inheritance structure within the Perl table classes.
- aliased_tables
-
[TODO]
- column_types
-
[TODO]
- column_handlers
-
[TODO]
{column1 => \%handlers1, ...}
where
%handlers1
contains {handler_name_1 => coderef1, }Associates some handlers to some columns in the current table class. Then, when you call
$obj->apply_column_handler($handler_name)
: each column having a handler of the corresponding name will execute the associated code. This can be useful for all sorts of data manipulation :converting dates between internal database format and user presentation format
converting empty strings into null values
inflating scalar values into objects
column data validation
[TODO]
- auto_insert_columns
-
[TODO]
- auto_update_columns
-
[TODO]
- no_update_columns
-
[TODO]
View()
$meta_schema->View($class_name, $default_columns, $db_tables,
\%where, @parent_tables);
This is another front-end method for define_table(), for creating a new Perl class of name $class_name
that represents a SQL SELECT request of shape
SELECT $columns FROM $db_tables [ WHERE %where ]
The optional list of @parent_tables
contains names of Perl table classes from which the view will also inherit. If the SQL code in $db_tables
is a join between several tables, then it is a good idea to mention these tables in @parent_tables
, so that their path methods become available to instances of this view. Be careful about table names : the SQL code in $db_tables
should contain database table names, whereas the members of @parent_tables
should be Perl table classes.
Perl views as defined here have nothing to do with views declared in the database itself. Perl views are totally unknown to the database, they are just abstractions of SQL statements. If you need to access database views, just use the Table()
declaration, like for a regular table.
Association() / Composition() / define_association ()
# front-end method
$schema->Association([$class1, $role1, $multiplicity1, @columns1],
[$class2, $role2, $multiplicity2, @columns2]);
# or (special kind of association)
$schema->Composition([$class1, $role1, $multiplicity1, @columns1],
[$class2, $role2, $multiplicity2, @columns2]);
# or (back-end method)
$meta_schema->define_association(
name => $association_name, # optional
kind => $kind, # 'Association' or 'Composition'
A => {
table => $meta_table_instance,
role => $role_name, # optional
multiplicity => $multiplicity_spec, # ex. "1..*"
join_cols => [$col1, ...] # optional
},
B => { ... }, # same structure as 'A'
);
Declares an association between two tables (or even two instances of the same table). The front-end methods shown above are equivalent to
$schema->metadm->define_association(
A => {table => $class1->metadm, role => $role1,
multiplicity => $multiplicity1, join_cols => \@columns1},
B => {table => $class2->metadm, role => $role2,
multiplicity => $multiplicity2, join_cols => \@columns2},
kind => 'Association' # or 'Composition'
);
The arguments are :
- A
-
A description of the first association end, which is composed of
- table
-
An instance of DBIx::DataModel::Meta::Source::Table.
- role
-
The role name of that source within the association. A Perl method of the same name will be defined in the remote source (the other end of the association). Besides, the role name is also used when building joins through
$schema->join(qw/FirstTable role1 role2 .../)
One of the role names in the association can be anonymous (undef), but not both. If anonymous, there will be no Perl method and no possibility to join in that direction, so it defines a unidirectional association.
If several associations attempt to define the same role name in the same table, an exception is generated.
- multiplicity
-
The multiplicity specification, i.e. the minimum and maximum number of occurrences of that association end, for any given instance of the other end (if not clear, see UML textbooks).
The multiplicity can be expressed either as an arrayref
[$min, $max]
, or as a string"$min..$max"
. The$max
can be'*'
or'n'
, which is interpreted as the maximum integer value. If expressed as a string, a mere'*'
is interpreted as'0..*'
, and a mere'1'
is interpreted as'1..1'
.Numbers different from
0
,1
or*
may be given as multiplicity bounds, but this will be just documentary : technically, all that matters iswhether the lower bound is 0 or more (if 0, generated joins will be left joins, otherwise inner joins)
whether the upper bound is 1 or more (if 1, the associated method returns a single object, otherwise it returns an arrayref)
- join_cols
-
An arrayref of columns that participate in the database join, for this side of the association. The full database join will be built by creating a
LEFT|INNER JOIN ... ON ..
clause in which the left-hand and right-hand sides of theON
subclause come from thejoin_cols
of both association ends.This argument is optional: if absent, it will be filled by default by taking the primary key of the table with minimum multiplicity 1, for both sides of the association. This default behaviour is convenient for data models where primary keys and foreign keys are identical (for example
dpt_id
both as primary key inDepartment
and as foreign key inActivity
). Some data models have a different policy, where primary keys are always named the same (for exampleid
), and foreign keys are named after the related table name : in such models, the default does not work, and you have to specify the join columns explicitly.If the association is many-to-many (i.e. if the maximum multiplicity is greater than 1 on both sides), then
join_cols
takes a special meaning : it no longer represents database columns, but rather represents two role names (in the sense just defined above) to follow for reaching the remote end of the association. Thereforejoin_cols
must contain exactly 2 items in that case : the path to the intermediate table, and the path from the intermediate table to the remote end. Here is again the example from "SYNOPSIS" in DBIx::DataModel :My::Schema->define_association( kind => 'Association', A => { table => My::Schema::Department->metadm, role => 'departments', multiplicity => '*', join_cols => [qw/activities department/], }, B => { table => My::Schema::Employee->metadm, role => 'employees', multiplicity => '*', join_cols => [qw/activities employee/], }, );
- B
-
A description of the second association end, following exactly the same principles as for the
'A'
end. - name
-
Optional name for the association (otherwise an implicit name will be built by default from the concatenation of the role names).
- kind
-
A string describing the association kind, i.e. one of :
Association
,Aggregation
orComposition
.Compositions are associations with some additional semantics. In UML class diagrams, compositions are pictured with a black diamond on one side : this side will be called the composite class, while the other side will be called the component class. In
DBIx::DataModel
, the diamond (the composite class) corresponds to theA
association end, and the component class corresponds to theB
end, so the order is important (while for plain associations the order makes no difference).The UML intended meaning of a composition is that objects of the component classes cannot exist outside of their composite class. Within
DBIx::DataModel
, the additional semantics for compositions is to support cascaded insertions and deletions, and auto-expansion; so the special semantis attached to kindComposition
is :the multiplicity must be 1-to-n
the
'B'
end of the association (the "component" part) must not be component of another association (it can only be component of one single composite table).this association can be used for auto-expanding the composite object (i.e. automatically fetching all component parts from the database) -- see "expand" in DBIx::DataModel::Source and "auto_expand"
this association can be used for cascaded inserts like
$source->insert({ column1 => $val1, ... $component_name1 => [{$sub_object1}, ...], ... })
see "insert"
The main record will be inserted in the composite class, and within the same transaction, subrecords will be inserted into the component classes, with foreign keys automatically filled with appropriate values.
this association can be used for cascaded deletes : the argument to a
delete
may contain lists of component records to be deleted together with the main record of the composite class.
The association also creates instances of DBIx::DataModel::Meta::Path for representing the directional paths between those sources.
Type()
# front_end_method
$schema->Type($type_name =>
$handler_name_1 => sub { ... },
$handler_name_2 => sub { ... },
...
);
or in verbose form :
$meta_schema->define_type(
name => $type_name,
handlers => {
$handler_name_1 => sub { ... },
$handler_name_2 => sub { ... },
...
},
);
This declares a type, which is just a hashref of handler names and handler bodies (coderefs). The type can then be applied to some columns in some tables; this is usually done in the Table declaration (column_types
argument), or can be applied later through the "define_column_type" method.
Handlers receive the column value as usual through $_[0]
. If the value is to be modified (for example for scalar conversions or while inflating values into objects), the result should be put back into $_[0]
. In addition to the column value, other info is passed to the handler :
$handler_body = sub {
my ($column_value, $obj, $column_name, $handler_name) = @_;
my $new_val = $obj->compute_new_val($column_value, ...);
$column_value = $new_val; # WRONG : will be a no-op
$_[0] = $new_val; # OK : value is converted
}
The second argument $obj
is the object from where $column_value
was taken -- most probably an instance of a Table or Join class. Use this if you need to read some contextual information, but avoid modifying $obj
: you would most probably get unexpected results, since the collection of available columns may vary from one call to the other.
Other arguments $column_name
and $handler_name
are obvious.
Handler names from_DB and to_DB have a special meaning : they are called automatically just after reading data from the database, or just before writing into the database. Handler name validate is used by the method "has_invalid_columns()".
The "SYNOPSIS" in DBIx::DataModel shows some examples for types "Date", "Percent" and "Multivalue".
A Type
does not create a Perl class.
define_join()
This method builds or retrieves a pre-existing subclass of DBIx::DataModel::Source::Join, and returns the associated meta-object (an instance of DBIx::DataModel::Meta::Source::Join).
my $meta_join = $meta_schema->define_join($table, $path1, $path2, ..);
The join starts from a given table class and follows one or several associations through their path names; the resulting SQL request contains parameters automatically inferred from the associations. So for example
$meta_schema->define_join(qw/Department activities employee/);
is more or less equivalent to
my $sql = <<_EOSQL_
Department
LEFT OUTER JOIN Activity ON Department.dpt_id = Activity.dpt_id
LEFT OUTER JOIN Employee ON Activity.emp_id = Employee.emp_id
_EOSQL_
$schema->View("Department=>activities=>employee", '*', $sql,
qw/Department Activity Employee/);
For each pair of tables, the kind of join is chosen according to the multiplicity declared with that role in the association : if the minimum multiplicity is 0, the join will be LEFT OUTER JOIN; otherwise it will be a usual inner join (exception if $meta_schema->sql_no_inner_after_left_join
is true : after a first left join, all remaining tables are also connected through additional left joins). The default kind of join chosen by this rule may be overriden by inserting intermediate connectors in the list, namely '<=>'
for inner joins and '=>'
for left joins. So for example
$meta_schema->define_join(qw/Department <=> activities <=> employee/);
becomes equivalent to
my $sql = <<_EOSQL_
Department
INNER JOIN Activity ON Department.dpt_id = Activity.dpt_id
INNER JOIN Employee ON Activity.emp_id = Employee.emp_id
_EOSQL_
Table names in the SQL statement correspond to what was defined in the $meta_schema->Table(...)
declarations. However, tables may be aliased using |
as a separator :
$meta_schema->define_join(qw/Department|dpt activities|act employee|emp/)
->select(-columns => qw/dpt.name act.d_begin emp.lastname/,
-where => {"dpt.dpt_name" => {-like => "A%"}});
which generates
SELECT dpt.name, act.d_begin, emp.lastname
FROM Department AS dpt
LEFT OUTER JOIN Activity AS act ON dpt.dpt_id = act.dpt_id
LEFT OUTER JOIN Employee AS emp ON act.emp_id = emp.emp_id
WHERE dtp.dpt_name like 'A%'
All tables participating in a join
are stacked, and further roles are found by walking up the stack. So in
..->define_join(qw/FirstTable path1 path2 path3/)
we must find a path1
in FirstTable
, from which we know what will be the Table2
. Then, we must find a path2
in in Table2
, or otherwise in FirstTable
, in order to know Table3
. In turn, path3
must be found either in Table3
, or in Table2
, or in FirstTable
, etc. To resolve ambiguities, prefix the path by the name or alias of the targeted source, such as :
..->define_join(qw/FirstTable path1|p1
FirstTable.path2
p1.path3|p3
path2.path4/)
The name of the resulting join class will be composed by concatenating table, connectors and path names, including optional aliases. If the same sequence of table and paths was already encountered before, the Perl class already exists, and its corresponding meta-object is returned; otherwise, a new Perl class is created together with its meta-object.
The main purpose of define_join
is to gain efficiency in interacting with the database. If we write
foreach my $dpt (@{$schema->table('Department')->select}) {
foreach my $act ($dpt->activities) {
my $emp = $act->employee;
printf "%s works in %s since %s\n",
$emp->{lastname}, $dpt->{dpt_name}, $act->{d_begin};
}
}
many database calls are generated behind the scene, in the loops that call the activities
and employee
methods. Instead we could write
my $join = $meta_schema->define_join(qw/Department activities employee/);
foreach my $row (@{$join->select}) {
printf "%s works in %s since %s\n",
$row->{lastname}, $row->{dpt_name}, $row->{d_begin};
}
which generates one single call to the database.
define_navigation_method
$table->define_navigation_method($meth_name => qw/role1 role2 .../,
\%optional_select_args);
Inserts into the $table
class a new method named $meth_name
, that will automatically call "define_join()" and then select(), passing %optional_select_args
to the select
call. This is useful for joining several tables at once, so for example with
$meta_schema->table('Department')->define_navigation_method(
employees => qw/activities employee/
);
we can then write
my $empl_ref = $some_dept->employees(-where => {gender => 'F'},
-columns => [qw/firstname lastname]);
This method is used internally to implement many-to-many associations; so if you have only two roles to follow, you would probably be better off by defining the association, which is a more abstract notion. Direct calls to define_navigation_method
are still useful if you want to follow three or more roles at once.
The last argument to define_navigation_method
is an optional hashref; if present, the hash will be passed as initial argument to the select
call.
define_column_type()
$meta_table->define_column_type($type_name, @column_names);
Registers type $type_name
to be applied to columns with name in @column_names
, within the target $meta_table
.
define_column_handlers()
$meta_table->define_column_handlers($column_name,
$handler_name_1 => sub { ... },
...
);
Registers handlers to be applied to $column_name
, within the target $meta_table
. The main purpose of this method is for implementing the higher-level "define_column_type()" method; however it can also be called directly, without the need for defining a type.
define_auto_expand
$meta_table->define_auto_expand(@component_names);
Generates an "auto_expand()" method for the class, that will autoexpand on the roles listed (i.e. will call the appropriate method and store the result in a local slot within the object). In other words, the object knows how to expand itself, fetching information from associated tables, in order to build a data tree in memory. Only component names declared through Composition() may be auto-expanded.
Be careful about performance issues: when an object uses auto-expansion through a call to "autoExpand()", every auto-expanded role will generate an additional call to the database. This might be slow, especially if there are recursive auto-expansions; so in some cases it will be more appropriate to flatten the tree and use database joins, typically through the method join().
META-SCHEMA NAVIGATION
Meta-schema methods
tables
my @meta_tables = $meta_schema->tables;
Returns all of DBIx::DataModel::Meta::Source::Table instances declared in this $meta_schema
.
table
my $meta_table = $meta_schema->table($table_name);
Returns the single instance of DBIx::DataModel::Meta::Source::Table with name $table_name
, or undef
.
associations
my @associations = $meta_schema->associations;
Returns all of DBIx::DataModel::Meta::Association instances declared in this $meta_schema
.
association
my $association = $meta_schema->associations($association_name);
Returns the single instance of DBIx::DataModel::Meta::Source::Association with name $association_name
, or undef
.
types
my @types = $meta_schema->types;
Returns all of DBIx::DataModel::Meta::Type instances declared in this $meta_schema
.
type
my $type = $meta_schema->type($type_name);
Returns the single instance of DBIx::DataModel::Meta::Type with name $type_name
, or undef
.
joins
my @joins = $meta_schema->joins;
Returns all of DBIx::DataModel::Meta::Source::Join instances declared in this $meta_schema
.
join
my $join = $meta_schema->join($join_name);
Returns the single instance of DBIx::DataModel::Meta::Source::Join with name $join_name
, or undef
.
other accessors
Accessor methods are defined for the following members of the $meta_schema
:
- class
- sql_no_inner_after_left_join
- auto_insert_columns
- auto_update_columns
- no_update_columns
- table_parent
- table_metaclass
- join_parent
- join_metaclass
- association_metaclass
- path_metaclass
- type_metaclass
- statement_class
Meta-source methods
Accessor methods are defined for the following members of a $meta_source
(instance of either DBIx::DataModel::Meta::Source::Table or DBIx::DataModel::Meta::Source::Join) :
In addition, other methods are defined :
ancestors()
Returns a flattened list of recursive calls to the "parents()" method.
auto_insert_column
Returns a flattened hash, built from auto_insert_columns
declared in this source, in its ancestors, or in the $meta_schema
.
auto_update_column
Returns a flattened hash, built from auto_update_columns
declared in this source, in its ancestors, or in the $meta_schema
.
no_update_column
Returns a flattened hash, built from no_update_columns
declared in this source, in its ancestors, or in the $meta_schema
. Keys are column names, values are insignificant.
path
Returns a flattened hash, built from no_update_columns
declared in this source, in its ancestors, or in the $meta_schema
.
db_from
Returns what will be injected as -from
argument into the "select" in SQL::Abstract::More call.
where
Returns the optional "where" condition associated with this source (in the case of "View()").
Meta-table methods
In addition to the $meta_source
methods above, the following methods are defined for an instance of DBIx::DataModel::Meta::Source::Table :
components
Returns the list of other meta-sources that have been declared as components of this source, through the "Composition()" declaration.
Association methods
schema
The DBIx::DataModel::Meta::Schema instance in which this association is declared.
A
Returns the hashref describing the "A" end of the association. Keys in the hashref are :
- table
-
The DBIx::DataModel::Meta::Source::Table instance.
- role
-
The optional string defining the role of this source in the association.
- multiplicity
-
An arrayref
[$min, $max]
of UML minimum and maximum multiplicity. - join_cols
-
An arrayref of column names participating in the join on this side of the association.
B
Returns the hashref describing the "B" end of the association.
name
Returns the association name
kind
Returns the association kind (Association
or Composition
).
path_AB
Returns the DBIx::DataModel::Meta::Path object describing the path from A to B.
path_BA
Returns the DBIx::DataModel::Meta::Path object describing the path from B to A.
Path methods
name
The name of this path.
from
Reference to the DBIx::DataModel::Meta::Source where this path starts.
to
Reference to the DBIx::DataModel::Meta::Source where this path ends.
on
Hashref for generating the join condition (keys are colums for the left-hand side, values are columns for the right-hand side).
multiplicity
association
Reference to the DBIx::DataModel::Meta::Association that created this path.
direction
Either "AB"
or "BA"
.
Type methods
schema
The DBIx::DataModel::Meta::Schema instance in which this type is declared.
name
Name of this type.
handlers
Hashref of handlers declared in this type (keys are handler names, values are handler bodies, i.e. coderefs).
SCHEMA INSTANCIATION AND PARAMETERS
A $schema
is an instance of a subclass of DBIx::DataModel::Schema. The subclass holds a reference to a $meta_schema
where all information about tables, associations, etc. is kept. Each instance of that subclass holds information about the database connection, the debugging status, etc.
A schema subclass can have several instances; in that case, the application runs in multi-schema mode. However, multi-schema mode is only useful in some special situations, like for example transferring data between several databases; in most common cases, a single-schema mode is enough.
Single-schema mode is activated by default, which means that all method calls can be performed directly on the subclass; the subclass will manage a singleton instance, and will delegate calls to that singleton. This is the recommended way to work with DBIx::DataModel
, because it uses less memory, and simplifies the application code (there is no need to pass a $schema
reference around between all modules).
If you need it, multi-schema mode is activated by calling the new()
method, as many times as you need. Once this mode is activated, it is not possible to go back to single-schema mode. Furthermore, multi-schema mode should be activated before the singleton has been created, i.e. before any call to the class methods below.
Because of this duality, all methods below, described as $schema->some_method(...)
, can be called either as class methods (single-schema mode), or as instance methods (multi-schema mode).
Schema::new()
my $schema = $schema_subclass->new(%options);
As just explained, this activates multi-schema mode, and returns a new schema instance. %options
may contain some initial settings for dbh
, debug
, etc.; this is the same as creating the schema first, and then calling the setter methods below $schema->dbh(...)
, $schema->debug(...)
, etc.
dbh
my $dbh = DBI::connect(...);
$schema->dbh($dbh, %options); # set
$schema->dbh([$dbh, %options]); # set, alternative syntax
my $dbh = $schema->dbh; # get back just the dbh
my ($dbh, %options) = $schema->dbh; # get back all
Returns or sets the handle to a DBI database handle (see DBI). This handle is schema-specific. DBIx::DataModel
expects the handle to be opened with RaiseError => 1
(see "Transactions and error handling").
In %options
you may pass any key-value pairs, and retrieve them later by calling dbh
in a list context, which may be useful for holding driver-specific information. DBIx::DataModel
will only inspect those options for knowing how to retrieve database-generated keys (see the "insert" method below).
Changing the database handle through the dbh
method is forbidden while a transaction is in course. However, a nested transaction may temporarily change the database handle by supplying it as argument to the "do_transaction" method.
To unset the database handle, call $schema->dbh(undef)
.
debug
$schema->debug(1); # will warn for each SQL statement
$schema->debug($debug_object); # will call $debugObject->debug($sql)
$schema->debug(undef); # turn off debugging
Debug mode is useful for seeing SQL statements generated by DBIx::DataModel
. Enabling debugging with a $debug_object
will typically be useful in conjunction with something like Log::Log4perl or Log::Dispatch. Otherwise, enabling debugging with just any true scalar will print SQL statements on STDERR.
There is also another way to see the SQL code for one particular statement :
my $spy_sql = sub {my ($sql, @bind) = @_;
print STDERR join "\n", $sql, @bind;
return ($sql, @bind);};
my $result = $source->select(-columns => \@columns,
-where => \%criteria,
-post_SQL => $spy_sql);
sql_abstract
$schema->sql_abstract($an_SQL_Abstract_More_instance); # set
my $sqlam = $schema->sql_abstract; # get
Sets or retrieves the instance of SQL::Abstract::More used by this $schema
. If the client code does not set it explictly, an instance wil be implicitly created.
dbi_prepare_method
$schema->dbi_prepare_method($method); # set
my $method = $schema->dbi_prepare_method; # get
Sets or retrieves the method sent to DBI for preparing SQL statements. The default is "prepare"
; it can be set to "prepare_cached"
instead.
placeholder_prefix
$schema->placeholder_prefix($prefix); # set
my $prefix = $schema->placeholder_prefix; # get
Sets or retrieves the prefix string to recognize "named placeholders" within a statement. That prefix should never match any regular data encountered in your application; the default is '?:'
.
select_implicitly_for
$schema->select_implicitly_for($string); # set
my $string = $schema->select_implicitly_for; # get
Sets or retrieves a default value for the -for
argument to select().
This default value is not set for statements with -result_as => 'subquery'
(because the FOR clause in an SQL statement only makes sense at the top level, not in a subquery).
localize_state
{
my $scope_guard = $schema->localize_state(@schema_members_to_localize);
... # do some work, possibly change state
} # $scope_guard out of scope : previous state of $schema is restored
Applies dynamic scoping to a $schema
, like Perl's local
construct (see "Temporary Values via local" in perlsub). Here however, since local
is not perfectly suited for private class data, we provide a solution which is similar in spirit, but slightly different in implementation. The localize_state
method internally takes a copy of the current state, and returns a handle to it. The handle should be stored in a my
variable; when that variable goes out of scope (at block exit), then the previous state is restored.
The optional argument @schema_members_to_localize
specifies precisely which schema members should be localized. If it is empty, the default list is : dbh
, dbh_options
, debug
, select_implicitly_for
, dbi_prepare_method
.
DATA RETRIEVAL AND MANIPULATION
do_transaction
my $coderef = sub {$table1->insert(...); $table2->update(...); ...};
$schema->do_transaction($coderef);
Evaluates the code within a transaction. In case of failure, the transaction is rolled back, and an exception is raised, with a message containing the initial error and the status of the rollback (because the rollback itself may also fail). If you need finer details, you can treat the exception as an object with two methods initial_error
and rollback_errors
:
eval {$schema->do_transaction($coderef); 1}
or do {my $err = $@;
explain($err->initial_error, $err->rollback_errors)};
Usually the coderef passed as argument will be a closure that may refer to variables local to the environment where the closure was created.
Nested calls to do_transaction
are supported : only the top-level call will actually initiate and then commit the transaction, while an exception at any level will abort and rollback the whole thing.
If the nested transaction needs to temporarily work on a different database handle, it may do so by supplying the dbh and its options as additional arguments :
$schema->do_transaction($coderef, $new_dbh, %new_dbh_options);
When called in this form, do_transaction
will temporarily set the dbh to the supplied value, and then return to the previous value when the nested transaction is finished. Commits on all involved database handles are delayed until the top-level transaction is finished.
There is no support (yet!) for nested transactions with intermediate savepoints.
fetch
my $record = $table->fetch(@key_values, \%options);
Fetches a single record from a table, from its primary key value (on one or several columns). %options
may specify things like -for
, -pre_exec
, -post_exec
, etc.
This method is just syntactic sugar for
my $record = $table->select(-fetch => \@key_values, %options);
(see below).
fetch_cached
my $record = $table->fetch_cached(@key_values, \%options);
Like fetch
, except that the result is stored in a cache, and further calls to the same methods with the same parameters will return the cached record instead of going back to the database. The cache does not know about any updates to the database, so this is mainly useful for readonly data.
The cache is stored internally in $table->metadm->{fetch_cached}{$dbh_addr}{$freeze_args}
(where $dbh_addr
is Scalar::Util::refaddr(MyTable->dbh)
and $freeze_args
is Storable::freeze(@keyValues, \%options)
). Client code may use this information to clear the cache or tie it to a more sophisticated caching module.
select
Given a $target
, which could be either a table, a view or a statement :
$records = $target->select(
-columns => \@columns,
# OR : -columns => [-distinct => @columns],
-where => \%where,
# OR : -fetch => $key,
# OR : -fetch => \@key,
-group_by => \@groupings,
-having => \%criteria,
-order_by => \@order,
-for => $purpose,
-post_SQL => sub {...},
-pre_exec => sub {...},
-post_exec => sub {...},
-post_bless => sub {...},
-prepare_attrs => \%attrs,
-limit => $limit,
-offset => $offset,
-page_size => $pageSize,
-page_index => $pageIndex,
-column_types => \%columnTypes,
-result_as => 'rows' || 'firstrow'
|| 'hashref' || [hashref => @cols]
|| 'sth' || 'sql'
|| 'subquery' || 'flat_arrayref'
|| 'statement' || 'fast_statement'
);
Applies a SQL SELECT to the $target
, and returns a result as specified by the -result_as
argument (see below).
Arguments are all optional and are passed by name.
Named arguments to select()
-columns => \@columns
-
\@columns
is a reference to an array of SQL column specifications (i.e. column names,*
ortable.*
, functions, etc.).Initial words in
@columns
that start with a hyphen are treated as verbatim SQL : in particular,-columns => [-DISTINCT => qw/col1 col2 .../]
will yieldSELECT DISTINCT col1, col2, ... FROM ...
A '|' in a column is translated into an 'AS' clause, according to the current SQL dialect in SQL::Abstract::More : this is convenient when using perl
qw/.../
operator for columns, as in-columns => [ qw/table1.longColumn|t1lc table2.longColumn|t2lc/ ]
Column aliasing should be avoided on key columns (either primary or foreign keys), because role methods will no longer be able to navigate through the joins (currently
DBIx::DataModel
is not clever enough to rename its internal join constraints according to column aliases). Aliasing on non-key columns is OK, and column handlers will operate properly on aliased columns.The argument to
-columns
can also be a string instead of an arrayref, like for example"c1 AS foobar, MAX(c2) AS m_c2, COUNT(c3) AS n_c3"
; however this is mainly for backwards compatibility. The recommended way is to use the arrayref notation as explained above :-columns => [ qw/ c1|foobar MAX(c2)|m_c2 COUNT(c3)|n_c3 / ]
If omitted,
\@columns
takes the default, which is usually '*', unless modified through thedefault_columns
argument to the table declaration.No verification is done on the list of retrieved
\@columns
, so the list does not have to include the primary or foreign keys --- but then later attempts to perform joins or updates will obviously fail. -distinct => \@columns
-
behaves like the
-columns
arguments, except that keywordDISTINCT
will be included in the generated SQL. -where => \%where
-
\%where
is a reference to a hash or array of criteria that will be translated into SQL clauses. In most cases, this will just be something like{col1 => 'val1', col2 => 'val2'}
; see SQL::Abstract::select for detailed description of the structure of that hash or array. It can also be a plain SQL string like"col1 IN (3, 5, 7, 11) OR col2 IS NOT NULL"
. -fetch => \@columns
-
equivalent to
...->select(-where => {<primary_key_column0> => $columns[0], <primary_key_column1> => $columns[1], ...}, -result_as => "firstrow")
If the primary key ranges on one single column (which is the most frequent case), then the argument to
-fetch
can also be a single scalar value :...->select(-fetch => $key)
When calling a table directly, the
select(-fetch => ..)
syntax is awkward; you will most certainly prefer the syntactic sugar offered by the fetch() method :$table->fetch(@key)
However, the
-fetch
notation is useful when walking through association roles :$employee->activities(-fetch => $act_id)
This example will generate the following SQL
SELECT * FROM activity WHERE act_id=$act_id AND emp_id=$employee->{emp_id}
Notice how this is different from
$schema->table('Activity')->fetch($act_id)
which would generate
SELECT * FROM activity WHERE act_id=$act_id
Both examples would end up with the same record, but in the first case there is an additional check that this record really belongs to the given employee.
In presence of
-fetch
, arguments-where
and-select_as
are not allowed. -group_by => "string"
or-group_by => \@array
-
adds a
GROUP BY
clause in the SQL statement. Grouping columns are specified either by a plain string or by an array of strings. -having => "string"
or-having => \%criteria
-
adds a
HAVING
clause in the SQL statement (only makes sense together with aGROUP BY
clause). This is like a-where
clause, except that the criteria are applied after grouping has occured. -order_by => \@order
-
\@order
is a reference to a list of columns for sorting. It can also be a plain SQL string like"col1 DESC, col3, col2 DESC"
. Columns can also be prefixed by '+' or '-' for indicating sorting directions, so for example-orderBy => [qw/-col1 +col2 -col3/]
will generate the SQL clauseORDER BY col1 DESC, col2 ASC, col3 DESC
. -for => $clause
-
specifies an additional clause to be added at the end of the SQL statement, like
-for => 'read only'
or-for => 'update'
. -post_SQL => sub{...}
-
hook for specifying a callback function to be called on SQL code and bind values, before preparing the statement. It will be called as follows:
($sql, @bind) = $args->{-post_SQL}->($sql, @bind) if $args->{-post_SQL};
-pre_exec => sub{...}, -post_exec => sub{...}
-
hooks for specifying callback functions to be called on the DBI statement handle, just before or just after invoking
execute()
. So the sequence will be more or less like this:$sth = $dbh->prepare($sql_statement); $pre_exec_callback->($sth) if $pre_exec_callback; $sth->execute(@bind_values); $post_exec_callback->($sth) if $post_exec_callback;
This is mostly useful if you need to call driver-specific functions at those stages.
-post_bless => sub{...}
-
hook for specifying a callback function to be called on data rows. The callback will be called after bless_from_DB, i.e. the row is already an object of the proper class and column handlers have been applied.
-prepare_attrs => \%attrs
-
Optional attributes that will be transmitted to "prepare" in DBI.
-page_size => $page_size
-
specifies how many rows will be retrieved per "page" of data. Default is unlimited (or more precisely the maximum value of a short integer on your system). When specified, automatically implies
-limit
. -page_index => $page_index
-
specifies the page number (starting at 1). Default is 1. When specified, automatically implies
-offset
. -limit => $limit
-
limit to the number of rows that will be retrieved. Automatically implied by
-page_size
. -offset => $offset
-
Automatically implied by
-page_index
. -column_types => \%column_types
-
dynamically specifies some column types at the statement level. Usually column types are defined within tables at compile time, but it may be necessary to defined additional types within the statement, for example when using database functions and/or aliases. The argument is a hashref in which keys are names of column types defined within the schema, and values are arrayrefs of column names :
select(-columns => [qw/ MAX(date_col)|max_date MIN(date_col)|min_date ... /], -column_types => { Date => [qw/max_date min_date/] }, ...)
-result_as => $result_kind
-
specifies what kind of result will be produced. The result is always a scalar and does not depend on the calling context. Possible result kinds are :
- rows
-
The result will be a ref to an array of rows, blessed into objects of the class. This is the default result kind. If there are no data rows, a ref to an empty list is returned.
- firstrow
-
The result will be just the first data row, blessed into an object of the class. If there is no data,
undef
is returned. - hashref || [hashref => @cols]
-
The result will be a hashref. Keys in the hash correspond to distinct values of the specified columns, and values are data row objects. If the argument is given as
[hashref => @cols]
, the column(s) are specified by the caller; otherwise if the argument is given as a simple string,@cols
will default to$source->primary_key
. If there is more than one column, the result will be a tree of nested hashes. This-result_as
is normally used only where the key fields values for each row are unique. If multiple rows are returned with the same values for the key fields then later rows overwrite earlier ones. - flat_arrayref
-
The result will be a ref to an array that concatenates results from each row. Usually this is combined with a
-columns
argument with one single column, to get a vertical slice from a resultset, like inmy $all_names = $schema->table('People')->select( -columns => [-DISTINCT => qw/firstname/], -result_As => 'flat_arrayref', ); print sort @$all_names;
However, it may also be used for example to fill a hash from pairs retrieved from each row, like in
my $pairs = $schema->table('People')->select( -columns => [qw/pers_id firstname/], -result_as => 'flat_arrayref' ); my %hash = @$pairs;
Finally, it can be convenient for avoiding column aliases, when using aggregator functions :
my $array_ref = $source->select(-columns => [qw/MAX(col1) AVG(col2) COUNT(DISTINCT(col3))/], -where => ..., -result_as => 'flat_arrayref'); my ($max_col1, $avg_col2, $count_col3) = @$array_ref;
- statement
-
The result will be an instance of a DBIx::DataModel::Statement. That object has a
next
method that fetches the next datarow and blesses it into the appropriate object, or returnsundef
when there is no more data to fetch. So a typical usage pattern is :my $statement = $class->select(-where => \%criteria, -result_as => 'statement'); while (my $row = $statement->next) { do_something_with($row); }
If called with an argument, the
next
method returns an array ref of several rows, as inmy $rows = $statement->next(10);
Finally, the statement also has an
all
method that returns an arrayref of all remaining rows.When creating a new Schema, a different statement class can be specified via the
statement_class
argument. For example the DBIx::DataModel::Statement::JDBC subclass in this distribution is intended for DBD::JDBC data sources, and gives access to some JDBC methods over the statement (for example positioning instructions). - fast_statement
-
The result is like a normal statement, except that rows are successively fetched into the same memory location, using DBI's fetch and bind_columns methods. This is the fastest way to get data; however, pay attention to this warning from DBI's documentation : Note that the same array reference is returned for each fetch, so don't store the reference and then use it after a later fetch. Also, the elements of the array are also reused for each row, so take care if you want to take a reference to an element. Furthermore, any field added into the row will remain present for the next rows.
Of course it is not possible to call
all
ornext(10)
on a fast statement. - sth
-
The result will be an executed
DBI
statement handle. Then it is up to the caller to retrieve data rows using the DBI API. If needed, these rows can be later blessed into appropriate objects through bless_from_DB(). - sql
-
In scalar context, the result will just be the generated SQL statement. In list context, it will be
($sql, @bind)
, i.e. the SQL statement together with the bind values. - subquery
-
Returns a ref to an arrayref containing
\["($sql)", @bind]
. This is meant to be passed to a second query through SQL::Abstract, as in :my $subquery = $source1->select(..., -resultAs => 'subquery'); my $rows = $source2->select( -columns => ..., -where => {foo => 123, bar => {-not_in => $subquery}} );
unbless
$schema->unbless($obj1, $obj2, ...);
Recursively applies "damn" in Acme::Damn to remove all class information from its arguments : these become plain Perl hashrefs, arrayrefs or scalars.
This may be useful if the datatree returned by a select(..) / expand(..)
needs to be exported through an external module that only considers plain datastructures; this is the case for example with "Dump" in YAML::Syck.
insert
my @ids = $table->insert({col1 => $val1, col2 => $val2, ...},
{...},
%options);
# or
my @ids = $table->insert([qw/ col1 col2 .../],
[ $val1, $val2, ... ],
...);
Inserts a collection of rows into the database, given either as a list of hashrefs, or as a first arrayref containing the column names, followed by a list of arrayrefs containing values for each row to be inserted.
In either form, the method applies the to_DB
handlers, removes the no_update
columns, and then inserts the new records into the database. Because of the handlers, this operation may modify the argument data, so it is not safe to access $val1
, $val2
, etc. after the call.
Primary key column(s) should of course be present in the supplied hashrefs, unless the the key is auto-generated by the database (see below).
Each hashref will be blessed into the $table
class, and will be inserted through the internal _singleInsert() method. The default implementation of this method should be good enough for most common uses, but you may want to refine it in your table classes if you need some fancy handling on primary keys (like for example computing a random key and checking whether that key is free). The default implementation uses the following algorithm to retrieve keys auto-generated by the database :
if a dbh option called
last_insert_id
is found (see options passed to the "dbh" method), this is taken as a callback function, which gets called as$dbh_options{last_insert_id}->($dbh, $table_name, $column_name)
if options called
catalog
and/orschema
are found,DBIx::DataModel
will call$dbh->last_insert_id($dbh_options{catalog}, $dbh_options{schema}, $table_name, $column_name)
otherwise,
DBIx::DataModel
will call$dbh->last_insert_id(undef, undef, undef, undef)
If the table is a composite class (see Composition() above), then the component parts may be supplied within the hashref, with keys equal to the role names, and values given as arrayrefs of sub-hashrefs; then these will be inserted into the database, at the same time as the main record, with join values automatically filled in (cascaded insert). For example :
HR::Employee->insert({firstname => "Johann Sebastian",
lastname => "Bach",
activities => [{d_begin => '01.01.1695',
d_end => '18.07.1750',
dpt_code => 'CPT'}]});
The insert()
call may take a list of %options specified at the end of the argument list (notice they are not given as a hashref, but as a mere hash, or list of pairs). Actually the only option currently supported is -returning, with an argument that may be either a scalar, an arrayref or an empty hashref :
if it is a scalar or an arrayref, that value is passed to "insert" in SQL::Abstract and finally to the SQL level (INSERT ... RETURNING ...); whatever is returned from the database for each single record gets flattened into a single list transmitted back to the caller.
my @result = $table->insert({...}, ..., -returning => $scalar_or_arrayref);
if it is an empty hashref, the return value is also a list of hashrefs (one for each inserted record), containing the column name(s) and value(s) of the primary key for that record, and possibly containing subhashes or subarrays for other records created through cascaded inserts. For example:
my @result = HR::Employee->insert({..., activities => [{...}, ...]}, ..., -returning => {}); my $prim_key_first_emp = $result[0]{emp_id}; my $prim_key_first_act = $result[0]{activities}[0]{act_id};
if the
-returning
option is absent, values returned by calls to _singleInsert() are collected into a flattened array, and then returned byinsert()
; usually, these are the primary keys of the inserted records. If this array contains several values andinsert()
was called from a scalar context, a warning is issued.
update
$table->update({col1 => $val1, ...});
$table->update(@primary_key, {col1 => $val1, ...});
$table->update(-set => {col1 => $val1, ...},
-where => \%condition);
$obj->update;
This is both a class and an instance method, with several syntaxes. It applies the to_DB
handlers, removes the no_update
columns, and then updates the database for the given record.
When called as a class method, the columns and values to update are supplied as a hashref. The second syntax with @primary_key
is an alternate way to supply the values for the primary key (it may be more convenient because you don't need to repeat the name of primary key columns). So if emp_id
is the primary key of table Employee
, then the following are equivalent :
HR::Employee->update({emp_id => $eid,
address => $newAddr,
phone => $newPhone});
HR::Employee->update($eid => {address => $newAddr,
phone => $newPhone});
The third syntax with -set
and -where
keywords is used for simultaneously updating several records (bulk update); it will send one single SQL request of shape
UPDATE table SET col1='val1', ... WHERE ...
but in that case, since the data did not transit through Perl objects, no column handers will be applied.
When called as an instance method, i.e.
$someEmployee->update;
the columns and values to update are taken from the object in memory (ignoring all non-scalar values).
The update
method only updates the columns received as arguments : it knows nothing about other columns that may sit in the database table. Therefore if you have two concurrent clients doing
(client1) $table->update($id, {c1 => $v1, c2 => $v2});
(client2) $table->update($id, {c3 => $v3, c4 => $v4, c5 => $v5});
the final state of record $id
in the database will reflect changes from both clients.
delete
$table->delete({column1 => value1, ...});
$table->delete(@primary_key);
$table->delete(-where => \%condition);
$row->delete;
This is both a class and an instance method. It deletes a record from the database.
When called as a class method, the primary key of the record to delete is supplied either as a hashref, or directly as a list of values. Note that $table->delete(11, 22)
does not mean "delete records with keys 11 and 22", but rather "delete record having primary key (11, 22)"; in other words, you only delete one record at a time.
The syntax with the -where
keyword is used for simultaneously updating several records (bulk update); it will send one single SQL request of shape
DELETE FROM table WHERE ...
When called as an instance method, the primary key is taken from object columns in memory. If the table is a composite class (see Composition() above), and if the object contains references to lists of component parts, then those will be recursively deleted together with the main object (cascaded delete). However, if there are other component parts in the database, not referenced in the hashref, then those will not be automatically deleted : in other words, the delete
method does not go by itself to the database to find all component parts (this is the job of the client code, or sometimes of the database itself).
[CONTINUE HERE]
applyColumnHandler
$class ->applyColumnHandler($handlerName, \@objects);
$object->applyColumnHandler($handlerName);
Inspects the target object or list of objects; for every column that exists in the object, checks whether a handler named $handlerName
was declared for that column (see method "ColumnHandlers"), and if so, calls the handler. By this definition, if a column is absent in an object, then the handler for that column is not called, even though it was declared in the class.
The results of handler calls are collected into a hashref, with an entry for each column name. The value of each entry depends on how applyColumnHandlers
was called : if it was called as an instance method, then the result is something of shape
{columnName1 => resultValue1, columnName2 => resultValue2, ... }
if it was called as a class method (i.e. if \@objects
is defined), then the result is something of shape
{columnName1 => [resultValue1forObject1, resultValue1forObject2, ...],
columnName2 => [resultValue2forObject1, resultValue2forObject2, ...],
... }
If columnName
is not present in the target object(s), then the corresponding result value is undef
.
hasInvalidColumns
my $invalid_columns = $obj->hasInvalidColumns;
if ($invalid_columns) {
print "wrong data in columns ", join(", ", @$invalid_columns);
}
else {
print "all columns OK";
}
Applies the 'validate' handler to all existent columns. Returns a ref to the list of invalid columns, or undef if there are none.
Note that this is validation at the column level, not at the record level. As a result, your validation handlers can check if an existent column is empty, but cannot check if a column is missing (because in that case the handler would not be called).
Your 'validate' handlers, defined through "ColumnHandlers", should return 0 or an empty string whenever the column value is invalid. Never return undef
, because we would no longer be able to distinguish between an invalid existent column and a missing column.
expand
$obj->expand($role [, @args] )
Executes the method $role
to follow an Association, stores the result in the object itself under $obj->{$role}
, and returns that result. This is typically used to expand an object into a tree datastructure. Optional @args
are passed to $obj->$role(@args)
, for example for specifying -where
, -columns
or -orderBy
options.
After the expansion, further calls to $obj->$role
(without any arguments) will reuse that same expanded result instead of calling again the database. This caching improves efficiency, but also introduces the risk of side-effects across your code : after
$obj->expand(someRole => (-columns => [qw/just some columns/],
-where => {someField => 'restriction'}))
further calls to $obj->someRole()
will just return a dataset restricted according to the above criteria, instead of a full join. To prevent that effect, you would need to delete $obj->{someRole}
, or to call the role with arguments : $obj->someRole('*')
.
autoExpand
$record->autoExpand( $recurse );
Asks the object to expand itself with some objects in foreign tables. Does nothing by default. Should be redefined in subclasses, most probably through the "AutoExpand" method (with capital 'A'). If the optional argument $recurse
is true, then autoExpand
is recursively called on the expanded objects.
blessFromDB
$class->blessFromDB($record);
Blesses $record
into an object of the table or view class, and applies the fromDB
column handlers.
primKey
my @primKeyColumns = $source->primKey;
my @primKeyValues = $obj->primKey;
If called as a class method, returns the list of columns registered as primary key for that table (via Schema->Table(..)
), or computed as primary key for that view (concatenation of primary keys of joined tables that are in a 1-to-many association).
If called as an instance method, returns the list of values in those columns.
When called in scalar context and the primary key has only one column, returns that column (so you can call $my k = $obj->primKey
).
DEPRECATED METHODS
Here are some deprecated methods from previous versions
ViewFromRoles
is now called "join" (class method inSchema
)selectFromRoles
is now called "join" (instance method inSource
)MethodFromRoles
is now called "MethodFromJoin" (class method inSource
)selectSth
is now writenselect(..., resultAs => "sth")
SqlDialect
is now expressed as argument to Schema()applyColumnHandlers
is now calledapplyColumnHandler
keepLasth
andlasth
are no longer needed; if you want to interact with the database statement handle, use the DBIx::DataModel::Statement API.preselectWhere
is no longer needed (superseded by theStatement::refine
method).-postFetch
inselect(..., -postFetch => sub {... } ... )
is now called-postBless
OLD_STUFF
OLD_STUFF
join as class method within a Table or View
my $statement = $table->join(qw/role1 role2 .../)->prepare;
Starting from a given table, returns a reference to a statement that selects a collection of data rows from associated tables, performing the appropriate joins. Internally this is implemented throught the /define_join()
method, with an additional join criteria to constrain on the primary key(s) of $table
. That statement cannot be executed yet, because the values of the primary key are not known until we have an instance of $table
; but the statement can already be prepared. Later on, we can execute the statement by binding it to an instance of $table
:
my $obj = $table->fetch(...);
my $rows = $statement->execute($obj)->all;
join as instance method within a Table or View
Creates a statement as just explained above, and immediately binds it to the current object. So for example if $emp->{emp_id} == 987
, then
$emp->join(qw/activities department/)
->select(-where => {d_end => undef})
will generate
SELECT * FROM Activity INNER JOIN Department
ON Activity.dpt_id = Department.dpt_id
WHERE emp_id = 987 AND d_end IS NULL
AutoInsertColumns
$schema->AutoInsertColumns( columnName1 => sub{...}, ... );
$table ->AutoInsertColumns( columnName1 => sub{...}, ... );
Declares handler code that will automatically fill column names columnName1
, etc. at each insert, either for a single table, or (if declared at the Schema level), for every table. For example, each record could remember who created it and when with something like
$schema->AutoInsertColumns( created_by =>
sub{$ENV{REMOTE_USER} . ", " . localtime}
);
The handler code will be called as
$handler->(\%record, $table)
so that it can know something about its calling context. In most cases, however, the handler will not need these parameters, because it just returns global information such as current user or current date/time.
AutoUpdateColumns
$schema->AutoUpdateColumns( columnName1 => sub{...}, ... );
$table ->AutoUpdateColumns( columnName1 => sub{...}, ... );
Just like AutoInsertColumns
, but will be called automatically at each update and each insert. This is typically used to remember the author and/or date and time of the last modification of a record. If you use both AutoInsertColumns
and AutoUpdateColumns
, make sure that the column names are not the same.
When doing an update (i.e. not an insert), the handler code will be called as
$handler->(\%record, $table, \%where)
where %record
contains the columns to be updated and %where
contains the primary key (column name(s) and value(s)).
NoUpdateColumns
$schema->NoUpdateColumns(@columns);
$table ->NoUpdateColumns(@columns);
Defines an array of column names that will be excluded from INSERT/UPDATE statements. This is useful for example when some column are set up automatically by the database (like automatic time stamps or user identification). It can also be useful if you want to temporarily add information to memory objects, without passing it back to the database.
NoUpdate columns can be set for a whole Schema, or for a specific Table class.
1 POD Error
The following errors were encountered while parsing the POD:
- Around line 115:
Non-ASCII character seen before =encoding in 'façade;'. Assuming CP1252