⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 monetresultset.java

📁 这个是内存数据库的客户端
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/* * The contents of this file are subject to the MonetDB Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://monetdb.cwi.nl/Legal/MonetDBLicense-1.1.html * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Original Code is the MonetDB Database System. * * The Initial Developer of the Original Code is CWI. * Portions created by CWI are Copyright (C) 1997-2007 CWI. * All Rights Reserved. */package nl.cwi.monetdb.jdbc;import java.sql.*;import java.io.*;import java.util.*;import java.math.*;import java.net.*;/** * A ResultSet suitable for the MonetDB database. * <br /><br /> * A table of data representing a database result set, which is usually * generated by executing a statement that queries the database. * <br /><br /> * A ResultSet object maintains a cursor pointing to its current row of data. * Initially the cursor is positioned before the first row. The next method * moves the cursor to the next row, and because it returns false when there * are no more rows in the ResultSet object, it can be used in a while loop to * iterate through the result set. * <br /><br /> * The current state of this ResultSet is that it supports positioning in the * result set, absolute and relative. A slight performance difference between * FORWARD_ONLY or result sets scrollable in both directions can be noticed as * for FORWARD_ONLY result sets the memory usage will be likely lower for large * result sets. * * @author Fabian Groffen <Fabian.Groffen@cwi.nl> * @version 0.7 */public class MonetResultSet implements ResultSet {	/** The last column read using some getXXX function */	private int lastColumnRead = -1;	// the following have default access modifier for the MonetVirtualResultSet	/** The current line of the buffer split in columns */	String[] result;	/** The current position of the cursor for this ResultSet object */	int curRow = 0;	// a blank final is immutable once assigned in the constructor	/** A Header to retrieve lines from */	private final MonetConnection.ResultSetResponse header;	/** The names of the columns in this ResultSet */	private final String[] columns;	/** The MonetDB types of the columns in this ResultSet */	private final String[] types;	/** The id of this ResultSet (needed for closing) */	private final String tableID;	/** The number of rows in this ResultSet */	final int tupleCount;	// default for the MonetVirtualResultSet	/** The parental Statement object */	private final Statement statement;	/** The type of this ResultSet (forward or scrollable) */	private int type = TYPE_FORWARD_ONLY;	/** The concurrency of this ResultSet (currently only read-only) */	private int concurrency = CONCUR_READ_ONLY;	/** The warnings for this ResultSet object */	private SQLWarning warnings;	/**	 * Main constructor backed by the given Header.	 *	 * @param statement the statement which created this ResultSet	 * @param header a header containing the query, resultset type, etc.	 * @throws SQLException is a protocol error occurs	 */	MonetResultSet(		Statement statement,		MonetConnection.ResultSetResponse header)		throws SQLException	{		this.statement = statement;		this.header = header;		this.type = header.getRSType();		this.concurrency = header.getRSConcur();		// well there is only one supported concurrency, so we don't have to		// bother about that		// throws SQLException on getters of Header, so we find out immediately		// if an error occurred for this query		columns = header.getNames();		types = header.getTypes();		tableID = "" + header.id;		tupleCount = header.tuplecount;		// create result array		result = new String[columns.length];	}	/**	 * Constructor used by MonetFillableResultSet.	 * DO NOT USE THIS CONSTRUCTOR IF YOU ARE NOT EXTENDING THIS OBJECT!	 *	 * @param columns the column names	 * @param types the column types	 * @param results the number of rows in the ResultSet	 * @throws IOException if communicating with monet failed	 * @throws SQLException is a protocol error occurs	 */	MonetResultSet(		String[] columns,		String[] types,		int results	) throws IllegalArgumentException	{		if (columns == null || types == null) {			throw new IllegalArgumentException("One of the given arguments is null!");		}		if (columns.length != types.length) {			throw new IllegalArgumentException("Given arguments are not the same size!");		}		if (results < 0) {			throw new IllegalArgumentException("Negative rowcount not allowed!");		}		this.header = null;		this.tableID = null;		this.statement = null; // no parent, required for specs		this.columns = columns;		this.types = types;		this.tupleCount = results;	}	//== methods of interface ResultSet	// Chapter 14.2.2 Sun JDBC 3.0 Specification	/**	 * Moves the cursor to the given row number in this ResultSet object.	 * <br /><br />	 * If the row number is positive, the cursor moves to the given row number	 * with respect to the beginning of the result set. The first row is row 1,	 * the second is row 2, and so on.	 * <br /><br />	 * If the given row number is negative, the cursor moves to an absolute row	 * position with respect to the end of the result set. For example, calling	 * the method absolute(-1) positions the cursor on the last row; calling the	 * method absolute(-2) moves the cursor to the next-to-last row, and so on.	 * <br /><br />	 * An attempt to position the cursor beyond the first/last row in the result	 * set leaves the cursor before the first row or after the last row.	 * Note: calling absolute(1) is the same as calling first(). Calling	 *       absolute(-1) is the same as calling last().	 *	 * @param row the number of the row to which the cursor should move. A	 *        positive number indicates the row number counting from the	 *        beginning of the result set; a negative number indicates the row	 *        number counting from the end of the result set	 * @return true if the cursor is on the result set; false otherwise	 * @throws SQLException if a database access error occurs, or the result set	 *         type is TYPE_FORWARD_ONLY	 */ 	public boolean absolute(int row) throws SQLException {		if (row != curRow + 1 && type == TYPE_FORWARD_ONLY) throw			new SQLException("(Absolute) positioning not allowed on forward " +				" only result sets!");		if (header.isClosed()) throw new SQLException("ResultSet is closed!");		// first calculate what the JDBC row is		if (row < 0) {			// calculate the negatives...			row = tupleCount + row + 1;		}		// now place the row not farther than just before or after the result		if (row < 0) row = 0;	// before first		else if (row > tupleCount + 1) row = tupleCount + 1;	// after last		String tmpLine = header.getLine(row - 1);		// store it		curRow = row;		if (tmpLine == null) return(false);		int len = tmpLine.length();		char[] chrLine = new char[len];		tmpLine.getChars(0, len, chrLine, 0);		// extract separate fields by examining string, char for char		boolean inString = false, escaped = false;		int cursor = 2, column = 0, i = 2;		StringBuffer uesc = new StringBuffer();		for (; i < len; i++) {			switch(chrLine[i]) {				default:					escaped = false;				break;				case '\\':					escaped = !escaped;				break;				case '"':					/**					 * If all strings are wrapped between two quotes, a \" can					 * never exist outside a string. Thus if we believe that we					 * are not within a string, we can safely assume we're about					 * to enter a string if we find a quote.					 * If we are in a string 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 for all					 * cases. Because "test \\\"" can exist as well, we need to					 * know if a quote is prefixed by an escaping slash or not.					 */					if (!inString) {						inString = true;					} else if (!escaped) {						inString = false;					}					// reset escaped flag					escaped = false;				break;				case '\t':					if (!inString &&						(i > 0 && chrLine[i - 1] == ',') ||						(i + 1 == len - 1 && chrLine[++i] == ']')) // dirty					{						// split!						if (chrLine[cursor] == '"' &&							chrLine[i - 2] == '"')						{							// reuse the StringBuffer by cleaning it							uesc.delete(0, uesc.length());							// prevent capacity increasements							uesc.ensureCapacity((i - 2) - (cursor + 1));							for (int pos = cursor + 1; pos < i - 2; pos++) {								if (chrLine[pos] == '\\' && pos + 1 < i - 2) {									pos++;									// strToStr and strFromStr in gdk_atoms.mx only									// support \t \n \\ \" and \377									switch (chrLine[pos]) {										case '\\':											uesc.append('\\');										break;										case 'n':											uesc.append('\n');										break;										case 't':											uesc.append('\t');										break;										case '"':											uesc.append('"');										break;										case '0': case '1': case '2': case '3':											// this could be an octal number, let's check it out											if (pos + 2 < i - 2 &&												chrLine[pos + 1] >= '0' && chrLine[pos + 1] <= '7' &&												chrLine[pos + 2] >= '0' && chrLine[pos + 2] <= '7'											) {												// we got the number!												try {													uesc.append((char)(Integer.parseInt("" + chrLine[pos] + chrLine[pos + 1] + chrLine[pos + 2], 8)));													pos += 2;													break;												} catch (NumberFormatException e) {													// hmmm, this point should never be reached actually...													throw new AssertionError("Flow error, should never try to parse non-number");												}											}											// do default action if number seems not to be correct										default:											// this is wrong, just ignore the escape, and print the char											uesc.append(chrLine[pos]);										break;									}								} else {									uesc.append(chrLine[pos]);								}							}							// put the unescaped string in the right place							result[column++] = uesc.toString();						} else if ((i - 1) - cursor == 4 &&								tmpLine.indexOf("NULL", cursor) == cursor)						{							result[column++] = null;						} else {							result[column++] =								tmpLine.substring(cursor, i - 1);						}						cursor = i + 1;					}					// reset escaped flag					escaped = false;				break;			}		}		// check if this result is of the size we expected it to be		if (column != columns.length) throw new AssertionError("Illegal result length: " + column + "\nlast read: " + (column > 0 ? result[column - 1] : "<none>"));		// reset lastColumnRead		lastColumnRead = -1;		return(true);	}	/**	 * Moves the cursor to the end of this ResultSet object, just after the last	 * row. This method has no effect if the result set contains no rows.	 *	 * @throws SQLException if a database access error occurs or the result set	 *         type is TYPE_FORWARD_ONLY	 */	public void afterLast() throws SQLException {		absolute(tupleCount + 1);	}	/**	 * Moves the cursor to the front of this ResultSet object, just before the	 * first row. This method has no effect if the result set contains no rows.	 *	 * @throws SQLException if a database access error occurs or the result set	 *         type is TYPE_FORWARD_ONLY	 */	public void beforeFirst() throws SQLException {		absolute(0);	}	/**	 * Clears all warnings reported for this ResultSet object. After a call to	 * this method, the method getWarnings returns null until a new warning is	 * reported for this ResultSet object.	 */	public void clearWarnings() {		warnings = null;	}	/**	 * Releases this ResultSet object's database (and JDBC) resources	 * immediately instead of waiting for this to happen when it is	 * automatically closed.	 */	public void close() {		if (!header.isClosed()) {			header.close();		}	}	// Chapter 14.2.3 from Sun JDBC 3.0 specification	/**	 * Maps the given ResultSet column name to its ResultSet column index.	 * Column names supplied to getter methods are case insensitive. If a select	 * list contains the same column more than once, the first instance of the	 * column will be returned.	 *	 * @param columnName the name of the column	 * @return the column index of the given column name	 * @throws SQLException if the ResultSet object does not contain columnName	 */	public int findColumn(String columnName) throws SQLException {		for (int i = 0; i < columns.length; i++) {			if (columns[i].equalsIgnoreCase(columnName)) return(i + 1);		}

⌨️ 快捷键说明

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