mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-24 15:55:55 +00:00
#374 - removed old ddl generation mechanism
This commit is contained in:
@@ -249,7 +249,7 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
|
||||
for (SpiEbeanPlugin plugin : ServiceLoader.load(SpiEbeanPlugin.class)) {
|
||||
spiPlugins.add(plugin);
|
||||
plugin.setup(this, this.getDatabasePlatform(), config);
|
||||
plugin.setup(this, config);
|
||||
|
||||
if (plugin instanceof DdlGenerator) {
|
||||
// backwards compatible
|
||||
@@ -261,7 +261,7 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
// ServiceLoader not finding ddlGenerator (typically OSGi)
|
||||
ddlGenerator = new DdlGenerator();
|
||||
spiPlugins.add(ddlGenerator);
|
||||
ddlGenerator.setup(this, this.getDatabasePlatform(), config);
|
||||
ddlGenerator.setup(this, config);
|
||||
}
|
||||
|
||||
ebeanPlugins = Collections.unmodifiableList(spiPlugins);
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.ddl;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
|
||||
import com.avaje.ebeaninternal.server.deploy.InheritInfoVisitor;
|
||||
|
||||
/**
|
||||
* Base BeanVisitor that can help visiting inherited properties.
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public abstract class AbstractBeanVisitor implements BeanVisitor {
|
||||
|
||||
/**
|
||||
* Visit all the other inheritance properties that are not on the root.
|
||||
*/
|
||||
public void visitInheritanceProperties(BeanDescriptor<?> descriptor, PropertyVisitor pv) {
|
||||
|
||||
InheritInfo inheritInfo = descriptor.getInheritInfo();
|
||||
if (inheritInfo != null && inheritInfo.isRoot()){
|
||||
// add all properties on the children objects
|
||||
InheritChildVisitor childVisitor = new InheritChildVisitor(pv);
|
||||
inheritInfo.visitChildren(childVisitor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper used to visit all the inheritInfo/BeanDescriptor in
|
||||
* the inheritance hierarchy (to add their 'local' properties).
|
||||
*/
|
||||
protected static class InheritChildVisitor implements InheritInfoVisitor {
|
||||
|
||||
final PropertyVisitor pv;
|
||||
|
||||
protected InheritChildVisitor(PropertyVisitor pv) {
|
||||
this.pv = pv;
|
||||
}
|
||||
|
||||
public void visit(InheritInfo inheritInfo) {
|
||||
BeanProperty[] propertiesLocal = inheritInfo.getBeanDescriptor().propertiesLocal();
|
||||
VisitorUtil.visit(propertiesLocal, pv);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.ddl;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompound;
|
||||
|
||||
/**
|
||||
* Has no implementation. Can be used as a base object so that
|
||||
* selective methods can be implemented.
|
||||
*/
|
||||
public abstract class AbstractPropertyVisitor implements PropertyVisitor {
|
||||
|
||||
public void visitEmbedded(BeanPropertyAssocOne<?> p) {
|
||||
}
|
||||
|
||||
public void visitEmbeddedScalar(BeanProperty p, BeanPropertyAssocOne<?> embedded) {
|
||||
}
|
||||
|
||||
public void visitMany(BeanPropertyAssocMany<?> p) {
|
||||
}
|
||||
|
||||
public void visitOneExported(BeanPropertyAssocOne<?> p) {
|
||||
}
|
||||
|
||||
public void visitOneImported(BeanPropertyAssocOne<?> p) {
|
||||
}
|
||||
|
||||
public void visitScalar(BeanProperty p) {
|
||||
}
|
||||
|
||||
public void visitCompound(BeanPropertyCompound p) {
|
||||
}
|
||||
|
||||
public void visitCompoundScalar(BeanPropertyCompound compound, BeanProperty p) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.ddl;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.DbDdlSyntax;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompound;
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoin;
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoinColumn;
|
||||
|
||||
/**
|
||||
* Used to generate the foreign key DDL and related indexes.
|
||||
*/
|
||||
public class AddForeignKeysVisitor extends AbstractBeanVisitor {
|
||||
|
||||
final DdlGenContext ctx;
|
||||
|
||||
final FkeyPropertyVisitor pv;
|
||||
|
||||
public AddForeignKeysVisitor(boolean addMode, DdlGenContext ctx) {
|
||||
this.ctx = ctx;
|
||||
this.pv = new FkeyPropertyVisitor(addMode, this, ctx);
|
||||
}
|
||||
|
||||
public boolean visitBean(BeanDescriptor<?> descriptor) {
|
||||
return descriptor.isInheritanceRoot();
|
||||
}
|
||||
|
||||
public void visitBeanEnd(BeanDescriptor<?> descriptor) {
|
||||
|
||||
visitInheritanceProperties(descriptor, pv);
|
||||
}
|
||||
|
||||
public void visitBegin() {
|
||||
}
|
||||
|
||||
public void visitEnd() {
|
||||
ctx.addIntersectionFkeys();
|
||||
}
|
||||
|
||||
public PropertyVisitor visitProperty(BeanProperty p) {
|
||||
return pv;
|
||||
}
|
||||
|
||||
|
||||
public static class FkeyPropertyVisitor extends BaseTablePropertyVisitor {
|
||||
|
||||
/**
|
||||
* Set to false when generating drop foreign key statements.
|
||||
*/
|
||||
final boolean addMode;
|
||||
|
||||
final DdlGenContext ctx;
|
||||
|
||||
final AddForeignKeysVisitor parent;
|
||||
|
||||
public FkeyPropertyVisitor(boolean addMode, AddForeignKeysVisitor parent, DdlGenContext ctx) {
|
||||
this.addMode = addMode;
|
||||
this.parent = parent;
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEmbeddedScalar(BeanProperty p, BeanPropertyAssocOne<?> embedded) {
|
||||
// not interested
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOneImported(BeanPropertyAssocOne<?> p) {
|
||||
|
||||
// alter table {basetable} add foreign key (...) references {} (...) on delete restrict on update restrict;
|
||||
// Alter table o_address add Foreign Key (country_code) references o_country (code) on delete restrict on update restrict;
|
||||
|
||||
String baseTable = p.getBeanDescriptor().getBaseTable();
|
||||
TableJoin tableJoin = p.getTableJoin();
|
||||
TableJoinColumn[] columns = tableJoin.columns();
|
||||
|
||||
String tableName = p.getBeanDescriptor().getBaseTable();
|
||||
DbDdlSyntax ddlSyntax = ctx.getDdlSyntax();
|
||||
String fkName = ddlSyntax.getForeignKeyName(tableName, p.getName(), ctx.incrementFkCount());
|
||||
|
||||
if (!addMode) {
|
||||
// look to generate drop foreign key statement
|
||||
String dropKeyConstraintPrefix = ddlSyntax.dropKeyConstraintPrefix(tableName, fkName);
|
||||
if (dropKeyConstraintPrefix != null && !dropKeyConstraintPrefix.isEmpty()) {
|
||||
ctx.write(dropKeyConstraintPrefix).write(" ");
|
||||
}
|
||||
}
|
||||
|
||||
ctx.write("alter table ").write(baseTable).write(addOrDrop());
|
||||
if (fkName != null) {
|
||||
ctx.write("constraint ").write(fkName).write(" ");
|
||||
}
|
||||
if (addMode) {
|
||||
ctx.write("foreign key (");
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
if (i > 0) {
|
||||
ctx.write(",");
|
||||
}
|
||||
ctx.write(columns[i].getLocalDbColumn());
|
||||
}
|
||||
ctx.write(")");
|
||||
|
||||
ctx.write(" references ");
|
||||
ctx.write(tableJoin.getTable());
|
||||
ctx.write(" (");
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
if (i > 0) {
|
||||
ctx.write(",");
|
||||
}
|
||||
ctx.write(columns[i].getForeignDbColumn());
|
||||
}
|
||||
ctx.write(")");
|
||||
|
||||
String fkeySuffix = ctx.getDdlSyntax().getForeignKeySuffix();
|
||||
if (fkeySuffix != null) {
|
||||
ctx.write(" ").write(fkeySuffix);
|
||||
}
|
||||
}
|
||||
ctx.write(";").writeNewLine();
|
||||
|
||||
if (addMode && ddlSyntax.isRenderIndexForFkey()){
|
||||
|
||||
//create index idx_fk_o_address_ctry on o_address(country_code);
|
||||
ctx.write("create index ");
|
||||
|
||||
String idxName = ddlSyntax.getIndexName(tableName, p.getName(), ctx.incrementIxCount());
|
||||
if (idxName != null){
|
||||
ctx.write(idxName);
|
||||
}
|
||||
|
||||
ctx.write(" on ").write(baseTable).write(" (");
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
if (i > 0){
|
||||
ctx.write(",");
|
||||
}
|
||||
ctx.write(columns[i].getLocalDbColumn());
|
||||
}
|
||||
ctx.write(");").writeNewLine();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return 'add' or 'drop' of foreign key.
|
||||
*/
|
||||
protected String addOrDrop() {
|
||||
return addMode ? " add " : " drop " ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitScalar(BeanProperty p) {
|
||||
// not interested
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCompound(BeanPropertyCompound p) {
|
||||
// not interested
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCompoundScalar(BeanPropertyCompound compound, BeanProperty p) {
|
||||
// not interested
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.ddl;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompound;
|
||||
|
||||
/**
|
||||
* Used to help mark PropertyVisitor methods that need to be implemented
|
||||
* to visit base table properties.
|
||||
*/
|
||||
public abstract class BaseTablePropertyVisitor implements PropertyVisitor {
|
||||
|
||||
/**
|
||||
* Not required in that you can use the visitEmbeddedScalar.
|
||||
*/
|
||||
public void visitEmbedded(BeanPropertyAssocOne<?> p) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method.
|
||||
*/
|
||||
public abstract void visitEmbeddedScalar(BeanProperty p, BeanPropertyAssocOne<?> embedded);
|
||||
|
||||
/**
|
||||
* Not part of base table.
|
||||
*/
|
||||
public void visitMany(BeanPropertyAssocMany<?> p) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Not part of base table.
|
||||
*/
|
||||
public void visitOneExported(BeanPropertyAssocOne<?> p) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method for the foreign key.
|
||||
*/
|
||||
public abstract void visitOneImported(BeanPropertyAssocOne<?> p);
|
||||
|
||||
/**
|
||||
* Override this method for normal scalar property.
|
||||
*/
|
||||
public abstract void visitScalar(BeanProperty p);
|
||||
|
||||
/**
|
||||
* Not required in that the scalar properties map to the columns.
|
||||
*/
|
||||
public void visitCompound(BeanPropertyCompound p){
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method for scalar property inside a Immutable Compound Value object.
|
||||
*/
|
||||
public abstract void visitCompoundScalar(BeanPropertyCompound compound, BeanProperty p);
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.ddl;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
|
||||
/**
|
||||
* Visitor pattern for visiting a BeanDescriptor and potentially all its bean
|
||||
* properties.
|
||||
*/
|
||||
public interface BeanVisitor {
|
||||
|
||||
/**
|
||||
* Starting.
|
||||
*/
|
||||
void visitBegin();
|
||||
|
||||
/**
|
||||
* Visit a BeanDescriptor and return true to continue visiting the bean
|
||||
* (return false to skip visiting this bean).
|
||||
*/
|
||||
boolean visitBean(BeanDescriptor<?> descriptor);
|
||||
|
||||
/**
|
||||
* Visit a property potentially return a specific PropertyVisitor.
|
||||
* <p>
|
||||
* A PropertyVisitor can be returned to more easily process bean properties
|
||||
* by their specific type.
|
||||
* </p>
|
||||
*/
|
||||
PropertyVisitor visitProperty(BeanProperty p);
|
||||
|
||||
/**
|
||||
* Finished visiting the BeanDescriptor.
|
||||
*/
|
||||
void visitBeanEnd(BeanDescriptor<?> descriptor);
|
||||
|
||||
/**
|
||||
* Finished all visiting.
|
||||
*/
|
||||
void visitEnd();
|
||||
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.ddl;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompound;
|
||||
|
||||
/**
|
||||
* A visitor that creates indexes for columns annotated with ColumnIndex
|
||||
*
|
||||
* @author rvbiljouw
|
||||
* @see com.avaje.ebean.annotation.Index
|
||||
*/
|
||||
public class CreateIndexVisitor extends AbstractBeanVisitor {
|
||||
private final IndexPropertyVisitor iv;
|
||||
|
||||
public CreateIndexVisitor(DdlGenContext ctx) {
|
||||
this.iv = new IndexPropertyVisitor(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBegin() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visitBean(BeanDescriptor<?> descriptor) {
|
||||
return descriptor.isInheritanceRoot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyVisitor visitProperty(BeanProperty p) {
|
||||
return iv;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBeanEnd(BeanDescriptor<?> descriptor) {
|
||||
visitInheritanceProperties(descriptor, iv);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
|
||||
}
|
||||
|
||||
private static final class IndexPropertyVisitor extends BaseTablePropertyVisitor {
|
||||
private final DdlGenContext ctx;
|
||||
|
||||
public IndexPropertyVisitor(DdlGenContext ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEmbeddedScalar(BeanProperty p, BeanPropertyAssocOne<?> embedded) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOneImported(BeanPropertyAssocOne<?> p) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitScalar(BeanProperty p) {
|
||||
String baseTable = p.getBeanDescriptor().getBaseTable();
|
||||
if (p.isIndexed()) {
|
||||
String indexName = p.getIndexName();
|
||||
if (indexName.length() == 0) {
|
||||
indexName = ctx.getDdlSyntax().getIndexName(baseTable, p.getDbColumn(), ctx.incrementIxCount());
|
||||
}
|
||||
ctx.write("create index ")
|
||||
.write(indexName)
|
||||
.write(" on ")
|
||||
.write(baseTable)
|
||||
.write("(")
|
||||
.write(p.getDbColumn())
|
||||
.write(");")
|
||||
.writeNewLine();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCompoundScalar(BeanPropertyCompound compound, BeanProperty p) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.ddl;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoin;
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoinColumn;
|
||||
|
||||
|
||||
/**
|
||||
* Create the sql to create the intersection table and its foreign key
|
||||
* constraints.
|
||||
*/
|
||||
public class CreateIntersectionTable {
|
||||
|
||||
private static final String NEW_LINE = "\n";
|
||||
|
||||
private final DdlGenContext ctx;
|
||||
|
||||
private final BeanPropertyAssocMany<?> manyProp;
|
||||
private final TableJoin intersectionTableJoin;
|
||||
private final TableJoin tableJoin;
|
||||
|
||||
private final StringBuilder sb = new StringBuilder();
|
||||
|
||||
private final StringBuilder pkeySb = new StringBuilder();
|
||||
|
||||
private int foreignKeyCount;
|
||||
|
||||
private final int maxFkeyLength;
|
||||
|
||||
public CreateIntersectionTable(DdlGenContext ctx, BeanPropertyAssocMany<?> manyProp) {
|
||||
this.ctx = ctx;
|
||||
this.manyProp = manyProp;
|
||||
this.intersectionTableJoin = manyProp.getIntersectionTableJoin();
|
||||
this.tableJoin = manyProp.getTableJoin();
|
||||
this.maxFkeyLength = ctx.getDdlSyntax().getMaxConstraintNameLength()-3;
|
||||
}
|
||||
|
||||
public void build() {
|
||||
|
||||
String createTable = buildCreateTable();
|
||||
ctx.addCreateIntersectionTable(createTable);
|
||||
|
||||
foreignKeyCount = 0;
|
||||
buildFkConstraints();
|
||||
}
|
||||
|
||||
private void buildFkConstraints() {
|
||||
|
||||
BeanDescriptor<?> localDesc = manyProp.getBeanDescriptor();
|
||||
String fk1 = buildFkConstraints(localDesc, intersectionTableJoin.columns(), true);
|
||||
ctx.addIntersectionTableFk(fk1);
|
||||
|
||||
BeanDescriptor<?> targetDesc = manyProp.getTargetDescriptor();
|
||||
String fk2 = buildFkConstraints(targetDesc, tableJoin.columns(), false);
|
||||
ctx.addIntersectionTableFk(fk2);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private String getFkNameSuffix() {
|
||||
|
||||
foreignKeyCount++;
|
||||
|
||||
if (foreignKeyCount > 9){
|
||||
return "_"+foreignKeyCount;
|
||||
} else {
|
||||
return "_0"+foreignKeyCount;
|
||||
}
|
||||
}
|
||||
|
||||
private String getFkNameWithSuffix(String fkName) {
|
||||
if (fkName.length() > maxFkeyLength){
|
||||
fkName = fkName.substring(0, maxFkeyLength);
|
||||
}
|
||||
return fkName+getFkNameSuffix();
|
||||
}
|
||||
|
||||
private String buildFkConstraints(BeanDescriptor<?> desc, TableJoinColumn[] columns, boolean direction) {
|
||||
|
||||
|
||||
StringBuilder fkBuf = new StringBuilder();
|
||||
|
||||
String fkName = "fk_"+intersectionTableJoin.getTable()+"_"+desc.getBaseTable();
|
||||
|
||||
fkName = getFkNameWithSuffix(fkName);
|
||||
|
||||
fkBuf.append("alter table ");
|
||||
fkBuf.append(intersectionTableJoin.getTable());
|
||||
fkBuf.append(" add constraint ").append(fkName);
|
||||
|
||||
fkBuf.append(" foreign key (");
|
||||
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
if (i > 0) {
|
||||
fkBuf.append(", ");
|
||||
}
|
||||
String col = direction ? columns[i].getForeignDbColumn() : columns[i].getLocalDbColumn();
|
||||
fkBuf.append(col);
|
||||
}
|
||||
fkBuf.append(") references ").append(desc.getBaseTable()).append(" (");
|
||||
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
if (i > 0) {
|
||||
fkBuf.append(", ");
|
||||
}
|
||||
String col = !direction ? columns[i].getForeignDbColumn() : columns[i].getLocalDbColumn();
|
||||
fkBuf.append(col);
|
||||
}
|
||||
fkBuf.append(")");
|
||||
|
||||
String fkeySuffix = ctx.getDdlSyntax().getForeignKeySuffix();
|
||||
if (fkeySuffix != null){
|
||||
fkBuf.append(" ");
|
||||
fkBuf.append(fkeySuffix);
|
||||
}
|
||||
fkBuf.append(";").append(NEW_LINE);
|
||||
|
||||
return fkBuf.toString();
|
||||
}
|
||||
|
||||
private String buildCreateTable() {
|
||||
|
||||
BeanDescriptor<?> localDesc = manyProp.getBeanDescriptor();
|
||||
BeanDescriptor<?> targetDesc = manyProp.getTargetDescriptor();
|
||||
|
||||
sb.append("create table ");
|
||||
sb.append(intersectionTableJoin.getTable());
|
||||
sb.append(" (").append(NEW_LINE);
|
||||
|
||||
TableJoinColumn[] columns = intersectionTableJoin.columns();
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
|
||||
addColumn(localDesc, columns[i].getForeignDbColumn(), columns[i].getLocalDbColumn());
|
||||
}
|
||||
|
||||
TableJoinColumn[] otherColumns = tableJoin.columns();
|
||||
for (int i = 0; i < otherColumns.length; i++) {
|
||||
|
||||
addColumn(targetDesc, otherColumns[i].getLocalDbColumn(), otherColumns[i].getForeignDbColumn());
|
||||
}
|
||||
|
||||
sb.append(" constraint pk_").append(intersectionTableJoin.getTable());
|
||||
sb.append(" primary key (").append(pkeySb.toString().substring(2));
|
||||
sb.append("))").append(NEW_LINE).append(";").append(NEW_LINE);
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void addColumn(BeanDescriptor<?> desc, String column, String findPropColumn) {
|
||||
|
||||
pkeySb.append(", ");
|
||||
pkeySb.append(column);
|
||||
|
||||
writeColumn(column);
|
||||
|
||||
BeanProperty p = desc.getIdBinder().findBeanProperty(findPropColumn);
|
||||
if (p == null) {
|
||||
throw new RuntimeException("Could not find id property for " + findPropColumn);
|
||||
}
|
||||
|
||||
String columnDefn = ctx.getColumnDefn(p);
|
||||
sb.append(columnDefn);
|
||||
sb.append(" not null");
|
||||
sb.append(",").append(NEW_LINE);
|
||||
}
|
||||
|
||||
private void writeColumn(String columnName) {
|
||||
sb.append(" ").append(ctx.pad(columnName, 30)).append(" ");
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.ddl;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Used to generate the drop table DDL script.
|
||||
*/
|
||||
public class CreateSequenceVisitor implements BeanVisitor {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CreateSequenceVisitor.class);
|
||||
|
||||
private final DdlGenContext ctx;
|
||||
|
||||
private final boolean supportsSequence;
|
||||
|
||||
public CreateSequenceVisitor(DdlGenContext ctx) {
|
||||
this.ctx = ctx;
|
||||
this.supportsSequence = ctx.getDbPlatform().getDbIdentity().isSupportsSequence();
|
||||
}
|
||||
|
||||
public boolean visitBean(BeanDescriptor<?> descriptor) {
|
||||
|
||||
if (!descriptor.isInheritanceRoot()){
|
||||
return false;
|
||||
}
|
||||
if (descriptor.getSequenceName() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!supportsSequence){
|
||||
// Hopefully a generic test case
|
||||
String msg = "Not creating sequence "+descriptor.getSequenceName()+" on Bean "+descriptor.getName()
|
||||
+" as DatabasePlatform does not support sequences";
|
||||
logger.warn(msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
String sequenceName = descriptor.getSequenceName();
|
||||
if (sequenceName != null) {
|
||||
int initialValue = descriptor.getSequenceInitialValue();
|
||||
int allocationSize = descriptor.getSequenceAllocationSize();
|
||||
String createSeq = ctx.getDbPlatform().ddlCreateSequence(sequenceName, initialValue, allocationSize);
|
||||
ctx.write(createSeq).writeNewLine().writeNewLine();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void visitBeanEnd(BeanDescriptor<?> descriptor) {
|
||||
}
|
||||
|
||||
public void visitBegin() {
|
||||
}
|
||||
|
||||
public void visitEnd() {
|
||||
}
|
||||
|
||||
public PropertyVisitor visitProperty(BeanProperty p) {
|
||||
// Return null as we are not interested in properties
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,231 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.ddl;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebean.config.TableName;
|
||||
import com.avaje.ebean.config.dbplatform.DbDdlSyntax;
|
||||
import com.avaje.ebean.config.dbplatform.IdType;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompound;
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoin;
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoinColumn;
|
||||
import com.avaje.ebeaninternal.server.deploy.id.ImportedId;
|
||||
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
|
||||
|
||||
/**
|
||||
* Used as part of CreateTableVisitor to generated the create table DDL script.
|
||||
*/
|
||||
public class CreateTableColumnVisitor extends BaseTablePropertyVisitor {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CreateTableColumnVisitor.class);
|
||||
|
||||
private final DdlGenContext ctx;
|
||||
|
||||
private final DbDdlSyntax ddl;
|
||||
|
||||
private final CreateTableVisitor parent;
|
||||
|
||||
private BeanPropertyAssocOne<?> embedded;
|
||||
|
||||
public CreateTableColumnVisitor(CreateTableVisitor parent, DdlGenContext ctx) {
|
||||
this.parent = parent;
|
||||
this.ctx = ctx;
|
||||
this.ddl = ctx.getDdlSyntax();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMany(BeanPropertyAssocMany<?> p) {
|
||||
if (p.isManyToMany()) {
|
||||
//noinspection StatementWithEmptyBody
|
||||
if (p.getMappedBy() != null) {
|
||||
// only create on other 'owning' side
|
||||
|
||||
} else {
|
||||
TableJoin intersectionTableJoin = p.getIntersectionTableJoin();
|
||||
|
||||
// check if the intersection table has already been created
|
||||
String intTable = intersectionTableJoin.getTable();
|
||||
if (ctx.isProcessIntersectionTable(intTable)) {
|
||||
// build the create table and fkey constraints
|
||||
// putting the DDL into ctx for later output as we are
|
||||
// in the middle of rendering the create table DDL
|
||||
new CreateIntersectionTable(ctx, p).build();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void visitCompoundScalar(BeanPropertyCompound compound, BeanProperty p) {
|
||||
visitScalar(p);
|
||||
}
|
||||
|
||||
public void visitCompound(BeanPropertyCompound p) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEmbeddedScalar(BeanProperty p, BeanPropertyAssocOne<?> embedded) {
|
||||
|
||||
this.embedded = embedded;
|
||||
visitScalar(p);
|
||||
}
|
||||
|
||||
private StringBuilder createUniqueConstraintBuffer(String table, String column) {
|
||||
|
||||
String uqConstraintName = "uq_"+TableName.parse(table)+"_"+column;
|
||||
|
||||
if (uqConstraintName.length() > ddl.getMaxConstraintNameLength()) {
|
||||
uqConstraintName = uqConstraintName.substring(0, ddl.getMaxConstraintNameLength());
|
||||
}
|
||||
|
||||
uqConstraintName = ctx.removeQuotes(uqConstraintName);
|
||||
uqConstraintName = StringHelper.replaceString(uqConstraintName, " ", "_");
|
||||
|
||||
StringBuilder constraintExpr = new StringBuilder();
|
||||
constraintExpr.append("constraint ").append(uqConstraintName).append(" unique (");
|
||||
|
||||
return constraintExpr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOneImported(BeanPropertyAssocOne<?> p) {
|
||||
|
||||
ImportedId importedId = p.getImportedId();
|
||||
|
||||
TableJoinColumn[] columns = p.getTableJoin().columns();
|
||||
if (columns.length == 0) {
|
||||
String msg = "No join columns for " + p.getFullBeanName();
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
|
||||
StringBuilder constraintExpr = createUniqueConstraintBuffer(p.getBeanDescriptor().getBaseTable(), columns[0].getLocalDbColumn());
|
||||
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
|
||||
String dbCol = columns[i].getLocalDbColumn();
|
||||
|
||||
if (i > 0) {
|
||||
constraintExpr.append(", ");
|
||||
}
|
||||
constraintExpr.append(dbCol);
|
||||
|
||||
if (parent.isDbColumnWritten(dbCol)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
parent.writeColumnName(dbCol, p);
|
||||
|
||||
BeanProperty importedProperty = importedId.findMatchImport(dbCol);
|
||||
if (importedProperty != null) {
|
||||
|
||||
String columnDefn = ctx.getColumnDefn(importedProperty);
|
||||
ctx.write(columnDefn);
|
||||
|
||||
} else {
|
||||
throw new RuntimeException("Imported BeanProperty not found?");
|
||||
}
|
||||
|
||||
if (!p.isNullable()) {
|
||||
ctx.write(" not null");
|
||||
}
|
||||
ctx.write(",").writeNewLine();
|
||||
}
|
||||
constraintExpr.append(")");
|
||||
|
||||
if (p.isOneToOne()) {
|
||||
if (ddl.isAddOneToOneUniqueContraint()) {
|
||||
parent.addUniqueConstraint(constraintExpr.toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitScalar(BeanProperty p) {
|
||||
|
||||
if (p.isSecondaryTable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (parent.isDbColumnWritten(p.getDbColumn())) {
|
||||
return;
|
||||
}
|
||||
|
||||
parent.writeColumnName(p.getDbColumn(), p);
|
||||
|
||||
String columnDefn = ctx.getColumnDefn(p);
|
||||
|
||||
boolean identity = isIdentity(p);
|
||||
if (identity) {
|
||||
ctx.write(ddl.getIdentityColumnDefn(columnDefn));
|
||||
} else {
|
||||
ctx.write(columnDefn);
|
||||
}
|
||||
|
||||
if (p.isId() && ddl.isInlinePrimaryKeyConstraint()){
|
||||
ctx.write(" primary key");
|
||||
|
||||
} else if (!p.isNullable() || p.isDDLNotNull()) {
|
||||
ctx.write(" not null");
|
||||
}
|
||||
|
||||
if (identity) {
|
||||
writeIdentitySuffix();
|
||||
}
|
||||
|
||||
if (p.isUnique() && !p.isId()) {
|
||||
parent.addUniqueConstraint(createUniqueConstraint(p));
|
||||
}
|
||||
|
||||
parent.addCheckConstraint(p);
|
||||
ctx.write(",").writeNewLine();
|
||||
}
|
||||
|
||||
private String createUniqueConstraint(BeanProperty p) {
|
||||
|
||||
String baseTable = p.getBeanDescriptor().getBaseTable();
|
||||
if (baseTable == null) {
|
||||
// Embedded bean property that has unique constraint on it
|
||||
baseTable = embedded.getBeanDescriptor().getBaseTable();
|
||||
}
|
||||
StringBuilder expr = createUniqueConstraintBuffer(baseTable, p.getDbColumn());
|
||||
|
||||
expr.append(p.getDbColumn()).append(")");
|
||||
return expr.toString();
|
||||
}
|
||||
|
||||
protected void writeIdentitySuffix() {
|
||||
String identity = ddl.getIdentitySuffix();
|
||||
if (identity != null && identity.length() > 0) {
|
||||
ctx.write(" ").write(identity);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isIdentity(BeanProperty p) {
|
||||
|
||||
if (p.isId()) {
|
||||
try {
|
||||
IdType idType = p.getBeanDescriptor().getIdType();
|
||||
|
||||
if (idType.equals(IdType.IDENTITY)) {
|
||||
|
||||
int jdbcType = p.getScalarType().getJdbcType();
|
||||
if (jdbcType == Types.INTEGER || jdbcType == Types.BIGINT || jdbcType == Types.SMALLINT) {
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
String msg = "Error determining identity on property " + p.getFullBeanName();
|
||||
logger.error(msg, e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,264 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.ddl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebean.config.TableName;
|
||||
import com.avaje.ebean.config.dbplatform.DbDdlSyntax;
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompound;
|
||||
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueContraint;
|
||||
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.SqlReservedWords;
|
||||
|
||||
/**
|
||||
* Used to generated the create table DDL script.
|
||||
*/
|
||||
public class CreateTableVisitor extends AbstractBeanVisitor {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CreateTableVisitor.class);
|
||||
|
||||
private final DdlGenContext ctx;
|
||||
|
||||
private final PropertyVisitor pv;
|
||||
|
||||
private final DbDdlSyntax ddl;
|
||||
|
||||
private final int columnNameWidth;
|
||||
|
||||
// avoid writing columns twice, e.g. when used in associations with insertable=false and updateable=false
|
||||
private final Set<String> wroteColumns = new HashSet<String>();
|
||||
|
||||
private ArrayList<String> checkConstraints = new ArrayList<String>();
|
||||
|
||||
private ArrayList<String> uniqueConstraints = new ArrayList<String>();
|
||||
|
||||
private String table;
|
||||
|
||||
public Set<String> getWroteColumns() {
|
||||
return wroteColumns;
|
||||
}
|
||||
|
||||
|
||||
public CreateTableVisitor(DdlGenContext ctx) {
|
||||
this.ctx = ctx;
|
||||
this.ddl = ctx.getDdlSyntax();
|
||||
this.columnNameWidth = ddl.getColumnNameWidth();
|
||||
this.pv = new CreateTableColumnVisitor(this, ctx);
|
||||
}
|
||||
|
||||
public boolean isDbColumnWritten(String dbColumn) {
|
||||
// Columns are not case sensitive - user lower case
|
||||
// as e.g. @JoinColumn(s) may use a different case
|
||||
return wroteColumns.contains(dbColumn.toLowerCase());
|
||||
}
|
||||
|
||||
public void addDbColumnWritten(String dbColumn) {
|
||||
// Column names are case insensitive
|
||||
wroteColumns.add(dbColumn.toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the table name including a check for SQL reserved words.
|
||||
*/
|
||||
protected void writeTableName(BeanDescriptor<?> descriptor) {
|
||||
|
||||
// parse to remove any catalog or schema prefix on the table
|
||||
table = TableName.parse(descriptor.getBaseTable());
|
||||
ctx.write(descriptor.getBaseTable());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write the column name including a check for the SQL reserved words.
|
||||
*/
|
||||
protected void writeColumnName(String columnName, BeanProperty p) {
|
||||
|
||||
addDbColumnWritten(columnName);
|
||||
|
||||
if (SqlReservedWords.isKeyword(columnName)) {
|
||||
String propName = p == null ? "(Unknown)" : p.getFullBeanName();
|
||||
logger.warn("Column name [" + columnName + "] is a suspected SQL reserved word for property " + propName);
|
||||
}
|
||||
|
||||
ctx.write(" ").write(columnName, columnNameWidth).write(" ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a check constraint for the property if required.
|
||||
* <p>
|
||||
* Typically check constraint based on Enum mapping values.
|
||||
* </p>
|
||||
*/
|
||||
protected void addCheckConstraint(BeanProperty p, String prefix, String constraintExpression) {
|
||||
|
||||
if (p != null && constraintExpression != null) {
|
||||
|
||||
// build constraint clause
|
||||
String s = "constraint " + getConstraintName(prefix, p) + " " + constraintExpression;
|
||||
|
||||
// add to list as we render all check constraints just prior to primary key
|
||||
checkConstraints.add(s);
|
||||
}
|
||||
}
|
||||
|
||||
protected String getConstraintName(String prefix, BeanProperty p) {
|
||||
return prefix + table + "_" + p.getDbColumn();
|
||||
}
|
||||
|
||||
protected void addUniqueConstraint(String constraintExpression) {
|
||||
uniqueConstraints.add(constraintExpression);
|
||||
}
|
||||
|
||||
protected void addCheckConstraint(String constraintExpression) {
|
||||
checkConstraints.add(constraintExpression);
|
||||
}
|
||||
|
||||
protected void addCheckConstraint(BeanProperty p) {
|
||||
addCheckConstraint(p, "ck_", p.getDbConstraintExpression());
|
||||
}
|
||||
|
||||
public boolean visitBean(BeanDescriptor<?> descriptor) {
|
||||
|
||||
wroteColumns.clear();
|
||||
|
||||
if (!descriptor.isInheritanceRoot()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx.write("create table ");
|
||||
writeTableName(descriptor);
|
||||
ctx.write(" (").writeNewLine();
|
||||
|
||||
InheritInfo inheritInfo = descriptor.getInheritInfo();
|
||||
if (inheritInfo != null && inheritInfo.isRoot()) {
|
||||
String discColumn = inheritInfo.getDiscriminatorColumn();
|
||||
int discType = inheritInfo.getDiscriminatorType();
|
||||
int discLength = inheritInfo.getDiscriminatorLength();
|
||||
DbType dbType = ctx.getDbTypeMap().get(discType);
|
||||
String discDbType = dbType.renderType(discLength, 0);
|
||||
|
||||
writeColumnName(discColumn, null);
|
||||
ctx.write(discDbType);
|
||||
ctx.write(" not null,");
|
||||
ctx.writeNewLine();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void visitBeanEnd(BeanDescriptor<?> descriptor) {
|
||||
|
||||
visitInheritanceProperties(descriptor, pv);
|
||||
|
||||
if (checkConstraints.size() > 0) {
|
||||
for (String checkConstraint : checkConstraints) {
|
||||
ctx.write(" ").write(checkConstraint).write(",").writeNewLine();
|
||||
}
|
||||
checkConstraints = new ArrayList<String>();
|
||||
}
|
||||
|
||||
if (uniqueConstraints.size() > 0) {
|
||||
for (String constraint : uniqueConstraints) {
|
||||
ctx.write(" ").write(constraint).write(",").writeNewLine();
|
||||
}
|
||||
uniqueConstraints = new ArrayList<String>();
|
||||
}
|
||||
|
||||
CompoundUniqueContraint[] compoundUniqueConstraints = descriptor.getCompoundUniqueConstraints();
|
||||
if (compoundUniqueConstraints != null) {
|
||||
String table = descriptor.getBaseTable();
|
||||
for (int i = 0; i < compoundUniqueConstraints.length; i++) {
|
||||
String constraint = createUniqueConstraint(table, i, compoundUniqueConstraints[i]);
|
||||
ctx.write(" ").write(constraint).write(",").writeNewLine();
|
||||
}
|
||||
}
|
||||
|
||||
BeanProperty idProp = descriptor.getIdProperty();
|
||||
|
||||
if (idProp == null) {
|
||||
// No comma + new line
|
||||
ctx.removeLast().removeLast();
|
||||
} else if (ddl.isInlinePrimaryKeyConstraint()) {
|
||||
// The Primary Key constraint was inlined with the column
|
||||
// ... No comma + new line
|
||||
ctx.removeLast().removeLast();
|
||||
|
||||
} else {
|
||||
// Add the primay key constraint
|
||||
String pkName = ddl.getPrimaryKeyName(table);
|
||||
ctx.write(" constraint ").write(pkName).write(" primary key (");
|
||||
|
||||
VisitorUtil.visit(idProp, new AbstractPropertyVisitor() {
|
||||
|
||||
@Override
|
||||
public void visitEmbeddedScalar(BeanProperty p, BeanPropertyAssocOne<?> embedded) {
|
||||
ctx.write(p.getDbColumn()).write(", ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitScalar(BeanProperty p) {
|
||||
ctx.write(p.getDbColumn()).write(", ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCompoundScalar(BeanPropertyCompound compound, BeanProperty p) {
|
||||
ctx.write(p.getDbColumn()).write(", ");
|
||||
}
|
||||
|
||||
});
|
||||
// remove the last comma, end of PK
|
||||
ctx.removeLast().write(")");
|
||||
}
|
||||
|
||||
// end of table
|
||||
ctx.write(")").writeNewLine();
|
||||
ctx.write(";").writeNewLine().writeNewLine();
|
||||
ctx.flush();
|
||||
}
|
||||
|
||||
private String createUniqueConstraint(String table, int idx, CompoundUniqueContraint uc) {
|
||||
|
||||
StringBuilder sb = new StringBuilder(50);
|
||||
sb.append("constraint ")
|
||||
.append("uq_").append(TableName.parse(table)).append("_").append(idx + 1)
|
||||
.append(" unique (");
|
||||
|
||||
String[] columns = uc.getColumns();
|
||||
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append(columns[i]);
|
||||
}
|
||||
sb.append(")");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void visitBeanDescriptorEnd() {
|
||||
ctx.write(");").writeNewLine().writeNewLine();
|
||||
}
|
||||
|
||||
public PropertyVisitor visitProperty(BeanProperty p) {
|
||||
return pv;
|
||||
}
|
||||
|
||||
public void visitBegin() {
|
||||
|
||||
}
|
||||
|
||||
public void visitEnd() {
|
||||
ctx.addIntersectionCreateTables();
|
||||
ctx.flush();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,252 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.ddl;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.sql.Types;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.avaje.ebean.config.NamingConvention;
|
||||
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
|
||||
import com.avaje.ebean.config.dbplatform.DbDdlSyntax;
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebean.config.dbplatform.DbTypeMap;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarType;
|
||||
|
||||
/**
|
||||
* The context used during DDL generation.
|
||||
*/
|
||||
public class DdlGenContext {
|
||||
|
||||
private final StringWriter stringWriter = new StringWriter();
|
||||
|
||||
/**
|
||||
* Used to map bean types to DB specific types.
|
||||
*/
|
||||
private final DbTypeMap dbTypeMap;
|
||||
|
||||
/**
|
||||
* Handles DB specific DDL syntax.
|
||||
*/
|
||||
private final DbDdlSyntax ddlSyntax;
|
||||
|
||||
/**
|
||||
* The new line character that is used.
|
||||
*/
|
||||
private final String newLine;
|
||||
|
||||
/**
|
||||
* Last content written (used with removeLast())
|
||||
*/
|
||||
private final List<String> contentBuffer = new ArrayList<String>();
|
||||
|
||||
private final Set<String> intersectionTables = new HashSet<String>();
|
||||
|
||||
private final List<String> intersectionTablesCreateDdl = new ArrayList<String>();
|
||||
private final List<String> intersectionTablesFkDdl = new ArrayList<String>();
|
||||
|
||||
private final DatabasePlatform dbPlatform;
|
||||
|
||||
/** The Naming convention used to define FK an IX names */
|
||||
private final NamingConvention namingConvention;
|
||||
|
||||
/** The global fk count used to keep FK names unique */
|
||||
private int fkCount;
|
||||
|
||||
/** The ix count. */
|
||||
private int ixCount;
|
||||
|
||||
public DdlGenContext(DatabasePlatform dbPlatform, NamingConvention namingConvention){
|
||||
this.dbPlatform = dbPlatform;
|
||||
this.dbTypeMap = dbPlatform.getDbTypeMap();
|
||||
this.ddlSyntax = dbPlatform.getDbDdlSyntax();
|
||||
this.newLine = ddlSyntax.getNewLine();
|
||||
this.namingConvention = namingConvention;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the dbPlatform.
|
||||
*/
|
||||
public DatabasePlatform getDbPlatform() {
|
||||
return dbPlatform;
|
||||
}
|
||||
|
||||
public boolean isProcessIntersectionTable(String tableName){
|
||||
return intersectionTables.add(tableName);
|
||||
}
|
||||
|
||||
public void addCreateIntersectionTable(String createTableDdl){
|
||||
intersectionTablesCreateDdl.add(createTableDdl);
|
||||
}
|
||||
|
||||
public void addIntersectionTableFk(String intTableFk){
|
||||
intersectionTablesFkDdl.add(intTableFk);
|
||||
}
|
||||
|
||||
public void addIntersectionCreateTables() {
|
||||
for (String intTableCreate : intersectionTablesCreateDdl) {
|
||||
write(newLine);
|
||||
write(intTableCreate);
|
||||
}
|
||||
}
|
||||
|
||||
public void addIntersectionFkeys() {
|
||||
write(newLine);
|
||||
write(newLine);
|
||||
for (String intTableFk : intersectionTablesFkDdl) {
|
||||
write(newLine);
|
||||
write(intTableFk);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the generated content (DDL script).
|
||||
*/
|
||||
public String getContent(){
|
||||
return stringWriter.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the map used to determine the DB specific type
|
||||
* for a given bean property.
|
||||
*/
|
||||
public DbTypeMap getDbTypeMap() {
|
||||
return dbTypeMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return object to handle DB specific DDL syntax.
|
||||
*/
|
||||
public DbDdlSyntax getDdlSyntax() {
|
||||
return ddlSyntax;
|
||||
}
|
||||
|
||||
public String getColumnDefn(BeanProperty p) {
|
||||
DbType dbType = getDbType(p);
|
||||
return p.renderDbType(dbType);
|
||||
}
|
||||
|
||||
private DbType getDbType(BeanProperty p) {
|
||||
|
||||
ScalarType<?> scalarType = p.getScalarType();
|
||||
if (scalarType == null) {
|
||||
throw new RuntimeException("No scalarType for " + p.getFullBeanName());
|
||||
}
|
||||
|
||||
if (p.isDbEncrypted()){
|
||||
return dbTypeMap.get(p.getDbEncryptedType());
|
||||
}
|
||||
|
||||
int jdbcType = scalarType.getJdbcType();
|
||||
if (p.isLob() && jdbcType == Types.VARCHAR){
|
||||
// workaround for Postgres TEXT type which is
|
||||
// VARCHAR in jdbc API but TEXT in ddl
|
||||
jdbcType = Types.CLOB;
|
||||
}
|
||||
return dbTypeMap.get(jdbcType);
|
||||
}
|
||||
/**
|
||||
* Write content to the buffer.
|
||||
*/
|
||||
public DdlGenContext write(String content, int minWidth){
|
||||
|
||||
content = pad(content, minWidth);
|
||||
|
||||
contentBuffer.add(content);
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Write content to the buffer.
|
||||
*/
|
||||
public DdlGenContext write(String content){
|
||||
return write(content, 0);
|
||||
}
|
||||
|
||||
public DdlGenContext writeNewLine() {
|
||||
write(newLine);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the last content that was written.
|
||||
*/
|
||||
public DdlGenContext removeLast() {
|
||||
if (!contentBuffer.isEmpty()){
|
||||
contentBuffer.remove(contentBuffer.size()-1);
|
||||
} else {
|
||||
throw new RuntimeException("No lastContent to remove?");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the content to the buffer.
|
||||
*/
|
||||
public DdlGenContext flush() {
|
||||
if (!contentBuffer.isEmpty()){
|
||||
for (String s:contentBuffer){
|
||||
|
||||
if (s != null){
|
||||
stringWriter.write(s);
|
||||
}
|
||||
}
|
||||
contentBuffer.clear();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private String padding(int length){
|
||||
|
||||
StringBuilder sb = new StringBuilder(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
sb.append(" ");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String pad(String content, int minWidth){
|
||||
if (minWidth > 0 && content.length() < minWidth){
|
||||
int padding = minWidth - content.length();
|
||||
return content + padding(padding);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the namingConvention
|
||||
*/
|
||||
public NamingConvention getNamingConvention() {
|
||||
return namingConvention;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the incremented fkCount
|
||||
*/
|
||||
public int incrementFkCount() {
|
||||
return ++fkCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the incremented ixCount
|
||||
*/
|
||||
public int incrementIxCount() {
|
||||
return ++ixCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips off the Database Platform specific quoted identifier characters.
|
||||
*/
|
||||
public String removeQuotes(String dbColumn) {
|
||||
|
||||
dbColumn = StringHelper.replaceString(dbColumn, dbPlatform.getOpenQuote(), "");
|
||||
dbColumn = StringHelper.replaceString(dbColumn, dbPlatform.getCloseQuote(), "");
|
||||
|
||||
return dbColumn;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,14 @@
|
||||
package com.avaje.ebeaninternal.server.ddl;
|
||||
|
||||
import com.avaje.ebean.Transaction;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.dbmigration.model.CurrentModel;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanPlugin;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
@@ -13,19 +22,6 @@ import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebean.dbmigration.model.CurrentModel;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebean.Transaction;
|
||||
import com.avaje.ebean.config.NamingConvention;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanPlugin;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
|
||||
/**
|
||||
* Controls the generation of DDL and potentially runs the resulting scripts.
|
||||
*/
|
||||
@@ -35,8 +31,6 @@ public class DdlGenerator implements SpiEbeanPlugin {
|
||||
|
||||
private SpiEbeanServer server;
|
||||
|
||||
private DatabasePlatform dbPlatform;
|
||||
|
||||
private boolean generateDdl;
|
||||
private boolean runDdl;
|
||||
|
||||
@@ -44,14 +38,10 @@ public class DdlGenerator implements SpiEbeanPlugin {
|
||||
private String dropContent;
|
||||
private String createContent;
|
||||
|
||||
private NamingConvention namingConvention;
|
||||
|
||||
public void setup(SpiEbeanServer server, DatabasePlatform dbPlatform, ServerConfig serverConfig) {
|
||||
public void setup(SpiEbeanServer server, ServerConfig serverConfig) {
|
||||
this.server = server;
|
||||
this.dbPlatform = dbPlatform;
|
||||
this.generateDdl = serverConfig.isDdlGenerate();
|
||||
this.runDdl = serverConfig.isDdlRun();
|
||||
this.namingConvention = serverConfig.getNamingConvention();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,25 +124,8 @@ public class DdlGenerator implements SpiEbeanPlugin {
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
// DdlGenContext ctx = createContext();
|
||||
//
|
||||
// if (ctx.getDdlSyntax().isDropKeyConstraints()) {
|
||||
// // generate drop foreign key constraint statements (sql server joy)
|
||||
// AddForeignKeysVisitor fkeys = new AddForeignKeysVisitor(false, ctx);
|
||||
// VisitorUtil.visit(server, fkeys);
|
||||
// ctx.writeNewLine();
|
||||
// }
|
||||
//
|
||||
// DropTableVisitor drop = new DropTableVisitor(ctx);
|
||||
// VisitorUtil.visit(server, drop);
|
||||
//
|
||||
// DropSequenceVisitor dropSequence = new DropSequenceVisitor(ctx);
|
||||
// VisitorUtil.visit(server, dropSequence);
|
||||
//
|
||||
// ctx.flush();
|
||||
// dropContent = ctx.getContent();
|
||||
// return dropContent;
|
||||
}
|
||||
|
||||
public void writeMigration(File file) {
|
||||
|
||||
currentModel().writeMigration(file);
|
||||
@@ -166,22 +139,6 @@ public class DdlGenerator implements SpiEbeanPlugin {
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
// DdlGenContext ctx = createContext();
|
||||
// CreateTableVisitor create = new CreateTableVisitor(ctx);
|
||||
// VisitorUtil.visit(server, create);
|
||||
//
|
||||
// CreateSequenceVisitor createSequence = new CreateSequenceVisitor(ctx);
|
||||
// VisitorUtil.visit(server, createSequence);
|
||||
//
|
||||
// AddForeignKeysVisitor fkeys = new AddForeignKeysVisitor(true, ctx);
|
||||
// VisitorUtil.visit(server, fkeys);
|
||||
//
|
||||
// CreateIndexVisitor indexes = new CreateIndexVisitor(ctx);
|
||||
// VisitorUtil.visit(server, indexes);
|
||||
//
|
||||
// ctx.flush();
|
||||
// createContent = ctx.getContent();
|
||||
// return createContent;
|
||||
}
|
||||
|
||||
protected String getDropFileName() {
|
||||
@@ -192,12 +149,6 @@ public class DdlGenerator implements SpiEbeanPlugin {
|
||||
return server.getName() + "-create.sql";
|
||||
}
|
||||
|
||||
protected DdlGenContext createContext() {
|
||||
return new DdlGenContext(dbPlatform, namingConvention);
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected CurrentModel currentModel() {
|
||||
if (currentModel == null) {
|
||||
currentModel = new CurrentModel(server);
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.ddl;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.DbDdlSyntax;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Used to generate the drop table DDL script.
|
||||
*/
|
||||
public class DropSequenceVisitor implements BeanVisitor {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DropSequenceVisitor.class);
|
||||
|
||||
private final DdlGenContext ctx;
|
||||
|
||||
private final DbDdlSyntax ddlSyntax;
|
||||
|
||||
private final boolean supportsSequence;
|
||||
|
||||
public DropSequenceVisitor(DdlGenContext ctx) {
|
||||
this.ctx = ctx;
|
||||
this.ddlSyntax = ctx.getDdlSyntax();
|
||||
this.supportsSequence = ctx.getDbPlatform().getDbIdentity().isSupportsSequence();
|
||||
}
|
||||
|
||||
public boolean visitBean(BeanDescriptor<?> descriptor) {
|
||||
|
||||
|
||||
if (!descriptor.isInheritanceRoot()){
|
||||
return false;
|
||||
}
|
||||
if (descriptor.getSequenceName() != null) {
|
||||
|
||||
if (!supportsSequence){
|
||||
// Hopefully a generic test case
|
||||
String msg = "Not dropping sequence "+descriptor.getSequenceName()+" on Bean "+descriptor.getName()
|
||||
+" as DatabasePlatform does not support sequences";
|
||||
logger.trace(msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx.write("drop sequence ");
|
||||
if (ddlSyntax.getDropIfExists() != null){
|
||||
ctx.write(ddlSyntax.getDropIfExists()).write(" ");
|
||||
}
|
||||
ctx.write(descriptor.getSequenceName());
|
||||
ctx.write(";").writeNewLine().writeNewLine();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void visitBeanEnd(BeanDescriptor<?> descriptor) {
|
||||
}
|
||||
|
||||
public void visitBegin() {
|
||||
}
|
||||
|
||||
public void visitEnd() {
|
||||
}
|
||||
|
||||
public PropertyVisitor visitProperty(BeanProperty p) {
|
||||
// Return null as we are not interested in properties
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.ddl;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.DbDdlSyntax;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
|
||||
/**
|
||||
* Used to generate the drop table DDL script.
|
||||
*/
|
||||
public class DropTableVisitor implements BeanVisitor {
|
||||
|
||||
final DdlGenContext ctx;
|
||||
|
||||
final DbDdlSyntax ddlSyntax;
|
||||
|
||||
public DropTableVisitor(DdlGenContext ctx) {
|
||||
this.ctx = ctx;
|
||||
this.ddlSyntax = ctx.getDdlSyntax();
|
||||
}
|
||||
|
||||
protected void writeDropTable(BeanDescriptor<?> descriptor){
|
||||
writeDropTable(descriptor.getBaseTable());
|
||||
}
|
||||
|
||||
protected void writeDropTable(String tableName){
|
||||
ctx.write(ddlSyntax.dropTablePrefix(tableName));
|
||||
ctx.write("drop table ");
|
||||
if (ddlSyntax.getDropIfExists() != null){
|
||||
ctx.write(ddlSyntax.getDropIfExists()).write(" ");
|
||||
}
|
||||
ctx.write(tableName);
|
||||
|
||||
if (ddlSyntax.getDropTableCascade() != null){
|
||||
ctx.write(" ").write(ddlSyntax.getDropTableCascade());
|
||||
}
|
||||
ctx.write(";").writeNewLine().writeNewLine();
|
||||
}
|
||||
|
||||
public boolean visitBean(BeanDescriptor<?> descriptor) {
|
||||
|
||||
if (!descriptor.isInheritanceRoot()){
|
||||
return false;
|
||||
}
|
||||
|
||||
writeDropTable(descriptor);
|
||||
|
||||
dropIntersectionTables(descriptor);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void dropIntersectionTables(BeanDescriptor<?> descriptor) {
|
||||
|
||||
BeanPropertyAssocMany<?>[] manyProps = descriptor.propertiesMany();
|
||||
for (int i = 0; i < manyProps.length; i++) {
|
||||
if (manyProps[i].isManyToMany()){
|
||||
String intTable = manyProps[i].getIntersectionTableJoin().getTable();
|
||||
if (ctx.isProcessIntersectionTable(intTable)) {
|
||||
writeDropTable(intTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void visitBeanEnd(BeanDescriptor<?> descriptor) {
|
||||
}
|
||||
|
||||
public void visitBegin() {
|
||||
|
||||
if (ddlSyntax.getDisableReferentialIntegrity() != null){
|
||||
ctx.write(ddlSyntax.getDisableReferentialIntegrity());
|
||||
ctx.write(";").writeNewLine().writeNewLine();
|
||||
}
|
||||
}
|
||||
|
||||
public void visitEnd() {
|
||||
if (ddlSyntax.getEnableReferentialIntegrity() != null){
|
||||
ctx.write(ddlSyntax.getEnableReferentialIntegrity());
|
||||
ctx.write(";").writeNewLine().writeNewLine();
|
||||
}
|
||||
}
|
||||
|
||||
public PropertyVisitor visitProperty(BeanProperty p) {
|
||||
// Return null as we are not interested in properties
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.ddl;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompound;
|
||||
|
||||
/**
|
||||
* Used to visit a BeanProperty given the type of bean property it is.
|
||||
*/
|
||||
public interface PropertyVisitor {
|
||||
|
||||
/**
|
||||
* Visit a OneToMany or ManyToMany property.
|
||||
*/
|
||||
void visitMany(BeanPropertyAssocMany<?> p);
|
||||
|
||||
/**
|
||||
* Visit the imported side of a OneToOne property.
|
||||
*/
|
||||
void visitOneImported(BeanPropertyAssocOne<?> p);
|
||||
|
||||
/**
|
||||
* Visit the exported side of a OneToOne property.
|
||||
*/
|
||||
void visitOneExported(BeanPropertyAssocOne<?> p);
|
||||
|
||||
/**
|
||||
* Visit an embedded property.
|
||||
*/
|
||||
void visitEmbedded(BeanPropertyAssocOne<?> p);
|
||||
|
||||
/**
|
||||
* Visit the scalar property of an embedded bean.
|
||||
*/
|
||||
void visitEmbeddedScalar(BeanProperty p, BeanPropertyAssocOne<?> embedded);
|
||||
|
||||
/**
|
||||
* Visit a scalar property.
|
||||
*/
|
||||
void visitScalar(BeanProperty p);
|
||||
|
||||
/**
|
||||
* Visit a compound value object.
|
||||
*/
|
||||
void visitCompound(BeanPropertyCompound p);
|
||||
|
||||
/**
|
||||
* Visit the scalar value inside a compound value object.
|
||||
*/
|
||||
void visitCompoundScalar(BeanPropertyCompound compound, BeanProperty p);
|
||||
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.ddl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompound;
|
||||
|
||||
/**
|
||||
* Utility object to use BeanVisitor.
|
||||
*/
|
||||
public class VisitorUtil {
|
||||
|
||||
/**
|
||||
* Visit all the descriptors for a given server.
|
||||
*/
|
||||
public static void visit(SpiEbeanServer server, BeanVisitor visitor){
|
||||
|
||||
visit(server.getBeanDescriptors(), visitor);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Visit all the descriptors in the list.
|
||||
*/
|
||||
public static void visit(List<BeanDescriptor<?>> descriptors, BeanVisitor visitor){
|
||||
|
||||
visitor.visitBegin();
|
||||
|
||||
for (BeanDescriptor<?> desc : descriptors) {
|
||||
|
||||
if (desc.getBaseTable() != null){
|
||||
visitBean(desc, visitor);
|
||||
}
|
||||
}
|
||||
|
||||
visitor.visitEnd();
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit the bean using a visitor.
|
||||
*/
|
||||
public static void visitBean(BeanDescriptor<?> desc, BeanVisitor visitor) {
|
||||
|
||||
if (visitor.visitBean(desc)) {
|
||||
|
||||
BeanProperty idProp = desc.getIdProperty();
|
||||
if (idProp != null) {
|
||||
visit(visitor, idProp);
|
||||
}
|
||||
BeanPropertyAssocOne<?> unidirectional = desc.getUnidirectional();
|
||||
if (unidirectional != null) {
|
||||
visit(visitor, unidirectional);
|
||||
}
|
||||
BeanProperty[] propertiesNonTransient = desc.propertiesNonTransient();
|
||||
for (int i = 0; i < propertiesNonTransient.length; i++) {
|
||||
BeanProperty p = propertiesNonTransient[i];
|
||||
if (!p.isFormula() && !p.isSecondaryTable()) {
|
||||
visit(visitor, p);
|
||||
}
|
||||
}
|
||||
|
||||
visitor.visitBeanEnd(desc);
|
||||
}
|
||||
}
|
||||
|
||||
private static void visit(BeanVisitor visitor, BeanProperty p) {
|
||||
PropertyVisitor pv = visitor.visitProperty(p);
|
||||
if (pv != null) {
|
||||
visit(p, pv);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit all the properties.
|
||||
*/
|
||||
public static void visit(BeanProperty[] p, PropertyVisitor pv){
|
||||
|
||||
for (int i = 0; i < p.length; i++) {
|
||||
visit(p[i], pv);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit the property.
|
||||
*/
|
||||
public static void visit(BeanProperty p, PropertyVisitor pv) {
|
||||
|
||||
if (p instanceof BeanPropertyAssocMany<?>){
|
||||
pv.visitMany((BeanPropertyAssocMany<?>)p);
|
||||
|
||||
} else if (p instanceof BeanPropertyAssocOne<?>){
|
||||
BeanPropertyAssocOne<?> assocOne = (BeanPropertyAssocOne<?>)p;
|
||||
if (assocOne.isEmbedded()){
|
||||
pv.visitEmbedded(assocOne);
|
||||
BeanProperty[] embProps = assocOne.getProperties();
|
||||
for (int i = 0; i < embProps.length; i++) {
|
||||
pv.visitEmbeddedScalar(embProps[i], assocOne);
|
||||
}
|
||||
|
||||
|
||||
} else if (assocOne.isOneToOneExported()){
|
||||
pv.visitOneExported(assocOne);
|
||||
|
||||
} else {
|
||||
pv.visitOneImported(assocOne);
|
||||
|
||||
}
|
||||
} else if (p instanceof BeanPropertyCompound){
|
||||
BeanPropertyCompound compound = (BeanPropertyCompound)p;
|
||||
pv.visitCompound(compound);
|
||||
|
||||
BeanProperty[] properties = compound.getScalarProperties();
|
||||
for (int i = 0; i < properties.length; i++) {
|
||||
pv.visitCompoundScalar(compound, properties[i]);
|
||||
}
|
||||
|
||||
} else {
|
||||
pv.visitScalar(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.ddl;
|
||||
@@ -23,6 +23,7 @@ ebean.autofetch.traceUsageCollection=false
|
||||
|
||||
ebean.ddl.generate=true
|
||||
ebean.ddl.run=true
|
||||
datasource.default=h2
|
||||
|
||||
ebean.persistBatch=NONE
|
||||
ebean.persistBatchOnCascade=ALL
|
||||
@@ -50,7 +51,7 @@ ebean.cacheWarmingDelay=-1
|
||||
## DataSources (If using default Ebean DataSourceFactory)
|
||||
## -------------------------------------------------------------
|
||||
|
||||
datasource.default=ora
|
||||
|
||||
|
||||
datasource.h2.username=sa
|
||||
datasource.h2.password=
|
||||
@@ -96,9 +97,9 @@ datasource.hsqldb.databaseUrl=jdbc:hsqldb:mem:tests
|
||||
datasource.hsqldb.databaseDriver=org.hsqldb.jdbcDriver
|
||||
|
||||
|
||||
datasource.mysql.username=test
|
||||
datasource.mysql.password=test
|
||||
datasource.mysql.databaseUrl=jdbc:mysql://127.0.0.1:3306/test
|
||||
datasource.mysql.username=unit
|
||||
datasource.mysql.password=unit
|
||||
datasource.mysql.databaseUrl=jdbc:mysql://127.0.0.1:3306/unit
|
||||
datasource.mysql.databaseDriver=com.mysql.jdbc.Driver
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user