fix up use and don't plan
[dbsrgits/SQL-Translator-2.0-ish.git] / t / 02mysql-parser.t
CommitLineData
dbca887e 1use strict;
2e718597 2use warnings;
dbca887e 3use Test::More;
4use SQL::Translator;
dbca887e 5use SQL::Translator::Constants qw(:sqlt_types :sqlt_constants);
dbca887e 6
7{
8 my $tr = SQL::Translator->new({ from => 'MySQL' });
9 my $data = q|create table "sessions" (
10 id char(32) not null default '0' primary key,
11 a_session text,
12 ssn varchar(12) unique key,
13 age int key,
14 fulltext key `session_fulltext` (a_session)
15 );|;
16
17 #my $val = $tr->parse();
18# my $val = $tr->parse($data);
19 my $schema = $tr->parse($data);
20 is( $schema->is_valid, 1, 'Schema is valid' );
21 my @tables = $schema->get_tables;
22 is( scalar @tables, 1, 'Right number of tables (1)' );
23 my $table = shift @tables;
24 is( $table->name, 'sessions', 'Found "sessions" table' );
25
26 my @fields = $table->get_fields;
27 is( scalar @fields, 4, 'Right number of fields (4)' );
28
29 my $f1 = shift @fields;
30 my $f2 = shift @fields;
31 is( $f1->name, 'id', 'First field name is "id"' );
92a61e09 32 is( $f1->data_type, 'char', 'Type is "char"' );
dbca887e 33 is( $f1->size, 32, 'Size is "32"' );
34 is( $f1->is_nullable, 0, 'Field cannot be null' );
35 is( $f1->default_value, '0', 'Default value is "0"' );
36 is( $f1->is_primary_key, 1, 'Field is PK' );
37
38 is( $f2->name, 'a_session', 'Second field name is "a_session"' );
92a61e09 39 is( $f2->data_type, 'text', 'Type is "text"' );
40 is( $f2->size, 65_535, 'Size is "65,535"' );
dbca887e 41 is( $f2->is_nullable, 1, 'Field can be null' );
42 is( $f2->default_value, undef, 'Default value is undefined' );
43 is( $f2->is_primary_key, 0, 'Field is not PK' );
44
45 my @indices = $table->get_indices;
46 is( scalar @indices, 2, 'Right number of indices (2)' );
47
48 my $i = pop @indices;
49 is( $i->type, 'FULLTEXT', 'Found fulltext' );
50
51 my @constraints = $table->get_constraints;
52 is( scalar @constraints, 2, 'Right number of constraints (2)' );
92a61e09 53 my $c1 = shift @constraints;
54 is( $c1->type, PRIMARY_KEY, 'Constraint is a PK' );
55 is( join(',', $c1->fields), 'id', 'Constraint is on "id"' );
dbca887e 56 my $c2 = shift @constraints;
57 is( $c2->type, UNIQUE, 'Constraint is UNIQUE' );
58 is( join(',', $c2->fields), 'ssn', 'Constraint is on "ssn"' );
59}
60
61{
62 my $tr = SQL::Translator->new({ from => 'MySQL' });
63 my $schema = $tr->parse(
64 q[
65 CREATE TABLE `check` (
66 check_id int(7) unsigned zerofill NOT NULL default '0000000'
67 auto_increment primary key,
68 successful date NOT NULL default '0000-00-00',
69 unsuccessful date default '0000-00-00',
70 i1 int(11) default '0' not null,
71 s1 set('a','b','c') default 'b',
72 e1 enum('a','b','c') default 'c',
73 name varchar(30) default NULL,
74 foo_type enum('vk','ck') NOT NULL default 'vk',
75 date timestamp,
76 time_stamp2 timestamp,
77 KEY (i1),
78 UNIQUE (date, i1),
79 KEY date_idx (date),
92a61e09 80 KEY name_idx (name(10))
dbca887e 81 ) TYPE=MyISAM PACK_KEYS=1;
82 ]
83 );
84
85# my $schema = $tr->schema;
86 is( $schema->is_valid, 1, 'Schema is valid' );
87 my @tables = $schema->get_tables;
88 is( scalar @tables, 1, 'Right number of tables (1)' );
89 my $table = shift @tables;
90 is( $table->name, 'check', 'Found "check" table' );
91
92 my @fields = $table->get_fields;
93 is( scalar @fields, 10, 'Right number of fields (10)' );
94 my $f1 = shift @fields;
95 is( $f1->name, 'check_id', 'First field name is "check_id"' );
92a61e09 96 is( $f1->data_type, 'int', 'Type is "int"' );
dbca887e 97 is( $f1->size, 7, 'Size is "7"' );
98 is( $f1->is_nullable, 0, 'Field cannot be null' );
99 is( $f1->default_value, '0000000', 'Default value is "0000000"' );
100 is( $f1->is_primary_key, 1, 'Field is PK' );
101 is( $f1->is_auto_increment, 1, 'Field is auto inc' );
102 my %extra = $f1->extra;
103 ok( defined $extra{'unsigned'}, 'Field is unsigned' );
104 ok( defined $extra{'zerofill'}, 'Field is zerofill' );
105
106 my $f2 = shift @fields;
107 is( $f2->name, 'successful', 'Second field name is "successful"' );
108 is( $f2->data_type, 'date', 'Type is "date"' );
109 is( $f2->size, 0, 'Size is "0"' );
110 is( $f2->is_nullable, 0, 'Field cannot be null' );
111 is( $f2->default_value, '0000-00-00', 'Default value is "0000-00-00"' );
112 is( $f2->is_primary_key, 0, 'Field is not PK' );
113
114 my $f3 = shift @fields;
115 is( $f3->name, 'unsuccessful', 'Third field name is "unsuccessful"' );
116 is( $f3->data_type, 'date', 'Type is "date"' );
117 is( $f3->size, 0, 'Size is "0"' );
118 is( $f3->is_nullable, 1, 'Field can be null' );
119 is( $f3->default_value, '0000-00-00', 'Default value is "0000-00-00"' );
120 is( $f3->is_primary_key, 0, 'Field is not PK' );
121
122 my $f4 = shift @fields;
123 is( $f4->name, 'i1', 'Fourth field name is "i1"' );
92a61e09 124 is( $f4->data_type, 'int', 'Type is "int"' );
dbca887e 125 is( $f4->size, 11, 'Size is "11"' );
126 is( $f4->is_nullable, 0, 'Field cannot be null' );
127 is( $f4->default_value, '0', 'Default value is "0"' );
128 is( $f4->is_primary_key, 0, 'Field is not PK' );
129
130 my $f5 = shift @fields;
131 is( $f5->name, 's1', 'Fifth field name is "s1"' );
132 is( $f5->data_type, 'set', 'Type is "set"' );
133 is( $f5->size, 1, 'Size is "1"' );
134 is( $f5->is_nullable, 1, 'Field can be null' );
135 is( $f5->default_value, 'b', 'Default value is "b"' );
136 is( $f5->is_primary_key, 0, 'Field is not PK' );
137 my %f5extra = $f5->extra;
138 is( join(',', @{ $f5extra{'list'} || [] }), 'a,b,c', 'List is "a,b,c"' );
139
140 my $f6 = shift @fields;
141 is( $f6->name, 'e1', 'Sixth field name is "e1"' );
142 is( $f6->data_type, 'enum', 'Type is "enum"' );
143 is( $f6->size, 1, 'Size is "1"' );
144 is( $f6->is_nullable, 1, 'Field can be null' );
145 is( $f6->default_value, 'c', 'Default value is "c"' );
146 is( $f6->is_primary_key, 0, 'Field is not PK' );
147 my %f6extra = $f6->extra;
148 is( join(',', @{ $f6extra{'list'} || [] }), 'a,b,c', 'List is "a,b,c"' );
149
150 my $f7 = shift @fields;
151 is( $f7->name, 'name', 'Seventh field name is "name"' );
152 is( $f7->data_type, 'varchar', 'Type is "varchar"' );
153 is( $f7->size, 30, 'Size is "30"' );
154 is( $f7->is_nullable, 1, 'Field can be null' );
155 is( $f7->default_value, 'NULL', 'Default value is "NULL"' );
156 is( $f7->is_primary_key, 0, 'Field is not PK' );
157
158 my $f8 = shift @fields;
159 is( $f8->name, 'foo_type', 'Eighth field name is "foo_type"' );
160 is( $f8->data_type, 'enum', 'Type is "enum"' );
161 is( $f8->size, 2, 'Size is "2"' );
162 is( $f8->is_nullable, 0, 'Field cannot be null' );
163 is( $f8->default_value, 'vk', 'Default value is "vk"' );
164 is( $f8->is_primary_key, 0, 'Field is not PK' );
165 my %f8extra = $f8->extra;
166 is( join(',', @{ $f8extra{'list'} || [] }), 'vk,ck', 'List is "vk,ck"' );
167
168 my $f9 = shift @fields;
169 is( $f9->name, 'date', 'Ninth field name is "date"' );
170 is( $f9->data_type, 'timestamp', 'Type is "timestamp"' );
171 is( $f9->size, 0, 'Size is "0"' );
172 is( $f9->is_nullable, 1, 'Field can be null' );
173 is( $f9->default_value, undef, 'Default value is undefined' );
174 is( $f9->is_primary_key, 0, 'Field is not PK' );
175
176 my $f10 = shift @fields;
177 is( $f10->name, 'time_stamp2', 'Tenth field name is "time_stamp2"' );
178 is( $f10->data_type, 'timestamp', 'Type is "timestamp"' );
179 is( $f10->size, 0, 'Size is "0"' );
180 is( $f10->is_nullable, 1, 'Field can be null' );
181 is( $f10->default_value, undef, 'Default value is undefined' );
182 is( $f10->is_primary_key, 0, 'Field is not PK' );
183
184 my @indices = $table->get_indices;
185 is( scalar @indices, 3, 'Right number of indices (3)' );
186
187 my $i1 = shift @indices;
188 is( $i1->name, '', 'No name on index' );
189 is( $i1->type, NORMAL, 'Normal index' );
190 is( join(',', $i1->fields ), 'i1', 'Index is on field "i1"' );
191
192 my $i2 = shift @indices;
193 is( $i2->name, 'date_idx', 'Name is "date_idx"' );
194 is( $i2->type, NORMAL, 'Normal index' );
195 is( join(',', $i2->fields ), 'date', 'Index is on field "date"' );
196
197 my $i3 = shift @indices;
198 is( $i3->name, 'name_idx', 'Name is "name_idx"' );
199 is( $i3->type, NORMAL, 'Normal index' );
200 is( join(',', $i3->fields ), 'name(10)', 'Index is on field "name(10)"' );
201
202 my @constraints = $table->get_constraints;
203 is( scalar @constraints, 2, 'Right number of constraints (2)' );
204
205 my $c1 = shift @constraints;
206 is( $c1->type, PRIMARY_KEY, 'Constraint is a PK' );
207 is( join(',', $c1->fields), 'check_id', 'Constraint is on "check_id"' );
208
209 my $c2 = shift @constraints;
210 is( $c2->type, UNIQUE, 'Constraint is UNIQUE' );
211 is( join(',', $c2->fields), 'date,i1', 'Constraint is on "date, i1"' );
212}
213
214{
215 my $tr = SQL::Translator->new;
216 my $data = parse($tr,
217 q[
218 CREATE TABLE orders (
219 order_id integer NOT NULL auto_increment,
220 member_id varchar(255) comment 'fk to member',
221 billing_address_id int,
222 shipping_address_id int,
223 credit_card_id int,
224 status smallint NOT NULL,
225 store_id varchar(255) NOT NULL REFERENCES store,
226 tax decimal(8,2),
227 shipping_charge decimal(8,2),
228 price_paid decimal(8,2),
229 PRIMARY KEY (order_id),
230 KEY (status),
231 KEY (billing_address_id),
232 KEY (shipping_address_id),
233 KEY (member_id, store_id),
234 FOREIGN KEY (status) REFERENCES order_status(id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
235 FOREIGN KEY (billing_address_id) REFERENCES address(address_id),
236 FOREIGN KEY (shipping_address_id) REFERENCES address(address_id)
237 ) TYPE=INNODB COMMENT = 'orders table comment';
238
239 CREATE TABLE address (
240 address_id int NOT NULL auto_increment,
241 recipient varchar(255) NOT NULL,
242 address1 varchar(255) NOT NULL,
243 address2 varchar(255),
244 city varchar(255) NOT NULL,
245 state varchar(255) NOT NULL,
246 postal_code varchar(255) NOT NULL,
247 phone varchar(255),
248 PRIMARY KEY (address_id)
249 ) TYPE=INNODB;
250 ]
251 ) or die $tr->error;
252
253 my $schema = $tr->schema;
254 is( $schema->is_valid, 1, 'Schema is valid' );
255 my @tables = $schema->get_tables;
256 is( scalar @tables, 2, 'Right number of tables (2)' );
257
258 my $t1 = shift @tables;
259 is( $t1->name, 'orders', 'Found "orders" table' );
260 is( $t1->comments, 'orders table comment', 'Table comment OK' );
261
262 my @fields = $t1->get_fields;
263 is( scalar @fields, 10, 'Right number of fields (10)' );
264
265 my $f1 = shift @fields;
266 is( $f1->name, 'order_id', 'First field name is "order_id"' );
92a61e09 267 is( $f1->data_type, 'int', 'Type is "int"' );
dbca887e 268 is( $f1->size, 11, 'Size is "11"' );
269 is( $f1->is_nullable, 0, 'Field cannot be null' );
270 is( $f1->default_value, undef, 'Default value is undefined' );
271 is( $f1->is_primary_key, 1, 'Field is PK' );
272 is( $f1->is_auto_increment, 1, 'Field is auto inc' );
273
274 my $f2 = shift @fields;
275 is( $f2->name, 'member_id', 'Second field name is "member_id"' );
276 is( $f2->data_type, 'varchar', 'Type is "varchar"' );
277 is( $f2->size, 255, 'Size is "255"' );
278 is( $f2->is_nullable, 1, 'Field can be null' );
279 is( $f2->comments, 'fk to member', 'Field comment OK' );
280 is( $f2->default_value, undef, 'Default value is undefined' );
281
282 my $f3 = shift @fields;
283 is( $f3->name, 'billing_address_id',
284 'Third field name is "billing_address_id"' );
92a61e09 285 is( $f3->data_type, 'int', 'Type is "int"' );
dbca887e 286 is( $f3->size, 11, 'Size is "11"' );
287
288 my $f4 = shift @fields;
289 is( $f4->name, 'shipping_address_id',
290 'Fourth field name is "shipping_address_id"' );
92a61e09 291 is( $f4->data_type, 'int', 'Type is "int"' );
dbca887e 292 is( $f4->size, 11, 'Size is "11"' );
293
294 my $f5 = shift @fields;
295 is( $f5->name, 'credit_card_id', 'Fifth field name is "credit_card_id"' );
92a61e09 296 is( $f5->data_type, 'int', 'Type is "int"' );
dbca887e 297 is( $f5->size, 11, 'Size is "11"' );
298
299 my $f6 = shift @fields;
300 is( $f6->name, 'status', 'Sixth field name is "status"' );
301 is( $f6->data_type, 'smallint', 'Type is "smallint"' );
302 is( $f6->size, 6, 'Size is "6"' );
303 is( $f6->is_nullable, 0, 'Field cannot be null' );
304
305 my $f7 = shift @fields;
306 is( $f7->name, 'store_id', 'Seventh field name is "store_id"' );
307 is( $f7->data_type, 'varchar', 'Type is "varchar"' );
308 is( $f7->size, 255, 'Size is "255"' );
309 is( $f7->is_nullable, 0, 'Field cannot be null' );
310 is( $f7->is_foreign_key, 1, 'Field is a FK' );
311 my $fk_ref = $f7->foreign_key_reference;
312 isa_ok( $fk_ref, 'SQL::Translator::Schema::Constraint', 'FK' );
313 is( $fk_ref->reference_table, 'store', 'FK is to "store" table' );
314
315 my $f8 = shift @fields;
316 is( $f8->name, 'tax', 'Eighth field name is "tax"' );
317 is( $f8->data_type, 'decimal', 'Type is "decimal"' );
318 is( $f8->size, '8,2', 'Size is "8,2"' );
319
320 my $f9 = shift @fields;
321 is( $f9->name, 'shipping_charge', 'Ninth field name is "shipping_charge"' );
322 is( $f9->data_type, 'decimal', 'Type is "decimal"' );
323 is( $f9->size, '8,2', 'Size is "8,2"' );
324
325 my $f10 = shift @fields;
326 is( $f10->name, 'price_paid', 'Tenth field name is "price_paid"' );
327 is( $f10->data_type, 'decimal', 'Type is "decimal"' );
328 is( $f10->size, '8,2', 'Size is "8,2"' );
329
330 my @indices = $t1->get_indices;
331 is( scalar @indices, 4, 'Right number of indices (4)' );
332
333 my $i1 = shift @indices;
334 is( $i1->type, NORMAL, 'First index is normal' );
335 is( join(',', $i1->fields), 'status', 'Index is on "status"' );
336
337 my $i2 = shift @indices;
338 is( $i2->type, NORMAL, 'Second index is normal' );
339 is( join(',', $i2->fields), 'billing_address_id',
340 'Index is on "billing_address_id"' );
341
342 my $i3 = shift @indices;
343 is( $i3->type, NORMAL, 'Third index is normal' );
344 is( join(',', $i3->fields), 'shipping_address_id',
345 'Index is on "shipping_address_id"' );
346
347 my $i4 = shift @indices;
348 is( $i4->type, NORMAL, 'Third index is normal' );
349 is( join(',', $i4->fields), 'member_id,store_id',
350 'Index is on "member_id,store_id"' );
351
352 my @constraints = $t1->get_constraints;
353 is( scalar @constraints, 5, 'Right number of constraints (5)' );
354
355 my $c1 = shift @constraints;
356 is( $c1->type, PRIMARY_KEY, 'Constraint is a PK' );
357 is( join(',', $c1->fields), 'order_id', 'Constraint is on "order_id"' );
358
359 my $c2 = shift @constraints;
360 is( $c2->type, FOREIGN_KEY, 'Constraint is a FK' );
361 is( join(',', $c2->fields), 'status', 'Constraint is on "status"' );
362 is( $c2->reference_table, 'order_status', 'To table "order_status"' );
363 is( join(',', $c2->reference_fields), 'id', 'To field "id"' );
364
365 my $c3 = shift @constraints;
366 is( $c3->type, FOREIGN_KEY, 'Constraint is a FK' );
367 is( join(',', $c3->fields), 'billing_address_id',
368 'Constraint is on "billing_address_id"' );
369 is( $c3->reference_table, 'address', 'To table "address"' );
370 is( join(',', $c3->reference_fields), 'address_id',
371 'To field "address_id"' );
372
373 my $c4 = shift @constraints;
374 is( $c4->type, FOREIGN_KEY, 'Constraint is a FK' );
375 is( join(',', $c4->fields), 'shipping_address_id',
376 'Constraint is on "shipping_address_id"' );
377 is( $c4->reference_table, 'address', 'To table "address"' );
378 is( join(',', $c4->reference_fields), 'address_id',
379 'To field "address_id"' );
380
381 my $c5 = shift @constraints;
382 is( $c5->type, FOREIGN_KEY, 'Constraint is a FK' );
383 is( join(',', $c5->fields), 'store_id', 'Constraint is on "store_id"' );
384 is( $c5->reference_table, 'store', 'To table "store"' );
385 is( join(',', map { $_ || '' } $c5->reference_fields), '',
386 'No reference fields defined' );
387
388 my $t2 = shift @tables;
389 is( $t2->name, 'address', 'Found "address" table' );
390
391 my @t2_fields = $t2->get_fields;
392 is( scalar @t2_fields, 8, 'Right number of fields (8)' );
393}
394
395# djh Tests for:
396# USE database ;
397# ALTER TABLE ADD FOREIGN KEY
398# trailing comma on last create definition
399# Ignoring INSERT statements
400#
401{
402 my $tr = SQL::Translator->new;
403 my $data = parse($tr,
404 q[
405 USE database_name;
406
407 CREATE TABLE one (
408 id integer NOT NULL auto_increment,
409 two_id integer NOT NULL auto_increment,
410 some_data text,
411 PRIMARY KEY (id),
412 INDEX (two_id),
413 ) TYPE=INNODB;
414
415 CREATE TABLE two (
416 id int NOT NULL auto_increment,
417 one_id int NOT NULL auto_increment,
418 some_data text,
419 PRIMARY KEY (id),
420 INDEX (one_id),
421 FOREIGN KEY (one_id) REFERENCES one (id),
422 ) TYPE=INNODB;
423
424 ALTER TABLE one ADD FOREIGN KEY (two_id) REFERENCES two (id);
425
426 INSERT absolutely *#! any old $£ ? rubbish, even "quoted; semi-what""sits";
427 ]
428 ) or die $tr->error;
429
430 my $schema = $tr->schema;
431 is( $schema->is_valid, 1, 'Schema is valid' );
432 my $db_name = $schema->name;
433 is( $db_name, 'database_name', 'Database name extracted from USE' );
434 my @tables = $schema->get_tables;
435 is( scalar @tables, 2, 'Right number of tables (2)' );
436 my $table1 = shift @tables;
437 is( $table1->name, 'one', 'Found "one" table' );
438 my $table2 = shift @tables;
439 is( $table2->name, 'two', 'Found "two" table' );
440
441 my @constraints = $table1->get_constraints;
442 is(scalar @constraints, 2, 'Right number of constraints (2) on table one');
443
444 my $t1c1 = shift @constraints;
445 is( $t1c1->type, PRIMARY_KEY, 'Constraint is a PK' );
446 is( join(',', $t1c1->fields), 'id', 'Constraint is on "id"' );
447
448 my $t1c2 = shift @constraints;
449 is( $t1c2->type, FOREIGN_KEY, 'Constraint is a FK' );
450 is( join(',', $t1c2->fields), 'two_id', 'Constraint is on "two_id"' );
451 is( $t1c2->reference_table, 'two', 'To table "two"' );
452 is( join(',', $t1c2->reference_fields), 'id', 'To field "id"' );
453
454 @constraints = $table2->get_constraints;
455 is(scalar @constraints, 2, 'Right number of constraints (2) on table two');
456
457 my $t2c1 = shift @constraints;
458 is( $t2c1->type, PRIMARY_KEY, 'Constraint is a PK' );
459 is( join(',', $t2c1->fields), 'id', 'Constraint is on "id"' );
460
461 my $t2c2 = shift @constraints;
462 is( $t2c2->type, FOREIGN_KEY, 'Constraint is a FK' );
463 is( join(',', $t2c2->fields), 'one_id', 'Constraint is on "one_id"' );
464 is( $t2c2->reference_table, 'one', 'To table "one"' );
465 is( join(',', $t2c2->reference_fields), 'id', 'To field "id"' );
466}
467
468# cch Tests for:
469# comments like: /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
470# char fields with character set and collate qualifiers
471# timestamp fields with on update qualifier
472# charset table option
473#
474{
475 my $tr = SQL::Translator->new(parser_args => {mysql_parser_version => 50003});
476 my $data = parse($tr,
477 q[
478 DELIMITER ;;
479 /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;;
480 /*!50003 CREATE */ /*!50017 DEFINER=`cmdomain`@`localhost` */
481 /*!50003 TRIGGER `acl_entry_insert` BEFORE INSERT ON `acl_entry`
482 FOR EACH ROW SET NEW.dateCreated = CONVERT_TZ(SYSDATE(),'SYSTEM','+0:00'),
483 NEW.dateModified = CONVERT_TZ(SYSDATE(),'SYSTEM','+0:00') */;;
484
485 DELIMITER ;
486 CREATE TABLE one (
487 `op` varchar(255) character set latin1 collate latin1_bin default NULL,
488 `last_modified` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
489 ) TYPE=INNODB DEFAULT CHARSET=latin1;
490
491 /*!50001 CREATE ALGORITHM=UNDEFINED */
492 /*!50013 DEFINER=`cmdomain`@`localhost` SQL SECURITY DEFINER */
493 /*! VIEW `vs_asset` AS
494 select `a`.`asset_id` AS `asset_id`,`a`.`fq_name` AS `fq_name`,
495 `cfgmgmt_mig`.`ap_extract_folder`(`a`.`fq_name`) AS `folder_name`,
496 `cfgmgmt_mig`.`ap_extract_asset`(`a`.`fq_name`) AS `asset_name`,
497 `a`.`annotation` AS `annotation`,`a`.`asset_type` AS `asset_type`,
498 `a`.`foreign_asset_id` AS `foreign_asset_id`,
499 `a`.`foreign_asset_id2` AS `foreign_asset_id2`,`a`.`dateCreated` AS `date_created`,
500 `a`.`dateModified` AS `date_modified`,`a`.`container_id` AS `container_id`,
501 `a`.`creator_id` AS `creator_id`,`a`.`modifier_id` AS `modifier_id`,
502 `m`.`user_id` AS `user_access`
503 from (`asset` `a` join `M_ACCESS_CONTROL` `m` on((`a`.`acl_id` = `m`.`acl_id`))) */;
504 DELIMITER ;;
505 /*!50001 CREATE */
506 /*! VIEW `vs_asset2` AS
507 select `a`.`asset_id` AS `asset_id`,`a`.`fq_name` AS `fq_name`,
508 `cfgmgmt_mig`.`ap_extract_folder`(`a`.`fq_name`) AS `folder_name`,
509 `cfgmgmt_mig`.`ap_extract_asset`(`a`.`fq_name`) AS `asset_name`,
510 `a`.`annotation` AS `annotation`,`a`.`asset_type` AS `asset_type`,
511 `a`.`foreign_asset_id` AS `foreign_asset_id`,
512 `a`.`foreign_asset_id2` AS `foreign_asset_id2`,`a`.`dateCreated` AS `date_created`,
513 `a`.`dateModified` AS `date_modified`,`a`.`container_id` AS `container_id`,
514 `a`.`creator_id` AS `creator_id`,`a`.`modifier_id` AS `modifier_id`,
515 `m`.`user_id` AS `user_access`
516 from (`asset` `a` join `M_ACCESS_CONTROL` `m` on((`a`.`acl_id` = `m`.`acl_id`))) */;
517 DELIMITER ;;
518 /*!50001 CREATE OR REPLACE */
519 /*! VIEW `vs_asset3` AS
520 select `a`.`asset_id` AS `asset_id`,`a`.`fq_name` AS `fq_name`,
521 `cfgmgmt_mig`.`ap_extract_folder`(`a`.`fq_name`) AS `folder_name`,
522 `cfgmgmt_mig`.`ap_extract_asset`(`a`.`fq_name`) AS `asset_name`,
523 `a`.`annotation` AS `annotation`,`a`.`asset_type` AS `asset_type`,
524 `a`.`foreign_asset_id` AS `foreign_asset_id`,
525 `a`.`foreign_asset_id2` AS `foreign_asset_id2`,`a`.`dateCreated` AS `date_created`,
526 `a`.`dateModified` AS `date_modified`,`a`.`container_id` AS `container_id`,
527 `a`.`creator_id` AS `creator_id`,`a`.`modifier_id` AS `modifier_id`,
528 `m`.`user_id` AS `user_access`
529 from (`asset` `a` join `M_ACCESS_CONTROL` `m` on((`a`.`acl_id` = `m`.`acl_id`))) */;
530 DELIMITER ;;
531 /*!50003 CREATE*/ /*!50020 DEFINER=`cmdomain`@`localhost`*/ /*!50003 FUNCTION `ap_from_millitime_nullable`( millis_since_1970 BIGINT ) RETURNS timestamp
532 DETERMINISTIC
533 BEGIN
534 DECLARE rval TIMESTAMP;
535 IF ( millis_since_1970 = 0 )
536 THEN
537 SET rval = NULL;
538 ELSE
539 SET rval = FROM_UNIXTIME( millis_since_1970 / 1000 );
540 END IF;
541 RETURN rval;
542 END */;;
543 /*!50003 CREATE*/ /*!50020 DEFINER=`cmdomain`@`localhost`*/ /*!50003 PROCEDURE `sp_update_security_acl`(IN t_acl_id INTEGER)
544 BEGIN
545 DECLARE hasMoreRows BOOL DEFAULT TRUE;
546 DECLARE t_group_id INT;
547 DECLARE t_user_id INT ;
548 DECLARE t_user_name VARCHAR (512) ;
549 DECLARE t_message VARCHAR (512) ;
550
551 DROP TABLE IF EXISTS group_acl;
552 DROP TABLE IF EXISTS user_group;
553 DELETE FROM M_ACCESS_CONTROL WHERE acl_id = t_acl_id;
554
555 CREATE TEMPORARY TABLE group_acl SELECT DISTINCT p.id group_id, d.acl_id acl_id
556 FROM asset d, acl_entry e, alterpoint_principal p
557 WHERE d.acl_id = e.acl
558 AND p.id = e.principal AND d.acl_id = t_acl_id;
559
560 CREATE TEMPORARY TABLE user_group SELECT a.id user_id, a.name user_name, c.id group_id
561 FROM alterpoint_principal a, groups_for_user b, alterpoint_principal c
562 WHERE a.id = b.user_ref AND b.elt = c.id;
563
564 INSERT INTO M_ACCESS_CONTROL SELECT DISTINCT group_acl.group_id, group_acl.acl_id, user_group.user_id, user_group.user_name
565 FROM group_acl, user_group
566 WHERE group_acl.group_id = user_group.group_id ;
567 END */;;
568 ]
569 ) or die $tr->error;
570
571 my $schema = $tr->schema;
572 is( $schema->is_valid, 1, 'Schema is valid' );
573 my @tables = $schema->get_tables;
574 is( scalar @tables, 1, 'Right number of tables (1)' );
575 my $table1 = shift @tables;
576 is( $table1->name, 'one', 'Found "one" table' );
577
578 my @fields = $table1->get_fields;
579 is(scalar @fields, 2, 'Right number of fields (2) on table one');
580 my $tableTypeFound = 0;
581 my $charsetFound = 0;
582 for my $t1_option_ref ( $table1->options ) {
583 my($key, $value) = %{$t1_option_ref};
584 if ( $key eq 'TYPE' ) {
585 is($value, 'INNODB', 'Table has right table type option' );
586 $tableTypeFound = 1;
587 } elsif ( $key eq 'CHARACTER SET' ) {
588 is($value, 'latin1', 'Table has right character set option' );
589 $charsetFound = 1;
590 }
591 }
592 fail('Table did not have a type option') unless $tableTypeFound;
593 fail('Table did not have a character set option') unless $charsetFound;
594
595 my $t1f1 = shift @fields;
596 is( $t1f1->data_type, 'varchar', 'Field is a varchar' );
597 is( $t1f1->size, 255, 'Field is right size' );
598 is( $t1f1->extra('character set'), 'latin1', 'Field has right character set qualifier' );
599 is( $t1f1->extra('collate'), 'latin1_bin', 'Field has right collate qualifier' );
600 is( $t1f1->default_value, 'NULL', 'Field has right default value' );
601
602 my $t1f2 = shift @fields;
603 is( $t1f2->data_type, 'timestamp', 'Field is a timestamp' );
604 ok( !$t1f2->is_nullable, 'Field is not nullable' );
605 is_deeply(
606 $t1f2->default_value,
607 \'CURRENT_TIMESTAMP',
608 'Field has right default value'
609 );
610 is( $t1f2->extra('on update'), 'CURRENT_TIMESTAMP', 'Field has right on update qualifier' );
611
612 my @views = $schema->get_views;
613 is( scalar @views, 3, 'Right number of views (3)' );
614 my ($view3, $view1, $view2) = @views;
615 is( $view1->name, 'vs_asset', 'Found "vs_asset" view' );
616 is( $view2->name, 'vs_asset2', 'Found "vs_asset2" view' );
617 is( $view3->name, 'vs_asset3', 'Found "vs_asset3" view' );
618 like($view1->sql, qr/ALGORITHM=UNDEFINED/, "Detected algorithm");
619 like($view1->sql, qr/vs_asset/, "Detected view vs_asset");
620 unlike($view1->sql, qr/cfgmgmt_mig/, "Did not detect cfgmgmt_mig");
621
622 my @procs = $schema->get_procedures;
623 is( scalar @procs, 2, 'Right number of procedures (2)' );
624 my $proc1 = shift @procs;
625 is( $proc1->name, 'ap_from_millitime_nullable', 'Found "ap_from_millitime_nullable" procedure' );
626 like($proc1->sql, qr/CREATE FUNCTION ap_from_millitime_nullable/, "Detected procedure ap_from_millitime_nullable");
627 my $proc2 = shift @procs;
628 is( $proc2->name, 'sp_update_security_acl', 'Found "sp_update_security_acl" procedure' );
629 like($proc2->sql, qr/CREATE PROCEDURE sp_update_security_acl/, "Detected procedure sp_update_security_acl");
630}
631
632# Tests for collate table option
633{
634 my $tr = SQL::Translator->new(parser_args => {mysql_parser_version => 50003});
635 my $data = parse($tr,
636 q[
637 CREATE TABLE test ( id int ) DEFAULT CHARACTER SET latin1 COLLATE latin1_bin;
638 ] );
639
640 my $schema = $tr->schema;
641 is( $schema->is_valid, 1, 'Schema is valid' );
642 my @tables = $schema->get_tables;
643 is( scalar @tables, 1, 'Right number of tables (1)' );
644 my $table1 = shift @tables;
645 is( $table1->name, 'test', 'Found "test" table' );
646
647
648 my $collate = "Not found!";
649 my $charset = "Not found!";
650 for my $t1_option_ref ( $table1->options ) {
651 my($key, $value) = %{$t1_option_ref};
652 $collate = $value if $key eq 'COLLATE';
653 $charset = $value if $key eq 'CHARACTER SET';
654 }
655 is($collate, 'latin1_bin', "Collate found");
656 is($charset, 'latin1', "Character set found");
657}
658
659# Test the mysql version parser (probably needs to migrate to t/utils.t)
660my $parse_as = {
661 perl => {
662 '3.23.2' => 3.023002,
663 '4' => 4.000000,
664 '50003' => 5.000003,
665 '5.01.0' => 5.001000,
666 '5.1' => 5.001000,
667 },
668 mysql => {
669 '3.23.2' => 32302,
670 '4' => 40000,
671 '50003' => 50003,
672 '5.01.0' => 50100,
673 '5.1' => 50100,
674 },
675};
676
677for my $target (keys %$parse_as) {
678 for my $str (keys %{$parse_as->{$target}}) {
679 cmp_ok (
680 SQL::Translator::Utils::parse_mysql_version ($str, $target),
681 '==',
682 $parse_as->{$target}{$str},
683 "'$str' parsed as $target version '$parse_as->{$target}{$str}'",
684 );
685 }
686}
687
688eval { SQL::Translator::Utils::parse_mysql_version ('bogus5.1') };
689ok ($@, 'Exception thrown on invalid version string');
690
691{
692 my $tr = SQL::Translator->new;
693 my $data = q|create table merge_example (
694 id int(11) NOT NULL auto_increment,
695 shape_field geometry NOT NULL,
696 PRIMARY KEY (id),
697 SPATIAL KEY shape_field (shape_field)
698 ) ENGINE=MRG_MyISAM UNION=(`sometable_0`,`sometable_1`,`sometable_2`);|;
699
700 my $val = parse($tr, $data);
701 my $schema = $tr->schema;
702 is( $schema->is_valid, 1, 'Schema is valid' );
703 my @tables = $schema->get_tables;
704 is( scalar @tables, 1, 'Right number of tables (1)' );
705 my $table = shift @tables;
706 is( $table->name, 'merge_example', 'Found "merge_example" table' );
707
708 my $tableTypeFound = 0;
709 my $unionFound = 0;
710 for my $t_option_ref ( $table->options ) {
711 my($key, $value) = %{$t_option_ref};
712 if ( $key eq 'ENGINE' ) {
713 is($value, 'MRG_MyISAM', 'Table has right table engine option' );
714 $tableTypeFound = 1;
715 } elsif ( $key eq 'UNION' ) {
716 is_deeply($value, [ 'sometable_0','sometable_1','sometable_2' ],
717 "UNION option has correct set");
718 $unionFound = 1;
719 }
720 }
721
722 fail('Table did not have a type option') unless $tableTypeFound;
723 fail('Table did not have a union option') unless $unionFound;
724
725 my @fields = $table->get_fields;
726 is( scalar @fields, 2, 'Right number of fields (2)' );
727 my $f1 = shift @fields;
728 my $f2 = shift @fields;
729 is( $f1->name, 'id', 'First field name is "id"' );
92a61e09 730 is( $f1->data_type, 'int', 'Type is "int"' );
dbca887e 731 is( $f1->size, 11, 'Size is "11"' );
732 is( $f1->is_nullable, 0, 'Field cannot be null' );
733 is( $f1->is_primary_key, 1, 'Field is PK' );
734
735 is( $f2->name, 'shape_field', 'Second field name is "shape_field"' );
736 is( $f2->data_type, 'geometry', 'Type is "geometry"' );
737 is( $f2->is_nullable, 0, 'Field cannot be null' );
738 is( $f2->is_primary_key, 0, 'Field is not PK' );
739
740 my @indices = $table->get_indices;
741 is( scalar @indices, 1, 'Right number of indices (1)' );
742 my $i1 = shift @indices;
743 is( $i1->name, 'shape_field', 'No name on index' );
744 is( $i1->type, SPATIAL, 'Spatial index' );
745
746 my @constraints = $table->get_constraints;
747 is( scalar @constraints, 1, 'Right number of constraints (1)' );
748 my $c = shift @constraints;
749 is( $c->type, PRIMARY_KEY, 'Constraint is a PK' );
750 is( join(',', $c->fields), 'id', 'Constraint is on "id"' );
751}
752
753{
754 my @data = (
755 q|create table quote (
756 id int(11) NOT NULL auto_increment,
757 PRIMARY KEY (id)
758 ) ENGINE="innodb";|,
759 q|create table quote (
760 id int(11) NOT NULL auto_increment,
761 PRIMARY KEY (id)
762 ) ENGINE='innodb';|,
763 q|create table quote (
764 id int(11) NOT NULL auto_increment,
765 PRIMARY KEY (id)
766 ) ENGINE=innodb;|,
767 );
768 for my $data (@data) {
769 my $tr = SQL::Translator->new;
770
771 my $val = parse($tr, $data);
772 my $schema = $tr->schema;
773 is( $schema->is_valid, 1, 'Schema is valid' );
774 my @tables = $schema->get_tables;
775 is( scalar @tables, 1, 'Right number of tables (1)' );
776 my $table = shift @tables;
777 is( $table->name, 'quote', 'Found "quote" table' );
778
779 my $tableTypeFound = 0;
780 for my $t_option_ref ( $table->options ) {
781 my($key, $value) = %{$t_option_ref};
782 if ( $key eq 'ENGINE' ) {
783 is($value, 'innodb', 'Table has right table engine option' );
784 $tableTypeFound = 1;
785 }
786 }
787
788 fail('Table did not have a type option') unless $tableTypeFound;
789
790 my @fields = $table->get_fields;
791 my $f1 = shift @fields;
792 is( $f1->name, 'id', 'First field name is "id"' );
92a61e09 793 is( $f1->data_type, 'int', 'Type is "int"' );
dbca887e 794 is( $f1->size, 11, 'Size is "11"' );
795 is( $f1->is_nullable, 0, 'Field cannot be null' );
796 is( $f1->is_primary_key, 1, 'Field is PK' );
797 }
798}
799
800{
801 my $tr = SQL::Translator->new;
802 my $data = q|create table "sessions" (
803 id char(32) not null default '0' primary key,
804 ssn varchar(12) NOT NULL default 'test single quotes like in you''re',
805 user varchar(20) NOT NULL default 'test single quotes escaped like you\'re',
806 );|;
807
808 my $val = parse($tr, $data);
809 my $schema = $tr->schema;
810 is( $schema->is_valid, 1, 'Schema is valid' );
811 my @tables = $schema->get_tables;
812 is( scalar @tables, 1, 'Right number of tables (1)' );
813 my $table = shift @tables;
814 is( $table->name, 'sessions', 'Found "sessions" table' );
815
816 my @fields = $table->get_fields;
817 is( scalar @fields, 3, 'Right number of fields (3)' );
818 my $f1 = shift @fields;
819 my $f2 = shift @fields;
820 my $f3 = shift @fields;
821 is( $f1->name, 'id', 'First field name is "id"' );
822 is( $f1->data_type, 'char', 'Type is "char"' );
823 is( $f1->size, 32, 'Size is "32"' );
824 is( $f1->is_nullable, 0, 'Field cannot be null' );
825 is( $f1->default_value, '0', 'Default value is "0"' );
826 is( $f1->is_primary_key, 1, 'Field is PK' );
827
828 is( $f2->name, 'ssn', 'Second field name is "ssn"' );
829 is( $f2->data_type, 'varchar', 'Type is "varchar"' );
830 is( $f2->size, 12, 'Size is "12"' );
831 is( $f2->is_nullable, 0, 'Field can not be null' );
832 is( $f2->default_value, "test single quotes like in you''re", "Single quote in default value is escaped properly" );
833 is( $f2->is_primary_key, 0, 'Field is not PK' );
834
835 # this is more of a sanity test because the original sqlt regex for default looked for an escaped quote represented as \'
836 # however in mysql 5.x (and probably other previous versions) still actually outputs that as ''
837 is( $f3->name, 'user', 'Second field name is "user"' );
838 is( $f3->data_type, 'varchar', 'Type is "varchar"' );
839 is( $f3->size, 20, 'Size is "20"' );
840 is( $f3->is_nullable, 0, 'Field can not be null' );
841 is( $f3->default_value, "test single quotes escaped like you\\'re", "Single quote in default value is escaped properly" );
842 is( $f3->is_primary_key, 0, 'Field is not PK' );
843}