Coverage report

  %line %branch
org.apache.torque.engine.database.transform.SQLToAppData
41% 
76% 

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

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