FileDocCategorySizeDatePackage
ExecuteSQL.javaAPI DocExample7883Sat Jun 02 02:40:58 BST 2001None

ExecuteSQL.java

// This example is from _Java Examples in a Nutshell_. (http://www.oreilly.com)
// Copyright (c) 1997 by David Flanagan
// This example is provided WITHOUT ANY WARRANTY either expressed or implied.
// You may study, use, modify, and distribute it for non-commercial purposes.
// For any commercial use, see http://www.davidflanagan.com/javaexamples

import java.sql.*;
import java.io.*;

/**
 * A general-purpose SQL interpreter program.
 **/
public class ExecuteSQL {
  public static void main(String[] args) {
    Connection conn = null;  // Our JDBC connection to the database server
    try {
      String driver = null, url = null, user = "", password = "";

      // Parse all the command-line arguments
      for(int n = 0; n < args.length; n++) {
        if (args[n].equals("-d")) driver = args[++n];
        else if (args[n].equals("-u")) user = args[++n];
        else if (args[n].equals("-p")) password = args[++n];
        else if (url == null) url = args[n];
        else throw new IllegalArgumentException("Unknown argument.");
      }

      // The only required argument is the database URL.
      if (url == null) 
        throw new IllegalArgumentException("No database specified");

      // If the user specified the classname for the DB driver, load
      // that class dynamically.  This gives the driver the opportunity
      // to register itself with the DriverManager.
      if (driver != null) Class.forName(driver);

      // Now open a connection the specified database, using the user-specified
      // username and password, if any.  The driver manager will try all of
      // the DB drivers it knows about to try to parse the URL and connect to
      // the DB server.
      conn = DriverManager.getConnection(url, user, password);

      // Now create the statement object we'll use to talk to the DB
      Statement s = conn.createStatement();

      // Get a stream to read from the console
      BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

      // Loop forever, reading the user's queries and executing them
      while(true) {
        System.out.print("sql> ");   // prompt the user
        System.out.flush();          // make the prompt appear immediately
        String sql = in.readLine();  // get a line of input from the user

        // Quit when the user types "quit".
        if ((sql == null) || sql.equals("quit")) break;

        // Ignore blank lines
        if (sql.length() == 0) continue;
        
        // Now, attempt to execute the user's line of SQL and display results.
        try {
          // We don't know if this is a query or some kind of update, so we
          // use execute() instead of executeQuery() or executeUpdate()
          // If the return value is true, it was a query, else an update
          boolean status = s.execute(sql);
        
          // Loop until there are no more results to return
          do {
            if (status) { // statement was a query that returns a ResultSet
              // Get the set of results and display them
              ResultSet rs = s.getResultSet();
              printResultsTable(rs, System.out);
            }
            else {
              // If the SQL command that was executed was some kind of update
              // rather than a query, then it doesn't return a ResultSet.
              // Instead, we just print the number of rows that were affected.
              int numUpdates = s.getUpdateCount();
              System.out.println("Ok. " + numUpdates + " rows affected.");
            }

            // Now go see if there are even more results, and
            // continue the results display loop if there are.
            status = s.getMoreResults();
          // With some buggy JDBC drivers, this condition causes an infinite
          // loop with SQL updates. If that happens, change to: while(status); 
          } while(status || s.getUpdateCount() != -1);
        }
        // If a SQLException is thrown, display an error message.  Note that
        // SQLExceptions can have a general message and a DB-specific message
        // returned by getSQLState()
        catch (SQLException e) {
          System.err.println("SQLException: " + e.getMessage() + ":" +
                             e.getSQLState());
        }
        // Each time through this loop, check to see if any warnings were
        // issued.  Note that there can be a whole chain of warnings.
        finally { // print out any warnings that occurred
          for(SQLWarning w=conn.getWarnings(); w != null; w=w.getNextWarning())
            System.err.println("WARNING: " + w.getMessage() + 
                               ":" + w.getSQLState());
        }
      }
    }
    // Handle exceptions that occur during argument parsing, database
    // connection setup, etc.  For SQLExceptions, print the details.
    catch (Exception e) {
      System.err.println(e);
      if (e instanceof SQLException)
        System.err.println("SQL State: " + ((SQLException)e).getSQLState());
      System.err.println("Usage: java ExecuteSQL [-d <driver>] [-u <user>] " +
                         "[-p <password>] <database URL>");
    }
    // Be sure to always close the database connection when we exit, whether
    // we exit because the user types 'quit' or because of an exception thrown
    // while setting things up.  Closing this connection also implicitly
    // closes any open statements and result sets associated with it.
    finally {
      try { conn.close(); } catch (Exception e) {}
    }
  }

  /**
   * This method attempts to output the contents of a ResultSet in a 
   * textual table.  It relies on the ResultSetMetaData class, but a fair
   * bit of the code is simple string manipulation.
   **/
  static void printResultsTable(ResultSet rs, OutputStream output) 
       throws SQLException {
    // Set up the output stream
    PrintWriter out = new PrintWriter(new OutputStreamWriter(output));

    // Get some "meta data" (column names, etc.) about the results
    ResultSetMetaData metadata = rs.getMetaData();
    
    // Variables to hold important data about the table to be displayed
    int numcols = metadata.getColumnCount();// how many columns
    String[] labels = new String[numcols];  // the column labels
    int[] colwidths = new int[numcols];     // the width of each
    int[] colpos = new int[numcols];        // start position of each
    int linewidth;                          // total width of table
    
    // Figure out how wide the columns are, where each one begins, 
    // how wide each row of the table will be, etc.
    linewidth = 1; // for the initial '|'.
    for(int i = 0; i < numcols; i++) {          // for each column
      colpos[i] = linewidth;                    // save its position
      labels[i] = metadata.getColumnLabel(i+1); // get its label 
      // Get the column width.  If the db doesn't report one, guess
      // 30 characters.  Then check the length of the label, and use
      // it if it is larger than the column width
      int size =  metadata.getColumnDisplaySize(i+1);
      if (size == -1) size = 30;                // some drivers return -1...
      int labelsize = labels[i].length();
      if (labelsize > size) size = labelsize;   
      colwidths[i] = size + 1;                  // save the column the size  
      linewidth += colwidths[i] + 2;            // increment total size
    }
    
    // Create a horizontal divider line we use in the table.
    // Also create a blank line that is the initial value of each 
    // line of the table
    StringBuffer divider = new StringBuffer(linewidth);
    StringBuffer blankline = new StringBuffer(linewidth);
    for(int i = 0; i