diff --git a/lib/Data/ObjectDriver/Driver/DBI.pm b/lib/Data/ObjectDriver/Driver/DBI.pm index 148db0d..4977fa8 100644 --- a/lib/Data/ObjectDriver/Driver/DBI.pm +++ b/lib/Data/ObjectDriver/Driver/DBI.pm @@ -165,7 +165,7 @@ sub prepare_fetch { my $stmt = $driver->prepare_statement($class, $terms, $args); - my $sql = $stmt->as_sql; + my $sql = $stmt->as_sql($driver->rw_handle); $sql .= "\nFOR UPDATE" if $orig_args->{for_update}; return ($sql, $stmt->{bind}, $stmt) } diff --git a/lib/Data/ObjectDriver/SQL.pm b/lib/Data/ObjectDriver/SQL.pm index 8c43856..5ddfc7e 100644 --- a/lib/Data/ObjectDriver/SQL.pm +++ b/lib/Data/ObjectDriver/SQL.pm @@ -58,14 +58,19 @@ sub add_index_hint { } sub as_sql { - my $stmt = shift; + my ($stmt, $dbh) = @_; my $sql = ''; if (@{ $stmt->select }) { $sql .= 'SELECT '; $sql .= 'DISTINCT ' if $stmt->distinct; $sql .= join(', ', map { my $alias = $stmt->select_map->{$_}; - $alias && /(?:^|\.)\Q$alias\E$/ ? $_ : "$_ $alias"; + if ($alias && !/(?:^|\.)\Q$alias\E$/) { + $alias = $dbh->quote_identifier($alias) if $dbh; + qq!$_ $alias! + } else { + $_; + } } @{ $stmt->select }) . "\n"; } $sql .= 'FROM '; diff --git a/t/11-sql.t b/t/11-sql.t index 56a21ad..5d5c899 100644 --- a/t/11-sql.t +++ b/t/11-sql.t @@ -2,8 +2,16 @@ use strict; +use lib 't/lib'; use Data::ObjectDriver::SQL; -use Test::More tests => 113; +use Test::More tests => 111; +use DodTestUtil; + +BEGIN { DodTestUtil->check_driver } + +setup_dbs({ + global => [ qw( wines ) ], +}); my $stmt = ns(); ok($stmt, 'Created SQL object'); @@ -284,15 +292,34 @@ $stmt->add_select('bar'); $stmt->from([ qw( baz ) ]); is($stmt->as_sql, "SELECT foo, bar\nFROM baz\n"); -$stmt = ns(); -$stmt->add_select('f.foo' => 'foo'); -$stmt->add_select('COUNT(*)' => 'count'); -$stmt->from([ qw( baz ) ]); -is($stmt->as_sql, "SELECT f.foo, COUNT(*) count\nFROM baz\n"); -my $map = $stmt->select_map; -is(scalar(keys %$map), 2); -is($map->{'f.foo'}, 'foo'); -is($map->{'COUNT(*)'}, 'count'); +subtest 'SQL functions' => sub { + $stmt = ns(); + $stmt->add_select('f.foo' => 'foo'); + $stmt->add_select('COUNT(*)' => 'count'); + $stmt->from([ qw( baz ) ]); + is($stmt->as_sql, "SELECT f.foo, COUNT(*) count\nFROM baz\n"); + my $map = $stmt->select_map; + is(scalar(keys %$map), 2); + is_deeply($map, {'f.foo' => 'foo', 'COUNT(*)' => 'count'}, 'right map'); + + $stmt = ns(); + $stmt->add_select('count(foo)'); + $stmt->add_select('count(bar)'); + $stmt->from([qw( baz )]); + is($stmt->as_sql, "SELECT count(foo), count(bar)\nFROM baz\n"); + my $map = $stmt->select_map; + is(scalar(keys %$map), 2); + is_deeply($map, {'count(foo)' => 'count(foo)', 'count(bar)' => 'count(bar)'}, 'right map'); + + $stmt = ns(); + $stmt->add_select('count(foo)', 'count1'); + $stmt->add_select('count(bar)', 'count2'); + $stmt->from([qw( baz )]); + is($stmt->as_sql, "SELECT count(foo) count1, count(bar) count2\nFROM baz\n"); + my $map = $stmt->select_map; + is(scalar(keys %$map), 2); + is_deeply($map, {'count(foo)' => 'count1', 'count(bar)' => 'count2'}, 'right map'); +}; # HAVING $stmt = ns(); @@ -386,4 +413,29 @@ is( : "WHERE ((foo = ?)) AND ((baz = ?) AND ((bar LIKE ?) OR (bar LIKE ?)))\n" ); +subtest 'quote can be used based on given dbh' => sub { + use Wine; + $stmt = ns(); + $stmt->add_select(foo => 'bar'); + @{$stmt->from} = ('baz'); + my $quoted = Wine->driver->rw_handle->quote_identifier('bar'); + is sql_normalize($stmt->as_sql(Wine->driver->rw_handle)), sql_normalize(<<"EOF"), 'right sql'; +SELECT foo $quoted FROM baz +EOF +}; + sub ns { Data::ObjectDriver::SQL->new } + +sub sql_normalize { + my $sql = shift; + $sql =~ s{\s+}{ }g; + $sql =~ s{\( }{(}g; + $sql =~ s{ \)}{)}g; + $sql =~ s{([\(\)]) ([\(\)])}{$1$2}g; + $sql; +} + +END { + disconnect_all(qw/Wine/); + teardown_dbs(qw( global )); +}