b10dfa6654913cae063efd40ec179f642bc735dc
[dbsrgits/DBIx-Class-Schema-Loader.git] / t / 12pg_common.t
1 use strict;
2 use lib qw(t/lib);
3 use dbixcsl_common_tests;
4 use Test::More;
5 use List::MoreUtils 'apply';
6
7 my $dsn      = $ENV{DBICTEST_PG_DSN} || '';
8 my $user     = $ENV{DBICTEST_PG_USER} || '';
9 my $password = $ENV{DBICTEST_PG_PASS} || '';
10
11 my $tester = dbixcsl_common_tests->new(
12     vendor      => 'Pg',
13     auto_inc_pk => 'SERIAL NOT NULL PRIMARY KEY',
14     default_function => 'now()',
15     dsn         => $dsn,
16     user        => $user,
17     password    => $password,
18     data_types  => {
19         'bigint'    => { size => undef, data_type => 'bigint' },
20         'int8'      => { size => undef, data_type => 'int8' },
21         'bigserial' => { size => undef, data_type => 'bigserial' },
22         'serial8'   => { size => undef, data_type => 'serial8' },
23         'bit'       => { size => undef, data_type => 'bit' },
24         'boolean'   => { size => undef, data_type => 'boolean' },
25         'bool'      => { size => undef, data_type => 'bool' },
26         'box'       => { size => undef, data_type => 'box' },
27         'bytea'     => { size => undef, data_type => 'bytea' },
28         'cidr'      => { size => undef, data_type => 'cidr' },
29         'circle'    => { size => undef, data_type => 'circle' },
30         'date'      => { size => undef, data_type => 'date' },
31         'double precision' => { size => undef, data_type => 'double precision' },
32         'float8'      => { size => undef, data_type => 'float8' },
33         'inet'        => { size => undef, data_type => 'inet' },
34         'integer'     => { size => undef, data_type => 'integer' },
35         'int'         => { size => undef, data_type => 'int' },
36         'int4'        => { size => undef, data_type => 'int4' },
37         'interval'    => { size => undef, data_type => 'interval' },
38         'interval(2)' => { size => 2, data_type => 'interval' },
39         'line'        => { size => undef, data_type => 'line' },
40         'lseg'        => { size => undef, data_type => 'lseg' },
41         'macaddr'     => { size => undef, data_type => 'macaddr' },
42         'money'       => { size => undef, data_type => 'money' },
43         'path'        => { size => undef, data_type => 'path' },
44         'point'       => { size => undef, data_type => 'point' },
45         'polygon'     => { size => undef, data_type => 'polygon' },
46         'real'        => { size => undef, data_type => 'real' },
47         'float4'      => { size => undef, data_type => 'float4' },
48         'smallint'    => { size => undef, data_type => 'smallint' },
49         'int2'        => { size => undef, data_type => 'int2' },
50         'serial'      => { size => undef, data_type => 'serial' },
51         'serial4'     => { size => undef, data_type => 'serial4' },
52         'text'        => { size => undef, data_type => 'text' },
53         'time'        => { size => undef, data_type => 'time' },
54         'time(2)'     => { size => 2, data_type => 'time' },
55         'time without time zone'         => { size => undef, data_type => 'time without time zone' },
56         'time(2) without time zone'      => { size => 2, data_type => 'time without time zone' },
57         'time with time zone'            => { size => undef, data_type => 'time with time zone' },
58         'time(2) with time zone'         => { size => 2, data_type => 'time with time zone' },
59         'timestamp'                      => { size => undef, data_type => 'timestamp' },
60         'timestamp(2)'                   => { size => 2, data_type => 'timestamp' },
61         'timestamp without time zone'    => { size => undef, data_type => 'timestamp without time zone' },
62         'timestamp(2) without time zone' => { size => 2, data_type => 'timestamp without time zone' },
63         'timestamp with time zone'       => { size => undef, data_type => 'timestamp with time zone' },
64         'timestamp(2) with time zone'    => { size => 2, data_type => 'timestamp with time zone' },
65         'bit varying(2)'                 => { size => 2, data_type => 'bit varying' },
66         'varbit(2)'                      => { size => 2, data_type => 'varbit' },
67         'character varying(2)'           => { size => 2, data_type => 'character varying' },
68         'varchar(2)'                     => { size => 2, data_type => 'varchar' },
69         'character(2)'                   => { size => 2, data_type => 'character' },
70         'char(2)'                        => { size => 2, data_type => 'char' },
71         'numeric(6, 3)'                  => { size => [6,3], data_type => 'numeric' },
72         'decimal(6, 3)'                  => { size => [6,3], data_type => 'decimal' },
73     },
74     extra       => {
75         create => [
76             q{
77                 CREATE TABLE pg_loader_test1 (
78                     id SERIAL NOT NULL PRIMARY KEY,
79                     value VARCHAR(100)
80                 )
81             },
82             q{
83                 COMMENT ON TABLE pg_loader_test1 IS 'The Table'
84             },
85             q{
86                 COMMENT ON COLUMN pg_loader_test1.value IS 'The Column'
87             },
88             q{
89                 CREATE TABLE pg_loader_test2 (
90                     id SERIAL NOT NULL PRIMARY KEY,
91                     value VARCHAR(100)
92                 )
93             },
94             q{
95                 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'
96             },
97             # Test to make sure data_types that don't need a size => don't
98             # have one and check varying types have the correct size.
99             q{
100                 CREATE TABLE pg_loader_test3 (
101                     id SERIAL NOT NULL PRIMARY KEY,
102                     a_bigint BIGINT,
103                     an_int8 INT8,
104                     a_bigserial BIGSERIAL,
105                     a_serial8 SERIAL8,
106                     a_bit BIT,
107                     a_boolean BOOLEAN,
108                     a_bool BOOL,
109                     a_box BOX,
110                     a_bytea BYTEA,
111                     a_cidr CIDR,
112                     a_circle CIRCLE,
113                     a_date DATE,
114                     a_double_precision DOUBLE PRECISION,
115                     a_float8 FLOAT8,
116                     an_inet INET,
117                     an_integer INTEGER,
118                     an_int INT,
119                     an_int4 INT4,
120                     an_interval INTERVAL,
121                     an_interval_with_precision INTERVAL(2),
122                     a_line LINE,
123                     an_lseg LSEG,
124                     a_macaddr MACADDR,
125                     a_money MONEY,
126                     a_path PATH,
127                     a_point POINT,
128                     a_polygon POLYGON,
129                     a_real REAL,
130                     a_float4 FLOAT4,
131                     a_smallint SMALLINT,
132                     an_int2 INT2,
133                     a_serial SERIAL,
134                     a_serial4 SERIAL4,
135                     a_text TEXT,
136                     a_time TIME,
137                     a_time_with_precision TIME(2),
138                     a_time_without_time_zone TIME WITHOUT TIME ZONE,
139                     a_time_without_time_zone_with_precision TIME(2) WITHOUT TIME ZONE,
140                     a_time_with_time_zone TIME WITH TIME ZONE,
141                     a_time_with_time_zone_with_precision TIME(2) WITH TIME ZONE,
142                     a_timestamp TIMESTAMP,
143                     a_timestamp_with_precision TIMESTAMP(2),
144                     a_timestamp_without_time_zone TIMESTAMP WITHOUT TIME ZONE,
145                     a_timestamp_without_time_zone_with_precision TIMESTAMP(2) WITHOUT TIME ZONE,
146                     a_timestamp_with_time_zone TIMESTAMP WITH TIME ZONE,
147                     a_timestamp_with_time_zone_with_precision TIMESTAMP(2) WITH TIME ZONE,
148                     a_bit_varying_with_precision BIT VARYING(2),
149                     a_varbit_with_precision VARBIT(2),
150                     a_character_varying_with_precision CHARACTER VARYING(2),
151                     a_varchar_with_precision VARCHAR(2),
152                     a_character_with_precision CHARACTER(2),
153                     a_char_with_precision CHAR(2),
154                     the_numeric NUMERIC(6, 3),
155                     the_decimal DECIMAL(6, 3)
156                 )
157             },
158         ],
159         drop  => [ qw/ pg_loader_test1 pg_loader_test2 pg_loader_test3 / ],
160         count => 57,
161         run   => sub {
162             my ($schema, $monikers, $classes) = @_;
163
164             my $class    = $classes->{pg_loader_test1};
165             my $filename = $schema->_loader->_get_dump_filename($class);
166
167             my $code = do {
168                 local ($/, @ARGV) = (undef, $filename);
169                 <>;
170             };
171
172             like $code, qr/^=head1 NAME\n\n^$class - The Table\n\n^=cut\n/m,
173                 'table comment';
174
175             like $code, qr/^=head2 value\n\n(.+:.+\n)+\nThe Column\n\n/m,
176                 'column comment and attrs';
177
178             $class    = $classes->{pg_loader_test2};
179             $filename = $schema->_loader->_get_dump_filename($class);
180
181             $code = do {
182                 local ($/, @ARGV) = (undef, $filename);
183                 <>;
184             };
185
186             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,
187                 'long table comment is in DESCRIPTION';
188
189             my $rsrc = $schema->resultset($monikers->{pg_loader_test3})
190                 ->result_source;
191             my @type_columns = grep /^a/, $rsrc->columns;
192             my @without_precision = grep !/_with_precision\z/, @type_columns;
193             my @with_precision    = grep  /_with_precision\z/, @type_columns;
194             my %with_precision;
195             @with_precision{
196                 apply { s/_with_precision\z// } @with_precision
197             } = ();
198
199             for my $col (@without_precision) {
200                 my ($data_type) = $col =~ /^an?_(.*)/;
201                 ($data_type = uc $data_type) =~ s/_/ /g;
202
203                 ok((not exists $rsrc->column_info($col)->{size}),
204                     "$data_type " .
205                     (exists $with_precision{$col} ? 'without precision ' : '') .
206                     "has no 'size' column_info")
207                 or diag "size is ".$rsrc->column_info($col)->{size}."\n";
208             }
209
210             for my $col (@with_precision) {
211                 my ($data_type) = $col =~ /^an?_(.*)_with_precision\z/;
212                 ($data_type = uc $data_type) =~ s/_/ /g;
213                 my $size = $rsrc->column_info($col)->{size};
214
215                 is $size, 2,
216                   "$data_type with precision has a correct 'size' column_info";
217             }
218
219             is_deeply $rsrc->column_info('the_numeric')->{size}, [6,3],
220                 'size for NUMERIC(precision, scale) is correct';
221
222             is_deeply $rsrc->column_info('the_decimal')->{size}, [6,3],
223                 'size for DECIMAL(precision, scale) is correct';
224         },
225     },
226 );
227
228 if( !$dsn || !$user ) {
229     $tester->skip_tests('You need to set the DBICTEST_PG_DSN, _USER, and _PASS environment variables');
230 }
231 else {
232     $tester->run_tests();
233 }