File Coverage

blib/lib/DBIx/ProcedureCall/Oracle.pm
Criterion Covered Total %
statement 9 125 7.2
branch 0 50 0.0
condition 0 18 0.0
subroutine 3 8 37.5
pod n/a
total 12 201 5.9


line stmt bran cond sub pod time code
1             package DBIx::ProcedureCall::Oracle;
2              
3 2     2   56915 use strict;
  2         6  
  2         103  
4 2     2   12 use warnings;
  2         5  
  2         67  
5              
6 2     2   12 use Carp qw(croak);
  2         6  
  2         3664  
7              
8             our $VERSION = '0.10';
9              
10             our $ORA22905;
11              
12             sub __run_procedure{
13 0     0     shift;
14 0           my $dbh = shift;
15 0           my $name = shift;
16 0           my $attr = shift;
17 0           my $params;
18              
19             # if there is one more arg and it is a hashref, then we use named parameters
20 0 0 0       if (@_ == 1 and ref $_[0] eq 'HASH') {
21 0           return __run_procedure_named($dbh, $name, $attr, $_[0]);
22             }
23             # otherwise they are positional parameters
24 0           my $sql = "begin $name";
25 0 0         if (@_){
26 0           $sql .= '(' . join (',' , map ({ '?'} @_ )) . ')';
  0            
27             }
28 0           $sql .= '; end;';
29             # print $sql;
30             # prepare
31 0 0         $sql = $attr->{cached} ? $dbh->prepare_cached($sql)
32             : $dbh->prepare($sql);
33             # bind
34 0           DBIx::ProcedureCall::__bind_params($sql, 1, \@_);
35             # execute
36 0           $sql->execute;
37             }
38              
39             sub __run_procedure_named{
40 0     0     my ($dbh, $name, $attr, $params) = @_;
41 0           my $sql = "begin $name";
42 0           my @p = sort keys %$params;
43 0 0         if (@p){
44 0           @p = map { "$_ => :$_" } @p;
  0            
45 0           $sql .= '(' . join (',', @p) . ')';
46             }
47 0           $sql .= '; end;';
48             # print $sql;
49             # prepare
50 0 0         $sql = $attr->{cached} ? $dbh->prepare_cached($sql)
51             : $dbh->prepare($sql);
52             # bind
53 0           DBIx::ProcedureCall::__bind_params($sql, undef, $params);
54             # execute
55 0           $sql->execute;
56             }
57              
58             sub __run_function{
59 0     0     shift;
60 0           my $dbh = shift;
61 0           my $name = shift;
62 0           my $attr = shift;
63 0           my $params;
64            
65             # any fetch implies cursor (unless it is a table function)
66 0 0 0       if ( $attr->{'fetch'} and not $attr->{'table'} ) {
67 0           $attr->{'cursor'} = 1;
68             }
69             # if there is one more arg and it is a hashref , then we use with named parameters
70 0 0 0       if (@_ == 1 and ref $_[0] eq 'HASH') {
71 0           return __run_function_named($dbh, $name, $attr, $_[0]);
72             }
73             # otherwise they are positional parameters
74            
75             # table functions
76 0 0         if ($attr->{table}){
77             # workaround for pre-9.2.0.5.0
78 0 0 0       if (@_ and $ORA22905){
79 0           my $sql = "select * from table( $name (";
80 0           $sql .= join ',', map{$dbh->quote($_) } @_ ;
  0            
81 0           $sql .= '))';
82             # prepare
83 0           $sql = $dbh->prepare($sql);
84             # execute
85 0           $sql->execute;
86 0           return $sql;
87             }
88 0           my $sql = "select * from table( $name";
89 0 0         if (@_){
90 0           $sql .= '(' . join (',' , map ({ '?'} @_ )) . ')';
  0            
91             }
92 0           $sql .= ')';
93 0           eval{
94             # prepare
95 0 0         $sql = $attr->{cached} ? $dbh->prepare_cached($sql)
96             : $dbh->prepare($sql);
97             };
98             # error: if 22905 turn on workaround and try again
99 0 0 0       if ($@ and $dbh->err == 22905 and not defined $ORA22905){
      0        
100 0           $ORA22905 = 1;
101 0           return __run_function(__PACKAGE__, $dbh, $name, $attr, @_);
102             }
103             # bind
104 0           DBIx::ProcedureCall::__bind_params($sql, 1, \@_);
105             # execute
106 0           $sql->execute;
107 0           return $sql ;
108             }
109            
110 0           my $sql;
111            
112             # boolean function needs a conversion wrapper
113 0 0         if ($attr->{boolean}){
114 0           $sql = 'declare perl_oracle_procedures_b0 boolean; perl_oracle_procedures_n0 number; ';
115 0           $sql .= "begin perl_oracle_procedures_b0 := $name";
116 0 0         if (@_){
117 0           $sql .= '(' . join (',' , map ({ '?'} @_ )) . ')';
  0            
118             }
119 0           $sql .= '; if perl_oracle_procedures_b0 is null then perl_oracle_procedures_n0 := null;elsif perl_oracle_procedures_b0 then perl_oracle_procedures_n0 := 1;else perl_oracle_procedures_n0 := 0;end if; ? := perl_oracle_procedures_n0;end;';
120             }
121             else{
122 0           $sql = "begin ? := $name";
123 0 0         if (@_){
124 0           $sql .= '(' . join (',' , map ({ '?'} @_ )) . ')';
  0            
125             }
126 0           $sql .= '; end;';
127             }
128             # prepare
129 0 0         $sql = $attr->{cached} ? $dbh->prepare_cached($sql)
130             : $dbh->prepare($sql);
131            
132             # bind
133 0           my $i = 1;
134             # boolean conversion wrapper requires the out value to be bound LAST
135 0 0         if ($attr->{boolean}){
136 0           DBIx::ProcedureCall::__bind_params($sql, $i, \@_);
137 0           $i += @_;
138             }
139 0           my $r;
140            
141 0 0         if ($attr->{cursor}){
142 0           $sql->bind_param_inout($i++, \$r, 0, {ora_type => DBD::Oracle::ORA_RSET()});
143             }else{
144 0           $sql->bind_param_inout($i++, \$r, 100);
145             }
146            
147 0 0         unless ($attr->{boolean}){
148 0           DBIx::ProcedureCall::__bind_params($sql, $i, \@_);
149             }
150            
151             #execute
152 0           $sql->execute;
153 0           return $r;
154             }
155              
156             sub __run_function_named{
157 0     0     my ($dbh, $name, $attr, $params) = @_;
158             # table functions
159 0 0         if ($attr->{table}){
160 0           croak "cannot execute the table function '$name' with named parameters: only positional parameters are supported.";
161             }
162            
163 0           my $sql;
164 0           my @p = sort keys %$params;
165             # boolean function needs a conversion wrapper
166 0 0         if ($attr->{boolean}){
167 0           $sql = 'declare perl_oracle_procedures_b0 boolean; perl_oracle_procedures_n0 number; ';
168 0           $sql .= "begin perl_oracle_procedures_b0 := $name";
169 0 0         if (@p){
170 0           @p = map { "$_ => :$_" } @p;
  0            
171 0           $sql .= '(' . join (',', @p) . ')';
172             }
173 0           $sql .= '; if perl_oracle_procedures_b0 is null then perl_oracle_procedures_n0 := null;elsif perl_oracle_procedures_b0 then perl_oracle_procedures_n0 := 1;else perl_oracle_procedures_n0 := 0; end if; :perl_oracle_procedures_ret := perl_oracle_procedures_n0;end;';
174             }
175             else{
176 0           $sql = "begin :perl_oracle_procedures_ret := $name";
177 0 0         if (@p){
178 0           @p = map { "$_ => :$_" } @p;
  0            
179 0           $sql .= '(' . join (',', @p) . ')';
180             }
181 0           $sql .= '; end;';
182             }
183            
184            
185             # prepare
186 0 0         $sql = $attr->{cached} ? $dbh->prepare_cached($sql)
187             : $dbh->prepare($sql);
188             # bind
189 0           my $r;
190 0 0         if ($attr->{cursor}){
191 0           $sql->bind_param_inout(':perl_oracle_procedures_ret', \$r, 0, {ora_type => DBD::Oracle::ORA_RSET()});
192             }else{
193 0           $sql->bind_param_inout(':perl_oracle_procedures_ret', \$r, 100);
194             }
195             # bind
196 0           DBIx::ProcedureCall::__bind_params($sql, undef, $params);
197            
198             # execute
199 0           $sql->execute;
200 0           return $r;
201             }
202              
203             sub __close{
204 0     0     shift;
205 0           my $sth = shift;
206 0           my $conn = $sth->{Database};
207 0           my $sql = $conn->prepare('BEGIN close :curref; END;');
208 0           $sql->bind_param(":curref", $sth, {ora_type => DBD::Oracle::ORA_RSET()});
209 0           $sql->execute;
210             }
211              
212              
213              
214             1;
215             __END__