346c52fe3bb96fa37c0fa4d1566ed19ab212e207
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / CDBICompat / ImaDBI.pm
1 package # hide from PAUSE
2     DBIx::Class::CDBICompat::ImaDBI;
3
4 use strict;
5 use warnings;
6 use DBIx::ContextualFetch;
7
8 use base qw/DBIx::Class/;
9
10 __PACKAGE__->mk_classdata('sql_transformer_class' =>
11                           'DBIx::Class::CDBICompat::SQLTransformer');
12
13 __PACKAGE__->mk_classdata('_transform_sql_handler_order'
14                             => [ qw/TABLE ESSENTIAL JOIN IDENTIFIER/ ] );
15
16 __PACKAGE__->mk_classdata('_transform_sql_handlers' =>
17   {
18     'TABLE' =>
19       sub {
20         my ($self, $class, $data) = @_;
21         return $class->result_source_instance->name unless $data;
22         my ($f_class, $alias) = split(/=/, $data);
23         $f_class ||= $class;
24         $self->{_classes}{$alias} = $f_class;
25         return $f_class->result_source_instance->name." ${alias}";
26       },
27     'ESSENTIAL' =>
28       sub {
29         my ($self, $class, $data) = @_;
30         $class = $data ? $self->{_classes}{$data} : $class;
31         return join(', ', $class->columns('Essential'));
32       },
33     'IDENTIFIER' =>
34       sub {
35         my ($self, $class, $data) = @_;
36         $class = $data ? $self->{_classes}{$data} : $class;
37         return join ' AND ', map  "$_ = ?", $class->primary_columns;
38       },
39     'JOIN' =>
40       sub {
41         my ($self, $class, $data) = @_;
42         my ($from, $to) = split(/ /, $data);
43         my ($from_class, $to_class) = @{$self->{_classes}}{$from, $to};
44         my ($rel_obj) = grep { $_->{class} && $_->{class} eq $to_class }
45                           map { $from_class->relationship_info($_) }
46                             $from_class->relationships;
47         unless ($rel_obj) {
48           ($from, $to) = ($to, $from);
49           ($from_class, $to_class) = ($to_class, $from_class);
50           ($rel_obj) = grep { $_->{class} && $_->{class} eq $to_class }
51                           map { $from_class->relationship_info($_) }
52                             $from_class->relationships;
53         }
54         $self->throw_exception( "No relationship to JOIN from ${from_class} to ${to_class}" )
55           unless $rel_obj;
56         my $join = $from_class->storage->sql_maker->_join_condition(
57           $from_class->result_source_instance->resolve_condition(
58             $rel_obj->{cond}, $to, $from) );
59         return $join;
60       }
61         
62   } );
63
64 sub db_Main {
65   return $_[0]->storage->dbh;
66 }
67
68 sub connection {
69   my ($class, @info) = @_;
70   $info[3] = { %{ $info[3] || {}} };
71   $info[3]->{RootClass} = 'DBIx::ContextualFetch';
72   return $class->next::method(@info);
73 }
74
75 sub __driver {
76   return $_[0]->storage->dbh->{Driver}->{Name};
77 }
78
79 sub set_sql {
80   my ($class, $name, $sql) = @_;
81   no strict 'refs';
82   *{"${class}::sql_${name}"} =
83     sub {
84       my $sql = $sql;
85       my $class = shift;
86       return $class->storage->sth($class->transform_sql($sql, @_));
87     };
88   if ($sql =~ /select/i) {
89     my $meth = "sql_${name}";
90     *{"${class}::search_${name}"} =
91       sub {
92         my ($class, @args) = @_;
93         my $sth = $class->$meth;
94         return $class->sth_to_objects($sth, \@args);
95       };
96   }
97 }
98
99 sub sth_to_objects {
100   my ($class, $sth, $execute_args) = @_;
101
102   $sth->execute(@$execute_args);
103
104   my @ret;
105   while (my $row = $sth->fetchrow_hashref) {
106     push(@ret, $class->inflate_result($class->result_source_instance, $row));
107   }
108
109   return @ret;
110 }
111
112 sub transform_sql {
113   my ($class, $sql, @args) = @_;
114   
115   my $tclass = $class->sql_transformer_class;
116   $class->ensure_class_loaded($tclass);
117   my $t = $tclass->new($class, $sql, @args);
118
119   return sprintf($t->sql, $t->args);
120 }
121
122 package
123   DBIx::ContextualFetch::st; # HIDE FROM PAUSE THIS IS NOT OUR CLASS
124
125 no warnings 'redefine';
126
127 sub _untaint_execute {
128   my $sth = shift;
129   my $old_value = $sth->{Taint};
130   $sth->{Taint} = 0;
131   my $ret;
132   {
133     no warnings 'uninitialized';
134     $ret = $sth->SUPER::execute(@_);
135   }
136   $sth->{Taint} = $old_value;
137   return $ret;
138 }
139
140 1;