Coverage report

  %line %branch
org.apache.torque.task.TorqueSQLExec$Transaction
0% 
0% 

 1  
 package org.apache.torque.task;
 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.BufferedOutputStream;
 20  
 import java.io.BufferedReader;
 21  
 import java.io.IOException;
 22  
 import java.io.InputStreamReader;
 23  
 import java.io.File;
 24  
 import java.io.FileInputStream;
 25  
 import java.io.FileOutputStream;
 26  
 import java.io.FileReader;
 27  
 import java.io.PrintStream;
 28  
 import java.io.StringReader;
 29  
 import java.io.Reader;
 30  
 import java.util.List;
 31  
 import java.util.ArrayList;
 32  
 import java.util.Iterator;
 33  
 import java.util.HashMap;
 34  
 import java.util.Map;
 35  
 import java.util.Properties;
 36  
 import java.sql.Connection;
 37  
 import java.sql.DatabaseMetaData;
 38  
 import java.sql.Driver;
 39  
 import java.sql.ResultSet;
 40  
 import java.sql.ResultSetMetaData;
 41  
 import java.sql.SQLException;
 42  
 import java.sql.SQLWarning;
 43  
 import java.sql.Statement;
 44  
 import org.apache.commons.lang.StringUtils;
 45  
 import org.apache.tools.ant.AntClassLoader;
 46  
 import org.apache.tools.ant.BuildException;
 47  
 import org.apache.tools.ant.Project;
 48  
 import org.apache.tools.ant.ProjectHelper;
 49  
 import org.apache.tools.ant.Task;
 50  
 import org.apache.tools.ant.types.EnumeratedAttribute;
 51  
 import org.apache.tools.ant.types.Path;
 52  
 import org.apache.tools.ant.types.Reference;
 53  
 
 54  
 /**
 55  
  * This task uses an SQL -> Database map in the form of a properties
 56  
  * file to insert each SQL file listed into its designated database.
 57  
  *
 58  
  * @author <a href="mailto:jeff@custommonkey.org">Jeff Martin</a>
 59  
  * @author <a href="mailto:gholam@xtra.co.nz">Michael McCallum</A>
 60  
  * @author <a href="mailto:tim.stephenson@sybase.com">Tim Stephenson</A>
 61  
  * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</A>
 62  
  * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a>
 63  
  * @version $Id: TorqueSQLExec.java 239624 2005-08-24 12:18:03Z henning $
 64  
  */
 65  
 public class TorqueSQLExec extends Task
 66  
 {
 67  
     private int goodSql = 0;
 68  
     private int totalSql = 0;
 69  
     private Path classpath;
 70  
     private AntClassLoader loader;
 71  
 
 72  
     /**
 73  
      *
 74  
      */
 75  
     public static class DelimiterType extends EnumeratedAttribute
 76  
     {
 77  
         public static final String NORMAL = "normal";
 78  
         public static final String ROW = "row";
 79  
 
 80  
         public String[] getValues()
 81  
         {
 82  
             return new String[] {NORMAL, ROW};
 83  
         }
 84  
     }
 85  
 
 86  
     /** Database connection */
 87  
     private Connection conn = null;
 88  
 
 89  
     /** Autocommit flag. Default value is false */
 90  
     private boolean autocommit = false;
 91  
 
 92  
     /** SQL statement */
 93  
     private Statement statement = null;
 94  
 
 95  
     /** DB driver. */
 96  
     private String driver = null;
 97  
 
 98  
     /** DB url. */
 99  
     private String url = null;
 100  
 
 101  
     /** User name. */
 102  
     private String userId = null;
 103  
 
 104  
     /** Password */
 105  
     private String password = null;
 106  
 
 107  
     /** SQL input command */
 108  
     private String sqlCommand = "";
 109  
 
 110  
     /** SQL Statement delimiter */
 111  
     private String delimiter = ";";
 112  
 
 113  
     /**
 114  
      * The delimiter type indicating whether the delimiter will
 115  
      * only be recognized on a line by itself
 116  
      */
 117  
     private String delimiterType = DelimiterType.NORMAL;
 118  
 
 119  
     /** Print SQL results. */
 120  
     private boolean print = false;
 121  
 
 122  
     /** Print header columns. */
 123  
     private boolean showheaders = true;
 124  
 
 125  
     /** Results Output file. */
 126  
     private File output = null;
 127  
 
 128  
     /** RDBMS Product needed for this SQL. */
 129  
     private String rdbms = null;
 130  
 
 131  
     /** RDBMS Version needed for this SQL. */
 132  
     private String version = null;
 133  
 
 134  
     /** Action to perform if an error is found */
 135  
     private String onError = "abort";
 136  
 
 137  
     /** Encoding to use when reading SQL statements from a file */
 138  
     private String encoding = null;
 139  
 
 140  
     /** Src directory for the files listed in the sqldbmap. */
 141  
     private String srcDir;
 142  
 
 143  
     /** Properties file that maps an individual SQL file to a database. */
 144  
     private File sqldbmap;
 145  
 
 146  
     /**
 147  
      * Set the sqldbmap properties file.
 148  
      *
 149  
      * @param sqldbmap filename for the sqldbmap
 150  
      */
 151  
     public void setSqlDbMap(String sqldbmap)
 152  
     {
 153  
         this.sqldbmap = project.resolveFile(sqldbmap);
 154  
     }
 155  
 
 156  
     /**
 157  
      * Get the sqldbmap properties file.
 158  
      *
 159  
      * @return filename for the sqldbmap
 160  
      */
 161  
     public File getSqlDbMap()
 162  
     {
 163  
         return sqldbmap;
 164  
     }
 165  
 
 166  
     /**
 167  
      * Set the src directory for the sql files listed in the sqldbmap file.
 168  
      *
 169  
      * @param srcDir sql source directory
 170  
      */
 171  
     public void setSrcDir(String srcDir)
 172  
     {
 173  
         this.srcDir = project.resolveFile(srcDir).toString();
 174  
     }
 175  
 
 176  
     /**
 177  
      * Get the src directory for the sql files listed in the sqldbmap file.
 178  
      *
 179  
      * @return sql source directory
 180  
      */
 181  
     public String getSrcDir()
 182  
     {
 183  
         return srcDir;
 184  
     }
 185  
 
 186  
     /**
 187  
      * Set the classpath for loading the driver.
 188  
      *
 189  
      * @param classpath the classpath
 190  
      */
 191  
     public void setClasspath(Path classpath)
 192  
     {
 193  
         if (this.classpath == null)
 194  
         {
 195  
             this.classpath = classpath;
 196  
         }
 197  
         else
 198  
         {
 199  
             this.classpath.append(classpath);
 200  
         }
 201  
     }
 202  
 
 203  
     /**
 204  
      * Create the classpath for loading the driver.
 205  
      *
 206  
      * @return the classpath
 207  
      */
 208  
     public Path createClasspath()
 209  
     {
 210  
         if (this.classpath == null)
 211  
         {
 212  
             this.classpath = new Path(project);
 213  
         }
 214  
         return this.classpath.createPath();
 215  
     }
 216  
 
 217  
     /**
 218  
      * Set the classpath for loading the driver using the classpath reference.
 219  
      *
 220  
      * @param r reference to the classpath
 221  
      */
 222  
     public void setClasspathRef(Reference r)
 223  
     {
 224  
         createClasspath().setRefid(r);
 225  
     }
 226  
 
 227  
     /**
 228  
      * Set the sql command to execute
 229  
      *
 230  
      * @param sql sql command to execute
 231  
      */
 232  
     public void addText(String sql)
 233  
     {
 234  
         this.sqlCommand += sql;
 235  
     }
 236  
 
 237  
     /**
 238  
      * Set the JDBC driver to be used.
 239  
      *
 240  
      * @param driver driver class name
 241  
      */
 242  
     public void setDriver(String driver)
 243  
     {
 244  
         this.driver = driver;
 245  
     }
 246  
 
 247  
     /**
 248  
      * Set the DB connection url.
 249  
      *
 250  
      * @param url connection url
 251  
      */
 252  
     public void setUrl(String url)
 253  
     {
 254  
         this.url = url;
 255  
     }
 256  
 
 257  
     /**
 258  
      * Set the user name for the DB connection.
 259  
      *
 260  
      * @param userId database user
 261  
      */
 262  
     public void setUserid(String userId)
 263  
     {
 264  
         this.userId = userId;
 265  
     }
 266  
 
 267  
     /**
 268  
      * Set the file encoding to use on the sql files read in
 269  
      *
 270  
      * @param encoding the encoding to use on the files
 271  
      */
 272  
     public void setEncoding(String encoding)
 273  
     {
 274  
         this.encoding = encoding;
 275  
     }
 276  
 
 277  
     /**
 278  
      * Set the password for the DB connection.
 279  
      *
 280  
      * @param password database password
 281  
      */
 282  
     public void setPassword(String password)
 283  
     {
 284  
         this.password = password;
 285  
     }
 286  
 
 287  
     /**
 288  
      * Set the autocommit flag for the DB connection.
 289  
      *
 290  
      * @param autocommit the autocommit flag
 291  
      */
 292  
     public void setAutocommit(boolean autocommit)
 293  
     {
 294  
         this.autocommit = autocommit;
 295  
     }
 296  
 
 297  
     /**
 298  
      * Set the statement delimiter.
 299  
      *
 300  
      * <p>For example, set this to "go" and delimitertype to "ROW" for
 301  
      * Sybase ASE or MS SQL Server.</p>
 302  
      *
 303  
      * @param delimiter
 304  
      */
 305  
     public void setDelimiter(String delimiter)
 306  
     {
 307  
         this.delimiter = delimiter;
 308  
     }
 309  
 
 310  
     /**
 311  
      * Set the Delimiter type for this sql task. The delimiter type takes two
 312  
      * values - normal and row. Normal means that any occurence of the delimiter
 313  
      * terminate the SQL command whereas with row, only a line containing just
 314  
      * the delimiter is recognized as the end of the command.
 315  
      *
 316  
      * @param delimiterType
 317  
      */
 318  
     public void setDelimiterType(DelimiterType delimiterType)
 319  
     {
 320  
         this.delimiterType = delimiterType.getValue();
 321  
     }
 322  
 
 323  
     /**
 324  
      * Set the print flag.
 325  
      *
 326  
      * @param print
 327  
      */
 328  
     public void setPrint(boolean print)
 329  
     {
 330  
         this.print = print;
 331  
     }
 332  
 
 333  
     /**
 334  
      * Set the showheaders flag.
 335  
      *
 336  
      * @param showheaders
 337  
      */
 338  
     public void setShowheaders(boolean showheaders)
 339  
     {
 340  
         this.showheaders = showheaders;
 341  
     }
 342  
 
 343  
     /**
 344  
      * Set the output file.
 345  
      *
 346  
      * @param output
 347  
      */
 348  
     public void setOutput(File output)
 349  
     {
 350  
         this.output = output;
 351  
     }
 352  
 
 353  
     /**
 354  
      * Set the rdbms required
 355  
      *
 356  
      * @param vendor
 357  
      */
 358  
     public void setRdbms(String vendor)
 359  
     {
 360  
         this.rdbms = vendor.toLowerCase();
 361  
     }
 362  
 
 363  
     /**
 364  
      * Set the version required
 365  
      *
 366  
      * @param version
 367  
      */
 368  
     public void setVersion(String version)
 369  
     {
 370  
         this.version = version.toLowerCase();
 371  
     }
 372  
 
 373  
     /**
 374  
      * Set the action to perform onerror
 375  
      *
 376  
      * @param action
 377  
      */
 378  
     public void setOnerror(OnError action)
 379  
     {
 380  
         this.onError = action.getValue();
 381  
     }
 382  
 
 383  
     /**
 384  
      * Load the sql file and then execute it
 385  
      *
 386  
      * @throws BuildException
 387  
      */
 388  
     public void execute() throws BuildException
 389  
     {
 390  
         sqlCommand = sqlCommand.trim();
 391  
 
 392  
         if (sqldbmap == null || getSqlDbMap().exists() == false)
 393  
         {
 394  
             throw new BuildException("You haven't provided an sqldbmap, or "
 395  
                     + "the one you specified doesn't exist: " + sqldbmap);
 396  
         }
 397  
 
 398  
         if (driver == null)
 399  
         {
 400  
             throw new BuildException("Driver attribute must be set!", location);
 401  
         }
 402  
         if (userId == null)
 403  
         {
 404  
             throw new BuildException("User Id attribute must be set!",
 405  
                     location);
 406  
         }
 407  
         if (password == null)
 408  
         {
 409  
             throw new BuildException("Password attribute must be set!",
 410  
                     location);
 411  
         }
 412  
         if (url == null)
 413  
         {
 414  
             throw new BuildException("Url attribute must be set!", location);
 415  
         }
 416  
 
 417  
         Properties map = new Properties();
 418  
 
 419  
         try
 420  
         {
 421  
             FileInputStream fis = new FileInputStream(getSqlDbMap());
 422  
             map.load(fis);
 423  
             fis.close();
 424  
         }
 425  
         catch (IOException ioe)
 426  
         {
 427  
             throw new BuildException("Cannot open and process the sqldbmap!");
 428  
         }
 429  
 
 430  
         Map databases = new HashMap();
 431  
 
 432  
         Iterator eachFileName = map.keySet().iterator();
 433  
         while (eachFileName.hasNext())
 434  
         {
 435  
             String sqlfile = (String) eachFileName.next();
 436  
             String database = map.getProperty(sqlfile);
 437  
 
 438  
             List files = (List) databases.get(database);
 439  
 
 440  
             if (files == null)
 441  
             {
 442  
                 files = new ArrayList();
 443  
                 databases.put(database, files);
 444  
             }
 445  
 
 446  
             // We want to make sure that the base schemas
 447  
             // are inserted first.
 448  
             if (sqlfile.indexOf("schema.sql") != -1)
 449  
             {
 450  
                 files.add(0, sqlfile);
 451  
             }
 452  
             else
 453  
             {
 454  
                 files.add(sqlfile);
 455  
             }
 456  
         }
 457  
 
 458  
         Iterator eachDatabase = databases.keySet().iterator();
 459  
         while (eachDatabase.hasNext())
 460  
         {
 461  
             String db = (String) eachDatabase.next();
 462  
             List transactions = new ArrayList();
 463  
             eachFileName = ((List) databases.get(db)).iterator();
 464  
             while (eachFileName.hasNext())
 465  
             {
 466  
                 String fileName = (String) eachFileName.next();
 467  
                 File file = new File(srcDir, fileName);
 468  
 
 469  
                 if (file.exists())
 470  
                 {
 471  
                     Transaction transaction = new Transaction();
 472  
                     transaction.setSrc(file);
 473  
                     transactions.add(transaction);
 474  
                 }
 475  
                 else
 476  
                 {
 477  
                     super.log("File '" + fileName
 478  
                             + "' in sqldbmap does not exist, so skipping it.");
 479  
                 }
 480  
             }
 481  
 
 482  
             insertDatabaseSqlFiles(url, db, transactions);
 483  
         }
 484  
     }
 485  
 
 486  
     /**
 487  
      * Take the base url, the target database and insert a set of SQL
 488  
      * files into the target database.
 489  
      *
 490  
      * @param url
 491  
      * @param database
 492  
      * @param transactions
 493  
      */
 494  
     private void insertDatabaseSqlFiles(String url, String database,
 495  
             List transactions)
 496  
     {
 497  
         url = StringUtils.replace(url, "@DB@", database);
 498  
         System.out.println("Our new url -> " + url);
 499  
 
 500  
         Driver driverInstance = null;
 501  
         try
 502  
         {
 503  
             Class dc;
 504  
             if (classpath != null)
 505  
             {
 506  
                 log("Loading " + driver
 507  
                         + " using AntClassLoader with classpath " + classpath,
 508  
                         Project.MSG_VERBOSE);
 509  
 
 510  
                 loader = new AntClassLoader(project, classpath);
 511  
                 dc = loader.loadClass(driver);
 512  
             }
 513  
             else
 514  
             {
 515  
                 log("Loading " + driver + " using system loader.",
 516  
                         Project.MSG_VERBOSE);
 517  
                 dc = Class.forName(driver);
 518  
             }
 519  
             driverInstance = (Driver) dc.newInstance();
 520  
         }
 521  
         catch (ClassNotFoundException e)
 522  
         {
 523  
             throw new BuildException("Class Not Found: JDBC driver " + driver
 524  
                     + " could not be loaded", location);
 525  
         }
 526  
         catch (IllegalAccessException e)
 527  
         {
 528  
             throw new BuildException("Illegal Access: JDBC driver " + driver
 529  
                     + " could not be loaded", location);
 530  
         }
 531  
         catch (InstantiationException e)
 532  
         {
 533  
             throw new BuildException("Instantiation Exception: JDBC driver "
 534  
                     + driver + " could not be loaded", location);
 535  
         }
 536  
 
 537  
         try
 538  
         {
 539  
             log("connecting to " + url, Project.MSG_VERBOSE);
 540  
             Properties info = new Properties();
 541  
             info.put("user", userId);
 542  
             info.put("password", password);
 543  
             conn = driverInstance.connect(url, info);
 544  
 
 545  
             if (conn == null)
 546  
             {
 547  
                 // Driver doesn't understand the URL
 548  
                 throw new SQLException("No suitable Driver for " + url);
 549  
             }
 550  
 
 551  
             if (!isValidRdbms(conn))
 552  
             {
 553  
                 return;
 554  
             }
 555  
 
 556  
             conn.setAutoCommit(autocommit);
 557  
             statement = conn.createStatement();
 558  
             PrintStream out = System.out;
 559  
             try
 560  
             {
 561  
                 if (output != null)
 562  
                 {
 563  
                     log("Opening PrintStream to output file " + output,
 564  
                             Project.MSG_VERBOSE);
 565  
                     out = new PrintStream(class="keyword">new BufferedOutputStream(
 566  
                             new FileOutputStream(output)));
 567  
                 }
 568  
 
 569  
                 // Process all transactions
 570  
                 for (Iterator it = transactions.iterator(); it.hasNext();)
 571  
                 {
 572  
                     ((Transaction) it.next()).runTransaction(out);
 573  
                     if (!autocommit)
 574  
                     {
 575  
                         log("Commiting transaction", Project.MSG_VERBOSE);
 576  
                         conn.commit();
 577  
                     }
 578  
                 }
 579  
             }
 580  
             finally
 581  
             {
 582  
                 if (out != null && out != System.out)
 583  
                 {
 584  
                     out.close();
 585  
                 }
 586  
             }
 587  
         }
 588  
         catch (IOException e)
 589  
         {
 590  
             if (!autocommit && conn != null && onError.equals("abort"))
 591  
             {
 592  
                 try
 593  
                 {
 594  
                     conn.rollback();
 595  
                 }
 596  
                 catch (SQLException ex)
 597  
                 {
 598  
                     // do nothing.
 599  
                 }
 600  
             }
 601  
             throw new BuildException(e, location);
 602  
         }
 603  
         catch (SQLException e)
 604  
         {
 605  
             if (!autocommit && conn != null && onError.equals("abort"))
 606  
             {
 607  
                 try
 608  
                 {
 609  
                     conn.rollback();
 610  
                 }
 611  
                 catch (SQLException ex)
 612  
                 {
 613  
                     // do nothing.
 614  
                 }
 615  
             }
 616  
             throw new BuildException(e, location);
 617  
         }
 618  
         finally
 619  
         {
 620  
             try
 621  
             {
 622  
                 if (statement != null)
 623  
                 {
 624  
                     statement.close();
 625  
                 }
 626  
                 if (conn != null)
 627  
                 {
 628  
                     conn.close();
 629  
                 }
 630  
             }
 631  
             catch (SQLException e)
 632  
             {
 633  
             }
 634  
         }
 635  
 
 636  
         log(goodSql + " of " + totalSql
 637  
                 + " SQL statements executed successfully");
 638  
     }
 639  
 
 640  
     /**
 641  
      * Read the statements from the .sql file and execute them.
 642  
      * Lines starting with '//', '--' or 'REM ' are ignored.
 643  
      *
 644  
      * @param reader
 645  
      * @param out
 646  
      * @throws SQLException
 647  
      * @throws IOException
 648  
      */
 649  
     protected void runStatements(Reader reader, PrintStream out)
 650  
             throws SQLException, IOException
 651  
     {
 652  
         String sql = "";
 653  
         String line = "";
 654  
 
 655  
         BufferedReader in = new BufferedReader(reader);
 656  
 
 657  
         try
 658  
         {
 659  
             while ((line = in.readLine()) != null)
 660  
             {
 661  
                 line = line.trim();
 662  
                 line = ProjectHelper.replaceProperties(project, line,
 663  
                         project.getProperties());
 664  
                 if (line.startsWith("//") || line.startsWith("--"))
 665  
                 {
 666  
                     continue;
 667  
                 }
 668  
                 if (line.length() > 4
 669  
                         && line.substring(0, 4).equalsIgnoreCase("REM "))
 670  
                 {
 671  
                     continue;
 672  
                 }
 673  
 
 674  
                 sql += " " + line;
 675  
                 sql = sql.trim();
 676  
 
 677  
                 // SQL defines "--" as a comment to EOL
 678  
                 // and in Oracle it may contain a hint
 679  
                 // so we cannot just remove it, instead we must end it
 680  
                 if (line.indexOf("--") >= 0)
 681  
                 {
 682  
                     sql += "\n";
 683  
                 }
 684  
 
 685  
                 if (delimiterType.equals(DelimiterType.NORMAL)
 686  
                         && sql.endsWith(delimiter)
 687  
                         || delimiterType.equals(DelimiterType.ROW)
 688  
                         && line.equals(delimiter))
 689  
                 {
 690  
                     log("SQL: " + sql, Project.MSG_VERBOSE);
 691  
                     execSQL(sql.substring(0, sql.length() - delimiter.length()),
 692  
                             out);
 693  
                     sql = "";
 694  
                 }
 695  
             }
 696  
 
 697  
             // Catch any statements not followed by ;
 698  
             if (!sql.equals(""))
 699  
             {
 700  
                 execSQL(sql, out);
 701  
             }
 702  
         }
 703  
         catch (SQLException e)
 704  
         {
 705  
             throw e;
 706  
         }
 707  
     }
 708  
 
 709  
     /**
 710  
      * Verify if connected to the correct RDBMS
 711  
      *
 712  
      * @param conn
 713  
      */
 714  
     protected boolean isValidRdbms(Connection conn)
 715  
     {
 716  
         if (rdbms == null && version == class="keyword">null)
 717  
         {
 718  
             return true;
 719  
         }
 720  
 
 721  
         try
 722  
         {
 723  
             DatabaseMetaData dmd = conn.getMetaData();
 724  
 
 725  
             if (rdbms != null)
 726  
             {
 727  
                 String theVendor = dmd.getDatabaseProductName().toLowerCase();
 728  
 
 729  
                 log("RDBMS = " + theVendor, Project.MSG_VERBOSE);
 730  
                 if (theVendor == null || theVendor.indexOf(rdbms) < 0)
 731  
                 {
 732  
                     log("Not the required RDBMS: "
 733  
                             + rdbms, Project.MSG_VERBOSE);
 734  
                     return false;
 735  
                 }
 736  
             }
 737  
 
 738  
             if (version != null)
 739  
             {
 740  
                 String theVersion = dmd.getDatabaseProductVersion()
 741  
                         .toLowerCase();
 742  
 
 743  
                 log("Version = " + theVersion, Project.MSG_VERBOSE);
 744  
                 if (theVersion == null || !(theVersion.startsWith(version)
 745  
                         || theVersion.indexOf(" " + version) >= 0))
 746  
                 {
 747  
                     log("Not the required version: \"" + version + "\"",
 748  
                             Project.MSG_VERBOSE);
 749  
                     return false;
 750  
                 }
 751  
             }
 752  
         }
 753  
         catch (SQLException e)
 754  
         {
 755  
             // Could not get the required information
 756  
             log("Failed to obtain required RDBMS information", Project.MSG_ERR);
 757  
             return false;
 758  
         }
 759  
 
 760  
         return true;
 761  
     }
 762  
 
 763  
     /**
 764  
      * Exec the sql statement.
 765  
      *
 766  
      * @param sql
 767  
      * @param out
 768  
      * @throws SQLException
 769  
      */
 770  
     protected void execSQL(String sql, PrintStream out) throws SQLException
 771  
     {
 772  
         // Check and ignore empty statements
 773  
         if ("".equals(sql.trim()))
 774  
         {
 775  
             return;
 776  
         }
 777  
 
 778  
         try
 779  
         {
 780  
             totalSql++;
 781  
             if (!statement.execute(sql))
 782  
             {
 783  
                 log(statement.getUpdateCount() + " rows affected",
 784  
                         Project.MSG_VERBOSE);
 785  
             }
 786  
             else
 787  
             {
 788  
                 if (print)
 789  
                 {
 790  
                     printResults(out);
 791  
                 }
 792  
             }
 793  
 
 794  
             SQLWarning warning = conn.getWarnings();
 795  
             while (warning != null)
 796  
             {
 797  
                 log(warning + " sql warning", Project.MSG_VERBOSE);
 798  
                 warning = warning.getNextWarning();
 799  
             }
 800  
             conn.clearWarnings();
 801  
             goodSql++;
 802  
         }
 803  
         catch (SQLException e)
 804  
         {
 805  
             log("Failed to execute: " + sql, Project.MSG_ERR);
 806  
             if (!onError.equals("continue"))
 807  
             {
 808  
                 throw e;
 809  
             }
 810  
             log(e.toString(), Project.MSG_ERR);
 811  
         }
 812  
     }
 813  
 
 814  
     /**
 815  
      * print any results in the statement.
 816  
      *
 817  
      * @param out
 818  
      * @throws SQLException
 819  
      */
 820  
     protected void printResults(PrintStream out) throws java.sql.SQLException
 821  
     {
 822  
         ResultSet rs = null;
 823  
         do
 824  
         {
 825  
             rs = statement.getResultSet();
 826  
             if (rs != null)
 827  
             {
 828  
                 log("Processing new result set.", Project.MSG_VERBOSE);
 829  
                 ResultSetMetaData md = rs.getMetaData();
 830  
                 int columnCount = md.getColumnCount();
 831  
                 StringBuffer line = new StringBuffer();
 832  
                 if (showheaders)
 833  
                 {
 834  
                     for (int col = 1; col < columnCount; col++)
 835  
                     {
 836  
                          line.append(md.getColumnName(col));
 837  
                          line.append(",");
 838  
                     }
 839  
                     line.append(md.getColumnName(columnCount));
 840  
                     out.println(line);
 841  
                     line.setLength(0);
 842  
                 }
 843  
                 while (rs.next())
 844  
                 {
 845  
                     boolean first = true;
 846  
                     for (int col = 1; col <= columnCount; col++)
 847  
                     {
 848  
                         String columnValue = rs.getString(col);
 849  
                         if (columnValue != null)
 850  
                         {
 851  
                             columnValue = columnValue.trim();
 852  
                         }
 853  
 
 854  
                         if (first)
 855  
                         {
 856  
                             first = false;
 857  
                         }
 858  
                         else
 859  
                         {
 860  
                             line.append(",");
 861  
                         }
 862  
                         line.append(columnValue);
 863  
                     }
 864  
                     out.println(line);
 865  
                     line.setLength(0);
 866  
                 }
 867  
             }
 868  
         }
 869  
         while (statement.getMoreResults());
 870  
         out.println();
 871  
     }
 872  
 
 873  
     /**
 874  
      * Enumerated attribute with the values "continue", "stop" and "abort"
 875  
      * for the onerror attribute.
 876  
      */
 877  
     public static class OnError extends EnumeratedAttribute
 878  
     {
 879  
         public String[] getValues()
 880  
         {
 881  
             return new String[] {"continue", "stop", "abort"};
 882  
         }
 883  
     }
 884  
 
 885  
     /**
 886  
      * Contains the definition of a new transaction element.
 887  
      * Transactions allow several files or blocks of statements
 888  
      * to be executed using the same JDBC connection and commit
 889  
      * operation in between.
 890  
      */
 891  0
     public class Transaction
 892  
     {
 893  0
         private File tSrcFile = null;
 894  0
         private String tSqlCommand = "";
 895  
 
 896  
         public void setSrc(File src)
 897  
         {
 898  0
             this.tSrcFile = src;
 899  0
         }
 900  
 
 901  
         public void addText(String sql)
 902  
         {
 903  0
             this.tSqlCommand += sql;
 904  0
         }
 905  
 
 906  
         private void runTransaction(PrintStream out)
 907  
             throws IOException, SQLException
 908  
         {
 909  0
             if (tSqlCommand.length() != 0)
 910  
             {
 911  0
                 log("Executing commands", Project.MSG_INFO);
 912  0
                 runStatements(new StringReader(tSqlCommand), out);
 913  
             }
 914  
 
 915  0
             if (tSrcFile != null)
 916  
             {
 917  0
                 log("Executing file: " + tSrcFile.getAbsolutePath(),
 918  
                     Project.MSG_INFO);
 919  0
                 Reader reader = (encoding == null) ? new FileReader(tSrcFile)
 920  
                         : new InputStreamReader(class="keyword">new FileInputStream(tSrcFile),
 921  
                         encoding);
 922  0
                 runStatements(reader, out);
 923  0
                 reader.close();
 924  
             }
 925  0
         }
 926  
     }
 927  
 }

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