|
|
| |
Rose::DB::Object::Metadata::Column(3) |
User Contributed Perl Documentation |
Rose::DB::Object::Metadata::Column(3) |
Rose::DB::Object::Metadata::Column - Base class for database column metadata
objects.
package MyColumnType;
use Rose::DB::Object::Metadata::Column;
our @ISA = qw(Rose::DB::Object::Metadata::Column);
...
This is the base class for objects that store and manipulate database column
metadata. Column metadata objects store information about columns (data type,
size, etc.) and are responsible for parsing, formatting, and creating object
methods that manipulate column values.
Rose::DB::Object::Metadata::Column objects stringify to the value
returned by the name method. This allows full-blown column objects to be
used in place of column name strings in most situations.
A Rose::DB::Object::Metadata::Column-derived object is responsible for creating
object methods that manipulate column values. Each column object can make zero
or more methods for each available column method type. A column method type
describes the purpose of a method. The default column method types are:
- "get_set"
- A method that can both get and set the column value. If an argument is
passed, then the column value is set. In either case, the current column
value is returned.
- "get"
- A method that returns the current column value.
- "set"
- A method that sets the column value.
Methods are created by calling make_methods. A list of method
types can be passed to the call to make_methods. If absent, the list of
method types is determined by the auto_method_types method. A list of all
possible method types is available through the available_method_types
method.
These methods make up the "public" interface to column
method creation. There are, however, several "protected" methods
which are used internally to implement the methods described above. (The
word "protected" is used here in a vaguely C++ sense, meaning
"accessible to subclasses, but not to the public.") Subclasses
will probably find it easier to override and/or call these protected methods
in order to influence the behavior of the "public" method maker
methods.
A Rose::DB::Object::Metadata::Column object delegates method
creation to a Rose::Object::MakeMethods-derived class. Each
Rose::Object::MakeMethods-derived class has its own set of method types,
each of which takes it own set of arguments.
Using this system, four pieces of information are needed to create
a method on behalf of a Rose::DB::Object::Metadata::Column-derived
object:
- The column method type (e.g.,
"get_set",
"get",
"set")
- The method maker class (e.g.,
Rose::DB::Object::MakeMethods::Generic)
- The method maker method type (e.g., scalar)
- The method maker arguments (e.g., "interface
=> 'get_set_init'")
This information can be organized conceptually into a "method
map" that connects a column method type to a method maker class and,
finally, to one particular method type within that class, and its
arguments.
The default method map is:
- "get_set"
- Rose::DB::Object::MakeMethods::Generic, scalar,
"interface => 'get_set', ..."
- "get"
- Rose::DB::Object::MakeMethods::Generic, scalar,
"interface => 'get', ..."
- "set"
- Rose::DB::Object::MakeMethods::Generic, scalar,
"interface => 'set', ..."
Each item in the map is a column method type. For each column
method type, the method maker class, the method maker method type, and the
"interesting" method maker arguments are listed, in that
order.
The "..." in the method maker arguments is meant to
indicate that other arguments have been omitted. For example, the column
object's default value is passed as part of the arguments for all method
types. These arguments that are common to all column method types are
routinely omitted from the method map for the sake of brevity. If there are
no "interesting" method maker arguments, then "..." may
appear by itself.
The purpose of documenting the method map is to answer the
question, "What kind of method(s) will be created by this column object
for a given method type?" Given the method map, it's possible to read
the documentation for each method maker class to determine how methods of
the specified type behave when passed the listed arguments.
To this end, each Rose::DB::Object::Metadata::Column-derived class
in the Rose::DB::Object module distribution will list its method map in its
documentation. This is a concise way to document the behavior that is
specific to each column class, while omitting the common functionality
(which is documented here, in the column base class).
Remember, the existence and behavior of the method map is really
implementation detail. A column object is free to implement the public
method-making interface however it wants, without regard to any conceptual
or actual method map. It must then, of course, document what kinds of
methods it makes for each of its method types, but it does not have to use a
method map to do so.
Triggers allow code to run in response to certain column-related events. An
event may trigger zero or more pieces of code. The names and behaviors of the
various kinds of events are as follows.
- on_get
- Triggered when a column value is retrieved for some purpose other
than storage in the database. For example, when end-user code
retrieves a column value by calling an accessor method, this event is
triggered. This event is not triggered when a column value is
retrieved while the object is being saved into the database.
Each piece of code responding to an
"on_get" event will be passed a single
argument: a reference to the object itself. The return value is not
used.
- on_set
- Triggered when a column value is set to a value that came from somewhere
other than the database. For example, when end-user code sets a
column value by calling a mutator method, this event is triggered. This
event is not triggered when a column value is set while the object
is being loaded from the database.
The "on_set" event occurs
after the column value has been set. Each piece of code
responding to an "on_set" event will
be passed a single argument: a reference to the object itself. The
return value is not used.
- on_load
- Triggered when a column value is set while an object is being loaded from
the database.
The "on_load" event occurs
after the column value has been loaded. Each piece of code
responding to an "on_load" event will
be passed a single argument: a reference to the object itself. The
return value is not used.
- on_save
- Triggered when a column value is retrieved while an object is being saved
into the database.
Each piece of code responding to an
"on_save" event will be passed a
single argument: a reference to the object itself. The return value is
not used.
- inflate
- Triggered when a column value is retrieved for some purpose other
than storage in the database. For example, when end-user code
retrieves a column value by calling an accessor method, and that value
came directly from the database, this event is triggered.
Inflation will only happen "as needed." That is, a
value that has already been inflated will not be inflated again, and a
value that comes from the database and goes back into it without ever
being retrieved by end-user code will never be inflated at all.
Each piece of code responding to an
"inflate" event will be passed two
arguments: a reference to the object itself and the value to be
inflated. It should return an inflated version of that value. Note that
the value to be inflated may have come from the database, or from
end-user code. Be prepared to handle almost anything.
- deflate
- Triggered when a column value that did not come directly from the database
needs to be put into the database. For example, when a column value set by
end-user code needs to be saved into the database, this event is
triggered.
Deflation will only happen "as needed." That is, a
value that has already been deflated will not be deflated again, and a
value that comes from the database and goes back into it without ever
being retrieved by end-user code will never need to be deflated at
all.
Each piece of code responding to a
"deflate" event will be passed two
arguments: a reference to the object itself and the value to be
deflated. It should return a deflated version of that value suitable for
saving into the currently connected database. Note that the value to be
deflated may have come from the database, or from end-user code. Be
prepared to handle almost anything.
All triggers are disabled while inside code called in response to
a trigger event. Such code may call any other column methods, including
methods that belong to its own column, without fear of infinite recursion
into trigger service subroutines. Alternately, triggers may be explicitly
enabled if desired. Just watch out for infinite loops.
For performance reasons, none of the column classes bundled with
Rose::DB::Object use triggers by default. Some of them do inflate and
deflate values, but they do so internally (inside the accessor and mutator
methods created by the Rose::Object::MakeMethods-derived classes that
service those column types). You can still add triggers to these column
types, but the interaction between the internal inflate/deflate actions and
the triggers for those same events can become a bit
"non-obvious."
- default_auto_method_types [TYPES]
- Get or set the default list of auto_method_types. TYPES should be a list
of column method types. Returns the list of default column method types
(in list context) or a reference to an array of the default column method
types (in scalar context). The default list contains only the
"get_set" column method type.
- default_undef_overrides_default [BOOL]
- Get or set the default value of the undef_overrides_default attribute. The
default value is undef.
This default only applies when the column does not have a
parent metadata object or if the metadata object's
column_undef_overrides_default method returns undef.
- new PARAMS
- Constructs a new object based on PARAMS, where PARAMS are name/value
pairs. Any object method is a valid parameter name.
- accessor_method_name
- Returns the name of the method used to get the column value. This is a
convenient shortcut for:
$column->method_name('get') || $column->method_name('get_set');
- add_trigger [ EVENT, CODEREF | PARAMS ]
- Add a trigger, as specified by either an event and a code reference, or a
set of named parameters that include an event, a code reference, and an
optional name and position for the trigger.
If there are only two arguments, and the first is a valid
event name, then the second must be a code reference. Otherwise, the
arguments are taken as named parameters.
Valid parameters are:
- "code CODEREF"
- A reference to a subroutine that will be called in response to a trigger
event. This parameter is required. See the triggers section of this
documentation for a description of the arguments to and return values
expected from these routines for each type of event.
- "event EVENT"
- The name of the event that activates this trigger. This parameter is
required. Valid event names are
"on_get",
"on_set",
"on_load",
"on_save",
"inflate", and
"deflate". See the triggers section of
this documentation for more information on these event types.
- "name NAME"
- An optional name mapped to the triggered subroutine. If a name is not
supplied, one will be generated. A known name is necessary if you ever
want to delete a particular subroutine from the list of triggered
subroutine for a given event.
- "position POS"
- The position in the list of triggered subroutines to add this new code.
Triggered subroutines are kept in an ordered list. By default, new
triggers are added to the end of the list, which means they run last.
Valid position arguments are:
- "end", "last", or "push"
- Add to the end of the list.
- "start", "first", or "unshift"
- Add to the beginning of the list.
If omitted, the position defaults to "end."
Examples:
# Add trigger using an event name and a code reference
$column->add_trigger(on_set => sub { print "set!\n" });
# Same as above, but using named parameters
$column->add_trigger(event => 'on_set',
code => sub { print "set!\n" });
# Same as the above, but with a custom name and explicit position
$column->add_trigger(event => 'on_set',
code => sub { print "set!\n" },
name => 'debugging',
position => 'end');
- alias [NAME]
- Get or set an alternate name for this column.
- available_method_types
- Returns the full list of column method types supported by this class.
- auto_method_types [TYPES]
- Get or set the list of column method types that are automatically created
when make_methods is called without an explicit list of column method
types. The default list is determined by the default_auto_method_types
class method.
- build_method_name_for_type TYPE
- Return a method name for the column method type TYPE. The default
implementation returns the column's alias (if defined) or name for the
method type "get_set", and the same thing with a
"get_" or "set_" prefix for the "get" and
"set" column method types, respectively.
- default [VALUE]
- Get or set the default value of the column.
- default_exists
- Returns true if a default value exists for this column (even if it is
undef), false otherwise.
- delete_default
- Deletes the default value for this column.
- delete_trigger PARAMS
- Delete a triggered subroutine from the list of triggered subroutines for a
given event. You must know the name applied to the triggered subroutine
when it was added in order to delete it. PARAMS are name/value pairs.
- "name NAME"
- The name applied to the triggered subroutine when it was added via the
added method. This parameter is required.
- "event EVENT"
- The name of the event that activates this trigger. This parameter is
required. Valid event names are
"on_get",
"on_set",
"on_load",
"on_save",
"inflate", and
"deflate". See the triggers section of
this documentation for more information on these event types.
A fatal error will occur if a matching trigger cannot be
found.
Examples:
# Add two named triggers
$column->add_trigger(event => 'on_set',
code => sub { print "set!\n" },
name => 'debugging');
$column->add_trigger(event => 'on_set',
code => sub { shift->do_something() },
name => 'side_effect');
# Delete the side_effect trigger
$column->delete_trigger(event => 'on_set',
name => 'side_effect');
# Fatal error: no trigger subroutine for this column
# named "nonesuch" for the event type "on_set"
$column->delete_trigger(event => 'on_set',
name => 'nonesuch');
- delete_triggers [EVENT]
- Delete all triggers for EVENT. If EVENT is omitted, delete all triggers
for all events for this column.
Valid event names are
"on_get",
"on_set",
"on_load",
"on_save",
"inflate", and
"deflate". See the triggers section of
this documentation for more information on these event types.
- disable_triggers
- Disable all triggers for this column.
- enable_triggers
- Enable all triggers for this column.
- format_value DB, VALUE
- Convert VALUE into a string suitable for the database column of this type.
VALUE is expected to be like the return value of the parse_value method.
DB is a Rose::DB object that may be used as part of the parsing process.
Both arguments are required.
- is_primary_key_member [BOOL]
- Get or set the boolean flag that indicates whether or not this column is
part of the primary key for its table.
- load_on_demand [BOOL]
- Get or set a boolean value that indicates whether or not a column's value
should be loaded only when needed. If true, then the column's value will
not automatically be fetched from the database when an object is loaded.
It will be fetched only if the column value is subsequently requested
through its accessor method. (This is often referred to as "lazy
loading.") The default value is false.
Note: a column that is part of a primary key cannot be loaded
on demand.
- lazy [BOOL]
- This is an alias for the load_on_demand method. It exists to allow this
common usage scenario:
__PACKAGE__->meta->columns
(
...
notes => { type => 'text', length => 1024, lazy => 1 },
);
without requiring the longer
"load_on_demand" parameter name to be
used.
- make_methods PARAMS
- Create object method used to manipulate column values. PARAMS are
name/value pairs. Valid PARAMS are:
- "preserve_existing BOOL"
- Boolean flag that indicates whether or not to preserve existing methods in
the case of a name conflict.
- "replace_existing BOOL"
- Boolean flag that indicates whether or not to replace existing methods in
the case of a name conflict.
- "target_class CLASS"
- The class in which to make the method(s). If omitted, it defaults to the
calling class.
- "types ARRAYREF"
- A reference to an array of column method types to be created. If omitted,
it defaults to the list of column method types returned by
auto_method_types.
If any of the methods could not be created for any reason, a fatal
error will occur.
- manager_uses_method [BOOL]
- If true, then Rose::DB::Object::QueryBuilder will pass column values
through the object method(s) associated with this column when composing
SQL queries where "query_is_sql" is not
set. The default value is false. See the Rose::DB::Object::QueryBuilder
documentation for more information.
Note: the method is named "manager_uses_method"
instead of, say, "query_builder_uses_method" because
Rose::DB::Object::QueryBuilder is rarely used directly. Instead, it's
mostly used indirectly through the Rose::DB::Object::Manager class.
- method_name TYPE [, NAME]
- Get or set the name of the column method of type TYPE.
- mutator_method_name
- Returns the name of the method used to set the column value. This is a
convenient shortcut for:
$column->method_name('set') || $column->method_name('get_set');
- name [NAME]
- Get or set the name of the column, not including the table name, username,
schema, or any other qualifier.
- nonpersistent [BOOL]
- Get or set a boolean flag that indicates whether or not the column is
non-persistent.
- not_null [BOOL]
- Get or set a boolean flag that indicates whether or not the column value
can be null.
- parse_value DB, VALUE
- Parse and return a convenient Perl representation of VALUE. What form this
value will take is up to the column subclass. If VALUE is a keyword or
otherwise has special meaning to the underlying database, it may be
returned unmodified. DB is a Rose::DB object that may be used as part of
the parsing process. Both arguments are required.
- primary_key_position [INT]
- Get or set the column's ordinal position in the primary key. Returns undef
if the column is not part of the primary key. Position numbering starts
from 1.
- remarks [TEXT]
- Get or set a text description of the column.
- rw_method_name
- Returns the name of the method used to get or set the column value. This
is a convenient shortcut for:
$column->method_name('get_set');
- should_inline_value DB, VALUE
- Given the Rose::DB-derived object DB and the column value VALUE, return
true of the value should be "inlined" (i.e., not bound to a
"?" placeholder and passed as an argument to DBI's execute
method), false otherwise. The default implementation always returns false.
This method is necessary because some DBI drivers do not (or
cannot) always do the right thing when binding values to placeholders in
SQL statements. For example, consider the following SQL for the Informix
database:
CREATE TABLE test (d DATETIME YEAR TO SECOND);
INSERT INTO test (d) VALUES (CURRENT);
This is valid Informix SQL and will insert a row with the
current date and time into the "test" table.
Now consider the following attempt to do the same thing using
DBI placeholders (assume the table was already created as per the CREATE
TABLE statement above):
$sth = $dbh->prepare('INSERT INTO test (d) VALUES (?)');
$sth->execute('CURRENT'); # Error!
What you'll end up with is an error like this:
DBD::Informix::st execute failed: SQL: -1262: Non-numeric
character in datetime or interval.
In other words, DBD::Informix has tried to quote the string
"CURRENT", which has special meaning to Informix only when it
is not quoted.
In order to make this work, the value "CURRENT" must
be "inlined" rather than bound to a placeholder when it is the
value of a "DATETIME YEAR TO SECOND" column in an Informix
database.
All of the information needed to make this decision is
available to the call to should_inline_value. It gets passed a
Rose::DB-derived object, from which it can determine the database
driver, and it gets passed the actual value, which it can check to see
if it matches "/^current$/i".
This is just one example. Each subclass of
Rose::DB::Object::Metadata::Column must determine for itself when a
value needs to be inlined.
- triggers EVENT [, CODEREF | ARRAYREF ]
- Get or set the list of trigger subroutines for EVENT. Valid event names
are "on_get",
"on_set",
"on_load",
"on_save",
"inflate", and
"deflate". See the triggers section of
this documentation for more information on these event types.
If passed a code ref or a reference to an array of code refs,
then the list of trigger subroutines for EVENT is replaced with those
code ref(s).
Returns a reference to an array of trigger subroutines for the
event type EVENT. If there are no triggers for EVENT, undef will be
returned.
- triggers_disabled
- Returns true if triggers are disabled for this column, false
otherwise.
- type
- Returns the (possibly abstract) data type of the column. The default
implementation returns "scalar".
- undef_overrides_default [BOOL]
- Get or set a boolean value that indicates whether or not setting the
column to an undef value overrides the column's default value.
The default value of this attribute is determined by the
parent metadata object's column_undef_overrides_default method, or the
column's default_undef_overrides_default class method id the metadata
object's column_undef_overrides_default method returns undef, or if the
column has no parent metadata object.
Example: consider a Rose::DB::Object-derived
"Person" class with a
"name" column set up like this:
package Person;
...
columns =>
[
name => { type => 'varchar', default => 'John Doe' },
...
],
...
The following behavior is the same regardless of the setting
of the undef_overrides_default attribute for the
"name" column:
$p = Person->new;
print $p->name; # John Doe
$p->name('Larry Wall');
print $p->name; # Larry Wall
If undef_overrides_default is false for the
"name" column, then this is the
behavior of explicitly setting the column to undef:
$p->name(undef);
print $p->name; # John Doe
If undef_overrides_default is true for the
"name" column, then this is the
behavior of explicitly setting the column to undef:
$p->name(undef);
print $p->name; # undef
The undef_overrides_default attribute can be set directly on
the column:
name => { type => 'varchar', default => 'John Doe',
undef_overrides_default => 1 },
or it can be set class-wide using the meta object's
column_undef_overrides_default attribute:
Person->meta->column_undef_overrides_default(1);
or it can be set for all classes that use a given
Rose::DB::Object::Metadata-derived class using the
default_column_undef_overrides_default class method:
My::DB::Object::Metadata->default_column_undef_overrides_default(1);
These methods are not part of the public interface, but are supported for use by
subclasses. Put another way, given an unknown object that "isa"
Rose::DB::Object::Metadata::Column, there should be no expectation that the
following methods exist. But subclasses, which know the exact class from which
they inherit, are free to use these methods in order to implement the public
API described above.
- method_maker_arguments TYPE
- Returns a hash (in list context) or reference to a hash (in scalar
context) of name/value arguments that will be passed to the
method_maker_class when making the column method type TYPE.
- method_maker_class TYPE [, CLASS]
- If CLASS is passed, the name of the Rose::Object::MakeMethods-derived
class used to create the object method of type TYPE is set to CLASS.
Returns the name of the Rose::Object::MakeMethods-derived
class used to create the object method of type TYPE.
- method_maker_type TYPE [, NAME]
- If NAME is passed, the name of the method maker method type for the column
method type TYPE is set to NAME.
Returns the method maker method type for the column method
type TYPE.
John C. Siracusa (siracusa@gmail.com)
Copyright (c) 2010 by John C. Siracusa. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same terms
as Perl itself.
Visit the GSP FreeBSD Man Page Interface. Output converted with ManDoc. |