File Coverage

blib/lib/SQL/Tokenizer.pm
Criterion Covered Total %
statement 19 19 100.0
branch 3 4 75.0
condition n/a
subroutine 6 6 100.0
pod 2 2 100.0
total 30 31 96.7


line stmt bran cond sub pod time code
1             package SQL::Tokenizer;
2              
3 16     16   469330 use warnings;
  16         37  
  16         598  
4 16     16   90 use strict;
  16         30  
  16         540  
5              
6 16     16   816 use 5.006002;
  16         67  
  16         762  
7              
8 16     16   89 use Exporter;
  16         28  
  16         42203  
9              
10             our @ISA = qw(Exporter);
11              
12             our @EXPORT_OK= qw(tokenize_sql);
13              
14             our $VERSION= '0.24';
15              
16             my $re= qr{
17             (
18             (?:--|\#)[\ \t\S]* # single line comments
19             |
20             (?:<>|<=>|>=|<=|==|=|!=|!|<<|>>|<|>|\|\||\||&&|&|-|\+|\*(?!/)|/(?!\*)|\%|~|\^|\?)
21             # operators and tests
22             |
23             [\[\]\(\),;.] # punctuation (parenthesis, comma)
24             |
25             \'\'(?!\') # empty single quoted string
26             |
27             \"\"(?!\"") # empty double quoted string
28             |
29             "(?>(?:(?>[^"\\]+)|""|\\.)*)+"
30             # anything inside double quotes, ungreedy
31             |
32             `(?>(?:(?>[^`\\]+)|``|\\.)*)+`
33             # anything inside backticks quotes, ungreedy
34             |
35             '(?>(?:(?>[^'\\]+)|''|\\.)*)+'
36             # anything inside single quotes, ungreedy.
37             |
38             /\*[\ \t\r\n\S]*?\*/ # C style comments
39             |
40             (?:[\w:@]+(?:\.(?:\w+|\*)?)*)
41             # words, standard named placeholders, db.table.*, db.*
42             |
43             (?: \$_\$ | \$\d+ | \${1,2} )
44             # dollar expressions - eg $_$ $3 $$
45             |
46             \n # newline
47             |
48             [\t\ ]+ # any kind of white spaces
49             )
50             }smx;
51              
52             sub tokenize_sql {
53 66     66 1 129 my ( $query, $remove_white_tokens )= @_;
54              
55 66         185617 my @query= $query =~ m{$re}smxg;
56              
57 66 100       263 if ($remove_white_tokens) {
58 4         302 @query= grep( !/^[\s\n\r]*$/, @query );
59             }
60              
61 66 50       1086 return wantarray ? @query : \@query;
62             }
63              
64             sub tokenize {
65 64     64 1 52467 my $class= shift;
66 64         180 return tokenize_sql(@_);
67             }
68              
69             1;
70              
71             =pod
72              
73             =head1 NAME
74              
75             SQL::Tokenizer - A simple SQL tokenizer.
76              
77             =head1 VERSION
78              
79             0.20
80              
81             =head1 SYNOPSIS
82              
83             use SQL::Tokenizer qw(tokenize_sql);
84              
85             my $query= q{SELECT 1 + 1};
86             my @tokens= SQL::Tokenizer->tokenize($query);
87              
88             # @tokens now contains ('SELECT', ' ', '1', ' ', '+', ' ', '1')
89              
90             @tokens= tokenize_sql($query); # procedural interface
91              
92             =head1 DESCRIPTION
93              
94             SQL::Tokenizer is a simple tokenizer for SQL queries. It does not claim to be
95             a parser or query verifier. It just creates sane tokens from a valid SQL
96             query.
97              
98             It supports SQL with comments like:
99              
100             -- This query is used to insert a message into
101             -- logs table
102             INSERT INTO log (application, message) VALUES (?, ?)
103              
104             Also supports C<''>, C<""> and C<\'> escaping methods, so tokenizing queries
105             like the one below should not be a problem:
106              
107             INSERT INTO log (application, message)
108             VALUES ('myapp', 'Hey, this is a ''single quoted string''!')
109              
110             =head1 API
111              
112             =over 4
113              
114             =item tokenize_sql
115              
116             use SQL::Tokenizer qw(tokenize_sql);
117              
118             my @tokens= tokenize_sql($query);
119             my $tokens= tokenize_sql($query);
120              
121             $tokens= tokenize_sql( $query, $remove_white_tokens );
122              
123             C can be imported to current namespace on request. It receives a
124             SQL query, and returns an array of tokens if called in list context, or an
125             arrayref if called in scalar context.
126              
127             =item tokenize
128              
129             my @tokens= SQL::Tokenizer->tokenize($query);
130             my $tokens= SQL::Tokenizer->tokenize($query);
131              
132             $tokens= SQL::Tokenizer->tokenize( $query, $remove_white_tokens );
133              
134             This is the only available class method. It receives a SQL query, and returns an
135             array of tokens if called in list context, or an arrayref if called in scalar
136             context.
137              
138             If C<$remove_white_tokens> is true, white spaces only tokens will be removed from
139             result.
140              
141             =back
142              
143             =head1 ACKNOWLEDGEMENTS
144              
145             =over 4
146              
147             =item
148              
149             Evan Harris, for implementing Shell comment style and SQL operators.
150              
151             =item
152              
153             Charlie Hills, for spotting a lot of important issues I haven't thought.
154              
155             =item
156              
157             Jonas Kramer, for fixing MySQL quoted strings and treating dot as punctuation character correctly.
158              
159             =item
160              
161             Emanuele Zeppieri, for asking to fix SQL::Tokenizer to support dollars as well.
162              
163             =item
164              
165             Nigel Metheringham, for extending the dollar signal support.
166              
167             =item
168              
169             Devin Withers, for making it not choke on CR+LF in comments.
170              
171             =item
172              
173             Luc Lanthier, for simplifying the regex and make it not choke on backslashes.
174              
175             =back
176              
177             =head1 AUTHOR
178              
179             Copyright (c) 2007, 2008, 2009, 2010, 2011 Igor Sutton Lopes "". All rights
180             reserved.
181              
182             This module is free software; you can redistribute it and/or modify it under
183             the same terms as Perl itself.
184              
185             =cut
186