入口OracleStatement
预处理语句类继承了OracleStatement
public ResultSet executeQuery(String var1) throws SQLException {
synchronized(this.connection) {
Object var3 = null;
try {
this.executionType = 1;
this.noMoreUpdateCounts = false;
this.ensureOpen();
this.checkIfJdbcBatchExists();
this.sendBatch();
this.hasStream = false;
this.sqlObject.initialize(var1);
this.sqlKind = this.sqlObject.getSqlKind();
this.needToParse = true;
this.prepareForNewResults(true, true);
if (this.userRsetType == 1) {
this.doExecuteWithTimeout(); //执行查询
this.currentResultSet = new OracleResultSetImpl(this.connection, this);
var3 = this.currentResultSet;
} else {
var3 = this.doScrollStmtExecuteQuery();
if (var3 == null) {
this.currentResultSet = new OracleResultSetImpl(this.connection, this);
var3 = this.currentResultSet;
}
}
} finally {
this.executionType = -1;
}
return (ResultSet)var3;
}
}
void doExecuteWithTimeout() throws SQLException {
try {
this.cleanOldTempLobs();
this.connection.registerHeartbeat();
this.rowsProcessed = 0;
SQLException var1;
if (this.sqlKind.isSELECT()) {
if (this.connection.j2ee13Compliant && this.executionType == 2) {
var1 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), 129);
var1.fillInStackTrace();
throw var1;
}
this.connection.needLine();
if (!this.isOpen) {
this.connection.open(this);
this.isOpen = true;
}
if (this.queryTimeout != 0) { //如果有查询超时时间
try {
this.connection.getTimeout().setTimeout((long)(this.queryTimeout * 1000), this);
this.executeMaybeDescribe(); //执行查询
} finally {
this.connection.getTimeout().cancelTimeout();
}
} else {
this.executeMaybeDescribe();
}
this.checkValidRowsStatus();
if (this.serverCursor) {
this.adjustGotLastBatch();
}
} else {
if (this.connection.j2ee13Compliant && !this.sqlKind.isPlsqlOrCall() && this.executionType == 1) {
var1 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), 128);
var1.fillInStackTrace();
throw var1;
}
++this.currentRank;
if (this.currentRank >= this.batch) {
try {
this.connection.needLine();
this.cancelLock.enterExecuting();
if (!this.isOpen) {
this.connection.open(this);
this.isOpen = true;
}
if (this.queryTimeout != 0) {
this.connection.getTimeout().setTimeout((long)(this.queryTimeout * 1000), this);
}
this.executeForRows(false);
} catch (SQLException var14) {
this.needToParse = true;
if (this.batch > 1) {
this.clearBatch();
int[] var2;
int var3;
if (this.numberOfExecutedElementsInBatch != -1 && this.numberOfExecutedElementsInBatch < this.batch) {
var2 = new int[this.numberOfExecutedElementsInBatch];
for(var3 = 0; var3 < var2.length; ++var3) {
var2[var3] = -2;
}
} else {
var2 = new int[this.batch];
for(var3 = 0; var3 < var2.length; ++var3) {
var2[var3] = -3;
}
}
BatchUpdateException var17 = DatabaseError.createBatchUpdateException(var14, var2.length, var2);
var17.fillInStackTrace();
throw var17;
}
this.resetCurrentRowBinders();
throw var14;
} finally {
if (this.queryTimeout != 0) {
this.connection.getTimeout().cancelTimeout();
}
this.currentRank = 0;
this.cancelLock.exitExecuting();
this.checkValidRowsStatus();
}
}
}
} catch (SQLException var16) {
this.resetOnExceptionDuringExecute();
throw var16;
}
this.connection.registerHeartbeat();
}
void executeMaybeDescribe() throws SQLException {
boolean var1 = true;
if (this.rowPrefetchChanged) {
if (this.streamList == null && this.rowPrefetch != this.definesBatchSize) {
this.needToPrepareDefineBuffer = true;
}
this.rowPrefetchChanged = false;
}
if (!this.needToPrepareDefineBuffer) {
if (this.accessors == null) {
this.needToPrepareDefineBuffer = true;
} else if (this.columnsDefinedByUser) {
this.needToPrepareDefineBuffer = !this.checkAccessorsUsable();
}
}
boolean var2 = false;
try {
this.cancelLock.enterExecuting();
if (this.needToPrepareDefineBuffer) {
if (!this.columnsDefinedByUser) {
this.executeForDescribe(); //执行查询
var2 = true;
if (this.aFetchWasDoneDuringDescribe) {
var1 = false;
}
}
if (this.needToPrepareDefineBuffer) {
this.prepareAccessors();
}
}
int var3 = this.accessors.length;
for(int var4 = this.numberOfDefinePositions; var4 < var3; ++var4) {
Accessor var5 = this.accessors[var4];
if (var5 != null) {
var5.rowSpaceIndicator = null;
}
}
if (var1) {
this.executeForRows(var2);
}
} catch (SQLException var9) {
this.needToParse = true;
throw var9;
} finally {
this.cancelLock.exitExecuting();
}
}
T4CStatement
也继承了OracleStatement
class T4CStatement extends OracleStatement {
void executeForDescribe() throws SQLException {
this.t4Connection.assertLoggedOn("oracle.jdbc.driver.T4CStatement.execute_for_describe");
try {
if (this.t4Connection.useFetchSizeWithLongColumn) {
this.doOall8(true, true, true, true, false);
} else {
this.doOall8(true, true, false, true, this.definedColumnType != null); //执行查询
}
} catch (SQLException var7) {
throw var7;
} catch (IOException var8) {
((T4CConnection)this.connection).handleIOException(var8);
SQLException var2 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), var8);
var2.fillInStackTrace();
throw var2;
} finally {
this.rowsProcessed = this.t4Connection.all8.rowsProcessed;
this.validRows = this.t4Connection.all8.getNumRows();
}
void doOall8(boolean var1, boolean var2, boolean var3, boolean var4, boolean var5) throws SQLException, IOException {
if (var1 || var4 || !var2) {
this.oacdefSent = null;
}
this.t4Connection.assertLoggedOn("oracle.jdbc.driver.T4CStatement.doOall8");
if (this.sqlKind == SqlKind.UNINITIALIZED) {
SQLException var14 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), 439, "sqlKind = " + this.sqlKind);
var14.fillInStackTrace();
throw var14;
} else {
if (var3) {
this.rowPrefetchInLastFetch = this.rowPrefetch;
}
int var6 = this.numberOfDefinePositions;
if (this.sqlKind.isDML()) {
var6 = 0;
}
int var7;
if (this.accessors != null) {
for(var7 = 0; var7 < this.accessors.length; ++var7) {
if (this.accessors[var7] != null) {
this.accessors[var7].lastRowProcessed = 0;
}
}
}
if (this.outBindAccessors != null) {
for(var7 = 0; var7 < this.outBindAccessors.length; ++var7) {
if (this.outBindAccessors[var7] != null) {
this.outBindAccessors[var7].lastRowProcessed = 0;
}
}
}
if (this.returnParamAccessors != null) {
for(var7 = 0; var7 < this.returnParamAccessors.length; ++var7) {
if (this.returnParamAccessors[var7] != null) {
this.returnParamAccessors[var7].lastRowProcessed = 0;
}
}
}
int var11;
int var12;
if (this.bindIndicators != null) {
var7 = ((this.bindIndicators[this.bindIndicatorSubRange + 3] & '\uffff') << 16) + (this.bindIndicators[this.bindIndicatorSubRange + 4] & '\uffff');
int var8 = 0;
if (this.ibtBindChars != null) {
var8 = this.ibtBindChars.length * this.connection.conversion.cMaxCharSize;
}
for(int var9 = 0; var9 < this.numberOfBindPositions; ++var9) {
int var10 = this.bindIndicatorSubRange + 5 + 10 * var9;
var11 = this.bindIndicators[var10 + 2] & '\uffff';
if (var11 != 0) {
var12 = this.bindIndicators[var10 + 9] & '\uffff';
if (var12 == 2) {
var8 = Math.max(var11 * this.connection.conversion.maxNCharSize, var8);
} else {
var8 = Math.max(var11 * this.connection.conversion.cMaxCharSize, var8);
}
}
}
if (this.tmpBindsByteArray == null) {
this.tmpBindsByteArray = new byte[var8];
} else if (this.tmpBindsByteArray.length < var8) {
this.tmpBindsByteArray = null;
this.tmpBindsByteArray = new byte[var8];
}
} else {
this.tmpBindsByteArray = null;
}
int[] var15 = this.definedColumnType;
int[] var18 = this.definedColumnSize;
int[] var16 = this.definedColumnFormOfUse;
if (var5 && var4 && this.sqlObject.includeRowid) {
var15 = new int[this.definedColumnType.length + 1];
System.arraycopy(this.definedColumnType, 0, var15, 1, this.definedColumnType.length);
var15[0] = -8;
var18 = new int[this.definedColumnSize.length + 1];
System.arraycopy(this.definedColumnSize, 0, var18, 1, this.definedColumnSize.length);
var16 = new int[this.definedColumnFormOfUse.length + 1];
System.arraycopy(this.definedColumnFormOfUse, 0, var16, 1, this.definedColumnFormOfUse.length);
}
this.allocateTmpByteArray();
T4C8Oall var17 = this.t4Connection.all8;
this.t4Connection.sendPiggyBackedMessages();
try {
//执行查询
var17.doOALL(var1, var2, var3, var4, var5, this.sqlKind, this.cursorId, this.sqlObject.getSqlBytes(this.processEscapes, this.convertNcharLiterals), this.rowPrefetch, this.outBindAccessors, this.numberOfBindPositions, this.accessors, var6, this.bindBytes, this.bindChars, this.bindIndicators, this.bindIndicatorSubRange, this.connection.conversion, this.tmpBindsByteArray, this.parameterStream, parameterDatum, parameterOtype, this, this.ibtBindBytes, this.ibtBindChars, this.ibtBindIndicators, this.oacdefSent, var15, var18, var16, this.registration);
var11 = var17.getCursorId();
if (var11 != 0) {
this.cursorId = var11;
}
this.oacdefSent = var17.oacdefBindsSent;
} catch (SQLException var13) {
var12 = var17.getCursorId();
if (var12 != 0) {
this.cursorId = var12;
}
if (var13.getErrorCode() != DatabaseError.getVendorCode(110)) {
throw var13;
}
this.sqlWarning = DatabaseError.addSqlWarning(this.sqlWarning, 110);
}
}
}
T4C8Oall
final class T4C8Oall extends T4CTTIfun {
void doOALL(boolean var1, boolean var2, boolean var3, boolean var4, boolean var5, SqlKind var6, int var7, byte[] var8, int var9, Accessor[] var10, int var11, Accessor[] var12, int var13, byte[] var14, char[] var15, short[] var16, int var17, DBConversion var18, byte[] var19, InputStream[][] var20, byte[][][] var21, OracleTypeADT[][] var22, OracleStatement var23, byte[] var24, char[] var25, short[] var26, T4CTTIoac[] var27, int[] var28, int[] var29, int[] var30, NTFDCNRegistration var31) throws SQLException, IOException {
this.typeOfStatement = var6;
this.cursor = var7;
this.sqlStmt = var1 ? var8 : EMPTY_BYTES;
this.rowsToFetch = var9;
this.outBindAccessors = var10;
this.numberOfBindPositions = var11;
this.definesAccessors = var12;
this.definesLength = var13;
this.bindBytes = var14;
this.bindChars = var15;
this.bindIndicators = var16;
this.bindIndicatorSubRange = var17;
this.conversion = var18;
this.tmpBindsByteArray = var19;
this.parameterStream = var20;
this.parameterDatum = var21;
this.parameterOtype = var22;
this.oracleStatement = var23;
this.ibtBindBytes = var24;
this.ibtBindChars = var25;
this.ibtBindIndicators = var26;
this.oacdefBindsSent = var27;
this.definedColumnType = var28;
this.definedColumnSize = var29;
this.definedColumnFormOfUse = var30;
this.registration = var31;
this.dbCharSet = var18.getServerCharSetId();
this.NCharSet = var18.getNCharSetId();
int var32 = 0;
if (this.bindIndicators != null) {
var32 = ((this.bindIndicators[this.bindIndicatorSubRange + 3] & '\uffff') << 16) + (this.bindIndicators[this.bindIndicatorSubRange + 4] & '\uffff');
}
SQLException var40;
if (var8 == null) {
var40 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), 431);
var40.fillInStackTrace();
throw var40;
} else if (!this.typeOfStatement.isDML() && var32 > 1) {
var40 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), 433);
var40.fillInStackTrace();
throw var40;
} else {
this.rowsProcessed = 0;
this.options = 0L;
this.plsql = this.typeOfStatement.isPlsqlOrCall();
this.sendBindsDefinition = false;
if (this.receiveState != 0) {
this.receiveState = 0;
}
this.rxh.init();
this.rxd.init();
this.oer.init();
if (var5) {
this.initDefinesDefinition();
}
if (this.numberOfBindPositions > 0 && this.bindIndicators != null) {
if (this.oacdefBindsSent == null) {
this.oacdefBindsSent = new T4CTTIoac[this.numberOfBindPositions];
}
this.sendBindsDefinition = this.initBindsDefinition(this.oacdefBindsSent);
}
this.options = this.setOptions(var1, var2, var3, var5);
if ((this.options & 1L) > 0L) {
this.al8i4[0] = 1L;
} else {
this.al8i4[0] = 0L;
}
if (!this.plsql && !this.typeOfStatement.isOTHER()) {
if (var4) {
if (var3 && this.oracleStatement.connection.useFetchSizeWithLongColumn) {
this.al8i4[1] = (long)this.rowsToFetch;
} else {
this.al8i4[1] = 0L;
}
} else if (this.typeOfStatement.isDML()) {
this.al8i4[1] = var32 == 0 ? (long)this.oracleStatement.batch : (long)var32;
} else if (var3 && !var4) {
this.al8i4[1] = (long)this.rowsToFetch;
} else {
this.al8i4[1] = 0L;
}
} else {
this.al8i4[1] = 1L;
}
if (this.typeOfStatement.isSELECT()) {
this.al8i4[7] = 1L;
} else {
this.al8i4[7] = 0L;
}
long var33 = this.oracleStatement.inScn;
int var35 = (int)var33;
int var36 = (int)(var33 >> 32);
this.al8i4[5] = (long)var35;
this.al8i4[6] = (long)var36;
this.rowsProcessed = 0;
this.aFetchWasDone = false;
this.rxd.setNumberOfColumns(this.definesLength);
if ((this.options & 64L) != 0L && (this.options & 32L) == 0L && (this.options & 1L) == 0L && (this.options & 8L) == 0L && (this.options & 16L) == 0L && !this.oracleStatement.needToSendOalToFetch) {
this.setFunCode((short)5);
} else {
this.setFunCode((short)94);
}
this.nonFatalIOExceptions = null;
this.doRPC(); //执行查询
if ((this.options & 32L) != 0L) {
this.oracleStatement.inScn = 0L;
}
this.ibtBindIndicators = null;
this.ibtBindChars = null;
this.ibtBindBytes = null;
this.tmpBindsByteArray = null;
this.outBindAccessors = null;
this.bindBytes = null;
this.bindChars = null;
this.bindIndicators = null;
this.oracleStatement = null;
if (this.nonFatalIOExceptions != null) {
IOException var37 = (IOException)this.nonFatalIOExceptions.get(0);
try {
SQLException var38 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), 266);
var38.fillInStackTrace();
throw var38;
} catch (SQLException var39) {
var39.initCause(var37);
throw var39;
}
}
}
}
T4CTTIfun
是上面的类的子类
abstract class T4CTTIfun extends T4CTTIMsg {
final void doRPC() throws IOException, SQLException {
if (this.getTTCCode() == 17) {
SQLException var12 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), 401);
var12.fillInStackTrace();
throw var12;
} else {
for(int var1 = 0; var1 < 5; ++var1) {
this.init();
this.marshalFunHeader();
try {
this.connection.pipeState = 1;
this.marshal();
this.connection.pipeState = 2;
this.receive(); //读数据
break;
} catch (SQLException var10) {
SQLException var2 = var10;
synchronized(this.connection.cancelInProgressLockForThin) {
if (var2.getErrorCode() == 1013 || this.connection.cancelInProgressFlag && var2.getMessage() != null && var2.getMessage().contains("ORA-01013")) {
this.connection.cancelInProgressFlag = false;
this.connection.redoCursorClose();
if ((this.funCode == 15 || this.funCode == 12 || this.funCode == 13 || this.funCode == 14 || this.funCode == 59) && (this.oer.callNumber != this.connection.currentTTCSeqNumber || this.connection.statementCancel)) {
continue;
}
}
}
throw var10;
} finally {
this.connection.pipeState = -1;
}
}
}
}
这里就是最终的从服务器读数据的方法
private void receive() throws SQLException, IOException {
this.receiveState = 1;
SQLException var1 = null;
label249:
while(true) { //循环读数据
while(true) {
try {
short var2 = this.meg.unmarshalUB1();
this.ttilist.add(new Short(var2));
switch(var2) {
case 4:
this.processEOCS();
this.oer.init();
this.oer.unmarshal();
try {
this.processError();
} catch (SQLException var14) {
var1 = var14;
}
break label249;
case 5:
case 10:
case 13:
case 17:
case 18:
case 20:
case 22:
default:
SQLException var24 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), 401, this.ttilist.toString());
var24.fillInStackTrace();
throw var24;
case 6:
this.readRXH();
this.rxhProcessed = true;
break;
case 7:
this.receiveState = 2;
if (this.readRXD()) {
this.receiveState = 3;
return;
}
this.receiveState = 1;
break;
case 8:
if (this.rpaProcessed) {
SQLException var19 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), 401);
var19.fillInStackTrace();
throw var19;
}
this.readRPA();
try {
this.processRPA();
} catch (SQLException var16) {
var1 = var16;
}
this.rpaProcessed = true;
break;
case 9:
this.processEOCS();
if (this.connection.getTTCVersion() >= 3) {
short var23 = (short)this.meg.unmarshalUB2();
this.connection.endToEndECIDSequenceNumber = var23;
}
break label249;
case 11:
this.readIOV();
this.iovProcessed = true;
break;
case 12:
this.processSLG();
break;
case 14:
this.readLOBD();
break;
case 15:
this.oer.init();
this.oer.unmarshalWarning();
try {
this.oer.processWarning();
} catch (SQLWarning var15) {
this.connection.setWarnings(DatabaseError.addSqlWarning(this.connection.getWarnings(), var15));
}
break;
case 16:
this.readDCB();
break;
case 19:
this.meg.marshalUB1((short)19);
break;
case 21:
this.readBVC();
break;
case 23:
byte var3 = (byte)this.meg.unmarshalUB1();
int var4 = this.meg.unmarshalUB2();
byte var5 = (byte)this.meg.unmarshalUB1();
int var6;
if (var3 == 1) {
for(var6 = 0; var6 < var4; ++var6) {
T4CTTIidc var22 = new T4CTTIidc(this.connection);
var22.unmarshal();
}
} else if (var3 == 2) {
for(var6 = 0; var6 < var4; ++var6) {
short var21 = this.meg.unmarshalUB1();
}
} else if (var3 != 3 && var3 != 4) {
if (var3 == 5) {
T4CTTIkvarr var20 = new T4CTTIkvarr(this.connection);
var20.unmarshal();
} else if (var3 == 6) {
for(var6 = 0; var6 < var4; ++var6) {
NTFXSEvent var7 = new NTFXSEvent(this.connection);
this.connection.notify(var7);
}
}
}
}
} catch (BreakNetException var17) {
} finally {
this.connection.sentCancel = false;
}
}
}
this.receiveState = 0;
if (var1 != null) {
throw var1;
}
}
实现原理
oracle客户端和oracle服务器通信,有oracle自己的通信协议。
stackoverflow.com/questions/3…
1、问题
In ojdbc6, T4C8Oall commonly does get the bytes from the Oracle server. T4C8Oall extends T4CTTIfun.
1) Why are are T4C8Oall and T4CTTIfun named as they are?
2) How does T4C8Oall get the bytes from the Oracle server?
3) Does T4C8Oall behave the same for all versions of Oracle servers?
2、回答
1) These names are defined in the TTC protocol which isn't a publicly documented protocol. TTC (Two Task Common) is the protocol used by the Oracle Database server and is implemented by OCI (in C) and in the Oracle JDBC thin driver (in Java).
2) T4C8Oall gets the bytes from the Oracle server through this protocol. The rows are shipped one after the other in a single roundtrip.
3) T4C8Oall doesn't behave the same way for all versions of the Oracle servers. Newer versions will have additional data. The protocol is versioned and the version is negotiated during connection establishment.
调用栈
receive:403, T4CTTIfun (oracle.jdbc.driver)
doRPC:227, T4CTTIfun (oracle.jdbc.driver)
doOALL:531, T4C8Oall (oracle.jdbc.driver)
doOall8:195, T4CStatement (oracle.jdbc.driver)
executeForDescribe:876, T4CStatement (oracle.jdbc.driver)
executeMaybeDescribe:1175, OracleStatement (oracle.jdbc.driver)
doExecuteWithTimeout:1288, OracleStatement (oracle.jdbc.driver)
executeQuery:1498, OracleStatement (oracle.jdbc.driver)
executeQuery:406, OracleStatementWrapper (oracle.jdbc.driver)
isValidConnection:84, OracleValidConnectionChecker (com.alibaba.druid.pool.vendor)
validateConnection:1386, DruidAbstractDataSource (com.alibaba.druid.pool)
shrink:3146, DruidDataSource (com.alibaba.druid.pool)
run:2875, DruidDataSource$DestroyTask (com.alibaba.druid.pool)
run:2859, DruidDataSource$DestroyConnectionThread (com.alibaba.druid.pool)