package io.ebeaninternal.server.persist.dml;
import io.ebean.annotation.Platform;
import io.ebean.bean.EntityBean;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebeaninternal.server.core.PersistRequestBean;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.InheritInfo;
import io.ebeaninternal.server.persist.dmlbind.Bindable;
import io.ebeaninternal.server.persist.dmlbind.BindableDiscriminator;
import io.ebeaninternal.server.persist.dmlbind.BindableId;
import io.ebeaninternal.server.persist.dmlbind.BindableList;
import java.sql.SQLException;
import static io.ebean.annotation.Platform.MARIADB;
import static io.ebean.annotation.Platform.MYSQL;
final class InsertMeta {
private final String sqlNullId;
private final String sqlWithId;
private final String sqlDraftNullId;
private final String sqlDraftWithId;
private final BindableId id;
private final Bindable discriminator;
private final BindableList all;
private final BindableList allExcludeDraftOnly;
private final boolean supportsGetGeneratedKeys;
private final boolean concatinatedKey;
private final boolean supportsSelectLastInsertedId;
private final Bindable shadowFKey;
private final String[] identityDbColumns;
private final Platform platform;
InsertMeta(DatabasePlatform dbPlatform, BeanDescriptor<?> desc, Bindable shadowFKey, BindableId id, BindableList all) {
this.platform = dbPlatform.getPlatform();
this.discriminator = getDiscriminator(desc);
this.id = id;
this.all = all;
this.allExcludeDraftOnly = all.excludeDraftOnly();
this.shadowFKey = shadowFKey;
String tableName = desc.getBaseTable();
String draftTableName = desc.getDraftTable();
this.sqlWithId = genSql(false, tableName, false);
this.sqlDraftWithId = desc.isDraftable() ? genSql(false, draftTableName, true) : sqlWithId;
if (id.isConcatenated()) {
this.concatinatedKey = true;
this.identityDbColumns = null;
this.sqlNullId = null;
this.sqlDraftNullId = null;
this.supportsGetGeneratedKeys = false;
this.supportsSelectLastInsertedId = false;
} else {
this.concatinatedKey = false;
if (id.getIdentityColumn() == null) {
this.identityDbColumns = new String[]{};
this.supportsGetGeneratedKeys = false;
this.supportsSelectLastInsertedId = false;
} else {
this.identityDbColumns = new String[]{id.getIdentityColumn()};
this.supportsGetGeneratedKeys = dbPlatform.getDbIdentity().isSupportsGetGeneratedKeys();
this.supportsSelectLastInsertedId = desc.supportsSelectLastInsertedId();
}
this.sqlNullId = genSql(true, tableName, false);
this.sqlDraftNullId = desc.isDraftable() ? genSql(true, draftTableName, true) : sqlNullId;
}
}
private static Bindable getDiscriminator(BeanDescriptor<?> desc) {
InheritInfo inheritInfo = desc.getInheritInfo();
return inheritInfo != null ? new BindableDiscriminator(inheritInfo) : null;
}
boolean isConcatenatedKey() {
return concatinatedKey;
}
String[] getIdentityDbColumns() {
return identityDbColumns;
}
boolean supportsSelectLastInsertedId() {
return supportsSelectLastInsertedId;
}
boolean supportsGetGeneratedKeys() {
return supportsGetGeneratedKeys;
}
boolean deriveConcatenatedId(PersistRequestBean<?> persist) {
return id.deriveConcatenatedId(persist);
}
public void bind(DmlHandler request, EntityBean bean, boolean withId, boolean publish) throws SQLException {
if (withId) {
id.dmlBind(request, bean);
}
if (shadowFKey != null) {
shadowFKey.dmlBind(request, bean);
}
if (discriminator != null) {
discriminator.dmlBind(request, bean);
}
if (publish) {
allExcludeDraftOnly.dmlBind(request, bean);
} else {
all.dmlBind(request, bean);
}
}
public String getSql(boolean withId, boolean publish) {
if (withId) {
return publish ? sqlWithId : sqlDraftWithId;
} else {
return publish ? sqlNullId : sqlDraftNullId;
}
}
private String genSql(boolean nullId, String table, boolean draftTable) {
GenerateDmlRequest request = new GenerateDmlRequest();
request.setInsertSetMode();
request.append("insert into ").append(table);
if (nullId && noColumnsForInsert(draftTable)) {
return request.append(defaultValues()).toString();
}
request.append(" (");
if (!nullId) {
id.dmlAppend(request);
}
if (shadowFKey != null) {
shadowFKey.dmlAppend(request);
}
if (discriminator != null) {
discriminator.dmlAppend(request);
}
if (draftTable) {
all.dmlAppend(request);
} else {
allExcludeDraftOnly.dmlAppend(request);
}
request.append(") values (");
request.append(request.getInsertBindBuffer());
request.append(")");
return request.toString();
}
private String defaultValues() {
return platform.base() == MYSQL || platform.base() == MARIADB ? " values (default)" : " default values";
}
private boolean noColumnsForInsert(boolean draftTable) {
return shadowFKey == null
&& discriminator == null
&& (draftTable ? all.isEmpty() : allExcludeDraftOnly.isEmpty());
}
}