handle MySQL enums/sets containing elements with single quotes
[dbsrgits/DBIx-Class-Schema-Loader.git] / t / 10_02mysql_common.t
1 use strict;
2 use Test::More;
3 use lib qw(t/lib);
4 use dbixcsl_common_tests;
5
6 my $dsn         = $ENV{DBICTEST_MYSQL_DSN} || '';
7 my $user        = $ENV{DBICTEST_MYSQL_USER} || '';
8 my $password    = $ENV{DBICTEST_MYSQL_PASS} || '';
9 my $test_innodb = $ENV{DBICTEST_MYSQL_INNODB} || 0;
10
11 my $skip_rels_msg = 'You need to set the DBICTEST_MYSQL_INNODB environment variable to test relationships.';
12
13 my $innodb = $test_innodb ? q{Engine=InnoDB} : '';
14
15 my $tester = dbixcsl_common_tests->new(
16     vendor           => 'Mysql',
17     auto_inc_pk      => 'INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT',
18     innodb           => $innodb,
19     dsn              => $dsn,
20     user             => $user,
21     password         => $password,
22     connect_info_opts=> { on_connect_call => 'set_strict_mode' },
23     loader_options   => { preserve_case => 1 },
24     skip_rels        => $test_innodb ? 0 : $skip_rels_msg,
25     quote_char       => '`',
26     no_inline_rels   => 1,
27     no_implicit_rels => 1,
28     data_types  => {
29         # http://dev.mysql.com/doc/refman/5.5/en/data-type-overview.html
30         # Numeric Types
31         'bit'         => { data_type => 'bit', size => 1 },
32         'bit(11)'     => { data_type => 'bit', size => 11 },
33
34         'bool'        => { data_type => 'tinyint' },
35         'boolean'     => { data_type => 'tinyint' },
36         'tinyint'     => { data_type => 'tinyint' },
37         'tinyint unsigned'
38                       => { data_type => 'tinyint',   extra => { unsigned => 1 } },
39         'smallint'    => { data_type => 'smallint' },
40         'smallint unsigned'
41                       => { data_type => 'smallint',  extra => { unsigned => 1 } },
42         'mediumint'   => { data_type => 'mediumint' },
43         'mediumint unsigned'
44                       => { data_type => 'mediumint', extra => { unsigned => 1 } },
45         'int'         => { data_type => 'integer' },
46         'int unsigned'
47                       => { data_type => 'integer',   extra => { unsigned => 1 } },
48         'integer'     => { data_type => 'integer' },
49         'integer unsigned'
50                       => { data_type => 'integer',   extra => { unsigned => 1 } },
51         'integer not null'
52                       => { data_type => 'integer' },
53         'bigint'      => { data_type => 'bigint' },
54         'bigint unsigned'
55                       => { data_type => 'bigint',    extra => { unsigned => 1 } },
56
57         'serial'      => { data_type => 'bigint', is_auto_increment => 1, extra => { unsigned => 1 } },
58
59         'float'       => { data_type => 'float' },
60         'float unsigned'
61                       => { data_type => 'float',     extra => { unsigned => 1 } },
62         'double'      => { data_type => 'double precision' },
63         'double unsigned'
64                       => { data_type => 'double precision', extra => { unsigned => 1 } },
65         'double precision' =>
66                          { data_type => 'double precision' },
67         'double precision unsigned'
68                       => { data_type => 'double precision', extra => { unsigned => 1 } },
69
70         # we skip 'real' because its alias depends on the 'REAL AS FLOAT' setting
71
72         'float(2)'    => { data_type => 'float' },
73         'float(24)'   => { data_type => 'float' },
74         'float(25)'   => { data_type => 'double precision' },
75
76         'float(3,3)'  => { data_type => 'float', size => [3,3] },
77         'double(3,3)' => { data_type => 'double precision', size => [3,3] },
78         'double precision(3,3)'
79                       => { data_type => 'double precision', size => [3,3] },
80
81         'decimal'     => { data_type => 'decimal' },
82         'decimal unsigned'
83                       => { data_type => 'decimal', extra => { unsigned => 1 } },
84         'dec'         => { data_type => 'decimal' },
85         'numeric'     => { data_type => 'decimal' },
86         'fixed'       => { data_type => 'decimal' },
87
88         'decimal(3)'   => { data_type => 'decimal', size => [3,0] },
89
90         'decimal(3,3)' => { data_type => 'decimal', size => [3,3] },
91         'dec(3,3)'     => { data_type => 'decimal', size => [3,3] },
92         'numeric(3,3)' => { data_type => 'decimal', size => [3,3] },
93         'fixed(3,3)'   => { data_type => 'decimal', size => [3,3] },
94
95         # Date and Time Types
96         'date'        => { data_type => 'date', datetime_undef_if_invalid => 1 },
97         'datetime'    => { data_type => 'datetime', datetime_undef_if_invalid => 1 },
98         'timestamp default current_timestamp'
99                       => { data_type => 'timestamp', default_value => \'current_timestamp', datetime_undef_if_invalid => 1 },
100         'time'        => { data_type => 'time' },
101         'year'        => { data_type => 'year' },
102         'year(4)'     => { data_type => 'year' },
103         'year(2)'     => { data_type => 'year', size => 2 },
104
105         # String Types
106         'char'         => { data_type => 'char',      size => 1  },
107         'char(11)'     => { data_type => 'char',      size => 11 },
108         'varchar(20)'  => { data_type => 'varchar',   size => 20 },
109         'binary'       => { data_type => 'binary',    size => 1  },
110         'binary(11)'   => { data_type => 'binary',    size => 11 },
111         'varbinary(20)'=> { data_type => 'varbinary', size => 20 },
112
113         'tinyblob'    => { data_type => 'tinyblob' },
114         'tinytext'    => { data_type => 'tinytext' },
115         'blob'        => { data_type => 'blob' },
116
117         # text(M) types will map to the appropriate type, length is not stored
118         'text'        => { data_type => 'text' },
119
120         'mediumblob'  => { data_type => 'mediumblob' },
121         'mediumtext'  => { data_type => 'mediumtext' },
122         'longblob'    => { data_type => 'longblob' },
123         'longtext'    => { data_type => 'longtext' },
124
125         "enum('foo','bar','baz')"
126                       => { data_type => 'enum', extra => { list => [qw/foo bar baz/] } },
127         "enum('foo \\'bar\\' baz', 'foo ''bar'' quux')"
128                       => { data_type => 'enum', extra => { list => [q{foo 'bar' baz}, q{foo 'bar' quux}] } },
129         "set('foo \\'bar\\' baz', 'foo ''bar'' quux')"
130                       => { data_type => 'set', extra => { list => [q{foo 'bar' baz}, q{foo 'bar' quux}] } },
131         "set('foo','bar','baz')"
132                       => { data_type => 'set',  extra => { list => [qw/foo bar baz/] } },
133
134         # RT#68717
135         "enum('11,10 (<500)/0 DUN','4,90 (<120)/0 EUR') NOT NULL default '11,10 (<500)/0 DUN'"
136                       => { data_type => 'enum', extra => { list => ['11,10 (<500)/0 DUN', '4,90 (<120)/0 EUR'] }, default_value => '11,10 (<500)/0 DUN' },
137         "set('11_10 (<500)/0 DUN','4_90 (<120)/0 EUR') NOT NULL default '11_10 (<500)/0 DUN'"
138                       => { data_type => 'set', extra => { list => ['11_10 (<500)/0 DUN', '4_90 (<120)/0 EUR'] }, default_value => '11_10 (<500)/0 DUN' },
139         "enum('19,90 (<500)/0 EUR','4,90 (<120)/0 EUR','7,90 (<200)/0 CHF','300 (<6000)/0 CZK','4,90 (<100)/0 EUR','39 (<900)/0 DKK','299 (<5000)/0 EEK','9,90 (<250)/0 EUR','3,90 (<100)/0 GBP','3000 (<70000)/0 HUF','4000 (<70000)/0 JPY','13,90 (<200)/0 LVL','99 (<2500)/0 NOK','39 (<1000)/0 PLN','1000 (<20000)/0 RUB','49 (<2500)/0 SEK','29 (<600)/0 USD','19,90 (<600)/0 EUR','0 EUR','0 CHF') NOT NULL default '19,90 (<500)/0 EUR'"
140                       => { data_type => 'enum', extra => { list => ['19,90 (<500)/0 EUR','4,90 (<120)/0 EUR','7,90 (<200)/0 CHF','300 (<6000)/0 CZK','4,90 (<100)/0 EUR','39 (<900)/0 DKK','299 (<5000)/0 EEK','9,90 (<250)/0 EUR','3,90 (<100)/0 GBP','3000 (<70000)/0 HUF','4000 (<70000)/0 JPY','13,90 (<200)/0 LVL','99 (<2500)/0 NOK','39 (<1000)/0 PLN','1000 (<20000)/0 RUB','49 (<2500)/0 SEK','29 (<600)/0 USD','19,90 (<600)/0 EUR','0 EUR','0 CHF'] }, default_value => '19,90 (<500)/0 EUR' },
141     },
142     extra => {
143         create => [
144             qq{
145                 CREATE TABLE `mysql_loader-test1` (
146                     id INT AUTO_INCREMENT PRIMARY KEY,
147                     value varchar(100)
148                 ) $innodb
149             },
150             q{
151                 CREATE VIEW mysql_loader_test2 AS SELECT * FROM `mysql_loader-test1`
152             },
153             # RT#68717
154             qq{
155                 CREATE TABLE `mysql_loader_test3` (
156                   `ISO3_code` char(3) NOT NULL default '',
157                   `lang_pref` enum('de','en','fr','nl','dk','es','se') NOT NULL,
158                   `vat` decimal(4,2) default '16.00',
159                   `price_group` enum('EUR_DEFAULT','GBP_GBR','EUR_AUT_BEL_FRA_IRL_NLD','EUR_DNK_SWE','EUR_AUT','EUR_BEL','EUR_FIN','EUR_FRA','EUR_IRL','EUR_NLD','EUR_DNK','EUR_POL','EUR_PRT','EUR_SWE','CHF_CHE','DKK_DNK','SEK_SWE','NOK_NOR','USD_USA','CZK_CZE','PLN_POL','RUB_RUS','HUF_HUN','SKK_SVK','JPY_JPN','LVL_LVA','ROL_ROU','EEK_EST') NOT NULL default 'EUR_DEFAULT',
160                   `del_group` enum('19,90 (<500)/0 EUR','4,90 (<120)/0 EUR','7,90 (<200)/0 CHF','300 (<6000)/0 CZK','4,90 (<100)/0 EUR','39 (<900)/0 DKK','299 (<5000)/0 EEK','9,90 (<250)/0 EUR','3,90 (<100)/0 GBP','3000 (<70000)/0 HUF','4000 (<70000)/0 JPY','13,90 (<200)/0 LVL','99 (<2500)/0 NOK','39 (<1000)/0 PLN','1000 (<20000)/0 RUB','49 (<2500)/0 SEK','29 (<600)/0 USD','19,90 (<600)/0 EUR','0 EUR','0 CHF') NOT NULL default '19,90 (<500)/0 EUR',
161                   `express_del_group` enum('NO','39 EUR (EXPRESS)','59 EUR (EXPRESS)','79 CHF (EXPRESS)','49 EUR (EXPRESS)','990 CZK (EXPRESS)','19,9 EUR (EXPRESS)','290 DKK (EXPRESS)','990 EEK (EXPRESS)','39 GBP (EXPRESS)','14000 HUF (EXPRESS)','49 LVL (EXPRESS)','590 NOK (EXPRESS)','250 PLN (EXPRESS)','490 SEK (EXPRESS)') NOT NULL default 'NO',
162                   `pmethod` varchar(255) NOT NULL default 'VISA,MASTER',
163                   `delivery_time` varchar(5) default NULL,
164                   `express_delivery_time` varchar(5) default NULL,
165                   `eu` int(1) default '0',
166                   `cod_costs` varchar(12) default NULL,
167                   PRIMARY KEY (`ISO3_code`)
168                 ) $innodb
169             },
170         ],
171         pre_drop_ddl => [ 'DROP VIEW mysql_loader_test2', ],
172         drop => [ 'mysql_loader-test1', 'mysql_loader_test3' ],
173         count => 3,
174         run => sub {
175             my ($schema, $monikers, $classes) = @_;
176
177             is $monikers->{'mysql_loader-test1'}, 'MysqlLoaderTest1',
178                 'table with dash correctly monikerized';
179
180             my $rsrc = $schema->source('MysqlLoaderTest2');
181
182             is $rsrc->column_info('value')->{data_type}, 'varchar',
183                 'view introspected successfully';
184
185             $rsrc = $schema->source('MysqlLoaderTest3');
186
187             is_deeply $rsrc->column_info('del_group')->{extra}{list}, ['19,90 (<500)/0 EUR','4,90 (<120)/0 EUR','7,90 (<200)/0 CHF','300 (<6000)/0 CZK','4,90 (<100)/0 EUR','39 (<900)/0 DKK','299 (<5000)/0 EEK','9,90 (<250)/0 EUR','3,90 (<100)/0 GBP','3000 (<70000)/0 HUF','4000 (<70000)/0 JPY','13,90 (<200)/0 LVL','99 (<2500)/0 NOK','39 (<1000)/0 PLN','1000 (<20000)/0 RUB','49 (<2500)/0 SEK','29 (<600)/0 USD','19,90 (<600)/0 EUR','0 EUR','0 CHF'],
188                 'hairy enum introspected correctly';
189         },
190     },
191 );
192
193 if( !$dsn || !$user ) {
194     $tester->skip_tests('You need to set the DBICTEST_MYSQL_DSN, _USER, and _PASS environment variables');
195 }
196 else {
197     diag $skip_rels_msg if not $test_innodb;
198     $tester->run_tests();
199 }
200
201 # vim:et sts=4 sw=4 tw=0: