Merge lp:~nahiljain/to-drizzle/parse_create_table into lp:to-drizzle
- parse_create_table
- Merge into trunk
Proposed by
neh
Status: | Merged |
---|---|
Merged at revision: | 8 |
Proposed branch: | lp:~nahiljain/to-drizzle/parse_create_table |
Merge into: | lp:to-drizzle |
Diff against target: |
807 lines (+375/-84) 4 files modified
movetodrizzle/helpers/lexer.py (+5/-6) movetodrizzle/helpers/parser.py (+118/-59) movetodrizzle/helpers/statement_nodes.py (+30/-9) tests/parser_createtable_test.py (+222/-10) |
To merge this branch: | bzr merge lp:~nahiljain/to-drizzle/parse_create_table |
Related bugs: | |
Related blueprints: |
parser for parsing create table statements
(Essential)
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jay Pipes | Needs Fixing | ||
Review via email: mp+30552@code.launchpad.net |
Commit message
Description of the change
more test cases for parsing create table... made changes and stored values of length,binary etc
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'movetodrizzle/helpers/lexer.py' |
2 | --- movetodrizzle/helpers/lexer.py 2010-07-07 22:04:33 +0000 |
3 | +++ movetodrizzle/helpers/lexer.py 2010-07-22 18:42:46 +0000 |
4 | @@ -59,9 +59,7 @@ |
5 | 'constraint' : 'CONSTRAINT', |
6 | 'constraint' : 'CONSTRAINT', |
7 | 'references' : 'REFERENCES', |
8 | - 'match' : 'MATCH', |
9 | 'full' : 'FULL', |
10 | - 'match' : 'MATCH', |
11 | 'partial' : 'PARTIAL', |
12 | 'match' : 'MATCH', |
13 | 'simple' : 'SIMPLE', |
14 | @@ -71,7 +69,8 @@ |
15 | 'cascade' : 'CASCADE', |
16 | 'no' : 'NO', |
17 | 'action' : 'ACTION', |
18 | - 'delete' : 'DELETE' |
19 | + 'delete' : 'DELETE', |
20 | + 'comment' : 'COMMENT' |
21 | |
22 | |
23 | } |
24 | @@ -87,7 +86,7 @@ |
25 | 'SEMICOLON', |
26 | 'NUMBER', |
27 | 'FLOAT_NUMBER', |
28 | - 'COMMENT', |
29 | + 'COMMENT_CODE', |
30 | 'IDENTIFIER', |
31 | 'STRING', |
32 | 'DOT', |
33 | @@ -102,7 +101,7 @@ |
34 | t_RPAREN = r'\)' |
35 | t_COMMA = r'\,' |
36 | t_SEMICOLON = r'\;' |
37 | -t_DOT= r'.' |
38 | +t_DOT= r'\.' |
39 | t_EQUAL= r'\=' |
40 | |
41 | def t_NUMBER(t): |
42 | @@ -130,7 +129,7 @@ |
43 | return t |
44 | |
45 | #Define a rule so that we process comments |
46 | -def t_COMMENT(t): |
47 | +def t_COMMENT_CODE(t): |
48 | r'\/\*.*\*\/' |
49 | pass |
50 | |
51 | |
52 | === modified file 'movetodrizzle/helpers/parser.py' |
53 | --- movetodrizzle/helpers/parser.py 2010-07-15 16:41:56 +0000 |
54 | +++ movetodrizzle/helpers/parser.py 2010-07-22 18:42:46 +0000 |
55 | @@ -4,7 +4,6 @@ |
56 | from lexer import * |
57 | import re |
58 | from statement_nodes import * |
59 | - |
60 | # Begin grammar rules |
61 | def p_statement_list(p): |
62 | '''statement_list : statement_list statement''' |
63 | @@ -23,7 +22,7 @@ |
64 | p[0]=p[1] |
65 | |
66 | def p_create_table_simple(p): |
67 | - '''create_table_simple : CREATE temporary TABLE if_not_exists identifier_qualified_opt LPAREN col_list RPAREN table_options''' |
68 | + '''create_table_simple : CREATE temporary TABLE if_not_exists identifier_qualified_non_qualified_opt LPAREN col_list RPAREN table_options''' |
69 | a= CreateTableStatement(p[5], p[7], p[4], p[2]) |
70 | a.update_table_options(p[9]); |
71 | p[0]= a |
72 | @@ -31,17 +30,23 @@ |
73 | def p_table_options(p): |
74 | '''table_options : table_option table_options |
75 | | empty''' |
76 | - if(len(p)>2): |
77 | + if (len(p) > 2): |
78 | p[0]= [p[1]] + p[2] |
79 | else: |
80 | p[0]= [] |
81 | + |
82 | +def p_identifier_qualified_non_qualified_opt(p): |
83 | + '''identifier_qualified_non_qualified_opt : identifier_qualified_opt |
84 | + | identifier_non_qualified_opt''' |
85 | + p[0]= p[1] |
86 | + |
87 | |
88 | def p_qualified_identifier(p): |
89 | '''identifier_qualified_opt : IDENTIFIER DOT IDENTIFIER''' |
90 | p[0]= Identifier(p[1], p[3]) |
91 | |
92 | def p_non_qualified_identifier(p): |
93 | - '''identifier_qualified_opt : IDENTIFIER |
94 | + '''identifier_non_qualified_opt : IDENTIFIER |
95 | | STRING''' |
96 | p[0]= Identifier(p[1]) |
97 | |
98 | @@ -57,11 +62,11 @@ |
99 | def p_col(p): |
100 | '''col : col_conditional |
101 | | col_normal''' |
102 | - p[0]=p[1] |
103 | + p[0]= p[1] |
104 | |
105 | def p_col_conditional(p): |
106 | '''col_conditional : foreign_key_constraint''' |
107 | - p[0]=p[1] |
108 | + p[0]= p[1] |
109 | |
110 | def p_foreign_key_constraint(p): |
111 | '''foreign_key_constraint : constraint_opt FOREIGN KEY index_name_opt LPAREN index_col_name_list RPAREN reference_definition''' |
112 | @@ -71,23 +76,29 @@ |
113 | '''constraint_opt : CONSTRAINT |
114 | | CONSTRAINT identifier |
115 | | empty''' |
116 | - if(len(p)>2): |
117 | + if (len(p) > 2): |
118 | p[0]= p[2] |
119 | else: |
120 | - p[0]= len(p)>2 |
121 | + p[0]= len(p) > 2 |
122 | def p_index_name_opt(p): |
123 | '''index_name_opt : identifier |
124 | | empty ''' |
125 | - p[0]=p[1] |
126 | + if(len(p) > 1): |
127 | + p[0]= p[1] |
128 | + else: |
129 | + p[0]= len(p)>1 |
130 | + |
131 | |
132 | def p_index_col_name_list(p): |
133 | '''index_col_name_list : index_col_name COMMA index_col_name_list |
134 | | index_col_name''' |
135 | - if(len(p)>2): |
136 | + if (len(p) > 2): |
137 | p[0]= [p[1]]+ p[3] |
138 | else: |
139 | p[0]= [p[1]] |
140 | |
141 | + |
142 | + |
143 | def p_index_col_name(p): |
144 | '''index_col_name : identifier''' |
145 | p[0]= p[1] |
146 | @@ -101,26 +112,26 @@ |
147 | | MATCH PARTIAL |
148 | | MATCH SIMPLE |
149 | | empty''' |
150 | - if(len(p)>2): |
151 | + if (len(p) == 3): |
152 | p[0]= p[2] |
153 | else: |
154 | - p[0]= len(p)>2 |
155 | + p[0]= len(p) > 2 |
156 | |
157 | def p_on_delete_option(p): |
158 | '''on_delete_option : ON DELETE reference_options |
159 | | empty''' |
160 | - if(len(p)>3): |
161 | - p[0]= p[2] |
162 | + if (len(p) > 3): |
163 | + p[0]= p[3] |
164 | else: |
165 | - p[0]= len(p)>3 |
166 | + p[0]= len(p) > 3 |
167 | |
168 | def p_on_update_option(p): |
169 | '''on_update_option : ON UPDATE reference_options |
170 | | empty''' |
171 | - if(len(p)>3): |
172 | - p[0]= p[2] |
173 | + if (len(p) > 3): |
174 | + p[0]= p[3] |
175 | else: |
176 | - p[0]= len(p)>3 |
177 | + p[0]= len(p) > 3 |
178 | |
179 | def p_reference_options(p): |
180 | '''reference_options : RESTRICT |
181 | @@ -128,12 +139,12 @@ |
182 | | SET NULL |
183 | | NO ACTION |
184 | | empty''' |
185 | - if(len(p)==2): |
186 | - p[0]=p[1] |
187 | - elif(len(p)==3): |
188 | - p[0]=str(p[1])+str(p[2]) |
189 | + if (len(p) == 2): |
190 | + p[0]= p[1] |
191 | + elif (len(p) == 3): |
192 | + p[0]= str(p[1])+str(p[2]) |
193 | else: |
194 | - p[0]=None |
195 | + p[0]= None |
196 | |
197 | def p_col_normal(p): |
198 | '''col_normal : col_definition''' |
199 | @@ -141,8 +152,10 @@ |
200 | |
201 | def p_col_definition(p): |
202 | '''col_definition : identifier data_type nullable_constraint default_p auto_increment_p unique_p primary_key comment_p''' |
203 | + |
204 | p[0]= ColumnDefinition(p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]) |
205 | |
206 | + |
207 | def p_nullable_constraint(p): |
208 | '''nullable_constraint : NOT NULL |
209 | | NULL |
210 | @@ -152,7 +165,7 @@ |
211 | def p_default_p(p): |
212 | '''default_p : DEFAULT identifier |
213 | | empty''' |
214 | - if(len(p) > 2): |
215 | + if (len(p) > 2): |
216 | p[0]= p[2] |
217 | else: |
218 | p[0]= None |
219 | @@ -174,15 +187,15 @@ |
220 | p[0]= len(p) > 2 |
221 | |
222 | def p_comment_p(p): |
223 | - '''comment_p : COMMENT STRING |
224 | + '''comment_p : COMMENT STRING |
225 | | empty''' |
226 | - if(len(p)>2): |
227 | - p[0]= p[2] |
228 | - else: |
229 | - p[0]= len(p)>2 |
230 | + if (len(p) > 2): |
231 | + p[0]= p[2] |
232 | + else: |
233 | + p[0]= len(p) > 2 |
234 | |
235 | -def p_data_types(p): |
236 | - '''data_type : BIT |
237 | +def p_data_types_1(p): |
238 | + '''data_type : BIT |
239 | | mathematical length_opt unsigned_opt zerofill_opt |
240 | | DATE |
241 | | TIME |
242 | @@ -195,15 +208,34 @@ |
243 | | TINYBLOB |
244 | | BLOB |
245 | | MEDIUMBLOB |
246 | - | LONGBLOB |
247 | - | texts binary_opt character_set_opt collate_opt |
248 | + | LONGBLOB''' |
249 | + p[0]= DataTypeDesc(p[1]) |
250 | + if (len(p) == 1): |
251 | + p[0]= [p[1]] |
252 | + if (len(p) == 5): |
253 | + if(p[2] == False): |
254 | + length= None; |
255 | + decimal= None; |
256 | + elif(len(p[2]) == 2): |
257 | + length= p[2][0]; |
258 | + decimal= p[2][1]; |
259 | + else: |
260 | + length= p[2][0]; |
261 | + decimal= None; |
262 | + p[0]=DataTypeDesc(p[1],length,decimal,p[3],p[4]) |
263 | + if (len(p) == 4): |
264 | + p[0]= DataTypeDesc(p[1],None,None,None,None,p[2],p[3]) |
265 | + |
266 | +def p_data_types_2(p): |
267 | + '''data_type : texts binary_opt character_set_opt collate_opt |
268 | | set_enum character_set_opt collate_opt''' |
269 | - p[0]= p[1] |
270 | + p[0]= DataTypeDesc(p[1]); |
271 | |
272 | def p_set_enum(p): |
273 | '''set_enum : SET LPAREN value_list RPAREN |
274 | | ENUM LPAREN value_list RPAREN''' |
275 | - p[0]=p[1] |
276 | + p[0]= p[1] |
277 | + |
278 | |
279 | def p_value_list(p): |
280 | '''value_list : STRING COMMA value_list |
281 | @@ -229,29 +261,47 @@ |
282 | def p_character_set_opt(p): |
283 | '''character_set_opt : CHARACTER SET identifier |
284 | | empty''' |
285 | - pass |
286 | + if (len(p) > 3): |
287 | + p[0]= p[3] |
288 | + else: |
289 | + p[0]= len(p) > 3 |
290 | |
291 | def p_collate_opt(p): |
292 | '''collate_opt : COLLATE identifier |
293 | | empty''' |
294 | - pass |
295 | + if (len(p) > 2): |
296 | + p[0]= p[2] |
297 | + else: |
298 | + p[0]= len(p) > 2 |
299 | |
300 | def p_length_opt(p): |
301 | '''length_opt : LPAREN NUMBER RPAREN |
302 | | LPAREN NUMBER COMMA NUMBER RPAREN |
303 | | empty''' |
304 | - pass |
305 | + if (len(p) >= 6): |
306 | + p[0]= [p[2],p[4]] |
307 | + |
308 | + elif (len(p) == 4): |
309 | + p[0]= [p[2]] |
310 | + else: |
311 | + p[0]= len(p) > 6; |
312 | + |
313 | + |
314 | |
315 | def p_unsigned_opt(p): |
316 | '''unsigned_opt : UNSIGNED |
317 | | empty''' |
318 | - pass |
319 | + p[0]= len(p) > 1 |
320 | + |
321 | |
322 | def p_zerofill_opt(p): |
323 | '''zerofill_opt : ZEROFILL |
324 | | empty''' |
325 | - pass |
326 | - |
327 | + p[0]= len(p) > 1 |
328 | + |
329 | + |
330 | + |
331 | + |
332 | def p_mathematical(p): |
333 | '''mathematical : TINYINT |
334 | | SMALLINT |
335 | @@ -268,7 +318,7 @@ |
336 | def p_optional_temporary(p): |
337 | '''temporary : TEMPORARY |
338 | | empty''' |
339 | - # Returns True if the TEMPORARY phrase appeared, False otherwise |
340 | + # Returns True if the TEMPORARY phrase appeared, False otherwise |
341 | p[0]= len(p) > 1 |
342 | |
343 | def p_create_schema(p): |
344 | @@ -295,41 +345,45 @@ |
345 | p[0]= CreateSchemaStatement(p[4], p[6], p[8], p[3]) |
346 | |
347 | def p_optional_if_not_exists(p): |
348 | - '''if_not_exists : IF NOT EXISTS |
349 | + '''if_not_exists : IF NOT EXISTS |
350 | | empty''' |
351 | - # Returns True if the IF NOT EXISTS phrase appeared, False otherwise |
352 | + # Returns True if the IF NOT EXISTS phrase appeared, False otherwise |
353 | p[0]= len(p) > 2 |
354 | |
355 | def p_schema_or_database(p): |
356 | - '''schema_or_database : SCHEMA |
357 | + '''schema_or_database : SCHEMA |
358 | | DATABASE''' |
359 | - p[0]= p[1] |
360 | + p[0]= p[1] |
361 | |
362 | def p_identifier(p): |
363 | - '''identifier : IDENTIFIER |
364 | + '''identifier : IDENTIFIER |
365 | | STRING''' |
366 | - p[0]= p[1] |
367 | + p[0]= p[1] |
368 | |
369 | def p_charset(p): |
370 | - '''charset : CHARACTER SET |
371 | + '''charset : CHARACTER SET |
372 | | DEFAULT CHARACTER SET''' |
373 | pass |
374 | |
375 | -def p_table_option(p): |
376 | + |
377 | +def p_table_option_1(p): |
378 | """table_option : ENGINE opt_equal identifier |
379 | | AUTO_INCREMENT opt_equal NUMBER |
380 | | COMMENT opt_equal STRING""" |
381 | - temp=[] |
382 | + temp= [] |
383 | temp.append(p[1]) |
384 | temp.append(p[3]) |
385 | - p[0]=temp; |
386 | + p[0]= temp; |
387 | + |
388 | |
389 | -def p_table_option(p): |
390 | +def p_table_option_2(p): |
391 | '''table_option : default_opt CHARACTER SET opt_equal identifier''' |
392 | - temp=[] |
393 | - temp.append("CHARACTER SET",p[5]); |
394 | + temp= [] |
395 | + temp.append("CHARACTER SET"); |
396 | + temp.append(p[5]); |
397 | p[0]= temp; |
398 | |
399 | + |
400 | def p_default_opt(p): |
401 | '''default_opt : DEFAULT |
402 | | empty''' |
403 | @@ -338,17 +392,21 @@ |
404 | def p_opt_equal(p): |
405 | ''' opt_equal : EQUAL |
406 | | empty''' |
407 | - if(len(p)>1): |
408 | + if (len(p) > 1): |
409 | p[0]= p[1] |
410 | else: |
411 | - p[0]= len(p)>1; |
412 | + p[0]= len(p) > 1; |
413 | + |
414 | + |
415 | + |
416 | |
417 | def p_empty(p): |
418 | 'empty : ' |
419 | - pass # an empty rule that represents an optional piece |
420 | + pass # an empty rule that represents an optional |
421 | + # piece of a rule |
422 | |
423 | def p_error(p): |
424 | - # Called when a syntax or parse error occurs |
425 | + # Called when a syntax or parse error occurs |
426 | print "A parse error occurred at token %s" % p |
427 | |
428 | # Create the parser |
429 | @@ -359,3 +417,4 @@ |
430 | return parser.parse(subject) |
431 | except Exception as e: |
432 | print e |
433 | + |
434 | |
435 | === modified file 'movetodrizzle/helpers/statement_nodes.py' |
436 | --- movetodrizzle/helpers/statement_nodes.py 2010-07-15 16:41:56 +0000 |
437 | +++ movetodrizzle/helpers/statement_nodes.py 2010-07-22 18:42:46 +0000 |
438 | @@ -19,10 +19,32 @@ |
439 | def __repr__(self): |
440 | return "CreateSchemaStatement(schema= %s) (character_set= %s) (collate= %s) (if_not_exists= %s)" % (self.schema_name, self.character_set, self.collate_name, self.if_not_exists) |
441 | |
442 | +class DataTypeDesc(): |
443 | + def __init__(self, data_type, length= None, decimals= None, unsigned= None, zerofill= None, charset_name= None, collate_name= None, binary= None): |
444 | + self.data_type= data_type; |
445 | + self.length= length; |
446 | + self.unsigned= unsigned; |
447 | + self.zerofill= zerofill; |
448 | + self.decimals= decimals; |
449 | + self.collation_name= collate_name; |
450 | + self.charset_name= charset_name; |
451 | + self.binary= binary; |
452 | + |
453 | + def __repr__(self): |
454 | + return "DataTypeDesc(data_type= %s, length= %s, decimals= %s, zerofill= %s, unsigned= %s, collation_name= %s, charset_name= %s, binary= %s)" %( |
455 | + self.data_type, |
456 | + self.length, |
457 | + self.decimals, |
458 | + self.zerofill, |
459 | + self.unsigned, |
460 | + self.collation_name, |
461 | + self.charset_name, |
462 | + self.binary) |
463 | + |
464 | class ColumnDefinition(): |
465 | - def __init__(self, name, data_type, nullable= True, default= None, auto_increment= False, unique= False, primary_key= False, comment= None): |
466 | + def __init__(self, name, data_type_desc, nullable= True, default= None, auto_increment= False, unique= False, primary_key= False, comment= None): |
467 | self.name= name; |
468 | - self.data_type= data_type; |
469 | + self.data_type_desc= data_type_desc; |
470 | self.nullable= nullable; |
471 | self.default= default; |
472 | self.auto_increment= auto_increment; |
473 | @@ -30,9 +52,9 @@ |
474 | self.primary_key= primary_key; |
475 | self.comment= comment; |
476 | def __repr__(self): |
477 | - return "Column(col_name= %s, data_type= %s, nullable= %s, default= %s, auto_increment= %s, unique= %s, primary_key= %s, comment= %s)" % ( |
478 | + return "Column(col_name= %s, data_type_desc= %s, nullable= %s, default= %s, auto_increment= %s, unique= %s, primary_key= %s, comment= %s)" % ( |
479 | self.name, |
480 | - self.data_type, |
481 | + self.data_type_desc, |
482 | self.nullable, |
483 | str(self.default), |
484 | self.auto_increment, |
485 | @@ -50,13 +72,12 @@ |
486 | |
487 | class ForeignKeyConstraint(): |
488 | def __init__(self, constarint_name, index_name, parent_fields, reference): |
489 | - print constarint_name; |
490 | self.constarint_name= constarint_name; |
491 | self.index_name= index_name; |
492 | self.reference= reference; |
493 | self.parent_fields= parent_fields; |
494 | - def __repr__(self): |
495 | - return "Foreign Key(constraint_name= %s) (index_name=%s) (parent_fields= %s) (reference= %s)" %(self.constarint_name, self.index_name, self.parent_fields, self.reference) |
496 | + def __repr__(self): |
497 | + return "ForeignKeyConstraint(constraint_name= %s, index_name= %s, parent_fields= %s, reference= %s)" %(self.constarint_name, self.index_name, self.parent_fields, self.reference) |
498 | |
499 | class ReferenceDefinition(): |
500 | def __init__(self, name, col_name_list, match_option, on_delete, on_update): |
501 | @@ -66,7 +87,7 @@ |
502 | self.on_update= on_update; |
503 | self.on_delete= on_delete; |
504 | def __repr__(self): |
505 | - return "Reference(name= %s) (col_name_list= %s) (match_option= %s) (on_delete= %s) (on_update= %s)" %(self.name, self.col_name_list, self.match_option, self.on_delete, self.on_update); |
506 | + return "Reference(name= %s, col_name_list= %s, match_option= %s, on_delete= %s, on_update= %s)" %(self.name, self.col_name_list, self.match_option, self.on_delete, self.on_update); |
507 | |
508 | class CreateTableStatement(SqlStatement): |
509 | def __init__(self, table_name, list_columns, if_not_exists= False, temporary = False): |
510 | @@ -78,4 +99,4 @@ |
511 | def update_table_options(self, options): |
512 | self.table_options= options |
513 | def __repr__(self): |
514 | - return "CreateTableStatement(table= %s) (if_not_exists= %s) (temporary= %s) (columns= %s)" % (self.table_name, self.if_not_exists, self.temporary, str(self.columns)) |
515 | + return "CreateTableStatement(table= %s) (if_not_exists= %s) (temporary= %s) (columns= %s) (table_options= %s)" % (self.table_name, self.if_not_exists, self.temporary, str(self.columns),self.table_options) |
516 | |
517 | === modified file 'tests/parser_createtable_test.py' |
518 | --- tests/parser_createtable_test.py 2010-07-07 22:04:33 +0000 |
519 | +++ tests/parser_createtable_test.py 2010-07-22 18:42:46 +0000 |
520 | @@ -13,7 +13,7 @@ |
521 | self.assertEqual(ct.table_name.qualifier, None) |
522 | self.assertEqual(ct.table_name.name, "t1") |
523 | self.assertEqual(ct.columns[0].name, "field1") |
524 | - self.assertEqual(str(ct.columns[0].data_type), "INT") |
525 | + self.assertEqual(str(ct.columns[0].data_type_desc.data_type), "INT") |
526 | self.assertEqual(ct.columns[0].nullable, False) |
527 | |
528 | def test_create_table_nullable_explicit(self): |
529 | @@ -23,7 +23,7 @@ |
530 | self.assertEqual(ct.table_name.qualifier, None) |
531 | self.assertEqual(ct.table_name.name, "t1") |
532 | self.assertEqual(ct.columns[0].name, "field1") |
533 | - self.assertEqual(str(ct.columns[0].data_type), "INT") |
534 | + self.assertEqual(str(ct.columns[0].data_type_desc.data_type), "INT") |
535 | self.assertEqual(ct.columns[0].nullable, True) |
536 | |
537 | def test_create_table_nullable_implicit(self): |
538 | @@ -33,7 +33,7 @@ |
539 | self.assertEqual(ct.table_name.qualifier, None) |
540 | self.assertEqual(ct.table_name.name, "t1") |
541 | self.assertEqual(ct.columns[0].name, "field1") |
542 | - self.assertEqual(str(ct.columns[0].data_type), "INT") |
543 | + self.assertEqual(str(ct.columns[0].data_type_desc.data_type), "INT") |
544 | self.assertEqual(ct.columns[0].nullable, True) |
545 | |
546 | def test_create_table_no_default(self): |
547 | @@ -43,7 +43,7 @@ |
548 | self.assertEqual(ct.table_name.qualifier, None) |
549 | self.assertEqual(ct.table_name.name, "t1") |
550 | self.assertEqual(ct.columns[0].name, "field1") |
551 | - self.assertEqual(str(ct.columns[0].data_type), "INT") |
552 | + self.assertEqual(str(ct.columns[0].data_type_desc.data_type), "INT") |
553 | self.assertEqual(ct.columns[0].default, None) |
554 | |
555 | def test_create_table_default_string(self): |
556 | @@ -53,7 +53,7 @@ |
557 | self.assertEqual(ct.table_name.qualifier, None) |
558 | self.assertEqual(ct.table_name.name, "t1") |
559 | self.assertEqual(ct.columns[0].name, "field1") |
560 | - self.assertEqual(str(ct.columns[0].data_type), "INT") |
561 | + self.assertEqual(str(ct.columns[0].data_type_desc.data_type), "INT") |
562 | self.assertEqual(ct.columns[0].default, "42") |
563 | |
564 | def test_create_table_default_string_with_nullable(self): |
565 | @@ -63,7 +63,7 @@ |
566 | self.assertEqual(ct.table_name.qualifier, None) |
567 | self.assertEqual(ct.table_name.name, "t1") |
568 | self.assertEqual(ct.columns[0].name, "field1") |
569 | - self.assertEqual(str(ct.columns[0].data_type), "INT") |
570 | + self.assertEqual(str(ct.columns[0].data_type_desc.data_type), "INT") |
571 | self.assertEqual(ct.columns[0].default, "42") |
572 | self.assertEqual(ct.columns[0].nullable, False) |
573 | |
574 | @@ -96,7 +96,8 @@ |
575 | statements= parser.parse_string(sql) |
576 | self.assertNotEqual(statements, None, "using data_type %s" % data_type) |
577 | ct= statements[0] |
578 | - self.assertEqual(str(ct.columns[0].data_type), data_type) |
579 | + self.assertEqual(str(ct.columns[0].data_type_desc.data_type), data_type) |
580 | + |
581 | |
582 | def test_create_table_primary_key(self): |
583 | sql= "CREATE TABLE t1 (field1 INT NOT NULL PRIMARY KEY);" |
584 | @@ -105,9 +106,220 @@ |
585 | self.assertEqual(ct.table_name.qualifier, None) |
586 | self.assertEqual(ct.table_name.name, "t1") |
587 | self.assertEqual(ct.columns[0].name, "field1") |
588 | - self.assertEqual(str(ct.columns[0].data_type), "INT") |
589 | - self.assertEqual(ct.columns[0].nullable, False) |
590 | - self.assertEqual(ct.columns[0].primary_key, True) |
591 | + self.assertEqual(str(ct.columns[0].data_type_desc.data_type), "INT") |
592 | + self.assertEqual(ct.columns[0].nullable, False) |
593 | + self.assertEqual(ct.columns[0].primary_key, True) |
594 | + |
595 | + def test_create_table__length(self): |
596 | + sql= "CREATE TABLE t1 (field1 INT (26) NOT NULL PRIMARY KEY);" |
597 | + statements= parser.parse_string(sql) |
598 | + ct= statements[0] |
599 | + self.assertEqual(ct.table_name.qualifier, None) |
600 | + self.assertEqual(ct.table_name.name, "t1") |
601 | + self.assertEqual(ct.columns[0].name, "field1") |
602 | + self.assertEqual(str(ct.columns[0].data_type_desc.data_type), "INT") |
603 | + self.assertEqual(str(ct.columns[0].data_type_desc.length), "26") |
604 | + self.assertEqual(ct.columns[0].nullable, False) |
605 | + self.assertEqual(ct.columns[0].primary_key, True) |
606 | + |
607 | + def test_create_table_length_length(self): |
608 | + sql= "CREATE TABLE t1 (field1 DECIMAL (5,2) NOT NULL PRIMARY KEY);" |
609 | + statements= parser.parse_string(sql) |
610 | + ct= statements[0] |
611 | + self.assertEqual(ct.table_name.qualifier, None) |
612 | + self.assertEqual(ct.table_name.name, "t1") |
613 | + self.assertEqual(ct.columns[0].name, "field1") |
614 | + self.assertEqual(str(ct.columns[0].data_type_desc.data_type), "DECIMAL") |
615 | + self.assertEqual(str(ct.columns[0].data_type_desc.length), "5") |
616 | + self.assertEqual(str(ct.columns[0].data_type_desc.decimals), "2") |
617 | + self.assertEqual(ct.columns[0].nullable, False) |
618 | + self.assertEqual(ct.columns[0].primary_key, True) |
619 | + |
620 | + def test_create_table_length_length_unsigned_zerofill(self): |
621 | + sql= "CREATE TABLE t1 (field1 DECIMAL (5,2) UNSIGNED ZEROFILL NOT NULL PRIMARY KEY);" |
622 | + statements= parser.parse_string(sql) |
623 | + ct= statements[0] |
624 | + self.assertEqual(ct.table_name.qualifier, None) |
625 | + self.assertEqual(ct.table_name.name, "t1") |
626 | + self.assertEqual(ct.columns[0].name, "field1") |
627 | + self.assertEqual(str(ct.columns[0].data_type_desc.data_type), "DECIMAL") |
628 | + self.assertEqual(str(ct.columns[0].data_type_desc.length), "5") |
629 | + self.assertEqual(str(ct.columns[0].data_type_desc.decimals), "2") |
630 | + self.assertEqual(ct.columns[0].data_type_desc.unsigned, True) |
631 | + self.assertEqual(ct.columns[0].data_type_desc.zerofill, True) |
632 | + self.assertEqual(ct.columns[0].nullable, False) |
633 | + self.assertEqual(ct.columns[0].primary_key, True) |
634 | + |
635 | + def test_create_table_char_varchar(self): |
636 | + sql= "CREATE TABLE t1 (field1 CHAR CHARACTER SET utf8 COLLATE col1);" |
637 | + statements= parser.parse_string(sql) |
638 | + ct= statements[0] |
639 | + self.assertEqual(ct.table_name.qualifier, None) |
640 | + self.assertEqual(ct.table_name.name, "t1") |
641 | + self.assertEqual(ct.columns[0].name, "field1") |
642 | + self.assertEqual(ct.columns[0].data_type_desc.data_type, "CHAR") |
643 | + self.assertEqual(ct.columns[0].data_type_desc.length, None) |
644 | + self.assertEqual(ct.columns[0].data_type_desc.decimals, None) |
645 | + self.assertEqual(ct.columns[0].data_type_desc.unsigned, None) |
646 | + self.assertEqual(ct.columns[0].data_type_desc.zerofill, None) |
647 | + self.assertEqual(ct.columns[0].data_type_desc.charset_name, 'utf8') |
648 | + self.assertEqual(ct.columns[0].data_type_desc.collation_name, 'col1') |
649 | + self.assertEqual(ct.columns[0].nullable, True) |
650 | + self.assertEqual(ct.columns[0].primary_key, False) |
651 | + |
652 | + def test_create_table_foreign_constraint(self): |
653 | + sql= "CREATE TABLE t1 (field1 DECIMAL NOT NULL PRIMARY KEY, FOREIGN KEY (field1) REFERENCES reftable (ref_field1));" |
654 | + statements= parser.parse_string(sql) |
655 | + ct= statements[0] |
656 | + self.assertEqual(ct.table_name.qualifier, None) |
657 | + self.assertEqual(ct.table_name.name, "t1") |
658 | + self.assertEqual(ct.columns[0].name, "field1") |
659 | + self.assertEqual(str(ct.columns[0].data_type_desc.data_type), "DECIMAL") |
660 | + self.assertEqual(ct.columns[0].nullable, False) |
661 | + self.assertEqual(ct.columns[0].primary_key, True) |
662 | + self.assertEqual(ct.columns[1].constarint_name, False); |
663 | + self.assertEqual(ct.columns[1].index_name, None); |
664 | + self.assertEqual(ct.columns[1].parent_fields[0],"field1"); |
665 | + self.assertEqual(ct.columns[1].reference.name,"reftable"); |
666 | + self.assertEqual(ct.columns[1].reference.col_name_list[0],"ref_field1"); |
667 | + self.assertEqual(ct.columns[1].reference.on_update,False); |
668 | + self.assertEqual(ct.columns[1].reference.on_delete,False); |
669 | + self.assertEqual(ct.columns[1].reference.match_option,False); |
670 | + |
671 | + def test_create_table_foreign_constraint_options(self): |
672 | + sql= "CREATE TABLE t1 (field1 DECIMAL NOT NULL PRIMARY KEY,FOREIGN KEY (field1) REFERENCES reftable (ref_field1) MATCH FULL ON DELETE CASCADE); " |
673 | + statements= parser.parse_string(sql) |
674 | + ct= statements[0] |
675 | + self.assertEqual(ct.table_name.qualifier, None) |
676 | + self.assertEqual(ct.table_name.name, "t1") |
677 | + self.assertEqual(ct.columns[0].name, "field1") |
678 | + self.assertEqual(str(ct.columns[0].data_type_desc.data_type), "DECIMAL") |
679 | + self.assertEqual(ct.columns[0].nullable, False) |
680 | + self.assertEqual(ct.columns[0].primary_key, True) |
681 | + self.assertEqual(ct.columns[1].constarint_name, False); |
682 | + self.assertEqual(ct.columns[1].index_name, None); |
683 | + self.assertEqual(ct.columns[1].parent_fields[0],"field1"); |
684 | + self.assertEqual(ct.columns[1].reference.name,"reftable"); |
685 | + self.assertEqual(ct.columns[1].reference.col_name_list[0],"ref_field1"); |
686 | + self.assertEqual(ct.columns[1].reference.on_update,False); |
687 | + self.assertEqual(ct.columns[1].reference.on_delete,"CASCADE"); |
688 | + self.assertEqual(ct.columns[1].reference.match_option,"FULL"); |
689 | + |
690 | + |
691 | + def test_create_table_foreign_constraint_options_constraint_name(self): |
692 | + sql= "CREATE TABLE t1 (field1 DECIMAL NOT NULL PRIMARY KEY,CONSTRAINT cons1 FOREIGN KEY (field1) REFERENCES reftable (ref_field1) MATCH FULL ON DELETE CASCADE ON UPDATE RESTRICT); " |
693 | + statements= parser.parse_string(sql) |
694 | + ct= statements[0] |
695 | + self.assertEqual(ct.table_name.qualifier, None) |
696 | + self.assertEqual(ct.table_name.name, "t1") |
697 | + self.assertEqual(ct.columns[0].name, "field1") |
698 | + self.assertEqual(str(ct.columns[0].data_type_desc.data_type), "DECIMAL") |
699 | + self.assertEqual(ct.columns[0].nullable, False) |
700 | + self.assertEqual(ct.columns[0].primary_key, True) |
701 | + self.assertEqual(ct.columns[1].constarint_name, 'cons1'); |
702 | + self.assertEqual(ct.columns[1].index_name, None); |
703 | + self.assertEqual(ct.columns[1].parent_fields[0],"field1"); |
704 | + self.assertEqual(ct.columns[1].reference.name,"reftable"); |
705 | + self.assertEqual(ct.columns[1].reference.col_name_list[0],"ref_field1"); |
706 | + self.assertEqual(ct.columns[1].reference.on_update,"RESTRICT"); |
707 | + self.assertEqual(ct.columns[1].reference.on_delete,"CASCADE"); |
708 | + self.assertEqual(ct.columns[1].reference.match_option,"FULL"); |
709 | + |
710 | + def test_create_table_foreign_constraint_options_constraint_no_name(self): |
711 | + sql= "CREATE TABLE t1 (field1 DECIMAL NOT NULL PRIMARY KEY,CONSTRAINT FOREIGN KEY (field1) REFERENCES reftable (ref_field1) MATCH FULL ON DELETE CASCADE); " |
712 | + statements= parser.parse_string(sql) |
713 | + ct= statements[0] |
714 | + self.assertEqual(ct.table_name.qualifier, None) |
715 | + self.assertEqual(ct.table_name.name, "t1") |
716 | + self.assertEqual(ct.columns[0].name, "field1") |
717 | + self.assertEqual(str(ct.columns[0].data_type_desc.data_type), "DECIMAL") |
718 | + self.assertEqual(ct.columns[0].nullable, False) |
719 | + self.assertEqual(ct.columns[0].primary_key, True) |
720 | + self.assertEqual(ct.columns[1].constarint_name, False); |
721 | + self.assertEqual(ct.columns[1].index_name, None); |
722 | + self.assertEqual(ct.columns[1].parent_fields[0],"field1"); |
723 | + self.assertEqual(ct.columns[1].reference.name,"reftable"); |
724 | + self.assertEqual(ct.columns[1].reference.col_name_list[0],"ref_field1"); |
725 | + self.assertEqual(ct.columns[1].reference.on_update,False); |
726 | + self.assertEqual(ct.columns[1].reference.on_delete,"CASCADE"); |
727 | + self.assertEqual(ct.columns[1].reference.match_option,"FULL"); |
728 | + |
729 | + def test_create_table_table_option(self): |
730 | + sql= "CREATE TABLE t1 (field1 INT NOT NULL PRIMARY KEY) AUTO_INCREMENT 5;" |
731 | + statements= parser.parse_string(sql) |
732 | + ct= statements[0] |
733 | + self.assertEqual(ct.table_name.qualifier, None) |
734 | + self.assertEqual(ct.table_name.name, "t1") |
735 | + self.assertEqual(ct.columns[0].name, "field1") |
736 | + self.assertEqual(str(ct.columns[0].data_type_desc.data_type), "INT") |
737 | + self.assertEqual(ct.columns[0].nullable, False) |
738 | + self.assertEqual(ct.columns[0].primary_key, True) |
739 | + self.assertEqual(ct.table_options[0][0],"AUTO_INCREMENT"); |
740 | + self.assertEqual(ct.table_options[0][1],5); |
741 | + |
742 | + def test_create_table_table_option_multiple(self): |
743 | + sql= "CREATE TABLE t1 (field1 INT NOT NULL PRIMARY KEY) AUTO_INCREMENT 5 CHARACTER SET utf8;" |
744 | + statements= parser.parse_string(sql) |
745 | + ct= statements[0] |
746 | + self.assertEqual(ct.table_name.qualifier, None) |
747 | + self.assertEqual(ct.table_name.name, "t1") |
748 | + self.assertEqual(ct.columns[0].name, "field1") |
749 | + self.assertEqual(str(ct.columns[0].data_type_desc.data_type), "INT") |
750 | + self.assertEqual(ct.columns[0].nullable, False) |
751 | + self.assertEqual(ct.columns[0].primary_key, True) |
752 | + self.assertEqual(ct.table_options[0][0],"AUTO_INCREMENT"); |
753 | + self.assertEqual(ct.table_options[0][1],5); |
754 | + self.assertEqual(ct.table_options[1][0],"CHARACTER SET"); |
755 | + self.assertEqual(ct.table_options[1][1],"utf8"); |
756 | + |
757 | + def test_create_table_table_option_comment(self): |
758 | + sql= "CREATE TABLE t1 (field1 INT) COMMENT 'comment1';" |
759 | + statements= parser.parse_string(sql) |
760 | + ct= statements[0] |
761 | + self.assertEqual(ct.table_name.qualifier, None) |
762 | + self.assertEqual(ct.table_name.name, "t1") |
763 | + self.assertEqual(ct.columns[0].name, "field1") |
764 | + self.assertEqual(str(ct.columns[0].data_type_desc.data_type), "INT") |
765 | + self.assertEqual(ct.table_options[0][0],"COMMENT"); |
766 | + self.assertEqual(ct.table_options[0][1],"comment1"); |
767 | + |
768 | + def test_create_table_qualified_identifier(self): |
769 | + sql= "CREATE TABLE t2.t1 (field1 INT);" |
770 | + statements= parser.parse_string(sql) |
771 | + ct= statements[0] |
772 | + self.assertEqual(ct.table_name.qualifier, "t1") |
773 | + self.assertEqual(ct.table_name.name, "t2") |
774 | + self.assertEqual(ct.columns[0].name, "field1") |
775 | + self.assertEqual(str(ct.columns[0].data_type_desc.data_type), "INT") |
776 | + |
777 | + |
778 | + def test_create_table_col_list_multiple_ol(self): |
779 | + sql= "CREATE TABLE t1 (field1 INT, field2 CHAR,field3 BLOB);" |
780 | + statements= parser.parse_string(sql) |
781 | + ct= statements[0] |
782 | + self.assertEqual(ct.table_name.qualifier, None) |
783 | + self.assertEqual(ct.table_name.name, "t1") |
784 | + self.assertEqual(ct.columns[0].name, "field1") |
785 | + self.assertEqual(str(ct.columns[0].data_type_desc.data_type), "INT") |
786 | + self.assertEqual(ct.columns[1].name, "field2") |
787 | + self.assertEqual(str(ct.columns[1].data_type_desc.data_type), "CHAR") |
788 | + self.assertEqual(ct.columns[2].name, "field3") |
789 | + self.assertEqual(str(ct.columns[2].data_type_desc.data_type), "BLOB") |
790 | + |
791 | + def test_create_table_table_option(self): |
792 | + sql= "CREATE TABLE t1 (field1 INT NOT NULL DEFAULT a AUTO_INCREMENT PRIMARY KEY COMMENT 'comment1');" |
793 | + statements= parser.parse_string(sql) |
794 | + ct= statements[0] |
795 | + self.assertEqual(ct.table_name.qualifier, None) |
796 | + self.assertEqual(ct.table_name.name, "t1") |
797 | + self.assertEqual(ct.columns[0].name, "field1") |
798 | + self.assertEqual(str(ct.columns[0].data_type_desc.data_type), "INT") |
799 | + self.assertEqual(ct.columns[0].nullable, False) |
800 | + self.assertEqual(ct.columns[0].primary_key, True) |
801 | + self.assertEqual(ct.columns[0].auto_increment, True) |
802 | + self.assertEqual(ct.columns[0].comment,"comment1") |
803 | + |
804 | + |
805 | |
806 | if __name__ == '__main__': |
807 | unittest.main() |
Hi!
Looks good, Nahil, but there's a few issues to fix up!
1) There is some extra print happening in the parse create table test case, as shown in the output here:
jpipes@ serialcoder: ~/repos/ movetodrizzle/ parse_create_ table/tests$ ./parser_ createtable_ test.py .....[[ 'AUTO_INCREMENT ', 5]] ------- ------- ------- ------- ------- ------- ------- ------- -------
.......
.
-------
Ran 13 tests in 0.009s
OK
Remove the printing of the [[AUTO_INCREMENT', 5]]
2) Remove all commented-out code:
60 +# '''foreign_ key_constraint : FOREIGN KEY LPAREN index_col_name_list RPAREN reference_ definition' ''
174 +
175 +#def p_data_types(p):
176 +# '''data_type : mathematical'''
177 +# p[0]= p[1]
178 +
179 +
180 +
303 +#print parse_string( "INSERT INTO neh1 VALUES (123,456,'abc');") "INSERT INTO neh1 SET a1=10,b2=25;")
304 +#print parse_string(
491 +# constraint_name= False) (index_name=None) (parent_fields= ['field1']) (reference= Reference(name= reftable) (col_name_list= ['ref_field1']) (match_option= False) (on_delete= False) (on_update= False))])]
3) Please, please be consistent in your code and spacing. :)
134 + if(len(p)>3):
135 + p[0]=p[3]
Please put a single space between if and the (
Please put a single space before and after the >
Please put a single space after the =
There are more places where the style is inconsistent. Please do fix them up :)
4) Tabs and spacing is off in your code. For instance:
188 - '''temporary : TEMPORARY
189 + '''temporary : TEMPORARY
190 | empty'''
191 - # Returns True if the TEMPORARY phrase appeared, False otherwise
192 - p[0]= len(p) > 1
193 + # Returns True if the TEMPORARY phrase appeared, False otherwise
194 + p[0]= len(p) > 1
For some reason, you are re-setting Tabs to a single space. Please make sure all indentation is exactly 2 spaces.
5) Returned data_type should not be a list.
357 - self.assertEqua l(str(ct. columns[ 0].data_ type), "INT") l(str(ct. columns[ 0].data_ type[0] ), "INT")
358 + self.assertEqua
Above, the columns[ 0].data_ type should be "INT", not ["INT"] ...
Cheers!
jay