Beispiel #1
0
    /**
     * Create a driver Error from an java.sql.SQLException, that displays the
     * sql statement/query.
     *
     * @param runtime
     * @param errorName
     * @param exception
     * @param statement
     * @return
     */
    public static RaiseException newDriverError(Ruby runtime, String errorName,
            SQLException exception, java.sql.Statement statement)
    {
        RubyClass driverError = runtime.getClass(errorName);
        int code = exception.getErrorCode();
        StringBuffer sb = new StringBuffer("(");

        // Append the Vendor Code, if there is one
        // TODO: parse vendor exception codes
        // TODO: replace 'vendor' with vendor name
        if (code > 0) sb.append("vendor_errno=").append(code).append(", ");
        sb.append("sql_state=").append(exception.getSQLState()).append(") ");
        sb.append(exception.getLocalizedMessage());
        // TODO: delegate to the DriverDefinition for this
        if (statement != null) sb.append("\nQuery: ").append(statement.toString());

        return new RaiseException(runtime, driverError, sb.toString(), true);
    }
  public Object invoke(Method method, Object[] args) throws Throwable {

    final String methodName = method.getName();

    if (!METHODS_TO_INTERCEPT.contains(methodName)) {
      return MethodUtils.proceedExecution(method, stmt, args);
    }

    // special treat for toString method
    if ("toString".equals(methodName)) {
      final StringBuilder sb = new StringBuilder();
      sb.append(stmt.getClass().getSimpleName());
      sb.append(" [");
      sb.append(stmt.toString());
      sb.append("]");
      return sb.toString(); // differentiate toString message.
    } else if ("getDataSourceName".equals(methodName)) {
      return dataSourceName;
    } else if ("getTarget".equals(methodName)) {
      // ProxyJdbcObject interface has method to return original object.
      return stmt;
    }

    if (StatementMethodNames.JDBC4_METHODS.contains(methodName)) {
      final Class<?> clazz = (Class<?>) args[0];
      if ("unwrap".equals(methodName)) {
        return stmt.unwrap(clazz);
      } else if ("isWrapperFor".equals(methodName)) {
        return stmt.isWrapperFor(clazz);
      }
    }

    if (StatementMethodNames.GET_CONNECTION_METHOD.contains(methodName)) {
      return connectionProxy;
    }

    if ("addBatch".equals(methodName) || "clearBatch".equals(methodName)) {
      if ("addBatch".equals(methodName) && ObjectArrayUtils.isFirstArgString(args)) {
        final QueryTransformer queryTransformer = interceptorHolder.getQueryTransformer();
        final String query = (String) args[0];
        final Class<? extends Statement> clazz = Statement.class;
        final int batchCount = batchQueries.size();
        final TransformInfo transformInfo =
            new TransformInfo(clazz, dataSourceName, query, true, batchCount);
        final String transformedQuery = queryTransformer.transformQuery(transformInfo);
        args[0] = transformedQuery; // replace to the new query
        batchQueries.add(transformedQuery);
      } else if ("clearBatch".equals(methodName)) {
        batchQueries.clear();
      }

      // proceed execution, no need to call listener
      try {
        return method.invoke(stmt, args);
      } catch (InvocationTargetException ex) {
        throw ex.getTargetException();
      }
    }

    List<QueryInfo> queries;
    boolean isBatchExecute = false;
    int batchSize = 0;

    if (StatementMethodNames.BATCH_EXEC_METHODS.contains(methodName)) {

      queries = new ArrayList<QueryInfo>(batchQueries.size());
      for (String batchQuery : batchQueries) {
        queries.add(new QueryInfo(batchQuery));
      }
      batchSize = batchQueries.size();
      batchQueries.clear();
      isBatchExecute = true;
      queries = Collections.unmodifiableList(queries);
    } else if (StatementMethodNames.QUERY_EXEC_METHODS.contains(methodName)
        && ObjectArrayUtils.isFirstArgString(args)) {
      final QueryTransformer queryTransformer = interceptorHolder.getQueryTransformer();
      final String query = (String) args[0];
      final TransformInfo transformInfo =
          new TransformInfo(Statement.class, dataSourceName, query, false, 0);
      final String transformedQuery = queryTransformer.transformQuery(transformInfo);
      args[0] = transformedQuery; // replace to the new query
      queries = Collections.singletonList(new QueryInfo(transformedQuery, null));
    } else {
      queries = Collections.emptyList();
    }

    final QueryExecutionListener listener = interceptorHolder.getListener();
    final ExecutionInfoBuilder execInfoBuilder =
        ExecutionInfoBuilder.create()
            .dataSourceName(dataSourceName)
            .batch(isBatchExecute)
            .batchSize(batchSize)
            .method(method)
            .methodArgs(args)
            .statement(stmt);
    listener.beforeQuery(execInfoBuilder.build(), queries);

    // Invoke method on original Statement.
    try {
      final TimeProvider timeProvider = connectionProxy.getTimeProvider();
      final long beforeTime = timeProvider.getCurrentTime();
      Object retVal;
      try {
        retVal = method.invoke(stmt, args);
      } finally {
        final long afterTime = timeProvider.getCurrentTime();
        execInfoBuilder.elapsedTime(afterTime - beforeTime, timeProvider.getTimeUnit());
      }

      execInfoBuilder.result(retVal);
      execInfoBuilder.success(true);

      return retVal;
    } catch (InvocationTargetException ex) {
      execInfoBuilder.throwable(ex.getTargetException());
      execInfoBuilder.success(false);
      throw ex.getTargetException();
    } finally {
      listener.afterQuery(execInfoBuilder.build(), queries);
    }
  }