\Q-uote column/alias names in regexes in _resolve_aliastypes_from_select_args topic/quote-escape
Dagfinn Ilmari Mannsåker [Sat, 26 Jul 2014 21:31:42 +0000 (22:31 +0100)]
Column names can contain regex metacharacters (which includes #, with
/x), so wrap them in \Q and \E to avoid syntax errors.

Changes
lib/DBIx/Class/Storage/DBIHacks.pm
t/lib/DBICTest/Schema/Artist.pm
t/lib/DBICTest/Schema/Quotes.pm
t/sqlmaker/quotes.t

diff --git a/Changes b/Changes
index d69a071..32c6de0 100644 (file)
--- a/Changes
+++ b/Changes
@@ -38,6 +38,8 @@ Revision history for DBIx::Class
           additional codepath (missed in 0.08260)
         - Fix inability to handle multiple consecutive transactions with
           savepoints on DBD::SQLite < 1.39
+        - Fix prefetching tables with columns with regex metacharacters
+          in the name
 
     * Misc
         - Ensure source metadata calls always take place on the result source
index 26f8dca..04c2740 100644 (file)
@@ -484,9 +484,9 @@ sub _resolve_aliastypes_from_select_args {
   # alias (should work even if they are in scalarrefs)
   for my $alias (keys %$alias_list) {
     my $al_re = qr/
-      $lquote $alias $rquote $sep (?: $lquote ([^$rquote]+) $rquote )?
+      $lquote \Q$alias\E $rquote $sep (?: $lquote ([^$rquote]+) $rquote )?
         |
-      \b $alias \. ([^\s\)\($rquote]+)?
+      \b \Q$alias\E \. ([^\s\)\($rquote]+)?
     /x;
 
     for my $type (keys %$to_scan) {
@@ -505,7 +505,7 @@ sub _resolve_aliastypes_from_select_args {
   for my $col (keys %$colinfo) {
     next if $col =~ / \. /x;   # if column is qualified it was caught by the above
 
-    my $col_re = qr/ $lquote ($col) $rquote /x;
+    my $col_re = qr/ $lquote (\Q$col\E) $rquote /x;
 
     for my $type (keys %$to_scan) {
       for my $piece (@{$to_scan->{$type}}) {
index 470796a..6702f11 100644 (file)
@@ -169,6 +169,8 @@ __PACKAGE__->has_many(
     },
 );
 
+__PACKAGE__->has_many(quotes => 'DBICTest::Schema::Quotes', 'artistid');
+
 sub sqlt_deploy_hook {
   my ($self, $sqlt_table) = @_;
 
index a6fe246..0d84eb8 100644 (file)
@@ -15,6 +15,15 @@ __PACKAGE__->add_columns(
     is_auto_increment => 1,
     accessor => 'has_more_quotes',
   },
+  'has # comment' => {
+    data_type => 'integer',
+    accessor => 'has_comment',
+  },
+  artistid => {
+    data_type => 'integer',
+  },
 );
 
+__PACKAGE__->belongs_to(artist => 'DBICTest::Schema::Artist', 'artistid');
+
 1;
index e4c6dbd..63d6f75 100644 (file)
@@ -34,7 +34,7 @@ is_same_sql_bind(
 
 is_same_sql_bind(
   $schema->resultset('Quotes')->search({})->as_query,
-  '(SELECT [me].[`has` [more]] "quotes"] FROM [`with` [some]] "quotes"] [me])',
+  '(SELECT [me].[`has` [more]] "quotes"], [me].[has # comment], [me].[artistid] FROM [`with` [some]] "quotes"] [me])',
   [],
   'got correct escaped quotes with bracket quoting'
 );
@@ -51,11 +51,18 @@ is_same_sql_bind (
 
 is_same_sql_bind(
   $schema->resultset('Quotes')->search({})->as_query,
-  '(SELECT `me`.```has`` [more] "quotes"` FROM ```with`` [some] "quotes"` `me`)',
+  '(SELECT `me`.```has`` [more] "quotes"`, `me`.`has # comment`, `me`.`artistid` FROM ```with`` [some] "quotes"` `me`)',
   [],
   'got correct escaped quotes with mysql quoting'
 );
 
+is_same_sql_bind(
+  $schema->resultset('Artist')->search({}, { prefetch => 'quotes' })->as_query,
+  '(SELECT `me`.`artistid`, `me`.`name`, `me`.`rank`, `me`.`charfield`, `quotes`.```has`` [more] "quotes"`, `quotes`.`has # comment`, `quotes`.`artistid` FROM `artist` `me` LEFT JOIN ```with`` [some] "quotes"` `quotes` ON `quotes`.`artistid` = `me`.`artistid`)',
+  [],
+  'got correct escaped comment with prefetch and mysql quoting'
+);
+
 # !!! talk to ribasushi *explicitly* before modfying these tests !!!
 {
   is_same_sql_bind(