+ * Only used for SQLite at this stage. + *
+ */ + public void setIdentitySuffix(String identitySuffix) { + this.identitySuffix = identitySuffix; + } + /** * Return the width for padding whitespace after column names. */ diff --git a/src/main/java/com/avaje/ebean/config/dbplatform/SQLitePlatform.java b/src/main/java/com/avaje/ebean/config/dbplatform/SQLitePlatform.java index 6e83b8555..37d6a1c3c 100644 --- a/src/main/java/com/avaje/ebean/config/dbplatform/SQLitePlatform.java +++ b/src/main/java/com/avaje/ebean/config/dbplatform/SQLitePlatform.java @@ -22,9 +22,15 @@ public class SQLitePlatform extends DatabasePlatform { dbTypeMap.put(Types.BIT, new DbType("int default 0")); dbTypeMap.put(Types.BOOLEAN, new DbType("int default 0")); - + dbTypeMap.put(Types.BIGINT, new DbType("integer")); + dbTypeMap.put(Types.SMALLINT, new DbType("integer")); + dbDdlSyntax.setInlinePrimaryKeyConstraint(true); - dbDdlSyntax.setIdentity("AUTOINCREMENT"); + + // AutoIncrement goes the primary key declaration + dbDdlSyntax.setIdentity(""); + dbDdlSyntax.setIdentitySuffix("AUTOINCREMENT"); + dbDdlSyntax.setDisableReferentialIntegrity("PRAGMA foreign_keys = OFF"); dbDdlSyntax.setEnableReferentialIntegrity("PRAGMA foreign_keys = ON"); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/ddl/CreateTableColumnVisitor.java b/src/main/java/com/avaje/ebeaninternal/server/ddl/CreateTableColumnVisitor.java index 06ea8ba77..30e7b23b9 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/ddl/CreateTableColumnVisitor.java +++ b/src/main/java/com/avaje/ebeaninternal/server/ddl/CreateTableColumnVisitor.java @@ -21,136 +21,130 @@ import org.slf4j.LoggerFactory; public class CreateTableColumnVisitor extends BaseTablePropertyVisitor { private static final Logger logger = LoggerFactory.getLogger(CreateTableColumnVisitor.class); - - private final DdlGenContext ctx; - private final DbDdlSyntax ddl; + private final DdlGenContext ctx; - private final CreateTableVisitor parent; + private final DbDdlSyntax ddl; - public CreateTableColumnVisitor(CreateTableVisitor parent, DdlGenContext ctx) { - this.parent = parent; - this.ctx = ctx; - this.ddl = ctx.getDdlSyntax(); - } + private final CreateTableVisitor parent; + 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()){ - 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(); - } - } - } - } + @Override + public void visitMany(BeanPropertyAssocMany> p) { + if (p.isManyToMany()) { + if (p.getMappedBy() != null) { + // only create on other 'owning' side - - public void visitCompoundScalar(BeanPropertyCompound compound, BeanProperty p) { - visitScalar(p); - } + } else { + TableJoin intersectionTableJoin = p.getIntersectionTableJoin(); - - public void visitCompound(BeanPropertyCompound p) { - // do nothing - } - - - @Override - public void visitEmbeddedScalar(BeanProperty p, BeanPropertyAssocOne> embedded) { - - visitScalar(p); - } - - private StringBuilder createUniqueConstraintBuffer(String table, String column) { - - String uqConstraintName = "uq_"+ table+ "_"+column; - - if (uqConstraintName.length() > ddl.getMaxConstraintNameLength()){ - uqConstraintName = uqConstraintName.substring(0, ddl.getMaxConstraintNameLength()); + // 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(); } - - 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) { + } + + public void visitCompoundScalar(BeanPropertyCompound compound, BeanProperty p) { + visitScalar(p); + } - ImportedId importedId = p.getImportedId(); + public void visitCompound(BeanPropertyCompound p) { + // do nothing + } - 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(); + @Override + public void visitEmbeddedScalar(BeanProperty p, BeanPropertyAssocOne> embedded) { - if (i > 0){ - constraintExpr.append(", "); - } - constraintExpr.append(dbCol); - - if (parent.isDbColumnWritten(dbCol)) { - continue; - } - - parent.writeColumnName(dbCol, p); + visitScalar(p); + } - BeanProperty importedProperty = importedId.findMatchImport(dbCol); - if (importedProperty != null) { + private StringBuilder createUniqueConstraintBuffer(String table, String column) { - String columnDefn = ctx.getColumnDefn(importedProperty); - ctx.write(columnDefn); + String uqConstraintName = "uq_" + table + "_" + column; - } else { - throw new RuntimeException("Imported BeanProperty not found?"); - } + if (uqConstraintName.length() > ddl.getMaxConstraintNameLength()) { + uqConstraintName = uqConstraintName.substring(0, ddl.getMaxConstraintNameLength()); + } - if (!p.isNullable()) { - ctx.write(" not null"); - } - ctx.write(",").writeNewLine(); - } - constraintExpr.append(")"); - - if (p.isOneToOne()){ - if (ddl.isAddOneToOneUniqueContraint()){ - parent.addUniqueConstraint( constraintExpr.toString()); - } - } - - } + 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 (p.isSecondaryTable()) { + return; + } if (parent.isDbColumnWritten(p.getDbColumn())) { return; @@ -161,7 +155,8 @@ public class CreateTableColumnVisitor extends BaseTablePropertyVisitor { String columnDefn = ctx.getColumnDefn(p); ctx.write(columnDefn); - if (isIdentity(p)) { + boolean identity = isIdentity(p); + if (identity) { writeIdentity(); } @@ -172,23 +167,25 @@ public class CreateTableColumnVisitor extends BaseTablePropertyVisitor { ctx.write(" not null"); } - if (p.isUnique() && !p.isId()){ - parent.addUniqueConstraint(createUniqueConstraint(p)); - } + if (identity) { + writeIdentitySuffix(); + } + + if (p.isUnique() && !p.isId()) { + parent.addUniqueConstraint(createUniqueConstraint(p)); + } parent.addCheckConstraint(p); - ctx.write(",").writeNewLine(); } - private String createUniqueConstraint(BeanProperty p) { - - StringBuilder expr = createUniqueConstraintBuffer(p.getBeanDescriptor().getBaseTable(), p.getDbColumn()); - - expr.append(p.getDbColumn()).append(")"); - - return expr.toString(); - } + private String createUniqueConstraint(BeanProperty p) { + + StringBuilder expr = createUniqueConstraintBuffer(p.getBeanDescriptor().getBaseTable(), p.getDbColumn()); + + expr.append(p.getDbColumn()).append(")"); + return expr.toString(); + } protected void writeIdentity() { String identity = ddl.getIdentity(); @@ -197,27 +194,33 @@ public class CreateTableColumnVisitor extends BaseTablePropertyVisitor { } } - 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; - } + 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; + } } \ No newline at end of file diff --git a/src/main/java/com/avaje/ebeaninternal/server/ddl/DdlGenerator.java b/src/main/java/com/avaje/ebeaninternal/server/ddl/DdlGenerator.java index fd7a9e4ce..e935872c4 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/ddl/DdlGenerator.java +++ b/src/main/java/com/avaje/ebeaninternal/server/ddl/DdlGenerator.java @@ -31,75 +31,75 @@ import com.avaje.ebeaninternal.api.SpiEbeanServer; public class DdlGenerator implements SpiEbeanPlugin { private static final Logger logger = LoggerFactory.getLogger(DdlGenerator.class); - - private SpiEbeanServer server; - private DatabasePlatform dbPlatform; + private SpiEbeanServer server; - private int summaryLength = 80; + private DatabasePlatform dbPlatform; - private boolean generateDdl; - private boolean runDdl; + private int summaryLength = 80; - private String dropContent; - private String createContent; + private boolean generateDdl; + private boolean runDdl; - private NamingConvention namingConvention; + private String dropContent; + private String createContent; - public void setup(SpiEbeanServer server, DatabasePlatform dbPlatform, ServerConfig serverConfig) { - this.server = server; - this.dbPlatform = dbPlatform; - this.generateDdl = serverConfig.isDdlGenerate(); - this.runDdl = serverConfig.isDdlRun(); - this.namingConvention = serverConfig.getNamingConvention(); - } + private NamingConvention namingConvention; - /** - * Generate the DDL and then run the DDL based on property settings (ebean.ddl.generate and ebean.ddl.run etc). - */ - public void execute(boolean online) { - generateDdl(); - if (online){ - runDdl(); - } - } + public void setup(SpiEbeanServer server, DatabasePlatform dbPlatform, ServerConfig serverConfig) { + this.server = server; + this.dbPlatform = dbPlatform; + this.generateDdl = serverConfig.isDdlGenerate(); + this.runDdl = serverConfig.isDdlRun(); + this.namingConvention = serverConfig.getNamingConvention(); + } - /** - * Generate the DDL drop and create scripts if the properties have been set. - */ - public void generateDdl() { - if (generateDdl) { - writeDrop(getDropFileName()); - writeCreate(getCreateFileName()); - } - } + /** + * Generate the DDL and then run the DDL based on property settings + * (ebean.ddl.generate and ebean.ddl.run etc). + */ + public void execute(boolean online) { + generateDdl(); + if (online) { + runDdl(); + } + } - /** - * Run the DDL drop and DDL create scripts if properties have been set. - */ - public void runDdl() { + /** + * Generate the DDL drop and create scripts if the properties have been set. + */ + public void generateDdl() { + if (generateDdl) { + writeDrop(getDropFileName()); + writeCreate(getCreateFileName()); + } + } - if (runDdl) { - try { - if (dropContent == null){ - dropContent = readFile(getDropFileName()); - } - if (createContent == null){ - createContent = readFile(getCreateFileName()); - } - runScript(true, dropContent); - runScript(false, createContent); + /** + * Run the DDL drop and DDL create scripts if properties have been set. + */ + public void runDdl() { - } catch (IOException e){ - String msg = "Error reading drop/create script from file system"; - throw new RuntimeException(msg, e); - } - } - } + if (runDdl) { + try { + if (dropContent == null) { + dropContent = readFile(getDropFileName()); + } + if (createContent == null) { + createContent = readFile(getCreateFileName()); + } + runScript(true, dropContent); + runScript(false, createContent); + + } catch (IOException e) { + String msg = "Error reading drop/create script from file system"; + throw new RuntimeException(msg, e); + } + } + } protected void writeDrop(String dropFile) { -// String c = generateDropDdl(); try { String c = generateDropDdl(); writeFile(dropFile, c); @@ -110,224 +110,223 @@ public class DdlGenerator implements SpiEbeanPlugin { } } - protected void writeCreate(String createFile) { + protected void writeCreate(String createFile) { -// String c = generateCreateDdl(); - try { - String c = generateCreateDdl(); - writeFile(createFile, c); + try { + String c = generateCreateDdl(); + writeFile(createFile, c); - } catch (IOException e) { - String msg = "Error generating Create DDL"; - throw new PersistenceException(msg, e); - } - } + } catch (IOException e) { + String msg = "Error generating Create DDL"; + throw new PersistenceException(msg, e); + } + } - public String generateDropDdl() { + public String generateDropDdl() { - DdlGenContext ctx = createContext(); + DdlGenContext ctx = createContext(); - DropTableVisitor drop = new DropTableVisitor(ctx); - VisitorUtil.visit(server, drop); + DropTableVisitor drop = new DropTableVisitor(ctx); + VisitorUtil.visit(server, drop); - DropSequenceVisitor dropSequence = new DropSequenceVisitor(ctx); - VisitorUtil.visit(server, dropSequence); + DropSequenceVisitor dropSequence = new DropSequenceVisitor(ctx); + VisitorUtil.visit(server, dropSequence); - ctx.flush(); - dropContent = ctx.getContent(); - return dropContent; - } + ctx.flush(); + dropContent = ctx.getContent(); + return dropContent; + } - public String generateCreateDdl() { + public String generateCreateDdl() { - DdlGenContext ctx = createContext(); - CreateTableVisitor create = new CreateTableVisitor(ctx); - VisitorUtil.visit(server, create); + DdlGenContext ctx = createContext(); + CreateTableVisitor create = new CreateTableVisitor(ctx); + VisitorUtil.visit(server, create); - CreateSequenceVisitor createSequence = new CreateSequenceVisitor(ctx); - VisitorUtil.visit(server, createSequence); + CreateSequenceVisitor createSequence = new CreateSequenceVisitor(ctx); + VisitorUtil.visit(server, createSequence); - AddForeignKeysVisitor fkeys = new AddForeignKeysVisitor(ctx); - VisitorUtil.visit(server, fkeys); + AddForeignKeysVisitor fkeys = new AddForeignKeysVisitor(ctx); + VisitorUtil.visit(server, fkeys); - ctx.flush(); - createContent = ctx.getContent(); - return createContent; - } + ctx.flush(); + createContent = ctx.getContent(); + return createContent; + } - protected String getDropFileName() { - return server.getName() + "-drop.sql"; - } + protected String getDropFileName() { + return server.getName() + "-drop.sql"; + } - protected String getCreateFileName() { - return server.getName() + "-create.sql"; - } + protected String getCreateFileName() { + return server.getName() + "-create.sql"; + } - protected DdlGenContext createContext() { - return new DdlGenContext(dbPlatform, namingConvention); - } + protected DdlGenContext createContext() { + return new DdlGenContext(dbPlatform, namingConvention); + } - protected void writeFile(String fileName, String fileContent) throws IOException { + protected void writeFile(String fileName, String fileContent) throws IOException { - File f = new File(fileName); + File f = new File(fileName); - FileWriter fw = new FileWriter(f); - try { - fw.write(fileContent); - fw.flush(); - } finally { - fw.close(); - } - } + FileWriter fw = new FileWriter(f); + try { + fw.write(fileContent); + fw.flush(); + } finally { + fw.close(); + } + } - protected String readFile(String fileName) throws IOException { + protected String readFile(String fileName) throws IOException { - File f = new File(fileName); - if (!f.exists()){ - return null; - } + File f = new File(fileName); + if (!f.exists()) { + return null; + } - StringBuilder buf = new StringBuilder(); + StringBuilder buf = new StringBuilder(); - FileReader fr = new FileReader(f); - LineNumberReader lr = new LineNumberReader(fr); - try { - String s = null; - while ((s = lr.readLine()) != null){ - buf.append(s).append("\n"); - } - } finally { - lr.close(); - } + FileReader fr = new FileReader(f); + LineNumberReader lr = new LineNumberReader(fr); + try { + String s = null; + while ((s = lr.readLine()) != null) { + buf.append(s).append("\n"); + } + } finally { + lr.close(); + } - return buf.toString(); - } + return buf.toString(); + } - /** - * Execute all the DDL statements in the script. - */ - public void runScript(boolean expectErrors, String content) { + /** + * Execute all the DDL statements in the script. + */ + public void runScript(boolean expectErrors, String content) { - StringReader sr = new StringReader(content); - List