private void checkSQL(ExecuteContext ctx, boolean patched) {
            assertTrue(ctx.batchSQL()[0].toLowerCase().contains("insert"));

            if (patched) {
                assertTrue(ctx.batchSQL()[0].toLowerCase().contains("values    ("));
            }
        }
        @Override
        public void renderStart(ExecuteContext ctx) {
            renderStart = ++callbackCount;
            checkBase(ctx);

            assertNull(ctx.batchSQL()[0]);
            assertNull(ctx.sql());
            assertNull(ctx.statement());
        }
        private void checkSQL(ExecuteContext ctx, boolean patched) {
            assertTrue(ctx.batchSQL()[0].toLowerCase().contains("select"));
            assertTrue(ctx.sql().toLowerCase().contains("select"));
            assertEquals(ctx.sql(), ctx.batchSQL()[0]);

            if (patched) {
                assertTrue(ctx.sql().toLowerCase().contains("as my_field"));
            }
        }
        private void checkSQL(ExecuteContext ctx, boolean patched) {
            for (int i = 0; i < rendered; i++) {
                assertTrue(ctx.batchQueries()[i].toString().toLowerCase().contains("insert"));

                if (patched) {
                    assertTrue(ctx.batchSQL()[i].toLowerCase().contains("values    ("));
                }
            }
        }
  @Override
  public void exception(ExecuteContext ctx) {
    SQLDialect dialect = ctx.configuration().dialect();
    SQLExceptionTranslator translator =
        (dialect != null)
            ? new SQLErrorCodeSQLExceptionTranslator(dialect.name())
            : new SQLStateSQLExceptionTranslator();

    ctx.exception(translator.translate("jOOQ", ctx.sql(), ctx.sqlException()));
  }
  @Override
  protected final void prepare(ExecuteContext ctx) throws SQLException {

    // [#1296] These dialects do not implement FOR UPDATE. But the same
    // effect can be achieved using ResultSet.CONCUR_UPDATABLE
    if (isForUpdate() && asList(CUBRID, SQLSERVER).contains(ctx.getDialect())) {
      ctx.statement(
          ctx.getConnection().prepareStatement(ctx.sql(), TYPE_SCROLL_SENSITIVE, CONCUR_UPDATABLE));
    }

    // Regular behaviour
    else {
      ctx.statement(ctx.getConnection().prepareStatement(ctx.sql()));
    }

    // [#1263] Allow for negative fetch sizes to support some non-standard
    // MySQL feature, where Integer.MIN_VALUE is used
    if (size != 0) {
      if (log.isDebugEnabled()) log.debug("Setting fetch size", size);

      ctx.statement().setFetchSize(size);
    }

    // [#1854] Set the max number of rows for this result query
    if (maxRows != 0) {
      ctx.statement().setMaxRows(maxRows);
    }
  }
        @Override
        public void bindEnd(ExecuteContext ctx) {
            bindEnd = ++callbackCount;
            checkBase(ctx);
            checkSQL(ctx, true);
            checkStatement(ctx, true);

            assertNull(ctx.resultSet());
            assertNull(ctx.record());
            assertNull(ctx.result());
        }
        @Override
        public void renderEnd(ExecuteContext ctx) {
            renderEnd.add(++callbackCount);
            rendered++;
            checkBase(ctx);
            checkStatement(ctx, false);
            checkSQL(ctx, false);

            ctx.batchSQL()[rendered - 1] = ctx.batchSQL()[rendered - 1].replaceFirst("(?i:values\\s+)", "values    ");
            checkSQL(ctx, true);
        }
        @Override
        public void fetchStart(ExecuteContext ctx) {
            fetchStart = ++callbackCount;
            checkBase(ctx);
            checkSQL(ctx, true);
            checkStatement(ctx, true);
            checkResultSet(ctx, true);

            assertNull(ctx.record());
            assertNull(ctx.result());
        }
        @Override
        public void renderEnd(ExecuteContext ctx) {
            renderEnd = ++callbackCount;
            checkBase(ctx);
            checkSQL(ctx, false);

            assertNull(ctx.statement());

            ctx.sql(ctx.sql().replaceFirst("(?i:values\\s+)", "values    "));
            checkSQL(ctx, true);
        }
Exemple #11
0
  /**
   * Default implementation for query execution using a prepared statement. Subclasses may override
   * this method.
   */
  protected int execute(ExecuteContext ctx, ExecuteListener listener) throws SQLException {
    int result = 0;
    listener.executeStart(ctx);

    if (!ctx.statement().execute()) {
      result = ctx.statement().getUpdateCount();
      ctx.rows(result);
    }

    listener.executeEnd(ctx);
    return result;
  }
        @Override
        public void end(ExecuteContext ctx) {
            end = ++callbackCount;
            checkBase(ctx);
            checkSQL(ctx, true);
            checkStatement(ctx, true);
            checkResultSet(ctx, true);
            assertNotNull(ctx.record());
            assertEquals(2, ctx.record().fieldsRow().size());

            assertNotNull(ctx.result());
            assertEquals(2, ctx.result().size());
        }
        @Override
        public void executeEnd(ExecuteContext ctx) {
            executeEnd = ++callbackCount;
            checkBase(ctx);
            checkSQL(ctx, true);
            checkStatement(ctx, true);

            checkResultSet(ctx, false);
            // TODO patch result set
            checkResultSet(ctx, true);

            assertNull(ctx.record());
            assertNull(ctx.result());
        }
        @Override
        public void recordEnd(ExecuteContext ctx) {
            recordEnd.add(++callbackCount);
            checkBase(ctx);
            checkSQL(ctx, true);
            checkStatement(ctx, true);
            checkResultSet(ctx, true);

            assertNotNull(ctx.record());
            assertEquals(2, ctx.record().fieldsRow().size());

            assertEquals(ids.remove(), ctx.record().getValue(0));
            assertEquals("Hello", ctx.record().getValue(1));
        }
        @Override
        public void prepareStart(ExecuteContext ctx) {
            prepareStart = ++callbackCount;
            checkBase(ctx);
            checkSQL(ctx, true);

            assertNull(ctx.statement());
        }
        @Override
        public void renderStart(ExecuteContext ctx) {
            renderStart.add(++callbackCount);
            checkBase(ctx);
            checkStatement(ctx, false);
            checkSQL(ctx, false);

            assertNull(ctx.sql());
        }
Exemple #17
0
  /** Workarounds for the unimplemented Postgres JDBC driver features */
  @SuppressWarnings("unchecked")
  private static <T> T pgGetArray(ExecuteContext ctx, Class<? extends T> type, int index)
      throws SQLException {

    ResultSet rs = ctx.resultSet();

    // Get the JDBC Array and check for null. If null, that's OK
    Array array = rs.getArray(index);
    if (array == null) {
      return null;
    }

    // Try fetching a Java Object[]. That's gonna work for non-UDT types
    try {
      return (T) convertArray(rs.getArray(index), (Class<? extends Object[]>) type);
    }

    // This might be a UDT (not implemented exception...)
    catch (Exception e) {
      List<Object> result = new ArrayList<Object>();

      // Try fetching the array as a JDBC ResultSet
      try {
        ctx.resultSet(array.getResultSet());
        while (ctx.resultSet().next()) {
          result.add(getFromResultSet(ctx, type.getComponentType(), 2));
        }
      }

      // That might fail too, then we don't know any further...
      catch (Exception fatal) {
        log.error("Cannot parse Postgres array: " + rs.getString(index));
        log.error(fatal);
        return null;
      } finally {
        ctx.resultSet(rs);
      }

      return (T) convertArray(result.toArray(), (Class<? extends Object[]>) type);
    }
  }
  @Override
  public final Result<R> fetch(int number) {
    // [#1157] This invokes listener.fetchStart(ctx), which has to be called
    // Before listener.resultStart(ctx)
    iterator();

    ResultImpl<R> result = new ResultImpl<R>(ctx.configuration(), fields);
    R record = null;

    ctx.result(result);
    listener.resultStart(ctx);

    for (int i = 0; i < number && ((record = iterator().next()) != null); i++) {
      result.addRecord(record);
    }

    ctx.result(result);
    listener.resultEnd(ctx);

    return result;
  }
Exemple #19
0
 private final String getSQL0(ExecuteContext ctx) {
   if (executePreparedStatements(configuration().settings())) {
     try {
       RenderContext render = new DefaultRenderContext(configuration);
       render.data(DATA_COUNT_BIND_VALUES, true);
       return render.render(this);
     } catch (DefaultRenderContext.ForceInlineSignal e) {
       ctx.data(DATA_FORCE_STATIC_STATEMENT, true);
       return getSQL(INLINED);
     }
   } else {
     return getSQL(INLINED);
   }
 }
Exemple #20
0
  private final Rendered getSQL0(ExecuteContext ctx) {
    Rendered result;

    // [#3542] [#4977] Some dialects do not support bind values in DDL statements
    if (ctx.type() == DDL) {
      ctx.data(DATA_FORCE_STATIC_STATEMENT, true);
      result = new Rendered(getSQL(INLINED));
    } else if (executePreparedStatements(configuration().settings())) {
      try {
        DefaultRenderContext render = new DefaultRenderContext(configuration);
        render.data(DATA_COUNT_BIND_VALUES, true);
        render.visit(this);
        result = new Rendered(render.render(), render.bindValues());
      } catch (DefaultRenderContext.ForceInlineSignal e) {
        ctx.data(DATA_FORCE_STATIC_STATEMENT, true);
        result = new Rendered(getSQL(INLINED));
      }
    } else {
      result = new Rendered(getSQL(INLINED));
    }

    return result;
  }
Exemple #21
0
  /**
   * Default implementation for query execution using a prepared statement. Subclasses may override
   * this method.
   */
  protected int execute(ExecuteContext ctx, ExecuteListener listener) throws SQLException {
    int result = 0;
    PreparedStatement stmt = ctx.statement();

    try {
      listener.executeStart(ctx);

      // [#1829] Statement.execute() is preferred over Statement.executeUpdate(), as
      // we might be executing plain SQL and returning results.
      if (!stmt.execute()) {
        result = stmt.getUpdateCount();
        ctx.rows(result);
      }

      listener.executeEnd(ctx);
      return result;
    }

    // [#3011] [#3054] Consume additional exceptions if there are any
    catch (SQLException e) {
      consumeExceptions(ctx.configuration(), stmt, e);
      throw e;
    }
  }
        @Override
        public void start(ExecuteContext ctx) {
            start = ++callbackCount;
            checkBase(ctx);

            assertNull(ctx.batchSQL()[0]);
            assertNull(ctx.sql());
            assertNull(ctx.statement());
            assertNull(ctx.resultSet());
            assertNull(ctx.record());
            assertNull(ctx.result());
        }
        @Override
        public void renderEnd(ExecuteContext ctx) {
            renderEnd = ++callbackCount;
            checkBase(ctx);
            checkSQL(ctx, false);

            assertNull(ctx.statement());
            assertNull(ctx.resultSet());
            assertNull(ctx.record());
            assertNull(ctx.result());

            ctx.sql(ctx.sql().replaceFirst("(?i:from)", "as my_field from"));
            checkSQL(ctx, true);
        }
Exemple #24
0
  @Override
  protected final int execute(ExecuteContext ctx, ExecuteListener listener) throws SQLException {
    if (returning.isEmpty()) {
      return super.execute(ctx, listener);
    } else {
      int result = 1;
      ResultSet rs;
      switch (ctx.configuration().dialect()) {

          // SQLite can select _rowid_ after the insert
        case SQLITE:
          {
            listener.executeStart(ctx);
            result = ctx.statement().executeUpdate();
            listener.executeEnd(ctx);

            DSLContext create =
                DSL.using(ctx.connection(), SQLDialect.SQLITE, ctx.configuration().settings());
            returned =
                create
                    .select(returning)
                    .from(getInto())
                    .where(rowid().equal(rowid().getDataType().convert(create.lastID())))
                    .fetchInto(getInto());

            return result;
          }

          // Sybase can select @@identity after the insert
          // TODO [#832] Fix this. This might be a driver issue. JDBC
          // Generated keys don't work with jconn3, but they seem to work
          // with jTDS (which is used for Sybase ASE integration)
        case CUBRID:
        case SYBASE:
          {
            listener.executeStart(ctx);
            result = ctx.statement().executeUpdate();
            listener.executeEnd(ctx);

            selectReturning(ctx.configuration(), create(ctx.configuration()).lastID());
            return result;
          }

          // Some dialects can only retrieve "identity" (AUTO_INCREMENT) values
          // Additional values have to be fetched explicitly
          // [#1260] TODO CUBRID supports this, but there's a JDBC bug
        case ASE:
        case DERBY:
        case H2:
        case INGRES:
        case MYSQL:
        case SQLSERVER:
          {
            listener.executeStart(ctx);
            result = ctx.statement().executeUpdate();
            listener.executeEnd(ctx);

            rs = ctx.statement().getGeneratedKeys();

            try {
              List<Object> list = new ArrayList<Object>();

              // Some JDBC drivers seem to illegally return null
              // from getGeneratedKeys() sometimes
              if (rs != null) {
                while (rs.next()) {
                  list.add(rs.getObject(1));
                }
              }

              selectReturning(ctx.configuration(), list.toArray());
              return result;
            } finally {
              JDBCUtils.safeClose(rs);
            }
          }

          // Firebird and Postgres can execute the INSERT .. RETURNING
          // clause like a select clause. JDBC support is not implemented
          // in the Postgres JDBC driver
        case FIREBIRD:
        case POSTGRES:
          {
            listener.executeStart(ctx);
            rs = ctx.statement().executeQuery();
            listener.executeEnd(ctx);

            break;
          }

          // These dialects have full JDBC support
        case DB2:
        case HSQLDB:
        case ORACLE:
        default:
          {
            listener.executeStart(ctx);
            result = ctx.statement().executeUpdate();
            listener.executeEnd(ctx);

            rs = ctx.statement().getGeneratedKeys();
            break;
          }
      }

      ExecuteContext ctx2 = new DefaultExecuteContext(ctx.configuration());
      ExecuteListener listener2 = new ExecuteListeners(ctx2);

      ctx2.resultSet(rs);
      returned =
          new CursorImpl<R>(ctx2, listener2, fieldArray(returning), null, true, false)
              .fetch()
              .into(getInto());
      return result;
    }
  }
Exemple #25
0
  @Override
  protected final void prepare(ExecuteContext ctx) throws SQLException {
    Connection connection = ctx.connection();

    // Just in case, always set Sybase ASE statement mode to return
    // Generated keys if client code wants to SELECT @@identity afterwards
    if (ctx.configuration().dialect() == SQLDialect.ASE) {
      ctx.statement(connection.prepareStatement(ctx.sql(), Statement.RETURN_GENERATED_KEYS));
      return;
    }

    // Normal statement preparing if no values should be returned
    else if (returning.isEmpty()) {
      super.prepare(ctx);
      return;
    }

    // Values should be returned from the INSERT
    else {
      switch (ctx.configuration().dialect()) {

          // Postgres uses the RETURNING clause in SQL
        case FIREBIRD:
        case POSTGRES:
          // SQLite will select last_insert_rowid() after the INSER
        case SQLITE:
          // Sybase will select @@identity after the INSERT
        case CUBRID:
        case SYBASE:
          super.prepare(ctx);
          return;

          // Some dialects can only return AUTO_INCREMENT values
          // Other values have to be fetched in a second step
          // [#1260] TODO CUBRID supports this, but there's a JDBC bug
        case ASE:
        case DERBY:
        case H2:
        case INGRES:
        case MYSQL:
        case SQLSERVER:
          ctx.statement(connection.prepareStatement(ctx.sql(), Statement.RETURN_GENERATED_KEYS));
          return;

          // The default is to return all requested fields directly
        case DB2:
        case HSQLDB:
        case ORACLE:
        default:
          {
            List<String> names = new ArrayList<String>();

            for (Field<?> field : returning) {
              names.add(field.getName());
            }

            ctx.statement(
                connection.prepareStatement(ctx.sql(), names.toArray(new String[names.size()])));
            return;
          }
      }
    }
  }
Exemple #26
0
  @SuppressWarnings("unchecked")
  public static <T> T getFromStatement(ExecuteContext ctx, Class<? extends T> type, int index)
      throws SQLException {
    CallableStatement stmt = (CallableStatement) ctx.statement();

    if (type == Blob.class) {
      return (T) stmt.getBlob(index);
    } else if (type == Boolean.class) {
      return (T) checkWasNull(stmt, Boolean.valueOf(stmt.getBoolean(index)));
    } else if (type == BigInteger.class) {
      BigDecimal result = stmt.getBigDecimal(index);
      return (T) (result == null ? null : result.toBigInteger());
    } else if (type == BigDecimal.class) {
      return (T) stmt.getBigDecimal(index);
    } else if (type == Byte.class) {
      return (T) checkWasNull(stmt, Byte.valueOf(stmt.getByte(index)));
    } else if (type == byte[].class) {
      return (T) stmt.getBytes(index);
    } else if (type == Clob.class) {
      return (T) stmt.getClob(index);
    } else if (type == Date.class) {
      return (T) stmt.getDate(index);
    } else if (type == Double.class) {
      return (T) checkWasNull(stmt, Double.valueOf(stmt.getDouble(index)));
    } else if (type == Float.class) {
      return (T) checkWasNull(stmt, Float.valueOf(stmt.getFloat(index)));
    } else if (type == Integer.class) {
      return (T) checkWasNull(stmt, Integer.valueOf(stmt.getInt(index)));
    } else if (type == Long.class) {
      return (T) checkWasNull(stmt, Long.valueOf(stmt.getLong(index)));
    } else if (type == Short.class) {
      return (T) checkWasNull(stmt, Short.valueOf(stmt.getShort(index)));
    } else if (type == String.class) {
      return (T) stmt.getString(index);
    } else if (type == Time.class) {
      return (T) stmt.getTime(index);
    } else if (type == Timestamp.class) {
      return (T) stmt.getTimestamp(index);
    } else if (type == YearToMonth.class) {
      if (ctx.getDialect() == POSTGRES) {
        Object object = stmt.getObject(index);
        return (T) (object == null ? null : PostgresUtils.toYearToMonth(object));
      } else {
        String string = stmt.getString(index);
        return (T) (string == null ? null : YearToMonth.valueOf(string));
      }
    } else if (type == DayToSecond.class) {
      if (ctx.getDialect() == POSTGRES) {
        Object object = stmt.getObject(index);
        return (T) (object == null ? null : PostgresUtils.toDayToSecond(object));
      } else {
        String string = stmt.getString(index);
        return (T) (string == null ? null : DayToSecond.valueOf(string));
      }
    } else if (type == UByte.class) {
      String string = stmt.getString(index);
      return (T) (string == null ? null : UByte.valueOf(string));
    } else if (type == UShort.class) {
      String string = stmt.getString(index);
      return (T) (string == null ? null : UShort.valueOf(string));
    } else if (type == UInteger.class) {
      String string = stmt.getString(index);
      return (T) (string == null ? null : UInteger.valueOf(string));
    } else if (type == ULong.class) {
      String string = stmt.getString(index);
      return (T) (string == null ? null : ULong.valueOf(string));
    }

    // The type byte[] is handled earlier. byte[][] can be handled here
    else if (type.isArray()) {
      return (T) convertArray(stmt.getObject(index), (Class<? extends Object[]>) type);
    } else if (ArrayRecord.class.isAssignableFrom(type)) {
      return (T) getArrayRecord(ctx, stmt.getArray(index), (Class<? extends ArrayRecord<?>>) type);
    } else if (EnumType.class.isAssignableFrom(type)) {
      return getEnumType(type, stmt.getString(index));
    } else if (MasterDataType.class.isAssignableFrom(type)) {
      return (T) getMasterDataType(type, stmt.getString(index));
    } else if (UDTRecord.class.isAssignableFrom(type)) {
      switch (ctx.getDialect()) {
        case POSTGRES:
          return (T) pgNewUDTRecord(type, stmt.getObject(index));
      }

      return (T) stmt.getObject(index, DataTypes.udtRecords());
    } else if (Result.class.isAssignableFrom(type)) {
      ResultSet nested = (ResultSet) stmt.getObject(index);
      return (T) getNewFactory(ctx).fetch(nested);
    } else {
      return (T) stmt.getObject(index);
    }
  }
Exemple #27
0
  @SuppressWarnings("unchecked")
  private static <T> T getFromResultSet(ExecuteContext ctx, Class<? extends T> type, int index)
      throws SQLException {

    ResultSet rs = ctx.resultSet();

    if (type == Blob.class) {
      return (T) rs.getBlob(index);
    } else if (type == Boolean.class) {
      return (T) checkWasNull(rs, Boolean.valueOf(rs.getBoolean(index)));
    } else if (type == BigInteger.class) {
      // The SQLite JDBC driver doesn't support BigDecimals
      if (ctx.getDialect() == SQLDialect.SQLITE) {
        return Convert.convert(rs.getString(index), (Class<? extends T>) BigInteger.class);
      } else {
        BigDecimal result = rs.getBigDecimal(index);
        return (T) (result == null ? null : result.toBigInteger());
      }
    } else if (type == BigDecimal.class) {
      // The SQLite JDBC driver doesn't support BigDecimals
      if (ctx.getDialect() == SQLDialect.SQLITE) {
        return Convert.convert(rs.getString(index), (Class<? extends T>) BigDecimal.class);
      } else {
        return (T) rs.getBigDecimal(index);
      }
    } else if (type == Byte.class) {
      return (T) checkWasNull(rs, Byte.valueOf(rs.getByte(index)));
    } else if (type == byte[].class) {
      return (T) rs.getBytes(index);
    } else if (type == Clob.class) {
      return (T) rs.getClob(index);
    } else if (type == Date.class) {
      return (T) getDate(ctx.getDialect(), rs, index);
    } else if (type == Double.class) {
      return (T) checkWasNull(rs, Double.valueOf(rs.getDouble(index)));
    } else if (type == Float.class) {
      return (T) checkWasNull(rs, Float.valueOf(rs.getFloat(index)));
    } else if (type == Integer.class) {
      return (T) checkWasNull(rs, Integer.valueOf(rs.getInt(index)));
    } else if (type == Long.class) {
      return (T) checkWasNull(rs, Long.valueOf(rs.getLong(index)));
    } else if (type == Short.class) {
      return (T) checkWasNull(rs, Short.valueOf(rs.getShort(index)));
    } else if (type == String.class) {
      return (T) rs.getString(index);
    } else if (type == Time.class) {
      return (T) getTime(ctx.getDialect(), rs, index);
    } else if (type == Timestamp.class) {
      return (T) getTimestamp(ctx.getDialect(), rs, index);
    } else if (type == YearToMonth.class) {
      if (ctx.getDialect() == POSTGRES) {
        Object object = rs.getObject(index);
        return (T) (object == null ? null : PostgresUtils.toYearToMonth(object));
      } else {
        String string = rs.getString(index);
        return (T) (string == null ? null : YearToMonth.valueOf(string));
      }
    } else if (type == DayToSecond.class) {
      if (ctx.getDialect() == POSTGRES) {
        Object object = rs.getObject(index);
        return (T) (object == null ? null : PostgresUtils.toDayToSecond(object));
      } else {
        String string = rs.getString(index);
        return (T) (string == null ? null : DayToSecond.valueOf(string));
      }
    } else if (type == UByte.class) {
      String string = rs.getString(index);
      return (T) (string == null ? null : UByte.valueOf(string));
    } else if (type == UShort.class) {
      String string = rs.getString(index);
      return (T) (string == null ? null : UShort.valueOf(string));
    } else if (type == UInteger.class) {
      String string = rs.getString(index);
      return (T) (string == null ? null : UInteger.valueOf(string));
    } else if (type == ULong.class) {
      String string = rs.getString(index);
      return (T) (string == null ? null : ULong.valueOf(string));
    }

    // The type byte[] is handled earlier. byte[][] can be handled here
    else if (type.isArray()) {
      switch (ctx.getDialect()) {
        case POSTGRES:
          {
            return pgGetArray(ctx, type, index);
          }

        default:
          // Note: due to a HSQLDB bug, it is not recommended to call rs.getObject() here:
          // See https://sourceforge.net/tracker/?func=detail&aid=3181365&group_id=23316&atid=378131
          return (T) convertArray(rs.getArray(index), (Class<? extends Object[]>) type);
      }
    } else if (ArrayRecord.class.isAssignableFrom(type)) {
      return (T) getArrayRecord(ctx, rs.getArray(index), (Class<? extends ArrayRecord<?>>) type);
    } else if (EnumType.class.isAssignableFrom(type)) {
      return getEnumType(type, rs.getString(index));
    } else if (MasterDataType.class.isAssignableFrom(type)) {
      return (T) getMasterDataType(type, rs.getObject(index));
    } else if (UDTRecord.class.isAssignableFrom(type)) {
      switch (ctx.getDialect()) {
        case POSTGRES:
          return (T) pgNewUDTRecord(type, rs.getObject(index));
      }

      return (T) rs.getObject(index, DataTypes.udtRecords());
    } else if (Result.class.isAssignableFrom(type)) {
      ResultSet nested = (ResultSet) rs.getObject(index);
      return (T) getNewFactory(ctx).fetch(nested);
    } else {
      return (T) rs.getObject(index);
    }
  }
Exemple #28
0
  private final int[] executePrepared() {
    ExecuteContext ctx = new DefaultExecuteContext(configuration, new Query[] {query});
    ExecuteListener listener = new ExecuteListeners(ctx);
    Connection connection = ctx.connection();

    // [#1371] fetch bind variables to restore them again, later
    DataType<?>[] paramTypes = dataTypes(query.getParams().values().toArray(new Field[0]));

    try {
      listener.renderStart(ctx);
      // [#1520] TODO: Should the number of bind values be checked, here?
      ctx.sql(create.render(query));
      listener.renderEnd(ctx);

      listener.prepareStart(ctx);
      ctx.statement(connection.prepareStatement(ctx.sql()));
      listener.prepareEnd(ctx);

      for (Object[] bindValues : allBindValues) {
        listener.bindStart(ctx);

        // [#1371] [#2139] Don't bind variables directly onto statement, bind them through the
        // collected params
        //                 list to preserve type information
        // [#3547]         The original query may have no Params specified - e.g. when it was
        // constructed with
        //                 plain SQL. In that case, infer the bind value type directly from the bind
        // value
        List<Field<?>> params =
            (paramTypes.length > 0) ? fields(bindValues, paramTypes) : fields(bindValues);

        visitAll(new DefaultBindContext(configuration, ctx.statement()), params);

        listener.bindEnd(ctx);
        ctx.statement().addBatch();
      }

      try {
        listener.executeStart(ctx);
        int[] result = ctx.statement().executeBatch();

        int[] batchRows = ctx.batchRows();
        for (int i = 0; i < batchRows.length && i < result.length; i++) batchRows[i] = result[i];

        listener.executeEnd(ctx);
        return result;
      } finally {
        consumeWarnings(ctx, listener);
      }
    } catch (RuntimeException e) {
      ctx.exception(e);
      listener.exception(ctx);
      throw ctx.exception();
    } catch (SQLException e) {
      ctx.sqlException(e);
      listener.exception(ctx);
      throw ctx.exception();
    } finally {
      Utils.safeClose(listener, ctx);
    }
  }
  @Override
  protected final int execute(ExecuteContext ctx, ExecuteListener listener) throws SQLException {
    Connection connection = ctx.getConnection();
    boolean autoCommit = false;

    // [#706] Postgres requires two separate queries running in the same
    // transaction to be executed when fetching refcursor types
    if (ctx.getDialect() == SQLDialect.POSTGRES && isSelectingRefCursor()) {
      autoCommit = connection.getAutoCommit();

      if (autoCommit) {
        if (log.isDebugEnabled()) log.debug("Unsetting auto-commit", false);

        connection.setAutoCommit(false);
      }
    }

    try {
      listener.executeStart(ctx);

      // JTDS doesn't seem to implement PreparedStatement.execute()
      // correctly, at least not for sp_help
      if (ctx.getDialect() == ASE) {
        ctx.resultSet(ctx.statement().executeQuery());
      }

      // [#1232] Avoid executeQuery() in order to handle queries that may
      // not return a ResultSet, e.g. SQLite's pragma foreign_key_list(table)
      else if (ctx.statement().execute()) {
        ctx.resultSet(ctx.statement().getResultSet());
      }

      listener.executeEnd(ctx);

      // Fetch a single result set
      if (!many) {
        if (ctx.resultSet() != null) {
          FieldList fields = new FieldList(getFields(ctx.resultSet().getMetaData()));
          cursor = new CursorImpl<R>(ctx, listener, fields, getRecordType());

          if (!lazy) {
            result = cursor.fetch();
            cursor = null;
          }
        } else {
          result = new ResultImpl<R>(ctx, new FieldList());
        }
      }

      // Fetch several result sets
      else {
        results = new ArrayList<Result<Record>>();
        boolean anyResults = false;

        while (ctx.resultSet() != null) {
          anyResults = true;

          FieldProvider fields = new MetaDataFieldProvider(ctx, ctx.resultSet().getMetaData());
          Cursor<Record> c = new CursorImpl<Record>(ctx, listener, fields, true);
          results.add(c.fetch());

          if (ctx.statement().getMoreResults()) {
            ctx.resultSet(ctx.statement().getResultSet());
          } else {
            ctx.resultSet(null);
          }
        }

        // Call this only when there was at least one ResultSet.
        // Otherwise, this call is not supported by ojdbc...
        if (anyResults) {
          ctx.statement().getMoreResults(Statement.CLOSE_ALL_RESULTS);
        }

        ctx.statement().close();
      }
    } finally {
      if (autoCommit) {
        if (log.isDebugEnabled()) log.debug("Resetting auto-commit", autoCommit);

        connection.setAutoCommit(autoCommit);
      }
    }

    return result != null ? result.size() : 0;
  }
Exemple #30
0
 @Override
 public void renderEnd(ExecuteContext ctx) {
   throw new QueryCollectorSignal(ctx.sql(), ctx.query());
 }