Use proper quote handling in _extract_order_criteria
Dagfinn Ilmari Mannsåker [Mon, 28 Jul 2014 14:06:19 +0000 (15:06 +0100)]
This should really be rewritten to localise the $sql_maker's quote
settings to force them _on_, à la _resolve_aliastypes_from_select_args

lib/DBIx/Class/SQLMaker.pm
lib/DBIx/Class/Storage/DBIHacks.pm

index 0d27ec9..d9dbffb 100644 (file)
@@ -65,11 +65,11 @@ sub _escape_char {
 }
 
 sub _unquote {
-  my ($self, $value) = @_;
+  my ($self, $value, @quotes) = @_;
 
   return $value unless defined $value;
 
-  my ($l, $r, $e) = map { quotemeta $_ } $self->_quote_chars, $self->_escape_char;
+  my ($l, $r, $e) = @quotes ? @quotes : map { quotemeta $_ } $self->_quote_chars, $self->_escape_char;
 
   # no quoting, all bets are off
   return $value unless length $e;
index 350bb56..e3d7e8a 100644 (file)
@@ -849,10 +849,14 @@ sub _extract_order_criteria {
     return scalar $sql_maker->_order_by_chunks ($order_by)
       unless wantarray;
 
-    my ($lq, $rq, $sep) = map { quotemeta($_) } (
-      ($orig_quote_chars ? @$orig_quote_chars : $sql_maker->_quote_chars),
-      $sql_maker->name_sep
-    );
+    my $sep = quotemeta($sql_maker->name_sep);
+
+    my @quotes = map { quotemeta($_) }
+        $orig_quote_chars
+          ? @$orig_quote_chars
+          : ($sql_maker->_quote_chars, $sql_maker->_escape_char);
+
+    my $quoted_ident_re = $sql_maker->_quoted_ident_re(@quotes);
 
     my @chunks;
     for ($sql_maker->_order_by_chunks ($order_by) ) {
@@ -861,8 +865,9 @@ sub _extract_order_criteria {
 
       # order criteria may have come back pre-quoted (literals and whatnot)
       # this is fragile, but the best we can currently do
-      $chunk->[0] =~ s/^ $lq (.+?) $rq $sep $lq (.+?) $rq $/"$1.$2"/xe
-        or $chunk->[0] =~ s/^ $lq (.+) $rq $/$1/x;
+      if (my @quoted = $chunk->[0] =~ /\A ($quoted_ident_re) (?: $sep ($quoted_ident_re) )? \z/x) {
+        $chunk->[0] = join('.', map { $sql_maker->_unquote($_, @quotes) } grep { defined } @quoted);
+      }
 
       push @chunks, $chunk;
     }
@@ -878,7 +883,7 @@ sub _extract_order_criteria {
 
     # pass these in to deal with literals coming from
     # the user or the deep guts of prefetch
-    my $orig_quote_chars = [$sql_maker->_quote_chars];
+    my $orig_quote_chars = [$sql_maker->_quote_chars, $sql_maker->_escape_char];
 
     local $sql_maker->{quote_char};
     return $parser->($sql_maker, $order_by, $orig_quote_chars);