Provided by: librose-db-object-perl_0.820-2_all bug

NAME

       Rose::DB::Object::Manager - Fetch multiple Rose::DB::Object-derived objects from the database using
       complex queries.

SYNOPSIS

         ##
         ## Given the following Rose::DB::Object-derived classes...
         ##

         package Category;

         use base 'Rose::DB::Object';

         __PACKAGE__->meta->setup
         (
           table   => 'categories',
           columns =>
           [
             id          => { type => 'int', primary_key => 1 },
             name        => { type => 'varchar', length => 255 },
             description => { type => 'text' },
           ],

           unique_key => 'name',
         );

         ...

         package CodeName;

         use base 'Rose::DB::Object';

         __PACKAGE__->meta->setup
         (
           table   => 'code_names',
           columns =>
           [
             id          => { type => 'int', primary_key => 1 },
             product_id  => { type => 'int' },
             name        => { type => 'varchar', length => 255 },
             applied     => { type => 'date', not_null => 1 },
           ],

           foreign_keys =>
           [
             product =>
             {
               class       => 'Product',
               key_columns => { product_id => 'id' },
             },
           ],
         );

         ...

         package Product;

         use base 'Rose::DB::Object';

         __PACKAGE__->meta->setup
         (
           table   => 'products',
           columns =>
           [
             id          => { type => 'int', primary_key => 1 },
             name        => { type => 'varchar', length => 255 },
             description => { type => 'text' },
             category_id => { type => 'int' },
             region_num  => { type => 'int' },

             status =>
             {
               type      => 'varchar',
               check_in  => [ 'active', 'inactive' ],
               default   => 'inactive',
             },

             start_date  => { type => 'datetime' },
             end_date    => { type => 'datetime' },

             date_created  => { type => 'timestamp', default => 'now' },
             last_modified => { type => 'timestamp', default => 'now' },
           ],

           unique_key => 'name',

           foreign_keys =>
           [
             category =>
             {
               class       => 'Category',
               key_columns =>
               {
                 category_id => 'id',
               }
             },
           ],

           relationships =>
           [
             code_names =>
             {
               type  => 'one to many',
               class => 'CodeName',
               column_map   => { id => 'product_id' },
               manager_args =>
               {
                 sort_by => CodeName->meta->table . '.applied DESC',
               },
             },
           ],
         );

         ...

         ##
         ## Create a manager class
         ##

         package Product::Manager;

         use base 'Rose::DB::Object::Manager';

         sub object_class { 'Product' }

         __PACKAGE__->make_manager_methods('products');

         # The call above creates the methods shown below.  (The actual
         # method bodies vary slightly, but this is the gist of it...)
         #
         # sub get_products
         # {
         #   shift->get_objects(@_, object_class => 'Product');
         # }
         #
         # sub get_products_iterator
         # {
         #   shift->get_objects_iterator(@_, object_class => 'Product');
         # }
         #
         # sub get_products_count
         # {
         #   shift->get_objects_count(@_, object_class => 'Product');
         # }
         #
         # sub update_products
         # {
         #   shift->update_objects(@_, object_class => 'Product');
         # }
         #
         # sub delete_products
         # {
         #   shift->delete_objects(@_, object_class => 'Product');
         # }

         ...

         ##
         ## Use the manager class
         ##

         #
         # Get a reference to an array of objects
         #

         $products =
           Product::Manager->get_products
           (
             query =>
             [
               category_id => [ 5, 7, 22 ],
               status      => 'active',
               start_date  => { lt => '15/12/2005 6:30 p.m.' },
               name        => { like => [ '%foo%', '%bar%' ] },
             ],
             sort_by => 'category_id, start_date DESC',
             limit   => 100,
             offset  => 80,
           );

         foreach my $product (@$products)
         {
           print $product->id, ' ', $product->name, "\n";
         }

         #
         # Get objects iterator
         #

         $iterator =
           Product::Manager->get_products_iterator
           (
             query =>
             [
               category_id => [ 5, 7, 22 ],
               status      => 'active',
               start_date  => { lt => '15/12/2005 6:30 p.m.' },
               name        => { like => [ '%foo%', '%bar%' ] },
             ],
             sort_by => 'category_id, start_date DESC',
             limit   => 100,
             offset  => 80,
           );

         while($product = $iterator->next)
         {
           print $product->id, ' ', $product->name, "\n";
         }

         print $iterator->total;

         #
         # Get objects count
         #

         $count =
           Product::Manager->get_products_count
           (
             query =>
             [
               category_id => [ 5, 7, 22 ],
               status      => 'active',
               start_date  => { lt => '15/12/2005 6:30 p.m.' },
               name        => { like => [ '%foo%', '%bar%' ] },
             ],
           );

          die Product::Manager->error  unless(defined $count);

         print $count; # or Product::Manager->total()

         #
         # Get objects and sub-objects in a single query
         #

         $products =
           Product::Manager->get_products
           (
             with_objects => [ 'category', 'code_names' ],
             query =>
             [
               category_id => [ 5, 7, 22 ],
               status      => 'active',
               start_date  => { lt => '15/12/2005 6:30 p.m.' },

               # We need to disambiguate the "name" column below since it
               # appears in more than one table referenced by this query.
               # When more than one table is queried, the tables have numbered
               # aliases starting from the "main" table ("products").  The
               # "products" table is t1, "categories" is t2, and "code_names"
               # is t3.  You can read more about automatic table aliasing in
               # the documentation for the get_objects() method below.
               #
               # "category.name" and "categories.name" would work too, since
               # table and relationship names are also valid prefixes.

               't2.name'   => { like => [ '%foo%', '%bar%' ] },
             ],
             sort_by => 'category_id, start_date DESC',
             limit   => 100,
             offset  => 80,
           );

         foreach my $product (@$products)
         {
           # The call to $product->category does not hit the database
           print $product->name, ': ', $product->category->name, "\n";

           # The call to $product->code_names does not hit the database
           foreach my $code_name ($product->code_names)
           {
             # This call doesn't hit the database either
             print $code_name->name, "\n";
           }
         }

         #
         # Update objects
         #

         $num_rows_updated =
           Product::Manager->update_products(
             set =>
             {
               end_date   => DateTime->now,
               region_num => { sql => 'region_num * -1' }
               status     => 'defunct',
             },
             where =>
             [
               start_date => { lt => '1/1/1980' },
               status     => [ 'active', 'pending' ],
             ]);

         #
         # Delete objects
         #

         $num_rows_deleted =
           Product::Manager->delete_products(
             where =>
             [
               status  => [ 'stale', 'old' ],
               name    => { like => 'Wax%' },
               or =>
               [
                 start_date => { gt => '2008-12-30' },
                 end_date   => { gt => 'now' },
               ],
             ]);

DESCRIPTION

       Rose::DB::Object::Manager is a base class for classes that select rows from tables fronted by
       Rose::DB::Object-derived classes.  Each row in the table(s) queried is converted into the equivalent
       Rose::DB::Object-derived object.

       Class methods are provided for fetching objects all at once, one at a time through the use of an
       iterator, or just getting the object count.  Subclasses are expected to create syntactically pleasing
       wrappers for Rose::DB::Object::Manager class methods, either manually or with the make_manager_methods
       method.  A very minimal example is shown in the synopsis above.

CLASS METHODS

       dbi_prepare_cached [BOOL]
           Get  or  set  a  boolean value that indicates whether or not this class will use DBI's prepare_cached
           method by default (instead of the prepare method) when preparing SQL queries.  The default  value  is
           false.

       default_limit_with_subselect [BOOL]
           Get  or set a boolean value that determines whether or not this class will consider using a sub-query
           to express "limit"/"offset"  constraints  when  fetching  sub-objects  related  through  one  of  the
           "...-to-many" relationship types.  Not all databases support this syntax, and not all queries can use
           it  even  in supported databases.  If this parameter is true, the feature will be used when possible,
           by default.  The default value is true.

       default_manager_method_types [ LIST | ARRAYREF ]
           Get or set the default list of method types used by the  make_manager_methods  method.   The  default
           list is "objects", "iterator", "count", "delete", and "update".

       default_nested_joins [BOOL]
           Get  or set a boolean value that determines whether or not this class will consider using nested JOIN
           syntax when fetching related objects.  Not all databases support this syntax, and not all queries can
           use it even in supported databases.  If this parameter  is  true,  the  feature  will  be  used  when
           possible, by default.  The default value is true.

       default_objects_per_page [NUM]
           Get or set the default number of items per page, as returned by the get_objects method when used with
           the "page" and/or "per_page" parameters.  The default value is 20.

       delete_objects [ PARAMS | ARRAYREF | HASHREF ]
           Delete  rows  from  a table fronted by a Rose::DB::Object-derived class based on PARAMS, where PARAMS
           are name/value pairs.  Returns the number of rows deleted, or undef if there was an error.

           If the first argument is a reference to a hash or array, it is converted to a reference to  an  array
           (if necessary) and taken as the value of the "where" parameter.

           Valid parameters are:

           all BOOL
               If  set to a true value, this parameter indicates an explicit request to delete all rows from the
               table.  If both the "all" and the "where" parameters are passed, a fatal error will occur.

           db DB
               A Rose::DB-derived object used to access the database.   If  omitted,  one  will  be  created  by
               calling the init_db method of the object_class.

           prepare_cached BOOL
               If  true,  then  DBI's  prepare_cached  method  will be used (instead of the prepare method) when
               preparing the SQL statement that will delete the objects.   If  omitted,  the  default  value  is
               determined by the dbi_prepare_cached class method.

           object_class CLASS
               The  name  of  the Rose::DB::Object-derived class that fronts the table from which rows are to be
               deleted.  This parameter is required; a fatal error will occur if it is omitted.  Defaults to the
               value returned by the object_class class method.

           where ARRAYREF
               The query parameters, passed as a reference to an array of name/value  pairs.   These  pairs  are
               used  to  formulate  the "where" clause of the SQL query that is used to delete the rows from the
               table.  Arbitrarily nested boolean logic is supported.

               For the complete list of valid parameter names and values, see the documentation for the  "query"
               parameter of the build_select function in the Rose::DB::Object::QueryBuilder module.

               If  this  parameter  is  omitted, this method will refuse to delete all rows from the table and a
               fatal error will occur.  To delete all rows from a table, you must pass the "all" parameter  with
               a true value.  If both the "all" and the "where" parameters are passed, a fatal error will occur.

       error
           Returns the text message associated with the last error, or false if there was no error.

       error_mode [MODE]
           Get  or  set  the error mode for this class.  The error mode determines what happens when a method of
           this class encounters an error.  The default setting is "fatal", which means that methods will  croak
           if they encounter an error.

           PLEASE  NOTE:  The  error  return  values  described  in the method documentation in the rest of this
           document are only relevant when the error mode is set to something "non-fatal."  In other  words,  if
           an  error  occurs,  you'll  never  see  any of those return values if the selected error mode dies or
           croaks or otherwise throws an exception when an error occurs.

           Valid values of MODE are:

           carp
               Call Carp::carp with the value of the object error as an argument.

           cluck
               Call Carp::cluck with the value of the object error as an argument.

           confess
               Call Carp::confess with the value of the object error as an argument.

           croak
               Call Carp::croak with the value of the object error as an argument.

           fatal
               An alias for the "croak" mode.

           return
               Return a value that indicates that an error has occurred, as described in the  documentation  for
               each method.

           In all cases, the class's "error" attribute will also contain the error message.

       get_objects [ PARAMS | HASHREF | ARRAYREF ]
           Get  Rose::DB::Object-derived  objects based on PARAMS, where PARAMS are name/value pairs.  Returns a
           reference to a (possibly empty) array, or undef if there was an error.

           If the first argument is a reference to a hash or array, it is converted to a reference to  an  array
           (if necessary) and taken as the value of the "query" parameter.

           Each  table that participates in the query will be aliased.  Each alias is in the form "tN" where "N"
           is an ascending number starting with 1.  The tables are numbered as follows.

           •   The primary table is always "t1"

           •   The table(s) that correspond to each relationship or foreign  key  named  in  the  "with_objects"
               parameter are numbered in order, starting with "t2"

           •   The  table(s)  that correspond to each relationship or foreign key named in the "require_objects"
               parameter are numbered in order, starting where the "with_objects" table aliases left off.

           "Many to many" relationships have two corresponding tables, and therefore will use two "tN"  numbers.
           All  other  supported  of relationship types only have just one table and will therefore use a single
           "tN" number.

           For example, imagine that the "Product" class shown in  the  synopsis  also  has  a  "many  to  many"
           relationship named "colors."  Now consider this call:

               $products =
                 Product::Manager->get_products(
                   require_objects => [ 'category' ],
                   with_objects    => [ 'code_names', 'colors' ],
                   multi_many_ok   => 1,
                   query           => [ status => 'defunct' ],
                   sort_by         => 't1.name');

           The  "products" table is "t1" since it's the primary table--the table behind the "Product" class that
           "Product::Manager" manages.  Next, the "with_objects" tables are aliased.  The "code_names" table  is
           "t2".  Since "colors" is a "many to many" relationship, it gets two numbers: "t3" and "t4".  Finally,
           the  "require_objects"  tables  are  numbered:  the  table behind the foreign key "category" is "t5".
           Here's an annotated version of the example above:

               # Table aliases in the comments
               $products =
                 Product::Manager->get_products(
                                      # t5
                   require_objects => [ 'category' ],
                                      # t2            t3, t4
                   with_objects    => [ 'code_names', 'colors' ],
                   multi_many_ok   => 1,
                   query           => [ status => 'defunct' ],
                   sort_by         => 't1.name'); # "products" is "t1"

           Also note that the "multi_many_ok" parameter was used in order to suppress the  warning  that  occurs
           when more than one "... to many" relationship is included in the combination of "require_objects" and
           "with_objects"  ("code_names"  (one  to  many)  and  "colors"  (many to many) in this case).  See the
           documentation for "multi_many_ok" below.

           The "tN" table aliases are for convenience, and to isolate end-user code from the actual table names.
           Ideally, the actual table names should only exist in one place in the entire code base: in the  class
           definitions for each Rose::DB::OBject-derived class.

           That  said, when using Rose::DB::Object::Manager, the actual table names can be used as well.  But be
           aware that some databases don't like a mix of table aliases and real table names  in  some  kinds  of
           queries.

           Valid parameters to get_objects are:

           allow_empty_lists BOOL
               If set to true, "query" parameters with empty lists as values are allowed.  For example:

                   @ids = (); # empty list

                   Product::Manager->get_products(
                     query =>
                     [
                       id => \@ids,
                       ...
                     ]);

               By default, passing an empty list as a value will cause a fatal error.

           db DB
               A  Rose::DB-derived  object  used  to  access  the  database.  If omitted, one will be created by
               calling the init_db method of the "object_class".

           debug BOOL
               If true, print the generated SQL to STDERR.

           distinct [ BOOL | ARRAYREF ]
               If set to any kind of true value, then the "DISTINCT" SQL keyword will be added to  the  "SELECT"
               statement.  Specific values trigger the behaviors described below.

               If  set  to a simple scalar value that is true, then only the columns in the primary table ("t1")
               are fetched from the database.

               If set to a reference to an array of table names, "tN" table aliases, or relationship or  foreign
               key  names,  then only the columns from the corresponding tables will be fetched.  In the case of
               relationships that involve more than one table, only the  "most  distant"  table  is  considered.
               (e.g.,  The  map  table  is  ignored in a "many to many" relationship.)  Columns from the primary
               table ("t1") are always selected, regardless of whether or not it appears in the list.

               This parameter conflicts with the "fetch_only" parameter in the case where both provide a list of
               table names or aliases.  In this case, if the value of the "distinct" parameter is also reference
               to an array table names or aliases, then a fatal error will occur.

           fetch_only ARRAYREF
               ARRAYREF should be a reference to an array of table names or "tN" table aliases. Only the columns
               from the corresponding tables will be fetched.  In the case of relationships  that  involve  more
               than  one table, only the "most distant" table is considered.  (e.g., The map table is ignored in
               a "many to many" relationship.)  Columns from the  primary  table  ("t1")  are  always  selected,
               regardless of whether or not it appears in the list.

               This  parameter  conflicts with the "distinct" parameter in the case where both provide a list of
               table names or aliases.  In this case, then a fatal error will occur.

           for_update BOOL
               If true, this parameter is translated to be the equivalent of  passing  the  lock  parameter  and
               setting the "type" to "for update".  For example, this:

                   for_update => 1

               is equivalent to this:

                   lock => { type => 'for update' }

               See the lock parameter below for more information.

           hints HASHREF
               A  reference to a hash of hints that influence the SQL generated to fetch the objects.  Hints are
               just "suggestions" and may be ignored, depending on the actual features  of  the  database  being
               queried.   Use  the debug parameter to see the generated SQL.  Most of the current hints apply to
               MySQL only.  See the relevant documentation for more details:

               <http://dev.mysql.com/doc/refman/5.0/en/select.html>

               The hints hash is keyed by tN table aliases or relationship names.  The value of each  key  is  a
               reference  to  a  hash of hint directives.  In the absence of any key for "t1" or the name of the
               primary table, the entire hints hash is considered applicable to the primary table.

               Valid hint directives are:

               all_rows BOOL
                   If true, direct the database to choose the query plan that returns all the records as quickly
                   as possible.

               big_result BOOL
                   If true, indicate to the database that the result set is expected to be big.

               buffer_result BOOL
                   If true, force the result to be put into a temporary table.

               cache BOOL
                   If true, ask the database to store the result in its query cache.

               calc_found_rows BOOL
                   If true, ask the database to internally calculate the number  of  rows  found,  ignoring  any
                   limit or offset arguments.

               comment TEXT
                   Add  a comment after the "SELECT" keyword in the query.  TEXT should not be surrounded by any
                   comment delimiters.  The appropriate delimiters will be added automatically.

               first_rows BOOL
                   If true, direct the database to choose the query plan that returns the first result record as
                   soon as possible.

               force_index [ INDEX | ARRAYREF ]
                   Force the use of the named indexes, specified by an index name or a reference to an array  of
                   index names.

               high_priority BOOL
                   If true, give this query higher priority.

               ignore_index [ INDEX | ARRAYREF ]
                   Ignore  the  named  indexes,  specified  by an index name or a reference to an array of index
                   names.

               no_cache BOOL
                   If true, ask the database not to store the result in its query cache.

               small_result BOOL
                   If true, indicate to the database that the result set is expected to be small.

               straight_join BOOL
                   If true, ask the database to join the tables in the order that they are listed in the  "FROM"
                   clause of the SQL statement.

               strict_ops BOOL
                   If   true,  any  comparison  operator  used  in  the  "query"  that  is  not  listed  in  the
                   Rose::DB::Object::QueryBuilder documentation will cause a fatal error.  The default value  is
                   determined by the strict_ops class method.

               use_index [ INDEX | ARRAYREF ]
                   Prefer  to  use  the  named indexes, specified by an index name or a reference to an array of
                   index names.

           inject_results BOOL
               If true, then the data returned from the database will be directly "injected"  into  the  objects
               returned  by  this  method,  bypassing the constructor and column mutator methods for each object
               class.  The default is false.  This parameter is ignored (i.e., treated as if it were  false)  if
               the "select" parameter is passed.

               This  parameter  is  useful for situations where the performance of get_objects is limited by the
               speed at which Rose::DB::Object-derived objects can be created.  It's safe to set this  parameter
               to true only if the constructor and column mutator methods for all of the classes involved do not
               have any side-effects (or if it's is okay to bypass any side-effects).

               The  default  Rose::DB::Object  constructor  and the column mutator methods created by the column
               classes included in the Rose::DB::Object module distribution do not  have  any  side-effects  and
               should therefore be safe to use with this parameter.

           limit NUM
               Return a maximum of NUM objects.

           limit_with_subselect BOOL
               This  parameter  controls  whether  or not this method will consider using a sub-query to express
               "limit"/"offset" constraints when fetching sub-objects related through one of  the  "...-to-many"
               relationship  types.   Not all databases support this syntax, and not all queries can use it even
               in supported databases.  If this parameter is true, the feature will be used when possible.

               The default value is determined by the default_limit_with_subselect class method.

           lock [ TYPE | HASHREF ]
               Select the objects using some form of locking.   These  lock  directives  have  database-specific
               behavior  and  not  all  directives  are  supported  by  all  databases.  Consult your database's
               documentation to find out more.  Use the debug parameter to see the generated SQL.

               The value should be a reference to a hash or a TYPE string, which is equivalent  to  setting  the
               value of the "type" key in the hash reference form.  For example, these are both equivalent:

                   lock => 'for update'
                   lock => { type => 'for update' }

               Valid hash keys are:

               columns ARRAYREF
                   A  reference  to  an  array  of column names to lock.  The columns may be prefixed with their
                   table name or their "tN" alias (e.g., "mytable.mycol" or "t2.mycol")  or  left  unadorned  if
                   they are not ambiguous.  References to scalars will be de-referenced and used as-is, included
                   literally in the SQL locking clause.

               nowait BOOL
                   If true, do not wait to acquire the lock.  If supported, this is usually by adding a "NOWAIT"
                   directive to the SQL.

               on ARRAYREF
                   A  reference to an array of items to lock.  Depending on the database, these may be column or
                   tables.  Both column and table names should be  specified  using  dot-separated  relationship
                   paths.

                   For  example,  "vendor.region.name"  would  lock the "name" column in the table arrived at by
                   traversing the "vendor" and then the "region" relationships, starting from the primary  table
                   ("t1").  Lone column names may also be used, provided they're not ambiguous.

                   For  locking  whole tables, "vendor.region" would lock the table arrived at by traversing the
                   "vendor" and then the "region" relationships.  (See the require_objects  parameter  for  more
                   information on relationship traversal.)

                   Finally,  references  to  scalars will be de-referenced and used as-is, included literally in
                   the SQL locking clause.

               skip_locked BOOL
                   If true, skip any locked rows.  If supported, this is  usually  by  adding  a  "SKIP  LOCKED"
                   clause to the SQL.

               tables ARRAYREF
                   A  reference  to  an  array  of  tables  to  lock.   Table named or "tN" aliases may be used.
                   References to scalars will be de-referenced and used as-is, included  literally  in  the  SQL
                   locking clause.

               type TYPE
                   The type of lock to acquire.  Valid values for TYPE are "for update" and "shared".  This hash
                   key is required unless the for_update parameter was passed with a true value.

               wait TIME
                   Wait  for  the  specified  TIME  (generally  seconds) before giving up acquiring the lock. If
                   supported, this is usually by adding a "WAIT ..." clause to the SQL.

               You may pass only one of the parameters that specifies "what to lock" (i.e., "columns", "on",  or
               "tables").

           nested_joins BOOL
               This  parameter  controls  whether or not this method will consider using nested JOIN syntax when
               fetching related objects.  Not all databases support this syntax, and not all queries will use it
               even in supported databases.  If this parameter is true, the feature will be used when possible.

               The default value is determined by the default_nested_joins class method.

           multi_many_ok BOOL
               If true, do not print a warning when attempting to do multiple LEFT OUTER  JOINs  against  tables
               related  by  "... to many" relationships.  See the documentation for the "with_objects" parameter
               for more information.

           nonlazy [ BOOL | ARRAYREF ]
               By default, get_objects will honor all load-on-demand columns when fetching  objects.   Use  this
               parameter to override that behavior and select all columns instead.

               If  the  value  is a true boolean value (typically "1"), then all columns will be fetched for all
               participating classes (i.e., the main object class as well as any sub-object classes).

               The value can  also  be  a  reference  to  an  array  of  relationship  names.   The  sub-objects
               corresponding  to  each  relationship name will have all their columns selected.  To refer to the
               main class (the "t1" table), use the special name "self".

           object_args HASHREF
               A reference to a hash of name/value pairs to be passed to the constructor of each  "object_class"
               object fetched, in addition to the values from the database.

           object_class CLASS
               The  name  of  the Rose::DB::Object-derived objects to be fetched.  This parameter is required; a
               fatal error will occur if it is omitted.  Defaults to the  value  returned  by  the  object_class
               class method.

           offset NUM
               Skip the first NUM rows.  If the database supports some sort of "limit with offset" syntax (e.g.,
               "LIMIT  10  OFFSET  20") then it will be used.  Otherwise, the first NUM rows will be fetched and
               then discarded.

               This parameter can only be used along with the "limit" parameter, otherwise a  fatal  error  will
               occur.

           page NUM
               Show page number NUM of objects.  Pages are numbered starting from 1.  A page number less than or
               equal to zero causes the page number to default to 1.

               The  number  of  objects  per  page  can  be  set by the "per_page" parameter.  If the "per_page"
               parameter is supplied and this parameter is omitted, it defaults to 1 (the first page).

               If this parameter is included along with either of the "limit" or <offset>  parameters,  a  fatal
               error will occur.

           per_page NUM
               The   number   of   objects   per   "page".     Defaults   to   the   value   returned   by   the
               default_objects_per_page class method (20, by default).

               If this parameter is included along with either of the "limit" or <offset>  parameters,  a  fatal
               error will occur.

           prepare_cached BOOL
               If  true,  then  DBI's  prepare_cached  method  will be used (instead of the prepare method) when
               preparing the SQL statement that will fetch the  objects.   If  omitted,  the  default  value  is
               determined by the dbi_prepare_cached class method.

           query ARRAYREF
               The  query  parameters,  passed  as a reference to an array of name/value pairs.  These pairs are
               used to formulate the "where" clause of the SQL query that, in turn, is used to fetch the objects
               from the database.  Arbitrarily nested boolean logic is supported.

               For the complete list of valid parameter names and values, see the documentation for the  "query"
               parameter of the build_select function in the Rose::DB::Object::QueryBuilder module.

               This    class    also    supports    an    extension   to   the   query   syntax   supported   by
               Rose::DB::Object::QueryBuilder.  In addition to  table  names  and  aliases,  column  (or  column
               method)  names  may  be  prefixed  with  foreign  key  or relationship names.  These names may be
               chained, with dots (".") separating the components.

               For example, imagine three  tables,  "products",  "vendors",  and  "regions",  fronted  by  three
               Rose::DB::Object-derived   classes,   "Product",  "Vendor",  and  "Region",  respectively.   Each
               "Product" has a "Vendor", and each "Vendor" has a "Region".

               To select only products whose vendors are in the United States, use a query argument like this:

                   query => [ 'vendor.region.name' => 'US' ],

               This assumes that the "Product" class has a relationship  or  foreign  key  named  "vendor"  that
               points  to  the product's "Vendor", and that the "Vendor" class has a foreign key or relationship
               named "region" that points to the vendor's "Region", and that 'vendor.region' (or any foreign key
               or  relationship  name  chain  that  begins  with  'vendor.region.')  is  an  argument   to   the
               "with_objects" or "require_objects" parameters.

               Please  note  that  the  "tN"  table  aliases  are not allowed in front of these kinds of chained
               relationship parameters.  (The chain of relationship names specifies the  target  table,  so  any
               "tN" alias would be redundant at best, or present a conflict at worst.)

           require_objects ARRAYREF
               Only  fetch  rows  from  the  primary table that have all of the associated sub-objects listed in
               ARRAYREF,  a  reference  to  an  array  of  foreign  key  or  relationship  names   defined   for
               "object_class".   The supported relationship types are "one to one," "one to many," and  "many to
               many".

               For each foreign key or relationship name listed in ARRAYREF, another table will be added to  the
               query via an implicit inner join.  The join conditions will be constructed automatically based on
               the  foreign  key  or  relationship  definitions.   Note  that  each  related  table  must have a
               Rose::DB::Object-derived class fronting it.

               Foreign key and relationship names may be chained, with dots (".")  separating  each  name.   For
               example,   imagine   three  tables,  "products",  "vendors",  and  "regions",  fronted  by  three
               Rose::DB::Object-derived  classes,  "Product",  "Vendor",  and  "Region",   respectively.    Each
               "Product" has a "Vendor", and each "Vendor" has a "Region".

               To  fetch  "Product"s  along  with  their  "Vendor"s,  and  their  vendors'  "Region"s, provide a
               "with_objects" argument like this:

                   require_objects => [ 'vendor.region' ],

               This assumes that the "Product" class has a relationship  or  foreign  key  named  "vendor"  that
               points  to  the product's "Vendor", and that the "Vendor" class has a foreign key or relationship
               named "region" that points to the vendor's "Region".

               This chaining syntax can be used to traverse relationships of any kind, including "one  to  many"
               and "many to many" relationships, to an arbitrary depth.

               The following optional suffixes may be added after any name in the chain in order to override the
               join type used:

                   Suffix    Join Type
                   ------    ----------
                   !         Inner join
                   ?         Left outer join

               Each  link  in  a  "require_objects"  chain  uses  an inner join by default.  In other words, the
               following "require_objects" parameters are all equivalent:

                   # These all mean the same thing
                   require_objects => [ 'vendor.region'   ]
                   require_objects => [ 'vendor!.region!' ]
                   require_objects => [ 'vendor.region!'  ]
                   require_objects => [ 'vendor!.region'  ]

               Thus, it is only really useful to use the "?" suffix in "require_objects" parameters (though  the
               "!" suffixes don't do any harm).  Here's a useful example of a call with hybrid join chain:

                   $products =
                     Product::Manager->get_products(
                       require_objects => [ 'vendor.region?' ]);

               All  product  objects returned would have associated vendor objects, but those vendor objects may
               or may not have associated region objects.

               Note that inner joins may be implicit and nested_joins may or may not be used.   When  in  doubt,
               use the debug parameter to see the generated SQL.

               Warning:  there  may  be  a geometric explosion of redundant data returned by the database if you
               include more than one "... to many" relationship in ARRAYREF.  Sometimes this may still  be  more
               efficient  than making additional queries to fetch these sub-objects, but that all depends on the
               actual data.  A warning will be emitted (via Carp::cluck) if you include more than  one  "...  to
               many"  relationship in ARRAYREF.  If you're sure you know what you're doing, you can silence this
               warning by passing the "multi_many_ok" parameter with a true value.

               Note: the "require_objects" list currently cannot be used to  simultaneously  fetch  two  objects
               that both front the same database table, but are of different classes.  One workaround is to make
               one  class  use  a synonym or alias for one of the tables.  Another option is to make one table a
               trivial view of the other.  The objective is to get the table names  to  be  different  for  each
               different  class  (even  if  it's  just  a  matter  of letter case, if your database is not case-
               sensitive when it comes to table names).

           select [ CLAUSE | ARRAYREF ]
               Select only the columns specified in either  a  comma-separated  string  of  column  names  or  a
               reference  to  an  array  of column names.  Strings are naively split between each comma.  If you
               need more complex parsing, please use the array-reference argument format instead.

               Column names should be prefixed by the appropriate "tN" table  alias,  the  table  name,  or  the
               foreign  key  or  relationship  name.   The prefix should be joined to the column name with a dot
               (".").  Examples: "t2.name", "vendors.age".

               Unprefixed columns are assumed to belong to the primary table ("t1") and are explicitly  prefixed
               as  such  when selecting from more than one table.  If a column name matches "/ AS \w+$/" then no
               prefix is applied.

               If the column name is "*" (e.g., "t1.*") then all columns from that table are selected.

               If an item in the referenced array is itself a reference to a scalar,  then  that  item  will  be
               dereferenced and passed through unmodified.

               If  selecting sub-objects via the "with_objects" or "require_objects" parameters, you must select
               the primary key columns from each sub-object table.  Failure to  do  so  will  cause  those  sub-
               objects not to be created.

               Be warned that you should provide some way to determine which column or method and which class an
               item belongs to: a tN prefix, a column name, or at the very least an "... AS ..." alias clause.

               If any "with_objects" or "require_objects" arguments are included in this call, the "select" list
               must  include  at  least  the primary key column(s) from each table that contributes to the named
               relationships.

               This parameter conflicts with the "fetch_only" parameter.  A fatal error will occur if  both  are
               used in the same call.

               If  this  parameter  is  omitted,  then  all  columns  from all participating tables are selected
               (optionally modified by the "nonlazy" parameter).

           share_db BOOL
               If true, "db" will be passed to each Rose::DB::Object-derived  object  when  it  is  constructed.
               Defaults to true.

           sort_by [ CLAUSE | ARRAYREF ]
               A  fully  formed SQL "ORDER BY ..." clause, sans the words "ORDER BY", or a reference to an array
               of strings or scalar references to be de-referenced as needed, joined with a comma, and  appended
               to the "ORDER BY" clause.

               If  an  argument  is  a  reference  to a scalar, then it is passed through to the ORDER BY clause
               unmodified.

               Otherwise, within each string, any instance of "NAME." will  be  replaced  with  the  appropriate
               "tN."  table  alias,  where  NAME  is a table, foreign key, or relationship name.  All unprefixed
               simple column names are assumed to belong to the primary table ("t1").

               If selecting sub-objects (via "require_objects" or "with_objects") that are related through  "one
               to  many" or "many to many" relationships, the first condition in the sort order clause must be a
               column in the primary table (t1).  If this condition is not met, the list of primary key  columns
               will be added to the beginning of the sort order clause automatically.

           table_aliases BOOL
               When  only  a  single  table  is used in q auery, this parameter controls whether or not the "tN"
               aliases are used.  If the parameter is not passed, then tables are aliased.  If it is passed with
               a false value, then tables are not aliased.  When more than one table participates  in  a  query,
               the "tN" table aliases are always used and this option is ignored.

           unique_aliases BOOL
               If  true, and if there is no explicit value for the "select" parameter and more than one table is
               participating in the query, then each selected column will be given a unique alias  by  prefixing
               it with its table alias and an underscore.  The default value is false.  Example:

                   SELECT
                     t1.id    AS t1_id,
                     t1.name  AS t1_name,
                     t2.id    AS t2_id,
                     t2.name  AS t2_name
                   FROM
                     foo AS t1,
                     bar AS t2
                   WHERE
                     ...

               These  unique aliases provide a technique of last resort for unambiguously addressing a column in
               a query clause.

           where ARRAYREF
               This is an alias for the "query" parameter (see above).

           with_map_records [ BOOL | METHOD | HASHREF ]
               When fetching related objects through a "many to many" relationship, objects of the map class are
               not retrieved by default.  Use this parameter to override the default behavior.

               If the value is "1", then each object fetched through a mapping table will  have  its  associated
               map record available through a "map_record()" attribute.

               If  a method name is provided instead, then each object fetched through a mapping table will have
               its associated map record available through a method of that name.

               If the value is a reference to a hash, then the keys  of  the  hash  should  be  "many  to  many"
               relationship names, and the values should be the method names through which the maps records will
               be available for each relationship.

           with_objects ARRAYREF
               Also fetch sub-objects (if any) associated with rows in the primary table based on a reference to
               an  array  of  foreign  key  or  relationship  names  defined  for "object_class".  The supported
               relationship types are "one to one," "one to many," and  "many to many".

               For each foreign key or relationship name listed in ARRAYREF, another table will be added to  the
               query  via  an  explicit  LEFT  OUTER JOIN.  (Foreign keys whose columns are all NOT NULL are the
               exception, however.  They are always fetched via inner joins.)    The  join  conditions  will  be
               constructed  automatically  based on the foreign key or relationship definitions.  Note that each
               related table must have a Rose::DB::Object-derived class fronting it.  See the  synopsis  for  an
               example.

               "Many  to  many"  relationships  are  a special case.  They will add two tables to the query (the
               "map" table plus the table with the actual data), which will offset the "tN" table  numbering  by
               one extra table.

               Foreign  key  and  relationship  names may be chained, with dots (".") separating each name.  For
               example,  imagine  three  tables,  "products",  "vendors",  and  "regions",  fronted   by   three
               Rose::DB::Object-derived   classes,   "Product",  "Vendor",  and  "Region",  respectively.   Each
               "Product" has a "Vendor", and each "Vendor" has a "Region".

               To fetch "Product"s  along  with  their  "Vendor"s,  and  their  vendors'  "Region"s,  provide  a
               "with_objects" argument like this:

                   with_objects => [ 'vendor.region' ],

               This  assumes  that  the  "Product"  class  has a relationship or foreign key named "vendor" that
               points to the product's "Vendor", and that the "Vendor" class has a foreign key  or  relationship
               named "region" that points to the vendor's "Region".

               This  chaining  syntax can be used to traverse relationships of any kind, including "one to many"
               and "many to many" relationships, to an arbitrary depth.

               The following optional suffixes may be added after any name in the chain in order to override the
               join type used:

                   Suffix    Join Type
                   ------    ----------
                   !         Inner join
                   ?         Left outer join

               Each link in a "with_objects" chain uses a left outer join  by  default.   In  other  words,  the
               following "with_objects" parameters are all equivalent:

                   # These all mean the same thing
                   with_objects => [ 'vendor.region'   ]
                   with_objects => [ 'vendor?.region?' ]
                   with_objects => [ 'vendor.region?'  ]
                   with_objects => [ 'vendor?.region'  ]

               Thus, it is only really useful to use the "!" suffix in "with_objects" parameters (though the "?"
               suffixes don't do any harm).  Here's a useful example of a call with hybrid join chain:

                   $products =
                     Product::Manager->get_products(
                       with_objects => [ 'vendor!.region' ]);

               All product objects returned would have associated vendor objects, but those vendor object may or
               may not have associated region objects.

               Note  that  inner  joins may be implicit and nested_joins may or may not be used.  When in doubt,
               use the debug parameter to see the generated SQL.

               Warning: there may be a geometric explosion of redundant data returned by  the  database  if  you
               include  more  than one "... to many" relationship in ARRAYREF.  Sometimes this may still be more
               efficient than making additional queries to fetch these sub-objects, but that all depends on  the
               actual  data.   A  warning will be emitted (via Carp::cluck) if you include more than one "... to
               many" relationship in ARRAYREF.  If you're sure you know what you're doing, you can silence  this
               warning by passing the "multi_many_ok" parameter with a true value.

               Note:  the  "with_objects" list currently cannot be used to simultaneously fetch two objects that
               both front the same database table, but are of different classes.  One workaround is to make  one
               class  use  a  synonym  or  alias  for  one of the tables.  Another option is to make one table a
               trivial view of the other.  The objective is to get the table names  to  be  different  for  each
               different  class  (even  if  it's  just  a  matter  of letter case, if your database is not case-
               sensitive when it comes to table names).

       get_objects_count [PARAMS]
           Accepts the same arguments as get_objects, but just returns the number of  objects  that  would  have
           been fetched, or undef if there was an error.

       get_objects_from_sql [ SQL | PARAMS ]
           Fetch  objects  using  a  custom  SQL  query.   Pass  either  a single SQL query string or name/value
           parameters as arguments.  Valid parameters are:

           args ARRAYREF
               A reference to an array of arguments to be passed to DBI's execute method when the query is  run.
               The number of items in this array must exactly match the number of placeholders in the SQL query.

           db DB
               A  Rose::DB-derived  object  used  to  access  the  database.  If omitted, one will be created by
               calling the init_db method of the "object_class".

           object_class CLASS
               The class name of the Rose::DB::Object-derived objects to be  fetched.   Defaults  to  the  value
               returned by the object_class class method.

           prepare_cached BOOL
               If  true,  then  DBI's  prepare_cached  method  will be used (instead of the prepare method) when
               preparing the SQL statement that will fetch the  objects.   If  omitted,  the  default  value  is
               determined by the dbi_prepare_cached class method.

           prepare_options HASHREF
               A  reference  to a hash of attributes to be passed to DBI's prepare or prepare_cached method when
               preparing the SQL statement.

           share_db BOOL
               If true, "db" will be passed to each Rose::DB::Object-derived  object  when  it  is  constructed.
               Defaults to true.

           sql SQL
               The SQL query string.  This parameter is required.

           Each  column  returned  by  the  SQL  query must be either a column or method name in "object_class".
           Column names take precedence in the case of a conflict.

           Returns a reference to an array of "object_class" objects.

           Examples:

               package Product::Manager;
               use Product;
               use base 'Rose::DB::Object::Manager';
               sub object_class { 'Product' }
               ...

               $products = Product::Manager->get_objects_from_sql(<<"EOF");
               SELECT * FROM products WHERE sku % 2 != 0 ORDER BY status, type
               EOF

               $products =
                 Product::Manager->get_objects_from_sql(
                   args => [ '2005-01-01' ],
                   sql  => 'SELECT * FROM products WHERE release_date > ?');

       get_objects_iterator [PARAMS]
           Accepts any valid get_objects arguments, but return a Rose::DB::Object::Iterator object, or undef  if
           there was an error.

       get_objects_iterator_from_sql [PARAMS]
           Accepts  any valid get_objects_from_sql arguments, but return a Rose::DB::Object::Iterator object, or
           undef if there was an error.

       get_objects_sql [PARAMS]
           Accepts the same arguments as get_objects, but return the SQL query string that would have been  used
           to fetch the objects (in scalar context), or the SQL query string and a reference to an array of bind
           values (in list context).

       make_manager_methods PARAMS
           Create  convenience  wrappers  for Rose::DB::Object::Manager's get_objects, get_objects_iterator, and
           get_objects_count class methods in the target class.  These wrapper methods will  not  overwrite  any
           existing  methods  in  the  target class.  If there is an existing method with the same name, a fatal
           error will occur.

           PARAMS can take several forms, depending on the calling context.  For a call to  make_manager_methods
           to succeed, the following information must be determined:

           •   object class

               The class of the Rose::DB::Object-derived objects to be fetched or counted.

           •   base name or method name

               The  base  name  is  a  string used as the basis of the method names.  For example, the base name
               "products"  might  be  used  to  create  methods  named   "get_products",   "get_products_count",
               "get_products_iterator", "delete_products", and "update_products".

               In  the absence of a base name, an explicit method name may be provided instead.  The method name
               will be used as is.

           •   method types

               The types  of  methods  that  should  be  generated.   Each  method  type  is  a  wrapper  for  a
               Rose::DB::Object::Manager   class   method.    The   mapping  of  method  type  names  to  actual
               Rose::DB::Object::Manager class methods defaults to the following:

                   Type        Method
                   --------    ----------------------
                   objects     get_objects()
                   iterator    get_objects_iterator()
                   count       get_objects_count()
                   delete      delete_objects()
                   update      update_objects()

               You may override the auto_manager_method_name method in  the  object_class's  convention  manager
               class to customize one or more of these names.

           •   target class

               The class that the methods should be installed in.

           Here  are  all of the different ways that each of those pieces of information can be provided, either
           implicitly or explicitly as part of PARAMS.

           •   object class

               If an "object_class" parameter is passed in PARAMS, then its value is used as the  object  class.
               Example:

                   $class->make_manager_methods(object_class => 'Product', ...);

               If  the  "object_class"  parameter  is  not  passed,  and  if  the  target  class  inherits  from
               Rose::DB::Object::Manager and has also defined an "object_class" method, then the return value of
               that method is used as the object class.  Example:

                 package Product::Manager;

                 use Rose::DB::Object::Manager;
                 our @ISA = qw(Rose::DB::Object::Manager);

                 sub object_class { 'Product' }

                 # Assume object_class parameter is not part of the ... below
                 __PACKAGE__->make_manager_methods(...);

               In this case, the object class would be "Product".

               Finally, if none of the above conditions are met, one final option is considered.  If the  target
               class inherits from Rose::DB::Object, then the object class is set to the target class.

               If  the  object class cannot be determined in one of the ways described above, then a fatal error
               will occur.

           •   base name or method name

               If a "base_name" parameter is passed in PARAMS, then its value is used as the base name  for  the
               generated methods.  Example:

                   $class->make_manager_methods(base_name => 'products', ...);

               If  the  "base_name"  parameter  is  not  passed, and if there is only one argument passed to the
               method, then the lone argument is used as the base name.  Example:

                   $class->make_manager_methods('products');

               (Note that, since the object class must be derived somehow, this will only work  in  one  of  the
               situations  (described  above)  where the object class can be derived from the calling context or
               class.)

               If a "methods" parameter is passed with a hash ref value, then each key of the hash  is  used  as
               the  base  name  for the method types listed in the corresponding value.  (See method types below
               for more information.)

               If a key of the "methods" hash ends in "()", then it is taken as the method name and is  used  as
               is.   For example, the key "foo" will be used as a base name, but the key "foo()" will be used as
               a method name.

               If  the  base  name  cannot  be  determined  in  one  of  the  ways  described  above,  then  the
               auto_manager_base_name  method  in the object_class's convention manager is called on to supply a
               base name.

           •   method types

               If  an  explicit  list  of  method  types  is  not  passed  to  the  method,  then  all  of   the
               default_manager_method_types are created.  Example:

                   # Base name is determined by convention manager auto_manager_base_name()
                   # method, all default method types created
                   $class->make_manager_methods();

                   # Base name is "products", all default method types created
                   $class->make_manager_methods('products');

                   # Base name is "products", all default method types created
                   $class->make_manager_methods(base_name => products', ...);

               (Again, note that the object class must be derived somehow.)

               If  a  "methods" parameter is passed, then its value must be a reference to a hash whose keys are
               base names or method names, and whose values are method types or references to arrays  of  method
               types.

               If  a  key  ends  in "()", then it is taken as a method name and is used as is.  Otherwise, it is
               used as a base name.  For example, the key "foo" will be used as a base name, but the key "foo()"
               will be used as a method name.

               If a key is a method name and its value specifies more than one method type, then a  fatal  error
               will occur.  (It's impossible to have more than one method with the same name.)

               Example:

                   # Make the following methods:
                   #
                   # * Base name: products; method types: objects, iterators
                   #
                   #     get_products()
                   #     get_products_iterator()
                   #
                   # * Method name: product_count; method type: count
                   #
                   #     product_count()
                   #
                   $class->make_manager_methods(...,
                     methods =>
                     {
                       'products'        => [ qw(objects iterator) ],
                       'product_count()' => 'count'
                     });

               If  the  value  of the "methods" parameter is not a reference to a hash, or if both the "methods"
               and "base_name" parameters are passed, then a fatal error will occur.

           •   target class

               If a "target_class" parameter is passed in PARAMS, then its value is used as  the  target  class.
               Example:

                   $class->make_manager_methods(target_class => 'Product', ...);

               If   a   "target_class"   parameter   is   not   passed,   and   if  the  calling  class  is  not
               Rose::DB::Object::Manager, then the calling class is used as the target  class.   Otherwise,  the
               class from which the method was called is used as the target class.  Examples:

                   # Target class is Product, regardless of the calling
                   # context or the value of $class
                   $class->make_manager_methods(target_class => 'Product', ...);

                   package Foo;

                   # Target class is Foo: no target_class parameter is passed
                   # and the calling class is Rose::DB::Object::Manager, so
                   # the class from which the method was called (Foo) is used.
                   Rose::DB::Object::Manager->make_manager_methods(
                     object_class => 'Bar',
                     base_name    => 'Baz');

                   package Bar;

                   # Target class is Foo: no target_class parameter is passed
                   # and the calling class is not Rose::DB::Object::Manager,
                   # so the calling class (Foo) is used.
                   Foo->make_manager_methods(object_class => 'Bar',
                                             base_name    => 'Baz');

           There's a lot of flexibility in this method's arguments (although some might use the word "confusion"
           instead), but the examples can be pared down to a few common usage scenarios.

           The first is the recommended technique, as seen in the synopsis. Create a separate manager class that
           inherits  from  Rose::DB::Object::Manager, override the "object_class" method to specify the class of
           the  objects  being  fetched,  and  then  pass  a  lone  base  name   argument   to   the   call   to
           make_manager_methods.

             package Product::Manager;

             use Rose::DB::Object::Manager;
             our @ISA = qw(Rose::DB::Object::Manager);

             sub object_class { 'Product' }

             __PACKAGE__->make_manager_methods('products');

           The second example is used to install object manager methods directly into a Rose::DB::Object-derived
           class.   I  do  not  recommend  this practice; I consider it "semantically impure" for the class that
           represents a single object to also be the class that's used to fetch multiple  objects.   Inevitably,
           classes  grow, and I'd like the "object manager" class to be separate from the object class itself so
           they can grow happily in isolation, with no potential clashes.

           Also, keep in mind that  Rose::DB::Object  and  Rose::DB::Object::Manager  have  separate  error_mode
           settings  which  must be synchronized or otherwise dealt with.  Another advantage of using a separate
           Rose::DB::Object::Manager subclass (as described earlier) is that you can override the error_mode  in
           your   Rose::DB::Object::Manager   subclass   only,   rather   than   overriding   the   base   class
           Rose::DB::Object::Manager error_mode, which may affect other classes.

           If none of that dissuades you, here's how to do it:

             package Product;

             use Rose::DB::Object:;
             our @ISA = qw(Rose::DB::Object);

             __PACKAGE__->make_manager_methods('products');

           Finally, sometimes you don't want or need to use make_manager_methods at all.  In fact,  this  method
           did  not exist in earlier versions of this module.  The formerly recommended way to use this class is
           still perfectly valid: subclass it and then call through to the base class methods.

             package Product::Manager;

             use Rose::DB::Object::Manager;
             our @ISA = qw(Rose::DB::Object::Manager);

             sub get_products
             {
               shift->get_objects(object_class => 'Product', @_);
             }

             sub get_products_iterator
             {
               shift->get_objects_iterator(object_class => 'Product', @_);
             }

             sub get_products_count
             {
               shift->get_objects_count(object_class => 'Product', @_);
             }

             sub delete_products
             {
               shift->delete_objects(object_class => 'Product', @_);
             }

             sub update_products
             {
               shift->update_objects(object_class => 'Product', @_);
             }

           Of course, these methods will all look very similar in each Rose::DB::Object::Manager-derived  class.
           Creating these identically structured methods is exactly what make_manager_methods automates for you.

           But  sometimes  you  want  to  customize  these methods, in which case the "longhand" technique above
           becomes essential.  For example, imagine that we want to extend the  code  in  the  synopsis,  adding
           support for a "with_categories" parameter to the "get_products()" method.

             Product::Manager->get_products(date_created    => '10/21/2001',
                                            with_categories => 1);

             ...

             sub get_products
             {
               my($class, %args) @_;

               if(delete $args{'with_categories'}) # boolean flag
               {
                 push(@{$args{'with_objects'}}, 'category');
               }

               Rose::DB::Object::Manager->get_objects(
                 %args, object_class => 'Product')
             }

           Here   we've   coerced   the  caller-friendly  "with_categories"  boolean  flag  parameter  into  the
           "with_objects => [  'category'  ]"  pair  that  Rose::DB::Object::Manager's  get_objects  method  can
           understand.

           This  is the typical evolution of an object manager method.  It starts out as being auto-generated by
           make_manager_methods, then becomes customized as new arguments are added.

       make_manager_method_from_sql [ NAME => SQL | PARAMS ]
           Create a class method in the calling class that will fetch objects using a  custom  SQL  query.   The
           method created will return a reference to an array of objects or a Rose::DB::Object::Iterator object,
           depending on whether the "iterator" parameter is set (see below).

           Pass  either  a  method  name  and  an SQL query string or name/value parameters as arguments.  Valid
           parameters are:

           iterator BOOL
               If true, the method created will return a Rose::DB::Object::Iterator object.

           object_class CLASS
               The class name of the Rose::DB::Object-derived objects to be  fetched.   Defaults  to  the  value
               returned by the object_class class method.

           params ARRAYREF
               To allow the method that will be created to accept named parameters (name/value pairs) instead of
               positional  parameters, provide a reference to an array of parameter names in the order that they
               should be passed to the call to DBI's execute method.

           method NAME
               The name of the method to be created.  This parameter is required.

           prepare_cached BOOL
               If true, then DBI's prepare_cached method will be used  (instead  of  the  prepare  method)  when
               preparing  the  SQL  statement  that  will  fetch  the objects.  If omitted, the default value is
               determined by the dbi_prepare_cached class method.

           share_db BOOL
               If true, "db" will be passed to each Rose::DB::Object-derived  object  when  it  is  constructed.
               Defaults to true.

           sql SQL
               The SQL query string.  This parameter is required.

           Each  column  returned  by  the  SQL  query must be either a column or method name in "object_class".
           Column names take precedence in the case of a conflict.

           Arguments passed to the created method will be passed to DBI's execute method when the query is  run.
           The  number  of arguments must exactly match the number of placeholders in the SQL query.  Positional
           parameters are required unless the "params" parameter is used.  (See description above.)

           Returns a code reference to the method created.

           Examples:

               package Product::Manager;

               use base 'Rose::DB::Object::Manager';
               ...

               # Make method that takes no arguments
               __PACKAGE__->make_manager_method_from_sql(get_odd_products =><<"EOF");
               SELECT * FROM products WHERE sku % 2 != 0
               EOF

               # Make method that takes one positional parameter
               __PACKAGE__->make_manager_method_from_sql(get_new_products =><<"EOF");
               SELECT * FROM products WHERE release_date > ?
               EOF

               # Make method that takes named parameters
               __PACKAGE__->make_manager_method_from_sql(
                 method => 'get_named_products',
                 params => [ qw(type name) ],
                 sql    => <<"EOF");
               SELECT * FROM products WHERE type = ? AND name LIKE ?
               EOF

               ...

               $products = Product::Manager->get_odd_products();

               $products = Product::Manager->get_new_products('2005-01-01');

               $products =
                 Product::Manager->get_named_products(
                   name => 'Kite%',
                   type => 'toy');

               # Make method that takes named parameters and returns an iterator
               __PACKAGE__->make_manager_method_from_sql(
                 method   => 'get_named_products_iterator',
                 iterator => 1,
                 params   => [ qw(type name) ],
                 sql      => <<"EOF");
               SELECT * FROM products WHERE type = ? AND name LIKE ?
               EOF

               $iterator =
                 Product::Manager->get_named_products_iterator(
                   name => 'Kite%',
                   type => 'toy');

               while(my $product = $iterator->next)
               {
                 ... # do something with $product

                 $iterator->finish  if(...); # finish early?
               }

       normalize_get_objects_args [ARGS]
           This method takes ARGS in  the  forms  accepted  by  get_objects  (and  other  similar  methods)  and
           normalizes  them  into  name/value  pairs.   Since get_objects can take arguments in many forms, this
           method is  useful  when  overriding  get_objects  in  a  custom  Rose::DB::Object::Manager  subclass.
           Example:

               package Product::Manager;

               use base 'Rose::DB::Object::Manager';

               use Product;

               sub object_class { 'Product' }
               ...

               sub get_products
               {
                 my($class, %args) = shift->normalize_get_objects_args(@_);

                 # Detect, extract, and handle custom argument
                 if(delete $args{'active_only'})
                 {
                   push(@{$args{'query'}}, status => 'active');
                 }

                 return $class->get_objects(%args); # call through to normal method
               }

           Now all of the following calls will work:

               $products =
                 Product::Manager->get_products([ type => 'boat' ], sort_by => 'name');

               $products =
                 Product::Manager->get_products({ name => { like => '%Dog%' } });

               $products =
                 Product::Manager->get_products([ id => { gt => 123 } ], active_only => 1);

       object_class
           Returns the class name of the Rose::DB::Object-derived objects to be managed by this class.  Override
           this method in your subclass.  The default implementation returns undef.

       perl_class_definition
           Attempts to create the Perl source code that is equivalent to the current class.  This works best for
           classes  created  via  Rose::DB::Object::Metadata's  make_manager_class method, but it will also work
           most of the time for classes whose methods were created using make_manager_methods.

           The Perl code is returned as a string.  Here's an example:

             package My::Product::Manager;

             use My::Product;

             use Rose::DB::Object::Manager;
             our @ISA = qw(Rose::DB::Object::Manager);

             sub object_class { 'My::Product' }

             __PACKAGE__->make_manager_methods('products');

             1;

       update_objects [PARAMS]
           Update rows in a table fronted by a Rose::DB::Object-derived class based on PARAMS, where PARAMS  are
           name/value pairs.  Returns the number of rows updated, or undef if there was an error.

           Valid parameters are:

           all BOOL
               If  set  to  a true value, this parameter indicates an explicit request to update all rows in the
               table.  If both the "all" and the "where" parameters are passed, a fatal error will occur.

           db DB
               A Rose::DB-derived object used to access the database.   If  omitted,  one  will  be  created  by
               calling the init_db method of the "object_class".

           object_class CLASS
               The  class name of the Rose::DB::Object-derived class that fronts the table whose rows will to be
               updated.  This parameter is required; a fatal error will occur if it is omitted.  Defaults to the
               value returned by the object_class class method.

           set PARAMS
               The names and values of the columns to be updated.  PARAMS should be a reference to a hash.  Each
               key of the hash should be a column name or column get/set method name.  If a value  is  a  simple
               scalar,  then  it  is  passed  through  the  get/set method that services the column before being
               incorporated into the SQL query.

               If a value is a reference to a scalar, then it is dereferenced  and  incorporated  into  the  SQL
               query as-is.

               If  a  value  is  a  reference  to  a  hash,  then it must contain a single key named "sql" and a
               corresponding value that will be incorporated into the SQL query as-is.

               Example:

                 $num_rows_updated =
                   Product::Manager->update_products(
                     set =>
                     {
                       end_date   => DateTime->now,
                       region_num => { sql => 'region_num * -1' }
                       count      => \q(count + 1),
                       status     => 'defunct',
                     },
                     where =>
                     [
                       status  => [ 'stale', 'old' ],
                       name    => { like => 'Wax%' }
                       or =>
                       [
                         start_date => { gt => '2008-12-30' },
                         end_date   => { gt => 'now' },
                       ],
                     ]);

               The call above would execute an SQL statement something like the one shown  below  (depending  on
               the database vendor, and assuming the current date was September 20th, 2005):

                   UPDATE products SET
                     end_date   = '2005-09-20',
                     region_num = region_num * -1,
                     count      = count + 1,
                     status     = 'defunct'
                   WHERE
                     status IN ('stale', 'old') AND
                     name LIKE 'Wax%' AND
                     (
                       start_date > '2008-12-30' OR
                       end_date   > '2005-09-20'
                     )

           where PARAMS
               The  query  parameters,  passed as a reference to an array of name/value pairs.  These PARAMS are
               used to formulate the "where" clause of the SQL query that is used to  update  the  rows  in  the
               table.  Arbitrarily nested boolean logic is supported.

               For  the complete list of valid parameter names and values, see the documentation for the "query"
               parameter of the build_select function in the Rose::DB::Object::QueryBuilder module.

               If this parameter is omitted, this method will refuse to update all rows in the table and a fatal
               error will occur.  To update all rows in a table, you must pass the "all" parameter with  a  true
               value.  If both the "all" and the "where" parameters are passed, a fatal error will occur.

       strict_ops [BOOL]
           Get  or set a boolean value that indicates whether using a comparison operator in the "query" that is
           not listed in the Rose::DB::Object::QueryBuilder documentation will cause a fatal error.  The default
           value is false.

SUPPORT

       For  an  informal  overview  of  Rose::DB::Object,  including  Rose::DB::Object::Manager,   consult   the
       Rose::DB::Object::Tutorial.

           perldoc Rose::DB::Object::Tutorial

       Any  Rose::DB::Object::Manager  questions or problems can be posted to the Rose::DB::Object mailing list.
       To subscribe to the list or view the archives, go here:

       <http://groups.google.com/group/rose-db-object>

       Although the mailing list is the preferred support mechanism, you can also email the author  (see  below)
       or file bugs using the CPAN bug tracking system:

       <http://rt.cpan.org/NoAuth/Bugs.html?Dist=Rose-DB-Object>

       There's also a wiki and other resources linked from the Rose project home page:

       <http://rosecode.org>

AUTHOR

       John C. Siracusa (siracusa@gmail.com)

LICENSE

       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.

perl v5.36.0                                       2022-10-14                     Rose::DB::Object::Manager(3pm)