need to clear converter after setting limit dialect
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / SQLMaker.pm
CommitLineData
d5dedbd6 1package DBIx::Class::SQLMaker;
6f4ddea1 2
a697fa31 3use strict;
4use warnings;
5
d5dedbd6 6=head1 NAME
7
8DBIx::Class::SQLMaker - An SQL::Abstract-based SQL maker class
9
10=head1 DESCRIPTION
11
12This module is a subclass of L<SQL::Abstract> and includes a number of
13DBIC-specific workarounds, not yet suitable for inclusion into the
14L<SQL::Abstract> core. It also provides all (and more than) the functionality
15of L<SQL::Abstract::Limit>, see L<DBIx::Class::SQLMaker::LimitDialects> for
16more info.
17
18Currently the enhancements to L<SQL::Abstract> are:
19
20=over
21
22=item * Support for C<JOIN> statements (via extended C<table/from> support)
23
24=item * Support of functions in C<SELECT> lists
25
26=item * C<GROUP BY>/C<HAVING> support (via extensions to the order_by parameter)
27
28=item * Support of C<...FOR UPDATE> type of select statement modifiers
29
10cef607 30=item * The L</-ident> operator
31
32=item * The L</-value> operator
33
d5dedbd6 34=back
35
36=cut
6a247f33 37
38use base qw/
39 SQL::Abstract
10cef607 40 DBIx::Class::SQLMaker::LimitDialects
6a247f33 41/;
42use mro 'c3';
a697fa31 43
10cef607 44use Module::Runtime qw(use_module);
6298a324 45use Sub::Name 'subname';
70c28808 46use DBIx::Class::Carp;
10cef607 47use DBIx::Class::Exception;
48use Moo;
e8fc51c7 49use namespace::clean;
b2b22cd6 50
10cef607 51has limit_dialect => (
52 is => 'rw', default => sub { 'LimitOffset' },
a0f03f66 53 trigger => sub {
54 $_[0]->clear_renderer_class;
55 $_[0]->clear_converter;
56 }
10cef607 57);
58
7027fcdb 59sub BUILD {
60 if ($_[0]->can('emulate_limit')) {
61 die <<EODIE;
62The ancient and horrible emulate_limit method was deprecated for many moons.
63Now, it is no more. Time to rewrite the code in ${\ref($_[0])}
64EODIE
65 }
66}
67
10cef607 68our %LIMIT_DIALECT_MAP = (
69 'GenericSubQ' => 'GenericSubquery',
10cef607 70);
71
72sub mapped_limit_dialect {
73 my ($self) = @_;
74 my $unmapped = $self->limit_dialect;
75 $LIMIT_DIALECT_MAP{$unmapped}||$unmapped;
76}
77
78around _build_renderer_roles => sub {
79 my ($orig, $self) = (shift, shift);
80 return (
81 $self->$orig(@_),
82 'Data::Query::Renderer::SQL::Slice::'.$self->mapped_limit_dialect
83 );
84};
6a247f33 85
3f5b99fe 86# for when I need a normalized l/r pair
87sub _quote_chars {
88 map
89 { defined $_ ? $_ : '' }
90 ( ref $_[0]->{quote_char} ? (@{$_[0]->{quote_char}}) : ( ($_[0]->{quote_char}) x 2 ) )
91 ;
92}
93
10cef607 94sub _build_converter_class {
95 Module::Runtime::use_module('DBIx::Class::SQLMaker::Converter')
96}
97
70c28808 98# FIXME when we bring in the storage weaklink, check its schema
99# weaklink and channel through $schema->throw_exception
100sub throw_exception { DBIx::Class::Exception->throw($_[1]) }
101
b2b22cd6 102BEGIN {
2ea6032a 103 # reinstall the belch()/puke() functions of SQL::Abstract with custom versions
70c28808 104 # that use DBIx::Class::Carp/DBIx::Class::Exception instead of plain Carp
b2b22cd6 105 no warnings qw/redefine/;
2ea6032a 106
107 *SQL::Abstract::belch = subname 'SQL::Abstract::belch' => sub (@) {
108 my($func) = (caller(1))[3];
109 carp "[$func] Warning: ", @_;
110 };
111
112 *SQL::Abstract::puke = subname 'SQL::Abstract::puke' => sub (@) {
113 my($func) = (caller(1))[3];
70c28808 114 __PACKAGE__->throw_exception("[$func] Fatal: " . join ('', @_));
2ea6032a 115 };
10cef607 116
117 # Current SQLA pollutes its namespace - clean for the time being
118 namespace::clean->clean_subroutines(qw/SQL::Abstract carp croak confess/);
b2b22cd6 119}
6f4ddea1 120
e9657379 121# the "oh noes offset/top without limit" constant
fcb7fcbb 122# limited to 31 bits for sanity (and consistency,
123# since it may be handed to the like of sprintf %u)
124#
125# Also *some* builds of SQLite fail the test
126# some_column BETWEEN ? AND ?: 1, 4294967295
127# with the proper integer bind attrs
128#
6a247f33 129# Implemented as a method, since ::Storage::DBI also
130# refers to it (i.e. for the case of software_limit or
131# as the value to abuse with MSSQL ordered subqueries)
fcb7fcbb 132sub __max_int () { 0x7FFFFFFF };
e9657379 133
e39f188a 134# poor man's de-qualifier
135sub _quote {
136 $_[0]->next::method( ( $_[0]{_dequalify_idents} and ! ref $_[1] )
137 ? $_[1] =~ / ([^\.]+) $ /x
138 : $_[1]
139 );
140}
141
b1d821de 142sub _where_op_NEST {
70c28808 143 carp_unique ("-nest in search conditions is deprecated, you most probably wanted:\n"
b1d821de 144 .q|{..., -and => [ \%cond0, \@cond1, \'cond2', \[ 'cond3', [ col => bind ] ], etc. ], ... }|
70c28808 145 );
b1d821de 146
147 shift->next::method(@_);
148}
149
28be821e 150around _converter_args => sub {
151 my ($orig, $self) = (shift, shift);
152 +{
153 %{$self->$orig(@_)},
154 name_sep => $self->name_sep,
d94b8193 155 limit_dialect => $self->mapped_limit_dialect,
28be821e 156 slice_stability => { $self->renderer->slice_stability },
157 slice_subquery => { $self->renderer->slice_subquery },
6f4ddea1 158 }
28be821e 159};
c2b7c5dc 160
28be821e 161# Handle limit-dialect selection
162sub select {
163 my $self = shift;
164 my ($table, $fields, $where, $rs_attrs, $limit, $offset) = @_;
583a0c65 165
28be821e 166 my ($sql, @bind) = $self->next::method(@_);
583a0c65 167
e5372da4 168 $sql .= $self->_lock_select ($rs_attrs->{for})
169 if $rs_attrs->{for};
170
10cef607 171 return wantarray ? ($sql, @bind) : $sql;
583a0c65 172}
173
174sub _assemble_binds {
175 my $self = shift;
8b31f62e 176 return map { @{ (delete $self->{"${_}_bind"}) || [] } } (qw/pre_select select from where group having order limit/);
6f4ddea1 177}
178
e5372da4 179my $for_syntax = {
180 update => 'FOR UPDATE',
181 shared => 'FOR SHARE',
182};
183sub _lock_select {
184 my ($self, $type) = @_;
8249c09b 185
186 my $sql;
187 if (ref($type) eq 'SCALAR') {
188 $sql = "FOR $$type";
189 }
190 else {
10cef607 191 $sql = $for_syntax->{$type} || $self->throw_exception( "Unknown SELECT .. FO
192R type '$type' requested" );
8249c09b 193 }
194
e5372da4 195 return " $sql";
196}
197
10cef607 198sub _recurse_from {
199 scalar shift->_render_sqla(table => \@_);
6f4ddea1 200}
201
10cef607 2021;
50136dd9 203
10cef607 204=head1 OPERATORS
81446c4f 205
10cef607 206=head2 -ident
50136dd9 207
10cef607 208Used to explicitly specify an SQL identifier. Takes a plain string as value
209which is then invariably treated as a column name (and is being properly
210quoted if quoting has been requested). Most useful for comparison of two
211columns:
83e09b5b 212
10cef607 213 my %where = (
214 priority => { '<', 2 },
215 requestor => { -ident => 'submitter' }
50136dd9 216 );
217
10cef607 218which results in:
6f4ddea1 219
10cef607 220 $stmt = 'WHERE "priority" < ? AND "requestor" = "submitter"';
221 @bind = ('2');
a6b68a60 222
10cef607 223=head2 -value
1cbd3034 224
10cef607 225The -value operator signals that the argument to the right is a raw bind value.
226It will be passed straight to DBI, without invoking any of the SQL::Abstract
227condition-parsing logic. This allows you to, for example, pass an array as a
228column value for databases that support array datatypes, e.g.:
15827712 229
10cef607 230 my %where = (
231 array => { -value => [1, 2, 3] }
b8391c87 232 );
6f4ddea1 233
10cef607 234which results in:
aa82ce29 235
10cef607 236 $stmt = 'WHERE array = ?';
237 @bind = ([1, 2, 3]);
d5dedbd6 238
239=head1 AUTHORS
240
241See L<DBIx::Class/CONTRIBUTORS>.
242
243=head1 LICENSE
244
245You may distribute this code under the same terms as Perl itself.
246
247=cut