| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Mysql::PrettyPrinter; |
|
2
|
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
22056
|
use strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
34
|
|
|
4
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
3707
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = 0.10; |
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
# Knowledge of MySQL keywords is stored in class variables to aid efficiency in |
|
9
|
|
|
|
|
|
|
# persistent environments (eg mod_perl) |
|
10
|
|
|
|
|
|
|
my $Keywords = []; |
|
11
|
|
|
|
|
|
|
# First-level keywords; outdent |
|
12
|
|
|
|
|
|
|
$Keywords->[0] = [ qw( |
|
13
|
|
|
|
|
|
|
ALTER CHANGE CREATE DELETE DROP FROM GRANT GROUP HAVING INSERT LIMIT MODIFY |
|
14
|
|
|
|
|
|
|
ORDER SELECT SET SHOW UNION UPDATE WHERE |
|
15
|
|
|
|
|
|
|
) ]; |
|
16
|
|
|
|
|
|
|
# Second-level keywords; prepend a linebreak |
|
17
|
|
|
|
|
|
|
$Keywords->[1] = [ qw( |
|
18
|
|
|
|
|
|
|
CROSS INNER JOIN LEFT OUTER RIGHT |
|
19
|
|
|
|
|
|
|
ELSE ELSEIF THEN WHEN |
|
20
|
|
|
|
|
|
|
) ]; |
|
21
|
|
|
|
|
|
|
# Third-level keywords; prepend a linebreak if within a join |
|
22
|
|
|
|
|
|
|
$Keywords->[2] = [ qw( |
|
23
|
|
|
|
|
|
|
AND OR |
|
24
|
|
|
|
|
|
|
) ]; |
|
25
|
|
|
|
|
|
|
# Other keywords; no intention to treat specially |
|
26
|
|
|
|
|
|
|
$Keywords->[3] = [ qw( |
|
27
|
|
|
|
|
|
|
ACCESSIBLE ADD ALL ANALYZE AS ASC ASENSITIVE BEFORE BETWEEN BIGINT BINARY |
|
28
|
|
|
|
|
|
|
BLOB BOTH BY CALL CASCADE CASE CHAR CHARACTER CHECK COLLATE COLUMN |
|
29
|
|
|
|
|
|
|
CONDITION CONNECTION CONSTRAINT CONTINUE CONVERT CURRENT_DATE CURRENT_TIME |
|
30
|
|
|
|
|
|
|
CURRENT_TIMESTAMP CURRENT_USER CURSOR DATABASE DATABASES DAY_HOUR |
|
31
|
|
|
|
|
|
|
DAY_MICROSECOND DAY_MINUTE DAY_SECOND DEC DECIMAL DECLARE DEFAULT DELAYED |
|
32
|
|
|
|
|
|
|
DESC DESCRIBE DETERMINISTIC DISTINCT DISTINCTROW DIV DOUBLE DUAL EACH |
|
33
|
|
|
|
|
|
|
ELSEIF ENCLOSED ESCAPED EXISTS EXIT EXPLAIN FALSE FETCH FLOAT FLOAT4 FLOAT8 |
|
34
|
|
|
|
|
|
|
FOR FORCE FOREIGN FULLTEXT GOTO HIGH_PRIORITY HOUR_MICROSECOND HOUR_MINUTE |
|
35
|
|
|
|
|
|
|
HOUR_SECOND IF IGNORE IN INDEX INFILE INOUT INSENSITIVE INT INT1 INT2 INT3 |
|
36
|
|
|
|
|
|
|
INT4 INT8 INTEGER INTERVAL INTO IS ITERATE KEY KEYS KILL LABEL LEADING |
|
37
|
|
|
|
|
|
|
LEAVE LIKE LIMIT LINEAR LINES LOAD LOCALTIME LOCALTIMESTAMP LOCK LONG |
|
38
|
|
|
|
|
|
|
LONGBLOB LONGTEXT LOOP LOW_PRIORITY MASTER_SSL_VERIFY_SERVER_CERT MATCH |
|
39
|
|
|
|
|
|
|
MEDIUMBLOB MEDIUMINT MEDIUMTEXT MIDDLEINT MINUTE_MICROSECOND MINUTE_SECOND |
|
40
|
|
|
|
|
|
|
MOD MODIFIES NATURAL NOT NO_WRITE_TO_BINLOG NULL NUMERIC ON OPTIMIZE OPTION |
|
41
|
|
|
|
|
|
|
OPTIONALLY OUT OUTFILE PRECISION PRIMARY PROCEDURE PURGE RANGE READ |
|
42
|
|
|
|
|
|
|
READ_ONLY READS READ_WRITE REAL REFERENCES REGEXP RELEASE RENAME REPEAT |
|
43
|
|
|
|
|
|
|
REPLACE REQUIRE RESTRICT RETURN REVOKE RLIKE SCHEMA SCHEMAS |
|
44
|
|
|
|
|
|
|
SECOND_MICROSECOND SENSITIVE SEPARATOR SHOW SMALLINT SPATIAL SPECIFIC SQL |
|
45
|
|
|
|
|
|
|
SQL_BIG_RESULT SQL_CALC_FOUND_ROWS SQLEXCEPTION SQL_SMALL_RESULT SQLSTATE |
|
46
|
|
|
|
|
|
|
SQLWARNING SSL STARTING STRAIGHT_JOIN TABLE TABLES TEMPORARY TERMINATED |
|
47
|
|
|
|
|
|
|
TINYBLOB TINYINT TINYTEXT TO TRAILING TRIGGER TRUE UNDO UNIQUE UNLOCK |
|
48
|
|
|
|
|
|
|
UNSIGNED UPGRADE USAGE USE USING UTC_DATE UTC_TIME UTC_TIMESTAMP VALUES |
|
49
|
|
|
|
|
|
|
VARBINARY VARCHAR VARCHARACTER VARYING WHILE WITH WRITE XOR YEAR_MONTH |
|
50
|
|
|
|
|
|
|
ZEROFILL |
|
51
|
|
|
|
|
|
|
) ]; |
|
52
|
|
|
|
|
|
|
my $Keyword = { map { $_ => 4 } @{$Keywords->[3]} }; |
|
53
|
|
|
|
|
|
|
foreach my $n (1..3) { |
|
54
|
|
|
|
|
|
|
%$Keyword = (%$Keyword, map { $_ => $n } @{$Keywords->[$n - 1]}); |
|
55
|
|
|
|
|
|
|
} |
|
56
|
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
sub new { |
|
58
|
0
|
|
|
0
|
1
|
|
my ($class, %param) = @_; |
|
59
|
0
|
|
|
|
|
|
return bless { |
|
60
|
|
|
|
|
|
|
space => ' ', |
|
61
|
|
|
|
|
|
|
break => "\n", |
|
62
|
|
|
|
|
|
|
indent => ' ', |
|
63
|
|
|
|
|
|
|
wrap => undef, |
|
64
|
|
|
|
|
|
|
sql => '', |
|
65
|
|
|
|
|
|
|
tokens => [], |
|
66
|
|
|
|
|
|
|
_level => 0, |
|
67
|
|
|
|
|
|
|
_pending => 1, |
|
68
|
|
|
|
|
|
|
%param |
|
69
|
|
|
|
|
|
|
}, $class; |
|
70
|
|
|
|
|
|
|
} |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
sub sql { |
|
73
|
0
|
|
|
0
|
1
|
|
my ($self, $sql) = @_; |
|
74
|
0
|
0
|
|
|
|
|
if (defined($sql)) { |
|
75
|
|
|
|
|
|
|
# Setter |
|
76
|
0
|
|
|
|
|
|
$self->{sql} = $sql; |
|
77
|
0
|
|
|
|
|
|
$self->{_pending} = 1; |
|
78
|
0
|
|
|
|
|
|
return $self; |
|
79
|
|
|
|
|
|
|
} |
|
80
|
|
|
|
|
|
|
else { |
|
81
|
|
|
|
|
|
|
# Getter |
|
82
|
0
|
|
|
|
|
|
return $self->{sql}; |
|
83
|
|
|
|
|
|
|
} |
|
84
|
|
|
|
|
|
|
} |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
sub add_sql { |
|
87
|
0
|
|
|
0
|
1
|
|
my ($self, $sql) = @_; |
|
88
|
0
|
0
|
|
|
|
|
$sql =~ s/^\s*/ / if length $self->{sql}; |
|
89
|
0
|
|
|
|
|
|
$self->{sql} .= $sql; |
|
90
|
0
|
|
|
|
|
|
$self->{_pending} = 1; |
|
91
|
0
|
|
|
|
|
|
return $self; |
|
92
|
|
|
|
|
|
|
} |
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub make_tokens { |
|
95
|
0
|
|
|
0
|
1
|
|
my ($self, %param) = @_; |
|
96
|
0
|
0
|
|
|
|
|
if (%param) { |
|
97
|
0
|
|
|
|
|
|
%$self = ( %$self, %param ); |
|
98
|
|
|
|
|
|
|
} |
|
99
|
0
|
0
|
|
|
|
|
if (exists $param{sql}) { |
|
100
|
0
|
|
|
|
|
|
$self->{_pending} = 1; |
|
101
|
|
|
|
|
|
|
} |
|
102
|
0
|
0
|
0
|
|
|
|
if ($self->{_pending} and length $self->{sql}) { |
|
103
|
0
|
|
|
|
|
|
@{ $self->{tokens} } = $self->lexicals($self->{sql}, 1); |
|
|
0
|
|
|
|
|
|
|
|
104
|
0
|
|
|
|
|
|
$self->{_pending} = 0; |
|
105
|
|
|
|
|
|
|
} |
|
106
|
0
|
|
|
|
|
|
return $self; |
|
107
|
|
|
|
|
|
|
} |
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub tokens { |
|
110
|
0
|
|
|
0
|
1
|
|
my ($self, @toks) = @_; |
|
111
|
0
|
0
|
|
|
|
|
if (scalar @toks) { |
|
112
|
|
|
|
|
|
|
# Setter |
|
113
|
0
|
|
|
|
|
|
@{ $self->{sql} } = @toks; |
|
|
0
|
|
|
|
|
|
|
|
114
|
0
|
|
|
|
|
|
$self->{_pending} = 0; |
|
115
|
0
|
|
|
|
|
|
return $self; |
|
116
|
|
|
|
|
|
|
} |
|
117
|
|
|
|
|
|
|
else { |
|
118
|
|
|
|
|
|
|
# Getter |
|
119
|
0
|
0
|
|
|
|
|
if ($self->{_pending}) { |
|
120
|
0
|
|
|
|
|
|
warn "Probable data conflict; suspicious invocation sequence"; |
|
121
|
|
|
|
|
|
|
} |
|
122
|
0
|
0
|
|
|
|
|
return wantarray ? @{$self->{tokens}} : $self->{tokens}; |
|
|
0
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
} |
|
124
|
|
|
|
|
|
|
} |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
sub add_tokens { |
|
127
|
0
|
|
|
0
|
1
|
|
my ($self, @toks) = @_; |
|
128
|
0
|
0
|
|
|
|
|
if ($self->{_pending}) { |
|
129
|
0
|
|
|
|
|
|
warn "Probable data conflict; suspicious invocation sequence"; |
|
130
|
|
|
|
|
|
|
} |
|
131
|
0
|
|
|
|
|
|
push(@{$self->{tokens}}, @toks); |
|
|
0
|
|
|
|
|
|
|
|
132
|
0
|
|
|
|
|
|
$self->{_pending} = 0; |
|
133
|
0
|
|
|
|
|
|
return $self; |
|
134
|
|
|
|
|
|
|
} |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
sub format { |
|
137
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
|
138
|
0
|
0
|
|
|
|
|
unless (ref $self) { |
|
|
|
0
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
# Shortcut used; need to start from scratch |
|
140
|
0
|
|
|
|
|
|
$self = $self->new(@_); |
|
141
|
0
|
|
|
|
|
|
$self->make_tokens; |
|
142
|
|
|
|
|
|
|
} |
|
143
|
|
|
|
|
|
|
elsif ($self->{_pending}) { |
|
144
|
|
|
|
|
|
|
# SQL waiting to be tokenised |
|
145
|
0
|
|
|
|
|
|
$self->make_tokens(@_); |
|
146
|
|
|
|
|
|
|
} |
|
147
|
|
|
|
|
|
|
|
|
148
|
0
|
|
|
|
|
|
$self->{_output} = ''; # Ultimate output |
|
149
|
0
|
|
|
|
|
|
$self->{_levels} = []; # Nested levels |
|
150
|
0
|
|
|
|
|
|
$self->{_blank_line} = 1; # Whether in a blank line |
|
151
|
0
|
|
|
|
|
|
$self->{_previous} = ''; # Previous token |
|
152
|
0
|
|
|
|
|
|
$self->{_joining} = 0; # Whether in a compound join |
|
153
|
0
|
|
|
|
|
|
$self->{_conditioning} = 0; # Whether in a conditional |
|
154
|
|
|
|
|
|
|
|
|
155
|
0
|
|
|
|
|
|
while (defined(my $token = shift @{$self->{tokens}} )) { |
|
|
0
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
# Some preprocessing of token |
|
157
|
0
|
0
|
|
|
|
|
if ($self->_is_keyword(uc $token)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
# Keyword => uppercase |
|
159
|
0
|
|
|
|
|
|
$token = uc $token; |
|
160
|
|
|
|
|
|
|
} |
|
161
|
|
|
|
|
|
|
elsif ($token =~ /^[,.;\(\)]$/) { |
|
162
|
|
|
|
|
|
|
# Punctuation |
|
163
|
|
|
|
|
|
|
; # nothing |
|
164
|
|
|
|
|
|
|
} |
|
165
|
|
|
|
|
|
|
elsif ($self->{_pending_nl}) { |
|
166
|
|
|
|
|
|
|
# Non-keyword/punctuation |
|
167
|
0
|
|
|
|
|
|
$self->_new_line; |
|
168
|
0
|
|
|
|
|
|
$self->{_pending_nl} = 0; |
|
169
|
|
|
|
|
|
|
} |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
# Build output |
|
172
|
0
|
0
|
0
|
|
|
|
if ($token eq '(') { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
173
|
0
|
|
|
|
|
|
push @{ $self->{_levels} }, $self->{_level}; |
|
|
0
|
|
|
|
|
|
|
|
174
|
0
|
|
|
|
|
|
$self->_add_token($token)->_new_line->_over; |
|
175
|
|
|
|
|
|
|
} |
|
176
|
|
|
|
|
|
|
elsif ($token eq ')') { |
|
177
|
0
|
|
0
|
|
|
|
$self->{_level} = pop(@{ $self->{_levels} }) || 0; |
|
178
|
0
|
|
|
|
|
|
$self->_new_line->_add_token($token); |
|
179
|
0
|
0
|
0
|
|
|
|
$self->_new_line |
|
180
|
|
|
|
|
|
|
unless uc($self->_next_token) eq 'AS' |
|
181
|
|
|
|
|
|
|
|| $self->_next_token eq ','; |
|
182
|
|
|
|
|
|
|
} |
|
183
|
|
|
|
|
|
|
elsif ($token eq ',') { |
|
184
|
0
|
|
|
|
|
|
$self->_add_token($token)->_new_line; |
|
185
|
|
|
|
|
|
|
} |
|
186
|
|
|
|
|
|
|
elsif ($token eq ';') { |
|
187
|
0
|
|
|
|
|
|
$self->_add_token($token)->_new_line; |
|
188
|
|
|
|
|
|
|
# End of statement; remove all indentation |
|
189
|
0
|
|
|
|
|
|
@{ $self->{_levels} } = (); |
|
|
0
|
|
|
|
|
|
|
|
190
|
0
|
|
|
|
|
|
$self->{_level} = 0; |
|
191
|
|
|
|
|
|
|
} |
|
192
|
|
|
|
|
|
|
elsif ($token eq 'UNION') { |
|
193
|
|
|
|
|
|
|
# End of statement; remove all indentation |
|
194
|
0
|
|
|
|
|
|
@{ $self->{_levels} } = (); |
|
|
0
|
|
|
|
|
|
|
|
195
|
0
|
|
|
|
|
|
$self->{_level} = 0; |
|
196
|
0
|
|
|
|
|
|
$self->_new_line->_add_token($token, 'K')->_new_line; |
|
197
|
|
|
|
|
|
|
} |
|
198
|
|
|
|
|
|
|
elsif ($token eq 'JOIN') { |
|
199
|
0
|
0
|
|
|
|
|
unless ($self->_is_keyword($self->{_previous})) { |
|
200
|
0
|
|
|
|
|
|
$self->_new_line; |
|
201
|
|
|
|
|
|
|
} |
|
202
|
0
|
|
|
|
|
|
$self->_add_token($token, 'K'); |
|
203
|
|
|
|
|
|
|
} |
|
204
|
|
|
|
|
|
|
elsif ($token eq 'ON') { |
|
205
|
0
|
|
|
|
|
|
$self->_add_token($token, 'K'); |
|
206
|
0
|
0
|
|
|
|
|
if ($self->_is_keyword($self->_next_keyword) == 3) { |
|
207
|
0
|
|
|
|
|
|
$self->_new_line->_over; |
|
208
|
0
|
|
|
|
|
|
$self->{_joining} = 1; |
|
209
|
|
|
|
|
|
|
} |
|
210
|
|
|
|
|
|
|
} |
|
211
|
|
|
|
|
|
|
elsif ($token eq 'CASE') { |
|
212
|
0
|
|
|
|
|
|
$self->_add_token($token, 'K')->_over; |
|
213
|
0
|
|
|
|
|
|
$self->{_conditioning} = 1; |
|
214
|
|
|
|
|
|
|
} |
|
215
|
|
|
|
|
|
|
elsif ($token eq 'END' and $self->{_conditioning}) { |
|
216
|
0
|
|
|
|
|
|
$self->_back->_new_line->_add_token($token, 'K'); |
|
217
|
0
|
|
|
|
|
|
$self->{_conditioning} = 0; |
|
218
|
|
|
|
|
|
|
} |
|
219
|
|
|
|
|
|
|
elsif ($self->_is_keyword($token) == 1) { |
|
220
|
|
|
|
|
|
|
# First-level keyword |
|
221
|
0
|
0
|
|
|
|
|
$self->_back unless $self->{_previous} eq '('; |
|
222
|
0
|
0
|
|
|
|
|
if ($self->{_joining}) { |
|
223
|
0
|
|
|
|
|
|
$self->_back; |
|
224
|
0
|
|
|
|
|
|
$self->{_joining} = 0; |
|
225
|
|
|
|
|
|
|
} |
|
226
|
0
|
|
|
|
|
|
$self->_new_line->_add_token($token, 'K')->_over; |
|
227
|
0
|
|
|
|
|
|
$self->{_pending_nl} = 1; |
|
228
|
|
|
|
|
|
|
} |
|
229
|
|
|
|
|
|
|
elsif ($self->_is_keyword($token) == 2) { |
|
230
|
|
|
|
|
|
|
# Second-level keyword |
|
231
|
0
|
0
|
|
|
|
|
if ($self->{_joining}) { |
|
232
|
0
|
|
|
|
|
|
$self->_back; |
|
233
|
0
|
|
|
|
|
|
$self->{_joining} = 0; |
|
234
|
|
|
|
|
|
|
} |
|
235
|
0
|
|
|
|
|
|
$self->_new_line->_add_token($token, 'K'); |
|
236
|
|
|
|
|
|
|
} |
|
237
|
|
|
|
|
|
|
elsif ($self->_is_keyword($token) == 3) { |
|
238
|
|
|
|
|
|
|
# Third-level keyword |
|
239
|
0
|
|
|
|
|
|
$self->_new_line->_add_token($token, 'K'); |
|
240
|
|
|
|
|
|
|
} |
|
241
|
|
|
|
|
|
|
elsif ($self->_is_keyword($token)) { |
|
242
|
|
|
|
|
|
|
# Other keyword |
|
243
|
0
|
|
|
|
|
|
$self->_add_token($token, 'K'); |
|
244
|
|
|
|
|
|
|
} |
|
245
|
|
|
|
|
|
|
elsif ($token =~ /^"[^"']*"$/) { |
|
246
|
|
|
|
|
|
|
# Quoted string |
|
247
|
0
|
|
|
|
|
|
$token =~ s/"/'/g; |
|
248
|
0
|
|
|
|
|
|
$self->_add_token($token, 'L'); |
|
249
|
|
|
|
|
|
|
} |
|
250
|
|
|
|
|
|
|
elsif ($token =~ /^'.*'$/) { |
|
251
|
|
|
|
|
|
|
# Quoted string |
|
252
|
0
|
|
|
|
|
|
$self->_add_token($token, 'L'); |
|
253
|
|
|
|
|
|
|
} |
|
254
|
|
|
|
|
|
|
elsif ($token =~ /^\d+$/) { |
|
255
|
|
|
|
|
|
|
# Number |
|
256
|
0
|
|
|
|
|
|
$self->_add_token($token, 'L'); |
|
257
|
|
|
|
|
|
|
} |
|
258
|
|
|
|
|
|
|
elsif ($self->_next_token eq '(') { |
|
259
|
0
|
|
|
|
|
|
$token = lc $token; |
|
260
|
0
|
|
|
|
|
|
$self->_add_token($token, 'F'); |
|
261
|
|
|
|
|
|
|
} |
|
262
|
|
|
|
|
|
|
else { |
|
263
|
0
|
|
|
|
|
|
$self->_add_token($token); |
|
264
|
|
|
|
|
|
|
} |
|
265
|
|
|
|
|
|
|
#TODO: Identify comments |
|
266
|
|
|
|
|
|
|
|
|
267
|
0
|
|
|
|
|
|
$self->{_previous} = $token; |
|
268
|
|
|
|
|
|
|
} |
|
269
|
|
|
|
|
|
|
|
|
270
|
0
|
|
|
|
|
|
$self->_new_line; |
|
271
|
0
|
|
|
|
|
|
return $self->{_output}; |
|
272
|
|
|
|
|
|
|
} |
|
273
|
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
# Add a token to the formatted string. |
|
275
|
|
|
|
|
|
|
sub _add_token { |
|
276
|
0
|
|
|
0
|
|
|
my ($self, $token, $type) = @_; |
|
277
|
0
|
|
0
|
|
|
|
$type ||= ''; |
|
278
|
|
|
|
|
|
|
|
|
279
|
0
|
0
|
|
|
|
|
if ($self->{wrap}) { |
|
280
|
|
|
|
|
|
|
# Format wrapping of keywords, etc |
|
281
|
0
|
0
|
0
|
|
|
|
if ($type eq 'K' and exists $self->{wrap}->{keyword}) { |
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
282
|
|
|
|
|
|
|
# Keyword |
|
283
|
0
|
|
|
|
|
|
$token = $self->{wrap}->{keyword}->[0] |
|
284
|
|
|
|
|
|
|
. $token |
|
285
|
|
|
|
|
|
|
. $self->{wrap}->{keyword}->[1]; |
|
286
|
|
|
|
|
|
|
} |
|
287
|
|
|
|
|
|
|
elsif ($type eq 'F' and exists $self->{wrap}->{function}) { |
|
288
|
|
|
|
|
|
|
# Function |
|
289
|
0
|
|
|
|
|
|
$token = $self->{wrap}->{function}->[0] |
|
290
|
|
|
|
|
|
|
. $token |
|
291
|
|
|
|
|
|
|
. $self->{wrap}->{function}->[1]; |
|
292
|
|
|
|
|
|
|
} |
|
293
|
|
|
|
|
|
|
elsif ($type eq 'L' and exists $self->{wrap}->{literal}) { |
|
294
|
|
|
|
|
|
|
# Literal |
|
295
|
0
|
|
|
|
|
|
$token = $self->{wrap}->{literal}->[0] |
|
296
|
|
|
|
|
|
|
. $token |
|
297
|
|
|
|
|
|
|
. $self->{wrap}->{literal}->[1]; |
|
298
|
|
|
|
|
|
|
} |
|
299
|
|
|
|
|
|
|
elsif ($type eq 'C' and exists $self->{wrap}->{comment}) { |
|
300
|
|
|
|
|
|
|
# Comment |
|
301
|
0
|
|
|
|
|
|
$token = $self->{wrap}->{comment}->[0] |
|
302
|
|
|
|
|
|
|
. $token |
|
303
|
|
|
|
|
|
|
. $self->{wrap}->{comment}->[1]; |
|
304
|
|
|
|
|
|
|
} |
|
305
|
|
|
|
|
|
|
} |
|
306
|
|
|
|
|
|
|
|
|
307
|
0
|
0
|
0
|
|
|
|
if ($token =~ /^[,.;]$/ or $self->{_previous} eq '.') { |
|
|
|
0
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
308
|
|
|
|
|
|
|
# Punctuation => no indent |
|
309
|
|
|
|
|
|
|
; |
|
310
|
|
|
|
|
|
|
} |
|
311
|
|
|
|
|
|
|
elsif ($token eq '(' |
|
312
|
|
|
|
|
|
|
and not $self->_is_keyword($self->{_previous}) |
|
313
|
|
|
|
|
|
|
and not $self->{_previous} eq ',') { |
|
314
|
|
|
|
|
|
|
# Function => no indent |
|
315
|
|
|
|
|
|
|
; |
|
316
|
|
|
|
|
|
|
} |
|
317
|
|
|
|
|
|
|
else { |
|
318
|
0
|
|
|
|
|
|
$self->{_output} .= $self->_indent; |
|
319
|
|
|
|
|
|
|
} |
|
320
|
|
|
|
|
|
|
|
|
321
|
0
|
|
|
|
|
|
$self->{_output} .= $token; |
|
322
|
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
# This can't be the beginning of a new line anymore. |
|
324
|
0
|
|
|
|
|
|
$self->{_blank_line} = 0; |
|
325
|
0
|
|
|
|
|
|
return $self; |
|
326
|
|
|
|
|
|
|
} |
|
327
|
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
# Increase the indentation level. |
|
329
|
|
|
|
|
|
|
sub _over { |
|
330
|
0
|
|
|
0
|
|
|
my ($self) = @_; |
|
331
|
0
|
|
|
|
|
|
++$self->{_level}; |
|
332
|
0
|
|
|
|
|
|
return $self; |
|
333
|
|
|
|
|
|
|
} |
|
334
|
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
# Decrease the indentation level. |
|
336
|
|
|
|
|
|
|
sub _back { |
|
337
|
0
|
|
|
0
|
|
|
my ($self) = @_; |
|
338
|
0
|
0
|
|
|
|
|
--$self->{_level} if $self->{_level} > 0; |
|
339
|
0
|
|
|
|
|
|
return $self; |
|
340
|
|
|
|
|
|
|
} |
|
341
|
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
# Return a string of spaces according to the current indentation level and the |
|
343
|
|
|
|
|
|
|
# spaces setting for indenting. |
|
344
|
|
|
|
|
|
|
sub _indent { |
|
345
|
0
|
|
|
0
|
|
|
my ($self) = @_; |
|
346
|
0
|
0
|
|
|
|
|
if ($self->{_blank_line}) { |
|
347
|
0
|
|
|
|
|
|
return $self->{indent} x $self->{_level}; |
|
348
|
|
|
|
|
|
|
} |
|
349
|
|
|
|
|
|
|
else { |
|
350
|
0
|
|
|
|
|
|
return $self->{space}; |
|
351
|
|
|
|
|
|
|
} |
|
352
|
|
|
|
|
|
|
} |
|
353
|
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
# Add a line break, but make sure there are no empty lines. |
|
355
|
|
|
|
|
|
|
sub _new_line { |
|
356
|
0
|
|
|
0
|
|
|
my ($self) = @_; |
|
357
|
0
|
0
|
|
|
|
|
$self->{_output} .= $self->{break} unless $self->{_blank_line}; |
|
358
|
0
|
|
|
|
|
|
$self->{_blank_line} = 1; |
|
359
|
0
|
|
|
|
|
|
return $self; |
|
360
|
|
|
|
|
|
|
} |
|
361
|
|
|
|
|
|
|
|
|
362
|
0
|
0
|
|
0
|
|
|
sub _next_token { scalar @{ $_[0]->{tokens} } ? $_[0]->{tokens}->[0] : '' } |
|
|
0
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
sub _next_keyword { |
|
365
|
0
|
|
|
0
|
|
|
my ($self) = @_; |
|
366
|
0
|
|
|
|
|
|
my $len = scalar @{ $self->{tokens} }; |
|
|
0
|
|
|
|
|
|
|
|
367
|
0
|
|
|
|
|
|
for (my $i = 0; $i < $len; $i++) { |
|
368
|
0
|
0
|
|
|
|
|
if ($self->_is_keyword(uc $self->{tokens}->[$i])) { |
|
369
|
0
|
|
|
|
|
|
return(uc $self->{tokens}->[$i]); |
|
370
|
|
|
|
|
|
|
} |
|
371
|
|
|
|
|
|
|
} |
|
372
|
0
|
|
|
|
|
|
return ''; |
|
373
|
|
|
|
|
|
|
} |
|
374
|
|
|
|
|
|
|
|
|
375
|
0
|
0
|
0
|
0
|
|
|
sub _is_keyword { defined $_[1] && exists $Keyword->{$_[1]} ? $Keyword->{$_[1]} : 0 } |
|
376
|
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
sub lexicals { |
|
378
|
0
|
|
|
0
|
1
|
|
my ($proto, $sql, $omit_whitespace_tokens) = @_; |
|
379
|
0
|
|
|
|
|
|
my @tokens = $sql =~ m{ |
|
380
|
|
|
|
|
|
|
(?:--|\#)[\ \t\S]* # single line comments |
|
381
|
|
|
|
|
|
|
| |
|
382
|
|
|
|
|
|
|
(?:<>|<=>|>=|<=|==|=|!=|!|<<|>>|<|>|\|\||\||&&|&|-|\+|\*(?!/)|/(?!\*)|\%|~|\^|\?) |
|
383
|
|
|
|
|
|
|
# operators and tests |
|
384
|
|
|
|
|
|
|
| |
|
385
|
|
|
|
|
|
|
[\[\]\(\),;.] # punctuation (parenthesis, comma) |
|
386
|
|
|
|
|
|
|
| |
|
387
|
|
|
|
|
|
|
\'\'(?!\') # empty single quoted string |
|
388
|
|
|
|
|
|
|
| |
|
389
|
|
|
|
|
|
|
\"\"(?!\"") # empty double quoted string |
|
390
|
|
|
|
|
|
|
| |
|
391
|
|
|
|
|
|
|
".*?(?:(?:""){1,}"|(?
|
|
392
|
|
|
|
|
|
|
# anything inside double quotes, ungreedy |
|
393
|
|
|
|
|
|
|
| |
|
394
|
|
|
|
|
|
|
`.*?(?:(?:``){1,}`|(?
|
|
395
|
|
|
|
|
|
|
# anything inside backticks quotes, ungreedy |
|
396
|
|
|
|
|
|
|
| |
|
397
|
|
|
|
|
|
|
'.*?(?:(?:''){1,}'|(?
|
|
398
|
|
|
|
|
|
|
# anything inside single quotes, ungreedy. |
|
399
|
|
|
|
|
|
|
| |
|
400
|
|
|
|
|
|
|
/\*[\ \t\n\S]*?\*/ # C style comments |
|
401
|
|
|
|
|
|
|
| |
|
402
|
|
|
|
|
|
|
(?:[\w:@]+(?:\.(?:\w+|\*)?)*) |
|
403
|
|
|
|
|
|
|
# words, standard named placeholders, db.table.*, db.* |
|
404
|
|
|
|
|
|
|
| |
|
405
|
|
|
|
|
|
|
(?:\${1,2}) # dollars |
|
406
|
|
|
|
|
|
|
| |
|
407
|
|
|
|
|
|
|
[\t\ ]+ # any kind of white spaces |
|
408
|
|
|
|
|
|
|
}mxg; |
|
409
|
|
|
|
|
|
|
|
|
410
|
0
|
0
|
|
|
|
|
@tokens = grep(!/^[\s\n\r]*$/, @tokens) if $omit_whitespace_tokens; |
|
411
|
0
|
0
|
|
|
|
|
return wantarray ? @tokens : \@tokens; |
|
412
|
|
|
|
|
|
|
} |
|
413
|
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
sub passthrough { |
|
415
|
0
|
|
|
0
|
1
|
|
my ($class, @args) = @_; |
|
416
|
0
|
|
|
|
|
|
my %param; |
|
417
|
0
|
0
|
|
|
|
|
if (ref($class)) { |
|
418
|
0
|
|
|
|
|
|
die "'passthrough' is a class method"; |
|
419
|
|
|
|
|
|
|
} |
|
420
|
0
|
|
|
|
|
|
eval { |
|
421
|
0
|
|
0
|
|
|
|
%param = @args || (); |
|
422
|
|
|
|
|
|
|
}; |
|
423
|
0
|
0
|
|
|
|
|
if ($@) { |
|
424
|
0
|
|
|
|
|
|
die "Options should be passed in hash style\n". $@; |
|
425
|
|
|
|
|
|
|
} |
|
426
|
0
|
|
|
|
|
|
local($/) = ''; |
|
427
|
0
|
|
|
|
|
|
print $class->format(sql => <>); |
|
428
|
|
|
|
|
|
|
} |
|
429
|
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
1; |
|
431
|
|
|
|
|
|
|
__END__ |