【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;
    }
posted @ 2017-01-08 00:19  淡丶无欲  阅读(10975)  评论(0编辑  收藏  举报