create_table 0.1.0
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/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +82 -0
- data/Rakefile +89 -0
- data/create_table.gemspec +28 -0
- data/features/parsing.feature +736 -0
- data/features/step_definitions/create_table/parsing_steps.rb +60 -0
- data/features/support/env.rb +28 -0
- data/lib/create_table.rb +2545 -0
- data/lib/create_table.rl +185 -0
- data/lib/create_table/column.rb +4920 -0
- data/lib/create_table/column.rl +338 -0
- data/lib/create_table/column_name_based_collection.rb +26 -0
- data/lib/create_table/common.rb +5 -0
- data/lib/create_table/common.rl +13 -0
- data/lib/create_table/index.rb +315 -0
- data/lib/create_table/index.rl +91 -0
- data/lib/create_table/mysql_reserved.txt +226 -0
- data/lib/create_table/parser.rb +36 -0
- data/lib/create_table/pg_reserved.txt +742 -0
- data/lib/create_table/unique.rb +7 -0
- data/lib/create_table/version.rb +3 -0
- data/spec/create_table_spec.rb +88 -0
- data/spec/generating/autoincrement_primary_key.yml +74 -0
- data/spec/generating/backticks.yml +22 -0
- data/spec/generating/charset.yml +21 -0
- data/spec/generating/comments.yml +34 -0
- data/spec/generating/doublequoted.yml +25 -0
- data/spec/generating/index.yml +37 -0
- data/spec/generating/named_unique.yml +37 -0
- data/spec/generating/reservedwords.yml +23 -0
- data/spec/generating/string_primary_key.yml +35 -0
- data/spec/generating/temporary.yml +25 -0
- data/spec/generating/unique.yml +35 -0
- data/spec/generating/unquoted.yml +25 -0
- data/spec/generating_spec.rb +27 -0
- data/spec/spec_helper.rb +66 -0
- metadata +263 -0
@@ -0,0 +1,338 @@
|
|
1
|
+
# MAKE SURE YOU'RE EDITING THE .RL FILE !!!
|
2
|
+
|
3
|
+
=begin
|
4
|
+
%%{
|
5
|
+
machine parser;
|
6
|
+
|
7
|
+
include "common.rl";
|
8
|
+
|
9
|
+
action StartName {
|
10
|
+
start_name = p
|
11
|
+
}
|
12
|
+
action EndName {
|
13
|
+
self.name = read(data, start_name, p)
|
14
|
+
}
|
15
|
+
|
16
|
+
action StartDataType {
|
17
|
+
start_data_type = p
|
18
|
+
}
|
19
|
+
|
20
|
+
action MarkNotNull {
|
21
|
+
mark_not_null = p - 4
|
22
|
+
}
|
23
|
+
action Null {
|
24
|
+
start_default ||= nil
|
25
|
+
unless start_default # FIXME could this be excluded by the state machine instead?
|
26
|
+
mark_not_null ||= nil
|
27
|
+
if mark_not_null
|
28
|
+
self.null = false
|
29
|
+
end_data_type ||= mark_not_null
|
30
|
+
else
|
31
|
+
self.null = true
|
32
|
+
end_data_type ||= p - 4
|
33
|
+
end
|
34
|
+
end
|
35
|
+
}
|
36
|
+
|
37
|
+
action MarkDefault {
|
38
|
+
mark_default = p - 1
|
39
|
+
}
|
40
|
+
action StartDefault {
|
41
|
+
start_default = p
|
42
|
+
end_data_type ||= mark_default
|
43
|
+
}
|
44
|
+
action EndQuotedDefault {
|
45
|
+
end_default = p
|
46
|
+
self.default = read_quoted(data, start_default, end_default)
|
47
|
+
ended_quoted_default = true
|
48
|
+
}
|
49
|
+
|
50
|
+
action MarkPrimaryKey {
|
51
|
+
mark_primary_key = p - 1
|
52
|
+
}
|
53
|
+
action PrimaryKey {
|
54
|
+
primary_key!
|
55
|
+
end_data_type ||= mark_primary_key
|
56
|
+
end_default ||= mark_primary_key
|
57
|
+
}
|
58
|
+
|
59
|
+
action MarkUnique {
|
60
|
+
mark_unique = p - 5
|
61
|
+
}
|
62
|
+
action Unique {
|
63
|
+
unique!
|
64
|
+
end_data_type ||= mark_unique
|
65
|
+
end_default ||= mark_unique
|
66
|
+
}
|
67
|
+
|
68
|
+
action MarkAutoincrement {
|
69
|
+
mark_autoincrement = p - 1
|
70
|
+
}
|
71
|
+
action Autoincrement {
|
72
|
+
autoincrement!
|
73
|
+
end_data_type ||= mark_autoincrement
|
74
|
+
end_default ||= mark_autoincrement
|
75
|
+
}
|
76
|
+
|
77
|
+
action MarkCollate {
|
78
|
+
mark_collate = p - 1
|
79
|
+
}
|
80
|
+
action StartCollate {
|
81
|
+
start_collate = p
|
82
|
+
}
|
83
|
+
action EndCollate {
|
84
|
+
self.collate = read_quoted(data, start_collate, p)
|
85
|
+
end_data_type ||= mark_collate
|
86
|
+
end_default ||= mark_collate
|
87
|
+
}
|
88
|
+
|
89
|
+
action MarkCharset {
|
90
|
+
mark_charset = p - 5
|
91
|
+
}
|
92
|
+
action StartCharset {
|
93
|
+
start_charset = p
|
94
|
+
}
|
95
|
+
action EndCharset {
|
96
|
+
self.charset = read_quoted(data, start_charset, p)
|
97
|
+
end_data_type ||= mark_charset
|
98
|
+
end_default ||= mark_charset
|
99
|
+
}
|
100
|
+
|
101
|
+
action BitterEnd {
|
102
|
+
# EndUnquotedDefault
|
103
|
+
start_default ||= nil
|
104
|
+
ended_quoted_default ||= nil
|
105
|
+
if start_default and not ended_quoted_default
|
106
|
+
end_default ||= p
|
107
|
+
self.default = read_quoted(data, start_default, end_default)
|
108
|
+
end
|
109
|
+
# EndDataType
|
110
|
+
end_data_type ||= p
|
111
|
+
self.data_type = read(data, start_data_type, end_data_type)
|
112
|
+
}
|
113
|
+
|
114
|
+
name = quote_ident ident >StartName %EndName quote_ident;
|
115
|
+
|
116
|
+
primary_key = ('primary'i space+ 'key'i) >MarkPrimaryKey @PrimaryKey;
|
117
|
+
|
118
|
+
autoincrement = ('auto'i '_'? 'increment'i) >MarkAutoincrement @Autoincrement;
|
119
|
+
|
120
|
+
unique = 'uniq'i %MarkUnique 'ue'i @Unique;
|
121
|
+
|
122
|
+
quoted_default_value = quote_value (not_quote_or_escape | escaped_something | quoted_quote)+ >StartDefault %EndQuotedDefault quote_value;
|
123
|
+
unquoted_default_value = (alnum any*) >StartDefault; # space*;
|
124
|
+
default = ('default'i space+) >MarkDefault (quoted_default_value | unquoted_default_value);
|
125
|
+
|
126
|
+
_null = ('not'i %MarkNotNull)? space+ 'null'i @Null;
|
127
|
+
|
128
|
+
quoted_charset_value = quote_value (not_quote_or_escape | escaped_something | quoted_quote)+ >StartCharset %EndCharset quote_value;
|
129
|
+
unquoted_charset_value = (any - space)+ >StartCharset %EndCharset space*;
|
130
|
+
charset = 'char'i %MarkCharset ('set'i | ('acter'i space+ 'set'i)) space+ (quoted_charset_value | unquoted_charset_value);
|
131
|
+
|
132
|
+
quoted_collate_value = quote_value (not_quote_or_escape | escaped_something | quoted_quote)+ >StartCollate %EndCollate quote_value;
|
133
|
+
unquoted_collate_value = (any - space)+ >StartCollate %EndCollate space*;
|
134
|
+
collate = ('collate'i space+) >MarkCollate (quoted_collate_value | unquoted_collate_value);
|
135
|
+
|
136
|
+
data_type = any+;
|
137
|
+
|
138
|
+
main := space* name space+ data_type >StartDataType _null? default? primary_key? unique? autoincrement? charset? collate? %BitterEnd;
|
139
|
+
}%%
|
140
|
+
=end
|
141
|
+
|
142
|
+
class CreateTable
|
143
|
+
class Column
|
144
|
+
class << self
|
145
|
+
def munge_data_type(original, ansi)
|
146
|
+
if original =~ /\((.*)\)/
|
147
|
+
[ ansi, '(', $1, ')' ].join
|
148
|
+
else
|
149
|
+
ansi
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
BLANK_STRING = ''
|
155
|
+
|
156
|
+
include Parser
|
157
|
+
|
158
|
+
attr_reader :parent
|
159
|
+
attr_reader :name
|
160
|
+
attr_reader :data_type
|
161
|
+
attr_writer :default
|
162
|
+
attr_writer :null
|
163
|
+
attr_accessor :charset
|
164
|
+
attr_accessor :collate
|
165
|
+
|
166
|
+
def initialize(parent)
|
167
|
+
@parent = parent
|
168
|
+
parent.columns << self
|
169
|
+
end
|
170
|
+
|
171
|
+
def name=(name)
|
172
|
+
@name = name
|
173
|
+
end
|
174
|
+
|
175
|
+
def data_type=(str)
|
176
|
+
str = str.upcase
|
177
|
+
case str
|
178
|
+
when /SERIAL/
|
179
|
+
autoincrement!
|
180
|
+
@data_type = 'INTEGER'
|
181
|
+
when 'INT IDENTITY(1,1)'
|
182
|
+
# TODO is this correct?
|
183
|
+
autoincrement!
|
184
|
+
primary_key!
|
185
|
+
@data_type = 'INTEGER'
|
186
|
+
when 'TINYINT(1)'
|
187
|
+
@data_type = 'BOOLEAN'
|
188
|
+
when 'INT(11)'
|
189
|
+
@data_type = 'INTEGER'
|
190
|
+
when /\bINT\b/
|
191
|
+
@data_type = Column.munge_data_type str, 'INTEGER'
|
192
|
+
when /\bVARCHAR\b/
|
193
|
+
@data_type = Column.munge_data_type str, 'CHARACTER VARYING'
|
194
|
+
else
|
195
|
+
@data_type = str
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def default
|
200
|
+
if defined?(@default)
|
201
|
+
@default
|
202
|
+
elsif primary_key and data_type =~ /char/i
|
203
|
+
BLANK_STRING
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def null
|
208
|
+
if defined?(@null)
|
209
|
+
@null
|
210
|
+
elsif primary_key
|
211
|
+
false
|
212
|
+
else
|
213
|
+
true
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
alias :allow_null :null
|
218
|
+
|
219
|
+
def primary_key
|
220
|
+
parent.primary_key == self
|
221
|
+
end
|
222
|
+
|
223
|
+
def primary_key!
|
224
|
+
parent.primary_key = name
|
225
|
+
end
|
226
|
+
|
227
|
+
def unique
|
228
|
+
if primary_key
|
229
|
+
true
|
230
|
+
elsif index = parent.indexes[name]
|
231
|
+
index.unique
|
232
|
+
else
|
233
|
+
false
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def named_unique
|
238
|
+
unique and parent.indexes[name].name
|
239
|
+
end
|
240
|
+
|
241
|
+
def unique!
|
242
|
+
parent.add_unique name
|
243
|
+
end
|
244
|
+
|
245
|
+
def index!
|
246
|
+
parent.add_index name
|
247
|
+
end
|
248
|
+
|
249
|
+
def indexed
|
250
|
+
primary_key or !!parent.indexes[name]
|
251
|
+
end
|
252
|
+
|
253
|
+
def autoincrement!
|
254
|
+
@autoincrement = true
|
255
|
+
end
|
256
|
+
|
257
|
+
def autoincrement
|
258
|
+
if defined?(@autoincrement)
|
259
|
+
@autoincrement
|
260
|
+
elsif default and default =~ /nextval/i
|
261
|
+
true
|
262
|
+
else
|
263
|
+
false
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
# @private
|
268
|
+
def column_names
|
269
|
+
[name]
|
270
|
+
end
|
271
|
+
|
272
|
+
def parse(str)
|
273
|
+
data = Parser.remove_comments(str).strip.unpack('c*')
|
274
|
+
%% write data;
|
275
|
+
# % (this fixes syntax highlighting)
|
276
|
+
parens = 0
|
277
|
+
p = item = 0
|
278
|
+
pe = eof = data.length
|
279
|
+
%% write init;
|
280
|
+
# % (this fixes syntax highlighting)
|
281
|
+
%% write exec;
|
282
|
+
# % (this fixes syntax highlighting)
|
283
|
+
self
|
284
|
+
end
|
285
|
+
|
286
|
+
# generating
|
287
|
+
|
288
|
+
def to_sql(format, options)
|
289
|
+
send "to_#{format}", options
|
290
|
+
end
|
291
|
+
|
292
|
+
def to_mysql(options)
|
293
|
+
parts = []
|
294
|
+
parts << CreateTable.quote_ident(name, options)
|
295
|
+
parts << data_type
|
296
|
+
if primary_key
|
297
|
+
parts << 'PRIMARY KEY'
|
298
|
+
elsif unique and not named_unique
|
299
|
+
parts << 'UNIQUE'
|
300
|
+
end
|
301
|
+
if autoincrement
|
302
|
+
parts << 'AUTO_INCREMENT'
|
303
|
+
end
|
304
|
+
parts.join ' '
|
305
|
+
end
|
306
|
+
|
307
|
+
def to_postgresql(options)
|
308
|
+
parts = []
|
309
|
+
parts << CreateTable.quote_ident(name, options)
|
310
|
+
if autoincrement and data_type =~ /integer/i
|
311
|
+
parts << 'SERIAL'
|
312
|
+
else
|
313
|
+
parts << data_type
|
314
|
+
end
|
315
|
+
if primary_key
|
316
|
+
parts << 'PRIMARY KEY'
|
317
|
+
elsif unique and not named_unique
|
318
|
+
parts << 'UNIQUE'
|
319
|
+
end
|
320
|
+
parts.join ' '
|
321
|
+
end
|
322
|
+
|
323
|
+
def to_sqlite3(options)
|
324
|
+
parts = []
|
325
|
+
parts << CreateTable.quote_ident(name, options)
|
326
|
+
parts << data_type
|
327
|
+
if primary_key
|
328
|
+
parts << 'PRIMARY KEY'
|
329
|
+
elsif unique and not named_unique
|
330
|
+
parts << 'UNIQUE'
|
331
|
+
end
|
332
|
+
if autoincrement
|
333
|
+
parts << 'AUTOINCREMENT'
|
334
|
+
end
|
335
|
+
parts.join ' '
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
class CreateTable
|
3
|
+
class ColumnNameBasedCollection < Delegator
|
4
|
+
class << self
|
5
|
+
def create
|
6
|
+
new([])
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def __getobj__
|
11
|
+
@items
|
12
|
+
end
|
13
|
+
|
14
|
+
def __setobj__(items)
|
15
|
+
@items = items
|
16
|
+
end
|
17
|
+
|
18
|
+
def [](column_names)
|
19
|
+
return if column_names.nil?
|
20
|
+
k = [column_names].flatten
|
21
|
+
retval = @items.select { |i| i.column_names == k }
|
22
|
+
raise "oops #{k.inspect}: #{retval.map(&:column_names).inspect}" if retval.length > 1
|
23
|
+
retval.first
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
%%{
|
2
|
+
machine parser;
|
3
|
+
ident = [_a-zA-Z][_a-zA-Z0-9]*;
|
4
|
+
quote_ident = ["`]?;
|
5
|
+
quote_value = ['"];
|
6
|
+
lparens = space* '(' space*;
|
7
|
+
rparens = space* ')' space*;
|
8
|
+
parens_counter = ( any | '(' @{parens+=1} | ')' @{parens-=1} )*;
|
9
|
+
with_parens = any+ & parens_counter;
|
10
|
+
not_quote_or_escape = [^'"\\];
|
11
|
+
escaped_something = /\\./;
|
12
|
+
quoted_quote = "''";
|
13
|
+
}%%
|
@@ -0,0 +1,315 @@
|
|
1
|
+
|
2
|
+
# MAKE SURE YOU'RE EDITING THE .RL FILE !!!
|
3
|
+
|
4
|
+
=begin
|
5
|
+
|
6
|
+
|
7
|
+
=end
|
8
|
+
|
9
|
+
class CreateTable
|
10
|
+
class Index
|
11
|
+
include Parser
|
12
|
+
|
13
|
+
attr_reader :parent
|
14
|
+
attr_reader :column_names
|
15
|
+
attr_accessor :name
|
16
|
+
|
17
|
+
def initialize(parent)
|
18
|
+
@parent = parent
|
19
|
+
@column_names = []
|
20
|
+
parent.indexes << self
|
21
|
+
end
|
22
|
+
|
23
|
+
def unique
|
24
|
+
false
|
25
|
+
end
|
26
|
+
|
27
|
+
def parse(str)
|
28
|
+
data = Parser.remove_comments(str).unpack('c*')
|
29
|
+
|
30
|
+
class << self
|
31
|
+
attr_accessor :_parser_actions
|
32
|
+
private :_parser_actions, :_parser_actions=
|
33
|
+
end
|
34
|
+
self._parser_actions = [
|
35
|
+
0, 1, 0, 1, 1, 1, 2, 1,
|
36
|
+
3
|
37
|
+
]
|
38
|
+
|
39
|
+
class << self
|
40
|
+
attr_accessor :_parser_key_offsets
|
41
|
+
private :_parser_key_offsets, :_parser_key_offsets=
|
42
|
+
end
|
43
|
+
self._parser_key_offsets = [
|
44
|
+
0, 0, 10, 15, 27, 31, 40, 45,
|
45
|
+
55, 57, 67
|
46
|
+
]
|
47
|
+
|
48
|
+
class << self
|
49
|
+
attr_accessor :_parser_trans_keys
|
50
|
+
private :_parser_trans_keys, :_parser_trans_keys=
|
51
|
+
end
|
52
|
+
self._parser_trans_keys = [
|
53
|
+
32, 34, 40, 96, 9, 13, 65, 90,
|
54
|
+
95, 122, 95, 65, 90, 97, 122, 32,
|
55
|
+
34, 40, 96, 9, 13, 48, 57, 65,
|
56
|
+
90, 95, 122, 32, 40, 9, 13, 32,
|
57
|
+
34, 96, 9, 13, 65, 90, 95, 122,
|
58
|
+
95, 65, 90, 97, 122, 34, 41, 44,
|
59
|
+
96, 48, 57, 65, 90, 95, 122, 41,
|
60
|
+
44, 32, 34, 41, 96, 9, 13, 65,
|
61
|
+
90, 95, 122, 32, 9, 13, 0
|
62
|
+
]
|
63
|
+
|
64
|
+
class << self
|
65
|
+
attr_accessor :_parser_single_lengths
|
66
|
+
private :_parser_single_lengths, :_parser_single_lengths=
|
67
|
+
end
|
68
|
+
self._parser_single_lengths = [
|
69
|
+
0, 4, 1, 4, 2, 3, 1, 4,
|
70
|
+
2, 4, 1
|
71
|
+
]
|
72
|
+
|
73
|
+
class << self
|
74
|
+
attr_accessor :_parser_range_lengths
|
75
|
+
private :_parser_range_lengths, :_parser_range_lengths=
|
76
|
+
end
|
77
|
+
self._parser_range_lengths = [
|
78
|
+
0, 3, 2, 4, 1, 3, 2, 3,
|
79
|
+
0, 3, 1
|
80
|
+
]
|
81
|
+
|
82
|
+
class << self
|
83
|
+
attr_accessor :_parser_index_offsets
|
84
|
+
private :_parser_index_offsets, :_parser_index_offsets=
|
85
|
+
end
|
86
|
+
self._parser_index_offsets = [
|
87
|
+
0, 0, 8, 12, 21, 25, 32, 36,
|
88
|
+
44, 47, 55
|
89
|
+
]
|
90
|
+
|
91
|
+
class << self
|
92
|
+
attr_accessor :_parser_indicies
|
93
|
+
private :_parser_indicies, :_parser_indicies=
|
94
|
+
end
|
95
|
+
self._parser_indicies = [
|
96
|
+
0, 2, 3, 2, 0, 4, 4, 1,
|
97
|
+
4, 4, 4, 1, 5, 5, 6, 5,
|
98
|
+
5, 7, 7, 7, 1, 8, 3, 8,
|
99
|
+
1, 3, 9, 9, 3, 10, 10, 1,
|
100
|
+
10, 10, 10, 1, 11, 12, 12, 11,
|
101
|
+
13, 13, 13, 1, 14, 14, 1, 14,
|
102
|
+
9, 15, 9, 14, 10, 10, 1, 15,
|
103
|
+
15, 1, 0
|
104
|
+
]
|
105
|
+
|
106
|
+
class << self
|
107
|
+
attr_accessor :_parser_trans_targs
|
108
|
+
private :_parser_trans_targs, :_parser_trans_targs=
|
109
|
+
end
|
110
|
+
self._parser_trans_targs = [
|
111
|
+
1, 0, 2, 5, 3, 4, 5, 3,
|
112
|
+
4, 6, 7, 8, 9, 7, 9, 10
|
113
|
+
]
|
114
|
+
|
115
|
+
class << self
|
116
|
+
attr_accessor :_parser_trans_actions
|
117
|
+
private :_parser_trans_actions, :_parser_trans_actions=
|
118
|
+
end
|
119
|
+
self._parser_trans_actions = [
|
120
|
+
0, 0, 0, 0, 1, 3, 3, 0,
|
121
|
+
0, 0, 5, 7, 7, 0, 0, 0
|
122
|
+
]
|
123
|
+
|
124
|
+
class << self
|
125
|
+
attr_accessor :parser_start
|
126
|
+
end
|
127
|
+
self.parser_start = 1;
|
128
|
+
class << self
|
129
|
+
attr_accessor :parser_first_final
|
130
|
+
end
|
131
|
+
self.parser_first_final = 10;
|
132
|
+
class << self
|
133
|
+
attr_accessor :parser_error
|
134
|
+
end
|
135
|
+
self.parser_error = 0;
|
136
|
+
|
137
|
+
class << self
|
138
|
+
attr_accessor :parser_en_main
|
139
|
+
end
|
140
|
+
self.parser_en_main = 1;
|
141
|
+
|
142
|
+
|
143
|
+
# % (this fixes syntax highlighting)
|
144
|
+
parens = 0
|
145
|
+
p = item = 0
|
146
|
+
pe = eof = data.length
|
147
|
+
|
148
|
+
begin
|
149
|
+
p ||= 0
|
150
|
+
pe ||= data.length
|
151
|
+
cs = parser_start
|
152
|
+
end
|
153
|
+
|
154
|
+
# % (this fixes syntax highlighting)
|
155
|
+
|
156
|
+
begin
|
157
|
+
_klen, _trans, _keys, _acts, _nacts = nil
|
158
|
+
_goto_level = 0
|
159
|
+
_resume = 10
|
160
|
+
_eof_trans = 15
|
161
|
+
_again = 20
|
162
|
+
_test_eof = 30
|
163
|
+
_out = 40
|
164
|
+
while true
|
165
|
+
_trigger_goto = false
|
166
|
+
if _goto_level <= 0
|
167
|
+
if p == pe
|
168
|
+
_goto_level = _test_eof
|
169
|
+
next
|
170
|
+
end
|
171
|
+
if cs == 0
|
172
|
+
_goto_level = _out
|
173
|
+
next
|
174
|
+
end
|
175
|
+
end
|
176
|
+
if _goto_level <= _resume
|
177
|
+
_keys = _parser_key_offsets[cs]
|
178
|
+
_trans = _parser_index_offsets[cs]
|
179
|
+
_klen = _parser_single_lengths[cs]
|
180
|
+
_break_match = false
|
181
|
+
|
182
|
+
begin
|
183
|
+
if _klen > 0
|
184
|
+
_lower = _keys
|
185
|
+
_upper = _keys + _klen - 1
|
186
|
+
|
187
|
+
loop do
|
188
|
+
break if _upper < _lower
|
189
|
+
_mid = _lower + ( (_upper - _lower) >> 1 )
|
190
|
+
|
191
|
+
if data[p].ord < _parser_trans_keys[_mid]
|
192
|
+
_upper = _mid - 1
|
193
|
+
elsif data[p].ord > _parser_trans_keys[_mid]
|
194
|
+
_lower = _mid + 1
|
195
|
+
else
|
196
|
+
_trans += (_mid - _keys)
|
197
|
+
_break_match = true
|
198
|
+
break
|
199
|
+
end
|
200
|
+
end # loop
|
201
|
+
break if _break_match
|
202
|
+
_keys += _klen
|
203
|
+
_trans += _klen
|
204
|
+
end
|
205
|
+
_klen = _parser_range_lengths[cs]
|
206
|
+
if _klen > 0
|
207
|
+
_lower = _keys
|
208
|
+
_upper = _keys + (_klen << 1) - 2
|
209
|
+
loop do
|
210
|
+
break if _upper < _lower
|
211
|
+
_mid = _lower + (((_upper-_lower) >> 1) & ~1)
|
212
|
+
if data[p].ord < _parser_trans_keys[_mid]
|
213
|
+
_upper = _mid - 2
|
214
|
+
elsif data[p].ord > _parser_trans_keys[_mid+1]
|
215
|
+
_lower = _mid + 2
|
216
|
+
else
|
217
|
+
_trans += ((_mid - _keys) >> 1)
|
218
|
+
_break_match = true
|
219
|
+
break
|
220
|
+
end
|
221
|
+
end # loop
|
222
|
+
break if _break_match
|
223
|
+
_trans += _klen
|
224
|
+
end
|
225
|
+
end while false
|
226
|
+
_trans = _parser_indicies[_trans]
|
227
|
+
cs = _parser_trans_targs[_trans]
|
228
|
+
if _parser_trans_actions[_trans] != 0
|
229
|
+
_acts = _parser_trans_actions[_trans]
|
230
|
+
_nacts = _parser_actions[_acts]
|
231
|
+
_acts += 1
|
232
|
+
while _nacts > 0
|
233
|
+
_nacts -= 1
|
234
|
+
_acts += 1
|
235
|
+
case _parser_actions[_acts - 1]
|
236
|
+
when 0 then
|
237
|
+
begin
|
238
|
+
start_name = p end
|
239
|
+
when 1 then
|
240
|
+
begin
|
241
|
+
self.name = read(data, start_name, p) end
|
242
|
+
when 2 then
|
243
|
+
begin
|
244
|
+
start_column_name = p end
|
245
|
+
when 3 then
|
246
|
+
begin
|
247
|
+
column_names << read(data, start_column_name, p) end
|
248
|
+
end # action switch
|
249
|
+
end
|
250
|
+
end
|
251
|
+
if _trigger_goto
|
252
|
+
next
|
253
|
+
end
|
254
|
+
end
|
255
|
+
if _goto_level <= _again
|
256
|
+
if cs == 0
|
257
|
+
_goto_level = _out
|
258
|
+
next
|
259
|
+
end
|
260
|
+
p += 1
|
261
|
+
if p != pe
|
262
|
+
_goto_level = _resume
|
263
|
+
next
|
264
|
+
end
|
265
|
+
end
|
266
|
+
if _goto_level <= _test_eof
|
267
|
+
end
|
268
|
+
if _goto_level <= _out
|
269
|
+
break
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
# % (this fixes syntax highlighting)
|
275
|
+
self
|
276
|
+
end
|
277
|
+
|
278
|
+
def column_names=(column_names)
|
279
|
+
@column_names = [column_names].compact.flatten
|
280
|
+
end
|
281
|
+
|
282
|
+
def to_sql(format, options)
|
283
|
+
return if primary_key
|
284
|
+
return if unique and name.nil?
|
285
|
+
parts = []
|
286
|
+
parts << 'CREATE'
|
287
|
+
parts << 'UNIQUE' if (unique and name)
|
288
|
+
parts << 'INDEX'
|
289
|
+
parts += [ quoted_name(options), 'ON', parent.quoted_table_name(options), '(', quoted_column_names(options), ')' ]
|
290
|
+
parts.join ' '
|
291
|
+
end
|
292
|
+
|
293
|
+
def primary_key
|
294
|
+
if pk = parent.primary_key
|
295
|
+
pk.column_names == column_names
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
def quoted_name(options)
|
300
|
+
if name
|
301
|
+
CreateTable.quote_ident name, options
|
302
|
+
elsif unique
|
303
|
+
"uidx_#{parent.table_name}_on_#{name}"
|
304
|
+
else
|
305
|
+
"idx_#{parent.table_name}_on_#{name}"
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
def quoted_column_names(options)
|
310
|
+
column_names.map do |column_name|
|
311
|
+
CreateTable.quote_ident column_name, options
|
312
|
+
end.join(', ')
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|