WIP: Make ->count call ->count_rs->first unless software_limit=1
[dbsrgits/DBIx-Class.git] / t / storage / quote_names.t
1 use strict;
2 use warnings;
3 use Test::More;
4 use Data::Dumper::Concise;
5 use Try::Tiny;
6 use lib qw(t/lib);
7 use DBICTest;
8
9 my %expected = (
10   'DBIx::Class::Storage::DBI'                    =>
11       # no default quote_char
12     {                             name_sep => '.' },
13
14   'DBIx::Class::Storage::DBI::MSSQL'             =>
15     { quote_char => [ '[', ']' ], name_sep => '.' },
16
17   'DBIx::Class::Storage::DBI::DB2'               =>
18     { quote_char => '"',          name_sep => '.' },
19
20   'DBIx::Class::Storage::DBI::Informix'          =>
21     { quote_char => '"',          name_sep => '.' },
22
23   'DBIx::Class::Storage::DBI::InterBase'         =>
24     { quote_char => '"',          name_sep => '.' },
25
26   'DBIx::Class::Storage::DBI::mysql'             =>
27     { quote_char => '`',          name_sep => '.' },
28
29   'DBIx::Class::Storage::DBI::Pg'             =>
30     { quote_char => '"',          name_sep => '.' },
31
32   'DBIx::Class::Storage::DBI::ODBC::ACCESS'      =>
33     { quote_char => [ '[', ']' ], name_sep => '.' },
34
35 # Not testing this one, it's a pain.
36 #  'DBIx::Class::Storage::DBI::ODBC::DB2_400_SQL' =>
37 #    { quote_char => '"',          name_sep => qr/must be connected/ },
38
39   'DBIx::Class::Storage::DBI::Oracle::Generic'   =>
40     { quote_char => '"',          name_sep => '.' },
41
42   'DBIx::Class::Storage::DBI::SQLAnywhere'       =>
43     { quote_char => '"',          name_sep => '.' },
44
45   'DBIx::Class::Storage::DBI::SQLite'            =>
46     { quote_char => '"',          name_sep => '.' },
47
48   'DBIx::Class::Storage::DBI::Sybase::ASE'       =>
49     { quote_char => [ '[', ']' ], name_sep => '.' },
50 );
51
52 for my $class (keys %expected) { SKIP: {
53   eval "require ${class}"
54     or skip "Skipping test of quotes for $class due to missing dependencies", 1;
55
56   my $mapping = $expected{$class};
57   my ($quote_char, $name_sep) = @$mapping{qw/quote_char name_sep/};
58   my $instance = $class->new;
59
60   my $quote_char_text = dumper($quote_char);
61
62   if (exists $mapping->{quote_char}) {
63     is_deeply $instance->sql_quote_char, $quote_char,
64       "sql_quote_char for $class is $quote_char_text";
65   }
66
67   is $instance->sql_name_sep, $name_sep,
68     "sql_name_sep for $class is '$name_sep'";
69 }}
70
71 # Try quote_names with available DBs.
72
73 # Env var to base class mapping, these are the DBs I actually have.
74 # the SQLITE is a fake memory dsn
75 local $ENV{DBICTEST_SQLITE_DSN} = 'dbi:SQLite::memory:';
76 my %dbs = (
77   SQLITE           => 'DBIx::Class::Storage::DBI::SQLite',
78   ORA              => 'DBIx::Class::Storage::DBI::Oracle::Generic',
79   PG               => 'DBIx::Class::Storage::DBI::Pg',
80   MYSQL            => 'DBIx::Class::Storage::DBI::mysql',
81   DB2              => 'DBIx::Class::Storage::DBI::DB2',
82   SYBASE           => 'DBIx::Class::Storage::DBI::Sybase::ASE',
83   SQLANYWHERE      => 'DBIx::Class::Storage::DBI::SQLAnywhere',
84   SQLANYWHERE_ODBC => 'DBIx::Class::Storage::DBI::SQLAnywhere',
85   FIREBIRD         => 'DBIx::Class::Storage::DBI::InterBase',
86   FIREBIRD_ODBC    => 'DBIx::Class::Storage::DBI::InterBase',
87   INFORMIX         => 'DBIx::Class::Storage::DBI::Informix',
88   MSSQL_ODBC       => 'DBIx::Class::Storage::DBI::MSSQL',
89 );
90
91 # lie that we already locked stuff - the tests below do not touch anything
92 # unless we are under travis, where the OOM killers reign and things are rough
93 $ENV{DBICTEST_LOCK_HOLDER} = -1
94   unless DBICTest::RunMode->is_ci;
95
96 # Make sure oracle is tried last - some clients (e.g. 10.2) have symbol
97 # clashes with libssl, and will segfault everything coming after them
98 for my $db (sort {
99     $a eq 'ORA' ? 1
100   : $b eq 'ORA' ? -1
101   : $a cmp $b
102 } keys %dbs) {
103   my ($dsn, $user, $pass) = map $ENV{"DBICTEST_${db}_$_"}, qw/DSN USER PASS/;
104
105   next unless $dsn;
106
107   my $schema;
108
109   my $sql_maker = try {
110     $schema = DBICTest::Schema->connect($dsn, $user, $pass, {
111       quote_names => 1
112     });
113     $schema->storage->ensure_connected;
114     $schema->storage->sql_maker;
115   } || next;
116
117   my ($exp_quote_char, $exp_name_sep) =
118     @{$expected{$dbs{$db}}}{qw/quote_char name_sep/};
119
120   my ($quote_char_text, $name_sep_text) = map { dumper($_) }
121     ($exp_quote_char, $exp_name_sep);
122
123   is_deeply $sql_maker->quote_char,
124     $exp_quote_char,
125     "$db quote_char with quote_names => 1 is $quote_char_text";
126
127
128   is $sql_maker->name_sep,
129     $exp_name_sep,
130     "$db name_sep with quote_names => 1 is $name_sep_text";
131
132   # if something was produced - it better be quoted
133   if (
134     # the SQLT producer has no idea what quotes are :/
135     ! grep { $db eq $_ } qw( SYBASE DB2 )
136       and
137     my $ddl = try { $schema->deployment_statements }
138   ) {
139     my $quoted_artist = $sql_maker->_quote('artist');
140
141     like ($ddl, qr/^CREATE\s+TABLE\s+\Q$quoted_artist/msi, "$db DDL contains expected quoted table name");
142   }
143 }
144
145 done_testing;
146
147 sub dumper {
148   my $val = shift;
149
150   my $dd = DumperObject;
151   $dd->Indent(0);
152   return $dd->Values([ $val ])->Dump;
153 }
154
155 1;