001package io.ebeaninternal.server.core; 002 003import io.ebeaninternal.api.SpiEbeanServer; 004import io.ebeaninternal.api.SpiSqlUpdate; 005import io.ebeaninternal.api.SpiTransaction; 006import io.ebeaninternal.server.lib.Str; 007import io.ebeaninternal.server.persist.BatchControl; 008import io.ebeaninternal.server.persist.PersistExecute; 009import io.ebeaninternal.server.persist.TrimLogSql; 010 011/** 012 * Persist request specifically for CallableSql. 013 */ 014public final class PersistRequestUpdateSql extends PersistRequest { 015 016 public enum SqlType { 017 SQL_UPDATE, SQL_DELETE, SQL_INSERT, SQL_UNKNOWN 018 } 019 020 private final SpiSqlUpdate updateSql; 021 022 private int rowCount; 023 024 private String bindLog; 025 026 private SqlType sqlType; 027 028 private String tableName; 029 030 private boolean addBatch; 031 032 private final boolean forceNoBatch; 033 034 private boolean batchThisRequest; 035 private boolean flushQueue; 036 037 public PersistRequestUpdateSql(SpiEbeanServer server, SpiSqlUpdate sqlUpdate, 038 SpiTransaction t, PersistExecute persistExecute, boolean forceNoBatch) { 039 040 super(server, t, persistExecute, sqlUpdate.getLabel()); 041 this.type = Type.UPDATESQL; 042 this.updateSql = sqlUpdate; 043 this.forceNoBatch = forceNoBatch; 044 updateSql.reset(); 045 } 046 047 public PersistRequestUpdateSql(SpiEbeanServer server, SpiSqlUpdate sqlUpdate, 048 SpiTransaction t, PersistExecute persistExecute) { 049 this(server, sqlUpdate, t, persistExecute, false); 050 } 051 052 @Override 053 public void profile(long offset, int flushCount) { 054 profileBase(EVT_UPDATESQL, offset, "", flushCount); 055 } 056 057 /** 058 * Add this statement to JDBC batch for later execution. 059 */ 060 public int addBatch() { 061 this.addBatch = true; 062 return executeOrQueue(); 063 } 064 065 /** 066 * Execute using jdbc batch. 067 */ 068 public void executeAddBatch() { 069 this.addBatch = true; 070 persistExecute.executeSqlUpdate(this); 071 } 072 073 /** 074 * Add this request to BatchControl to flush later. 075 */ 076 public void addToFlushQueue(boolean early) { 077 BatchControl control = transaction.getBatchControl(); 078 if (control == null) { 079 control = persistExecute.createBatchControl(transaction); 080 } 081 flushQueue = true; 082 control.addToFlushQueue(this, early); 083 } 084 085 @Override 086 public boolean isFlushQueue() { 087 return flushQueue; 088 } 089 090 @Override 091 public int executeNow() { 092 return persistExecute.executeSqlUpdate(this); 093 } 094 095 @Override 096 public boolean isBatchThisRequest() { 097 return !forceNoBatch && (addBatch || super.isBatchThisRequest()); 098 } 099 100 @Override 101 public int executeOrQueue() { 102 return executeStatement(); 103 } 104 105 /** 106 * Return the UpdateSql. 107 */ 108 public SpiSqlUpdate getUpdateSql() { 109 return updateSql; 110 } 111 112 /** 113 * No concurrency checking so just note the rowCount. 114 */ 115 @Override 116 public void checkRowCount(int count) { 117 this.rowCount = count; 118 } 119 120 /** 121 * Not called for this type of request. 122 */ 123 @Override 124 public void setGeneratedKey(Object idValue) { 125 updateSql.setGeneratedKey(idValue); 126 } 127 128 public boolean isGetGeneratedKeys() { 129 return updateSql.isGetGeneratedKeys(); 130 } 131 132 /** 133 * Specify the type of statement executed. Used to automatically register 134 * with the transaction event. 135 */ 136 public void setType(SqlType sqlType, String tableName) { 137 this.sqlType = sqlType; 138 this.tableName = tableName; 139 } 140 141 /** 142 * Set the bound values. 143 */ 144 public void setBindLog(String bindLog) { 145 this.bindLog = bindLog; 146 } 147 148 public void startBind(boolean batchThisRequest) { 149 this.batchThisRequest = batchThisRequest; 150 super.startBind(batchThisRequest); 151 } 152 153 /** 154 * Log the sql bind used with jdbc batch. 155 */ 156 public void logSqlBatchBind() { 157 if (transaction.isLogSql()) { 158 transaction.logSql(Str.add(" -- bind(", bindLog, ")")); 159 } 160 } 161 162 /** 163 * Perform post execute processing. 164 */ 165 @Override 166 public void postExecute() { 167 if (startNanos > 0) { 168 persistExecute.collectSqlUpdate(label, startNanos); 169 } 170 if (transaction.isLogSql() && !batchThisRequest) { 171 transaction.logSql(Str.add(TrimLogSql.trim(updateSql.getGeneratedSql()), "; -- bind(", bindLog, ") rows(", String.valueOf(rowCount), ")")); 172 } 173 174 if (updateSql.isAutoTableMod()) { 175 // add the modification info to the TransactionEvent 176 // this is used to invalidate cached objects etc 177 switch (sqlType) { 178 case SQL_INSERT: 179 transaction.getEvent().add(tableName, true, false, false); 180 break; 181 case SQL_UPDATE: 182 transaction.getEvent().add(tableName, false, true, false); 183 break; 184 case SQL_DELETE: 185 transaction.getEvent().add(tableName, false, false, true); 186 break; 187 case SQL_UNKNOWN: 188 transaction.markNotQueryOnly(); 189 190 default: 191 break; 192 } 193 } 194 } 195 196}