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 + -
显示快捷键?