From: Peter Rabbitson Date: Thu, 14 Oct 2010 05:06:28 +0000 (+0200) Subject: Set name_sep by default (even if unused). Simplify raw-sql scanner code X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=3f5b99fea8b445c7a61057f4210a715ffb8e677e;p=dbsrgits%2FDBIx-Class-Historic.git Set name_sep by default (even if unused). Simplify raw-sql scanner code --- diff --git a/lib/DBIx/Class/Manual/Cookbook.pod b/lib/DBIx/Class/Manual/Cookbook.pod index 87ffd96..4f599b7 100644 --- a/lib/DBIx/Class/Manual/Cookbook.pod +++ b/lib/DBIx/Class/Manual/Cookbook.pod @@ -1669,7 +1669,8 @@ brackets, or a C<"> or C<'>: Check the documentation of your database for the correct quote characters to use. C needs to be set to allow the SQL -generator to put the quotes the correct place. +generator to put the quotes the correct place, and defaults to +C<.> if not supplied. In most cases you should set these as part of the arguments passed to L: diff --git a/lib/DBIx/Class/SQLMaker.pm b/lib/DBIx/Class/SQLMaker.pm index ea2b23e..f43aa0b 100644 --- a/lib/DBIx/Class/SQLMaker.pm +++ b/lib/DBIx/Class/SQLMaker.pm @@ -42,6 +42,14 @@ use namespace::clean; __PACKAGE__->mk_group_accessors (simple => qw/quote_char name_sep limit_dialect/); +# for when I need a normalized l/r pair +sub _quote_chars { + map + { defined $_ ? $_ : '' } + ( ref $_[0]->{quote_char} ? (@{$_[0]->{quote_char}}) : ( ($_[0]->{quote_char}) x 2 ) ) + ; +} + BEGIN { # reinstall the carp()/croak() functions imported into SQL::Abstract # as Carp and Carp::Clan do not like each other much diff --git a/lib/DBIx/Class/SQLMaker/LimitDialects.pm b/lib/DBIx/Class/SQLMaker/LimitDialects.pm index 723001d..846cab7 100644 --- a/lib/DBIx/Class/SQLMaker/LimitDialects.pm +++ b/lib/DBIx/Class/SQLMaker/LimitDialects.pm @@ -348,7 +348,7 @@ sub _Top { my $inner_order = ($order_by_requested ? $requested_order : [ map - { join ('', $rs_attrs->{alias}, $self->{name_sep}||'.', $_ ) } + { "$rs_attrs->{alias}.$_" } ( $rs_attrs->{_rsroot_source_handle}->resolve->_pri_cols ) ] ); @@ -608,10 +608,7 @@ sub _subqueried_limit_attrs { croak 'Limit dialect implementation usable only in the context of DBIC (missing $rs_attrs)' unless ref ($rs_attrs) eq 'HASH'; - my ($re_sep, $re_alias) = map { quotemeta $_ } ( - $self->name_sep || '.', - $rs_attrs->{alias}, - ); + my ($re_sep, $re_alias) = map { quotemeta $_ } ( $self->{name_sep}, $rs_attrs->{alias} ); # correlate select and as, build selection index my (@sel, $in_sel_index); @@ -651,7 +648,11 @@ sub _subqueried_limit_attrs { # for possible further chaining) my (@in_sel, @out_sel, %renamed); for my $node (@sel) { - if (first { $_ =~ / (?{as}, $node->{unquoted_sql}) ) { + if ( + $node->{as} =~ / (?{unquoted_sql} =~ / (?{as} = $self->_unqualify_colname($node->{as}); my $quoted_as = $self->_quote($node->{as}); push @in_sel, sprintf '%s AS %s', $node->{sql}, $quoted_as; @@ -690,8 +691,7 @@ sub _subqueried_limit_attrs { sub _unqualify_colname { my ($self, $fqcn) = @_; - my $re_sep = quotemeta($self->name_sep || '.'); - $fqcn =~ s/ $re_sep /__/xg; + $fqcn =~ s/ \. /__/xg; return $fqcn; } diff --git a/lib/DBIx/Class/Storage/DBI.pm b/lib/DBIx/Class/Storage/DBI.pm index d54e0b2..6a85b2c 100644 --- a/lib/DBIx/Class/Storage/DBI.pm +++ b/lib/DBIx/Class/Storage/DBI.pm @@ -453,8 +453,7 @@ of available limit dialects see L. =item quote_char -Specifies what characters to use to quote table and column names. If -you use this you will want to specify L as well. +Specifies what characters to use to quote table and column names. C expects either a single character, in which case is it is placed on either side of the table/column name, or an arrayref of length @@ -465,14 +464,9 @@ SQL Server you should use C<< quote_char => [qw/[ ]/] >>. =item name_sep -This only needs to be used in conjunction with C, and is used to +This parameter is only useful in conjunction with C, and is used to specify the character that separates elements (schemas, tables, columns) from -each other. In most cases this is simply a C<.>. - -The consequences of not supplying this value is that L -will assume DBIx::Class' uses of aliases to be complete column -names. The output will look like I<"me.name"> when it should actually -be I<"me"."name">. +each other. If unspecified it defaults to the most commonly used C<.>. =item unsafe @@ -525,7 +519,7 @@ L 'postgres', 'my_pg_password', { AutoCommit => 1 }, - { quote_char => q{"}, name_sep => q{.} }, + { quote_char => q{"} }, ] ); @@ -999,6 +993,7 @@ sub sql_maker { bindtype=>'columns', array_datatypes => 1, limit_dialect => $dialect, + name_sep => '.', %opts, )); } diff --git a/lib/DBIx/Class/Storage/DBIHacks.pm b/lib/DBIx/Class/Storage/DBIHacks.pm index ed5de4d..23b528b 100644 --- a/lib/DBIx/Class/Storage/DBIHacks.pm +++ b/lib/DBIx/Class/Storage/DBIHacks.pm @@ -226,21 +226,27 @@ sub _resolve_aliastypes_from_select_args { # set up a botched SQLA my $sql_maker = $self->sql_maker; - my $sep = quotemeta ($self->_sql_maker_opts->{name_sep} || '.'); - my ($orig_lquote, $orig_rquote) = map { quotemeta $_ } (do { - if (ref $sql_maker->{quote_char} eq 'ARRAY') { - @{$sql_maker->{quote_char}} - } - else { - ($sql_maker->{quote_char} || '') x 2; - } - }); + local $sql_maker->{having_bind}; # these are throw away results + + # we can't scan properly without any quoting (\b doesn't cut it + # everywhere), so unless there is proper quoting set - use our + # own weird impossible character. + # Also in the case of no quoting, we need to explicitly disable + # name_sep, otherwise sorry nasty legacy syntax like + # { 'count(foo.id)' => { '>' => 3 } } will stop working >:( + local $sql_maker->{quote_char} = $sql_maker->{quote_char}; + local $sql_maker->{name_sep} = $sql_maker->{name_sep}; + + unless (defined $sql_maker->{quote_char} and length $sql_maker->{quote_char}) { + $sql_maker->{quote_char} = "\x00"; + $sql_maker->{name_sep} = ''; + } + + my ($lquote, $rquote, $sep) = map { quotemeta $_ } ($sql_maker->_quote_chars, $sql_maker->name_sep); - local $sql_maker->{quote_char} = "\x00"; # so that we can regex away # generate sql chunks - local $sql_maker->{having_bind}; # these are throw away results my $to_scan = { restricting => [ $sql_maker->_recurse_where ($where), @@ -261,16 +267,11 @@ 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/ - \x00 $alias \x00 $sep + $lquote $alias $rquote $sep | - \b $alias $sep + \b $alias \. /x; - # add matching for possible quoted literal sql - $al_re = qr/ $al_re | $orig_lquote $alias $orig_rquote /x - if ($orig_lquote && $orig_rquote); - - for my $type (keys %$to_scan) { for my $piece (@{$to_scan->{$type}}) { $aliases_by_type->{$type}{$alias} = 1 if ($piece =~ $al_re); @@ -281,12 +282,9 @@ sub _resolve_aliastypes_from_select_args { # now loop through unqualified column names, and try to locate them within # the chunks for my $col (keys %$colinfo) { - next if $col =~ $sep; # if column is qualified it was caught by the above - - my $col_re = qr/ \x00 $col \x00 /x; + next if $col =~ / \. /x; # if column is qualified it was caught by the above - $col_re = qr/ $col_re | $orig_lquote $col $orig_rquote /x - if ($orig_lquote && $orig_rquote); + my $col_re = qr/ $lquote $col $rquote /x; for my $type (keys %$to_scan) { for my $piece (@{$to_scan->{$type}}) { @@ -361,9 +359,6 @@ sub _resolve_column_info { my ($self, $ident, $colnames) = @_; my ($alias2src, $root_alias) = $self->_resolve_ident_sources($ident); - my $sep = $self->_sql_maker_opts->{name_sep} || '.'; - my $qsep = quotemeta $sep; - my (%return, %seen_cols, @auto_colnames); # compile a global list of column names, to be able to properly @@ -372,7 +367,7 @@ sub _resolve_column_info { my $rsrc = $alias2src->{$alias}; for my $colname ($rsrc->columns) { push @{$seen_cols{$colname}}, $alias; - push @auto_colnames, "$alias$sep$colname" unless $colnames; + push @auto_colnames, "$alias.$colname" unless $colnames; } } @@ -383,7 +378,7 @@ sub _resolve_column_info { COLUMN: foreach my $col (@$colnames) { - my ($alias, $colname) = $col =~ m/^ (?: ([^$qsep]+) $qsep)? (.+) $/x; + my ($alias, $colname) = $col =~ m/^ (?: ([^\.]+) \. )? (.+) $/x; unless ($alias) { # see if the column was seen exactly once (so we know which rsrc it came from) diff --git a/t/71mysql.t b/t/71mysql.t index 01c32d8..66ebfd2 100644 --- a/t/71mysql.t +++ b/t/71mysql.t @@ -263,7 +263,6 @@ NULLINSEARCH: { my $ansi_schema = DBICTest::Schema->connect ($dsn, $user, $pass, { on_connect_call => 'set_strict_mode', quote_char => '`', - name_sep => '.' }); my $rs = $ansi_schema->resultset('CD');