anbt-sql-formatter 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/anbt-sql-formatter +0 -3
- data/lib/anbt-sql-formatter/coarse-tokenizer.rb +1 -3
- data/lib/anbt-sql-formatter/exception.rb +0 -2
- data/lib/anbt-sql-formatter/formatter.rb +50 -57
- data/lib/anbt-sql-formatter/helper.rb +42 -56
- data/lib/anbt-sql-formatter/parser.rb +40 -52
- data/lib/anbt-sql-formatter/rule.rb +5 -2
- data/lib/anbt-sql-formatter/token.rb +1 -10
- data/lib/anbt-sql-formatter/version.rb +1 -1
- data/test/helper.rb +7 -1
- data/test/test_coarse-tokenizer.rb +327 -228
- data/test/test_formatter.rb +363 -276
- data/test/test_helper.rb +2 -2
- data/test/test_parser.rb +302 -213
- data/test/test_rule.rb +10 -8
- metadata +21 -31
data/bin/anbt-sql-formatter
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
#! /usr/bin/ruby1.8
|
2
2
|
# -*- coding: utf-8 -*-
|
3
3
|
|
4
|
-
require "pp"
|
5
|
-
|
6
4
|
begin
|
7
5
|
require "anbt-sql-formatter/formatter"
|
8
6
|
rescue LoadError
|
@@ -44,7 +42,6 @@ def main
|
|
44
42
|
formatter = AnbtSql::Formatter.new(rule)
|
45
43
|
result = formatter.format(src)
|
46
44
|
puts result
|
47
|
-
#pp result
|
48
45
|
end
|
49
46
|
|
50
47
|
main()
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
|
-
require "pp"
|
4
|
-
|
5
3
|
require "anbt-sql-formatter/rule"
|
6
4
|
require "anbt-sql-formatter/parser"
|
7
5
|
require "anbt-sql-formatter/exception"
|
@@ -11,6 +9,8 @@ require "anbt-sql-formatter/helper" # Stack
|
|
11
9
|
class AnbtSql
|
12
10
|
class Formatter
|
13
11
|
|
12
|
+
include StringUtil
|
13
|
+
|
14
14
|
@rule = nil
|
15
15
|
|
16
16
|
def initialize(rule)
|
@@ -49,7 +49,7 @@ class AnbtSql
|
|
49
49
|
@function_bracket.clear()
|
50
50
|
begin
|
51
51
|
isSqlEndsWithNewLine = false
|
52
|
-
if sql_str.
|
52
|
+
if sql_str.end_with?("\n")
|
53
53
|
isSqlEndsWithNewLine = true
|
54
54
|
end
|
55
55
|
|
@@ -103,8 +103,8 @@ class AnbtSql
|
|
103
103
|
tokens[index + 1].string == "+" &&
|
104
104
|
tokens[index + 2].string == ")")
|
105
105
|
tokens[index].string = "(+)"
|
106
|
-
|
107
|
-
|
106
|
+
ArrayUtil.remove(tokens, index + 1)
|
107
|
+
ArrayUtil.remove(tokens, index + 1)
|
108
108
|
end
|
109
109
|
index += 1
|
110
110
|
end
|
@@ -115,17 +115,17 @@ class AnbtSql
|
|
115
115
|
prevToken = nil
|
116
116
|
|
117
117
|
(tokens.size - 1).downto(1){|index|
|
118
|
-
token =
|
119
|
-
prevToken =
|
118
|
+
token = ArrayUtil.get(tokens, index)
|
119
|
+
prevToken = ArrayUtil.get(tokens, index - 1)
|
120
120
|
|
121
121
|
if (token._type == AnbtSql::TokenConstants::SPACE &&
|
122
122
|
(prevToken._type == AnbtSql::TokenConstants::SYMBOL ||
|
123
123
|
prevToken._type == AnbtSql::TokenConstants::COMMENT))
|
124
|
-
|
124
|
+
ArrayUtil.remove(tokens, index)
|
125
125
|
elsif ((token._type == AnbtSql::TokenConstants::SYMBOL ||
|
126
126
|
token._type == AnbtSql::TokenConstants::COMMENT) &&
|
127
127
|
prevToken._type == AnbtSql::TokenConstants::SPACE)
|
128
|
-
|
128
|
+
ArrayUtil.remove(tokens, index - 1)
|
129
129
|
elsif (token._type == AnbtSql::TokenConstants::SPACE)
|
130
130
|
token.string = " "
|
131
131
|
end
|
@@ -138,8 +138,8 @@ class AnbtSql
|
|
138
138
|
|
139
139
|
# Length of tokens changes in loop!
|
140
140
|
while index < tokens.size
|
141
|
-
prev =
|
142
|
-
token =
|
141
|
+
prev = ArrayUtil.get(tokens, index - 1)
|
142
|
+
token = ArrayUtil.get(tokens, index )
|
143
143
|
|
144
144
|
if (prev._type != AnbtSql::TokenConstants::SPACE &&
|
145
145
|
token._type != AnbtSql::TokenConstants::SPACE)
|
@@ -153,11 +153,11 @@ class AnbtSql
|
|
153
153
|
# 関数名の後ろにはスペースは入れない
|
154
154
|
# no space after function name
|
155
155
|
if (@rule.function?(prev.string) &&
|
156
|
-
token.string
|
156
|
+
token.string == "(")
|
157
157
|
index += 1 ; next
|
158
158
|
end
|
159
159
|
|
160
|
-
|
160
|
+
ArrayUtil.add(tokens, index,
|
161
161
|
AnbtSql::Token.new(AnbtSql::TokenConstants::SPACE, " ")
|
162
162
|
)
|
163
163
|
end
|
@@ -178,7 +178,7 @@ class AnbtSql
|
|
178
178
|
index = 0
|
179
179
|
# Length of tokens changes in loop!
|
180
180
|
while index < tokens.size
|
181
|
-
token =
|
181
|
+
token = ArrayUtil.get(tokens, index)
|
182
182
|
|
183
183
|
if token._type == AnbtSql::TokenConstants::SYMBOL # ****
|
184
184
|
|
@@ -208,61 +208,61 @@ class AnbtSql
|
|
208
208
|
elsif token._type == AnbtSql::TokenConstants::KEYWORD # ****
|
209
209
|
|
210
210
|
# indentを2つ増やし、キーワードの後ろで改行
|
211
|
-
if (token.string
|
212
|
-
token.string
|
213
|
-
token.string
|
211
|
+
if (equals_ignore_case(token.string, "DELETE") ||
|
212
|
+
equals_ignore_case(token.string, "SELECT") ||
|
213
|
+
equals_ignore_case(token.string, "UPDATE") )
|
214
214
|
indent += 2
|
215
215
|
index += insert_return_and_indent(tokens, index + 1, indent, "+2")
|
216
216
|
end
|
217
217
|
|
218
218
|
# indentを1つ増やし、キーワードの後ろで改行
|
219
|
-
if @rule.kw_plus1_indent_x_nl.any?{ |kw| token.string
|
219
|
+
if @rule.kw_plus1_indent_x_nl.any?{ |kw| equals_ignore_case(token.string, kw) }
|
220
220
|
indent += 1
|
221
221
|
index += insert_return_and_indent(tokens, index + 1, indent)
|
222
222
|
end
|
223
223
|
|
224
224
|
# キーワードの前でindentを1つ減らして改行、キーワードの後ろでindentを戻して改行。
|
225
|
-
if @rule.kw_minus1_indent_nl_x_plus1_indent.any?{ |kw| token.string
|
225
|
+
if @rule.kw_minus1_indent_nl_x_plus1_indent.any?{ |kw| equals_ignore_case(token.string, kw) }
|
226
226
|
index += insert_return_and_indent(tokens, index , indent - 1)
|
227
227
|
index += insert_return_and_indent(tokens, index + 1, indent )
|
228
228
|
end
|
229
229
|
|
230
230
|
# キーワードの前でindentを1つ減らして改行、キーワードの後ろでindentを戻して改行。
|
231
|
-
if (token.string
|
231
|
+
if (equals_ignore_case(token.string, "VALUES"))
|
232
232
|
indent -= 1
|
233
233
|
index += insert_return_and_indent(tokens, index, indent)
|
234
234
|
end
|
235
235
|
|
236
236
|
# キーワードの前でindentを1つ減らして改行
|
237
|
-
if (token.string
|
237
|
+
if (equals_ignore_case(token.string, "END"))
|
238
238
|
indent -= 1
|
239
239
|
index += insert_return_and_indent(tokens, index, indent)
|
240
240
|
end
|
241
241
|
|
242
242
|
# キーワードの前で改行
|
243
|
-
if @rule.kw_nl_x.any?{ |kw| token.string
|
243
|
+
if @rule.kw_nl_x.any?{ |kw| equals_ignore_case(token.string, kw) }
|
244
244
|
index += insert_return_and_indent(tokens, index, indent)
|
245
245
|
end
|
246
246
|
|
247
247
|
# キーワードの前で改行, インデント+1
|
248
|
-
if @rule.kw_nl_x_plus1_indent.any?{ |kw| token.string
|
248
|
+
if @rule.kw_nl_x_plus1_indent.any?{ |kw| equals_ignore_case(token.string, kw) }
|
249
249
|
index += insert_return_and_indent(tokens, index, indent + 1)
|
250
250
|
end
|
251
251
|
|
252
252
|
# キーワードの前で改行。indentを強制的に0にする。
|
253
|
-
if (token.string
|
254
|
-
token.string
|
255
|
-
token.string
|
253
|
+
if (equals_ignore_case(token.string, "UNION" ) ||
|
254
|
+
equals_ignore_case(token.string, "INTERSECT") ||
|
255
|
+
equals_ignore_case(token.string, "EXCEPT" ) )
|
256
256
|
indent -= 2
|
257
257
|
index += insert_return_and_indent(tokens, index , indent)
|
258
258
|
index += insert_return_and_indent(tokens, index + 1, indent)
|
259
259
|
end
|
260
260
|
|
261
|
-
if token.string
|
261
|
+
if equals_ignore_case(token.string, "BETWEEN")
|
262
262
|
encounterBetween = true
|
263
263
|
end
|
264
264
|
|
265
|
-
if token.string
|
265
|
+
if equals_ignore_case(token.string, "AND")
|
266
266
|
# BETWEEN のあとのANDは改行しない。
|
267
267
|
if not encounterBetween
|
268
268
|
index += insert_return_and_indent(tokens, index, indent)
|
@@ -272,10 +272,10 @@ class AnbtSql
|
|
272
272
|
|
273
273
|
elsif (token._type == AnbtSql::TokenConstants::COMMENT) # ****
|
274
274
|
|
275
|
-
if token.string.
|
275
|
+
if token.string.start_with?("/*")
|
276
276
|
# マルチラインコメントの後に改行を入れる。
|
277
277
|
index += insert_return_and_indent(tokens, index + 1, indent)
|
278
|
-
elsif
|
278
|
+
elsif token.string.start_with?("--")
|
279
279
|
index += insert_return_and_indent(tokens, index + 1, indent)
|
280
280
|
end
|
281
281
|
end
|
@@ -295,21 +295,21 @@ class AnbtSql
|
|
295
295
|
(tokens.size - 1).downto(4).each{|index|
|
296
296
|
next if (index >= tokens.size())
|
297
297
|
|
298
|
-
t0 =
|
299
|
-
t1 =
|
300
|
-
t2 =
|
301
|
-
t3 =
|
302
|
-
t4 =
|
298
|
+
t0 = ArrayUtil.get(tokens, index )
|
299
|
+
t1 = ArrayUtil.get(tokens, index - 1)
|
300
|
+
t2 = ArrayUtil.get(tokens, index - 2)
|
301
|
+
t3 = ArrayUtil.get(tokens, index - 3)
|
302
|
+
t4 = ArrayUtil.get(tokens, index - 4)
|
303
303
|
|
304
|
-
if (t4.string
|
305
|
-
t3.string.
|
306
|
-
t1.string.
|
307
|
-
t0.string
|
304
|
+
if (equals_ignore_case(t4.string , "(") &&
|
305
|
+
equals_ignore_case(t3.string.strip, "" ) &&
|
306
|
+
equals_ignore_case(t1.string.strip, "" ) &&
|
307
|
+
equals_ignore_case(t0.string , ")") )
|
308
308
|
t4.string = t4.string + t2.string + t0.string
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
309
|
+
ArrayUtil.remove(tokens, index )
|
310
|
+
ArrayUtil.remove(tokens, index - 1)
|
311
|
+
ArrayUtil.remove(tokens, index - 2)
|
312
|
+
ArrayUtil.remove(tokens, index - 3)
|
313
313
|
end
|
314
314
|
}
|
315
315
|
end
|
@@ -321,15 +321,15 @@ class AnbtSql
|
|
321
321
|
# SQLの前後に空白があったら削除する。
|
322
322
|
# Delete space token at first and last of SQL tokens.
|
323
323
|
|
324
|
-
token =
|
324
|
+
token = ArrayUtil.get(tokens, 0)
|
325
325
|
if (token._type == AnbtSql::TokenConstants::SPACE)
|
326
|
-
|
326
|
+
ArrayUtil.remove(tokens, 0)
|
327
327
|
end
|
328
328
|
return [] if tokens.empty?
|
329
329
|
|
330
|
-
token =
|
330
|
+
token = ArrayUtil.get(tokens, tokens.size() - 1)
|
331
331
|
if token._type == AnbtSql::TokenConstants::SPACE
|
332
|
-
|
332
|
+
ArrayUtil.remove(tokens, tokens.size() - 1)
|
333
333
|
end
|
334
334
|
return [] if tokens.empty?
|
335
335
|
|
@@ -361,33 +361,26 @@ class AnbtSql
|
|
361
361
|
begin
|
362
362
|
# 挿入する文字列を作成する。
|
363
363
|
s = "\n"
|
364
|
-
# もし1つ前にシングルラインコメントがあるなら、改行は不要。
|
365
|
-
prevToken = tokens.get(index - 1)
|
366
|
-
|
367
|
-
if (prevToken._type == AnbtSql::TokenConstants::COMMENT &&
|
368
|
-
prevToken.string.startsWith("--"))
|
369
|
-
s = ""
|
370
|
-
end
|
371
364
|
|
372
365
|
# インデントをつける。
|
373
366
|
indent = 0 if indent < 0 ## Java版と異なる
|
374
367
|
s += @rule.indent_string * indent
|
375
368
|
|
376
369
|
# 前後にすでにスペースがあれば、それを置き換える。
|
377
|
-
token =
|
370
|
+
token = ArrayUtil.get(tokens, index)
|
378
371
|
if token._type == AnbtSql::TokenConstants::SPACE
|
379
372
|
token.string = s
|
380
373
|
return 0
|
381
374
|
end
|
382
375
|
|
383
|
-
token =
|
376
|
+
token = ArrayUtil.get(tokens, index - 1)
|
384
377
|
if token._type == AnbtSql::TokenConstants::SPACE
|
385
378
|
token.string = s
|
386
379
|
return 0
|
387
380
|
end
|
388
381
|
|
389
382
|
# 前後になければ、新たにスペースを追加する。
|
390
|
-
|
383
|
+
ArrayUtil.add(tokens, index,
|
391
384
|
AnbtSql::Token.new(AnbtSql::TokenConstants::SPACE, s)
|
392
385
|
)
|
393
386
|
return 1
|
@@ -1,73 +1,59 @@
|
|
1
|
-
|
1
|
+
class AnbtSql
|
2
|
+
class Stack
|
3
|
+
include Enumerable
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
def initialize
|
7
|
-
@arr = []
|
8
|
-
end
|
9
|
-
|
10
|
-
def each
|
11
|
-
@arr.each{|item|
|
12
|
-
yield item
|
13
|
-
}
|
14
|
-
end
|
15
|
-
|
16
|
-
def clear
|
17
|
-
@arr.clear
|
18
|
-
end
|
19
|
-
|
20
|
-
def push(o)
|
21
|
-
@arr.push o
|
22
|
-
end
|
23
|
-
|
24
|
-
def pop
|
25
|
-
@arr.pop
|
26
|
-
end
|
27
|
-
end
|
5
|
+
def initialize
|
6
|
+
@arr = []
|
7
|
+
end
|
28
8
|
|
9
|
+
def each
|
10
|
+
@arr.each{|item|
|
11
|
+
yield item
|
12
|
+
}
|
13
|
+
end
|
29
14
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
15
|
+
def clear
|
16
|
+
@arr.clear
|
17
|
+
end
|
34
18
|
|
35
|
-
|
36
|
-
|
37
|
-
|
19
|
+
def push(o)
|
20
|
+
@arr.push o
|
21
|
+
end
|
38
22
|
|
39
|
-
|
40
|
-
|
23
|
+
def pop
|
24
|
+
@arr.pop
|
25
|
+
end
|
41
26
|
end
|
42
27
|
|
43
|
-
|
44
|
-
|
45
|
-
|
28
|
+
module StringUtil
|
29
|
+
def char_at(str, n)
|
30
|
+
if n < 0 || str.size - 1 < n
|
31
|
+
raise IndexOutOfBoundsException
|
32
|
+
end
|
46
33
|
|
47
|
-
|
48
|
-
|
49
|
-
end
|
34
|
+
str.slice(n, 1)
|
35
|
+
end
|
50
36
|
|
51
|
-
|
52
|
-
|
37
|
+
def equals_ignore_case(str_a, str_b)
|
38
|
+
str_a.casecmp(str_b) == 0
|
39
|
+
end
|
53
40
|
end
|
54
|
-
end
|
55
41
|
|
42
|
+
module ArrayUtil
|
43
|
+
def self.remove(ary, n)
|
44
|
+
ary.delete_at n
|
45
|
+
end
|
56
46
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
47
|
+
def self.get(ary, n)
|
48
|
+
if n < 0 || ary.size - 1 < n
|
49
|
+
raise IndexOutOfBoundsException
|
50
|
+
end
|
61
51
|
|
62
|
-
|
63
|
-
if n >= self.size || n <= -1
|
64
|
-
raise IndexOutOfBoundsException
|
52
|
+
ary[n]
|
65
53
|
end
|
66
54
|
|
67
|
-
self
|
68
|
-
|
69
|
-
|
70
|
-
def add(n,o)
|
71
|
-
self.insert(n,o)
|
55
|
+
def self.add(ary, n, o)
|
56
|
+
ary.insert(n, o)
|
57
|
+
end
|
72
58
|
end
|
73
59
|
end
|
@@ -10,6 +10,8 @@ require "anbt-sql-formatter/coarse-tokenizer"
|
|
10
10
|
class AnbtSql
|
11
11
|
class Parser
|
12
12
|
|
13
|
+
include ::AnbtSql::StringUtil
|
14
|
+
|
13
15
|
def initialize(rule)
|
14
16
|
@rule = rule
|
15
17
|
|
@@ -26,7 +28,7 @@ class AnbtSql
|
|
26
28
|
|
27
29
|
# 2文字からなる記号。
|
28
30
|
# なお、|| は文字列結合にあたります。
|
29
|
-
@two_character_symbol = [ "<>", "<=", ">=", "||" ]
|
31
|
+
@two_character_symbol = [ "<>", "<=", ">=", "||", "!=" ]
|
30
32
|
end
|
31
33
|
|
32
34
|
|
@@ -49,7 +51,7 @@ class AnbtSql
|
|
49
51
|
return false if space?(c)
|
50
52
|
return false if digit?(c)
|
51
53
|
return false if symbol?(c)
|
52
|
-
|
54
|
+
|
53
55
|
true
|
54
56
|
end
|
55
57
|
|
@@ -64,7 +66,7 @@ class AnbtSql
|
|
64
66
|
# アンダースコアは記号とは扱いません
|
65
67
|
# これ以降の文字の扱いは保留
|
66
68
|
def symbol?(c)
|
67
|
-
%w(" ? % & ' \( \) | * + , - . / : ; < = > ).include? c
|
69
|
+
%w(" ? % & ' \( \) | * + , - . / : ; < = > !).include? c
|
68
70
|
#"
|
69
71
|
end
|
70
72
|
|
@@ -80,35 +82,36 @@ class AnbtSql
|
|
80
82
|
$stderr.puts "next_token #{@pos} <#{@before}> #{@before.length}" if $DEBUG
|
81
83
|
|
82
84
|
start_pos = @pos
|
83
|
-
|
85
|
+
|
84
86
|
if @pos >= @before.length
|
85
87
|
@pos += 1
|
86
88
|
return nil
|
87
89
|
end
|
88
|
-
|
89
|
-
@char = @before
|
90
|
+
|
91
|
+
@char = char_at(@before, @pos)
|
90
92
|
|
91
93
|
if space?(@char)
|
92
94
|
workString = ""
|
93
|
-
loop {
|
95
|
+
loop {
|
94
96
|
workString += @char
|
95
97
|
|
96
|
-
|
97
|
-
if
|
98
|
-
@pos
|
99
|
-
|
100
|
-
workString, start_pos)
|
98
|
+
is_next_char_space = false
|
99
|
+
if @pos + 1 < @before.size &&
|
100
|
+
space?(char_at(@before, @pos+1))
|
101
|
+
is_next_char_space = true
|
101
102
|
end
|
102
103
|
|
103
|
-
|
104
|
-
|
105
|
-
if @pos >= @before.length()
|
104
|
+
if not is_next_char_space
|
105
|
+
@pos += 1
|
106
106
|
return AnbtSql::Token.new(AnbtSql::TokenConstants::SPACE,
|
107
|
-
|
107
|
+
workString, start_pos)
|
108
|
+
else
|
109
|
+
@pos += 1
|
110
|
+
next
|
108
111
|
end
|
109
112
|
}
|
110
113
|
|
111
|
-
|
114
|
+
|
112
115
|
elsif @char == ";"
|
113
116
|
@pos += 1
|
114
117
|
# 2005.07.26 Tosiki Iga セミコロンは終了扱いではないようにする。
|
@@ -116,66 +119,51 @@ class AnbtSql
|
|
116
119
|
";", start_pos)
|
117
120
|
|
118
121
|
elsif digit?(@char)
|
119
|
-
if
|
120
|
-
|
122
|
+
if /^(0x[0-9a-fA-F]+)/ =~ @before[@pos..-1] || # hex
|
123
|
+
/^(\d+(\.\d+(e-?\d+)?)?)/ =~ @before[@pos..-1] # integer, float or scientific
|
121
124
|
num = $1
|
122
125
|
@pos += num.length
|
123
126
|
return AnbtSql::Token.new(AnbtSql::TokenConstants::VALUE,
|
124
127
|
num, start_pos)
|
128
|
+
else
|
129
|
+
raise "must not happen"
|
125
130
|
end
|
126
131
|
|
127
|
-
s = ""
|
128
|
-
while (digit?(@char) || @char == '.')
|
129
|
-
# if (ch == '.') type = Token.REAL
|
130
|
-
s += @char
|
131
|
-
@pos += 1
|
132
|
-
|
133
|
-
if (@pos >= @before.length)
|
134
|
-
# 長さを超えている場合には処理中断します。
|
135
|
-
break
|
136
|
-
end
|
137
|
-
|
138
|
-
@char = @before.charAt(@pos)
|
139
|
-
end
|
140
|
-
return AnbtSql::Token.new(AnbtSql::TokenConstants::VALUE,
|
141
|
-
s, start_pos)
|
142
|
-
|
143
|
-
|
144
132
|
elsif letter?(@char)
|
145
133
|
s = ""
|
146
134
|
# 文字列中のドットについては、文字列と一体として考える。
|
147
|
-
while (letter?(@char) || digit?(@char) || @char == '.')
|
135
|
+
while (letter?(@char) || digit?(@char) || @char == '.')
|
148
136
|
s += @char
|
149
137
|
@pos += 1
|
150
138
|
if (@pos >= @before.length())
|
151
139
|
break
|
152
140
|
end
|
153
141
|
|
154
|
-
@char = @before
|
142
|
+
@char = char_at(@before, @pos)
|
155
143
|
end
|
156
144
|
|
157
145
|
if AnbtSql::Constants::SQL_RESERVED_WORDS.map{|w| w.upcase }.include?(s.upcase)
|
158
146
|
return AnbtSql::Token.new(AnbtSql::TokenConstants::KEYWORD,
|
159
147
|
s, start_pos)
|
160
148
|
end
|
161
|
-
|
149
|
+
|
162
150
|
return AnbtSql::Token.new(AnbtSql::TokenConstants::NAME,
|
163
151
|
s, start_pos)
|
164
152
|
|
165
153
|
elsif symbol?(@char)
|
166
154
|
s = "" + @char
|
167
155
|
@pos += 1
|
168
|
-
if (@pos >= @before.length())
|
156
|
+
if (@pos >= @before.length())
|
169
157
|
return AnbtSql::Token.new(AnbtSql::TokenConstants::SYMBOL,
|
170
158
|
s, start_pos)
|
171
159
|
end
|
172
160
|
|
173
161
|
# 2文字の記号かどうか調べる
|
174
|
-
ch2 = @before
|
162
|
+
ch2 = char_at(@before, @pos)
|
175
163
|
#for (int i = 0; i < two_character_symbol.length; i++) {
|
176
164
|
for i in 0...@two_character_symbol.length
|
177
|
-
if (@two_character_symbol[i]
|
178
|
-
@two_character_symbol[i]
|
165
|
+
if (char_at(@two_character_symbol[i], 0) == @char &&
|
166
|
+
char_at(@two_character_symbol[i], 1) == ch2)
|
179
167
|
@pos += 1
|
180
168
|
s += ch2
|
181
169
|
break
|
@@ -209,7 +197,7 @@ class AnbtSql
|
|
209
197
|
pos = 0
|
210
198
|
while pos < coarse_tokens.size
|
211
199
|
coarse_token = coarse_tokens[pos]
|
212
|
-
|
200
|
+
|
213
201
|
case coarse_token._type
|
214
202
|
|
215
203
|
when :quote_single
|
@@ -255,10 +243,10 @@ class AnbtSql
|
|
255
243
|
##
|
256
244
|
# 2つ以上並んだキーワードは1つのキーワードとみなします。
|
257
245
|
# ["a", " ", "group", " ", "by", " ", "b"]
|
258
|
-
# => ["a", " ", "group by", " ", "b"]
|
246
|
+
# => ["a", " ", "group by", " ", "b"]
|
259
247
|
def concat_multiwords_keyword(tokens)
|
260
248
|
temp_kw_list = @rule.kw_multi_words.map{|kw| kw.split(" ") }
|
261
|
-
|
249
|
+
|
262
250
|
# ワード数が多い順から
|
263
251
|
temp_kw_list.sort{ |a, b|
|
264
252
|
b.size <=> a.size
|
@@ -270,7 +258,7 @@ class AnbtSql
|
|
270
258
|
temp_tokens = tokens[index, target_tokens_size].map {|x|
|
271
259
|
x.string.sub(/\s+/, " ")
|
272
260
|
}
|
273
|
-
|
261
|
+
|
274
262
|
if /#{kw.join(" ")}/i =~ temp_tokens.join
|
275
263
|
tokens[index].string = temp_tokens.join
|
276
264
|
(target_tokens_size-1).downto(1).each{|c|
|
@@ -297,28 +285,28 @@ class AnbtSql
|
|
297
285
|
coarse_tokens = CoarseTokenizer.new.tokenize(sql_str)
|
298
286
|
|
299
287
|
prepare_tokens(coarse_tokens)
|
300
|
-
|
288
|
+
|
301
289
|
tokens = []
|
302
290
|
count = 0
|
303
291
|
@token_pos = 0
|
304
292
|
loop {
|
305
293
|
token = next_token()
|
306
|
-
|
294
|
+
|
307
295
|
if $DEBUG
|
308
296
|
pp "=" * 64, count, token, token.class
|
309
297
|
end
|
310
|
-
|
298
|
+
|
311
299
|
if token._type == AnbtSql::TokenConstants::END_OF_SQL
|
312
300
|
break
|
313
301
|
else
|
314
302
|
;
|
315
303
|
end
|
316
|
-
|
304
|
+
|
317
305
|
tokens.push token
|
318
306
|
count += 1
|
319
307
|
@token_pos += 1
|
320
308
|
}
|
321
|
-
|
309
|
+
|
322
310
|
concat_multiwords_keyword(tokens)
|
323
311
|
|
324
312
|
tokens
|