Giter Site home page Giter Site logo

dbix-lite's Introduction

NAME

DBIx::Lite - Chained and minimal ORM

VERSION

version 0.33

SYNOPSIS

use DBIx::Lite;

my $dbix = DBIx::Lite->new;
my $dbix = DBIx::Lite->new(dbh => $dbh);
my $dbix = DBIx::Lite->connect("dbi:Pg:dbname=$db", $user, $passwd, {pg_enable_utf8 => 1});

# build queries using chained methods -- no schema definition required
my $authors_rs = $dbix->table('authors');
my $authors_rs = $dbix->table('authors')->search({ country => 'IT' });
my $books_rs = $dbix
    ->table('books')
    ->select('id', 'title', 'year')
    ->left_join('authors', { author_id => 'id' })
    ->select_also(['authors.name' => 'author_name'])
    ->order_by('year');

# retrieve rows and columns -- still no schema definition required
my @authors = $authors_rs->all;
my $author = $authors_rs->search({ id => 1 })->single;
while (my $book = $books_rs->next) {
    printf "%s (%s)\n", $book->title, $book->author_name;  # automatic accessor methods
}
my @author_names = $authors_rs->get_column('name');
my $book_count = $books_rs->count;

# manipulate rows
my $book = $dbix->table('books')->insert({ name => 'Camel Tales', year => 2012 });
$books_rs->search({ year => { '<' => 1920 } })->update({ very_old => 1 });
$authors_rs->search({ age => { '>' => 99 } })->delete;

# define a primary key and get more features
$dbix->schema->table('authors')->autopk('id');
my $author = $dbix_lite->table('authors')->find(2);
$author->update({ age => 40 });
$author->delete;

# define relationships
$dbix->schema->one_to_many('authors.id' => 'books.author_id', 'author');
my $author = $books->author;
my $books_rs = $author->books->search({ year => 2012 });
my $book = $author->insert_related('books', { title => "A Camel's Life" });

# define custom object classes
$dbix->schema
    ->table('subjects')
    ->class('My::Subject')
    ->resultset_class('My::Subject::ResultSet');

ABSTRACT

Many ORMs and DBI abstraction layers are available on CPAN, one of the most notables being DBIx::Class which provides the most powerful features to handle database contents using OOP.

DBIx::Lite was written with some goals in mind, that no other available module provides. Such goals/key features are:

no need to define your database schema (most features work without one and some advanced features only require some bits, and still not the full table definitions)
no need to connect to database: the module can just generate SQL for you
chained methods with lazy SQL generation
joins/relationships
optional custom classes for results and resultsets with custom methods
SQL::Abstract syntax
paging features (with Data::Page)

METHODS

Instantiating a DBIx::Lite object isn't more difficult than just writing:

my $dbix = DBIx::Lite->new;

This will give you an unconnected object, that you can use to generate SQL commands using the select_sql(), insert_sql(), update_sql() and delete_sql() methods.

If you want to connect to a database you can pass a pre-connected database handle with the dbh argument or you can supply your connection options to the connect() method. All arguments passed to connect() will be just passed to DBIx::Connector which will be used to manage your connection under the hood.

my $dbix = DBIx::Lite->new(dbh => $dbh);
my $dbix = DBIx::Lite->connect("dbi:Pg:dbname=$db", $user, $passwd, {pg_enable_utf8 => 1});

Note that connect() can be called as an object method too, if you want to connect an unconnected DBIx::Lite object at a later stage:

my $dbix = DBIx::Lite->new;
$dbix->connect("dbi:Pg:dbname=$db", $user, $passwd);

new

This class method may accept the following optional arguments:

dbh

This argument allows you to supply a pre-made DBI database handle. See the example in the previous paragraph.

connector

This argument allows you to supply a pre-made DBIx::Connector object.

schema

This argument allows you to supply a pre-made DBIx::Lite::Schema object. If none is provided, a new empty one will be created for each DBIx::Lite object. This argument is useful if you want to prepare your schema in advance and reutilize it across multiple connections.

abstract

This argument allows you to supply options for SQL::Abstract::More module. Here is example for MySQL DB backend to quote fields names with backtick to allow using reserved words as column's names.

my $dbix = DBIx::Lite->new( abstract => { quote_char => '`', name_sep => '.' } );
$dbix->connect("DBI:mysql:$db_dbname;host=$db_host", $db_username, $db_password); 

connect

This methods accepts a list of arguments that are passed to DBIx::Connector. It returns the DBIx::Lite object. It can be called either as class or object method.

table

This method accepts a table name and returns a DBIx::Lite::ResultSet object on which you can chain its methods to build your query.

my $rs = $dbix->table('books');

schema

This method returns our DBIx::Lite::Schema object which may hold the definitions required for some advanced feature of DBIx::Lite. You can call then call its methods:

$dbix->schema->table('authors')->autopk('id');

See the DBIx::Lite::Schema documentation for an explanation of its methods.

dbh

This method returns a DBI database handle that you can use to perform manual queries.

txn

This method accepts a coderef which will be run inside a transaction.

$dbix->txn(sub {
    $dbix->table('books')->update({ year => 2015 });
});

AUTHOR

Alessandro Ranellucci <[email protected]>

COPYRIGHT AND LICENSE

This software is copyright (c) 2021 by Alessandro Ranellucci.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

dbix-lite's People

Contributors

alranel avatar hippich avatar keedi avatar manuelm avatar pla-zbw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

dbix-lite's Issues

pk() method implementation inconsistent with documentation

The pk() method accepts, according to the documentation, multiple primary keys in following format:

->pk('key1', 'key2');

This will result in a rather hard to debug issue since the check against ARRAY in pk() will fail and only the first key will be used. Only by passing a array ref the check will succeed and actually use all of the keys:

->pk(['key1', 'key2']

The following code illustrates this issue:

use DBIx::Lite;
use Data::Dumper;

my $dbix = DBIx::Lite->new;

my $table1 = $dbix->schema->table('dummy1');
$table1->pk('key1', 'key2');
my @keys1 = $table1->pk;
print "pk called with two values: " . Dumper(\@keys1) . "\n";;

my $table2 = $dbix->schema->table('dummy2');
$table2->pk(['key1', 'key2']);
my @keys2 = $table2->pk;
print "pk called with hashref: " . Dumper(\@keys2) . "\n";

unable to use select_sql without a database handle

DBIx::Lite::VERSION = 0.31

I'm trying to generate some SQL without connecting to a database, and I believe something like the following should work:

DBIx::Lite->new->table('foo')->select_sql

However, I'm getting the following error message:

No database handle or DBIx::Connector object provided

Thanks,
Diab

Fails with perls < 5.10

Sample fail report: http://www.cpantesters.org/cpan/report/16e39e1c-0cd6-11e9-9312-ee9892007808

Likely blame (untested): '//' operator

Found in: https://metacpan.org/source/AAR/DBIx-Lite-0.32/lib/DBIx/Lite/ResultSet.pm#L34

    $self->{cur_table} //= $self->{table};

If you want to keep the '//' operator it would be cool if you could predeclare the dependency. That way the FAILS are converted to UNKNOWNS. Details about how to do it are on this page: http://wiki.cpantesters.org/wiki/CPANAuthorNotes

Thanks!

t/sqlite.t started to fail (with newest SQL::Abstract?)

My smoker systems started to report the following failure:

DBD::SQLite::db prepare failed: near "FROM": syntax error at t/sqlite.t line 24.
# Looks like your test exited with 2 before it could output anything.
t/sqlite.t ............... 
Dubious, test returned 2 (wstat 512, 0x200)
Failed 20/20 subtests 

I guess this is caused by changes in SQL::Abstract 2.x (@shadowcat-mst: FYI).

can't update under sqlite database

I tried to use update() method for SQLite DB.
but I failed with following message:

DBD::SQLite::db prepare failed: no such table: books AS me at ...

I think this is due to SQLIte doesn't support AS syntax for UPDATE statement.
unlike other database (MySQL).

http://www.sqlite.org/syntaxdiagrams.html#update-stmt

I edited update_sql() not to use table_alias() then update() method works well.
But I'm not sure this approach is proper for this module or not.

Rows affected information

Hello,

is it possible to get "$rows_affected" after table operations like update or delete with a number of rows affected by the db operation?

Automatic retrieval of primary keys overrides columns of joined tables with same column name

Suppose we are doing the following:

my $rs = $dbix->table('foo')->left_join('bar', { 'bar_id' => 'id' })->select('bar.id');

Also suppose we defined id as primary key for table foo. DBIX::Lite will automatically retrieve that column in order to make $row->update() work. However, that overrides our ->select('bar.id').

When primary keys are automatically added by _select_sth_for_object() they should be aliased with a private name, used as primary key by $row->update().

Disconnected SQL generation does not work

$resultset->select_sql calls $resultset->_table_alias which calls $dbix_lite->driver_name which calls $dbix_lite->dbh without arguments which croaks if the DBIx::Lite does not have a database connection.

Thus, no database handle or connection, no SQL.

There ought to be tests that make sure disconnected SQL generation works.

table name is double quoted when connecting to Postgres, leading to illegal sql

DBIx::Lite::ResultSet outputs illegal syntax for the DELETE command when quote_char is turned on and the connection is to Postgres.

Here's an example:

#! perl

use v5.10;
use DBIx::Lite;

my $dbix = DBIx::Lite->new( abstract => { quote_char => q{"}, name_sep=> q{.} } );
$dbix->connect("dbi:Pg:dbname=$ENV{PGDATABASE};host=$ENV{PGHOST}",q{},q{});

say $dbix->table('foo')->delete_sql;

This outputs:

DELETE FROM """foo"" AS ""me"""

which when fed to Postgres results in

dj=> DELETE FROM """foo"" AS ""me""";
ERROR:  relation ""foo" AS "me"" does not exist
LINE 1: DELETE FROM """foo"" AS ""me""";
                    ^

essentially the q{"foo" as "me"} table alias phrase is being passed as a single string.

This behavior begins in DBIx::Lite::ResultSet::_table_alias_expr where DBIx::Lite::ResultSet::_table_alias is called and returns an alias of "me" for the table, hardwired because of the Pg connection and the delete statement.

It then calls SQL::Abstract::More::table_alias, where it is first quoted (via SQL::Abstract::More::_make_sub_table_alias)
and then again when it calls SQL::Abstract::More::delete, which passes the call on to SQL::Abstract::Classic::delete() where the second quoting happens.

DBIx::Lite::Schema::Table::class is documented as accepting a $inflator argument, but it doesn't

Documentation for DBIx::Lite::Schema::Table::class says:

The "class()" method accepts three more optional arguments:

    $dbix->schema->table('books')->class('My::Book', $constructor, $storage, $inflator);

However, it doesn't actually look for and act on the $inflator argument. Unfortunately this means to get that functionality requires overriding/wrapping the undocumented DBIx::Lite::ResultSet::_inflate_row method.

Smart matching operator not available in 5.8

Hiya,

Just noticed some failed tests on CPAN. I believe it's because you're using a smart matching operating in ResultSet.pm, but this wasn't introduced until 5.10.
I'd probably recommend adding 'use 5.010' to your Makefile.PM so the cpantesters are aware of it.

Cheers!

SELECT DISTINCT available only via hack

$DBIx::Lite::VERSION = 0.31

I'm trying to generate a SELECT DISTINCT statement. The underlying SQL::Abstract::More module uses the following syntax:

-columns  => [-distinct => qw/col1 col2/],

But that doesn't work with DBIx::Lite:

$pg->table( 'arc4gl_keywd' )->select( -distinct => '*' )->select_sql

returns

'SELECT me.-distinct, me.* FROM arc4gl_keywd AS me'

Instead I have to do this:

$pg->table( 'arc4gl_keywd' )->from('arc4gl_keywd')->select( -distinct => '*' )->select_sql;

to get

'SELECT distinct * FROM arc4gl_keywd'

Thanks,
Diab

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.