NAME

Teng - very simple DBI wrapper/ORMapper

SYNOPSIS

my $db = MyDB->new({ connect_info => [ 'dbi:SQLite:' ] });
my $row = $db->insert( 'table' => {
    col1 => $value
} );

DESCRIPTION

Teng is very simple DBI wrapper and simple O/R Mapper. It aims to be lightweight, with minimal dependencies so it's easier to install.

THE SOFTWARE IS IT'S IN ALPHA QUALITY. IT MAY CHANGE THE API WITHOUT NOTICE.

BASIC USAGE

create your db model base class.

package Your::Model;
use parent 'Teng';
1;

create your db schema class. See Teng::Schema for docs on defining schema class.

package Your::Model::Schema;
use Teng::Schema::Declare;
table {
    name 'user';
    pk 'id';
    columns qw( foo bar baz );
};
1;

in your script.

use Your::Model;

my $teng = Your::Model->new(\%args);
# insert new record.
my $row = $teng->insert('user',
    {
        id   => 1,
    }
);
$row->update({name => 'nekokak'});

$row = $teng->search_by_sql(q{SELECT id, name FROM user WHERE id = ?}, [ 1 ]);
$row->delete();

ARCHITECTURE

Teng classes are comprised of three distinct components:

MODEL

The model is where you say

package MyApp::Model;
use parent 'Teng';

This is the entry point to using Teng. You connect, insert, update, delete, select stuff using this object.

SCHEMA

The schema is a simple class that describes your table definitions. Note that this is different from DBIx::Class terms. DBIC's schema is equivalent to Teng's model + schema, where the actual schema information is scattered across the result classes.

In Teng, you simply use Teng::Schema's domain specific languaage to define a set of tables

package MyApp::Model::Schema;
use Teng::Schema::Declare;

table {
    name $table_name;
    pk $primary_key_column;
    columns qw(
        column1
        column2
        column3
    );
}

... and other tables ...

ROW

Unlike DBIx::Class, you don't need to have a set of classes that represent a row type (i.e. "result" classes in DBIC terms). In Teng, the row objects are blessed into anonymous classes that inherit from Teng::Row, so you don't have to create these classes if you just want to use some simple queries.

If you want to define methods to be performed by your row objects, simply create a row class like so:

package MyApp::Model::Row::Camelizedtable_name;
use parent qw(Teng::Row);

Note that your table name will be camelized.

METHODS

Teng provides a number of methods to all your classes,

$teng = Teng->new(\%args)

Creates a new Teng instance.

# connect new database connection.
my $db = Your::Model->new(
    connect_info => [ $dsn, $username, $password, \%connect_options ]
);

Arguments can be:

  • connect_info

    Specifies the information required to connect to the database. The argument should be a reference to a array in the form:

    [ $dsn, $user, $password, \%options ]

    You must pass connect_info or dbh to the constructor.

  • dbh

    Specifies the database handle to use. If this value is passed without specifying connect_info, then automatic reconnects normally provided by Teng is not performed (however, you are free to create a Teng instance using only dbh if you don't care about such features)

  • schema

    Specifies the Teng::Schema instance to use. If not specified, the value specified in schema_class is loaded and instantiated for you.

  • schema_class

    Specifies the schema class to use. By default {YOUR_MODEL_CLASS}::Schema is used.

  • suppress_row_objects

    Specifies the row object creation mode. By default this value is true. If you specifies this to a false value, no row object will be created when a SELECT statement is issued..

  • sql_builder

    Speficies the SQL builder object. By default SQL::Maker is used, and as such, if you provide your own SQL builder the interface needs to be compatible with SQL::Maker.

$row = $teng->insert($table_name, \%row_data)

Inserts a new record. Returns the inserted row object.

my $row = $teng->insert('user',{
    id   => 1,
    name => 'nekokak',
});

If a primary key is available, it will be fetched after the insert -- so an INSERT followed by SELECT is performed. If you do not want this, use fast_insert.

$last_insert_id = $teng->fast_insert($table_name, \%row_data);

insert new record and get last_insert_id.

no creation row object.

$update_row_count = $teng->update($table_name, \%update_row_data, [\%update_condition])

Calls UPDATE on $table_name, with values specified in %update_ro_data, and returns the number of rows updated. You may optionally specify %update_condition to create a conditional update query.

my $update_row_count = $teng->update('user',
    {
        name => 'nomaneko',
    },
    {
        id => 1
    }
);
# Executes UPDATE user SET name = 'nomaneko' WHERE id = 1

You can also call update on a row object:

my $row = $teng->single('user',{id => 1});
$row->update({name => 'nomaneko'});
$delete_row_count = $teng->delete($table, \%delete_condition)

Deletes the specified record(s) from $table and returns the number of rows deleted. You may optionally specify %delete_condition to create a conditional delete query.

my $rows_deleted = $teng->delete( 'user', {
    id => 1
} );
# Executes DELETE FROM user WHERE id = 1

You can also call delete on a row object:

my $row = $teng->single('user', {id => 1});
$row->delete
$itr = $teng->search($table_name, [\%search_condition, [\%search_attr]])

simple search method. search method get Teng::Iterator's instance object.

see Teng::Iterator

get iterator:

my $itr = $teng->search('user',{id => 1},{order_by => 'id'});

get rows:

my @rows = $teng->search('user',{id => 1},{order_by => 'id'});
$row = $teng->single($table_name, \%search_condition)

get one record. give back one case of the beginning when it is acquired plural records by single method.

my $row = $teng->single('user',{id =>1});
$itr = $teng->search_named($sql, [\%bind_values, [$table_name]])

execute named query

my $itr = $teng->search_named(q{SELECT * FROM user WHERE id = :id}, {id => 1});

If you give ArrayRef to value, that is expanded to "(?,?,?,?)" in SQL. It's useful in case use IN statement.

# SELECT * FROM user WHERE id IN (?,?,?);
# bind [1,2,3]
my $itr = $teng->search_named(q{SELECT * FROM user WHERE id IN :ids}, {id => [1, 2, 3]});

If you give table_name. It is assumed the hint that makes Teng::Row's Object.

$itr = $teng->search_by_sql($sql, [\@bind_vlues, [$table_name]])

execute your SQL

my $itr = $teng->search_by_sql(q{
    SELECT
        id, name
    FROM
        user
    WHERE
        id = ?
},[ 1 ]);

If $table is specified, it set table infomation to result iterator. So, you can use table row class to search_by_sql result.

$teng->txn_scope

Creates a new transaction scope guard object.

do {
    my $txn = $teng->txn_scope;

    $row->update({foo => 'bar'});

    $txn->commit;
}

If an exception occurs, or the guard object otherwise leaves the scope before $txn->commit is called, the transaction will be rolled back by an explicit "txn_rollback" call. In essence this is akin to using a "txn_begin"/"txn_commit" pair, without having to worry about calling "txn_rollback" at the right places. Note that since there is no defined code closure, there will be no retries and other magic upon database disconnection.

$txn_manager = $teng->txn_manager

Get the DBIx::TransactionManager instance.

$teng->txn_begin

start new transaction.

$teng->txn_commit

commit transaction.

$teng->txn_rollback

rollback transaction.

$teng->txn_end

finish transaction.

$teng->do($sql, [\%option, \@bind_values])

Execute the query specified by $sql, using %option and @bind_values as necessary. This pretty much a wrapper around http://search.cpan.org/dist/DBI/DBI.pm#do

$teng->dbh

get database handle.

$teng->connect(\@connect_info)

connect database handle.

connect_info is [$dsn, $user, $password, $options].

If you give \@connect_info, create new database connection.

$teng->disconnect()

Disconnects from the currently connected database.

$teng->suppress_row_objects($flag)

set row object creation mode.

$teng->load_plugin();

load Teng::Plugin's

$teng->handle_error

handling error method.

How do you use display the profiling result?

use Devel::KYTProf.

TRIGGERS

Teng does not support triggers (NOTE: do not confuse it with SQL triggers - we're talking about Perl level triggers). If you really want to hook into the various methods, use something like Moose, Mouse, and Class::Method::Modifiers.

SEE ALSO

Fork

This module was forked from DBIx::Skinny, around version 0.0732. many incompatible changes have been made.

BUGS AND LIMITATIONS

No bugs have been reported.

AUTHORS

Atsushi Kobayashi <nekokak __at__ gmail.com>

Tokuhiro Matsuno <tokuhirom@gmail.com>

Daisuke Maki <daisuke@endeworks.jp>

SUPPORT

irc: #dbix-skinny@irc.perl.org

ML: http://groups.google.com/group/dbix-skinny

REPOSITORY

git clone git://github.com/nekokak/p5-teng.git  

LICENCE AND COPYRIGHT

Copyright (c) 2010, the Teng "AUTHOR". All rights reserved.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic.