Compare commits

..
Author SHA1 Message Date
Rob Bygrave b6b666013e ClickHouse: Support optimised inserts for ClickHouse 2024-04-17 22:50:28 +12:00
32 changed files with 499 additions and 153 deletions
@@ -199,12 +199,21 @@ public class DatabasePlatform {
protected SqlExceptionTranslator exceptionTranslator = new SqlCodeTranslator(); protected SqlExceptionTranslator exceptionTranslator = new SqlCodeTranslator();
protected InsertSqlSyntaxExtension insertSqlSyntaxExtension = new StandardInsertSqlSyntax();
/** /**
* Instantiates a new database platform. * Instantiates a new database platform.
*/ */
public DatabasePlatform() { public DatabasePlatform() {
} }
/**
* Return the Insert SQL syntax helper.
*/
public InsertSqlSyntaxExtension insertSqlSyntaxExtension() {
return insertSqlSyntaxExtension;
}
/** /**
* Translate the SQLException into a specific persistence exception if possible. * Translate the SQLException into a specific persistence exception if possible.
*/ */
@@ -0,0 +1,32 @@
package io.ebean.config.dbplatform;
/**
* Insert SQL syntax to allow support for ClickHouse type optimisation for inserts.
*/
public interface InsertSqlSyntaxExtension {
/**
* Start the columns.
*/
String startColumns();
/**
* End of the columns.
*/
String endColumns();
/**
* Return true for insert to use standard binding.
*/
boolean useBinding();
/**
* Start types for non-standard binding (e.g. ClickHouse).
*/
String startTypes();
/**
* End types for non-standard binding (e.g. ClickHouse).
*/
String endTypes();
}
@@ -0,0 +1,32 @@
package io.ebean.config.dbplatform;
/**
* Standard Insert SQL syntax.
*/
public final class StandardInsertSqlSyntax implements InsertSqlSyntaxExtension {
@Override
public String startColumns() {
return " (";
}
@Override
public String endColumns() {
return ") values (";
}
@Override
public boolean useBinding() {
return true;
}
@Override
public String startTypes() {
throw new IllegalStateException();
}
@Override
public String endTypes() {
throw new IllegalStateException();
}
}
@@ -5,6 +5,7 @@ import io.ebean.DatabaseBuilder;
import io.ebean.Model; import io.ebean.Model;
import io.ebean.RawSqlBuilder; import io.ebean.RawSqlBuilder;
import io.ebean.annotation.ConstraintMode; import io.ebean.annotation.ConstraintMode;
import io.ebean.annotation.Platform;
import io.ebean.bean.BeanCollection; import io.ebean.bean.BeanCollection;
import io.ebean.bean.EntityBean; import io.ebean.bean.EntityBean;
import io.ebean.config.*; import io.ebean.config.*;
@@ -632,6 +633,8 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
} }
private void registerDescriptor(DeployBeanInfo<?> info) { private void registerDescriptor(DeployBeanInfo<?> info) {
platformUsesColumnDefinitions(info);
BeanDescriptor<?> desc = new BeanDescriptor<>(this, info.getDescriptor()); BeanDescriptor<?> desc = new BeanDescriptor<>(this, info.getDescriptor());
descMap.put(desc.type().getName(), desc); descMap.put(desc.type().getName(), desc);
if (desc.isDocStoreMapped()) { if (desc.isDocStoreMapped()) {
@@ -644,6 +647,23 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
} }
} }
private void platformUsesColumnDefinitions(DeployBeanInfo<?> info) {
if (databasePlatform.isPlatform(Platform.CLICKHOUSE) && !DbOffline.isGenerateMigration()) {
// ClickHouse uses column definition to optimise JDBC bulk inserts
DbPlatformTypeMapping typeMapping = databasePlatform.dbTypeMap();
for (DeployBeanProperty property : info.getDescriptor().propertiesAll()) {
if (property.getDbColumnDefn() == null) {
DbPlatformType dbPlatformType = typeMapping.get(property.getDbType());
String columnDefn = dbPlatformType.renderType(property.getDbLength(), property.getDbScale());
if (property.isNullable()) {
columnDefn = "Nullable(" + columnDefn + ")";
}
property.setDbColumnDefn(columnDefn);
}
}
}
}
/** /**
* Read the initial deployment information for the entities. * Read the initial deployment information for the entities.
* <p> * <p>
@@ -43,6 +43,11 @@ public interface ImportedId {
*/ */
void dmlAppend(GenerateDmlRequest request); void dmlAppend(GenerateDmlRequest request);
/**
* Append column and type for Insert (ClickHouse).
*/
void dmlType(GenerateDmlRequest request);
/** /**
* Bind the value from the bean. * Bind the value from the bean.
*/ */
@@ -66,6 +66,16 @@ public final class ImportedIdEmbedded implements ImportedId {
} }
} }
@Override
public void dmlType(GenerateDmlRequest request) {
boolean update = request.isUpdate();
for (ImportedIdSimple anImported : imported) {
if (anImported.isInclude(update)) {
anImported.dmlType(request);
}
}
}
@Override @Override
public String importedIdClause() { public String importedIdClause() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
@@ -37,6 +37,7 @@ public final class ImportedIdSimple implements ImportedId, Comparable<ImportedId
final BeanPropertyAssoc<?> owner; final BeanPropertyAssoc<?> owner;
final String localDbColumn; final String localDbColumn;
private final String localColumnDefn;
private final String localSqlFormula; private final String localSqlFormula;
final BeanProperty foreignProperty; final BeanProperty foreignProperty;
private final int position; private final int position;
@@ -49,6 +50,7 @@ public final class ImportedIdSimple implements ImportedId, Comparable<ImportedId
this.localDbColumn = InternString.intern(localDbColumn); this.localDbColumn = InternString.intern(localDbColumn);
this.localSqlFormula = InternString.intern(localSqlFormula); this.localSqlFormula = InternString.intern(localSqlFormula);
this.foreignProperty = foreignProperty; this.foreignProperty = foreignProperty;
this.localColumnDefn = foreignProperty.dbColumnDefn();
this.position = position; this.position = position;
this.insertable = insertable; this.insertable = insertable;
this.updateable = updateable; this.updateable = updateable;
@@ -143,6 +145,11 @@ public final class ImportedIdSimple implements ImportedId, Comparable<ImportedId
request.appendColumn(localDbColumn); request.appendColumn(localDbColumn);
} }
@Override
public void dmlType(GenerateDmlRequest request) {
request.appendColumnDefn(localDbColumn, localColumnDefn);
}
@Override @Override
public String importedIdClause() { public String importedIdClause() {
return localDbColumn + " = ?"; return localDbColumn + " = ?";
@@ -15,14 +15,26 @@ public final class GenerateDmlRequest {
private String prefix2; private String prefix2;
private int insertMode; private int insertMode;
private int bindColumnCount; private int bindColumnCount;
private boolean hasColumnDefn;
GenerateDmlRequest append(String s) { GenerateDmlRequest append(String s) {
sb.append(s); sb.append(s);
return this; return this;
} }
/**
* Append column and type for Insert (ClickHouse).
*/
public void appendColumnDefn(String columnName, String columnDefn) {
if (hasColumnDefn) {
sb.append(", ");
} else {
hasColumnDefn = true;
}
sb.append(columnName).append(' ').append(columnDefn);
}
public void appendColumn(String column) { public void appendColumn(String column) {
//String bind = (insertMode > 0) ? "?" : "=?";
appendColumn(column, "?"); appendColumn(column, "?");
} }
@@ -4,6 +4,7 @@ import io.ebean.InsertOptions;
import io.ebean.annotation.Platform; import io.ebean.annotation.Platform;
import io.ebean.bean.EntityBean; import io.ebean.bean.EntityBean;
import io.ebean.config.dbplatform.DatabasePlatform; import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.config.dbplatform.InsertSqlSyntaxExtension;
import io.ebeaninternal.server.core.PersistRequestBean; import io.ebeaninternal.server.core.PersistRequestBean;
import io.ebeaninternal.server.deploy.BeanDescriptor; import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.InheritInfo; import io.ebeaninternal.server.deploy.InheritInfo;
@@ -37,10 +38,13 @@ final class InsertMeta {
private final Bindable shadowFKey; private final Bindable shadowFKey;
private final String[] identityDbColumns; private final String[] identityDbColumns;
private final Platform platform; private final Platform platform;
private final InsertSqlSyntaxExtension insertMetaSql;
private final InsertMetaOptions options; private final InsertMetaOptions options;
InsertMeta(DatabasePlatform dbPlatform, BeanDescriptor<?> desc, Bindable shadowFKey, BindableId id, BindableList all) { InsertMeta(DatabasePlatform dbPlatform, BeanDescriptor<?> desc, Bindable shadowFKey, BindableId id, BindableList all) {
this.platform = dbPlatform.platform(); this.platform = dbPlatform.platform();
this.insertMetaSql = dbPlatform.insertSqlSyntaxExtension();
this.options = InsertMetaPlatform.create(platform, desc, this); this.options = InsertMetaPlatform.create(platform, desc, this);
this.discriminator = discriminator(desc); this.discriminator = discriminator(desc);
this.id = id; this.id = id;
@@ -174,7 +178,7 @@ final class InsertMeta {
request.append(defaultValues()); request.append(defaultValues());
return; return;
} }
request.append(" ("); request.append(insertMetaSql.startColumns());
if (!nullId) { if (!nullId) {
id.dmlAppend(request); id.dmlAppend(request);
} }
@@ -189,9 +193,28 @@ final class InsertMeta {
} else { } else {
allExcludeDraftOnly.dmlAppend(request); allExcludeDraftOnly.dmlAppend(request);
} }
request.append(") values ("); request.append(insertMetaSql.endColumns());
request.append(request.insertBindBuffer()); if (insertMetaSql.useBinding()) {
request.append(")"); request.append(request.insertBindBuffer());
request.append(")");
} else {
request.append(insertMetaSql.startTypes());
if (!nullId) {
id.dmlType(request);
}
if (shadowFKey != null) {
shadowFKey.dmlType(request);
}
if (discriminator != null) {
discriminator.dmlType(request);
}
if (draftTable) {
all.dmlType(request);
} else {
allExcludeDraftOnly.dmlType(request);
}
request.append(insertMetaSql.endTypes());
}
} }
private String defaultValues() { private String defaultValues() {
@@ -33,6 +33,11 @@ public interface Bindable {
*/ */
void dmlAppend(GenerateDmlRequest request); void dmlAppend(GenerateDmlRequest request);
/**
* Append column and type for Insert (ClickHouse).
*/
void dmlType(GenerateDmlRequest request);
/** /**
* Bind given the request and bean. The bean could be the oldValues bean * Bind given the request and bean. The bean could be the oldValues bean
* when binding a update or delete where clause with ALL concurrency mode. * when binding a update or delete where clause with ALL concurrency mode.
@@ -40,6 +40,11 @@ class BindableAssocOne implements Bindable {
importedId.dmlAppend(request); importedId.dmlAppend(request);
} }
@Override
public void dmlType(GenerateDmlRequest request) {
importedId.dmlType(request);
}
@Override @Override
public void dmlBind(BindableRequest request, EntityBean bean) throws SQLException { public void dmlBind(BindableRequest request, EntityBean bean) throws SQLException {
EntityBean assocBean = (EntityBean) assocOne.getValue(bean); EntityBean assocBean = (EntityBean) assocOne.getValue(bean);
@@ -39,6 +39,11 @@ public final class BindableDiscriminator implements Bindable {
request.appendColumn(columnName); request.appendColumn(columnName);
} }
@Override
public void dmlType(GenerateDmlRequest request) {
throw new IllegalArgumentException("Not supported");
}
@Override @Override
public void dmlBind(BindableRequest bindRequest, EntityBean bean) throws SQLException { public void dmlBind(BindableRequest bindRequest, EntityBean bean) throws SQLException {
bindRequest.bind(discValue, sqlType); bindRequest.bind(discValue, sqlType);
@@ -35,6 +35,13 @@ final class BindableEmbedded implements Bindable {
} }
} }
@Override
public void dmlType(GenerateDmlRequest request) {
for (Bindable item : items) {
item.dmlType(request);
}
}
@Override @Override
public void addToUpdate(PersistRequestBean<?> request, List<Bindable> list) { public void addToUpdate(PersistRequestBean<?> request, List<Bindable> list) {
if (request.isAddToUpdate(embProp)) { if (request.isAddToUpdate(embProp)) {
@@ -41,6 +41,11 @@ final class BindableEncryptedProperty implements Bindable {
request.appendColumn(prop.dbColumn(), prop.dbBind()); request.appendColumn(prop.dbColumn(), prop.dbBind());
} }
@Override
public void dmlType(GenerateDmlRequest request) {
request.appendColumnDefn(prop.dbColumn(), prop.dbColumnDefn());
}
@Override @Override
public void dmlBind(BindableRequest request, EntityBean bean) throws SQLException { public void dmlBind(BindableRequest request, EntityBean bean) throws SQLException {
Object value = null; Object value = null;
@@ -81,6 +81,13 @@ final class BindableIdEmbedded implements BindableId {
} }
} }
@Override
public void dmlType(GenerateDmlRequest request) {
for (BeanProperty prop : props) {
request.appendColumn(prop.dbColumnDefn());
}
}
@Override @Override
public boolean deriveConcatenatedId(PersistRequestBean<?> persist) { public boolean deriveConcatenatedId(PersistRequestBean<?> persist) {
if (matches == null) { if (matches == null) {
@@ -28,6 +28,11 @@ final class BindableIdEmpty implements BindableId {
// nothing // nothing
} }
@Override
public void dmlType(GenerateDmlRequest request) {
// nothing
}
@Override @Override
public void dmlBind(BindableRequest request, EntityBean bean) { public void dmlBind(BindableRequest request, EntityBean bean) {
// nothing // nothing
@@ -58,17 +58,18 @@ final class BindableIdScalar implements BindableId {
@Override @Override
public void dmlAppend(GenerateDmlRequest request) { public void dmlAppend(GenerateDmlRequest request) {
request.appendColumn(uidProp.dbColumn()); request.appendColumn(uidProp.dbColumn());
} }
@Override
public void dmlType(GenerateDmlRequest request) {
request.appendColumnDefn(uidProp.dbColumn(), uidProp.dbColumnDefn());
}
@Override @Override
public void dmlBind(BindableRequest request, EntityBean bean) throws SQLException { public void dmlBind(BindableRequest request, EntityBean bean) throws SQLException {
Object value = uidProp.getValue(bean); Object value = uidProp.getValue(bean);
request.bind(value, uidProp); request.bind(value, uidProp);
// used for summary logging // used for summary logging
request.setIdValue(value); request.setIdValue(value);
} }
@@ -60,6 +60,13 @@ public final class BindableList implements Bindable {
} }
} }
@Override
public void dmlType(GenerateDmlRequest request) {
for (Bindable item : items) {
item.dmlType(request);
}
}
@Override @Override
public void dmlBind(BindableRequest bindRequest, EntityBean bean) throws SQLException { public void dmlBind(BindableRequest bindRequest, EntityBean bean) throws SQLException {
for (Bindable item : items) { for (Bindable item : items) {
@@ -36,6 +36,11 @@ class BindableProperty implements Bindable {
request.appendColumn(prop.dbColumn()); request.appendColumn(prop.dbColumn());
} }
@Override
public void dmlType(GenerateDmlRequest request) {
request.appendColumnDefn(prop.dbColumn(), prop.dbColumnDefn());
}
/** /**
* Normal binding of a property value from the bean. * Normal binding of a property value from the bean.
*/ */
@@ -41,6 +41,11 @@ final class BindablePropertyVersion implements Bindable {
request.appendColumn(prop.dbColumn()); request.appendColumn(prop.dbColumn());
} }
@Override
public void dmlType(GenerateDmlRequest request) {
request.appendColumnDefn(prop.dbColumn(), prop.dbColumnDefn());
}
/** /**
* Normal binding of a property value from the bean. * Normal binding of a property value from the bean.
*/ */
@@ -45,6 +45,11 @@ public final class BindableUnidirectional implements Bindable {
importedId.dmlAppend(request); importedId.dmlAppend(request);
} }
@Override
public void dmlType(GenerateDmlRequest request) {
importedId.dmlType(request);
}
@Override @Override
public void dmlBind(BindableRequest request, EntityBean bean) throws SQLException { public void dmlBind(BindableRequest request, EntityBean bean) throws SQLException {
PersistRequestBean<?> persistRequest = request.persistRequest(); PersistRequestBean<?> persistRequest = request.persistRequest();
@@ -5,6 +5,7 @@ import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer; import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer;
import io.ebeaninternal.dbmigration.ddlgeneration.DdlHandler; import io.ebeaninternal.dbmigration.ddlgeneration.DdlHandler;
import io.ebeaninternal.dbmigration.ddlgeneration.DdlOptions; import io.ebeaninternal.dbmigration.ddlgeneration.DdlOptions;
import io.ebeaninternal.dbmigration.migration.Column;
public class ClickHouseDdl extends PlatformDdl { public class ClickHouseDdl extends PlatformDdl {
@@ -17,6 +18,16 @@ public class ClickHouseDdl extends PlatformDdl {
this.columnNotNull = null; this.columnNotNull = null;
} }
@Override
protected String columnDefn(Column column) {
String defn = super.columnDefn(column);
if (isTrue(column.isNotnull()) || isTrue(column.isPrimaryKey())) {
return defn;
} else {
return "Nullable(" + defn + ")";
}
}
@Override @Override
public DdlHandler createDdlHandler(DatabaseBuilder.Settings config) { public DdlHandler createDdlHandler(DatabaseBuilder.Settings config) {
return new ClickHouseDdlHandler(config, this); return new ClickHouseDdlHandler(config, this);
@@ -230,13 +230,13 @@ public class PlatformDdl {
* Write the column definition to the create table statement. * Write the column definition to the create table statement.
*/ */
protected void writeColumnDefinition(DdlBuffer buffer, Column column, DdlIdentity identity) { protected void writeColumnDefinition(DdlBuffer buffer, Column column, DdlIdentity identity) {
String columnDefn = convert(column.getType()); buffer.append(" ");
buffer.append(quote(column.getName()), 29);
String columnDefn = columnDefn(column);
if (identity.useIdentity() && isTrue(column.isPrimaryKey())) { if (identity.useIdentity() && isTrue(column.isPrimaryKey())) {
columnDefn = asIdentityColumn(columnDefn, identity); columnDefn = asIdentityColumn(columnDefn, identity);
} }
buffer.append(" ");
buffer.append(quote(column.getName()), 29);
buffer.append(columnDefn); buffer.append(columnDefn);
if (!Boolean.TRUE.equals(column.isPrimaryKey())) { if (!Boolean.TRUE.equals(column.isPrimaryKey())) {
String defaultValue = convertDefaultValue(column.getDefaultValue()); String defaultValue = convertDefaultValue(column.getDefaultValue());
@@ -251,6 +251,13 @@ public class PlatformDdl {
// so that the database can potentially provide a nice SQL error // so that the database can potentially provide a nice SQL error
} }
/**
* Return the plaform specific column type definition.
*/
protected String columnDefn(Column column) {
return convert(column.getType());
}
/** /**
* Returns the check constraint. * Returns the check constraint.
*/ */
@@ -0,0 +1,28 @@
package io.ebeaninternal.dbmigration;
import io.ebean.platform.clickhouse.ClickHousePlatform;
import io.ebeaninternal.dbmigration.ddlgeneration.PlatformDdlBuilder;
import io.ebeaninternal.dbmigration.ddlgeneration.platform.PlatformDdl;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class ClickHousePlatformTest {
@Test
void testTypeConversion() {
PlatformDdl ddl = PlatformDdlBuilder.create(new ClickHousePlatform());
assertThat(ddl.convert("clob")).isEqualTo("String");
assertThat(ddl.convert("varchar(20)")).isEqualTo("String");
assertThat(ddl.convert("json")).isEqualTo("JSON");
assertThat(ddl.convert("jsonb")).isEqualTo("JSON");
assertThat(ddl.convert("decimal(10)")).isEqualTo("Decimal(10)");
assertThat(ddl.convert("decimal(8,4)")).isEqualTo("Decimal(8,4)");
assertThat(ddl.convert("decimal")).isEqualTo("Decimal(16,3)");
assertThat(ddl.convert("boolean")).isEqualTo("Bool");
assertThat(ddl.convert("bit")).isEqualTo("bit");
}
}
@@ -0,0 +1,56 @@
package io.ebeaninternal.dbmigration.ddlgeneration.platform;
import io.ebean.platform.clickhouse.ClickHousePlatform;
import io.ebeaninternal.dbmigration.migration.Column;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class ClickHouseDdlTest {
private final ClickHouseDdl ddl = new ClickHouseDdl(new ClickHousePlatform());
@Test
void convert() {
assertThat(ddl.convert("boolean")).isEqualTo("Bool");
assertThat(ddl.convert("integer")).isEqualTo("UInt32");
assertThat(ddl.convert("bigint")).isEqualTo("UInt64");
assertThat(ddl.convert("decimal(20,3)")).isEqualTo("Decimal(20,3)");
assertThat(ddl.convert("varchar(20)")).isEqualTo("String");
assertThat(ddl.convert("hstore")).isEqualTo("Map(String,String)");
assertThat(ddl.convert("json")).isEqualTo("JSON");
assertThat(ddl.convert("varchar[]")).isEqualTo("Array(String)");
}
@Test
void columnDefnNullable() {
Column column = new Column();
column.setType("varchar(20)");
column.setNotnull(null);
assertThat(ddl.columnDefn(column)).isEqualTo("Nullable(String)");
}
@Test
void columnDefnNullable2() {
Column column = new Column();
column.setType("varchar(20)");
column.setNotnull(Boolean.FALSE);
assertThat(ddl.columnDefn(column)).isEqualTo("Nullable(String)");
}
@Test
void columnDefnNotNull() {
Column column = new Column();
column.setType("varchar(20)");
column.setNotnull(Boolean.TRUE);
assertThat(ddl.columnDefn(column)).isEqualTo("String");
}
@Test
void columnDefnNotNullPrimaryKey() {
Column column = new Column();
column.setType("varchar(20)");
column.setPrimaryKey(Boolean.TRUE);
assertThat(ddl.columnDefn(column)).isEqualTo("String");
}
}
@@ -123,8 +123,8 @@ class DbTypeMapTest {
assertThat(dbTypeMap.lookup("varchar", true).renderType(20, 0)).isEqualTo("String"); assertThat(dbTypeMap.lookup("varchar", true).renderType(20, 0)).isEqualTo("String");
assertThat(dbTypeMap.lookup("timestamp", false).renderType(0, 0)).isEqualTo("DateTime"); assertThat(dbTypeMap.lookup("timestamp", false).renderType(0, 0)).isEqualTo("DateTime");
assertThat(dbTypeMap.lookup("localdatetime", false).renderType(0, 0)).isEqualTo("DateTime"); assertThat(dbTypeMap.lookup("localdatetime", false).renderType(0, 0)).isEqualTo("DateTime");
assertThat(dbTypeMap.lookup("json", false).renderType(0, 0)).isEqualTo("String"); assertThat(dbTypeMap.lookup("json", false).renderType(0, 0)).isEqualTo("JSON");
assertThat(dbTypeMap.lookup("jsonb", false).renderType(0, 0)).isEqualTo("String"); assertThat(dbTypeMap.lookup("jsonb", false).renderType(0, 0)).isEqualTo("JSON");
assertThat(dbTypeMap.lookup("jsonclob", false).renderType(0, 0)).isEqualTo("String"); assertThat(dbTypeMap.lookup("jsonclob", false).renderType(0, 0)).isEqualTo("String");
assertThat(dbTypeMap.lookup("jsonblob", false).renderType(0, 0)).isEqualTo("blob"); assertThat(dbTypeMap.lookup("jsonblob", false).renderType(0, 0)).isEqualTo("blob");
assertThat(dbTypeMap.lookup("jsonvarchar", false).renderType(200, 0)).isEqualTo("String"); assertThat(dbTypeMap.lookup("jsonvarchar", false).renderType(200, 0)).isEqualTo("String");
@@ -2,24 +2,24 @@
-- apply changes -- apply changes
create table migtest_ckey_assoc ( create table migtest_ckey_assoc (
id UInt32, id UInt32,
assoc_one String assoc_one Nullable(String)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_ckey_detail ( create table migtest_ckey_detail (
id UInt32, id UInt32,
something String something Nullable(String)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_ckey_parent ( create table migtest_ckey_parent (
one_key UInt32, one_key UInt32,
two_key String, two_key String,
name String, name Nullable(String),
version UInt32 version UInt32
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_fk_cascade ( create table migtest_fk_cascade (
id UInt64, id UInt64,
one_id UInt64 one_id Nullable(UInt64)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_fk_cascade_one ( create table migtest_fk_cascade_one (
@@ -28,12 +28,12 @@ create table migtest_fk_cascade_one (
create table migtest_fk_none ( create table migtest_fk_none (
id UInt64, id UInt64,
one_id UInt64 one_id Nullable(UInt64)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_fk_none_via_join ( create table migtest_fk_none_via_join (
id UInt64, id UInt64,
one_id UInt64 one_id Nullable(UInt64)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_fk_one ( create table migtest_fk_one (
@@ -42,73 +42,73 @@ create table migtest_fk_one (
create table migtest_fk_set_null ( create table migtest_fk_set_null (
id UInt64, id UInt64,
one_id UInt64 one_id Nullable(UInt64)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_e_basic ( create table migtest_e_basic (
id UInt32, id UInt32,
status String, status Nullable(String),
status2 String default 'N', status2 String default 'N',
name String, name Nullable(String),
description String, description Nullable(String),
description_file blob, description_file Nullable(blob),
json_list String, json_list Nullable(JSON),
a_lob String default 'X', a_lob String default 'X',
some_date DateTime, some_date Nullable(DateTime),
old_boolean UInt8 default 0, old_boolean Bool default false,
old_boolean2 UInt8, old_boolean2 Nullable(Bool),
eref_id UInt32, eref_id Nullable(UInt32),
indextest1 String, indextest1 Nullable(String),
indextest2 String, indextest2 Nullable(String),
indextest3 String, indextest3 Nullable(String),
indextest4 String, indextest4 Nullable(String),
indextest5 String, indextest5 Nullable(String),
indextest6 String, indextest6 Nullable(String),
user_id UInt32 user_id UInt32
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_e_enum ( create table migtest_e_enum (
id UInt32, id UInt32,
test_status String test_status Nullable(String)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_e_history ( create table migtest_e_history (
id UInt32, id UInt32,
test_string String test_string Nullable(String)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_e_history2 ( create table migtest_e_history2 (
id UInt32, id UInt32,
test_string String, test_string Nullable(String),
obsolete_string1 String, obsolete_string1 Nullable(String),
obsolete_string2 String obsolete_string2 Nullable(String)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_e_history3 ( create table migtest_e_history3 (
id UInt32, id UInt32,
test_string String test_string Nullable(String)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_e_history4 ( create table migtest_e_history4 (
id UInt32, id UInt32,
test_number UInt32 test_number Nullable(UInt32)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_e_history5 ( create table migtest_e_history5 (
id UInt32, id UInt32,
test_number UInt32 test_number Nullable(UInt32)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_e_history6 ( create table migtest_e_history6 (
id UInt32, id UInt32,
test_number1 UInt32, test_number1 Nullable(UInt32),
test_number2 UInt32 test_number2 UInt32
) ENGINE = Log(); ) ENGINE = Log();
create table "migtest_QuOtEd" ( create table "migtest_QuOtEd" (
id String, id String,
status1 String, status1 Nullable(String),
status2 String status2 Nullable(String)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_e_ref ( create table migtest_e_ref (
@@ -118,35 +118,35 @@ create table migtest_e_ref (
create table migtest_e_softdelete ( create table migtest_e_softdelete (
id UInt32, id UInt32,
test_string String test_string Nullable(String)
) ENGINE = Log(); ) ENGINE = Log();
create table "table" ( create table "table" (
"index" String, "index" String,
"from" String, "from" Nullable(String),
"to" String, "to" Nullable(String),
"varchar" String, "varchar" Nullable(String),
"foreign" String, "foreign" Nullable(String),
textfield String textfield String
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_mtm_c ( create table migtest_mtm_c (
id UInt32, id UInt32,
name String name Nullable(String)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_mtm_m ( create table migtest_mtm_m (
id UInt64, id UInt64,
name String name Nullable(String)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_oto_child ( create table migtest_oto_child (
id UInt32, id UInt32,
name String name Nullable(String)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_oto_master ( create table migtest_oto_master (
id UInt64, id UInt64,
name String name Nullable(String)
) ENGINE = Log(); ) ENGINE = Log();
@@ -21,104 +21,104 @@ create table drop_ref_many (
create table drop_ref_one ( create table drop_ref_one (
id UInt32, id UInt32,
parent_id UInt32 parent_id Nullable(UInt32)
) ENGINE = Log(); ) ENGINE = Log();
create table drop_ref_one_to_one ( create table drop_ref_one_to_one (
id UInt32, id UInt32,
parent_id UInt32 parent_id Nullable(UInt32)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_e_test_binary ( create table migtest_e_test_binary (
id UInt32, id UInt32,
test_byte16 String, test_byte16 Nullable(String),
test_byte256 String, test_byte256 Nullable(String),
test_byte512 String, test_byte512 Nullable(String),
test_byte1k String, test_byte1k Nullable(String),
test_byte2k String, test_byte2k Nullable(String),
test_byte4k String, test_byte4k Nullable(String),
test_byte8k String, test_byte8k Nullable(String),
test_byte16k String, test_byte16k Nullable(String),
test_byte32k String, test_byte32k Nullable(String),
test_byte64k String, test_byte64k Nullable(String),
test_byte128k String, test_byte128k Nullable(String),
test_byte256k String, test_byte256k Nullable(String),
test_byte512k String, test_byte512k Nullable(String),
test_byte1m String, test_byte1m Nullable(String),
test_byte2m String, test_byte2m Nullable(String),
test_byte4m String, test_byte4m Nullable(String),
test_byte8m String, test_byte8m Nullable(String),
test_byte16m String, test_byte16m Nullable(String),
test_byte32m String test_byte32m Nullable(String)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_e_test_json ( create table migtest_e_test_json (
id UInt32, id UInt32,
json255 String, json255 Nullable(JSON),
json256 String, json256 Nullable(JSON),
json512 String, json512 Nullable(JSON),
json1k String, json1k Nullable(JSON),
json2k String, json2k Nullable(JSON),
json4k String, json4k Nullable(JSON),
json8k String, json8k Nullable(JSON),
json16k String, json16k Nullable(JSON),
json32k String, json32k Nullable(JSON),
json64k String, json64k Nullable(JSON),
json128k String, json128k Nullable(JSON),
json256k String, json256k Nullable(JSON),
json512k String, json512k Nullable(JSON),
json1m String, json1m Nullable(JSON),
json2m String, json2m Nullable(JSON),
json4m String, json4m Nullable(JSON),
json8m String, json8m Nullable(JSON),
json16m String, json16m Nullable(JSON),
json32m String json32m Nullable(JSON)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_e_test_lob ( create table migtest_e_test_lob (
id UInt32, id UInt32,
lob255 String, lob255 Nullable(String),
lob256 String, lob256 Nullable(String),
lob512 String, lob512 Nullable(String),
lob1k String, lob1k Nullable(String),
lob2k String, lob2k Nullable(String),
lob4k String, lob4k Nullable(String),
lob8k String, lob8k Nullable(String),
lob16k String, lob16k Nullable(String),
lob32k String, lob32k Nullable(String),
lob64k String, lob64k Nullable(String),
lob128k String, lob128k Nullable(String),
lob256k String, lob256k Nullable(String),
lob512k String, lob512k Nullable(String),
lob1m String, lob1m Nullable(String),
lob2m String, lob2m Nullable(String),
lob4m String, lob4m Nullable(String),
lob8m String, lob8m Nullable(String),
lob16m String, lob16m Nullable(String),
lob32m String lob32m Nullable(String)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_e_test_varchar ( create table migtest_e_test_varchar (
id UInt32, id UInt32,
varchar255 String, varchar255 Nullable(String),
varchar256 String, varchar256 Nullable(String),
varchar512 String, varchar512 Nullable(String),
varchar1k String, varchar1k Nullable(String),
varchar2k String, varchar2k Nullable(String),
varchar4k String, varchar4k Nullable(String),
varchar8k String, varchar8k Nullable(String),
varchar16k String, varchar16k Nullable(String),
varchar32k String, varchar32k Nullable(String),
varchar64k String, varchar64k Nullable(String),
varchar128k String, varchar128k Nullable(String),
varchar256k String, varchar256k Nullable(String),
varchar512k String, varchar512k Nullable(String),
varchar1m String, varchar1m Nullable(String),
varchar2m String, varchar2m Nullable(String),
varchar4m String, varchar4m Nullable(String),
varchar8m String, varchar8m Nullable(String),
varchar16m String, varchar16m Nullable(String),
varchar32m String varchar32m Nullable(String)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_e_user ( create table migtest_e_user (
@@ -168,8 +168,8 @@ alter table migtest_e_basic alter column a_lob drop default;
alter table migtest_e_basic alter column a_lob set null; alter table migtest_e_basic alter column a_lob set null;
alter table migtest_e_basic alter column user_id set null; alter table migtest_e_basic alter column user_id set null;
alter table migtest_e_basic add column new_string_field String default 'foo''bar'; alter table migtest_e_basic add column new_string_field String default 'foo''bar';
alter table migtest_e_basic add column new_boolean_field UInt8 default 1; alter table migtest_e_basic add column new_boolean_field Bool default true;
alter table migtest_e_basic add column new_boolean_field2 UInt8 default 1; alter table migtest_e_basic add column new_boolean_field2 Bool default true;
alter table migtest_e_basic add column progress UInt32 default 0; alter table migtest_e_basic add column progress UInt32 default 0;
alter table migtest_e_basic add column new_integer UInt32 default 42; alter table migtest_e_basic add column new_integer UInt32 default 42;
alter table migtest_e_history alter column test_string UInt64; alter table migtest_e_history alter column test_string UInt64;
@@ -179,11 +179,11 @@ alter table migtest_e_history2 add column test_string2 String;
alter table migtest_e_history2 add column test_string3 String default 'unknown'; alter table migtest_e_history2 add column test_string3 String default 'unknown';
alter table migtest_e_history2 add column new_column String; alter table migtest_e_history2 add column new_column String;
alter table migtest_e_history4 alter column test_number UInt64; alter table migtest_e_history4 alter column test_number UInt64;
alter table migtest_e_history5 add column test_boolean UInt8 default 0; alter table migtest_e_history5 add column test_boolean Bool default false;
alter table migtest_e_history6 alter column test_number1 set default 42; alter table migtest_e_history6 alter column test_number1 set default 42;
alter table migtest_e_history6 alter column test_number1 set not null; alter table migtest_e_history6 alter column test_number1 set not null;
alter table migtest_e_history6 alter column test_number2 set null; alter table migtest_e_history6 alter column test_number2 set null;
alter table migtest_e_softdelete add column deleted UInt8 default 0; alter table migtest_e_softdelete add column deleted Bool default false;
alter table migtest_oto_child add column master_id UInt64; alter table migtest_oto_child add column master_id UInt64;
-- apply post alter -- apply post alter
alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I','?')); alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I','?'));
@@ -11,8 +11,8 @@ alter table migtest_e_enum drop constraint if exists ck_migtest_e_enum_test_stat
-- apply changes -- apply changes
create table "migtest_QuOtEd" ( create table "migtest_QuOtEd" (
id String, id String,
status1 String, status1 Nullable(String),
status2 String status2 Nullable(String)
) ENGINE = Log(); ) ENGINE = Log();
create table migtest_e_ref ( create table migtest_e_ref (
@@ -41,8 +41,8 @@ alter table migtest_e_basic alter column a_lob set not null;
alter table migtest_e_basic alter column user_id set default 23; alter table migtest_e_basic alter column user_id set default 23;
alter table migtest_e_basic alter column user_id set not null; alter table migtest_e_basic alter column user_id set not null;
alter table migtest_e_basic add column description_file blob; alter table migtest_e_basic add column description_file blob;
alter table migtest_e_basic add column old_boolean UInt8 default 0; alter table migtest_e_basic add column old_boolean Bool default false;
alter table migtest_e_basic add column old_boolean2 UInt8; alter table migtest_e_basic add column old_boolean2 Bool;
alter table migtest_e_basic add column eref_id UInt32; alter table migtest_e_basic add column eref_id UInt32;
alter table migtest_e_history2 alter column test_string drop default; alter table migtest_e_history2 alter column test_string drop default;
alter table migtest_e_history2 alter column test_string set null; alter table migtest_e_history2 alter column test_string set null;
@@ -1,6 +1,6 @@
193400547, 1.0__initial.sql 1470313592, 1.0__initial.sql
-1021430823, 1.1.sql -1717710527, 1.1.sql
688811494, 1.2__dropsFor_1.1.sql 688811494, 1.2__dropsFor_1.1.sql
1015552567, 1.3.sql 864347736, 1.3.sql
1436420661, 1.4__dropsFor_1.3.sql 1436420661, 1.4__dropsFor_1.3.sql
@@ -0,0 +1,33 @@
package io.ebean.platform.clickhouse;
import io.ebean.config.dbplatform.InsertSqlSyntaxExtension;
public final class ClickHouseInsertSqlSyntax implements InsertSqlSyntaxExtension {
// insert into mytable select col1, col2 from input('col1 String, col2 DateTime64(3), col3 Int32')
@Override
public String startColumns() {
return " select ";
}
@Override
public String endColumns() {
return " from";
}
@Override
public boolean useBinding() {
return false;
}
@Override
public String startTypes() {
return " input('";
}
@Override
public String endTypes() {
return "')";
}
}
@@ -13,13 +13,9 @@ public class ClickHousePlatform extends DatabasePlatform {
public ClickHousePlatform() { public ClickHousePlatform() {
super(); super();
this.platform = Platform.CLICKHOUSE; this.platform = Platform.CLICKHOUSE;
//this.dbEncrypt = this.insertSqlSyntaxExtension = new ClickHouseInsertSqlSyntax();
//this.historySupport =
//this.exceptionTranslator =
this.nativeUuidType = true; this.nativeUuidType = true;
this.dbDefaultValue.setNow("now()"); this.dbDefaultValue.setNow("now()");
this.dbDefaultValue.setFalse("0");
this.dbDefaultValue.setTrue("1");
this.dbIdentity.setIdType(IdType.IDENTITY); this.dbIdentity.setIdType(IdType.IDENTITY);
this.dbIdentity.setSupportsGetGeneratedKeys(false); this.dbIdentity.setSupportsGetGeneratedKeys(false);
@@ -27,7 +23,7 @@ public class ClickHousePlatform extends DatabasePlatform {
this.dbIdentity.setSupportsIdentity(true); this.dbIdentity.setSupportsIdentity(true);
this.booleanDbType = Types.INTEGER; this.booleanDbType = Types.INTEGER;
dbTypeMap.put(DbType.BOOLEAN, new DbPlatformType("UInt8")); dbTypeMap.put(DbType.BOOLEAN, new DbPlatformType("Bool"));
// using unsigned as default types ... // using unsigned as default types ...
dbTypeMap.put(DbType.TINYINT, new DbPlatformType("UInt8", false)); dbTypeMap.put(DbType.TINYINT, new DbPlatformType("UInt8", false));
dbTypeMap.put(DbType.SMALLINT, new DbPlatformType("UInt16", false)); dbTypeMap.put(DbType.SMALLINT, new DbPlatformType("UInt16", false));
@@ -41,7 +37,10 @@ public class ClickHousePlatform extends DatabasePlatform {
dbTypeMap.put(DbType.VARCHAR, new DbPlatformType("String", false)); dbTypeMap.put(DbType.VARCHAR, new DbPlatformType("String", false));
dbTypeMap.put(DbType.LONGVARCHAR, new DbPlatformType("String", false)); dbTypeMap.put(DbType.LONGVARCHAR, new DbPlatformType("String", false));
dbTypeMap.put(DbType.CLOB, new DbPlatformType("String", false)); dbTypeMap.put(DbType.CLOB, new DbPlatformType("String", false));
dbTypeMap.put(DbType.JSONVARCHAR, new DbPlatformType("String", false)); dbTypeMap.put(DbType.HSTORE, new DbPlatformType("Map(String,String)", false));
dbTypeMap.put(DbType.JSON, new DbPlatformType("JSON", false));
dbTypeMap.put(DbType.JSONB, new DbPlatformType("JSON", false));
dbTypeMap.put(DbType.JSONVARCHAR, new DbPlatformType("JSON", false));
dbTypeMap.put(DbType.UUID, new DbPlatformType("UUID", false)); dbTypeMap.put(DbType.UUID, new DbPlatformType("UUID", false));
dbTypeMap.put(DbType.INET, new DbPlatformType("String", false)); dbTypeMap.put(DbType.INET, new DbPlatformType("String", false));
dbTypeMap.put(DbType.CIDR, new DbPlatformType("String", false)); dbTypeMap.put(DbType.CIDR, new DbPlatformType("String", false));