📄 mysqlio.java
字号:
* streamed? * @param catalog the database name in use when the result set was created * @param isBinaryEncoded is this result set in native encoding? * @param unpackFieldInfo should we read MYSQL_FIELD info (if available)? * * @return a result set * * @throws SQLException if a database access error occurs */ protected ResultSetImpl getResultSet(StatementImpl callingStatement, long columnCount, int maxRows, int resultSetType, int resultSetConcurrency, boolean streamResults, String catalog, boolean isBinaryEncoded, Field[] metadataFromCache) throws SQLException { Buffer packet; // The packet from the server Field[] fields = null; // Read in the column information if (metadataFromCache == null /* we want the metadata from the server */) { fields = new Field[(int) columnCount]; for (int i = 0; i < columnCount; i++) { Buffer fieldPacket = null; fieldPacket = readPacket(); fields[i] = unpackField(fieldPacket, false); } } else { for (int i = 0; i < columnCount; i++) { skipPacket(); } } packet = reuseAndReadPacket(this.reusablePacket); readServerStatusForResultSets(packet); // // Handle cursor-based fetch first // if (this.connection.versionMeetsMinimum(5, 0, 2) && this.connection.getUseCursorFetch() && isBinaryEncoded && callingStatement != null && callingStatement.getFetchSize() != 0 && callingStatement.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) { ServerPreparedStatement prepStmt = (com.mysql.jdbc.ServerPreparedStatement) callingStatement; boolean usingCursor = true; // // Server versions 5.0.5 or newer will only open // a cursor and set this flag if they can, otherwise // they punt and go back to mysql_store_results() behavior // if (this.connection.versionMeetsMinimum(5, 0, 5)) { usingCursor = (this.serverStatus & SERVER_STATUS_CURSOR_EXISTS) != 0; } if (usingCursor) { RowData rows = new RowDataCursor( this, prepStmt, fields); ResultSetImpl rs = buildResultSetWithRows( callingStatement, catalog, fields, rows, resultSetType, resultSetConcurrency, isBinaryEncoded); if (usingCursor) { rs.setFetchSize(callingStatement.getFetchSize()); } return rs; } } RowData rowData = null; if (!streamResults) { rowData = readSingleRowSet(columnCount, maxRows, resultSetConcurrency, isBinaryEncoded, (metadataFromCache == null) ? fields : metadataFromCache); } else { rowData = new RowDataDynamic(this, (int) columnCount, (metadataFromCache == null) ? fields : metadataFromCache, isBinaryEncoded); this.streamingData = rowData; } ResultSetImpl rs = buildResultSetWithRows(callingStatement, catalog, (metadataFromCache == null) ? fields : metadataFromCache, rowData, resultSetType, resultSetConcurrency, isBinaryEncoded); return rs; } /** * Forcibly closes the underlying socket to MySQL. */ protected final void forceClose() { try { if (this.mysqlInput != null) { this.mysqlInput.close(); } } catch (IOException ioEx) { // we can't do anything constructive about this // Let the JVM clean it up later this.mysqlInput = null; } try { if (this.mysqlOutput != null) { this.mysqlOutput.close(); } } catch (IOException ioEx) { // we can't do anything constructive about this // Let the JVM clean it up later this.mysqlOutput = null; } try { if (this.mysqlConnection != null) { this.mysqlConnection.close(); } } catch (IOException ioEx) { // we can't do anything constructive about this // Let the JVM clean it up later this.mysqlConnection = null; } } /** * Reads and discards a single MySQL packet from the input stream. * * @throws SQLException if the network fails while skipping the * packet. */ protected final void skipPacket() throws SQLException { try { int lengthRead = readFully(this.mysqlInput, this.packetHeaderBuf, 0, 4); if (lengthRead < 4) { forceClose(); throw new IOException(Messages.getString("MysqlIO.1")); //$NON-NLS-1$ } int packetLength = (this.packetHeaderBuf[0] & 0xff) + ((this.packetHeaderBuf[1] & 0xff) << 8) + ((this.packetHeaderBuf[2] & 0xff) << 16); if (this.traceProtocol) { StringBuffer traceMessageBuf = new StringBuffer(); traceMessageBuf.append(Messages.getString("MysqlIO.2")); //$NON-NLS-1$ traceMessageBuf.append(packetLength); traceMessageBuf.append(Messages.getString("MysqlIO.3")); //$NON-NLS-1$ traceMessageBuf.append(StringUtils.dumpAsHex( this.packetHeaderBuf, 4)); this.connection.getLog().logTrace(traceMessageBuf.toString()); } byte multiPacketSeq = this.packetHeaderBuf[3]; if (!this.packetSequenceReset) { if (this.enablePacketDebug && this.checkPacketSequence) { checkPacketSequencing(multiPacketSeq); } } else { this.packetSequenceReset = false; } this.readPacketSequence = multiPacketSeq; skipFully(this.mysqlInput, packetLength); } catch (IOException ioEx) { throw SQLError.createCommunicationsException(this.connection, this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, ioEx); } catch (OutOfMemoryError oom) { try { this.connection.realClose(false, false, true, oom); } finally { throw oom; } } } /** * Read one packet from the MySQL server * * @return the packet from the server. * * @throws SQLException DOCUMENT ME! * @throws CommunicationsException DOCUMENT ME! */ protected final Buffer readPacket() throws SQLException { try { int lengthRead = readFully(this.mysqlInput, this.packetHeaderBuf, 0, 4); if (lengthRead < 4) { forceClose(); throw new IOException(Messages.getString("MysqlIO.1")); //$NON-NLS-1$ } int packetLength = (this.packetHeaderBuf[0] & 0xff) + ((this.packetHeaderBuf[1] & 0xff) << 8) + ((this.packetHeaderBuf[2] & 0xff) << 16); if (packetLength > this.maxAllowedPacket) { throw new PacketTooBigException(packetLength, this.maxAllowedPacket); } if (this.traceProtocol) { StringBuffer traceMessageBuf = new StringBuffer(); traceMessageBuf.append(Messages.getString("MysqlIO.2")); //$NON-NLS-1$ traceMessageBuf.append(packetLength); traceMessageBuf.append(Messages.getString("MysqlIO.3")); //$NON-NLS-1$ traceMessageBuf.append(StringUtils.dumpAsHex( this.packetHeaderBuf, 4)); this.connection.getLog().logTrace(traceMessageBuf.toString()); } byte multiPacketSeq = this.packetHeaderBuf[3]; if (!this.packetSequenceReset) { if (this.enablePacketDebug && this.checkPacketSequence) { checkPacketSequencing(multiPacketSeq); } } else { this.packetSequenceReset = false; } this.readPacketSequence = multiPacketSeq; // Read data byte[] buffer = new byte[packetLength + 1]; int numBytesRead = readFully(this.mysqlInput, buffer, 0, packetLength); if (numBytesRead != packetLength) { throw new IOException("Short read, expected " + packetLength + " bytes, only read " + numBytesRead); } buffer[packetLength] = 0; Buffer packet = new Buffer(buffer); packet.setBufLength(packetLength + 1); if (this.traceProtocol) { StringBuffer traceMessageBuf = new StringBuffer(); traceMessageBuf.append(Messages.getString("MysqlIO.4")); //$NON-NLS-1$ traceMessageBuf.append(getPacketDumpToLog(packet, packetLength)); this.connection.getLog().logTrace(traceMessageBuf.toString()); } if (this.enablePacketDebug) { enqueuePacketForDebugging(false, false, 0, this.packetHeaderBuf, packet); } if (this.connection.getMaintainTimeStats()) { this.lastPacketReceivedTimeMs = System.currentTimeMillis(); } return packet; } catch (IOException ioEx) { throw SQLError.createCommunicationsException(this.connection, this.lastPacketSentTimeMs, this.lastPacketReceivedTimeMs, ioEx); } catch (OutOfMemoryError oom) { try { this.connection.realClose(false, false, true, oom); } finally { throw oom; } } } /** * Unpacks the Field information from the given packet. Understands pre 4.1 * and post 4.1 server version field packet structures. * * @param packet the packet containing the field information * @param extractDefaultValues should default values be extracted? * * @return the unpacked field * * @throws SQLException DOCUMENT ME! */ protected final Field unpackField(Buffer packet, boolean extractDefaultValues) throws SQLException { if (this.use41Extensions) { // we only store the position of the string and // materialize only if needed... if (this.has41NewNewProt) { // Not used yet, 5.0? int catalogNameStart = packet.getPosition() + 1; int catalogNameLength = packet.fastSkipLenString(); catalogNameStart = adjustStartForFieldLength(catalogNameStart, catalogNameLength); } int databaseNameStart = packet.getPosition() + 1; int databaseNameLength = packet.fastSkipLenString(); databaseNameStart = adjustStartForFieldLength(databaseNameStart, databaseNameLength); int tableNameStart = packet.getPosition() + 1; int tableNameLength = packet.fastSkipLenString(); tableNameStart = adjustStartForFieldLength(tableNameStart, tableNameLength); // orgTableName is never used so skip int originalTableNameStart = packet.getPosition() + 1; int originalTableNameLength = packet.fastSkipLenString(); originalTableNameStart = adjustStartForFieldLength(originalTableNameStart, originalTableNameLength); // we only store the position again... int nameStart = packet.getPosition() + 1; int nameLength = packet.fastSkipLenString(); nameStart = adjustStartForFieldLength(nameStart, nameLength); // orgColName is not required so skip... int originalColumnNameStart = packet.getPosition() + 1; int originalColumnNameLength = packet.fastSkipLenString(); originalColumnNameStart = adjustStartForFieldLength(originalColumnNameStart, originalColumnNameLength); packet.readByte(); short charSetNumber = (short) packet.readInt(); long colLength = 0; if (this.has41NewNewProt) { colLength = packet.readLong(); } else { colLength = packet.readLongInt(); } int colType = packet.readByte() & 0xff; short colFlag = 0; if (this.hasLongColumnInfo) { colFlag = (short) packet.readInt(); } else { colFlag = (short) (packet.readByte() & 0xff); } int colDecimals = packet.readByte() & 0xff; int defaultValueStart = -1; int defaultValueLength = -1; if (extractDefaultValues) { defaultValueStart = packet.getPosition() + 1; defaultValueLength = packet.fastSkipLenString(); } Field field = new Field(this.connection, packet.getByteBuffer(), databaseNameStart, databaseNameLength, tableNameStart, tableNameLength, originalTableNameStart, originalTableNameLength, nameStart, nameLength, originalColumnNameStart, originalColumnNameLength, colLength, colType, colFlag, colDecimals,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -