【spring】(填坑)sql注入攻擊 - 持久層參數化


結果

    填坑失敗,並沒有看懂是如何檢測sql攻擊的。

   只能說的是: 建議都使用參數化傳遞sql語句參數。(所以,用hibernate、mybatis等框架的真不用太擔心sql攻擊問題。)

前言

  本文主要是為了填坑:【spring】jdbcTemplate之sql參數注入

在上文中的demo是:

  正確sql:

  select c.child_id childId,c.child_name,c.child_age childAge,c.parent_id parentId from child c where c.child_id= '1'

攻擊sql:

  select c.child_id childId,c.child_name,c.child_age childAge,c.parent_id parentId from child c where c.child_id= '1';delete from child where child_id='1';--'

執行拋出的異常:

java.sql.SQLException: ORA-00911: 無效字符
	at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:439)
	at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:395)
	at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:802)
	at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:436)
	at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
	at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:521)
	at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:205)
	at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:861)
	at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1145)
	at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1267)
	at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3449)
	at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3493)
	at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1203)
	at com.vergilyn.test.sh.dao.JdbcTemplateDao.injectionAttack(JdbcTemplateDao.java:49)
	at com.lyn.Junit.TestJdbc.testInjectionAttack(TestJdbc.java:35)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)

最后給出的錯誤結論oracle驅動jar中處理對sql注入攻擊進行了處理。

為什么會得出錯誤結論:

  1、肯定是技術不過關、分析不仔細。

  2、沒有嚴格去驗證,單純的測試了jdbc、jdbcTemplate、Hibernate就得出了此結論。

異常原因:

  根據異常提示,我去看了下ojdbc5.jar中的源碼。  即核心是oracle/jdbc/driver/T4CMAREngine.class中的unmarshalUB2()、buffer2Value(byte var)。

  主要是在buffer2Value()方法返回long的值是911,然后ojdbc在后面根據此值拋出以上異常。

  表示實在看不懂buffer2Value()及其內部含義,但簡單理解就是在攻擊sql中出現了”;”分號,導致拋出此異常。

一、驗證非參數話會存在sql注入攻擊(jdbcTemplate測試)

    @Test
    @Rollback()
    public void testSqlInjectionAttack(){ //結論: jdbcTemplate不用參數化會存在sql攻擊問題。
        String id = "1";        //正確參數
//        id = "1' or 1=1 --";    //sql攻擊參數
        Object rs = jdbcDao.sqlInjectionAttack(id);
       System.out.println(JSON.toJSONString(rs));
    }
  public Object sqlInjectionAttack(String id){
        String sql = "select c.child_id childId,c.child_name,c.child_age childAge,c.parent_id parentId from child c";
        sql += " where c.child_id= '"+id+"'";
        return this.jdbcTemplate.query(sql,new BeanPropertyRowMapper<Child>(Child.class));
    }

說明:1、正確的是返回一個Child對象。攻擊sql則返回List<Child>對象。

  2、用的方法是query(…)。如果是queryForXXX(…),可能會拋異常:org.springframework.dao.IncorrectResultSizeDataAccessException: Incorrect result size: expected 1, actual 10

sql攻擊結果:
image

二、驗證參數化查詢防止sql注入攻擊

    @Test
    @Rollback()
    public void solveSqlInjectionAttack(){ //參數化sql防止sql注入攻擊
        String id = "1";        //正確參數
//        id = "1' or 1=1 --";    //sql攻擊參數
        Object rs = jdbcTemplateDao.solveSqlInjectionAttack(id);
       System.out.println(JSON.toJSONString(rs));
    }
  public Object solveSqlInjectionAttack(String id){
        String sql = "select c.child_id childId,c.child_name,c.child_age childAge,c.parent_id parentId from child c";
        sql += " where c.child_id= ?";
        return this.jdbcTemplate.query(sql,new Object[]{id},new BeanPropertyRowMapper<Child>(Child.class));
    }

正確sql結果:

image

攻擊sql結果:

信息: Rolled back transaction for test context [DefaultTestContext@1cfddcd testClass = JdbcTemplateTest, testInstance = com.vergilyn.persistence.test.jdbcTemplate.JdbcTemplateTest@1ead226, testMethod = solveSqlInjectionAttack@JdbcTemplateTest, testException = org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [select c.child_id childId,c.child_name,c.child_age childAge,c.parent_id parentId from child c where c.child_id= ?]; ORA-01722: 無效數字
; nested exception is java.sql.SQLException: ORA-01722: 無效數字
, mergedContextConfiguration = [MergedContextConfiguration@18add92 testClass = JdbcTemplateTest, locations = '{classpath:jdbcTemplate/jdbcTemplate-context.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]].

十二月 31, 2016 12:42:03 上午 org.springframework.context.support.AbstractApplicationContext doClose
信息: Closing org.springframework.context.support.GenericApplicationContext@1f12030: startup date [Sat Dec 31 00:41:44 CST 2016]; root of context hierarchy

org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [select c.child_id childId,c.child_name,c.child_age childAge,c.parent_id parentId from child c where c.child_id= ?]; ORA-01722: 無效數字
; nested exception is java.sql.SQLException: ORA-01722: 無效數字
	at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:243)
	at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
	at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:660)
	at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:695)
	at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:727)
	at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:737)
	at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:787)
	at com.vergilyn.persistence.jdbcTemplate.JdbcTemplateDao.solveSqlInjectionAttack(JdbcTemplateDao.java:42)
	at com.vergilyn.persistence.test.jdbcTemplate.JdbcTemplateTest.solveSqlInjectionAttack(JdbcTemplateTest.java:30)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:73)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:73)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:224)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
Caused by: java.sql.SQLException: ORA-01722: 無效數字

	at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:439)
	at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:395)
	at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:802)
	at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:436)
	at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
	at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:521)
	at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:205)
	at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:861)
	at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1145)
	at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1267)
	at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3449)
	at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3493)
	at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1203)
	at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
	at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
	at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
	at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:703)
	at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:644)
	... 34 more
異常信息

以上結果是因為,數據庫中的CHILD_ID的類型是NUMBER,傳入的參數卻是String。

當我把CHILD_ID的類型修改為:varchar2時,sql可正常執行。但sql查詢結果是null。因為,數據庫記錄中並沒有一個CHILD_ID = ”1' or 1=1 --“

三、部分源碼 (填坑失敗,后面的代碼邏輯實在難看懂。)

       /**
	 * Query using a prepared statement, allowing for a PreparedStatementCreator
	 * and a PreparedStatementSetter. Most other query methods use this method,
	 * but application code will always work with either a creator or a setter.
	 * @param psc Callback handler that can create a PreparedStatement given a
	 * Connection
	 * @param pss object that knows how to set values on the prepared statement.
	 * If this is null, the SQL will be assumed to contain no bind parameters.
	 * @param rse object that will extract results.
	 * @return an arbitrary result object, as returned by the ResultSetExtractor
	 * @throws DataAccessException if there is any problem
	 */
	public <T> T query(
			PreparedStatementCreator psc, final PreparedStatementSetter pss, final ResultSetExtractor<T> rse)
			throws DataAccessException {

		Assert.notNull(rse, "ResultSetExtractor must not be null");
		logger.debug("Executing prepared SQL query");

		return execute(psc, new PreparedStatementCallback<T>() { //line:695 
			@Override
			public T doInPreparedStatement(PreparedStatement ps) throws SQLException {
				ResultSet rs = null;
				try {
					if (pss != null) {
						pss.setValues(ps);
					}
					rs = ps.executeQuery(); // 拋出異常方法 - 02 					
                                                         ResultSet rsToUse = rs;
					if (nativeJdbcExtractor != null) {
						rsToUse = nativeJdbcExtractor.getNativeResultSet(rs);
					}
					return rse.extractData(rsToUse);
				}
				finally {
					JdbcUtils.closeResultSet(rs);
					if (pss instanceof ParameterDisposer) {
						((ParameterDisposer) pss).cleanupParameters();
					}
				}
			}
		});
	}
            //-------------------------------------------------------------------------
	// Methods dealing with prepared statements
	//-------------------------------------------------------------------------
           @Override
	public <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action)
			throws DataAccessException {

		Assert.notNull(psc, "PreparedStatementCreator must not be null");
		Assert.notNull(action, "Callback object must not be null");
		if (logger.isDebugEnabled()) {
			String sql = getSql(psc);
			logger.debug("Executing prepared SQL statement" + (sql != null ? " [" + sql + "]" : ""));
		}

		Connection con = DataSourceUtils.getConnection(getDataSource());
		PreparedStatement ps = null;
		try {
			Connection conToUse = con;
			if (this.nativeJdbcExtractor != null &&
					this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativePreparedStatements()) {
				conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
			}
			ps = psc.createPreparedStatement(conToUse);
			applyStatementSettings(ps);
			PreparedStatement psToUse = ps;
			if (this.nativeJdbcExtractor != null) {
				psToUse = this.nativeJdbcExtractor.getNativePreparedStatement(ps);
			}
			T result = action.doInPreparedStatement(psToUse);  // 拋出異常方法 - 01
			handleWarnings(ps);
			return result;
		}
		catch (SQLException ex) {
			// Release Connection early, to avoid potential connection pool deadlock
			// in the case when the exception translator hasn't been initialized yet.
			if (psc instanceof ParameterDisposer) {
				((ParameterDisposer) psc).cleanupParameters();
			}
			String sql = getSql(psc);
			psc = null;
			JdbcUtils.closeStatement(ps);
			ps = null;
			DataSourceUtils.releaseConnection(con, getDataSource());
			con = null;
			throw getExceptionTranslator().translate("PreparedStatementCallback", sql, ex); //line: 660
		}
		finally {
			if (psc instanceof ParameterDisposer) {
				((ParameterDisposer) psc).cleanupParameters();
			}
			JdbcUtils.closeStatement(ps);
			DataSourceUtils.releaseConnection(con, getDataSource());
		}
	}

其中拋異常的方法是: at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:660)

  方法中的>>>> T result = action.doInPreparedStatement(psToUse);
image

此處的action.doInPreparedStatement(psToUse)實際調用的就是上面 - 匿名內部類中定義的。

// 拋出異常 - 02 代碼 
public ResultSet executeQuery() throws SQLException {
        this.checkOpen();
        try {
            return DelegatingResultSet.wrapResultSet(this, ((PreparedStatement)this._stmt).executeQuery());
        } catch (SQLException var2) {
            this.handleException(var2);
            throw new AssertionError();
        }
    }

出現異常方法:((PreparedStatement)this._stmt).executeQuery()。  this._stmt = OraclePreparedStatementWrapper.class

// OraclePreparedStatementWrapper.class 
public ResultSet executeQuery() throws SQLException {
        return this.preparedStatement.executeQuery(); //this.preparedStatement = T4CPreparedStatement.class 
    }
class T4CPreparedStatement extends OraclePreparedStatement;  
// OraclePreparedStatement.class
public ResultSet executeQuery() throws SQLException {
    PhysicalConnection var1 = this.connection;
    synchronized(this.connection) {
        this.executionType = 1;
        this.executeInternal(); // 異常方法 - 03
        if(this.userRsetType == 1) {
            this.currentResultSet = new OracleResultSetImpl(this.connection, this);
            return this.currentResultSet;
        } else {
            if(this.scrollRset == null) {
                this.currentResultSet = new OracleResultSetImpl(this.connection, this);
                this.scrollRset = this.currentResultSet;
            }
            return this.scrollRset;
        }
    }
}

int executeInternal() throws SQLException {
        this.noMoreUpdateCounts = false;
        this.ensureOpen();
        if(this.currentRank > 0 && this.m_batchStyle == 2) {
            SQLException var3 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), 81, "batch must be either executed or cleared");
            var3.fillInStackTrace();
            throw var3;
        } else {
            boolean var1 = this.userRsetType == 1;
            this.prepareForNewResults(true, false);
            this.processCompletedBindRow(this.sqlKind == 0?1:this.batch, false);
            if(!var1 && !this.scrollRsetTypeSolved) {
                return this.doScrollPstmtExecuteUpdate() + this.prematureBatchCount;
            } else {
                this.doExecuteWithTimeout(); // 異常方法 - 04
                boolean var2 = this.prematureBatchCount != 0 && this.validRows > 0;
                if(!var1) {
                    this.currentResultSet = new OracleResultSetImpl(this.connection, this);
                    this.scrollRset = ResultSetUtil.createScrollResultSet(this, this.currentResultSet, this.realRsetType);
                    if(!this.connection.accumulateBatchResult) {
                        var2 = false;
                    }
                }

                if(var2) {
                    this.validRows += this.prematureBatchCount;
                    this.prematureBatchCount = 0;
                }

                return this.validRows;
            }
        }
    }
void doExecuteWithTimeout() throws SQLException {
        try {
            this.cleanOldTempLobs();
            this.connection.registerHeartbeat();
            this.rowsProcessed = 0;
            SQLException var1;
            if(this.sqlKind == 0) {
                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(); // 異常方法 - 05
                }

                this.checkValidRowsStatus();
                if(this.serverCursor) {
                    this.adjustGotLastBatch();
                }
            } else {
                if(this.connection.j2ee13Compliant && this.sqlKind != 1 && this.sqlKind != 4 && this.executionType == 1) {
                    var1 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), 128);
                    var1.fillInStackTrace();
                    throw var1;
                }

                ++this.currentRank;
                if(this.currentRank >= this.batch) {
                    try {
                        this.connection.needLine();
                        if(!this.isOpen) {
                            this.connection.open(this);
                            this.isOpen = true;
                        }

                        if(this.queryTimeout != 0) {
                            this.connection.getTimeout().setTimeout((long)(this.queryTimeout * 1000), this);
                        }

                        this.isExecuting = true;
                        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.isExecuting = false;
                        this.checkValidRowsStatus();
                    }
                }
            }
        } catch (SQLException var16) {
            this.resetOnExceptionDuringExecute();
            throw var16;
        }

        this.connection.registerHeartbeat();
    }
void executeMaybeDescribe() throws SQLException
  {
    int i = 1;
    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 = (!checkAccessorsUsable());
      }
    }
    boolean bool = false;
    try
    {
      this.isExecuting = true;
      if (this.needToPrepareDefineBuffer)
      {
        if (!this.columnsDefinedByUser)
        {
          executeForDescribe();// 異常方法 – 06 實際是調用T4CPreparedStatement.class中的實現方法
          bool = true;
          if (this.aFetchWasDoneDuringDescribe) {
            i = 0;
          }
        }
        if (this.needToPrepareDefineBuffer)
        {
          prepareAccessors();
        }
      }

      int j = this.accessors.length;
      for (int k = this.numberOfDefinePositions; k < j; k++)
      {
        Accessor localAccessor = this.accessors[k];
        if (localAccessor != null)
          localAccessor.rowSpaceIndicator = null;
      }
      if (i != 0) {
        executeForRows(bool);
      }
    }
    catch (SQLException localSQLException)
    {
      this.needToParse = true;
      throw localSQLException;
    }
    finally
    {
      this.isExecuting = false;
    }
  }
// T4CPreparedStatement.class
void executeForDescribe() throws SQLException {
        this.t4Connection.assertLoggedOn("oracle.jdbc.driver.T4CPreparedStatement.execute_for_describe");
        this.cleanOldTempLobs();

        try {
            if(this.t4Connection.useFetchSizeWithLongColumn) {
                this.doOall8(true, true, true, true, false);
            } else {
                this.doOall8(true, true, false, true, this.definedColumnType != null);// 異常 - 07
            }
        } catch (SQLException var8) {
            throw var8;  // ORA-01722: 無效數字
        } catch (IOException var9) {
            ((T4CConnection)this.connection).handleIOException(var9);
            SQLException var2 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), var9);
            var2.fillInStackTrace();
            throw var2;
        } finally {
            this.rowsProcessed = this.t4Connection.all8.rowsProcessed;
            this.validRows = this.t4Connection.all8.getNumRows();
        }

        this.needToParse = false;
        this.implicitDefineForLobPrefetchDone = false;
        this.aFetchWasDoneDuringDescribe = false;
        if(this.t4Connection.all8.aFetchWasDone) {
            this.aFetchWasDoneDuringDescribe = true;
            this.rowPrefetchInLastFetch = this.rowPrefetch;
        }

        for(int var1 = 0; var1 < this.numberOfDefinePositions; ++var1) {
            this.accessors[var1].initMetadata();
        }

        this.needToPrepareDefineBuffer = false;
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM