1package Alzabo::Runtime; 2 3use strict; 4 5use Alzabo; 6 7use Alzabo::Runtime::Column; 8use Alzabo::Runtime::ColumnDefinition; 9use Alzabo::Runtime::ForeignKey; 10use Alzabo::Runtime::Index; 11use Alzabo::Runtime::InsertHandle; 12use Alzabo::Runtime::JoinCursor; 13use Alzabo::Runtime::Row; 14use Alzabo::Runtime::RowCursor; 15use Alzabo::Runtime::Schema; 16use Alzabo::Runtime::Table; 17use Alzabo::Utils; 18 19use vars qw($VERSION); 20 21$VERSION = 2.0; 22 231; 24 25sub import 26{ 27 shift; 28 29 # ignore errors and let them be handled later in the app when it 30 # tries to access the schema. 31 eval { Alzabo::Runtime::Schema->load_from_file( name => $_ ); } foreach @_; 32} 33 34sub sqlmaker 35{ 36 my ($schema, $p) = @_; 37 38 my %sqlmaker_p = ( exists $p->{quote_identifiers} ? 39 ( quote_identifiers => $p->{quote_identifiers} ) : 40 () 41 ); 42 43 return $schema->sqlmaker(%sqlmaker_p); 44} 45 46sub process_where_clause 47{ 48 my ($sql, $where) = @_; 49 50 $where = [ $where ] 51 unless Alzabo::Utils::is_arrayref( $where->[0] ) || $where->[0] eq '('; 52 53 my $has_where = 54 ( $sql->last_op eq 'where' || $sql->last_op eq 'condition' ) ? 1 : 0; 55 56 _process_conditions( $sql, $has_where, $where, 'where' ); 57} 58 59sub process_having_clause 60{ 61 my ($sql, $having) = @_; 62 63 $having = [ $having ] 64 unless Alzabo::Utils::is_arrayref( $having->[0] ) || $having->[0] eq '('; 65 66 my $has_having = 67 ( $sql->last_op eq 'having' || $sql->last_op eq 'condition' ) ? 1 : 0; 68 69 _process_conditions( $sql, $has_having, $having, 'having' ); 70} 71 72sub _process_conditions 73{ 74 my ($sql, $has_start, $conditions, $needed_op) = @_; 75 76 my $needs_op = $sql->last_op eq 'where' || $sql->last_op eq 'having' ? 0 : 1; 77 78 if ($has_start) 79 { 80 # wrap this in parens in order to protect from interactions with 81 # join clauses 82 $sql->and if $needs_op; 83 84 $sql->subgroup_start; 85 86 $needs_op = 0; 87 } 88 89 my $x = 0; 90 foreach my $clause (@$conditions) 91 { 92 if (ref $clause) 93 { 94 Alzabo::Exception::Params->throw 95 ( error => "Individual where clause components must be array references" ) 96 unless Alzabo::Utils::is_arrayref($clause); 97 98 Alzabo::Exception::Params->throw 99 ( error => "Individual where clause components cannot be empty" ) 100 unless @$clause; 101 102 if ($needs_op) 103 { 104 my $op = $x || $has_start ? 'and' : $needed_op; 105 $sql->$op(); 106 } 107 108 $sql->condition(@$clause); 109 $needs_op = 1; 110 } 111 elsif (lc $clause eq 'and' || lc $clause eq 'or') 112 { 113 $sql->$clause(); 114 $needs_op = 0; 115 next; 116 } 117 elsif ($clause eq '(') 118 { 119 if ($needs_op) 120 { 121 my $op = $x || $has_start ? 'and' : $needed_op; 122 $sql->$op(); 123 } 124 $sql->subgroup_start; 125 $needs_op = 0; 126 } 127 elsif ($clause eq ')') 128 { 129 $sql->subgroup_end; 130 $needs_op = 1; 131 } 132 else 133 { 134 Alzabo::Exception::Params->throw( error => "Invalid where clause specification: $clause" ); 135 } 136 $x++; 137 } 138 139 $sql->subgroup_end if $has_start; 140} 141 142sub process_order_by_clause 143{ 144 _process_by_clause(@_, 'order'); 145} 146 147sub process_group_by_clause 148{ 149 _process_by_clause(@_, 'group'); 150} 151 152sub _process_by_clause 153{ 154 my ($sql, $by, $type) = @_; 155 156 my @items; 157 if ( Alzabo::Utils::safe_isa( $by, 'Alzabo::Column' ) || Alzabo::Utils::safe_isa( $by, 'Alzabo::SQLMaker::Function' ) ) 158 { 159 @items = $by; 160 } 161 elsif ( Alzabo::Utils::is_arrayref($by) ) 162 { 163 @items = @$by; 164 } 165 166 my $method = "${type}_by"; 167 $sql->$method(@items); 168} 169 170 171 172__END__ 173 174=head1 NAME 175 176Alzabo::Runtime - Loads all Alzabo::Runtime::* classes 177 178=head1 SYNOPSIS 179 180 use Alzabo::Runtime qw( schema_name ); 181 182=head1 DESCRIPTION 183 184Using this module loads Alzabo::Runtime::* modules. 185 186These modules are what an end user of Alzabo uses to instantiate 187objects representing data in a given schema. 188 189=head1 import METHOD 190 191This method is called when you C<use> this class. You can pass an 192array of strings to the module via the C<use> function. These strings 193are assumed to be the names of schema objects that you want to load. 194This can be useful if you are running under a mod_perl (or similar) 195environment and has the potential to save some memory by preloading 196the objects before a fork, hopefully increasing shared memory. 197 198This method explicitly ignores errors that may occur when trying to 199load a particular schema. This means that later attempts to retrieve 200that schema will probably also fail. This is done so that the 201application that wants a particular schema can explicitly handle the 202failure later on. 203 204=head1 AUTHOR 205 206Dave Rolsky, <autarch@urth.org> 207 208=cut 209