File Coverage

blib/lib/DBIx/Connection/Oracle/SQL.pm
Criterion Covered Total %
statement 15 68 22.0
branch 0 20 0.0
condition 0 12 0.0
subroutine 5 14 35.7
pod 8 8 100.0
total 28 122 22.9


line stmt bran cond sub pod time code
1             package DBIx::Connection::Oracle::SQL;
2              
3 1     1   4908 use strict;
  1         4  
  1         42  
4 1     1   5 use warnings;
  1         2  
  1         37  
5 1     1   6 use vars qw($VERSION $LOB_MAX_SIZE);
  1         2  
  1         63  
6              
7 1     1   6 use Abstract::Meta::Class ':all';
  1         2  
  1         247  
8 1     1   5 use Carp 'confess';
  1         2  
  1         1016  
9              
10             $VERSION = 0.04;
11             $LOB_MAX_SIZE = (1024 * 1024 * 1024);
12              
13             =head1 NAME
14              
15             DBIx::Connection::Oracle::SQL - Oracle catalog sql abstractaction layer.
16              
17             =cut
18              
19             =head1 SYNOPSIS
20            
21             use DBIx::Connection::Oracle::SQL;
22              
23              
24             =head1 DESCRIPTION
25              
26             Represents sql abstract layer
27              
28             =head1 EXPORT
29              
30             None
31              
32             =head2 METHODS
33              
34             =over
35              
36             =item sequence_value
37              
38             Returns sql statement that returns next sequence value
39              
40             =cut
41              
42             sub sequence_value {
43 0     0 1   my ($class, $sequence_name) = @_;
44 0           "SELECT ${sequence_name}.NEXTVAL as val FROM dual"
45             }
46              
47              
48              
49             =item reset_sequence
50              
51             Returns sql statement that restarts sequence.
52              
53             =cut
54              
55             sub reset_sequence {
56 0     0 1   my ($class, $sequence_name, $restart_with, $increment_by) = @_;
57 0   0       $restart_with ||= 1;
58 0   0       $increment_by ||= 1;
59 0           ("DROP SEQUENCE ${sequence_name}", "CREATE SEQUENCE ${sequence_name} START WITH ${restart_with} INCREMENT BY ${increment_by}");
60             }
61              
62              
63             =item has_sequence
64              
65             Returns sql statement that check is sequence exists in database schema
66              
67             =cut
68              
69             sub has_sequence {
70 0     0 1   my ($class) = @_;
71 0           "SELECT sequence_name FROM user_sequences WHERE sequence_name = UPPER(?)"
72             }
73              
74              
75             =item has_table
76              
77             Returns sql statement that check is table exists in database schema
78              
79             =cut
80              
81             sub has_table {
82 0     0 1   my ($class, $connection, $table_name) = @_;
83 0           my $result;
84 0           my $sql = "SELECT table_name FROM user_tables WHERE table_name = UPPER(?)";
85 0           my $record = $connection->record($sql, $table_name);
86 0 0         $result = [undef,$connection->name, $record->{table_name}, undef]
87             if $record->{table_name};
88 0           $result
89             }
90              
91              
92             =item primary_key_info
93              
94             =cut
95              
96             sub primary_key_info {
97 0     0 1   my ($class, $schema) = @_;
98 0 0         $schema
99             ? "SELECT LOWER(cl.column_name) AS column_name, cs.constraint_name AS pk_name, LOWER(cs.table_name) AS table_name FROM all_cons_columns cl
100             JOIN all_constraints cs
101             ON (cl.owner = cs. owner AND cl.constraint_name = cs. constraint_name AND constraint_type='P'
102             AND cs.table_name = UPPER(?) AND cs.owner = UPPER(?))
103             ORDER BY position"
104             : "SELECT LOWER(cl.column_name) AS column_name, cs.constraint_name, LOWER(cs.table_name) AS table_name FROM user_cons_columns cl
105             JOIN user_constraints cs
106             ON (cl.constraint_name = cs. constraint_name AND constraint_type='P' AND cs.table_name = UPPER(?))
107             ORDER BY position";
108             }
109              
110              
111             =item set_session_variables
112              
113             Sets session variables.
114             It uses the following sql command pattern,
115              
116             alter session set variable = value;
117              
118             DBIx::Connection::Oracle::Session->initialise_session($connection, {NLS_DATE_FORMAT => 'DD.MM.YYYY'});
119              
120             =cut
121              
122             sub set_session_variables {
123 0     0 1   my ($class, $connection, $db_session_variables) = @_;
124 0           my $plsql = "BEGIN\n";
125             $plsql .= "execute immediate 'alter session set " . $_ . "=''" . $db_session_variables->{$_} . "''';\n"
126 0           for keys %$db_session_variables;
127 0           $plsql .= "END;";
128 0           $connection->do($plsql);
129             }
130              
131              
132             =item update_lob
133              
134             Updates lob. (Large Object)
135             Takes connection object, table name, lob column_name, lob conetent, hash_ref to primary key values. optionally lob size column name.
136              
137             =cut
138              
139             sub update_lob {
140 0     0 1   my ($class, $connection, $table_name, $lob_column_name, $lob, $primary_key_values, $lob_size_column_name) = @_;
141 0 0 0       confess "missing primary key for lob update on ${table_name}.${lob_column_name}"
142             if (!$primary_key_values || ! (%$primary_key_values));
143              
144 0           my $sql = "UPDATE ${table_name} SET ${lob_column_name} = ? ";
145 0 0         $sql .= ($lob_size_column_name ? ", ${lob_size_column_name} = ? " : '')
146             . $connection->_where_clause($primary_key_values);
147 0           my $clas = 'DBD::Oracle';
148 0 0         my $ora_type = $clas->can('SQLT_BIN') ? $class->SQLT_BIN : $clas->ORA_BLOB;
149 0           my $bind_counter = 1;
150 0           my $sth = $connection->dbh->prepare($sql);
151 0           $sth->bind_param($bind_counter++ ,$lob, { ora_type => $ora_type});
152 0 0 0       $sth->bind_param($bind_counter++ , length($lob || '')) if $lob_size_column_name;
153 0           for my $k (sort keys %$primary_key_values) {
154 0           $sth->bind_param($bind_counter++ , $primary_key_values->{$k});
155             }
156 0           $sth->execute();
157             }
158              
159              
160             =item fetch_lob
161              
162             Retrieves lob.
163             Takes connection object, table name, lob column_name, hash_ref to primary key values. optionally lob size column name.
164             By default max lob size is set to 1 GB
165             DBIx::Connection::Oracle::SQL::LOB_MAX_SIZE = (1024 * 1024 * 1024);
166              
167             =cut
168              
169             {
170             my %long_read_cache;
171              
172             sub fetch_lob {
173 0     0 1   my ($class, $connection, $table_name, $lob_column_name, $primary_key_values, $lob_size_column_name) = @_;
174 0 0 0       confess "missing primary key for lob update on ${table_name}.${lob_column_name}"
175             if (! $primary_key_values || ! (%$primary_key_values));
176            
177 0           my $dbh = $connection->dbh;
178             # a bit hacky but it looks like DBD::Oracle 1.20 caches first call with LongReadLen
179             # and doesn't allow updates for greater size then the initial LongReadLen read
180             # so physicaly 1GB on lob limitiation to declared here variable $LOB_SIZE = (1024 * 1024 * 1024);
181             # another working solution is to reconnection - to expensive thuogh
182            
183 0 0         if (! exists($long_read_cache{"_" . $dbh})){
184 0           $dbh->{LongReadLen} = $LOB_MAX_SIZE;
185 0           $long_read_cache{"_" . $dbh} = 1;
186            
187             } else {
188 0           $dbh->{LongReadLen} = $class->_get_lob_size($connection, $table_name, $primary_key_values, $lob_size_column_name);
189             }
190            
191 0           my $sql = "SELECT ${lob_column_name} as lob_content FROM ${table_name} " . $connection->_where_clause($primary_key_values);
192 0           my $record = $connection->record($sql, map { $primary_key_values->{$_}} sort keys %$primary_key_values);
  0            
193 0           $record->{lob_content};
194             }
195             }
196              
197              
198             =item _get_lob_size
199              
200             Returns lob size.
201              
202             =cut
203              
204             sub _get_lob_size {
205 0     0     my ($class, $connection, $table_name, $primary_key_values, $lob_size_column_name) = @_;
206 0           my $resut;
207 0 0         if($lob_size_column_name) {
208 0           my $sql = "SELECT ${lob_size_column_name} as lob_size FROM ${table_name} " . $connection->_where_clause($primary_key_values);
209 0           my ($record) = $connection->record($sql, map { $primary_key_values->{$_}} sort keys %$primary_key_values);
  0            
210 0           $resut = $record->{lob_size};
211             }
212 0 0         $resut || $LOB_MAX_SIZE;
213             }
214              
215             1;
216              
217             __END__