FileDocCategorySizeDatePackage
SQLRunner.javaAPI DocExample12078Sat May 29 21:56:02 BST 2004None

SQLRunner

public class SQLRunner extends Object implements ResultsDecoratorPrinter
Class to run an SQL script, like psql(1), SQL*Plus, or similar programs. Command line interface accepts options -c config [-f configFile] [scriptFile].

Input language is: escape commands (begin with \ and MUST end with semi-colon), or standard SQL statements which must also end with semi-colon);

Escape sequences:

  • \m (output-mode), takes character t for text, h for html, s for sql, x for xml (not in this version) (the SQL output is intended to be usable to re-insert the data into another identical table, but this has not been extensively tested!).
  • \o output-file, redirects output.
  • \q quit the program
TODO: Fix parsing so escapes don't need to end with SQL semi-colon.

This class can also be used from within programs such as servlets, etc.

TODO: knobs to set debug mode (interactively & from getopt!)

For example, this command and input: SQLrunner -c testdb \ms; select *from person where person_key=4; might produce this output:

Executing : <
author
Ian Darwin, http://www.darwinsys.com/

Fields Summary
public static final String
MODE_TXT
The mode for textual output
public static final String
MODE_HTML
The mode for HTML output
public static final String
MODE_SQL
The mode for SQL output
public static final String
MODE_XML
The mode for XML output
protected Connection
conn
Database connection
protected Statement
stmt
SQL Statement
protected PrintWriter
out
Where the output is going
private ResultsDecorator
currentDecorator
private ResultsDecorator
textDecorator
private ResultsDecorator
sqlDecorator
private ResultsDecorator
htmlDecorator
private ResultsDecorator
xmlDecorator
boolean
debug
Constructors Summary
public SQLRunner(String driver, String dbUrl, String user, String password, String outputFile, String outputMode)
Construct a SQLRunner object

param
driver String for the JDBC driver
param
dbUrl String for the JDBC URL
param
user String for the username
param
password String for the password, normally in cleartext
param
outputMode One of the MODE_XXX constants.
throws
ClassNotFoundException
throws
SQLException

		conn = ConnectionUtil.createConnection(driver, dbUrl, user, password);
		finishSetup(outputFile, outputMode);
	
public SQLRunner(Connection c, String outputFile, String outputMode)

		// set up the SQL input
		conn = c;
		finishSetup(outputFile, outputMode);
	
Methods Summary
public voidclose()

		stmt.close();
		conn.close();
		out.flush();
		out.close();
	
private voiddisplay(java.lang.String rest)
Display - something

param
rest - what to display XXX: Move formatting to ResultsDecorator: listTables(rs), listColumns(rs)

		if (rest.equals("t")) {
			// Display list of tables
			DatabaseMetaData md = conn.getMetaData();
			ResultSet rs = md.getTables(null, null, "%", null);
			while (rs.next()) {
				System.out.println(rs.getString(3));
			}
		} else if (rest.startsWith("t")) {
			// Display one table
			String tableName = rest.substring(1).trim();
			System.out.println("# Display table " + tableName);
			DatabaseMetaData md = conn.getMetaData();
			ResultSet rs = md.getColumns(null, null, tableName, "%");
			while (rs.next()) {
				System.out.println(rs.getString(4));
			}
		} else
			throw new IllegalArgumentException("\\d"  + rest + " invalid");
	
private voiddoEscape(java.lang.String str)
Process an escape like \ms; for mode=sql.

		String rest = null;
		if (str.length() > 2) {
			rest = str.substring(2);
		}
		
		if (str.startsWith("\\d")) {	// Display
			if (rest == null){
				throw new IllegalArgumentException("\\d needs display arg");
			}
			display(rest);
		} else if (str.startsWith("\\m")) {	// MODE
			if (rest == null){
				throw new IllegalArgumentException("\\m needs output mode arg");
			}
			setOutputMode(rest);
		} else if (str.startsWith("\\o")){
			if (rest == null){
				throw new IllegalArgumentException("\\o needs output file arg");
			}
			setOutputFile(rest);
		} else if (str.startsWith("\\q")){
			System.exit(0);
		} else {
			throw new IllegalArgumentException("Unknown escape: " + str);
		}
		
	
private static voiddoHelp(int i)
print help; called from several places in main


	         
	     
		System.out.println(
		"Usage: SQLRunner [-f configFile] [-c config] [SQLscript[ ...]");
		System.exit(i);
	
voidfinishSetup(java.lang.String outputFileName, java.lang.String outputMode)

		DatabaseMetaData dbm = conn.getMetaData();
		String dbName = dbm.getDatabaseProductName();
		System.out.println("SQLRunner: Connected to " + dbName);
		stmt = conn.createStatement();
		
		if (outputFileName == null) {
			out = new PrintWriter(System.out);
		} else {
			out = new PrintWriter(new FileWriter(outputFileName));
		}
		
		setOutputMode(outputMode);
	
public java.io.PrintWritergetPrintWriter()

		return out;
	
public static java.lang.StringgetStatement(java.io.BufferedReader is)
Extract one statement from the given Reader. Ignore comments and null lines.

return
The SQL statement, up to but not including the ';' character. May be null if not statement found.

		String ret="";
		String line;
		boolean found = false;
		while ((line = is.readLine()) != null) {
			if (line == null || line.length() == 0) {
				continue;
			}
			if (!(line.startsWith("#") || line.startsWith("--"))) {
				ret += ' " + line;
				found = true;
			}
			if (line.endsWith(";")) {
				// Kludge, kill off empty statements (";") by itself, continue scanning.
				if (line.length() == 1)
					line = "";
				ret = ret.substring(0, ret.length()-1);
				return ret;
			}
		}
		return null;
	
public booleanisDebug()

return
Returns the debug.

		return debug;
	
public static voidmain(java.lang.String[] args)
main - parse arguments, construct SQLRunner object, open file(s), run scripts.

throws
SQLException if anything goes wrong.
throws
DatabaseException if anything goes wrong.

		String config = "default";
		String outputMode = MODE_TXT;
		String outputFile = null;
		boolean debug = false;
		GetOpt go = new GetOpt("df:c:m:o:");
		char c;
		while ((c = go.getopt(args)) != GetOpt.DONE) {
			switch(c) {
			case 'h":
				doHelp(0);
				break;
			case 'd":
				debug = true;
				break;
			case 'f":
				ConnectionUtil.setConfigFileName(go.optarg());
				break;
			case 'c":
				config = go.optarg();
				break;
			case 'm":
				outputMode = go.optarg();
				break;
			case 'o":
				outputFile = go.optarg();
				break;
			default:
				System.err.println("Unknown option character " + c);
				doHelp(1);
			}
		}

		try {

			Connection conn = ConnectionUtil.getConnection(config);

			SQLRunner prog = new SQLRunner(conn, outputFile, outputMode);
			prog.setDebug(debug);
			
			if (go.getOptInd() == args.length) {
				prog.runScript(new BufferedReader(
					new InputStreamReader(System.in)));
			} else for (int i = go.getOptInd()-1; i < args.length; i++) {
				prog.runScript(args[i]);
			}
			prog.close();
		} catch (SQLException ex) {
			throw new DataBaseException(ex.toString());
		} catch (IOException ex) {
			throw new DataBaseException(ex.toString());
		}
		System.exit(0);
	
public voidprint(java.lang.String line)

		out.print(line);
	
public voidprintln(java.lang.String line)

		out.println(line);
		out.flush();
	
public voidprintln()

		out.println();
		out.flush();
	
public voidrunScript(java.lang.String scriptFile)
Run one script file, by name. Called from cmd line main or from user code.


		BufferedReader is;

		// Load the script file first, it's the most likely error
		is = new BufferedReader(new FileReader(scriptFile));

		runScript(is);
	
public voidrunScript(java.io.BufferedReader is)
Run one script, by name, given a BufferedReader.


		String stmt;
		int i = 0;
		System.out.println("SQLRunner: ready.");
		while ((stmt = getStatement(is)) != null) {
			stmt = stmt.trim();
			if (stmt.startsWith("\\")) {
				doEscape(stmt);
			} else {
				runStatement(stmt);
			}
		}
	
public voidrunStatement(java.lang.String str)
Run one Statement, and format results as per Update or Query. Called from runScript or from user code.

		
		System.out.println("Executing : <<" + str.trim() + ">>");
		System.out.flush();
		try {
			boolean hasResultSet = stmt.execute(str);
			if (!hasResultSet)
				currentDecorator.write(stmt.getUpdateCount());
			else {
				ResultSet rs = stmt.getResultSet();
				currentDecorator.write(rs);
			}
		} catch (SQLException ex) {
			if (debug){
				throw ex;
			} else {
				System.out.println("ERROR: " + ex.toString());
			}
		}
		System.out.println();
	
public voidsetDebug(boolean debug)

param
debug True to enable debug, false to disable.

		this.debug = debug;
	
private voidsetOutputFile(java.lang.String fileName)
Set the output to the given filename.

param
fileName

		File file = new File(fileName);
		out = new PrintWriter(new FileWriter(file), true);
		System.out.println("Output set to " + file.getCanonicalPath());
	
private voidsetOutputFile()
Set the output file back to System.out

		out = new PrintWriter(System.out, true);
	
voidsetOutputMode(java.lang.String outputMode)
Set the output mode.

param
outputMode Must be a value equal to one of the MODE_XXX values.
throws
IllegalArgumentException if the mode is not valid.

		if (outputMode.length() == 0) { throw new IllegalArgumentException(
			"invalid mode: " + outputMode + "; must be t, h or s"); }

		// Assign the correct ResultsDecorator, creating them on the fly
		// using the lazy evaluation pattern.
		ResultsDecorator newDecorator = null;
		switch (outputMode.charAt(0)) {
			case 't":
				if (textDecorator == null) {
					textDecorator = new ResultsDecoratorText(this);
				}
				newDecorator = textDecorator;
				break;
			case 'h":
				if (htmlDecorator == null) {
					htmlDecorator = new ResultsDecoratorHTML(this);
				}
				newDecorator = htmlDecorator;
				break;
			case 's":
				if (sqlDecorator == null) {
					sqlDecorator = new ResultsDecoratorSQL(this);
				}
				newDecorator = sqlDecorator;
				break;
			case 'x":
				if (xmlDecorator == null) {
					xmlDecorator = new ResultsDecoratorXML(this);
				}
				newDecorator = sqlDecorator;
				break;
			default:
				throw new IllegalArgumentException("invalid mode: "
								+ outputMode + "; must be t, h or s");
		}
		if (currentDecorator != newDecorator) {
			currentDecorator = newDecorator;
			System.out.println("Mode set to  "
					+ currentDecorator.getName());
		}