4 use DBIx::Class::Schema::Loader 'make_schema_at';
5 use DBIx::Class::Schema::Loader::Utils qw/no_warnings slurp_file/;
9 use File::Path 'rmtree';
13 use dbixcsl_common_tests ();
14 use dbixcsl_test_dir '$tdir';
16 use constant EXTRA_DUMP_DIR => "$tdir/pg_extra_dump";
18 my $dsn = $ENV{DBICTEST_PG_DSN} || '';
19 my $user = $ENV{DBICTEST_PG_USER} || '';
20 my $password = $ENV{DBICTEST_PG_PASS} || '';
22 my $tester = dbixcsl_common_tests->new(
24 auto_inc_pk => 'SERIAL NOT NULL PRIMARY KEY',
27 password => $password,
28 loader_options => { preserve_case => 1 },
29 connect_info_opts => {
31 on_connect_do => [ 'SET client_min_messages=WARNING' ],
35 # http://www.postgresql.org/docs/7.4/interactive/datatype.html
38 boolean => { data_type => 'boolean' },
39 bool => { data_type => 'boolean' },
41 => { data_type => 'boolean', default_value => \'false' },
43 => { data_type => 'boolean', default_value => \'true' },
44 'bool default 0::bool'
45 => { data_type => 'boolean', default_value => \'false' },
46 'bool default 1::bool'
47 => { data_type => 'boolean', default_value => \'true' },
49 bigint => { data_type => 'bigint' },
50 int8 => { data_type => 'bigint' },
51 bigserial => { data_type => 'bigint', is_auto_increment => 1 },
52 serial8 => { data_type => 'bigint', is_auto_increment => 1 },
53 integer => { data_type => 'integer' },
54 int => { data_type => 'integer' },
55 int4 => { data_type => 'integer' },
56 serial => { data_type => 'integer', is_auto_increment => 1 },
57 serial4 => { data_type => 'integer', is_auto_increment => 1 },
58 smallint => { data_type => 'smallint' },
59 int2 => { data_type => 'smallint' },
61 money => { data_type => 'money' },
63 'double precision' => { data_type => 'double precision' },
64 float8 => { data_type => 'double precision' },
65 real => { data_type => 'real' },
66 float4 => { data_type => 'real' },
67 'float(24)' => { data_type => 'real' },
68 'float(25)' => { data_type => 'double precision' },
69 'float(53)' => { data_type => 'double precision' },
70 float => { data_type => 'double precision' },
72 numeric => { data_type => 'numeric' },
73 decimal => { data_type => 'numeric' },
74 'numeric(6,3)' => { data_type => 'numeric', size => [6,3] },
75 'decimal(6,3)' => { data_type => 'numeric', size => [6,3] },
78 'bit varying(2)' => { data_type => 'varbit', size => 2 },
79 'varbit(2)' => { data_type => 'varbit', size => 2 },
80 'varbit' => { data_type => 'varbit' },
81 bit => { data_type => 'bit', size => 1 },
82 'bit(3)' => { data_type => 'bit', size => 3 },
85 inet => { data_type => 'inet' },
86 cidr => { data_type => 'cidr' },
87 macaddr => { data_type => 'macaddr' },
90 point => { data_type => 'point' },
91 line => { data_type => 'line' },
92 lseg => { data_type => 'lseg' },
93 box => { data_type => 'box' },
94 path => { data_type => 'path' },
95 polygon => { data_type => 'polygon' },
96 circle => { data_type => 'circle' },
99 'character varying(2)' => { data_type => 'varchar', size => 2 },
100 'varchar(2)' => { data_type => 'varchar', size => 2 },
101 'character(2)' => { data_type => 'char', size => 2 },
102 'char(2)' => { data_type => 'char', size => 2 },
103 # check that default null is correctly rewritten
104 'char(3) default null' => { data_type => 'char', size => 3,
105 default_value => \'null' },
106 'character' => { data_type => 'char', size => 1 },
107 'char' => { data_type => 'char', size => 1 },
108 text => { data_type => 'text' },
109 # varchar with no size has unlimited size, we rewrite to 'text'
110 varchar => { data_type => 'text',
111 original => { data_type => 'varchar' } },
112 # check default null again (to make sure ref is safe)
113 'varchar(3) default null' => { data_type => 'varchar', size => 3,
114 default_value => \'null' },
117 date => { data_type => 'date' },
118 interval => { data_type => 'interval' },
119 'interval(2)' => { data_type => 'interval', size => 2 },
120 time => { data_type => 'time' },
121 'time(2)' => { data_type => 'time', size => 2 },
122 'time without time zone' => { data_type => 'time' },
123 'time(2) without time zone' => { data_type => 'time', size => 2 },
124 'time with time zone' => { data_type => 'time with time zone' },
125 'time(2) with time zone' => { data_type => 'time with time zone', size => 2 },
126 timestamp => { data_type => 'timestamp' },
127 'timestamp default now()'
128 => { data_type => 'timestamp', default_value => \'current_timestamp',
129 original => { default_value => \'now()' } },
130 'timestamp(2)' => { data_type => 'timestamp', size => 2 },
131 'timestamp without time zone' => { data_type => 'timestamp' },
132 'timestamp(2) without time zone' => { data_type => 'timestamp', size => 2 },
134 'timestamp with time zone' => { data_type => 'timestamp with time zone' },
135 'timestamp(2) with time zone' => { data_type => 'timestamp with time zone', size => 2 },
138 bytea => { data_type => 'bytea' },
141 pg_loader_test_enum => { data_type => 'enum', extra => { custom_type_name => 'pg_loader_test_enum',
142 list => [ qw/foo bar baz/] } },
146 CREATE TYPE pg_loader_test_enum AS ENUM (
154 CREATE SCHEMA dbicsl_test
157 CREATE SEQUENCE dbicsl_test.myseq
160 CREATE TABLE pg_loader_test1 (
161 id INTEGER NOT NULL DEFAULT nextval('dbicsl_test.myseq') PRIMARY KEY,
166 COMMENT ON TABLE pg_loader_test1 IS 'The\15\12Table ∑'
169 COMMENT ON COLUMN pg_loader_test1.value IS 'The\15\12Column'
172 CREATE TABLE pg_loader_test2 (
173 id SERIAL PRIMARY KEY,
178 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'
181 CREATE SCHEMA "dbicsl-test"
184 CREATE TABLE "dbicsl-test".pg_loader_test4 (
185 id SERIAL PRIMARY KEY,
190 CREATE TABLE "dbicsl-test".pg_loader_test5 (
191 id SERIAL PRIMARY KEY,
193 four_id INTEGER UNIQUE REFERENCES "dbicsl-test".pg_loader_test4 (id)
197 CREATE SCHEMA "dbicsl.test"
200 CREATE TABLE "dbicsl.test".pg_loader_test6 (
201 id SERIAL PRIMARY KEY,
203 pg_loader_test4_id INTEGER REFERENCES "dbicsl-test".pg_loader_test4 (id)
207 CREATE TABLE "dbicsl.test".pg_loader_test7 (
208 id SERIAL PRIMARY KEY,
210 six_id INTEGER UNIQUE REFERENCES "dbicsl.test".pg_loader_test6 (id)
214 CREATE TABLE "dbicsl-test".pg_loader_test8 (
215 id SERIAL PRIMARY KEY,
217 pg_loader_test7_id INTEGER REFERENCES "dbicsl.test".pg_loader_test7 (id)
222 'DROP SCHEMA dbicsl_test CASCADE',
223 'DROP SCHEMA "dbicsl-test" CASCADE',
224 'DROP SCHEMA "dbicsl.test" CASCADE',
225 'DROP TYPE pg_loader_test_enum',
227 drop => [ qw/ pg_loader_test1 pg_loader_test2 / ],
230 my ($schema, $monikers, $classes) = @_;
232 is $schema->source($monikers->{pg_loader_test1})->column_info('id')->{sequence},
234 'qualified sequence detected';
236 my $class = $classes->{pg_loader_test1};
237 my $filename = $schema->loader->get_dump_filename($class);
239 my $code = slurp_file $filename;
241 like $code, qr/^=head1 NAME\n\n^$class - The\nTable ∑\n\n^=cut\n/m,
244 like $code, qr/^=head2 value\n\n(.+:.+\n)+\nThe\nColumn\n\n/m,
245 'column comment and attrs';
247 $class = $classes->{pg_loader_test2};
248 $filename = $schema->loader->get_dump_filename($class);
250 $code = slurp_file $filename;
252 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,
253 'long table comment is in DESCRIPTION';
255 foreach my $db_schema (['dbicsl-test', 'dbicsl.test'], '%') {
257 rmtree EXTRA_DUMP_DIR;
260 local $SIG{__WARN__} = sub {
261 push @warns, $_[0] unless $_[0] =~ /\bcollides\b/;
268 db_schema => $db_schema,
270 dump_directory => EXTRA_DUMP_DIR,
273 [ $dsn, $user, $password, {
274 on_connect_do => [ 'SET client_min_messages=WARNING' ],
278 diag join "\n", @warns if @warns;
281 } 'dumped schema for "dbicsl-test" and "dbicsl.test" schemas with no warnings';
283 my ($test_schema, $rsrc, $rs, $row, %uniqs, $rel_info);
286 ok $test_schema = PGMultiSchema->connect($dsn, $user, $password, {
287 on_connect_do => [ 'SET client_min_messages=WARNING' ],
289 } 'connected test schema';
292 ok $rsrc = $test_schema->source('PgLoaderTest4');
293 } 'got source for table in schema name with dash';
295 is try { $rsrc->column_info('id')->{is_auto_increment} }, 1,
296 'column in schema name with dash';
298 is try { $rsrc->column_info('value')->{data_type} }, 'varchar',
299 'column in schema name with dash';
301 is try { $rsrc->column_info('value')->{size} }, 100,
302 'column in schema name with dash';
305 ok $rs = $test_schema->resultset('PgLoaderTest4');
306 } 'got resultset for table in schema name with dash';
309 ok $row = $rs->create({ value => 'foo' });
310 } 'executed SQL on table in schema name with dash';
312 $rel_info = try { $rsrc->relationship_info('pg_loader_test5') };
314 is_deeply $rel_info->{cond}, {
315 'foreign.four_id' => 'self.id'
316 }, 'relationship in schema name with dash';
318 is $rel_info->{attrs}{accessor}, 'single',
319 'relationship in schema name with dash';
321 is $rel_info->{attrs}{join_type}, 'LEFT',
322 'relationship in schema name with dash';
325 ok $rsrc = $test_schema->source('PgLoaderTest5');
326 } 'got source for table in schema name with dash';
328 %uniqs = try { $rsrc->unique_constraints };
331 'got unique and primary constraint in schema name with dash';
334 ok $rsrc = $test_schema->source('PgLoaderTest6');
335 } 'got source for table in schema name with dot';
337 is try { $rsrc->column_info('id')->{is_auto_increment} }, 1,
338 'column in schema name with dot introspected correctly';
340 is try { $rsrc->column_info('value')->{data_type} }, 'varchar',
341 'column in schema name with dot introspected correctly';
343 is try { $rsrc->column_info('value')->{size} }, 100,
344 'column in schema name with dot introspected correctly';
347 ok $rs = $test_schema->resultset('PgLoaderTest6');
348 } 'got resultset for table in schema name with dot';
351 ok $row = $rs->create({ value => 'foo' });
352 } 'executed SQL on table in schema name with dot';
354 $rel_info = try { $rsrc->relationship_info('pg_loader_test7') };
356 is_deeply $rel_info->{cond}, {
357 'foreign.six_id' => 'self.id'
358 }, 'relationship in schema name with dot';
360 is $rel_info->{attrs}{accessor}, 'single',
361 'relationship in schema name with dot';
363 is $rel_info->{attrs}{join_type}, 'LEFT',
364 'relationship in schema name with dot';
367 ok $rsrc = $test_schema->source('PgLoaderTest7');
368 } 'got source for table in schema name with dot';
370 %uniqs = try { $rsrc->unique_constraints };
373 'got unique and primary constraint in schema name with dot';
376 ok $test_schema->source('PgLoaderTest6')
377 ->has_relationship('pg_loader_test4');
378 } 'cross-schema relationship in multi-db_schema';
381 ok $test_schema->source('PgLoaderTest4')
382 ->has_relationship('pg_loader_test6s');
383 } 'cross-schema relationship in multi-db_schema';
386 ok $test_schema->source('PgLoaderTest8')
387 ->has_relationship('pg_loader_test7');
388 } 'cross-schema relationship in multi-db_schema';
391 ok $test_schema->source('PgLoaderTest7')
392 ->has_relationship('pg_loader_test8s');
393 } 'cross-schema relationship in multi-db_schema';
399 if( !$dsn || !$user ) {
400 $tester->skip_tests('You need to set the DBICTEST_PG_DSN, _USER, and _PASS environment variables');
403 $tester->run_tests();
407 rmtree EXTRA_DUMP_DIR unless $ENV{SCHEMA_LOADER_TESTS_NOCLEANUP};
409 # vim:et sw=4 sts=4 tw=0: