Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Data-ObjectDriver CPAN distribution.

Report information
The Basics
Id: 41929
Status: resolved
Priority: 0/
Queue: Data-ObjectDriver

People
Owner: yann.kerherve [...] gmail.com
Requestors: xiaoou.wu [...] oracle.com
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: (no value)
Fixed in: (no value)



Subject: Oracle Driver for Data-ObjectDriver
Hi, We are developing a job queue using TheSchwartz, which requires Data- ObjectDriver. But our backend database is Oracle, and I find there is no Oracle driver for Data-ObjectDriver now. Attached is my version of Oracle Driver :-) -- Xiaoou
Subject: v1.diff
--- /dev/null 2008-12-24 00:39:55.772008657 +0800 +++ lib/Data/ObjectDriver/Driver/DBD/Oracle.pm 2008-12-25 08:23:33.000000000 +0800 @@ -0,0 +1,110 @@ +# $Id$ +# Contributor(s): Xiaoou Wu <xiaoou.wu@oracle.com> +# +=head1 NAME + +Data::ObjectDriver::Driver::DBD::Oracle - Oracle Driver for Data::ObjectDriver + +=head1 DESCRIPTION + +This module overrides methods of the Data::ObjectDriver::Driver::DBD module +with Oracle specific implementation. + +=cut + +package Data::ObjectDriver::Driver::DBD::Oracle; + +use strict; + +use base qw( Data::ObjectDriver::Driver::DBD ); + +use Data::ObjectDriver::SQL::Oracle; +use DBD::Oracle qw(:ora_types); + +sub init_dbh { + my $dbd = shift; + my ($dbh) = @_; + $dbh->{LongReadLen} = 1024000; + $dbh->{FetchHashKeyName} = 'NAME_lc'; + return bless $dbh, 'Data::ObjectDriver::Driver::DBD::Oracle::db'; +} + +sub bind_param_attributes { + my ($dbd, $data_type) = @_; + if ($data_type && $data_type eq 'blob') { + return { ora_type => ORA_BLOB }; + } + return; +} + +## Oracle doesn't support auto-increment, it needs a SEQUENCE to emulate +## this feature. +sub fetch_id { + my $dbd = shift; + my ($class, $dbh, $sth, $driver) = @_; + my $seq = $dbd->sequence_name($class, $driver); + my ($last_insert_id) = $dbh->selectrow_array("SELECT $seq.CURRVAL " + . " FROM DUAL"); + return $last_insert_id; +} + +sub sequence_name { + my $dbd = shift; + my ($class, $driver) = @_; + my $datasource = $class ->datasource; + my $prefix = $driver->prefix; + $datasource = join('', $prefix, $datasource) if $prefix; + join '_', $datasource, + $dbd->db_column_name($class->datasource, + $class->properties->{primary_key}), + 'seq'; +} + +sub bulk_insert { + my $dbd = shift; + my $dbh = shift; + my $table = shift; + my $cols = shift; + my $rows_ref = shift; + + my $sql = "INSERT INTO $table(" + . join(',', @{$cols}) + . ") VALUES (" + . join(',', map {'?'} @{$cols}) + . ")"; + my $sth = $dbh->prepare($sql); + foreach my $row (@{$rows_ref}) { + $sth->execute(@{$row}); + } + return 1; +} + +## +sub sql_class { 'Data::ObjectDriver::SQL::Oracle' } + +package Data::ObjectDriver::Driver::DBD::Oracle::db; + +use strict; + +## Inherit the DB class from DBI::db. +use base qw(DBI::db); + +## Oracle doesn't allow a SELECT statement without FROM. +sub _adjust_stmt { + my $stmt = shift; + my $has_select = ($stmt =~ m/^\s*SELECT\b/io); + my $has_from = ($stmt =~ m/\bFROM\b/io); + $stmt .= " FROM DUAL" if ($has_select and !$has_from); + return $stmt; +} + +sub selectrow_array { + my $self = shift; + my $stmt = shift; + $stmt = _adjust_stmt($stmt); + unshift @_, $stmt; + $self->SUPER::selectrow_array(@_); +} + +1; + --- /dev/null 2008-12-24 00:39:55.772008657 +0800 +++ lib/Data/ObjectDriver/SQL/Oracle.pm 2008-12-25 08:17:21.000000000 +0800 @@ -0,0 +1,39 @@ +# $Id$ +# Contributor(s): Xiaoou Wu <xiaoou.wu@oracle.com> +# + +package Data::ObjectDriver::SQL::Oracle; + +use strict; +use base qw(Data::ObjectDriver::SQL); + +## Oracle doesn't have the LIMIT clause. +sub as_limit { + return; +} + +## Override as_sql to emulate the LIMIT clause. +sub as_sql { + my $stmt = shift; + my $limit = $stmt->limit; + my $offset = $stmt->offset; + + if (defined $limit && defined $offset){ + my @fields = $stmt->select; + push(@fields, "ROW_NUMBER() OVER (ORDER BY 1) R"); + } + + my $sql = $stmt->SUPER::as_sql(@_); + + if (defined $limit){ + $sql = "SELECT * FROM ( $sql ) WHERE "; + if(defined $offset){ + $sql = $sql . " R BETWEEN $offset + 1 AND $limit + $offset"; + } else { + $sql = $sql . " rownum <= $limit"; + } + } + return $sql; +} + +1;
RT-Send-CC: data-objectdriver [...] googlegroups.com
Hi, Thanks for the patch. Could you please send copyright and license statement along with your patch? Yann
Attached is with copyright and license statement. Thanks, Xiaoou
--- /dev/null 2008-12-24 00:39:55.772008657 +0800 +++ lib/Data/ObjectDriver/Driver/DBD/Oracle.pm 2009-01-07 19:35:44.000000000 +0800 @@ -0,0 +1,157 @@ +# $Id$ +# Contributor(s): Xiaoou Wu <xiaoou.wu@oracle.com> +# +package Data::ObjectDriver::Driver::DBD::Oracle; + +use strict; + +use base qw( Data::ObjectDriver::Driver::DBD ); + +use Data::ObjectDriver::SQL::Oracle; +use DBD::Oracle qw(:ora_types); + +sub init_dbh { + my $dbd = shift; + my ($dbh) = @_; + $dbh->{LongReadLen} = 1024000; + $dbh->{FetchHashKeyName} = 'NAME_lc'; + return bless $dbh, 'Data::ObjectDriver::Driver::DBD::Oracle::db'; +} + +sub bind_param_attributes { + my ($dbd, $data_type) = @_; + if ($data_type && $data_type eq 'blob') { + return { ora_type => ORA_BLOB }; + } + return; +} + + +sub map_error_code { + my $dbd = shift; + my($code, $msg) = @_; + if ($msg && $msg =~ /ORA-00001/i) { + return Data::ObjectDriver::Errors->UNIQUE_CONSTRAINT; + } else { + return; + } +} + +## Oracle doesn't support auto-increment, it needs a SEQUENCE to emulate +## this feature. For usage, please see NOTES. +sub fetch_id { + my $dbd = shift; + my ($class, $dbh, $sth, $driver) = @_; + my $seq = $dbd->sequence_name($class, $driver); + my ($last_insert_id) = $dbh->selectrow_array("SELECT $seq.CURRVAL " + . " FROM DUAL"); + return $last_insert_id; +} + +sub sequence_name { + my $dbd = shift; + my ($class, $driver) = @_; + my $datasource = $class ->datasource; + my $prefix = $driver->prefix; + $datasource = join('', $prefix, $datasource) if $prefix; + join '_', $datasource, + $dbd->db_column_name($class->datasource, + $class->properties->{primary_key}), + 'seq'; +} + +sub bulk_insert { + my $dbd = shift; + my $dbh = shift; + my $table = shift; + my $cols = shift; + my $rows_ref = shift; + + my $sql = "INSERT INTO $table(" + . join(',', @{$cols}) + . ") VALUES (" + . join(',', map {'?'} @{$cols}) + . ")"; + my $sth = $dbh->prepare($sql); + foreach my $row (@{$rows_ref}) { + $sth->execute(@{$row}); + } + return 1; +} + +## +sub sql_class { 'Data::ObjectDriver::SQL::Oracle' } + +package Data::ObjectDriver::Driver::DBD::Oracle::db; + +use strict; + +## Inherit the DB class from DBI::db. +use base qw(DBI::db); + +## Oracle doesn't allow a SELECT statement without FROM. +sub _adjust_stmt { + my $stmt = shift; + my $has_select = ($stmt =~ m/^\s*SELECT\b/io); + my $has_from = ($stmt =~ m/\bFROM\b/io); + $stmt .= " FROM DUAL" if ($has_select and !$has_from); + return $stmt; +} + +sub selectrow_array { + my $self = shift; + my $stmt = shift; + $stmt = _adjust_stmt($stmt); + unshift @_, $stmt; + $self->SUPER::selectrow_array(@_); +} + +1; + +__END__ + +=head1 NAME + +Data::ObjectDriver::Driver::DBD::Oracle - Oracle Driver for Data::ObjectDriver + +=head1 DESCRIPTION + +This module overrides methods of the Data::ObjectDriver::Driver::DBD module +with Oracle specific implementation. + +=head1 NOTES + +Oracle doesn't support auto-increment, so before you use this feature, you +should create a sequence and a trigger to work with it. + +For example, you want field ID in table WINES be auto-increment, then create: + + -- Create sequence + CREATE SEQUENCE WINES_ID_SEQ + MINVALUE 1 + MAXVALUE 999999999999999999999999999 + START WITH 1 + INCREMENT BY 1 + NOCACHE; + + -- Create trigger + CREATE OR REPLACE TRIGGER WINES_ID_TR + BEFORE INSERT ON WINES + FOR EACH ROW + BEGIN + SELECT WINES_ID_SEQ.NEXTVAL INTO :NEW.ID FROM DUAL; + END; + +=head1 LICENSE + +This module is free software; +you may redistribute and/or modify it under the same +terms as Perl itself. + +=head1 AUTHOR & COPYRIGHT + +This module is +copyright (c) 2009 Xiaoou Wu E<lt>xiaoou.wu@oracle.comE<gt>. +All rights reserved. + +=cut --- /dev/null 2008-12-24 00:39:55.772008657 +0800 +++ lib/Data/ObjectDriver/SQL/Oracle.pm 2009-01-07 19:37:45.000000000 +0800 @@ -0,0 +1,63 @@ +# $Id$ +# Contributor(s): Xiaoou Wu <xiaoou.wu@oracle.com> +# +package Data::ObjectDriver::SQL::Oracle; + +use strict; +use base qw(Data::ObjectDriver::SQL); + +## Oracle doesn't have the LIMIT clause. +sub as_limit { + return; +} + +## Override as_sql to emulate the LIMIT clause. +sub as_sql { + my $stmt = shift; + my $limit = $stmt->limit; + my $offset = $stmt->offset; + + if (defined $limit && defined $offset){ + my @fields = $stmt->select; + push(@fields, "ROW_NUMBER() OVER (ORDER BY 1) R"); + } + + my $sql = $stmt->SUPER::as_sql(@_); + + if (defined $limit){ + $sql = "SELECT * FROM ( $sql ) WHERE "; + if(defined $offset){ + $sql = $sql . " R BETWEEN $offset + 1 AND $limit + $offset"; + } else { + $sql = $sql . " rownum <= $limit"; + } + } + return $sql; +} + +1; + +__END__ + +=head1 NAME + +Data::ObjectDriver::SQL::Oracle + +=head1 DESCRIPTION + +This module overrides methods of the Data::ObjectDriver::SQL module +with Oracle specific implementation. + +=head1 LICENSE + +This module is free software; +you may redistribute and/or modify it under the same +terms as Perl itself. + +=head1 AUTHOR & COPYRIGHT + +This module is +copyright (c) 2009 Xiaoou Wu E<lt>xiaoou.wu@oracle.comE<gt>. +All rights reserved. + +=cut
Hi, I've integrated your patch with a few minor formatting changes, it would be appreciated if you could test that the version out of the trunk works for you since I don't have an easy way to test against an Oracle database. Thanks Yann
Fixed in 0.06