Provided by: librose-db-object-perl_0.815-1_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.