NAME
DBIx::DBO::Query - An OO interface to SQL queries and results. Encapsulates an entire query in an object.
SYNOPSIS
# Create a Query object by JOINing 2 tables
my $query = $dbo->query('my_table', 'my_other_table');
# Get the Table objects from the query
my ($table1, $table2) = $query->tables;
# Add a JOIN ON clause
$query->join_on($table1 ** 'login', '=', $table2 ** 'username');
# Find our ancestors, and order by age (oldest first)
$query->where('name', '=', 'Adam');
$query->where('name', '=', 'Eve');
$query->order_by({ COL => 'age', ORDER => 'DESC' });
# New Query using a LEFT JOIN
($query, $table1) = $dbo->query('my_table');
$table2 = $query->join_table('another_table', 'LEFT');
$query->join_on($table1 ** 'parent_id', '=', $table2 ** 'child_id');
# Find those not aged between 20 and 30.
$query->where($table1 ** 'age', '<', 20, FORCE => 'OR'); # Force OR so that we get: (age < 20 OR age > 30)
$query->where($table1 ** 'age', '>', 30, FORCE => 'OR'); # instead of the default: (age < 20 AND age > 30)
DESCRIPTION
A Query
object represents rows from a database (from one or more tables). This module makes it easy, not only to fetch and use the data in the returned rows, but also to modify the query to return a different result set.
METHODS
new
DBIx::DBO::Query->new($dbo, $table1, ...);
Create a new Query
object from the tables specified. In scalar context, just the Query
object will be returned. In list context, the Query
object and DBIx::DBO::Table objects will be returned for each table specified.
reset
$query->reset;
Reset the query, start over with a clean slate.
NB: This will not remove the JOINs or JOIN ON clauses.
tables
Return a list of DBIx::DBO::Table objects for this query.
column
$query->column($alias_or_column_name);
Returns a reference to a column for use with other methods.
show
$query->show(@columns);
$query->show($table1, {COL => $table2 ** 'name', AS => 'name2'});
$query->show($table1 ** 'id', {FUNC => 'UCASE(?)', COL => 'name', AS => 'alias'}, ...
Specify which columns to show as an array. If the array is empty all columns will be shown. If you use a Table object, all the columns from that table will be shown.
distinct
$query->distinct(1);
my $is_distinct = $query->distinct();
Takes a boolean argument to add or remove the DISTINCT clause for the returned rows. Returns the previous setting.
join_table
$query->join_table($table, $join_type);
$query->join_table([$schema, $table], $join_type);
$query->join_table($table_object, $join_type);
Join a table onto the query, creating a DBIx::DBO::Table object if needed. This will perform a comma (", ") join unless $join_type is specified.
Valid join types are any accepted by the DB. Eg: 'JOIN'
, 'LEFT'
, 'RIGHT'
, undef
(for comma join), 'INNER'
, 'OUTER'
, ...
Returns the Table
object.
join_on
$query->join_on($table_object, $expression1, $operator, $expression2);
$query->join_on($table2, $table1 ** 'id', '=', $table2 ** 'id');
Join tables on a specific WHERE clause. The first argument is the table object being joined onto. Then a JOIN ON condition follows, which uses the same arguments as "where".
open_join_on_bracket
, close_join_on_bracket
$query->open_join_on_bracket($table, 'OR');
$query->join_on(...
$query->close_join_on_bracket($table);
Equivalent to open_bracket, but for the JOIN ON clause. The first argument is the table being joined onto.
where
Restrict the query with the condition specified (WHERE clause).
$query->where($expression1, $operator, $expression2);
$query->where($table1 ** 'id', '=', $table2 ** 'id');
$operator
is one of: '=', '<', '>', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN', ...
$expression
s can be any of the following:
A scalar value:
123
or'hello'
(or for$expression1
a column name:'id'
)A scalar reference:
\"22 * 3"
(These are passed unquoted in the SQL statement!)An array reference:
[1, 3, 5]
(Used withIN
andBETWEEN
etc)A Column object:
$table ** 'id'
or$table->column('id')
A hash reference: (Described below)
For a more complex where expression it can be passed as a hash reference. Possibly containing scalars, arrays or Column objects.
$query->where('name', '=', { FUNC => 'COALESCE(?,?)', VAL => [$name, 'Unknown'] });
$query->where('string', '=', { FUNC => "CONCAT('Mr. ',?)", COL => 'name' });
The keys to the hash in a complex expression are:
VAL
=> A scalar, scalar reference or an array reference.COL
=> The name of a column or a Column object.AS
=> An alias name.FUNC
=> A string to be inserted into the SQL, possibly containing "?" placeholders.COLLATE
=> The collation for this value/field.ORDER
=> To order by a column (Used only ingroup_by
andorder_by
).
Multiple where
expressions are combined cleverly using the preferred aggregator 'AND'
(unless open_bracket was used to change this). So that when you add where expressions to the query, they will be AND
ed together. However some expressions that refer to the same column will automatically be OR
ed instead where this makes sense, currently: '='
, 'IS NULL'
, <=>
, IN
and 'BETWEEN'
. Similarly, when the preferred aggregator is 'OR'
the following operators will be AND
ed together: '!='
, 'IS NOT NULL'
, <>
, NOT IN
and 'NOT BETWEEN'
.
$query->where('id', '=', 5);
$query->where('name', '=', 'Bob');
$query->where('id', '=', 7);
$query->where(...
# Produces: WHERE ("id" = 5 OR "id" = 7) AND "name" = 'Bob' AND ...
unwhere
$query->unwhere();
$query->unwhere($column);
Removes all previously added "where" restrictions for a column. If no column is provided, the whole WHERE clause is removed.
open_bracket
, close_bracket
$query->open_bracket('OR');
$query->where( ...
$query->where( ...
$query->close_bracket;
Used to group where
expressions together in parenthesis using either 'AND'
or 'OR'
as the preferred aggregator. All the where
calls made between open_bracket
and close_bracket
will be inside the parenthesis.
Without any parenthesis 'AND'
is the preferred aggregator.
group_by
$query->group_by('column', ...);
$query->group_by($table ** 'column', ...);
$query->group_by({ COL => $table ** 'column', ORDER => 'DESC' }, ...);
Group the results by the column(s) listed. This will replace the GROUP BY clause. To remove the GROUP BY clause simply call group_by
without any columns.
having
Restrict the query with the condition specified (HAVING clause). This takes the same arguments as "where".
$query->having($expression1, $operator, $expression2);
unhaving
$query->unhaving();
$query->unhaving($column);
Removes all previously added "having" restrictions for a column. If no column is provided, the whole HAVING clause is removed.
order_by
$query->order_by('column', ...);
$query->order_by($table ** 'column', ...);
$query->order_by({ COL => $table ** 'column', ORDER => 'DESC' }, ...);
Order the results by the column(s) listed. This will replace the ORDER BY clause. To remove the ORDER BY clause simply call order_by
without any columns.
limit
$query->limit;
$query->limit($rows);
$query->limit($rows, $offset);
Limit the maximum number of rows returned to $rows
, optionally skipping the first $offset
rows. When called without arguments or if $rows
is undefined, the limit is removed.
arrayref
$query->arrayref;
$query->arrayref(\%attr);
Run the query using DBI->selectall_arrayref which returns the result as an arrayref. You can specify a slice by including a 'Slice' or 'Columns' attribute in %attr
- See DBI->selectall_arrayref.
hashref
$query->hashref($key_field);
$query->hashref($key_field, \%attr);
Run the query using DBI->selectall_hashref which returns the result as an hashref. $key_field
defines which column, or columns, are used as keys in the returned hash.
col_arrayref
$query->col_arrayref;
$query->col_arrayref(\%attr);
Run the query using DBI->selectcol_arrayref which returns the result as an arrayref of the values of each row in one array. By default it pushes all the columns requested by the "show" method onto the result array (this differs from the DBI
). Or to specify which columns to include in the result use the 'Columns' attribute in %attr
- see DBI->selectcol_arrayref.
fetch
my $row = $query->fetch;
Fetch the next row from the query. This will run/rerun the query if needed.
Returns a DBIx::DBO::Row object or undefined if there are no more rows.
row
my $row = $query->row;
Returns the DBIx::DBO::Row object for the current row from the query or an empty DBIx::DBO::Row object if there is no current row.
run
$query->run;
Run/rerun the query. This is called automatically before fetching the first row.
rows
my $row_count = $query->rows;
Count the number of rows returned. Returns undefined if the number is unknown.
count_rows
my $row_count = $query->count_rows;
Count the number of rows that would be returned. Returns undefined if there is an error.
found_rows
$query->config(CalcFoundRows => 1); # Only applicable to MySQL
my $total_rows = $query->found_rows;
Return the number of rows that would have been returned if there was no limit clause. Before runnning the query the CalcFoundRows
config option can be enabled for improved performance on supported databases.
Returns undefined if there is an error or is unable to determine the number of found rows.
sql
my $sql = $query->sql;
Returns the SQL query statement string.
sth
my $sth = $query->sth;
Reutrns the DBI
statement handle from the query. This will run/rerun the query if needed.
finish
$query->finish;
Calls DBI->finish on the statement handle, if it's active. Restarts stored queries from the first row (if created using the StoreRows
config).
Common Methods
These methods are accessible from all DBIx::DBO* objects.
dbh
The read-write DBI
handle.
rdbh
The read-only DBI
handle, or if there is no read-only connection, the read-write DBI
handle.
do
$query->do($statement) or die $query->dbh->errstr;
$query->do($statement, \%attr) or die $query->dbh->errstr;
$query->do($statement, \%attr, @bind_values) or die ...
This provides access to DBI->do method. It defaults to using the read-write DBI
handle.
config
$query_setting = $query->config($option);
$query->config($option => $query_setting);
Get or set this Query
object's config settings. When setting an option, the previous value is returned. When getting an option's value, if the value is undefined, the DBIx::DBO's value is returned.
See "Available_config_options" in DBIx::DBO.
SUBCLASSING
When subclassing DBIx::DBO::Query
, please note that Query
objects created with the "new" method are blessed into a DBD driver specific module. For example, if using MySQL, a new Query
object will be blessed into DBIx::DBO::Query::DBD::mysql
which inherits from DBIx::DBO::Query
. However if objects are created from a subclass called MySubClass
the new object will be blessed into MySubClass::DBD::mysql
which will inherit from both MySubClass
and DBIx::DBO::Query::DBD::mysql
.
Classes can easily be created for tables in your database. Assume you want to create a Query
and Row
class for a "Users" table:
package My::Users;
use base 'DBIx::DBO::Query';
sub new {
my $class = shift;
my $dbo = shift;
my $self = $class->SUPER::new($dbo, 'Users'); # Create the Query for the "Users" table
# We could even add some JOINs or other clauses here
return $self;
}
sub _row_class { 'My::User' } # Rows are blessed into this class
package My::User;
use base 'DBIx::DBO::Row';
sub new {
my $class = shift;
my ($dbo, $parent) = @_;
$parent ||= My::Users->new($dbo); # The Row will use the same table as it's parent
$class->SUPER::new($dbo, $parent);
}
TODO LIST
Better explanation of how to construct complex queries. This module is currently still in development (including the documentation), but I will be adding to/completing it in the near future.