DBIx-Oro
文件大小: unknow
源码售价: 5 个金币 积分规则     积分充值
资源说明:Simple Database Accessor
=pod

=head1 NAME

DBIx::Oro - Simple Relational Database Accessor


=head1 SYNOPSIS

  use DBIx::Oro;

  # Create new object
  my $oro = DBIx::Oro->new(

    # Create an SQLite in-memory DB and initialize
    ':memory:' => sub {

      # Initialize tables with direct SQL
      $_->do(
        'CREATE TABLE User (
           id    INTEGER PRIMARY KEY,
           name  TEXT,
           age   TEXT
        )'
      ) or return -1;
    }
  );

  # Execute SQL directly
  $oro->do(
    'CREATE TABLE Post (
       time     INTEGER,
       msg      TEXT,
       user_id  INTEGER
    )'
  );

  # Wrap multiple actions in transactions
  $oro->txn(
    sub {

      # Insert simple data
      my $rv = $_->insert(User => {
        name => 'Akron',
        age  => '20'
      });

      # Easily rollback transaction
      return -1 unless $rv;

      # Get latest inserted id
      my $user_id = $_->last_insert_id;

      # Bulk insert data with default values
      $_->insert(Post => [
        [ time => time ],
        [ user_id => $user_id ],
        'msg'] => (
          ['Hello World!'],
    ['Seems to work!'],
    ['I can insert bulk messages ...'],
    ['And I can stop.']
        )
      ) or return -1;
  });

  # Load a dataset based on a unique condition
  my $user = $oro->load(User => { name => 'Akron' });

  print $user->{age}; # '20'

  # Count the number of entries on a table
  print $oro->count('Post'); # '4'

  # Select multiple datasets based on conditions
  my $msgs = $oro->select(Post => ['msg'] => {
    msg => { like => '%wo%' }
  });

  # Results are simple datastructures
  print $_->{msg} . "\n" foreach @$msgs;
  # 'Hello World!'
  # 'Seems to work!'

  # Create joined tables
  my $join = $oro->table([
    User => ['name'] => { id => 1 },
    Post => ['msg']  => { user_id => 1 }
  ]);

  # Select on joined tables and send data to a callback
  my $msg = $join->select({
      name   => 'Akron',
      msg    => { not_glob => 'And*' },
      -limit => 2
  });
  foreach (@$msg) {
    print $_->{name}, ': ', $_->{msg}, "\n";
  };

  # Akron: Hello World!
  # Akron: I can insert bulk messages ...

  # Investigate generated SQL data for debugging
  print $join->last_sql;

  # 'SELECT User.name AS `name`, Post.msg AS `msg`
  # FROM User, Post WHERE User.id = Post.user_id
  # AND Post.msg NOT GLOB ? AND User.name = ?
  # LIMIT ?'


=head1 DESCRIPTION

L is a database accessor that provides
basic functionalities to work with simple relational databases,
especially in a web environment.

Its aim is not to be a complete abstract replacement
for SQL communication with DBI, but to make common tasks easier.
For now it's focused on SQLite - but first steps to make it less
dependent on SQLite are done. It should be fork- and thread-safe.

See L
and L
for database specific drivers.

B.>


=head1 ATTRIBUTES

=head2 dbh

  my $dbh = $oro->dbh;
  $oro->dbh(DBI->connect('...'));

The DBI database handle.


=head2 driver

  print $oro->driver;

The driver (e.g., C or C) of the Oro instance.


=head2 last_insert_id

  my $id = $oro->last_insert_id;

The globally last inserted id regarding the database connection.


=head2 last_sql

  print $oro->last_sql;
  my ($sql, $from_cache) = $oro->last_sql;

The last executed SQL command.

In array context this will also return a value indicating
if the request was a real database request.
If the last result was returned by a cache, the value is true, otherwise false.

B This is for debugging purposes only - the returned SQL may not be
valid due to reformatting.

B


=head1 METHODS

=head2 new

  my $oro = DBIx::Oro->new('test.sqlite');
  $oro = DBIx::Oro->new('test.sqlite' => sub {
    shift->do(
      'CREATE TABLE Person (
          id    INTEGER PRIMARY KEY,
          name  TEXT NOT NULL,
          age   INTEGER
      )');
  });
  $oro = DBIx::Oro->new(
    driver   => 'MySQL',
    database => 'TestDB',
    user     => 'root',
    password => ''
  );

Creates a new Oro database handle.

Accepts a C attribute (supported are currently
C and C) all attributes
accepted by this specific driver.

If only a string value is given, this will be treated as
a filename of a L object.
If the filename is C<:memory:>, this will be an in-memory SQLite database.
If the database file does not already exist, it is created.
An additional callback function may be passed, that serves
as the C attribute of the SQLite
Driver's L.

B


=head2 insert

  $oro->insert(Person => {
    id   => 4,
    name => 'Peter',
    age  => 24,
    address => \"SELECT address FROM Address where id = 4",
    country => [\"SELECT country FROM County where id = ?", 3]
  });
  $oro->insert(Person =>
    ['id', 'name'] => [4, 'Peter'], [5, 'Sabine']
  );

Inserts a new row to a given table for single insertions.

Expects the table name and a hash reference of values to insert.
In case the values are scalar references, the string is directly used
as an SQL statement. In case the values are array references and the first
element is a scalar reference, the string is directly used as an SQL
statement and the following values are inserted for placeholders.

For multiple insertions, it expects the table name
to insert, an array reference of the column names and an arbitrary
long array of array references of values to insert.

  $oro->insert(Person =>
    ['prename', [ surname => 'Meier' ]] =>
      map { [$_] } qw/Peter Sabine Frank/
  );

For multiple insertions with defaults, the array reference for column
names can contain array references itself with a column name followed by
the default value. This value is inserted for each inserted entry
and is especially useful for C relation tables.

B The treatment of scalar and array references as insertion values
is EXPERIMENTAL and may change without warnings.

=head2 update

  my $rows = $oro->update(Person => { name => 'Daniel' }, { id => 4 });

Updates values of an existing row of a given table.

Expects the table name to update, a hash reference of values to update,
and optionally a hash reference with L, the rows have to fulfill.

Returns the number of rows affected.


=head2 merge

  $oro->merge(Person => { age => 29 }, { name => 'Daniel' });

Updates values of an existing row of a given table,
otherwise inserts them (so called I).

Expects the table name to update or insert, a hash reference of
values to update or insert, and optionally a hash reference with L,
the rows have to fulfill.

Scalar condition values will be inserted, if the field values do not exist.


=head2 select

  my $users = $oro->select('Person');
  $users = $oro->select(Person => ['id', 'name']);
  $users = $oro->select(Person =>
    [qw/id age/] => {
      age    => 24,
      name   => ['Daniel', 'Sabine'],
      rights => [\"SELECT right FROM Rights WHERE right = ?", 2]
    });
  $users = $oro->select(Person => ['name:displayName']);


Returns an array reference of rows as hash references of a given table,
that meet a given condition.

Expects the table name of the selection
(or a L)
and optionally an array reference
of fields, optionally a hash reference with L,
L, and SQL specific L
all rows have to fulfill.

Fields can be column names or SQL functions.
With a colon you can define aliases of field names,
like with C.
For preprocessing field values special L can be applied.


=head2 load

  my $user  = $oro->load(Person => { id => 4 });
  my $user  = $oro->load(Person => ['name'], { id => 4 });
  my $count = $oro->load(Person => ['count(*):persons']);

Returns a single hash reference of a given table,
that meets a given condition.

Expects the table name of selection (or a L),
an optional array reference of fields
to return and a hash reference with L, the rows have to fulfill.
Normally this will include the primary key.
L, L,
L as well as the L can be applied
as with L.
Fields can be column names or functions. With a colon you can define
aliases for the field names.


=head2 list

  my $users = $oro->list(Table => {
    sortBy => 'name',
    startPage => 5,
    count => 20
  });

Returns a response hash based on queries as specified in
L
and L.
This is useful to be directly called from web applications.

Expects a table name (in case no table or joined table was created
using L) and a hash reference supporting the following
parameters:

=over 4

=item startIndex

The offset index of the result set.
Needs to be a positive integer. Defaults to C<0>.

=item startPage

The page number of the result set. Defaults to C<1>.

=item count

The number of entries per page. Defaults to C<25>.

=item sortBy

The field to sort the result by.
Needs to be a field name.

=item sortOrder

The order of sorting. Defaults to C.
Also accepts C.

=item filterBy

A field to filter the result by.

=item filterOp

The operation to filter the results based on the C field.
Supports C, to filter on results that have the field defined
(opposite to C), C, to filter on results that have
the field with a value defined by C (opposite to C),
C, to filter on results that have a field
containing a string defined by C, and C, to filter
on results that have a field starting with a string defined by C.

B: The C and C filter operations are EXPERIMENTAL
and may change without warnings.

=item filterValue

The string to check with C.


=item fields

An array reference or comma separated string of
fields to be returned. Defaults to all fields.

=back

In addition to that, the caching system can be applied as with L.

A final callback function can be used to modify each entry.

The created response is a hash reference with the following structure:

  #  {
  #    totalResults => 44,
  #    startIndex   => 0,
  #    itemsPerPage => 20,
  #    startPage    => 5,
  #    entry => [
  #      { name => 'Akron', age => 20 },
  #      { name => 'Peter', age => 30 }
  #    ]
  #  }

The objects in the entry array can be different, depending on
the optionally passed callback function.

All valid parameters are returned, including the C value,
giving the number of elements in the non-filtered result set.
The C parameter is consumed and the correct C
value is returned. The C array reference contains hash references
of all rows.

B


=head2 count

  my $persons = $oro->count('Person');
  my $pauls   = $oro->count('Person' => { name => 'Paul' });

Returns the number of rows of a table.

Expects the table name and a hash reference with conditions,
the rows have to fulfill.
Caching can be applied as with L.


=head2 delete

  my $rows = $oro->delete(Person => { id => 4 });

Deletes rows of a given table, that meet a given condition.

Expects the table name of selection and optionally a hash reference
with conditions, L and L,
the rows have to fulfill.
In case of scalar values, identity is tested for the condition.
In case of array references, it is tested, if the field value is an
element of the set.
L and L can be applied as with L.

Returns the number of rows that were deleted.


=head2 table

  # Table names
  my $person = $oro->table('Person');
  print $person->count;
  my $person = $person->load({ id => 2 });
  my $persons = $person->select({ name => 'Paul' });
  $person->insert({ name => 'Ringo' });
  $person->delete;

  # Joined tables
  my $books = $oro->table(
    [
      Person =>    ['name:author', 'age:age'] => { id => 1 },
      Book =>      ['title'] => { author_id => 1, publisher_id => 2 },
      Publisher => ['name:publisher', 'id:pub_id'] => { id => 2 }
    ]
  );
  $books->select({ author => 'Akron' });
  $books->list({ filterBy => 'author', filterOp => 'present' });
  print $books->count;

Returns a new Oro object with a predefined table or joined tables.

Allows to omit the first table argument for the methods
L, L, L,
L and - in case of non-joined-tables -
for L, L, L, and L.

In conjunction with a L this can be seen as an I.

B


=head2 txn

  $oro->txn(
    sub {
      foreach (1..100) {
        $oro->insert(Person => { name => 'Peter'.$_ }) or return -1;
      };
      $oro->delete(Person => { id => 400 });

      $oro->txn(
        sub {
          $_->insert('Person' => { name => 'Fry' }) or return -1;
        }) or return -1;
    });

Wrap transactions.

Expects an anonymous subroutine containing all actions.
If the subroutine returns -1, the transactional data will be omitted.
Otherwise the actions will be released.
Transactions established with this method can be securely nested
(although inner transactions may not be true transactions depending
on the driver).


=head2 do

  $oro->do(
    'CREATE TABLE Person (
        id   INTEGER PRIMARY KEY,
        name TEXT NOT NULL,
     )');

Executes direct SQL code.

This is a wrapper for the L method of DBI (but fork- and thread-safe).


=head2 explain

  print $oro->explain(
    'SELECT ? FROM Person', ['name']
  );

Returns the query plan for a given query as a line-breaked string.

B


=head2 prep_and_exec

  my ($rv, $sth) = $oro->prep_and_exec(
    'SELECT ? FROM Person', ['name'], 'cached'
  );

  if ($rv) {
    my $row;
    while ($row = $sth->fetchrow_hashref) {
      print $row->{name};
      if ($name eq 'Fry') {
        $sth->finish;
        last;
      };
    };
  };

Prepare and execute an SQL statement with all checkings.
Returns the return value (on error C, otherwise C,
e.g. the number of modified rows) and - in an array context -
the statement handle.

Accepts the SQL statement, parameters for binding in an array
reference and optionally a boolean value, if the prepared
statement should be cached by L.


=head1 RETRIEVAL OPTIONS

When retrieving data using L