X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FSQL%2FAbstract.pm;h=4279a9be162534b09094327be275d535236cdf8b;hb=13cc86afceb9b27d9647caded03e806d2350ba48;hp=c88d0c2708dd56380d087fcfe4b8960425b4397b;hpb=20e178a84a647f5ae98a16a7358496c6dc86caf0;p=dbsrgits%2FSQL-Abstract.git diff --git a/lib/SQL/Abstract.pm b/lib/SQL/Abstract.pm index c88d0c2..4279a9b 100644 --- a/lib/SQL/Abstract.pm +++ b/lib/SQL/Abstract.pm @@ -16,6 +16,11 @@ BEGIN { else { require mro; } + + *SQL::Abstract::_ENV_::DETECT_AUTOGENERATED_STRINGIFICATION = $ENV{SQLA_ISVALUE_IGNORE_AUTOGENERATED_STRINGIFICATION} + ? sub () { 0 } + : sub () { 1 } + ; } #====================================================================== @@ -108,6 +113,8 @@ sub is_plain_value ($) { or # has nummification or boolification, AND fallback is *not* disabled ( + SQL::Abstract::_ENV_::DETECT_AUTOGENERATED_STRINGIFICATION + and ( grep { *{"${_}::(0+"}{CODE} } @{$_[2]} or @@ -490,9 +497,15 @@ sub _recurse_where { my ($sql, @bind) = $self->$method($where, $logic); - # DBIx::Class directly calls _recurse_where in scalar context, so - # we must implement it, even if not in the official API - return wantarray ? ($sql, @bind) : $sql; + # DBIx::Class used to call _recurse_where in scalar context + # something else might too... + if (wantarray) { + return ($sql, @bind); + } + else { + belch "Calling _recurse_where in scalar context is deprecated and will go away before 2.0"; + return $sql; + } } @@ -1711,7 +1724,7 @@ say something like this: my %data = ( name => 'Bill', - date_entered => \["to_date(?,'MM/DD/YYYY')", "03/02/2003"], + date_entered => \[ "to_date(?,'MM/DD/YYYY')", "03/02/2003" ], ); The first value in the array is the actual SQL. Any other values are @@ -1765,9 +1778,9 @@ Easy, eh? =head1 METHODS -The methods are simple. There's one for each major SQL operation, +The methods are simple. There's one for every major SQL operation, and a constructor you use first. The arguments are specified in a -similar order to each method (table, then fields, then a where +similar order for each method (table, then fields, then a where clause) to try and simplify things. =head2 new(option => 'value') @@ -1912,7 +1925,7 @@ are or are not included. You could wrap that above C loop in a simple sub called C or something and reuse it repeatedly. You still get a layer of abstraction over manual SQL specification. -Note that if you set L to C, the C<\[$sql, @bind]> +Note that if you set L to C, the C<\[ $sql, @bind ]> construct (see L) will expect the bind values in this format. @@ -2153,6 +2166,48 @@ module: On failure returns C, on sucess returns a B reference to the original supplied argument. +=over + +=item * Note + +The stringification overloading detection is rather advanced: it takes +into consideration not only the presence of a C<""> overload, but if that +fails also checks for enabled +L|overload/Magic Autogeneration>, based +on either C<0+> or C. + +Unfortunately testing in the field indicates that this +detection B<< may tickle a latent bug in perl versions before 5.018 >>, +but only when very large numbers of stringifying objects are involved. +At the time of writing ( Sep 2014 ) there is no clear explanation of +the direct cause, nor is there a manageably small test case that reliably +reproduces the problem. + +If you encounter any of the following exceptions in B - this module may be to blame: + + Operation "ne": no method found, + left argument in overloaded package , + right argument in overloaded package + +or perhaps even + + Stub found while resolving method "???" overloading """" in package + +If you fall victim to the above - please attempt to reduce the problem +to something that could be sent to the L +(either publicly or privately). As a workaround in the meantime you can +set C<$ENV{SQLA_ISVALUE_IGNORE_AUTOGENERATED_STRINGIFICATION}> to a true +value, which will most likely eliminate your problem (at the expense of +not being able to properly detect exotic forms of stringification). + +This notice and environment variable will be removed in a future version, +as soon as the underlying problem is found and a reliable workaround is +devised. + +=back + =head2 is_literal_value Determines if the supplied argument is a literal value as understood by this @@ -2295,7 +2350,7 @@ Which would generate: @bind = ('2', '5', 'nwiger'); If you want to include literal SQL (with or without bind values), just use a -scalar reference or array reference as the value: +scalar reference or reference to an arrayref as the value: my %where = ( date_entered => { '>' => \["to_date(?, 'MM/DD/YYYY')", "11/26/2008"] }, @@ -2304,7 +2359,7 @@ scalar reference or array reference as the value: Which would generate: - $stmt = "WHERE date_entered > "to_date(?, 'MM/DD/YYYY') AND date_expires < now()"; + $stmt = "WHERE date_entered > to_date(?, 'MM/DD/YYYY') AND date_expires < now()"; @bind = ('11/26/2008'); @@ -2318,7 +2373,7 @@ this (notice the C): Because, in Perl you I do this: - priority => { '!=', 2, '!=', 1 } + priority => { '!=' => 2, '!=' => 1 } As the second C key will obliterate the first. The solution is to use the special C<-modifier> form inside an arrayref: @@ -2510,10 +2565,10 @@ to change the logic inside : That would yield: - WHERE ( user = ? AND ( - ( workhrs > ? AND geo = ? ) - OR ( workhrs < ? OR geo = ? ) - ) ) + $stmt = "WHERE ( user = ? + AND ( ( workhrs > ? AND geo = ? ) + OR ( workhrs < ? OR geo = ? ) ) )"; + @bind = ('nwiger', '20', 'ASIA', '50', 'EURO'); =head3 Algebraic inconsistency, for historical reasons @@ -2634,7 +2689,7 @@ not so common, but perfectly legal Perl). For example, to find a date in Postgres you can use something like this: my %where = ( - date_column => \[q/= date '2008-09-30' - ?::integer/, 10/] + date_column => \[ "= date '2008-09-30' - ?::integer", 10 ] ) This would create: @@ -2643,15 +2698,16 @@ This would create: @bind = ('10'); Note that you must pass the bind values in the same format as they are returned -by L. That means that if you set L to C, you must -provide the bind values in the C<< [ column_meta => value ] >> format, where -C is an opaque scalar value; most commonly the column name, but -you can use any scalar value (including references and blessed references), -L will simply pass it through intact. So if C is set -to C the above example will look like: +by L. This means that if you set L +to C, you must provide the bind values in the +C<< [ column_meta => value ] >> format, where C is an opaque +scalar value; most commonly the column name, but you can use any scalar value +(including references and blessed references), L will simply +pass it through intact. So if C is set to C the above +example will look like: my %where = ( - date_column => \[q/= date '2008-09-30' - ?::integer/, [ dummy => 10 ]/] + date_column => \[ "= date '2008-09-30' - ?::integer", [ {} => 10 ] ] ) Literal SQL is especially useful for nesting parenthesized clauses in the @@ -2858,14 +2914,14 @@ Either a coderef or a plain scalar method name. In both cases the expected return is C<< ($sql, @bind) >>. When supplied with a method name, it is simply called on the -L object as: +L object as: $self->$method_name ($field, $op, $arg) Where: - $op is the part that matched the handler regex $field is the LHS of the operator + $op is the part that matched the handler regex $arg is the RHS When supplied with a coderef, it is called as: @@ -2934,7 +2990,7 @@ Either a coderef or a plain scalar method name. In both cases the expected return is C<< $sql >>. When supplied with a method name, it is simply called on the -L object as: +L object as: $self->$method_name ($op, $arg) @@ -3042,7 +3098,7 @@ The main changes are : =item * -support for literal SQL through the C<< \ [$sql, bind] >> syntax. +support for literal SQL through the C<< \ [ $sql, @bind ] >> syntax. =item *