mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#374 - MsSqlServer - adjust tests (due to jdbc batch support etc) add in support for unique index handling
This commit is contained in:
@@ -120,6 +120,13 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>microsoft</groupId>
|
||||
<artifactId>sqlserver-jdbc</artifactId>
|
||||
<version>4.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
|
||||
@@ -23,6 +23,7 @@ public class MsSqlServer2005Platform extends DatabasePlatform {
|
||||
// due to lack of support for getGeneratedKeys in batch mode
|
||||
this.disallowBatchOnCascade = true;
|
||||
this.idInExpandedForm = true;
|
||||
this.selectCountWithAlias = true;
|
||||
this.sqlLimiter = new MsSqlServer2005SqlLimiter();
|
||||
this.platformDdl = new MsSqlServerDdl(dbTypeMap, dbIdentity);
|
||||
this.dbIdentity.setIdType(IdType.IDENTITY);
|
||||
@@ -46,9 +47,9 @@ public class MsSqlServer2005Platform extends DatabasePlatform {
|
||||
dbTypeMap.put(Types.LONGVARBINARY, new DbType("image"));
|
||||
dbTypeMap.put(Types.LONGVARCHAR, new DbType("text"));
|
||||
|
||||
dbTypeMap.put(Types.DATE, new DbType("datetime"));
|
||||
dbTypeMap.put(Types.TIME, new DbType("datetime"));
|
||||
dbTypeMap.put(Types.TIMESTAMP, new DbType("datetime"));
|
||||
dbTypeMap.put(Types.DATE, new DbType("date"));
|
||||
dbTypeMap.put(Types.TIME, new DbType("time"));
|
||||
dbTypeMap.put(Types.TIMESTAMP, new DbType("datetime2"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,11 @@ public class BaseTableDdl implements TableDdl {
|
||||
*/
|
||||
protected IndexSet indexSet = new IndexSet();
|
||||
|
||||
/**
|
||||
* Used when unique constraints specifically for OneToOne can't be created normally (MsSqlServer).
|
||||
*/
|
||||
protected IndexSet externalUnique = new IndexSet();
|
||||
|
||||
// counters used when constraint names are truncated due to maximum length
|
||||
// and these counters are used to keep the constraint name unique
|
||||
protected int countCheck;
|
||||
@@ -45,10 +50,11 @@ public class BaseTableDdl implements TableDdl {
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset counters and index set for each table.
|
||||
* Reset counters and index set for each table processed.
|
||||
*/
|
||||
protected void reset() {
|
||||
indexSet.clear();
|
||||
externalUnique.clear();
|
||||
countCheck = 0;
|
||||
countUnique = 0;
|
||||
countForeignKey = 0;
|
||||
@@ -57,7 +63,7 @@ public class BaseTableDdl implements TableDdl {
|
||||
|
||||
/**
|
||||
* Generate the appropriate 'create table' and matching 'drop table' statements
|
||||
* and add them to the 'apply' and 'rollback' buffers.
|
||||
* and add them to the appropriate 'apply' and 'rollback' buffers.
|
||||
*/
|
||||
@Override
|
||||
public void generate(DdlWrite writer, CreateTable createTable) throws IOException {
|
||||
@@ -98,6 +104,8 @@ public class BaseTableDdl implements TableDdl {
|
||||
|
||||
apply.newLine().append(")").endOfStatement();
|
||||
|
||||
writeUniqueOneToOneConstraints(writer, createTable);
|
||||
|
||||
// add drop table to the rollback buffer - do this before
|
||||
// we drop the related sequence (if sequences are used)
|
||||
dropTable(writer.rollback(), tableName);
|
||||
@@ -118,6 +126,29 @@ public class BaseTableDdl implements TableDdl {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Specific handling of OneToOne unique constraints for MsSqlServer.
|
||||
* For all other DB platforms these unique constraints are done inline as per normal.
|
||||
*/
|
||||
private void writeUniqueOneToOneConstraints(DdlWrite write, CreateTable createTable) throws IOException {
|
||||
|
||||
String tableName = createTable.getName();
|
||||
for (IndexColumns index : externalUnique.indexes) {
|
||||
String uqName = determineUniqueConstraintName(tableName, index.joinedNames());
|
||||
write.apply()
|
||||
.append(platformDdl.createExternalUniqueForOneToOne(uqName, tableName, index.columnsArray()))
|
||||
.endOfStatement();
|
||||
|
||||
// register it so we check against effective duplication
|
||||
// when creating the foreign key indexes
|
||||
indexSet.add(index);
|
||||
|
||||
write.rollbackForeignKeys()
|
||||
.append(platformDdl.dropIndex(uqName, tableName))
|
||||
.endOfStatement();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeSequence(DdlWrite writer, CreateTable createTable) throws IOException {
|
||||
|
||||
// explicit sequence use or platform decides
|
||||
@@ -231,7 +262,7 @@ public class BaseTableDdl implements TableDdl {
|
||||
|
||||
private void appendColumns(String[] columns, DdlBuffer buffer) throws IOException {
|
||||
buffer.append(" (");
|
||||
for (int i = 0; i <columns.length ; i++) {
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
if (i > 0) {
|
||||
buffer.append(",");
|
||||
}
|
||||
@@ -284,11 +315,17 @@ public class BaseTableDdl implements TableDdl {
|
||||
*/
|
||||
protected void writeUniqueConstraints(DdlBuffer apply, CreateTable createTable) throws IOException {
|
||||
|
||||
boolean inlineUniqueOneToOne = platformDdl.isInlineUniqueOneToOne();
|
||||
|
||||
List<Column> columns = createTable.getColumn();
|
||||
for (Column column : columns) {
|
||||
if (isTrue(column.isUnique())) {
|
||||
if (isTrue(column.isUnique()) || (inlineUniqueOneToOne && isTrue(column.isUniqueOneToOne()))) {
|
||||
// normal mechanism for adding unique constraint
|
||||
inlineUniqueConstraintSingle(apply, createTable.getName(), column);
|
||||
indexSet.add(column);
|
||||
} else if (!inlineUniqueOneToOne && isTrue(column.isUniqueOneToOne())) {
|
||||
// MsSqlServer specific mechanism for adding unique constraints (that allow nulls)
|
||||
externalUnique.add(column);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -459,7 +496,10 @@ public class BaseTableDdl implements TableDdl {
|
||||
return Boolean.TRUE.equals(value);
|
||||
}
|
||||
|
||||
private int toInt(BigInteger value) {
|
||||
/**
|
||||
* Return as an int value with 0 when it is null.
|
||||
*/
|
||||
protected int toInt(BigInteger value) {
|
||||
return (value == null) ? 0 : value.intValue();
|
||||
}
|
||||
|
||||
@@ -497,7 +537,7 @@ public class BaseTableDdl implements TableDdl {
|
||||
*/
|
||||
public boolean add(String[] columns) {
|
||||
IndexColumns newIndex = new IndexColumns(columns);
|
||||
for (int i = 0; i <indexes.size() ; i++) {
|
||||
for (int i = 0; i < indexes.size(); i++) {
|
||||
if (indexes.get(i).isMatch(newIndex)) {
|
||||
return false;
|
||||
}
|
||||
@@ -505,6 +545,14 @@ public class BaseTableDdl implements TableDdl {
|
||||
indexes.add(newIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the externally created unique constraint here so that we check later if foreign key indexes
|
||||
* don't need to be created (as the columns match this unique constraint).
|
||||
*/
|
||||
public void add(IndexColumns index) {
|
||||
indexes.add(index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -525,7 +573,7 @@ public class BaseTableDdl implements TableDdl {
|
||||
* Construct representing index.
|
||||
*/
|
||||
public IndexColumns(String[] columnNames) {
|
||||
for (int i = 0; i <columnNames.length; i++) {
|
||||
for (int i = 0; i < columnNames.length; i++) {
|
||||
columns.add(columnNames[i]);
|
||||
}
|
||||
}
|
||||
@@ -537,8 +585,36 @@ public class BaseTableDdl implements TableDdl {
|
||||
return columns.equals(other.columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a unique index based on the single column.
|
||||
*/
|
||||
protected void add(String column) {
|
||||
columns.add(column);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the columns as a string array.
|
||||
*/
|
||||
public String[] columnsArray() {
|
||||
return columns.toArray(new String[columns.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the column names all joined with underscore.
|
||||
*/
|
||||
public String joinedNames() {
|
||||
if (columns.size() == 1) {
|
||||
return columns.get(0);
|
||||
} else {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < columns.size(); i++) {
|
||||
if (i > 0) {
|
||||
sb.append("_");
|
||||
}
|
||||
sb.append(columns.get(i));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+36
-26
@@ -10,32 +10,42 @@ public class MsSqlServerDdl extends PlatformDdl {
|
||||
|
||||
public MsSqlServerDdl(DbTypeMap platformTypes, DbIdentity dbIdentity) {
|
||||
super(platformTypes, dbIdentity);
|
||||
this.identitySuffix = " generated by default as identity";
|
||||
this.identitySuffix = " identity(1,1)";
|
||||
this.foreignKeyRestrict = "";
|
||||
this.inlineUniqueOneToOne = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dropTable(String tableName) {
|
||||
return "IF OBJECT_ID('" + tableName + "', 'U') IS NOT NULL drop table " + tableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String alterTableDropForeignKey(String tableName, String fkName) {
|
||||
return "IF OBJECT_ID('" + fkName + "', 'F') IS NOT NULL " + super.alterTableDropForeignKey(tableName, fkName);
|
||||
}
|
||||
|
||||
/**
|
||||
* MsSqlServer specific null handling on unique constraints.
|
||||
*/
|
||||
@Override
|
||||
public String createExternalUniqueForOneToOne(String uqName, String tableName, String[] columns) {
|
||||
|
||||
// issues#233
|
||||
String start = "create unique nonclustered index " + uqName + " on " + tableName+ "(";
|
||||
StringBuilder sb = new StringBuilder(start);
|
||||
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append(columns[i]);
|
||||
}
|
||||
sb.append(") where");
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
sb.append(" ").append(columns[i]).append(" is not null");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
// /**
|
||||
// * MS SQL Server specific DDL Syntax.
|
||||
// */
|
||||
// public class MsDdlSyntax extends DbDdlSyntax {
|
||||
//
|
||||
// MsDdlSyntax() {
|
||||
// this.identity = "identity(1,1)";
|
||||
// this.dropKeyConstraints = true;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Return some DDL to disable constraints on the given table.
|
||||
// */
|
||||
// public String dropKeyConstraintPrefix(String tableName, String fkName) {
|
||||
// return "IF OBJECT_ID('"+fkName+"', 'F') IS NOT NULL";
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Return prefix text that goes before drop table.
|
||||
// */
|
||||
// public String dropTablePrefix(String tableName) {
|
||||
// return "IF OBJECT_ID('"+tableName+"', 'U') IS NOT NULL ";
|
||||
// }
|
||||
//
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -47,6 +47,10 @@ public class PlatformDdl {
|
||||
|
||||
protected String identitySuffix = " auto_increment";
|
||||
|
||||
/**
|
||||
* Set false for MsSqlServer to allow multiple nulls for OneToOne mapping.
|
||||
*/
|
||||
protected boolean inlineUniqueOneToOne = true;
|
||||
|
||||
public PlatformDdl(DbTypeMap platformTypes, DbIdentity dbIdentity) {
|
||||
this.dbIdentity = dbIdentity;
|
||||
@@ -157,4 +161,19 @@ public class PlatformDdl {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if unique constraints for OneToOne can be inlined as normal.
|
||||
* Returns false for MsSqlServer due to it's null handling for unique constraints.
|
||||
*/
|
||||
public boolean isInlineUniqueOneToOne() {
|
||||
return inlineUniqueOneToOne;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridden by MsSqlServer for specific null handling on unique constraints.
|
||||
*/
|
||||
public String createExternalUniqueForOneToOne(String uqName, String tableName, String[] columns) {
|
||||
// does nothing by default, really this is a MsSqlServer specific requirement
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ public class Column {
|
||||
protected String checkConstraint;
|
||||
@XmlAttribute(name = "unique")
|
||||
protected Boolean unique;
|
||||
@XmlAttribute(name = "uniqueOneToOne")
|
||||
protected Boolean uniqueOneToOne;
|
||||
@XmlAttribute(name = "primaryKey")
|
||||
protected Boolean primaryKey;
|
||||
@XmlAttribute(name = "identity")
|
||||
@@ -153,6 +155,30 @@ public class Column {
|
||||
this.unique = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the uniqueOneToOne property.
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link Boolean }
|
||||
*
|
||||
*/
|
||||
public Boolean isUniqueOneToOne() {
|
||||
return uniqueOneToOne;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the uniqueOneToOne property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link Boolean }
|
||||
*
|
||||
*/
|
||||
public void setUniqueOneToOne(Boolean value) {
|
||||
this.uniqueOneToOne = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the primaryKey property.
|
||||
*
|
||||
|
||||
@@ -15,8 +15,15 @@ public class MColumn {
|
||||
private boolean notnull;
|
||||
private boolean primaryKey;
|
||||
private boolean identity;
|
||||
|
||||
private boolean unique;
|
||||
|
||||
/**
|
||||
* Special unique for OneToOne as we need to handle that different
|
||||
* specifically for MsSqlServer.
|
||||
*/
|
||||
private boolean uniqueOneToOne;
|
||||
|
||||
public MColumn(Column column) {
|
||||
this.name = column.getName();
|
||||
this.type = column.getType();
|
||||
@@ -104,15 +111,31 @@ public class MColumn {
|
||||
return unique;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set unique specifically for OneToOne mapping.
|
||||
* We need special DDL for this case for MsSqlServer.
|
||||
*/
|
||||
public void setUniqueOneToOne(boolean uniqueOneToOne) {
|
||||
this.uniqueOneToOne = uniqueOneToOne;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is unique for a OneToOne.
|
||||
*/
|
||||
public boolean isUniqueOneToOne() {
|
||||
return uniqueOneToOne;
|
||||
}
|
||||
|
||||
public Column createColumn() {
|
||||
|
||||
Column c = new Column();
|
||||
c.setName(name);
|
||||
c.setType(type);
|
||||
if (notnull) c.setNotnull(notnull);
|
||||
if (unique) c.setUnique(unique);
|
||||
if (primaryKey) c.setPrimaryKey(primaryKey);
|
||||
if (identity) c.setIdentity(identity);
|
||||
if (notnull) c.setNotnull(true);
|
||||
if (unique) c.setUnique(true);
|
||||
if (uniqueOneToOne) c.setUniqueOneToOne(true);
|
||||
if (primaryKey) c.setPrimaryKey(true);
|
||||
if (identity) c.setIdentity(true);
|
||||
|
||||
c.setCheckConstraint(checkConstraint);
|
||||
c.setReferences(references);
|
||||
|
||||
@@ -9,16 +9,33 @@ package com.avaje.ebean.dbmigration.model;
|
||||
*/
|
||||
public class MCompoundUniqueConstraint {
|
||||
|
||||
/**
|
||||
* Flag if true indicates this was specifically created for a OneToOne mapping.
|
||||
*/
|
||||
private final boolean oneToOne;
|
||||
|
||||
/**
|
||||
* The columns combined to be unique.
|
||||
*/
|
||||
private final String[] columns;
|
||||
|
||||
public MCompoundUniqueConstraint(String[] columns) {
|
||||
public MCompoundUniqueConstraint(String[] columns, boolean oneToOne) {
|
||||
this.columns = columns;
|
||||
this.oneToOne = oneToOne;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the columns for this unique constraint.
|
||||
*/
|
||||
public String[] getColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this unqiue constraint is specifically for OneToOne mapping.
|
||||
*/
|
||||
public boolean isOneToOne() {
|
||||
return oneToOne;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -248,19 +248,19 @@ public class MTable {
|
||||
/**
|
||||
* Add a compound unique constraint.
|
||||
*/
|
||||
public void addCompoundUniqueConstraint(String[] columns) {
|
||||
compoundUniqueConstraints.add(new MCompoundUniqueConstraint(columns));
|
||||
public void addCompoundUniqueConstraint(String[] columns, boolean oneToOne) {
|
||||
compoundUniqueConstraints.add(new MCompoundUniqueConstraint(columns, oneToOne));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a compound unique constraint.
|
||||
*/
|
||||
public void addCompoundUniqueConstraint(List<MColumn> columns) {
|
||||
public void addCompoundUniqueConstraint(List<MColumn> columns, boolean oneToOne) {
|
||||
String[] cols = new String[columns.size()];
|
||||
for (int i = 0; i < columns.size(); i++) {
|
||||
cols[i] = columns.get(i).getName();
|
||||
}
|
||||
addCompoundUniqueConstraint(cols);
|
||||
addCompoundUniqueConstraint(cols, oneToOne);
|
||||
}
|
||||
|
||||
public void addForeignKey(MCompoundForeignKey compoundKey) {
|
||||
|
||||
@@ -3,34 +3,30 @@ package com.avaje.ebean.dbmigration.model.build;
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebean.config.dbplatform.IdType;
|
||||
import com.avaje.ebean.dbmigration.migration.IdentityType;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueContraint;
|
||||
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
|
||||
import com.avaje.ebean.dbmigration.model.MColumn;
|
||||
import com.avaje.ebean.dbmigration.model.MTable;
|
||||
import com.avaje.ebean.dbmigration.model.visitor.BeanPropertyVisitor;
|
||||
import com.avaje.ebean.dbmigration.model.visitor.BeanVisitor;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarType;
|
||||
|
||||
import java.sql.Types;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueContraint;
|
||||
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
|
||||
|
||||
/**
|
||||
* Used to build the Model objects MTable etc.
|
||||
*/
|
||||
public class ModelBuildBeanVisitor implements BeanVisitor {
|
||||
|
||||
private final ModelBuildContext ctx;
|
||||
private final ModelBuildContext ctx;
|
||||
|
||||
public ModelBuildBeanVisitor(ModelBuildContext ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
public ModelBuildBeanVisitor(ModelBuildContext ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the PropertyVisitor used to read all the property meta data
|
||||
* and in this case add MColumn objects to the model.
|
||||
* <p>
|
||||
* This creates an MTable and adds it to the model.
|
||||
* This creates an MTable and adds it to the model.
|
||||
* </p>
|
||||
*/
|
||||
public BeanPropertyVisitor visitBean(BeanDescriptor<?> descriptor) {
|
||||
@@ -59,7 +55,7 @@ public class ModelBuildBeanVisitor implements BeanVisitor {
|
||||
CompoundUniqueContraint[] compoundUniqueConstraints = descriptor.getCompoundUniqueConstraints();
|
||||
if (compoundUniqueConstraints != null) {
|
||||
for (int i = 0; i < compoundUniqueConstraints.length; i++) {
|
||||
table.addCompoundUniqueConstraint(compoundUniqueConstraints[i].getColumns());
|
||||
table.addCompoundUniqueConstraint(compoundUniqueConstraints[i].getColumns(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +64,6 @@ public class ModelBuildBeanVisitor implements BeanVisitor {
|
||||
|
||||
private void setIdentity(BeanDescriptor<?> descriptor, MTable table) {
|
||||
|
||||
|
||||
if (IdType.GENERATOR == descriptor.getIdType()) {
|
||||
// explicit generator like UUID
|
||||
table.setIdentityType(IdentityType.GENERATOR);
|
||||
@@ -94,20 +89,7 @@ public class ModelBuildBeanVisitor implements BeanVisitor {
|
||||
table.setSequenceInitial(initialValue);
|
||||
table.setSequenceAllocate(allocationSize);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
BeanProperty idProperty = descriptor.getIdProperty();
|
||||
if (idProperty != null) {
|
||||
ScalarType<Object> scalarType = idProperty.getScalarType();
|
||||
if (scalarType != null) {
|
||||
int jdbcType = scalarType.getJdbcType();
|
||||
if (jdbcType == Types.VARCHAR) {
|
||||
System.out.println("asd");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-5
@@ -115,14 +115,13 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
|
||||
modelColumns.add(col);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (p.isOneToOne()) {
|
||||
// Adding the unique constraint restricts the cardinality from OneToMany down to OneToOne
|
||||
// adding the unique constraint restricts the cardinality from OneToMany down to OneToOne
|
||||
// for MsSqlServer we need different DDL to handle NULL values on this constraint
|
||||
if (modelColumns.size() == 1) {
|
||||
modelColumns.get(0).setUnique(true);
|
||||
modelColumns.get(0).setUniqueOneToOne(true);
|
||||
} else {
|
||||
table.addCompoundUniqueConstraint(modelColumns);
|
||||
table.addCompoundUniqueConstraint(modelColumns, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,6 +169,7 @@ public class DefaultCsvCallback<T> implements CsvCallback<T> {
|
||||
logger.info("Creating transaction, batchSize[" + persistBatchSize + "]");
|
||||
transaction.setBatchMode(true);
|
||||
transaction.setBatchSize(persistBatchSize);
|
||||
transaction.setBatchGetGeneratedKeys(false);
|
||||
|
||||
} else {
|
||||
// explicitly turn off JDBC batching in case
|
||||
|
||||
@@ -264,6 +264,7 @@
|
||||
<xsd:attribute name="notnull" type="xsd:boolean"/>
|
||||
<xsd:attribute name="checkConstraint" type="xsd:string"/>
|
||||
<xsd:attribute name="unique" type="xsd:boolean"/>
|
||||
<xsd:attribute name="uniqueOneToOne" type="xsd:boolean"/>
|
||||
<xsd:attribute name="primaryKey" type="xsd:boolean"/>
|
||||
<xsd:attribute name="identity" type="xsd:boolean"/> <!-- aka autoincrement/identity -->
|
||||
<xsd:attribute name="references" type="xsd:string"/>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import org.avaje.agentloader.AgentLoader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -15,4 +16,12 @@ public class BaseTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* MS SQL Server does not allow setting explicit values on identity columns
|
||||
* so tests that do this need to be skipped for SQL Server.
|
||||
*/
|
||||
public boolean isMsSqlServer() {
|
||||
SpiEbeanServer spi = (SpiEbeanServer)Ebean.getDefaultServer();
|
||||
return spi.getDatabasePlatform().getName().startsWith("mssqlserver");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ public class TestBatchPersistCascade extends BaseTestCase {
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
EbeanServer ebeanServer = Ebean.getServer(null);
|
||||
|
||||
|
||||
@@ -15,142 +15,139 @@ import com.avaje.tests.model.basic.ResetBasicData;
|
||||
|
||||
public class TestLimitQuery extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void testNothing() {
|
||||
|
||||
}
|
||||
@Test
|
||||
public void testLimitWithMany() {
|
||||
rob();
|
||||
rob();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLimitWithMany() {
|
||||
rob();
|
||||
rob();
|
||||
}
|
||||
@Test
|
||||
public void testMaxRowsZeroWithFirstRow() {
|
||||
|
||||
@Test
|
||||
public void testMaxRowsZeroWithFirstRow() {
|
||||
ResetBasicData.reset();
|
||||
ResetBasicData.reset();
|
||||
|
||||
SpiEbeanServer server = (SpiEbeanServer)Ebean.getServer(null);
|
||||
boolean h2Db = "h2".equals(server.getDatabasePlatform().getName());
|
||||
SpiEbeanServer server = (SpiEbeanServer) Ebean.getServer(null);
|
||||
boolean h2Db = "h2".equals(server.getDatabasePlatform().getName());
|
||||
|
||||
Query<Order> query = Ebean.find(Order.class)
|
||||
.setAutofetch(false)
|
||||
.fetch("details")
|
||||
.where().gt("details.id", 0)
|
||||
.setMaxRows(0)
|
||||
.setFirstRow(3);
|
||||
Query<Order> query = Ebean.find(Order.class)
|
||||
.setAutofetch(false)
|
||||
.fetch("details")
|
||||
.where().gt("details.id", 0)
|
||||
.setMaxRows(0)
|
||||
.setFirstRow(3)
|
||||
.order().asc("orderDate");
|
||||
|
||||
query.findList();
|
||||
query.findList();
|
||||
|
||||
String sql = query.getGeneratedSql();
|
||||
boolean hasLimit = sql.contains("limit 0");
|
||||
boolean hasOffset = sql.contains("offset 3");
|
||||
String sql = query.getGeneratedSql();
|
||||
boolean hasLimit = sql.contains("limit 0");
|
||||
boolean hasOffset = sql.contains("offset 3");
|
||||
|
||||
if (h2Db) {
|
||||
Assert.assertTrue(hasLimit);
|
||||
Assert.assertTrue(hasOffset);
|
||||
}
|
||||
}
|
||||
if (h2Db) {
|
||||
Assert.assertTrue(hasLimit);
|
||||
Assert.assertTrue(hasOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxRowsWithFirstRowZero() {
|
||||
ResetBasicData.reset();
|
||||
@Test
|
||||
public void testMaxRowsWithFirstRowZero() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
SpiEbeanServer server = (SpiEbeanServer)Ebean.getServer(null);
|
||||
boolean h2Db = "h2".equals(server.getDatabasePlatform().getName());
|
||||
SpiEbeanServer server = (SpiEbeanServer) Ebean.getServer(null);
|
||||
boolean h2Db = "h2".equals(server.getDatabasePlatform().getName());
|
||||
|
||||
Query<Order> query = Ebean.find(Order.class)
|
||||
.setAutofetch(false)
|
||||
.fetch("details")
|
||||
.where().gt("details.id", 0)
|
||||
.setMaxRows(3)
|
||||
.setFirstRow(0);
|
||||
Query<Order> query = Ebean.find(Order.class)
|
||||
.setAutofetch(false)
|
||||
.fetch("details")
|
||||
.where().gt("details.id", 0)
|
||||
.setMaxRows(3)
|
||||
.setFirstRow(0);
|
||||
|
||||
query.findList();
|
||||
query.findList();
|
||||
|
||||
String sql = query.getGeneratedSql();
|
||||
boolean hasLimit = sql.contains("limit 3");
|
||||
boolean hasOffset = sql.contains("offset");
|
||||
String sql = query.getGeneratedSql();
|
||||
boolean hasLimit = sql.contains("limit 3");
|
||||
boolean hasOffset = sql.contains("offset");
|
||||
|
||||
if (h2Db) {
|
||||
Assert.assertTrue(sql, hasLimit);
|
||||
Assert.assertFalse(sql, hasOffset);
|
||||
}
|
||||
}
|
||||
if (h2Db) {
|
||||
Assert.assertTrue(sql, hasLimit);
|
||||
Assert.assertFalse(sql, hasOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaults() {
|
||||
ResetBasicData.reset();
|
||||
@Test
|
||||
public void testDefaults() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
SpiEbeanServer server = (SpiEbeanServer)Ebean.getServer(null);
|
||||
boolean h2Db = "h2".equals(server.getDatabasePlatform().getName());
|
||||
SpiEbeanServer server = (SpiEbeanServer) Ebean.getServer(null);
|
||||
boolean h2Db = "h2".equals(server.getDatabasePlatform().getName());
|
||||
|
||||
Query<Order> query = Ebean.find(Order.class)
|
||||
.setAutofetch(false)
|
||||
.fetch("details")
|
||||
.where().gt("details.id", 0)
|
||||
.query();
|
||||
Query<Order> query = Ebean.find(Order.class)
|
||||
.setAutofetch(false)
|
||||
.fetch("details")
|
||||
.where().gt("details.id", 0)
|
||||
.query();
|
||||
|
||||
query.findList();
|
||||
query.findList();
|
||||
|
||||
String sql = query.getGeneratedSql();
|
||||
boolean hasLimit = sql.contains("limit");
|
||||
boolean hasOffset = sql.contains("offset");
|
||||
String sql = query.getGeneratedSql();
|
||||
boolean hasLimit = sql.contains("limit");
|
||||
boolean hasOffset = sql.contains("offset");
|
||||
|
||||
if (h2Db) {
|
||||
Assert.assertFalse(hasLimit);
|
||||
Assert.assertFalse(hasOffset);
|
||||
}
|
||||
}
|
||||
if (h2Db) {
|
||||
Assert.assertFalse(hasLimit);
|
||||
Assert.assertFalse(hasOffset);
|
||||
}
|
||||
}
|
||||
|
||||
private void rob() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
SpiEbeanServer server = (SpiEbeanServer)Ebean.getServer(null);
|
||||
boolean h2Db = "h2".equals(server.getDatabasePlatform().getName());
|
||||
|
||||
Query<Order> query = Ebean.find(Order.class)
|
||||
.setAutofetch(false)
|
||||
.fetch("details")
|
||||
.where().gt("details.id", 0)
|
||||
.setMaxRows(10);
|
||||
//.findList();
|
||||
|
||||
List<Order> list = query.findList();
|
||||
|
||||
Assert.assertTrue("sz > 0", list.size() > 0);
|
||||
private void rob() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
String sql = query.getGeneratedSql();
|
||||
boolean hasDetailsJoin = sql.contains("join o_order_detail");
|
||||
boolean hasLimit = sql.contains("limit 10");
|
||||
boolean hasSelectedDetails = sql.contains("od.id,");
|
||||
boolean hasDistinct = sql.contains("select distinct");
|
||||
|
||||
Assert.assertTrue(hasDetailsJoin);
|
||||
Assert.assertFalse(hasSelectedDetails);
|
||||
Assert.assertTrue(hasDistinct);
|
||||
if (h2Db){
|
||||
Assert.assertTrue(hasLimit);
|
||||
}
|
||||
|
||||
query = Ebean.find(Order.class)
|
||||
.setAutofetch(false)
|
||||
.fetch("details")
|
||||
.setMaxRows(10);
|
||||
|
||||
query.findList();
|
||||
|
||||
sql = query.getGeneratedSql();
|
||||
hasDetailsJoin = sql.contains("left outer join o_order_detail");
|
||||
hasLimit = sql.contains("limit 10");
|
||||
hasSelectedDetails = sql.contains("od.id");
|
||||
hasDistinct = sql.contains("select distinct");
|
||||
SpiEbeanServer server = (SpiEbeanServer) Ebean.getServer(null);
|
||||
boolean h2Db = "h2".equals(server.getDatabasePlatform().getName());
|
||||
|
||||
Assert.assertFalse("no join with maxRows",hasDetailsJoin);
|
||||
Assert.assertFalse(hasSelectedDetails);
|
||||
Assert.assertFalse(hasDistinct);
|
||||
if (h2Db){
|
||||
Assert.assertTrue(hasLimit);
|
||||
}
|
||||
}
|
||||
Query<Order> query = Ebean.find(Order.class)
|
||||
.setAutofetch(false)
|
||||
.fetch("details")
|
||||
.where().gt("details.id", 0)
|
||||
.setMaxRows(10);
|
||||
//.findList();
|
||||
|
||||
List<Order> list = query.findList();
|
||||
|
||||
Assert.assertTrue("sz > 0", list.size() > 0);
|
||||
|
||||
String sql = query.getGeneratedSql();
|
||||
boolean hasDetailsJoin = sql.contains("join o_order_detail");
|
||||
boolean hasLimit = sql.contains("limit 10");
|
||||
boolean hasSelectedDetails = sql.contains("od.id,");
|
||||
boolean hasDistinct = sql.contains("select distinct");
|
||||
|
||||
Assert.assertTrue(hasDetailsJoin);
|
||||
Assert.assertFalse(hasSelectedDetails);
|
||||
Assert.assertTrue(hasDistinct);
|
||||
if (h2Db) {
|
||||
Assert.assertTrue(hasLimit);
|
||||
}
|
||||
|
||||
query = Ebean.find(Order.class)
|
||||
.setAutofetch(false)
|
||||
.fetch("details")
|
||||
.setMaxRows(10);
|
||||
|
||||
query.findList();
|
||||
|
||||
sql = query.getGeneratedSql();
|
||||
hasDetailsJoin = sql.contains("left outer join o_order_detail");
|
||||
hasLimit = sql.contains("limit 10");
|
||||
hasSelectedDetails = sql.contains("od.id");
|
||||
hasDistinct = sql.contains("select distinct");
|
||||
|
||||
Assert.assertFalse("no join with maxRows", hasDetailsJoin);
|
||||
Assert.assertFalse(hasSelectedDetails);
|
||||
Assert.assertFalse(hasDistinct);
|
||||
if (h2Db) {
|
||||
Assert.assertTrue(hasLimit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ public class TestBatchInsertSimple extends BaseTestCase {
|
||||
transaction.setBatch(PersistBatch.NONE);
|
||||
transaction.setBatchOnCascade(PersistBatch.INSERT);
|
||||
transaction.setBatchSize(30);
|
||||
// setBatchGetGeneratedKeys MUST be turned off for MS SQL Server because :(
|
||||
transaction.setBatchGetGeneratedKeys(false);
|
||||
|
||||
for (int i = 0; i < numOfMasters; i++) {
|
||||
UTMaster master = createMasterAndDetails(i, 20);
|
||||
@@ -43,6 +45,8 @@ public class TestBatchInsertSimple extends BaseTestCase {
|
||||
@Test
|
||||
public void testTransactional() {
|
||||
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
saveWithFullBatchMode();
|
||||
}
|
||||
|
||||
@@ -69,6 +73,8 @@ public class TestBatchInsertSimple extends BaseTestCase {
|
||||
transaction.setBatch(PersistBatch.NONE);
|
||||
transaction.setBatchOnCascade(PersistBatch.INSERT);
|
||||
transaction.setBatchSize(30);
|
||||
// setBatchGetGeneratedKeys MUST be turned off for MS SQL Server because :(
|
||||
transaction.setBatchGetGeneratedKeys(false);
|
||||
|
||||
for (int i = 0; i < numOfMasters; i++) {
|
||||
UTMaster master = createMaster(i);
|
||||
@@ -85,6 +91,9 @@ public class TestBatchInsertSimple extends BaseTestCase {
|
||||
@Test
|
||||
public void testJdbcBatchOnCollection() {
|
||||
|
||||
// MS SQL Server doesn't like batch inserts when we need getGeneratedKeys
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
int numOfMasters = 3;
|
||||
|
||||
List<UTMaster> masters = new ArrayList<UTMaster>();
|
||||
|
||||
+2
@@ -18,6 +18,8 @@ public class TestBatchInsertWithInitialisedCollection extends BaseTestCase {
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
List<OCachedBean> list = new ArrayList();
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
|
||||
@@ -22,141 +22,147 @@ import com.avaje.tests.lib.EbeanTestCase;
|
||||
* <li>find</li>
|
||||
* </ul>
|
||||
*/
|
||||
public class TestCore extends EbeanTestCase
|
||||
{
|
||||
//private boolean setup;
|
||||
public class TestCore extends EbeanTestCase {
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
Ebean.createUpdate(Item.class, "delete from Item").execute();
|
||||
Ebean.createUpdate(Region.class, "delete from Region").execute();
|
||||
Ebean.createUpdate(Type.class, "delete from Type").execute();
|
||||
Ebean.createUpdate(SubType.class, "delete from SubType").execute();
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
Transaction tx = getServer().beginTransaction();
|
||||
Ebean.createUpdate(Item.class, "delete from Item").execute();
|
||||
Ebean.createUpdate(Region.class, "delete from Region").execute();
|
||||
Ebean.createUpdate(Type.class, "delete from Type").execute();
|
||||
Ebean.createUpdate(SubType.class, "delete from SubType").execute();
|
||||
|
||||
SubType subType = new SubType();
|
||||
SubTypeKey subTypeKey = new SubTypeKey();
|
||||
subTypeKey.setSubTypeId(1);
|
||||
subType.setKey(subTypeKey);
|
||||
subType.setDescription("ANY SUBTYPE");
|
||||
getServer().save(subType);
|
||||
Transaction tx = getServer().beginTransaction();
|
||||
|
||||
Type type = new Type();
|
||||
TypeKey typeKey = new TypeKey();
|
||||
typeKey.setCustomer(1);
|
||||
typeKey.setType(10);
|
||||
type.setKey(typeKey);
|
||||
type.setDescription("Type Old-Item - Customer 1");
|
||||
type.setSubType(subType);
|
||||
getServer().save(type);
|
||||
SubType subType = new SubType();
|
||||
SubTypeKey subTypeKey = new SubTypeKey();
|
||||
subTypeKey.setSubTypeId(1);
|
||||
subType.setKey(subTypeKey);
|
||||
subType.setDescription("ANY SUBTYPE");
|
||||
getServer().save(subType);
|
||||
|
||||
type = new Type();
|
||||
typeKey = new TypeKey();
|
||||
typeKey.setCustomer(2);
|
||||
typeKey.setType(10);
|
||||
type.setKey(typeKey);
|
||||
type.setDescription("Type Old-Item - Customer 2");
|
||||
type.setSubType(subType);
|
||||
getServer().save(type);
|
||||
Type type = new Type();
|
||||
TypeKey typeKey = new TypeKey();
|
||||
typeKey.setCustomer(1);
|
||||
typeKey.setType(10);
|
||||
type.setKey(typeKey);
|
||||
type.setDescription("Type Old-Item - Customer 1");
|
||||
type.setSubType(subType);
|
||||
getServer().save(type);
|
||||
|
||||
Region region = new Region();
|
||||
RegionKey regionKey = new RegionKey();
|
||||
regionKey.setCustomer(1);
|
||||
regionKey.setType(500);
|
||||
region.setKey(regionKey);
|
||||
region.setDescription("Region West - Customer 1");
|
||||
getServer().save(region);
|
||||
type = new Type();
|
||||
typeKey = new TypeKey();
|
||||
typeKey.setCustomer(2);
|
||||
typeKey.setType(10);
|
||||
type.setKey(typeKey);
|
||||
type.setDescription("Type Old-Item - Customer 2");
|
||||
type.setSubType(subType);
|
||||
getServer().save(type);
|
||||
|
||||
region = new Region();
|
||||
regionKey = new RegionKey();
|
||||
regionKey.setCustomer(2);
|
||||
regionKey.setType(500);
|
||||
region.setKey(regionKey);
|
||||
region.setDescription("Region West - Customer 2");
|
||||
getServer().save(region);
|
||||
Region region = new Region();
|
||||
RegionKey regionKey = new RegionKey();
|
||||
regionKey.setCustomer(1);
|
||||
regionKey.setType(500);
|
||||
region.setKey(regionKey);
|
||||
region.setDescription("Region West - Customer 1");
|
||||
getServer().save(region);
|
||||
|
||||
Item item = new Item();
|
||||
ItemKey itemKey = new ItemKey();
|
||||
itemKey.setCustomer(1);
|
||||
itemKey.setItemNumber("ITEM1");
|
||||
item.setKey(itemKey);
|
||||
item.setUnits("P");
|
||||
item.setDescription("Fancy Car - Customer 1");
|
||||
item.setRegion(500);
|
||||
item.setType(10);
|
||||
getServer().save(item);
|
||||
region = new Region();
|
||||
regionKey = new RegionKey();
|
||||
regionKey.setCustomer(2);
|
||||
regionKey.setType(500);
|
||||
region.setKey(regionKey);
|
||||
region.setDescription("Region West - Customer 2");
|
||||
getServer().save(region);
|
||||
|
||||
item = new Item();
|
||||
itemKey = new ItemKey();
|
||||
itemKey.setCustomer(2);
|
||||
itemKey.setItemNumber("ITEM1");
|
||||
item.setKey(itemKey);
|
||||
item.setUnits("P");
|
||||
item.setDescription("Another Fancy Car - Customer 2");
|
||||
item.setRegion(500);
|
||||
item.setType(10);
|
||||
getServer().save(item);
|
||||
Item item = new Item();
|
||||
ItemKey itemKey = new ItemKey();
|
||||
itemKey.setCustomer(1);
|
||||
itemKey.setItemNumber("ITEM1");
|
||||
item.setKey(itemKey);
|
||||
item.setUnits("P");
|
||||
item.setDescription("Fancy Car - Customer 1");
|
||||
item.setRegion(500);
|
||||
item.setType(10);
|
||||
getServer().save(item);
|
||||
|
||||
tx.commit();
|
||||
}
|
||||
item = new Item();
|
||||
itemKey = new ItemKey();
|
||||
itemKey.setCustomer(2);
|
||||
itemKey.setItemNumber("ITEM1");
|
||||
item.setKey(itemKey);
|
||||
item.setUnits("P");
|
||||
item.setDescription("Another Fancy Car - Customer 2");
|
||||
item.setRegion(500);
|
||||
item.setType(10);
|
||||
getServer().save(item);
|
||||
|
||||
public void testFind()
|
||||
{
|
||||
List<Item> items = getServer().find(Item.class).findList();
|
||||
tx.commit();
|
||||
}
|
||||
|
||||
assertNotNull(items);
|
||||
assertEquals(2, items.size());
|
||||
public void testFind() {
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
Query<Item> qItems = getServer().find(Item.class);
|
||||
List<Item> items = getServer().find(Item.class).findList();
|
||||
|
||||
assertNotNull(items);
|
||||
assertEquals(2, items.size());
|
||||
|
||||
Query<Item> qItems = getServer().find(Item.class);
|
||||
// qItems.where(Expr.eq("key.customer", Integer.valueOf(1)));
|
||||
|
||||
// I want to discourage the direct use of Expr
|
||||
qItems.where().eq("key.customer", Integer.valueOf(1));
|
||||
items = qItems.findList();
|
||||
|
||||
assertNotNull(items);
|
||||
assertEquals(1, items.size());
|
||||
}
|
||||
// I want to discourage the direct use of Expr
|
||||
qItems.where().eq("key.customer", Integer.valueOf(1));
|
||||
items = qItems.findList();
|
||||
|
||||
/**
|
||||
* This partially loads the item and then lazy loads the ManyToOne assoc
|
||||
*/
|
||||
public void testDoubleLazyLoad()
|
||||
{
|
||||
ItemKey itemKey = new ItemKey();
|
||||
itemKey.setCustomer(2);
|
||||
itemKey.setItemNumber("ITEM1");
|
||||
|
||||
Item item = getServer().find(Item.class).select("description").where().idEq(itemKey).findUnique();
|
||||
assertNotNull(item);
|
||||
assertNotNull(item.getUnits());
|
||||
assertEquals("P", item.getUnits());
|
||||
assertNotNull(items);
|
||||
assertEquals(1, items.size());
|
||||
}
|
||||
|
||||
Type type = item.getEType();
|
||||
assertNotNull(type);
|
||||
assertNotNull(type.getDescription());
|
||||
/**
|
||||
* This partially loads the item and then lazy loads the ManyToOne assoc
|
||||
*/
|
||||
public void testDoubleLazyLoad() {
|
||||
|
||||
SubType subType = type.getSubType();
|
||||
assertNotNull(subType);
|
||||
assertNotNull(subType.getDescription());
|
||||
}
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
public void testEmbeddedWithOrder()
|
||||
{
|
||||
List<Item> items = getServer().find(Item.class).order("auditInfo.created asc, type asc").findList();
|
||||
ItemKey itemKey = new ItemKey();
|
||||
itemKey.setCustomer(2);
|
||||
itemKey.setItemNumber("ITEM1");
|
||||
|
||||
assertNotNull(items);
|
||||
assertEquals(2, items.size());
|
||||
}
|
||||
|
||||
|
||||
public void testFindAndOrderByEType() {
|
||||
|
||||
List<Item> items = getServer().find(Item.class).order("eType").findList();
|
||||
Item item = getServer().find(Item.class).select("description").where().idEq(itemKey).findUnique();
|
||||
assertNotNull(item);
|
||||
assertNotNull(item.getUnits());
|
||||
assertEquals("P", item.getUnits());
|
||||
|
||||
assertNotNull(items);
|
||||
assertEquals(2, items.size());
|
||||
}
|
||||
Type type = item.getEType();
|
||||
assertNotNull(type);
|
||||
assertNotNull(type.getDescription());
|
||||
|
||||
SubType subType = type.getSubType();
|
||||
assertNotNull(subType);
|
||||
assertNotNull(subType.getDescription());
|
||||
}
|
||||
|
||||
public void testEmbeddedWithOrder() {
|
||||
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
List<Item> items = getServer().find(Item.class).order("auditInfo.created asc, type asc").findList();
|
||||
|
||||
assertNotNull(items);
|
||||
assertEquals(2, items.size());
|
||||
}
|
||||
|
||||
|
||||
public void testFindAndOrderByEType() {
|
||||
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
List<Item> items = getServer().find(Item.class).order("eType").findList();
|
||||
|
||||
assertNotNull(items);
|
||||
assertEquals(2, items.size());
|
||||
}
|
||||
}
|
||||
+14
@@ -31,7 +31,12 @@ import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
*/
|
||||
public class TestOnCascadeDeleteChildrenWithCompositeKeys extends BaseTestCase {
|
||||
|
||||
|
||||
|
||||
@Before public void before() {
|
||||
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
// remove all the User records first
|
||||
Ebean.deleteAll(Ebean.find(User.class).findList());
|
||||
|
||||
@@ -44,6 +49,9 @@ public class TestOnCascadeDeleteChildrenWithCompositeKeys extends BaseTestCase {
|
||||
* work fine when delete User one by one
|
||||
*/
|
||||
@Test public void testDeleteById() {
|
||||
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
assertEquals(2, Ebean.find(User.class).findList().size());
|
||||
Ebean.delete(User.class, 1L);
|
||||
Ebean.delete(User.class, 2L);
|
||||
@@ -55,6 +63,9 @@ public class TestOnCascadeDeleteChildrenWithCompositeKeys extends BaseTestCase {
|
||||
* SQL generated: delete from user_role where (user_id) in ((?,?),(?,?))
|
||||
*/
|
||||
@Test public void testDeleteByIdList() {
|
||||
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
assertEquals(2, Ebean.find(User.class).findList().size());
|
||||
List<Long> ids = new ArrayList<Long>();
|
||||
ids.add(1L);
|
||||
@@ -65,6 +76,9 @@ public class TestOnCascadeDeleteChildrenWithCompositeKeys extends BaseTestCase {
|
||||
}
|
||||
|
||||
@Test public void testFindByParentIdList() {
|
||||
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
assertEquals(2, Ebean.find(User.class).findList().size());
|
||||
|
||||
SpiEbeanServer spiServer = (SpiEbeanServer)Ebean.getServer(null);
|
||||
|
||||
@@ -15,7 +15,9 @@ public class TestDeleteByIdWithPersistenceContext extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
Ebean.delete(Product.class, 100);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.avaje.tests.lib;
|
||||
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import junit.framework.TestCase;
|
||||
import junit.framework.TestResult;
|
||||
|
||||
@@ -28,7 +29,16 @@ public abstract class EbeanTestCase extends TestCase {
|
||||
}
|
||||
|
||||
public EbeanServer getServer() {
|
||||
|
||||
return Ebean.getServer(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* MS SQL Server does not allow setting explicit values on identity columns
|
||||
* so tests that do this need to be skipped for SQL Server.
|
||||
*/
|
||||
public boolean isMsSqlServer() {
|
||||
SpiEbeanServer spi = (SpiEbeanServer)Ebean.getDefaultServer();
|
||||
return spi.getDatabasePlatform().getName().startsWith("mssqlserver");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ public class TestInsertBatchThenFlushThenUpdate extends BaseTestCase {
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
Transaction txn = Ebean.beginTransaction();
|
||||
try {
|
||||
|
||||
@@ -17,6 +17,8 @@ public class TestInsertBatchThenUpdate extends BaseTestCase {
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
Transaction txn = Ebean.beginTransaction();
|
||||
try {
|
||||
|
||||
+2
@@ -17,6 +17,8 @@ public class TestInsertBatchWithDifferentRootTypes extends BaseTestCase {
|
||||
@Test
|
||||
public void testDifferRootTypes() {
|
||||
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
Transaction txn = Ebean.beginTransaction();
|
||||
try {
|
||||
|
||||
@@ -10,22 +10,22 @@ import com.avaje.tests.model.basic.ResetBasicData;
|
||||
|
||||
public class TestQueryLimitOffsetSimple extends BaseTestCase {
|
||||
|
||||
/**
|
||||
* Test the syntax of the limit offset clause.
|
||||
*/
|
||||
/**
|
||||
* Test the syntax of the limit offset clause.
|
||||
*/
|
||||
@Test
|
||||
public void testMe() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
Query<Order> query = Ebean.createQuery(Order.class, "where status = :A limit 100 offset 3");
|
||||
query.setParameter("A",Order.Status.NEW);
|
||||
|
||||
query
|
||||
.setFirstRow(10)
|
||||
//.setMaxRows(100)
|
||||
.findList();
|
||||
|
||||
}
|
||||
|
||||
public void testMe() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
Query<Order> query = Ebean.createQuery(Order.class, "where status = :A limit 100 offset 3");
|
||||
query.setParameter("A", Order.Status.NEW);
|
||||
|
||||
query
|
||||
.setFirstRow(10)
|
||||
.order().asc("id")
|
||||
.findList();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ public class TestOrderByWithFunction extends BaseTestCase {
|
||||
@Test
|
||||
public void testWithFunction() {
|
||||
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
Query<Customer> query = Ebean.find(Customer.class).order("length(name),name");
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
package com.avaje.tests.rawsql;
|
||||
|
||||
import com.avaje.tests.idkeys.db.AuditLog;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.SqlUpdate;
|
||||
|
||||
public class TestInsertSqlLogging extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
Ebean.delete(AuditLog.class, 10000);
|
||||
|
||||
String sql = "insert into audit_log (id, description, modified_description) values (?,?,?)";
|
||||
SqlUpdate sqlUpdate = Ebean.createSqlUpdate(sql);
|
||||
sqlUpdate.setParameter(1, 10000);
|
||||
sqlUpdate.setParameter(2, "hello");
|
||||
sqlUpdate.setParameter(3, "rob");
|
||||
|
||||
sqlUpdate.execute();
|
||||
|
||||
}
|
||||
}
|
||||
package com.avaje.tests.rawsql;
|
||||
|
||||
import com.avaje.tests.idkeys.db.AuditLog;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.SqlUpdate;
|
||||
|
||||
public class TestInsertSqlLogging extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
Ebean.delete(AuditLog.class, 10000);
|
||||
|
||||
String sql = "insert into audit_log (id, description, modified_description) values (?,?,?)";
|
||||
SqlUpdate sqlUpdate = Ebean.createSqlUpdate(sql);
|
||||
sqlUpdate.setParameter(1, 10000);
|
||||
sqlUpdate.setParameter(2, "hello");
|
||||
sqlUpdate.setParameter(3, "rob");
|
||||
|
||||
sqlUpdate.execute();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,9 @@ public class TestRawSqlOrmQuery extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void testFirstRowsMaxRows() throws InterruptedException, ExecutionException {
|
||||
|
||||
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
RawSql rawSql =
|
||||
|
||||
@@ -13,6 +13,8 @@ public class TestSaveSamePK extends BaseTestCase {
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
if (isMsSqlServer()) return;
|
||||
|
||||
// delete in case we are running multiple times without full db drop
|
||||
Ebean.delete(TSMaster.class, 10000);
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ ebean.autofetch.traceUsageCollection=false
|
||||
|
||||
ebean.ddl.generate=true
|
||||
ebean.ddl.run=true
|
||||
datasource.default=h2
|
||||
datasource.default=ms
|
||||
|
||||
ebean.persistBatch=NONE
|
||||
ebean.persistBatchOnCascade=ALL
|
||||
@@ -113,8 +113,8 @@ datasource.pg.password=unit
|
||||
datasource.pg.databaseUrl=jdbc:postgresql://127.0.0.1:5432/unit
|
||||
datasource.pg.databaseDriver=org.postgresql.Driver
|
||||
|
||||
#datasource.ms.username=sa
|
||||
#datasource.ms.password=changeme
|
||||
#datasource.ms.databaseUrl=jdbc:sqlserver://localhost:65188
|
||||
#datasource.ms.databaseDriver=com.microsoft.sqlserver.jdbc.SQLServerDriver
|
||||
datasource.ms.username=test
|
||||
datasource.ms.password=test
|
||||
datasource.ms.databaseUrl=jdbc:sqlserver://192.168.1.68:1433;databaseName=test
|
||||
datasource.ms.databaseDriver=com.microsoft.sqlserver.jdbc.SQLServerDriver
|
||||
|
||||
|
||||
Reference in New Issue
Block a user