File: Oracle.pm

package info (click to toggle)
libdata-objectdriver-perl 0.15-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 740 kB
  • ctags: 472
  • sloc: perl: 3,529; sql: 60; makefile: 7
file content (159 lines) | stat: -rw-r--r-- 3,831 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# $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 Data::ObjectDriver::Errors;
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