-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support table creation DDL translation #194
Changes from all commits
bccac22
838517f
d629a16
31ab485
1c0e801
2bc24a3
7d9bb8d
81fd866
80ad018
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ | |
|
||
import com.feedzai.commons.sql.abstraction.ddl.AlterColumn; | ||
import com.feedzai.commons.sql.abstraction.ddl.DbColumn; | ||
import com.feedzai.commons.sql.abstraction.ddl.DbEntity; | ||
import com.feedzai.commons.sql.abstraction.ddl.DropPrimaryKey; | ||
import com.feedzai.commons.sql.abstraction.ddl.Rename; | ||
import com.feedzai.commons.sql.abstraction.dml.Between; | ||
|
@@ -44,6 +45,7 @@ | |
import com.feedzai.commons.sql.abstraction.dml.dialect.SqlBuilder; | ||
import com.feedzai.commons.sql.abstraction.engine.configuration.PdbProperties; | ||
import com.google.common.base.Joiner; | ||
import java.util.Collections; | ||
import com.google.inject.Inject; | ||
import com.google.inject.Injector; | ||
import org.apache.commons.lang3.StringUtils; | ||
|
@@ -631,4 +633,58 @@ protected Union rowsToUnion(final List<Expression> rows) { | |
* @return The string representation of the given object. | ||
*/ | ||
public abstract String translate(StringAgg stringAgg); | ||
|
||
/** | ||
* Translates the given entity table creation to the current dialect. | ||
* | ||
* @param entity The entity to translate. | ||
* @return The create table translation result. | ||
*/ | ||
public abstract String translateCreateTable(DbEntity entity); | ||
|
||
/** | ||
* Translates the primary key not null constraints of the given entity table to the current dialect. | ||
* | ||
* @param entity The entity to translate. | ||
* @return The primary key not null constraints translation result. | ||
*/ | ||
public String translatePrimaryKeysNotNull(DbEntity entity) { | ||
// usually engines don't need to specify columns as not nulls to be PK. | ||
return ""; | ||
} | ||
Comment on lines
+645
to
+654
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When creating a table, the PRIMARY KEY columns should already be specified as NOT NULL if really needed. I suppose that the other engines that don't need this already assume that the PRIMARY KEY column is NOT NULL implicitly. |
||
|
||
/** | ||
* Translates the primary key constraints of the given entity table to the current dialect. | ||
* | ||
* @param entity The entity to translate. | ||
* @return The primary key constraints translation result. | ||
*/ | ||
public abstract String translatePrimaryKeysConstraints(DbEntity entity); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if the method |
||
|
||
/** | ||
* Translates the foreign key constraints of the given entity table to the current dialect. | ||
* | ||
* @param entity The entity to translate. | ||
* @return The foreign key constraints translation result. | ||
*/ | ||
public abstract List<String> translateForeignKey(DbEntity entity); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. translateForeignKeys |
||
|
||
/** | ||
* Translates the index creation of the given entity table to the current dialect. | ||
* | ||
* @param entity The entity to translate. | ||
* @return The index creation translation result. | ||
*/ | ||
public abstract List<String> translateCreateIndexes(DbEntity entity); | ||
|
||
/** | ||
* Translates the sequence creation of the given entity table to the current dialect. | ||
* | ||
* @param entity The entity to translate. | ||
* @return The sequence creation translation result. | ||
*/ | ||
public List<String> translateCreateSequences(DbEntity entity) { | ||
// the majority of engines don't need additional SQL to create sequences. | ||
return Collections.emptyList(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -230,6 +230,14 @@ public interface DatabaseEngine extends AutoCloseable { | |
*/ | ||
String translate(final Expression query); | ||
|
||
/** | ||
* Translates the given entity creation to the current dialect. | ||
* | ||
* @param entity The entity to translate. | ||
* @return The translation result. | ||
*/ | ||
String translateTableCreation(final DbEntity entity); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a breaking change that will require classes that implement this interface Let's avoid this, by turning this method into a default method that throws an |
||
|
||
/** | ||
* Gets the dialect being used. | ||
* | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,17 +17,23 @@ | |
package com.feedzai.commons.sql.abstraction.engine.impl; | ||
|
||
import com.feedzai.commons.sql.abstraction.ddl.DbColumn; | ||
import com.feedzai.commons.sql.abstraction.ddl.DbColumnConstraint; | ||
import com.feedzai.commons.sql.abstraction.ddl.DbEntity; | ||
import com.feedzai.commons.sql.abstraction.dml.Cast; | ||
import com.feedzai.commons.sql.abstraction.dml.Expression; | ||
import com.feedzai.commons.sql.abstraction.dml.RepeatDelimiter; | ||
import com.feedzai.commons.sql.abstraction.engine.DatabaseEngineException; | ||
import com.feedzai.commons.sql.abstraction.engine.DatabaseEngineRuntimeException; | ||
import com.feedzai.commons.sql.abstraction.engine.OperationNotSupportedRuntimeException; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import static com.feedzai.commons.sql.abstraction.engine.configuration.PdbProperties.VARCHAR_SIZE; | ||
import static com.feedzai.commons.sql.abstraction.util.StringUtils.md5; | ||
import static com.feedzai.commons.sql.abstraction.util.StringUtils.quotize; | ||
import static java.lang.String.format; | ||
import static org.apache.commons.lang3.StringUtils.join; | ||
|
||
/** | ||
* Provides SQL translation for CockroachDB. | ||
|
@@ -126,4 +132,103 @@ public String translate(final RepeatDelimiter rd) { | |
return join(all, delimiter); | ||
} | ||
} | ||
|
||
@Override | ||
public String translateCreateTable(final DbEntity entity) { | ||
final List<String> createTable = new ArrayList<>(); | ||
|
||
createTable.add("CREATE TABLE"); | ||
createTable.add(quotize(entity.getName())); | ||
|
||
// COLUMNS | ||
final List<String> columns = new ArrayList<>(); | ||
for (DbColumn c : entity.getColumns()) { | ||
final List<String> column = new ArrayList<>(); | ||
column.add(quotize(c.getName())); | ||
column.add(translate(c)); | ||
|
||
for (DbColumnConstraint cc : c.getColumnConstraints()) { | ||
column.add(cc.translate()); | ||
} | ||
|
||
if (c.isDefaultValueSet()) { | ||
column.add("DEFAULT"); | ||
column.add(translate(c.getDefaultValue())); | ||
} | ||
|
||
columns.add(join(column, " ")); | ||
} | ||
createTable.add("(" + join(columns, ", ")); | ||
// COLUMNS end | ||
|
||
|
||
// PRIMARY KEY | ||
final List<String> pks = new ArrayList<>(); | ||
for (String pk : entity.getPkFields()) { | ||
pks.add(quotize(pk)); | ||
} | ||
|
||
if (!pks.isEmpty()) { | ||
createTable.add(","); | ||
|
||
final String pkName = md5(format("PK_%s", entity.getName()), properties.getMaxIdentifierSize()); | ||
|
||
createTable.add("CONSTRAINT"); | ||
createTable.add(quotize(pkName)); | ||
createTable.add("PRIMARY KEY"); | ||
createTable.add("(" + join(pks, ", ") + ")"); | ||
} | ||
// PK end | ||
|
||
createTable.add(")"); | ||
|
||
return join(createTable, " "); | ||
} | ||
|
||
@Override | ||
public String translatePrimaryKeysConstraints(final DbEntity entity) { | ||
// primary keys are created on table creation. | ||
return ""; | ||
} | ||
|
||
@Override | ||
public List<String> translateCreateIndexes(final DbEntity entity) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should take a look at the tests, they didn't fail with this change and they should... |
||
final List<String> createSeqs = new ArrayList<>(); | ||
|
||
for (final DbColumn column : entity.getColumns()) { | ||
if (!column.isAutoInc()) { | ||
continue; | ||
} | ||
|
||
final String sequenceName = quotize(md5(format("%s_%s_SEQ", entity.getName(), column.getName()), | ||
properties.getMaxIdentifierSize())); | ||
|
||
final StringBuilder createSequence = new StringBuilder() | ||
.append("CREATE SEQUENCE ") | ||
.append(sequenceName) | ||
.append(" MINVALUE 0 MAXVALUE "); | ||
switch (column.getDbColumnType()) { | ||
case INT: | ||
createSequence.append(Integer.MAX_VALUE); | ||
break; | ||
case LONG: | ||
createSequence.append(Long.MAX_VALUE); | ||
break; | ||
default: | ||
throw new DatabaseEngineRuntimeException("Auto incrementation is only supported on INT and LONG"); | ||
} | ||
createSequence.append(" START 1 INCREMENT 1;"); | ||
|
||
createSequence.append("ALTER TABLE ") | ||
.append(quotize(entity.getName())) | ||
.append(" ALTER COLUMN ") | ||
.append(quotize(column.getName())) | ||
.append(" SET DEFAULT nextval('").append(sequenceName).append("')"); | ||
|
||
final String statement = createSequence.toString(); | ||
|
||
createSeqs.add(statement); | ||
} | ||
return createSeqs; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just checked this with H2 and PostgreSQL on the following entity:
With H2 it doesn't work, throws
UnsupportedOperationException
(see my comment in H2Translator.java);with PostgreSQL, the result is
This is kind of messy to look at in a log, and it is almost useless as input for another tool.
;
and start in a new line.[]
; the translations should all result in strings.Maybe you could use something like
(each translate* that returns a list should first be converted into a string with
String.join(";\n", list)
)By following that, we get