adding multi-schema tests
[dbsrgits/DBIx-Class-Schema-Loader.git] / t / 10_03pg_common.t
1 use strict;
2 use lib qw(t/lib);
3 use DBIx::Class::Schema::Loader 'make_schema_at';
4 use DBIx::Class::Schema::Loader::Utils 'no_warnings';
5 use dbixcsl_common_tests;
6 use Test::More;
7 use Test::Exception;
8 use File::Slurp 'slurp';
9 use utf8;
10 use Encode 'decode';
11 use Try::Tiny;
12
13 my $dsn      = $ENV{DBICTEST_PG_DSN} || '';
14 my $user     = $ENV{DBICTEST_PG_USER} || '';
15 my $password = $ENV{DBICTEST_PG_PASS} || '';
16
17 my $tester = dbixcsl_common_tests->new(
18     vendor      => 'Pg',
19     auto_inc_pk => 'SERIAL NOT NULL PRIMARY KEY',
20     dsn         => $dsn,
21     user        => $user,
22     password    => $password,
23     loader_options  => { preserve_case => 1 },
24     connect_info_opts => {
25         pg_enable_utf8 => 1,
26         on_connect_do  => [ 'SET client_min_messages=WARNING' ],
27     },
28     quote_char  => '"',
29     data_types  => {
30         # http://www.postgresql.org/docs/7.4/interactive/datatype.html
31         #
32         # Numeric Types
33         boolean     => { data_type => 'boolean' },
34         bool        => { data_type => 'boolean' },
35         'bool default false'
36                     => { data_type => 'boolean', default_value => \'false' },
37
38         bigint      => { data_type => 'bigint' },
39         int8        => { data_type => 'bigint' },
40         bigserial   => { data_type => 'bigint', is_auto_increment => 1 },
41         serial8     => { data_type => 'bigint', is_auto_increment => 1 },
42         integer     => { data_type => 'integer' },
43         int         => { data_type => 'integer' },
44         int4        => { data_type => 'integer' },
45         serial      => { data_type => 'integer', is_auto_increment => 1 },
46         serial4     => { data_type => 'integer', is_auto_increment => 1 },
47         smallint    => { data_type => 'smallint' },
48         int2        => { data_type => 'smallint' },
49
50         money       => { data_type => 'money' },
51
52         'double precision' => { data_type => 'double precision' },
53         float8             => { data_type => 'double precision' },
54         real               => { data_type => 'real' },
55         float4             => { data_type => 'real' },
56         'float(24)'        => { data_type => 'real' },
57         'float(25)'        => { data_type => 'double precision' },
58         'float(53)'        => { data_type => 'double precision' },
59         float              => { data_type => 'double precision' },
60
61         numeric        => { data_type => 'numeric' },
62         decimal        => { data_type => 'numeric' },
63         'numeric(6,3)' => { data_type => 'numeric', size => [6,3] },
64         'decimal(6,3)' => { data_type => 'numeric', size => [6,3] },
65
66         # Bit String Types
67         'bit varying(2)' => { data_type => 'varbit', size => 2 },
68         'varbit(2)'      => { data_type => 'varbit', size => 2 },
69         'varbit'         => { data_type => 'varbit' },
70         bit              => { data_type => 'bit', size => 1 },
71         'bit(3)'         => { data_type => 'bit', size => 3 },
72
73         # Network Types
74         inet    => { data_type => 'inet' },
75         cidr    => { data_type => 'cidr' },
76         macaddr => { data_type => 'macaddr' },
77
78         # Geometric Types
79         point   => { data_type => 'point' },
80         line    => { data_type => 'line' },
81         lseg    => { data_type => 'lseg' },
82         box     => { data_type => 'box' },
83         path    => { data_type => 'path' },
84         polygon => { data_type => 'polygon' },
85         circle  => { data_type => 'circle' },
86
87         # Character Types
88         'character varying(2)'           => { data_type => 'varchar', size => 2 },
89         'varchar(2)'                     => { data_type => 'varchar', size => 2 },
90         'character(2)'                   => { data_type => 'char', size => 2 },
91         'char(2)'                        => { data_type => 'char', size => 2 },
92         'character'                      => { data_type => 'char', size => 1 },
93         'char'                           => { data_type => 'char', size => 1 },
94         text                             => { data_type => 'text' },
95         # varchar with no size has unlimited size, we rewrite to 'text'
96         varchar                          => { data_type => 'text',
97                                               original => { data_type => 'varchar' } },
98
99         # Datetime Types
100         date                             => { data_type => 'date' },
101         interval                         => { data_type => 'interval' },
102         'interval(2)'                    => { data_type => 'interval', size => 2 },
103         time                             => { data_type => 'time' },
104         'time(2)'                        => { data_type => 'time', size => 2 },
105         'time without time zone'         => { data_type => 'time' },
106         'time(2) without time zone'      => { data_type => 'time', size => 2 },
107         'time with time zone'            => { data_type => 'time with time zone' },
108         'time(2) with time zone'         => { data_type => 'time with time zone', size => 2 },
109         timestamp                        => { data_type => 'timestamp' },
110         'timestamp default now()'
111                                          => { data_type => 'timestamp', default_value => \'current_timestamp',
112                                               original => { default_value => \'now()' } },
113         'timestamp(2)'                   => { data_type => 'timestamp', size => 2 },
114         'timestamp without time zone'    => { data_type => 'timestamp' },
115         'timestamp(2) without time zone' => { data_type => 'timestamp', size => 2 },
116
117         'timestamp with time zone'       => { data_type => 'timestamp with time zone' },
118         'timestamp(2) with time zone'    => { data_type => 'timestamp with time zone', size => 2 },
119
120         # Blob Types
121         bytea => { data_type => 'bytea' },
122
123         # Enum Types
124         pg_loader_test_enum => { data_type => 'enum', extra => { custom_type_name => 'pg_loader_test_enum',
125                                                                  list => [ qw/foo bar baz/] } },
126     },
127     pre_create => [
128         q{
129             CREATE TYPE pg_loader_test_enum AS ENUM (
130                 'foo', 'bar', 'baz'
131             )
132         },
133     ],
134     extra       => {
135         create => [
136             q{
137                 CREATE SCHEMA dbicsl_test
138             },
139             q{
140                 CREATE SEQUENCE dbicsl_test.myseq
141             },
142             q{
143                 CREATE TABLE pg_loader_test1 (
144                     id INTEGER NOT NULL DEFAULT nextval('dbicsl_test.myseq') PRIMARY KEY,
145                     value VARCHAR(100)
146                 )
147             },
148             qq{
149                 COMMENT ON TABLE pg_loader_test1 IS 'The\15\12Table ∑'
150             },
151             qq{
152                 COMMENT ON COLUMN pg_loader_test1.value IS 'The\15\12Column'
153             },
154             q{
155                 CREATE TABLE pg_loader_test2 (
156                     id SERIAL PRIMARY KEY,
157                     value VARCHAR(100)
158                 )
159             },
160             q{
161                 COMMENT ON TABLE pg_loader_test2 IS 'very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long comment'
162             },
163             q{
164                 CREATE SCHEMA "dbicsl-test"
165             },
166             q{
167                 CREATE TABLE "dbicsl-test".pg_loader_test3 (
168                     id SERIAL PRIMARY KEY,
169                     value VARCHAR(100)
170                 )
171             },
172             q{
173                 CREATE TABLE "dbicsl-test".pg_loader_test4 (
174                     id SERIAL PRIMARY KEY,
175                     value VARCHAR(100),
176                     three_id INTEGER UNIQUE REFERENCES "dbicsl-test".pg_loader_test3 (id)
177                 )
178             },
179             q{
180                 CREATE SCHEMA "dbicsl.test"
181             },
182             q{
183                 CREATE TABLE "dbicsl.test".pg_loader_test5 (
184                     id SERIAL PRIMARY KEY,
185                     value VARCHAR(100),
186                     pg_loader_test3_id INTEGER NOT NULL REFERENCES "dbicsl-test".pg_loader_test3 (id)
187                 )
188             },
189             q{
190                 CREATE TABLE "dbicsl.test".pg_loader_test6 (
191                     id SERIAL PRIMARY KEY,
192                     value VARCHAR(100),
193                     five_id INTEGER UNIQUE REFERENCES "dbicsl.test".pg_loader_test5 (id)
194                 )
195             },
196         ],
197         pre_drop_ddl => [
198             'DROP SCHEMA dbicsl_test CASCADE',
199             'DROP SCHEMA "dbicsl-test" CASCADE',
200             'DROP SCHEMA "dbicsl.test" CASCADE',
201             'DROP TYPE pg_loader_test_enum',
202         ],
203         drop  => [ qw/ pg_loader_test1 pg_loader_test2 / ],
204         count => 24,
205         run   => sub {
206             my ($schema, $monikers, $classes) = @_;
207
208             is $schema->source($monikers->{pg_loader_test1})->column_info('id')->{sequence},
209                 'dbicsl_test.myseq',
210                 'qualified sequence detected';
211
212             my $class    = $classes->{pg_loader_test1};
213             my $filename = $schema->_loader->get_dump_filename($class);
214
215             my $code = decode('UTF-8', scalar slurp $filename);
216
217             like $code, qr/^=head1 NAME\n\n^$class - The\nTable ∑\n\n^=cut\n/m,
218                 'table comment';
219
220             like $code, qr/^=head2 value\n\n(.+:.+\n)+\nThe\nColumn\n\n/m,
221                 'column comment and attrs';
222
223             $class    = $classes->{pg_loader_test2};
224             $filename = $schema->_loader->get_dump_filename($class);
225
226             $code = decode('UTF-8', scalar slurp $filename);
227
228             like $code, qr/^=head1 NAME\n\n^$class\n\n=head1 DESCRIPTION\n\n^very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long comment\n\n^=cut\n/m,
229                 'long table comment is in DESCRIPTION';
230
231             lives_and {
232                 no_warnings {
233                     make_schema_at(
234                         'PGMultiSchema',
235                         {
236                             naming => 'current',
237                             preserve_case => 1,
238                             db_schema => ['dbicsl-test', 'dbicsl.test'],
239                         },
240                         [ $dsn, $user, $password, {
241                             on_connect_do  => [ 'SET client_min_messages=WARNING' ],
242                         } ],
243                     );
244                 };
245             }
246 'created dynamic schema for "dbicsl-test" and "dbicsl.test" schemas with no warnings';
247
248             my ($rsrc, %uniqs, $rel_info);
249
250             lives_and {
251                 ok $rsrc = PGMultiSchema->source('PgLoaderTest3');
252             } 'got source for table in schema name with dash';
253
254             is try { $rsrc->column_info('id')->{is_auto_increment} }, 1,
255                 'column in schema name with dash';
256
257             is try { $rsrc->column_info('value')->{data_type} }, 'varchar',
258                 'column in schema name with dash';
259
260             is try { $rsrc->column_info('value')->{size} }, 100,
261                 'column in schema name with dash';
262
263             $rel_info = try { $rsrc->relationship_info('pg_loader_test4') };
264
265             is_deeply $rel_info->{cond}, {
266                 'foreign.three_id' => 'self.id'
267             }, 'relationship in schema name with dash';
268
269             is $rel_info->{attrs}{accessor}, 'single',
270                 'relationship in schema name with dash';
271
272             is $rel_info->{attrs}{join_type}, 'LEFT',
273                 'relationship in schema name with dash';
274
275             lives_and {
276                 ok $rsrc = PGMultiSchema->source('PgLoaderTest4');
277             } 'got source for table in schema name with dash';
278
279             %uniqs = try { $rsrc->unique_constraints };
280
281             is keys %uniqs, 2,
282                 'got unique and primary constraint in schema name with dash';
283
284             lives_and {
285                 ok $rsrc = PGMultiSchema->source('PgLoaderTest5');
286             } 'got source for table in schema name with dot';
287
288             is try { $rsrc->column_info('id')->{is_auto_increment} }, 1,
289                 'column in schema name with dot introspected correctly';
290
291             is try { $rsrc->column_info('value')->{data_type} }, 'varchar',
292                 'column in schema name with dash introspected correctly';
293
294             is try { $rsrc->column_info('value')->{size} }, 100,
295                 'column in schema name with dash introspected correctly';
296
297             $rel_info = try { $rsrc->relationship_info('pg_loader_test6') };
298
299             is_deeply $rel_info->{cond}, {
300                 'foreign.five_id' => 'self.id'
301             }, 'relationship in schema name with dot';
302
303             is $rel_info->{attrs}{accessor}, 'single',
304                 'relationship in schema name with dot';
305
306             is $rel_info->{attrs}{join_type}, 'LEFT',
307                 'relationship in schema name with dot';
308
309             lives_and {
310                 ok $rsrc = PGMultiSchema->source('PgLoaderTest6');
311             } 'got source for table in schema name with dot';
312
313             %uniqs = try { $rsrc->unique_constraints };
314
315             is keys %uniqs, 2,
316                 'got unique and primary constraint in schema name with dot';
317         },
318     },
319 );
320
321 if( !$dsn || !$user ) {
322     $tester->skip_tests('You need to set the DBICTEST_PG_DSN, _USER, and _PASS environment variables');
323 }
324 else {
325     $tester->run_tests();
326 }
327 # vim:et sw=4 sts=4 tw=0: