jdbcclient.java

来自「这个是内存数据库的客户端」· Java 代码 · 共 1,234 行 · 第 1/3 页

JAVA
1,234
字号
				}			}			out.println();			out.flush();		} while ((nextRslt = stmt.getMoreResults()) ||				 (aff = stmt.getUpdateCount()) != -1);		// if there were warnings for this statement,		// and/or connection show them!		warn = stmt.getWarnings();		while (warn != null) {			System.err.println("Statement warning: " +				warn.getMessage());			warn = warn.getNextWarning();		}		stmt.clearWarnings();		warn = con.getWarnings();		while (warn != null) {			System.err.println("Connection warning: " +				warn.getMessage());			warn = warn.getNextWarning();		}		con.clearWarnings();	}	/**	 * Starts a processing loop optimized for processing (large) chunks of	 * continous data, such as input from a file.  Unlike in the interactive	 * loop above, queries are sent only to the database if a certain batch	 * amount is reached.  No client side query checks are made, but everything	 * is sent to the server as-is.	 *	 * @param batchSize the number of items to store in the batch before	 *                  sending them to the database for execution.	 * @throws IOException if an IO exception occurs.	 */	public static void processBatch(int batchSize) throws IOException {		StringBuffer query = new StringBuffer();		String curLine;		int i = 0;		try {			// the main loop			for (i = 1; (curLine = in.readLine()) != null; i++) {				query.append(curLine);				if (curLine.endsWith(";")) {					// lousy check for end of statement, but in batch mode it					// is not very important to catch all end of statements...					stmt.addBatch(query.toString());					query.delete(0, query.length());				} else {					query.append('\n');				}				if (batchSize > 0 && i % batchSize == 0) {					stmt.executeBatch();					stmt.clearBatch();				}			}			stmt.addBatch(query.toString());			stmt.executeBatch();			stmt.clearBatch();		} catch (SQLException e) {			System.err.println("Error at line " + i + ": " + e.getMessage());			// print all error messages in the chain (if any)			while ((e = e.getNextException()) != null) {				System.err.println(e.getMessage());			}		}	}	/**	 * Wrapper method that decides to dump SQL or XML.  In the latter case,	 * this method does the XML data generation.	 *	 * @param out a Writer to write the data to	 * @param table the table to dump	 * @param dbmd the DatabaseMetaData to use	 * @param stmt the Statement to use	 * @throws SQLException if a database related error occurs	 */	public static void doDump(		PrintWriter out,		Table table,		DatabaseMetaData dbmd,		Statement stmt)	throws SQLException	{		e.dumpSchema(			dbmd,			table.getType(),			table.getCat(),			table.getSchem(),			table.getName()		);		out.println();		e.dumpResultSet(			stmt.executeQuery("SELECT * FROM " + table.getFqnameQ())		);		out.println();	}	/**	 * Simple helper method that generates a prompt.	 *	 * @param user the username	 * @param stack the current SQLStack	 * @param compl whether the statement is complete	 * @return a prompt which consist of a username plus the top of the stack	 */	private static String getPrompt(String user, SQLStack stack, boolean compl) {		return(user + (compl ? "-" : "=") +			(stack.empty() ? ">" : "" + stack.peek()) + " ");	}	/**	 * Scans the given string and tries to discover if it is a complete query	 * or that there needs something to be added.  If a string doesn't end with	 * a ; it is considered not to be complete.  SQL string quotation using ' and	 * SQL identifier quotation using " is taken into account when scanning a	 * string this way.	 * Additionally, this method removes comments from the SQL statements,	 * identified by -- and removes white space where appropriate.	 *	 * @param query the query to parse	 * @param stack query stack to work with	 * @param scolonterm whether a ';' makes this query part complete	 * @return a QueryPart object containing the results of this parse	 */	private static QueryPart scanQuery(			String query,			SQLStack stack,			boolean scolonterm)	{		// examine string, char for char		boolean wasInString = (stack.peek() == '\'');		boolean wasInIdentifier = (stack.peek() == '"');		boolean escaped = false;		int len = query.length();		for (int i = 0; i < len; i++) {			switch(query.charAt(i)) {				case '\\':					escaped = !escaped;				break;				default:					escaped = false;				break;				case '\'':					/**					 * We can not be in a string if we are in an identifier. So					 * If we find a ' and are not in an identifier, and not in					 * a string we can safely assume we will be now in a string.					 * If we are in a string already, we should stop being in a					 * string if we find a quote which is not prefixed by a \,					 * for that would be an escaped quote. However, a nasty					 * situation can occur where the string is like 'test \\'.					 * As obvious, a test for a \ in front of a ' doesn't hold					 * here. Because 'test \\\'' can exist as well, we need to					 * know if a quote is prefixed by an escaping slash or not.					 */					if (!escaped && stack.peek() != '"') {						if (stack.peek() != '\'') {							// although it makes no sense to escape a quote							// outside a string, it is escaped, thus not meant							// as quote for us, apparently							stack.push('\'');						} else {							stack.pop();						}					}					// reset escaped flag					escaped = false;				break;				case '"':					if (!escaped && stack.peek() != '\'') {						if (stack.peek() != '"') {							stack.push('"');						} else {							stack.pop();						}					}					// reset escaped flag					escaped = false;				break;				case '-':					if (!escaped && stack.peek() != '\'' && stack.peek() != '"' && i + 1 < len && query.charAt(i + 1) == '-') {						len = i;					}					escaped = false;				break;				case '(':					if (!escaped && stack.peek() != '\'' && stack.peek() != '"') {						stack.push('(');					}					escaped = false;				break;				case ')':					if (!escaped && stack.peek() == '(') {						stack.pop();					}					escaped = false;				break;			}		}		int start = 0;		if (!wasInString && !wasInIdentifier && len > 0) {			// trim spaces at the start of the string			for (; start < len && Character.isWhitespace(query.charAt(start)); start++);		}		int stop = len - 1;		if (stack.peek() !=  '\'' && !wasInIdentifier && stop > start) {			// trim spaces at the end of the string			for (; stop >= start && Character.isWhitespace(query.charAt(stop)); stop--);		}		stop++;		if (start == stop) {			// we have an empty string			return(new QueryPart(false, null, stack.peek() ==  '\'' || stack.peek() == '"'));		} else if (stack.peek() ==  '\'' || stack.peek() == '"') {			// we have an open quote			return(new QueryPart(false, query.substring(start, stop), true));		} else {			// see if the string is complete			if (scolonterm && query.charAt(stop - 1) == ';') {				return(new QueryPart(true, query.substring(start, stop), false));			} else {				return(new QueryPart(false, query.substring(start, stop), false));			}		}	}	public static String dq(String in) {		return("\"" + in.replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\\\"") + "\"");	}}/** * A QueryPart is (a part of) a SQL query.  In the QueryPart object information * like the actual SQL query string, whether it has an open quote and the like * is stored. */class QueryPart {	private boolean complete;	private String query;	private boolean open;	public QueryPart(boolean complete, String query, boolean open) {		this.complete = complete;		this.query = query;		this.open = open;	}	public boolean isEmpty() {		return(query == null);	}	public boolean isComplete() {		return(complete);	}	public String getQuery() {		return(query);	}	public boolean hasOpenQuote() {		return(open);	}}/** * An SQLStack is a simple stack that keeps track of open brackets and * (single and double) quotes in an SQL query. */class SQLStack {	StringBuffer stack;	public SQLStack() {		stack = new StringBuffer();	}	public char peek() {		if (empty()) {			return('\0');		} else {			return(stack.charAt(stack.length() - 1));		}	}	public char pop() {		char tmp = peek();		if (tmp != '\0') {			stack.setLength(stack.length() - 1);		}		return(tmp);	}	public char push(char item) {		stack.append(item);		return(item);	}	public boolean empty() {		return(stack.length() == 0);	}}/** * A Table represents an SQL table.  All data required to * generate a fully qualified name is stored, as well as dependency * data. */class Table {	final String cat;	final String schem;	final String name;	final String type;	final String fqname;	List needs;	Table(String cat, String schem, String name, String type) {		this.cat = cat;		this.schem = schem;		this.name = name;		this.type = type;		this.fqname = schem + "." + name;		needs = new ArrayList();	}	void addDependancy(Table dependsOn) throws Exception {		if (this.fqname.equals(dependsOn.fqname))			throw new Exception("Cyclic dependancy graphs are not supported (foreign key relation references self)");		if (dependsOn.needs.contains(this))			throw new Exception("Cyclic dependancy graphs are not supported (foreign key relation a->b and b->a)");		if (!needs.contains(dependsOn)) needs.add(dependsOn);	}	List requires(List existingTables) {		if (existingTables == null || existingTables.size() == 0)			return(new ArrayList(needs));		List req = new ArrayList();		for (int i = 0; i < needs.size(); i++) {			if (!existingTables.contains(needs.get(i)))				req.add(needs.get(i));		}		return(req);	}	String getCat() {		return(cat);	}	String getSchem() {		return(schem);	}	String getSchemQ() {		return(JdbcClient.dq(schem));	}	String getName() {		return(name);	}	String getNameQ() {		return(JdbcClient.dq(name));	}	String getType() {		return(type);	}	String getFqname() {		return(fqname);	}	String getFqnameQ() {		return(getSchemQ() + "." + getNameQ());	}	public String toString() {		return(fqname);	}	static Table findTable(String fqname, List list) {		for (int i = 0; i < list.size(); i++) {			if (((Table)(list.get(i))).fqname.equals(fqname))				return((Table)(list.get(i)));		}		// not found		return(null);	}	static void checkForLoop(Table table, List parents) throws Exception {		parents.add(table);		for (int i = 0; i < table.needs.size(); i++) {			Table child = (Table)(table.needs.get(i));			if (parents.contains(child))				throw new Exception("Cyclic dependancy graphs are not supported (cycle detected for " + child.fqname + ")");			checkForLoop(child, parents);		}	}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?