All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.ebeaninternal.server.persist.ExeUpdateSql Maven / Gradle / Ivy

There is a newer version: 15.8.0
Show newest version
package io.ebeaninternal.server.persist;

import io.ebean.util.JdbcClose;
import io.ebeaninternal.api.BindParams;
import io.ebeaninternal.api.SpiSqlUpdate;
import io.ebeaninternal.api.SpiTransaction;
import io.ebeaninternal.server.core.PersistRequestUpdateSql;
import io.ebeaninternal.server.core.PersistRequestUpdateSql.SqlType;
import io.ebeaninternal.server.util.BindParamsParser;

import jakarta.persistence.PersistenceException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * Executes the UpdateSql requests.
 */
final class ExeUpdateSql {

  private final Binder binder;
  private final PstmtFactory pstmtFactory;

  ExeUpdateSql(Binder binder) {
    this.binder = binder;
    this.pstmtFactory = new PstmtFactory();
  }

  /**
   * Execute the UpdateSql request.
   */
  public int execute(PersistRequestUpdateSql request) {
    boolean batchThisRequest = request.isBatchThisRequest();
    PreparedStatement pstmt = null;
    try {
      pstmt = bindStmt(request, batchThisRequest);
      if (batchThisRequest) {
        pstmt.addBatch();
        // return -1 to indicate batch mode
        return -1;
      } else {
        int rowCount = pstmt.executeUpdate();
        request.checkRowCount(rowCount);
        if (request.isGetGeneratedKeys()) {
          readGeneratedKeys(pstmt, request);
        }
        request.postExecute();
        return rowCount;
      }
    } catch (SQLException e) {
      throw request.translateSqlException(e);

    } finally {
      if (!batchThisRequest) {
        JdbcClose.close(pstmt);
      }
    }
  }

  private void readGeneratedKeys(PreparedStatement stmt, PersistRequestUpdateSql request) {
    ResultSet resultSet = null;
      try {
        resultSet = stmt.getGeneratedKeys();
        if (resultSet.next()) {
          request.setGeneratedKey(resultSet.getObject(1));
        }
      } catch (SQLException ex) {
        throw new PersistenceException(ex);

      } finally {
        JdbcClose.close(resultSet);
      }
  }

  private PreparedStatement bindStmt(PersistRequestUpdateSql request, boolean batchThisRequest) throws SQLException {
    request.startBind(batchThisRequest);
    SpiSqlUpdate updateSql = request.updateSql();
    SpiTransaction t = request.transaction();

    BindParams bindParams = updateSql.bindParams();

    // process named parameters if required
    String sql = updateSql.baseSql();
    sql = BindParamsParser.parse(bindParams, sql);
    parseUpdate(sql, request);

    PreparedStatement pstmt;
    if (batchThisRequest) {
      pstmt = pstmtFactory.pstmtBatch(t, sql, request);
    } else {
      pstmt = pstmtFactory.pstmt(t, sql, request.isGetGeneratedKeys());
    }
    if (updateSql.getTimeout() > 0) {
      pstmt.setQueryTimeout(updateSql.getTimeout());
    }
    String bindLog = null;
    if (!bindParams.isEmpty()) {
      bindLog = binder.bind(bindParams, pstmt, t.internalConnection());
    }
    request.setBindLog(bindLog);
    updateSql.setGeneratedSql(sql);
    if (batchThisRequest) {
      request.logSqlBatchBind();
    }
    return pstmt;
  }


  private void determineType(String word1, String word2, String word3, PersistRequestUpdateSql request) {
    if (word1.equalsIgnoreCase("UPDATE")) {
      request.setType(SqlType.SQL_UPDATE, word2);

    } else if (word1.equalsIgnoreCase("DELETE")) {
      request.setType(SqlType.SQL_DELETE, word3);

    } else if (word1.equalsIgnoreCase("INSERT")) {
      request.setType(SqlType.SQL_INSERT, word3);

    } else {
      request.setType(SqlType.SQL_UNKNOWN, null);
    }
  }

  private void parseUpdate(String sql, PersistRequestUpdateSql request) {
    int[] pos = new int[3];
    int spaceCount = 0;

    int len = sql.length();
    for (int i = 0; i < len; i++) {
      char c = sql.charAt(i);
      if (Character.isWhitespace(c)) {
        pos[spaceCount] = i;
        spaceCount++;
        if (spaceCount > 2) {
          break;
        }
      }
    }

    if (spaceCount < 2) {
      // unknown so no automatic L2 cache invalidation performed (so it should instead)
      // be done explicitly via the server.externalModification() method
      request.setType(SqlType.SQL_UNKNOWN, null);

    } else {
      // try to determine if it is insert, update or delete and the table involved
      // such that we can automatically manage L2 cache
      String firstWord = sql.substring(0, pos[0]);
      String secWord = sql.substring(pos[0] + 1, pos[1]);
      String thirdWord;
      if (pos[2] == 0) {
        // there is nothing after the table name
        thirdWord = sql.substring(pos[1] + 1);
      } else {
        thirdWord = sql.substring(pos[1] + 1, pos[2]);
      }

      determineType(firstWord, secWord, thirdWord, request);
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy