Clover Coverage Report - Impex Parent 1.0.21-SNAPSHOT (Aggregated)
Coverage timestamp: Tue Feb 8 2011 11:33:53 EST
../../../../../../img/srcFileCovDistChart0.png 0% of files have more coverage
211   581   75   14.07
116   417   0.36   15
15     5  
1    
 
  SQLToAppData       Line # 48 211 0% 75 342 0% 0.0
 
No Tests
 
1    package org.apache.torque.engine.database.transform;
2   
3    /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements. See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership. The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10    * with the License. You may obtain a copy of the License at
11    *
12    * http://www.apache.org/licenses/LICENSE-2.0
13    *
14    * Unless required by applicable law or agreed to in writing,
15    * software distributed under the License is distributed on an
16    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17    * KIND, either express or implied. See the License for the
18    * specific language governing permissions and limitations
19    * under the License.
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    * A Class that converts an sql input file to a Database structure.
40    * The class makes use of SQL Scanner to get
41    * sql tokens and the parses these to create the Database
42    * class. SQLToAppData is in effect a simplified sql parser.
43    *
44    * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
45    * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
46    * @version $Id: SQLToAppData.java,v 1.1 2007-10-21 07:57:26 abyrne Exp $
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    * Create a new class with an input Reader
59    *
60    * @param sqlFile the sql file
61    */
 
62  0 toggle public SQLToAppData(String sqlFile)
63    {
64  0 this.sqlFile = sqlFile;
65    }
66   
67    /**
68    * Create a new class with an input Reader. This ctor is not used
69    * but putting here in the event db.props properties are found to
70    * be useful converting sql to xml, the infrastructure will exist
71    *
72    * @param sqlFile the sql file
73    * @param databaseType
74    */
 
75  0 toggle public SQLToAppData(String sqlFile, String databaseType)
76    {
77  0 this.sqlFile = sqlFile;
78  0 this.databaseType = databaseType;
79    }
80   
81    /**
82    * Get the current input sql file
83    *
84    * @return the sql file
85    */
 
86  0 toggle public String getSqlFile()
87    {
88  0 return sqlFile;
89    }
90   
91    /**
92    * Set the current input sql file
93    *
94    * @param sqlFile the sql file
95    */
 
96  0 toggle public void setSqlFile(String sqlFile)
97    {
98  0 this.sqlFile = sqlFile;
99    }
100   
101    /**
102    * Move to the next token.
103    *
104    * @throws ParseException if there is no more tokens available.
105    */
 
106  0 toggle private void next() throws ParseException
107    {
108  0 if (count < tokens.size())
109    {
110  0 token = (Token) tokens.get(count++);
111    }
112    else
113    {
114  0 throw new ParseException("No More Tokens");
115    }
116    }
117   
118    /**
119    * Creates an error condition and adds the line and
120    * column number of the current token to the error
121    * message.
122    *
123    * @param name name of the error
124    * @throws ParseException
125    */
 
126  0 toggle private void err(String name) throws ParseException
127    {
128  0 throw new ParseException (name + " at [ line: " + token.getLine()
129    + " col: " + token.getCol() + " ]");
130    }
131   
132    /**
133    * Check if there is more tokens available for parsing.
134    *
135    * @return true if there are more tokens available
136    */
 
137  0 toggle private boolean hasTokens()
138    {
139  0 return count < tokens.size();
140    }
141   
142    /**
143    * Parses a CREATE TABLE FOO command.
144    *
145    * @throws ParseException
146    */
 
147  0 toggle private void create() throws ParseException
148    {
149  0 next();
150  0 if (token.getStr().toUpperCase().equals("TABLE"))
151    {
152  0 create_Table();
153    }
154    }
155   
156    /**
157    * Parses a CREATE TABLE sql command
158    *
159    * @throws ParseException error parsing the input file
160    */
 
161  0 toggle private void create_Table() throws ParseException
162    {
163  0 next();
164  0 String tableName = token.getStr(); // name of the table
165  0 next();
166  0 if (!token.getStr().equals("("))
167    {
168  0 err("( expected");
169    }
170  0 next();
171   
172  0 Table tbl = new Table (tableName);
173    //tbl.setIdMethod("none");
174  0 while (!token.getStr().equals(";"))
175    {
176  0 create_Table_Column(tbl);
177    }
178   
179  0 if (tbl.getPrimaryKey().size() == 1)
180    {
181  0 tbl.setIdMethod(IDMethod.ID_BROKER);
182    }
183    else
184    {
185  0 tbl.setIdMethod(IDMethod.NO_ID_METHOD);
186    }
187  0 appDataDB.addTable (tbl);
188    }
189   
190    /**
191    * Parses column information between the braces of a CREATE
192    * TABLE () sql statement.
193    *
194    * @throws ParseException error parsing the input file
195    */
 
196  0 toggle private void create_Table_Column(Table tbl) throws ParseException
197    {
198    // The token should be the first item
199    // which is the name of the column or
200    // PRIMARY/FOREIGN/UNIQUE
201  0 if (token.getStr().equals(","))
202    {
203  0 next();
204    }
205   
206  0 if (token.getStr().toUpperCase().equals("PRIMARY"))
207    {
208  0 create_Table_Column_Primary(tbl);
209    }
210  0 else if (token.getStr().toUpperCase().equals("FOREIGN"))
211    {
212  0 create_Table_Column_Foreign(tbl);
213    }
214  0 else if (token.getStr().toUpperCase().equals("UNIQUE"))
215    {
216  0 create_Table_Column_Unique(tbl);
217    }
218    else
219    {
220  0 create_Table_Column_Data(tbl);
221    }
222    }
223   
224    /**
225    * Parses PRIMARY KEY (FOO,BAR) statement
226    *
227    * @throws ParseException error parsing the input file
228    */
 
229  0 toggle private void create_Table_Column_Primary (Table tbl) throws ParseException
230    {
231  0 next();
232  0 if (!token.getStr().toUpperCase().equals("KEY"))
233    {
234  0 err("KEY expected");
235    }
236  0 next();
237  0 if (!token.getStr().toUpperCase().equals("("))
238    {
239  0 err("( expected");
240    }
241  0 next();
242   
243  0 String colName = token.getStr();
244  0 Column c = tbl.getColumn(colName);
245  0 if (c == null)
246    {
247  0 err("Invalid column name: " + colName);
248    }
249  0 c.setPrimaryKey(true);
250  0 next();
251  0 while (token.getStr().equals(","))
252    {
253  0 next();
254  0 colName = token.getStr();
255  0 c = tbl.getColumn(colName);
256  0 if (c == null)
257    {
258  0 err("Invalid column name: " + colName);
259    }
260  0 c.setPrimaryKey(true);
261  0 next();
262    }
263   
264  0 if (!token.getStr().toUpperCase().equals(")"))
265    {
266  0 err(") expected");
267    }
268  0 next(); // skip the )
269    }
270   
271    /**
272    * Parses UNIQUE (NAME,FOO,BAR) statement
273    *
274    * @throws ParseException error parsing the input file
275    */
 
276  0 toggle private void create_Table_Column_Unique(Table tbl) throws ParseException
277    {
278  0 next();
279  0 if (!token.getStr().toUpperCase().equals("("))
280    {
281  0 err("( expected");
282    }
283  0 next();
284  0 while (!token.getStr().equals(")"))
285    {
286  0 if (!token.getStr().equals(","))
287    {
288  0 String colName = token.getStr();
289  0 Column c = tbl.getColumn(colName);
290  0 if (c == null)
291    {
292  0 err("Invalid column name: " + colName);
293    }
294  0 c.setUnique(true);
295    }
296  0 next();
297    }
298  0 if (!token.getStr().toUpperCase().equals(")"))
299    {
300  0 err(") expected got: " + token.getStr());
301    }
302   
303  0 next(); // skip the )
304    }
305   
306    /**
307    * Parses FOREIGN KEY (BAR) REFERENCES TABLE (BAR) statement
308    *
309    * @throws ParseException error parsing the input file
310    */
 
311  0 toggle private void create_Table_Column_Foreign(Table tbl) throws ParseException
312    {
313  0 next();
314  0 if (!token.getStr().toUpperCase().equals("KEY"))
315    {
316  0 err("KEY expected");
317    }
318  0 next();
319  0 if (!token.getStr().toUpperCase().equals("("))
320    {
321  0 err("( expected");
322    }
323  0 next();
324   
325  0 ForeignKey fk = new ForeignKey();
326  0 List localColumns = new ArrayList();
327  0 tbl.addForeignKey(fk);
328   
329  0 String colName = token.getStr();
330  0 localColumns.add(colName);
331  0 next();
332  0 while (token.getStr().equals(","))
333    {
334  0 next();
335  0 colName = token.getStr();
336  0 localColumns.add(colName);
337  0 next();
338    }
339  0 if (!token.getStr().toUpperCase().equals(")"))
340    {
341  0 err(") expected");
342    }
343   
344  0 next();
345   
346  0 if (!token.getStr().toUpperCase().equals("REFERENCES"))
347    {
348  0 err("REFERENCES expected");
349    }
350   
351  0 next();
352   
353  0 fk.setForeignTableName(token.getStr());
354   
355  0 next();
356   
357  0 if (token.getStr().toUpperCase().equals("("))
358    {
359  0 next();
360  0 int i = 0;
361  0 fk.addReference((String) localColumns.get(i++), token.getStr());
362  0 next();
363  0 while (token.getStr().equals(","))
364    {
365  0 next();
366  0 fk.addReference((String) localColumns.get(i++), token.getStr());
367  0 next();
368    }
369  0 if (!token.getStr().toUpperCase().equals(")"))
370    {
371  0 err(") expected");
372    }
373  0 next();
374    }
375    }
376   
377    /**
378    * Parse the data definition of the column statement.
379    *
380    * @throws ParseException error parsing the input file
381    */
 
382  0 toggle private void create_Table_Column_Data(Table tbl) throws ParseException
383    {
384  0 String columnSize = null;
385  0 String columnPrecision = null;
386  0 String columnDefault = null;
387  0 boolean inEnum = false;
388   
389  0 String columnName = token.getStr();
390  0 next();
391  0 String columnType = token.getStr();
392   
393  0 if (columnName.equals(")") && columnType.equals(";"))
394    {
395  0 return;
396    }
397   
398  0 next();
399   
400    // special case for MySQL ENUM's which are stupid anyway
401    // and not properly handled by Torque.
402  0 if (columnType.toUpperCase().equals("ENUM"))
403    {
404  0 inEnum = true;
405  0 next(); // skip (
406  0 while (!token.getStr().equals(")"))
407    {
408    // skip until )
409  0 next();
410    }
411  0 while (!token.getStr().equals(","))
412    {
413  0 if (token.getStr().toUpperCase().equals("DEFAULT"))
414    {
415  0 next();
416  0 if (token.getStr().equals("'"))
417    {
418  0 next();
419    }
420  0 columnDefault = token.getStr();
421  0 next();
422  0 if (token.getStr().equals("'"))
423    {
424  0 next();
425    }
426    }
427    // skip until ,
428  0 next();
429    }
430  0 next(); // skip ,
431  0 columnType = "VARCHAR";
432    }
433  0 else if (token.getStr().toUpperCase().equals("("))
434    {
435  0 next();
436  0 columnSize = token.getStr();
437  0 next();
438  0 if (token.getStr().equals(","))
439    {
440  0 next();
441  0 columnPrecision = token.getStr();
442  0 next();
443    }
444   
445  0 if (!token.getStr().equals(")"))
446    {
447  0 err(") expected");
448    }
449  0 next();
450    }
451   
452  0 Column col = new Column(columnName);
453  0 if (columnPrecision != null)
454    {
455  0 columnSize = columnSize + columnPrecision;
456    }
457  0 col.setTypeFromString(columnType, columnSize);
458  0 tbl.addColumn(col);
459   
460  0 if (inEnum)
461    {
462  0 col.setNotNull(true);
463  0 if (columnDefault != null)
464    {
465  0 col.setDefaultValue(columnDefault);
466    }
467    }
468    else
469    {
470  0 while (!token.getStr().equals(",") && !token.getStr().equals(")"))
471    {
472  0 if (token.getStr().toUpperCase().equals("NOT"))
473    {
474  0 next();
475  0 if (!token.getStr().toUpperCase().equals("NULL"))
476    {
477  0 err("NULL expected after NOT");
478    }
479  0 col.setNotNull(true);
480  0 next();
481    }
482  0 else if (token.getStr().toUpperCase().equals("PRIMARY"))
483    {
484  0 next();
485  0 if (!token.getStr().toUpperCase().equals("KEY"))
486    {
487  0 err("KEY expected after PRIMARY");
488    }
489  0 col.setPrimaryKey(true);
490  0 next();
491    }
492  0 else if (token.getStr().toUpperCase().equals("UNIQUE"))
493    {
494  0 col.setUnique(true);
495  0 next();
496    }
497  0 else if (token.getStr().toUpperCase().equals("NULL"))
498    {
499  0 col.setNotNull(false);
500  0 next();
501    }
502  0 else if (token.getStr().toUpperCase().equals("AUTO_INCREMENT"))
503    {
504  0 col.setAutoIncrement(true);
505  0 next();
506    }
507  0 else if (token.getStr().toUpperCase().equals("DEFAULT"))
508    {
509  0 next();
510  0 if (token.getStr().equals("'"))
511    {
512  0 next();
513    }
514  0 col.setDefaultValue(token.getStr());
515  0 next();
516  0 if (token.getStr().equals("'"))
517    {
518  0 next();
519    }
520    }
521    else
522    {
523  0 StringBuffer line = new StringBuffer();
524  0 for (Iterator tokenIt = tokens.iterator();
525  0 tokenIt.hasNext();)
526    {
527  0 line.append(tokenIt.next());
528  0 if (tokenIt.hasNext())
529    {
530  0 line.append(" ");
531    }
532    }
533  0 throw new ParseException("Error parsing line "
534    + line + " : Unknown token Nr. "
535    + count
536    + " : "
537    + token);
538    }
539    }
540  0 next(); // eat the ,
541    }
542    }
543   
544    /**
545    * Execute the parser.
546    *
547    * @throws IOException If an I/O error occurs
548    * @throws ParseException error parsing the input file
549    */
 
550  0 toggle public Database execute() throws IOException, ParseException
551    {
552  0 count = 0;
553  0 appDataDB = new Database(databaseType);
554   
555  0 FileReader fr = new FileReader(sqlFile);
556  0 BufferedReader br = new BufferedReader(fr);
557  0 SQLScanner scanner = new SQLScanner(br);
558   
559  0 tokens = scanner.scan();
560   
561  0 br.close();
562   
563  0 while (hasTokens())
564    {
565  0 if (token == null)
566    {
567  0 next();
568    }
569   
570  0 if (token.getStr().toUpperCase().equals("CREATE"))
571    {
572  0 create();
573    }
574  0 if (hasTokens())
575    {
576  0 next();
577    }
578    }
579  0 return appDataDB;
580    }
581    }