Add SQLMaker methods for matching and unquoting quoted identifiers
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / SQLMaker.pm
index 5b5181f..0d27ec9 100644 (file)
@@ -44,14 +44,56 @@ use namespace::clean;
 
 __PACKAGE__->mk_group_accessors (simple => qw/quote_char name_sep limit_dialect/);
 
+sub _quoting_enabled {
+  ( defined $_[0]->{quote_char} and length $_[0]->{quote_char} ) ? 1 : 0
+}
+
 # for when I need a normalized l/r pair
 sub _quote_chars {
+
+  # in case we are called in the old !!$sm->_quote_chars fashion
+  return () if !wantarray and ( ! defined $_[0]->{quote_char} or ! length $_[0]->{quote_char} );
+
   map
     { defined $_ ? $_ : '' }
     ( ref $_[0]->{quote_char} ? (@{$_[0]->{quote_char}}) : ( ($_[0]->{quote_char}) x 2 ) )
   ;
 }
 
+sub _escape_char {
+  $_[0]->{escape_char} || ($_[0]->_quote_chars)[1] || '';
+}
+
+sub _unquote {
+  my ($self, $value) = @_;
+
+  return $value unless defined $value;
+
+  my ($l, $r, $e) = map { quotemeta $_ } $self->_quote_chars, $self->_escape_char;
+
+  # no quoting, all bets are off
+  return $value unless length $e;
+
+  my $re = $self->_quoted_ident_re($l, $r, $e);
+
+  if ($value =~ /\A$re\z/) {
+    $value =~ s/\A$l//;
+    $value =~ s/$r\z//;
+    $value =~ s/( $e [$e$r] )/substr($1, 1)/gex;
+    return $value;
+  }
+  else {
+    # not a quoted value, assume it's an identifier
+    return $value;
+  }
+}
+
+sub _quoted_ident_re {
+  my $self = shift;
+  my ($l, $r, $e) = @_ ? @_ : map { quotemeta $_ } $self->_quote_chars, $self->_escape_char;
+  return qr/ $l (?: [^$e$r] | $e [$e$r] )+ $r /x;
+}
+
 # FIXME when we bring in the storage weaklink, check its schema
 # weaklink and channel through $schema->throw_exception
 sub throw_exception { DBIx::Class::Exception->throw($_[1]) }