Coverage report

  %line %branch
org.apache.torque.engine.database.transform.SQLToAppData
0% 
0% 

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

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.