|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Rose::DBx::Object::Builder;  | 
| 
2
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
41272
 | 
 use strict;  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
45
 | 
    | 
| 
3
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
6
 | 
 use warnings;  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34
 | 
    | 
| 
4
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
6
 | 
 no warnings 'recursion';  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
50
 | 
    | 
| 
5
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
6
 | 
 use Exporter 'import';  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
43
 | 
    | 
| 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
7
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
12
 | 
 use base qw(Rose::Object);  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1074
 | 
    | 
| 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our @EXPORT = qw(config parse build show);  | 
| 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our @EXPORT_OK = qw(config parse build show);  | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
11
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
1774
 | 
 use Lingua::EN::Inflect 'PL';  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24587
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
144
 | 
    | 
| 
12
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
1023
 | 
 use Regexp::Common;  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5543
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
    | 
| 
13
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
85533
 | 
 use DBI;  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18963
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6745
 | 
    | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $VERSION = 0.09;  | 
| 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 12.9  | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub config {  | 
| 
19
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
  
1
  
 | 
880
 | 
 	my $self = shift;  | 
| 
20
 | 
7
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
52
 | 
 	unless ($self && defined $self->{CONFIG}) {  | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$self->{CONFIG} = {  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			db => {  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				name => undef,   | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				type => 'mysql',   | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				host => '127.0.0.1',   | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				port => undef,   | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				username => 'root',   | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				password => 'root',   | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				tables_are_singular => undef,  | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				table_prefix => '',  | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				options => {RaiseError => 0, PrintError => 0, AutoCommit => 1}},  | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			format => {  | 
| 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				expression => sub {  | 
| 
34
 | 
35
 | 
 
 | 
 
 | 
  
35
  
 | 
 
 | 
73
 | 
 					my $expression = lc(shift);  | 
| 
35
 | 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
303
 | 
 					$expression =~ s/\s*,?\s*\band\b\s*,?\s*/, /g;  | 
| 
36
 | 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
199
 | 
 					$expression =~ s/\b(a|an|the)\b//g;  | 
| 
37
 | 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
57
 | 
 					$expression =~ s/\.//g;  | 
| 
38
 | 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
82
 | 
 					return $expression;  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				},  | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				table => sub {  | 
| 
41
 | 
60
 | 
 
 | 
 
 | 
  
60
  
 | 
 
 | 
88
 | 
 					my $table = shift;  | 
| 
42
 | 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
292
 | 
 					$table =~ s/^\s+|\s+$//g;					  | 
| 
43
 | 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
108
 | 
 					$table =~ s/\s+/_/g;  | 
| 
44
 | 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
189
 | 
 					return $table;  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				},  | 
| 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				column => sub {  | 
| 
47
 | 
115
 | 
 
 | 
 
 | 
  
115
  
 | 
 
 | 
163
 | 
 					my $column = shift;  | 
| 
48
 | 
115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
510
 | 
 					$column =~ s/^\s+|\s+$//g;  | 
| 
49
 | 
115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
273
 | 
 					$column =~ s/\s+/_/g;  | 
| 
50
 | 
115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
262
 | 
 					return $column;  | 
| 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				},  | 
| 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			},  | 
| 
53
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
65
 | 
 			table => {  | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				mysql => 'CREATE TABLE [% table_name %] ([% columns %]) TYPE=INNODB;',  | 
| 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				Pg => 'CREATE TABLE [% table_name %] ([% columns %]);',  | 
| 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				SQLite => 'CREATE TABLE [% table_name %] ([% columns %]);',  | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			},  | 
| 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			primary_key => {  | 
| 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				name => 'id',  | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				type => {  | 
| 
61
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 					mysql => 'INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY',  | 
| 
62
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 					Pg => 'SERIAL PRIMARY KEY',  | 
| 
63
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 					SQLite => 'INTEGER NOT NULL PRIMARY KEY',  | 
| 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				}  | 
| 
65
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			},  | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			foreign_key => {  | 
| 
67
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				suffix => '_id',  | 
| 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				type => {  | 
| 
69
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 					mysql => 'INTEGER',  | 
| 
70
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 					Pg => 'INTEGER',  | 
| 
71
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 					SQLite => 'INTEGER',  | 
| 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				},  | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				singular => 1,  | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				clause => 'FOREIGN KEY ([% foreign_key %]) REFERENCES [% reference_table %] ([% reference_primary_key %]) ON UPDATE CASCADE ON DELETE CASCADE',  | 
| 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			},  | 
| 
76
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			add_clause => 'ALTER TABLE [% table_name %] ADD [% clause %];',  | 
| 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			map_table => '[% table_name %]_[% foreign_table_name %]_map',  | 
| 
78
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			columns => {  | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				name => 'VARCHAR(255)',  | 
| 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				unique => 'VARCHAR(255) UNIQUE',  | 
| 
81
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				required => 'VARCHAR(255) NOT NULL',  | 
| 
82
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				text => 'TEXT',  | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				integer => 'INTEGER',  | 
| 
84
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				number => 'NUMERIC',  | 
| 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				date => 'DATE',  | 
| 
86
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				time => 'TIME',  | 
| 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				timestamp => 'TIMESTAMP',  | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				money => 'DECIMAL(13,2)',  | 
| 
89
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				boolean => 'BOOLEAN',  | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		};  | 
| 
92
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  | 
| 
93
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
 		$self->{CONFIG}->{columns}->{title} = $self->{CONFIG}->{columns}->{name};  | 
| 
94
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
 		$self->{CONFIG}->{columns}->{description} = $self->{CONFIG}->{columns}->{text};  | 
| 
95
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 		$self->{CONFIG}->{columns}->{percentage} = $self->{CONFIG}->{columns}->{number};  | 
| 
96
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 		$self->{CONFIG}->{columns}->{cost} = $self->{CONFIG}->{columns}->{money};  | 
| 
97
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
 		$self->{CONFIG}->{columns}->{price} = $self->{CONFIG}->{columns}->{money};  | 
| 
98
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 		$self->{CONFIG}->{columns}->{username} = $self->{CONFIG}->{columns}->{unique};  | 
| 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
100
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
101
 | 
7
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
22
 | 
 	if (@_) {  | 
| 
102
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 		my $config = shift;  | 
| 
103
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 		foreach my $hash (keys %{$config}) {  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
    | 
| 
104
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
5
 | 
 			if (ref $config->{$hash} eq 'HASH') {  | 
| 
105
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1
 | 
 				foreach my $key (keys %{$config->{$hash}}) {  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
    | 
| 
106
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
5
 | 
 					if (ref $config->{$hash}->{$key} eq 'HASH') {  | 
| 
107
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 						foreach my $sub_key (keys %{$config->{$hash}->{$key}}) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
108
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 							$self->{CONFIG}->{$hash}->{$key}->{$sub_key} = $config->{$hash}->{$key}->{$sub_key};  | 
| 
109
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 						}  | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 					}  | 
| 
111
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 					else {  | 
| 
112
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
 						$self->{CONFIG}->{$hash}->{$key} = $config->{$hash}->{$key};  | 
| 
113
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 					}  | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				}  | 
| 
115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
116
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			else {  | 
| 
117
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 				$self->{CONFIG}->{$hash} = $config->{$hash};  | 
| 
118
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
119
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
120
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
122
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
 	return $self->{CONFIG};  | 
| 
123
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
124
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
125
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub build {  | 
| 
126
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
 	my $self = shift;  | 
| 
127
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my $dbh = shift;  | 
| 
128
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my $config = $self->config;  | 
| 
129
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my $schema = $self->parse;  | 
| 
130
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	return unless $schema;  | 
| 
131
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
132
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	unless ($dbh) {  | 
| 
133
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		die "Database name missing" unless $config->{db}->{name};  | 
| 
134
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		my $host;  | 
| 
135
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	 	$host = 'host='. $config->{db}->{host} if $config->{db}->{host};  | 
| 
136
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		$host .= ';port='.$config->{db}->{port} if $config->{db}->{port};  | 
| 
137
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		my $dsn = qq(dbi:$config->{db}->{type}:dbname=$config->{db}->{name};$host);  | 
| 
138
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		$dbh = DBI->connect($dsn, $config->{db}->{username}, $config->{db}->{password}, $config->{db}->{options}) or die "Error opening database: $config->{db}->{name}\n";  | 
| 
139
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
141
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	eval {	  | 
| 
142
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		foreach my $sql (split /;/, $schema) {  | 
| 
143
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			$dbh->do($sql) or warn "Error executing SQL: $sql;\n";  | 
| 
144
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
145
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		$dbh->commit unless $config->{db}->{options}->{AutoCommit};  | 
| 
146
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	};  | 
| 
147
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
148
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	if ($@) {  | 
| 
149
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		warn "Transaction aborted: $@";  | 
| 
150
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		eval {$dbh->rollback};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
151
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   	}  | 
| 
152
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
153
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	$dbh->disconnect or die "Error closing database: $config->{db}->{name}\n";  | 
| 
154
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
155
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
156
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub parse {  | 
| 
157
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
  
1
  
 | 
2062
 | 
 	my $self = shift;  | 
| 
158
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
 	my $string = shift;  | 
| 
159
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
160
 | 
5
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
17
 | 
 	if ($string) {  | 
| 
161
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
 		my $config = $self->config;  | 
| 
162
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31
 | 
 		foreach my $expression (split /\./, $string) {  | 
| 
163
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
43
 | 
 			my $schema;  | 
| 
164
 | 
30
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
243
 | 
 			if ($expression =~ /\s+as\s+/) {     | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
165
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
 				$schema = _as ($config, $expression);  | 
| 
166
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
167
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			elsif ($expression =~ /vice[\s\-]+versa/) {  | 
| 
168
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
 				$schema = _many_to_many ($config, $expression);  | 
| 
169
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
170
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			elsif ($expression =~ /(has|have)\s+many/) {  | 
| 
171
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
 				$schema = _has_many ($config, $expression);			  | 
| 
172
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
173
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			else {      | 
| 
174
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
41
 | 
 				$schema = _has_a ($config, $expression);  | 
| 
175
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
176
 | 
30
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
155
 | 
 			$self->{SCHEMA} .= $schema if $schema;  | 
| 
177
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
178
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
179
 | 
5
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
56
 | 
 	return $self->{SCHEMA} || '';  | 
| 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
181
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
182
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub show {  | 
| 
183
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
1
  
 | 
736
 | 
 	my $self = shift;  | 
| 
184
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
 	my $schema = $self->parse(@_);  | 
| 
185
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
6
 | 
 	return unless $schema;  | 
| 
186
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 	my @pretty;  | 
| 
187
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
188
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
 	foreach my $schema (split /;/, $schema) {  | 
| 
189
 | 
9
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
30
 | 
 		if ($schema =~ /CREATE/) {  | 
| 
190
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
37
 | 
 			$schema =~ s/^([^\(]+)\(/$1\(\n\t/g;  | 
| 
191
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
67
 | 
 			$schema =~ s/\)([^\)]+)$/\n\)$1/g;  | 
| 
192
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
71
 | 
 			$schema =~ s/([^\d]),([^\d])/$1,\n\t$2/g;  | 
| 
193
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
 			$schema =~ s/\)$/\n)/;  | 
| 
194
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
195
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
 		push @pretty, $schema . ';';  | 
| 
196
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
197
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
 	return join "\n\n", @pretty;  | 
| 
198
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
199
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
200
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _as {  | 
| 
201
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
10
 | 
 	my $config = shift;  | 
| 
202
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
 	my $expression = $config->{format}->{expression}->(shift);  | 
| 
203
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
55
 | 
 	my ($table_name, $has, $foreign_table_name, $foreign_key) = split /\s+(has|have)\s+(.*)\s+as\s+(.*)/, $expression;  | 
| 
204
 | 
5
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
44
 | 
 	return unless $table_name && $foreign_table_name && $foreign_key;  | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
205
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
 	$table_name = _normalise_table($config, $config->{format}->{table}->($table_name));  | 
| 
206
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
 	$foreign_table_name = _normalise_table($config, $config->{format}->{table}->($foreign_table_name));  | 
| 
207
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
 	$foreign_key = $config->{format}->{column}->($foreign_key);  | 
| 
208
 | 
5
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
19
 | 
 	$foreign_key = $config->{foreign_key}->{singular} ? _singularise($foreign_key) : $foreign_key;  | 
| 
209
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
 	$foreign_key .= $config->{foreign_key}->{suffix};  | 
| 
210
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
211
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
 	my $add_column = $config->{add_clause};  | 
| 
212
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
 	$add_column =~ s/\[%\s*table_name\s*%\]/$table_name/;  | 
| 
213
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
 	$add_column =~ s/\[%\s*table_name\s*%\]/$table_name/;  | 
| 
214
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
215
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
 	my $foreign_key_column = $foreign_key . ' ' . $config->{foreign_key}->{type}->{$config->{db}->{type}};  | 
| 
216
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
 	$add_column =~ s/\[%\s*clause\s*%\]/$foreign_key_column/;  | 
| 
217
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
 	my $schema = $add_column;  | 
| 
218
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
219
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
73
 | 
 	my $add_foreign_key = $config->{add_clause};  | 
| 
220
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
 	$add_foreign_key =~ s/\[%\s*table_name\s*%\]/$table_name/;	  | 
| 
221
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
 	my $foreign_key_clause = _generate_foreign_key_clause($config, $foreign_key, $foreign_table_name);  | 
| 
222
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
 	$add_foreign_key =~ s/\[%\s*clause\s*%\]/$foreign_key_clause/;  | 
| 
223
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
48
 | 
 	$schema .= $add_foreign_key;  | 
| 
224
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
225
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
 	return $schema;  | 
| 
226
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
227
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
228
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _many_to_many {  | 
| 
229
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
13
 | 
 	my $config = shift;  | 
| 
230
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
 	my $expression = $config->{format}->{expression}->(shift);  | 
| 
231
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
79
 | 
 	$expression =~ s/,\s+vice[\s\-]+versa//;  | 
| 
232
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
48
 | 
 	my ($table_name, $has, $foreign_table_name) = split /\s*(has|have)\s+many\s*/, $expression;  | 
| 
233
 | 
5
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
28
 | 
 	return unless $table_name && $foreign_table_name;  | 
| 
234
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
 	$table_name = _normalise_table($config, $config->{format}->{table}->($table_name));  | 
| 
235
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
 	$foreign_table_name = _normalise_table($config, $config->{format}->{table}->($foreign_table_name));  | 
| 
236
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
44
 | 
 	my $map_table = $config->{map_table};  | 
| 
237
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
33
 | 
 	$map_table =~ s/\[%\s*table_name\s*%\]/$table_name/;  | 
| 
238
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
 	$map_table =~ s/\[%\s*foreign_table_name\s*%\]/$foreign_table_name/;  | 
| 
239
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
240
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
 	my $schema = $config->{table}->{$config->{db}->{type}};  | 
| 
241
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
 	$schema =~ s/\[%\s*table_name\s*%\]/$map_table/;  | 
| 
242
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  | 
| 
243
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
 	my $foreign_keys;  | 
| 
244
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
 	my @columns = ($config->{primary_key}->{name} . ' ' . $config->{primary_key}->{type}->{$config->{db}->{type}});  | 
| 
245
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
246
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
 	foreach my $table ($table_name, $foreign_table_name) {  | 
| 
247
 | 
10
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
36
 | 
 		my $foreign_key = $config->{foreign_key}->{singular} ? _singularise($table) : $table;  | 
| 
248
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
 		$foreign_key .= $config->{foreign_key}->{suffix};  | 
| 
249
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
 		$foreign_keys->{$foreign_key} = $table;  | 
| 
250
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
52
 | 
 		push @columns, $foreign_key . ' ' . $config->{foreign_key}->{type}->{$config->{db}->{type}};  | 
| 
251
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
252
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
253
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
 	foreach my $foreign_key (keys %{$foreign_keys}) {  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
    | 
| 
254
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
 		push @columns, _generate_foreign_key_clause($config, $foreign_key, $foreign_keys->{$foreign_key});  | 
| 
255
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
256
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
257
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
 	my $schema_columns = join ',', @columns;  | 
| 
258
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
 	$schema =~ s/\[%\s*columns\s*%\]/$schema_columns/;  | 
| 
259
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
 	return $schema;  | 
| 
260
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
261
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
262
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _has_many {  | 
| 
263
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
9
 | 
 	my $config = shift;  | 
| 
264
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
 	my $expression = $config->{format}->{expression}->(shift);  | 
| 
265
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
49
 | 
 	my ($table_name, $has, $foreign_table_name) = split /\s*(has|have)\s+many\s*/, $expression;  | 
| 
266
 | 
5
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
31
 | 
 	return unless $table_name && $foreign_table_name;  | 
| 
267
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
 	$table_name = _normalise_table($config, $config->{format}->{table}->($table_name));  | 
| 
268
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
 	$foreign_table_name = _normalise_table($config, $config->{format}->{table}->($foreign_table_name));  | 
| 
269
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
 	my $add_column = $config->{add_clause};  | 
| 
270
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
 	$add_column =~ s/\[%\s*table_name\s*%\]/$foreign_table_name/;  | 
| 
271
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
272
 | 
5
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
21
 | 
 	my $foreign_key = $config->{foreign_key}->{singular} ? _singularise($table_name) : $table_name;  | 
| 
273
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
52
 | 
 	$foreign_key .= $config->{foreign_key}->{suffix};  | 
| 
274
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
275
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
 	my $foreign_key_column = $foreign_key . ' ' . $config->{foreign_key}->{type}->{$config->{db}->{type}};  | 
| 
276
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
 	$add_column =~ s/\[%\s*clause\s*%\]/$foreign_key_column/;  | 
| 
277
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
 	my $schema = $add_column;  | 
| 
278
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
279
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
 	my $add_foreign_key = $config->{add_clause};  | 
| 
280
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
 	$add_foreign_key =~ s/\[%\s*table_name\s*%\]/$foreign_table_name/;  | 
| 
281
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
282
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
 	my $foreign_key_clause = _generate_foreign_key_clause($config, $foreign_key, $table_name);  | 
| 
283
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
 	$add_foreign_key =~ s/\[%\s*clause\s*%\]/$foreign_key_clause/;  | 
| 
284
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
 	$schema .= $add_foreign_key;  | 
| 
285
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
286
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
 	return $schema;  | 
| 
287
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
288
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _has_a {  | 
| 
290
 | 
20
 | 
 
 | 
 
 | 
  
20
  
 | 
 
 | 
29
 | 
 	my $config = shift;  | 
| 
291
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
52
 | 
 	my $expression = $config->{format}->{expression}->(shift);  | 
| 
292
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
157
 | 
 	my ($table_name, $has, $columns) = ($expression =~ /^([\w_\-0-9\s]+)\s+(has|have)\s+(.*)$/);  | 
| 
293
 | 
20
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
110
 | 
 	return unless $table_name && $columns;	  | 
| 
294
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
295
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
 	my ($schema, $foreign_keys, $foreign_table_name, $foreign_table_columns, $custom_columns);  | 
| 
296
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
38
 | 
 	my $foreign_key_suffix = $config->{foreign_key}->{suffix};  | 
| 
297
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
49
 | 
 	my $table = {name => _normalise_table($config, $config->{format}->{table}->($table_name))};  | 
| 
298
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
299
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31
 | 
 	push @{$table->{columns}}, {name => $config->{primary_key}->{name}, type => $config->{primary_key}->{type}->{$config->{db}->{type}}};  | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
120
 | 
    | 
| 
300
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
301
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
79
 | 
 	while ($columns =~ /[()]/) {  | 
| 
302
 | 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4776
 | 
 		($foreign_table_name, $foreign_table_columns) = ($columns =~ /([\w_\-0-9\s]+)\s*($RE{balanced}{-parens=>'()'})/);		  | 
| 
303
 | 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5948
 | 
 		($foreign_table_columns) = ($foreign_table_columns =~ /\((.*)\)/);  | 
| 
304
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  | 
| 
305
 | 
35
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
125
 | 
 		if($foreign_table_columns =~ /^\s*(has|have)/) {					  | 
| 
306
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
 			$schema .= _has_a($config, join ' ', ($foreign_table_name , $foreign_table_columns));  | 
| 
307
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
 			$foreign_table_name = _normalise_table($config, $config->{format}->{table}->($foreign_table_name));  | 
| 
308
 | 
5
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
20
 | 
 			my $foreign_key = $config->{foreign_key}->{singular} ? _singularise($foreign_table_name) : $foreign_table_name;  | 
| 
309
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
 			$foreign_key .= $foreign_key_suffix;  | 
| 
310
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
 			$foreign_keys->{$foreign_key} = $foreign_table_name;  | 
| 
311
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
 			$columns =~ s/(\b[\w_\-0-9\s]*)\b\s*($RE{balanced}{-parens=>'()'})/$foreign_key/;  | 
| 
312
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
313
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		else {  | 
| 
314
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
83
 | 
 			$foreign_table_name = $config->{format}->{column}->($foreign_table_name);  | 
| 
315
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			  | 
| 
316
 | 
30
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
128
 | 
 			if ($foreign_table_columns =~ /^reference/) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
317
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
 				my $foreign_key = $foreign_table_name;  | 
| 
318
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
 				my ($reference_table) = ($foreign_table_columns =~ /^references?\s+([\w_\-0-9\s]+)$/);  | 
| 
319
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				  | 
| 
320
 | 
5
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
16
 | 
 				if ($reference_table) {  | 
| 
321
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
 					$foreign_table_name = _normalise_table($config, $config->{format}->{table}->($reference_table));  | 
| 
322
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				}  | 
| 
323
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				else {  | 
| 
324
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 					$foreign_table_name =~ s/$foreign_key_suffix$//;  | 
| 
325
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 					$foreign_table_name = _normalise_table($config, $config->{format}->{table}->($foreign_table_name));  | 
| 
326
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				}  | 
| 
327
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 								  | 
| 
328
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
 				$foreign_keys->{$foreign_key} = $foreign_table_name;  | 
| 
329
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
330
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			elsif (exists $config->{columns}->{$foreign_table_columns}) {  | 
| 
331
 | 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
84
 | 
 				$custom_columns->{$foreign_table_name} = $config->{columns}->{$foreign_table_columns};  | 
| 
332
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
333
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			  | 
| 
334
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
139
 | 
 			$columns =~ s/([\w_\-0-9]*)\s*($RE{balanced}{-parens=>'()'})/$1/; # clean it for the while loop  | 
| 
335
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
336
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
337
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  | 
| 
338
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2619
 | 
 	foreach my $column (split /\s*,\s*/, $columns) {  | 
| 
339
 | 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
184
 | 
 		$column = $config->{format}->{column}->($column);  | 
| 
340
 | 
80
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
177
 | 
 		if (exists $foreign_keys->{$column}) {  | 
| 
341
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
 			push @{$table->{columns}}, {name => $column, type => $config->{foreign_key}->{type}->{$config->{db}->{type}}};  | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
67
 | 
    | 
| 
342
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		else {  | 
| 
344
 | 
70
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
191
 | 
 			if (exists $custom_columns->{$column}) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
345
 | 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
 				push @{$table->{columns}}, {name => $column, type => $custom_columns->{$column}};  | 
| 
 
 | 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
111
 | 
    | 
| 
346
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
347
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			elsif (exists $config->{columns}->{$column}) {  | 
| 
348
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
 				push @{$table->{columns}}, {name => $column, type => $config->{columns}->{$column}};  | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
111
 | 
    | 
| 
349
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
350
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			else {  | 
| 
351
 | 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
 				my $column_type;  | 
| 
352
 | 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
 				DEF: foreach my $column_key (keys %{$config->{columns}}) {  | 
| 
 
 | 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
119
 | 
    | 
| 
353
 | 
310
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
2632
 | 
 					if ($column =~ /$column_key/) {  | 
| 
354
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 						 # first match  | 
| 
355
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
 						$column_type = $column_key;  | 
| 
356
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
43
 | 
 						last DEF;  | 
| 
357
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 					}  | 
| 
358
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				}  | 
| 
359
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				  | 
| 
360
 | 
25
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
81
 | 
 				if ($column_type) {  | 
| 
361
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
 					push @{$table->{columns}}, {name => $column, type => $config->{columns}->{$column_type}};  | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
115
 | 
    | 
| 
362
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				}  | 
| 
363
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				else {  | 
| 
364
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
 					push @{$table->{columns}}, {name => $column, type => $config->{columns}->{name}}; # default  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
    | 
| 
365
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				}  | 
| 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}   | 
| 
367
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
368
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
369
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
370
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
39
 | 
 	my $schema_columns = [map {$_->{name} . ' ' . $_->{type}} @{$table->{columns}}];  | 
| 
 
 | 
100
 | 
 
 | 
 
 | 
 
 | 
 
 | 
275
 | 
    | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
43
 | 
    | 
| 
371
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
372
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31
 | 
 	foreach my $foreign_key (keys %{$foreign_keys}) {		  | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
61
 | 
    | 
| 
373
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
 		push @{$schema_columns}, _generate_foreign_key_clause($config, $foreign_key, $foreign_keys->{$foreign_key});  | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34
 | 
    | 
| 
374
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
375
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
376
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
33
 | 
 	my $schema_columns_string = join ',', @{$schema_columns};  | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
63
 | 
    | 
| 
377
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  | 
| 
378
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
60
 | 
 	$schema .= $config->{table}->{$config->{db}->{type}};  | 
| 
379
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
180
 | 
 	$schema =~ s/\[%\s*table_name\s*%\]/$table->{name}/;  | 
| 
380
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
102
 | 
 	$schema =~ s/\[%\s*columns\s*%\]/$schema_columns_string/;	  | 
| 
381
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
382
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
193
 | 
 	return $schema;  | 
| 
383
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
384
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
385
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _singularise  {  | 
| 
386
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# based on Rose::DB::Object::ConventionManager  | 
| 
387
 | 
85
 | 
 
 | 
 
 | 
  
85
  
 | 
 
 | 
122
 | 
 	my $word = shift;  | 
| 
388
 | 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
170
 | 
 	$word =~ s/ies$/y/i;  | 
| 
389
 | 
85
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
215
 | 
 	return $word if ($word =~ s/ses$/s/);  | 
| 
390
 | 
85
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
256
 | 
 	return $word if($word =~ /[aeiouy]ss$/i);  | 
| 
391
 | 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
178
 | 
 	$word =~ s/s$//i;  | 
| 
392
 | 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
207
 | 
 	return $word;  | 
| 
393
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
394
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
395
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _generate_foreign_key_clause {  | 
| 
396
 | 
30
 | 
 
 | 
 
 | 
  
30
  
 | 
 
 | 
59
 | 
 	my ($config, $foreign_key, $reference_table) = @_;  | 
| 
397
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
56
 | 
 	my $foreign_key_clause = $config->{foreign_key}->{clause};  | 
| 
398
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
144
 | 
 	$foreign_key_clause =~ s/\[%\s*foreign_key\s*%\]/$foreign_key/;  | 
| 
399
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
144
 | 
 	$foreign_key_clause =~ s/\[%\s*reference_table\s*%\]/$reference_table/;  | 
| 
400
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
183
 | 
 	$foreign_key_clause =~ s/\[%\s*reference_primary_key\s*%\]/$config->{primary_key}->{name}/;  | 
| 
401
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
121
 | 
 	return $foreign_key_clause;  | 
| 
402
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
403
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
404
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _normalise_table {  | 
| 
405
 | 
60
 | 
 
 | 
 
 | 
  
60
  
 | 
 
 | 
107
 | 
 	my ($config, $table) = @_;  | 
| 
406
 | 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
149
 | 
 	my $table_name;  | 
| 
407
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
408
 | 
60
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
154
 | 
 	if ($config->{db}->{tables_are_singular}) {  | 
| 
409
 | 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
104
 | 
 		$table_name = _singularise($table);  | 
| 
410
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
411
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	else {  | 
| 
412
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		$table_name = Lingua::EN::Inflect::PL(_singularise($table));  | 
| 
413
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
414
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
415
 | 
60
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
234
 | 
 	return $config->{db}->{table_prefix} . $table_name if defined $config->{db}->{table_prefix};  | 
| 
416
 | 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
98
 | 
 	return $table_name;  | 
| 
417
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
418
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
419
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
420
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
421
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __END__  |