1   package org.apache.torque.engine.database.transform;
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  import java.io.BufferedReader;
23  import java.io.FileReader;
24  import java.io.IOException;
25  import java.util.ArrayList;
26  import java.util.Iterator;
27  import java.util.List;
28  
29  import org.apache.torque.engine.database.model.Column;
30  import org.apache.torque.engine.database.model.Database;
31  import org.apache.torque.engine.database.model.ForeignKey;
32  import org.apache.torque.engine.database.model.IDMethod;
33  import org.apache.torque.engine.database.model.Table;
34  import org.apache.torque.engine.sql.ParseException;
35  import org.apache.torque.engine.sql.SQLScanner;
36  import org.apache.torque.engine.sql.Token;
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  public class SQLToAppData
49  {
50      private String sqlFile;
51      private List tokens;
52      private Token token;
53      private Database appDataDB;
54      private int count;
55      private String databaseType;
56  
57      
58  
59  
60  
61  
62      public SQLToAppData(String sqlFile)
63      {
64          this.sqlFile = sqlFile;
65      }
66  
67      
68  
69  
70  
71  
72  
73  
74  
75      public SQLToAppData(String sqlFile, String databaseType)
76      {
77          this.sqlFile = sqlFile;
78          this.databaseType = databaseType;
79      }
80  
81      
82  
83  
84  
85  
86      public String getSqlFile()
87      {
88          return sqlFile;
89      }
90  
91      
92  
93  
94  
95  
96      public void setSqlFile(String sqlFile)
97      {
98          this.sqlFile = sqlFile;
99      }
100 
101     
102 
103 
104 
105 
106     private void next() throws ParseException
107     {
108         if (count < tokens.size())
109         {
110             token = (Token) tokens.get(count++);
111         }
112         else
113         {
114             throw new ParseException("No More Tokens");
115         }
116     }
117 
118     
119 
120 
121 
122 
123 
124 
125 
126     private void err(String name) throws ParseException
127     {
128         throw new ParseException (name + " at [ line: " + token.getLine()
129                 + " col: " + token.getCol() + " ]");
130     }
131 
132     
133 
134 
135 
136 
137     private boolean hasTokens()
138     {
139         return count < tokens.size();
140     }
141 
142     
143 
144 
145 
146 
147     private void create() throws ParseException
148     {
149         next();
150         if (token.getStr().toUpperCase().equals("TABLE"))
151         {
152             create_Table();
153         }
154     }
155 
156     
157 
158 
159 
160 
161     private void create_Table() throws ParseException
162     {
163         next();
164         String tableName = token.getStr(); 
165         next();
166         if (!token.getStr().equals("("))
167         {
168             err("( expected");
169         }
170         next();
171 
172         Table tbl = new Table (tableName);
173         
174         while (!token.getStr().equals(";"))
175         {
176             create_Table_Column(tbl);
177         }
178 
179         if (tbl.getPrimaryKey().size() == 1)
180         {
181             tbl.setIdMethod(IDMethod.ID_BROKER);
182         }
183         else
184         {
185             tbl.setIdMethod(IDMethod.NO_ID_METHOD);
186         }
187         appDataDB.addTable (tbl);
188     }
189 
190     
191 
192 
193 
194 
195 
196     private void create_Table_Column(Table tbl) throws ParseException
197     {
198         
199         
200         
201         if (token.getStr().equals(","))
202         {
203             next();
204         }
205 
206         if (token.getStr().toUpperCase().equals("PRIMARY"))
207         {
208             create_Table_Column_Primary(tbl);
209         }
210         else if (token.getStr().toUpperCase().equals("FOREIGN"))
211         {
212             create_Table_Column_Foreign(tbl);
213         }
214         else if (token.getStr().toUpperCase().equals("UNIQUE"))
215         {
216             create_Table_Column_Unique(tbl);
217         }
218         else
219         {
220             create_Table_Column_Data(tbl);
221         }
222     }
223 
224     
225 
226 
227 
228 
229     private void create_Table_Column_Primary (Table tbl) throws ParseException
230     {
231         next();
232         if (!token.getStr().toUpperCase().equals("KEY"))
233         {
234             err("KEY expected");
235         }
236         next();
237         if (!token.getStr().toUpperCase().equals("("))
238         {
239             err("( expected");
240         }
241         next();
242 
243         String colName = token.getStr();
244         Column c = tbl.getColumn(colName);
245         if (c == null)
246         {
247             err("Invalid column name: " + colName);
248         }
249         c.setPrimaryKey(true);
250         next();
251         while (token.getStr().equals(","))
252         {
253             next();
254             colName = token.getStr();
255             c = tbl.getColumn(colName);
256             if (c == null)
257             {
258                 err("Invalid column name: " + colName);
259             }
260             c.setPrimaryKey(true);
261             next();
262         }
263 
264         if (!token.getStr().toUpperCase().equals(")"))
265         {
266             err(") expected");
267         }
268         next(); 
269     }
270 
271     
272 
273 
274 
275 
276     private void create_Table_Column_Unique(Table tbl) throws ParseException
277     {
278         next();
279         if (!token.getStr().toUpperCase().equals("("))
280         {
281             err("( expected");
282         }
283         next();
284         while (!token.getStr().equals(")"))
285         {
286             if (!token.getStr().equals(","))
287             {
288                 String colName = token.getStr();
289                 Column c = tbl.getColumn(colName);
290                 if (c == null)
291                 {
292                     err("Invalid column name: " + colName);
293                 }
294                 c.setUnique(true);
295             }
296             next();
297         }
298         if (!token.getStr().toUpperCase().equals(")"))
299         {
300             err(") expected got: " + token.getStr());
301         }
302 
303         next(); 
304     }
305 
306     
307 
308 
309 
310 
311     private void create_Table_Column_Foreign(Table tbl) throws ParseException
312     {
313         next();
314         if (!token.getStr().toUpperCase().equals("KEY"))
315         {
316             err("KEY expected");
317         }
318         next();
319         if (!token.getStr().toUpperCase().equals("("))
320         {
321             err("( expected");
322         }
323         next();
324 
325         ForeignKey fk = new ForeignKey();
326         List localColumns = new ArrayList();
327         tbl.addForeignKey(fk);
328 
329         String colName = token.getStr();
330         localColumns.add(colName);
331         next();
332         while (token.getStr().equals(","))
333         {
334             next();
335             colName = token.getStr();
336             localColumns.add(colName);
337             next();
338         }
339         if (!token.getStr().toUpperCase().equals(")"))
340         {
341             err(") expected");
342         }
343 
344         next();
345 
346         if (!token.getStr().toUpperCase().equals("REFERENCES"))
347         {
348             err("REFERENCES expected");
349         }
350 
351         next();
352 
353         fk.setForeignTableName(token.getStr());
354 
355         next();
356 
357         if (token.getStr().toUpperCase().equals("("))
358         {
359             next();
360             int i = 0;
361             fk.addReference((String) localColumns.get(i++), token.getStr());
362             next();
363             while (token.getStr().equals(","))
364             {
365                 next();
366                 fk.addReference((String) localColumns.get(i++), token.getStr());
367                 next();
368             }
369             if (!token.getStr().toUpperCase().equals(")"))
370             {
371                 err(") expected");
372             }
373             next();
374         }
375     }
376 
377     
378 
379 
380 
381 
382     private void create_Table_Column_Data(Table tbl) throws ParseException
383     {
384         String columnSize = null;
385         String columnPrecision = null;
386         String columnDefault = null;
387         boolean inEnum = false;
388 
389         String columnName = token.getStr();
390         next();
391         String columnType = token.getStr();
392 
393         if (columnName.equals(")") && columnType.equals(";"))
394         {
395             return;
396         }
397 
398         next();
399 
400         
401         
402         if (columnType.toUpperCase().equals("ENUM"))
403         {
404             inEnum = true;
405             next(); 
406             while (!token.getStr().equals(")"))
407             {
408                 
409                 next();
410             }
411             while (!token.getStr().equals(","))
412             {
413                 if (token.getStr().toUpperCase().equals("DEFAULT"))
414                 {
415                     next();
416                     if (token.getStr().equals("'"))
417                     {
418                         next();
419                     }
420                     columnDefault = token.getStr();
421                     next();
422                     if (token.getStr().equals("'"))
423                     {
424                         next();
425                     }
426                 }
427                 
428                 next();
429             }
430             next(); 
431             columnType = "VARCHAR";
432         }
433         else if (token.getStr().toUpperCase().equals("("))
434         {
435             next();
436             columnSize = token.getStr();
437             next();
438             if (token.getStr().equals(","))
439             {
440                 next();
441                 columnPrecision = token.getStr();
442                 next();
443             }
444 
445             if (!token.getStr().equals(")"))
446             {
447                 err(") expected");
448             }
449             next();
450         }
451 
452         Column col = new Column(columnName);
453         if (columnPrecision != null)
454         {
455             columnSize = columnSize + columnPrecision;
456         }
457         col.setTypeFromString(columnType, columnSize);
458         tbl.addColumn(col);
459 
460         if (inEnum)
461         {
462             col.setNotNull(true);
463             if (columnDefault != null)
464             {
465                 col.setDefaultValue(columnDefault);
466             }
467         }
468         else
469         {
470             while (!token.getStr().equals(",") && !token.getStr().equals(")"))
471             {
472                 if (token.getStr().toUpperCase().equals("NOT"))
473                 {
474                     next();
475                     if (!token.getStr().toUpperCase().equals("NULL"))
476                     {
477                         err("NULL expected after NOT");
478                     }
479                     col.setNotNull(true);
480                     next();
481                 }
482                 else if (token.getStr().toUpperCase().equals("PRIMARY"))
483                 {
484                     next();
485                     if (!token.getStr().toUpperCase().equals("KEY"))
486                     {
487                         err("KEY expected after PRIMARY");
488                     }
489                     col.setPrimaryKey(true);
490                     next();
491                 }
492                 else if (token.getStr().toUpperCase().equals("UNIQUE"))
493                 {
494                     col.setUnique(true);
495                     next();
496                 }
497                 else if (token.getStr().toUpperCase().equals("NULL"))
498                 {
499                     col.setNotNull(false);
500                     next();
501                 }
502                 else if (token.getStr().toUpperCase().equals("AUTO_INCREMENT"))
503                 {
504                     col.setAutoIncrement(true);
505                     next();
506                 }
507                 else if (token.getStr().toUpperCase().equals("DEFAULT"))
508                 {
509                     next();
510                     if (token.getStr().equals("'"))
511                     {
512                         next();
513                     }
514                     col.setDefaultValue(token.getStr());
515                     next();
516                     if (token.getStr().equals("'"))
517                     {
518                         next();
519                     }
520                 }
521                 else
522                 {
523                     StringBuffer line = new StringBuffer();
524                     for (Iterator tokenIt = tokens.iterator();
525                        tokenIt.hasNext();)
526                     {
527                         line.append(tokenIt.next());
528                         if (tokenIt.hasNext())
529                         {
530                             line.append(" ");
531                         }
532                     }
533                     throw new ParseException("Error parsing line "
534                             + line + " : Unknown token Nr. "
535                             + count
536                             + " : "
537                             + token);
538                 }
539             }
540             next(); 
541         }
542     }
543 
544     
545 
546 
547 
548 
549 
550     public Database execute() throws IOException, ParseException
551     {
552         count = 0;
553         appDataDB = new Database(databaseType);
554 
555         FileReader fr = new FileReader(sqlFile);
556         BufferedReader br = new BufferedReader(fr);
557         SQLScanner scanner = new SQLScanner(br);
558 
559         tokens = scanner.scan();
560 
561         br.close();
562 
563         while (hasTokens())
564         {
565             if (token == null)
566             {
567                 next();
568             }
569 
570             if (token.getStr().toUpperCase().equals("CREATE"))
571             {
572                 create();
573             }
574             if (hasTokens())
575             {
576                 next();
577             }
578         }
579         return appDataDB;
580     }
581 }