예제 #1
0
  @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);
    }
  }
예제 #2
0
        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"));
            }
        }
예제 #3
0
        @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);
        }
예제 #4
0
        @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);
        }
예제 #5
0
        @Override
        public void renderStart(ExecuteContext ctx) {
            renderStart.add(++callbackCount);
            checkBase(ctx);
            checkStatement(ctx, false);
            checkSQL(ctx, false);

            assertNull(ctx.sql());
        }
예제 #6
0
        @Override
        public void renderStart(ExecuteContext ctx) {
            renderStart = ++callbackCount;
            checkBase(ctx);

            assertNull(ctx.batchSQL()[0]);
            assertNull(ctx.sql());
            assertNull(ctx.statement());
        }
  @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()));
  }
예제 #8
0
        @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());
        }
예제 #9
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;
          }
      }
    }
  }
예제 #10
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);
    }
  }
예제 #11
0
 @Override
 public void renderEnd(ExecuteContext ctx) {
   throw new QueryCollectorSignal(ctx.sql(), ctx.query());
 }
예제 #12
0
 /** Default implementation for preparing a statement. Subclasses may override this method. */
 protected void prepare(ExecuteContext ctx) throws SQLException {
   ctx.statement(ctx.connection().prepareStatement(ctx.sql()));
 }
예제 #13
0
  @Override
  public final int execute() {
    if (isExecutable()) {

      // Get the attached configuration of this query
      Configuration c = configuration();

      // [#1191] The following triggers a start event on all listeners.
      //         This may be used to provide jOOQ with a JDBC connection,
      //         in case this Query / Configuration was previously
      //         deserialised
      ExecuteContext ctx = new DefaultExecuteContext(c, this);
      ExecuteListener listener = new ExecuteListeners(ctx);

      int result = 0;
      try {
        if (ctx.connection() == null) {
          throw new DetachedException("Cannot execute query. No Connection configured");
        }

        // [#385] If a statement was previously kept open
        if (keepStatement() && statement != null) {
          ctx.sql(sql);
          ctx.statement(statement);
        }

        // [#385] First time statement preparing
        else {
          listener.renderStart(ctx);
          ctx.sql(getSQL0(ctx));
          listener.renderEnd(ctx);

          sql = ctx.sql();

          listener.prepareStart(ctx);
          prepare(ctx);
          listener.prepareEnd(ctx);

          statement = ctx.statement();
        }

        // [#1856] Set the query timeout onto the Statement
        if (timeout != 0) {
          ctx.statement().setQueryTimeout(timeout);
        }

        if (

        // [#1145] Bind variables only for true prepared statements
        // [#2414] Even if parameters are inlined here, child
        //         QueryParts may override this behaviour!
        executePreparedStatements(c.settings())
            &&

            // [#1520] Renderers may enforce static statements, too
            !Boolean.TRUE.equals(ctx.data(DATA_FORCE_STATIC_STATEMENT))) {

          listener.bindStart(ctx);
          using(c).bindContext(ctx.statement()).visit(this);
          listener.bindEnd(ctx);
        }

        result = execute(ctx, listener);
        return result;
      } catch (SQLException e) {
        ctx.sqlException(e);
        listener.exception(ctx);
        throw ctx.exception();
      } finally {

        // [#2385] Successful fetchLazy() needs to keep open resources
        if (!keepResultSet() || ctx.exception() != null) {
          Utils.safeClose(listener, ctx, keepStatement());
        }

        if (!keepStatement()) {
          statement = null;
          sql = null;
        }
      }
    } else {
      if (log.isDebugEnabled()) {
        log.debug("Query is not executable", this);
      }

      return 0;
    }
  }