Browse Source

Added support for PostgreSQL. Passes all but the boolean-as-int tests.

tags/v0.7.0
James Moger 13 years ago
parent
commit
1734dc44d7

+ 1
- 0
.classpath View File

@@ -32,5 +32,6 @@
<attribute name="javadoc_location" value="jar:platform:/resource/iciql/ext/h2-1.3.159-javadoc.jar!/"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="ext/postgresql-9.0-801.jdbc4.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

+ 4
- 4
src/com/iciql/Db.java View File

@@ -72,10 +72,11 @@ public class Db {
// can register by...
// 1. Connection class name
// 2. DatabaseMetaData.getDatabaseProductName()
DIALECTS.put("Apache Derby", SQLDialectDerby.class);
DIALECTS.put("H2", SQLDialectH2.class);
DIALECTS.put("MySQL", SQLDialectMySQL.class);
DIALECTS.put("HSQL Database Engine", SQLDialectHSQL.class);
DIALECTS.put("Apache Derby", SQLDialectDerby.class);
DIALECTS.put("MySQL", SQLDialectMySQL.class);
DIALECTS.put("PostgreSQL", SQLDialectPostgreSQL.class);
}
private Db(Connection conn) {
@@ -249,8 +250,7 @@ public class Db {
try {
rc = stat.executeUpdate();
} catch (IciqlException e) {
if (e.getIciqlCode() != IciqlException.CODE_SCHEMA_NOT_FOUND
&& e.getIciqlCode() != IciqlException.CODE_TABLE_NOT_FOUND) {
if (e.getIciqlCode() != IciqlException.CODE_OBJECT_NOT_FOUND) {
throw e;
}
}

+ 1
- 2
src/com/iciql/DbInspector.java View File

@@ -169,8 +169,7 @@ public class DbInspector {
while (rs.next()) {
String t = rs.getString("TABLE_NAME");
if (!t.equalsIgnoreCase(iciqlTables)) {
tables.add(new TableInspector(s, t, getMetaData().storesUpperCaseIdentifiers(),
dateTimeClass));
tables.add(new TableInspector(s, t, dateTimeClass));
}
}
}

+ 25
- 20
src/com/iciql/IciqlException.java View File

@@ -27,10 +27,8 @@ public class IciqlException extends RuntimeException {
public static final int CODE_UNMAPPED_FIELD = 1;
public static final int CODE_DUPLICATE_KEY = 2;
public static final int CODE_SCHEMA_NOT_FOUND = 3;
public static final int CODE_TABLE_NOT_FOUND = 4;
public static final int CODE_TABLE_ALREADY_EXISTS = 5;
public static final int CODE_INDEX_ALREADY_EXISTS = 6;
public static final int CODE_OBJECT_NOT_FOUND = 3;
public static final int CODE_OBJECT_ALREADY_EXISTS = 4;
private static final String TOKEN_UNMAPPED_FIELD = "\\? (=|\\>|\\<|\\<\\>|!=|\\>=|\\<=|LIKE|BETWEEN) \\?";
@@ -97,34 +95,41 @@ public class IciqlException extends RuntimeException {
SQLException s = (SQLException) t;
String state = s.getSQLState();
if ("23000".equals(state)) {
// MySQL
// MySQL duplicate primary key on insert
iciqlCode = CODE_DUPLICATE_KEY;
} else if ("23505".equals(state)) {
// Derby duplicate primary key on insert
iciqlCode = CODE_DUPLICATE_KEY;
} else if ("42000".equals(state)) {
// MySQL
// MySQL duplicate unique index value on insert
iciqlCode = CODE_DUPLICATE_KEY;
} else if ("42Y07".equals(state)) {
// Derby
iciqlCode = CODE_SCHEMA_NOT_FOUND;
// Derby schema not found
iciqlCode = CODE_OBJECT_NOT_FOUND;
} else if ("42X05".equals(state)) {
// Derby
iciqlCode = CODE_TABLE_NOT_FOUND;
// Derby table not found
iciqlCode = CODE_OBJECT_NOT_FOUND;
} else if ("42S02".equals(state)) {
// H2
iciqlCode = CODE_TABLE_NOT_FOUND;
// H2 table not found
iciqlCode = CODE_OBJECT_NOT_FOUND;
} else if ("42501".equals(state)) {
// HSQL
iciqlCode = CODE_TABLE_NOT_FOUND;
// HSQL table not found
iciqlCode = CODE_OBJECT_NOT_FOUND;
} else if ("42P01".equals(state)) {
// PostgreSQL table not found
iciqlCode = CODE_OBJECT_NOT_FOUND;
} else if ("X0Y32".equals(state)) {
// Derby
iciqlCode = CODE_TABLE_ALREADY_EXISTS;
// Derby table already exists
iciqlCode = CODE_OBJECT_ALREADY_EXISTS;
} else if ("42P07".equals(state)) {
// PostgreSQL table or index already exists
iciqlCode = CODE_OBJECT_ALREADY_EXISTS;
} else if ("42S11".equals(state)) {
// H2
iciqlCode = CODE_INDEX_ALREADY_EXISTS;
// H2 index already exists
iciqlCode = CODE_OBJECT_ALREADY_EXISTS;
} else if ("42504".equals(state)) {
// HSQL
iciqlCode = CODE_INDEX_ALREADY_EXISTS;
// HSQL index already exists
iciqlCode = CODE_OBJECT_ALREADY_EXISTS;
}
}
}

+ 3
- 0
src/com/iciql/ModelUtils.java View File

@@ -113,6 +113,8 @@ class ModelUtils {
m.put("SIGNED", "INT");
m.put("INT8", "BIGINT");
m.put("IDENTITY", "BIGINT");
m.put("SERIAL", "INT");
m.put("BIGSERIAL", "BIGINT");

// decimal
m.put("NUMBER", "DECIMAL");
@@ -121,6 +123,7 @@ class ModelUtils {
m.put("FLOAT", "DOUBLE");
m.put("FLOAT4", "DOUBLE");
m.put("FLOAT8", "DOUBLE");
m.put("DOUBLE PRECISION", "DOUBLE");

// date
m.put("DATETIME", "TIMESTAMP");

+ 80
- 9
src/com/iciql/SQLDialectDefault.java View File

@@ -19,6 +19,7 @@ package com.iciql;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.text.MessageFormat;
import com.iciql.TableDefinition.FieldDefinition;
import com.iciql.TableDefinition.IndexDefinition;
@@ -26,8 +27,7 @@ import com.iciql.util.StatementBuilder;
import com.iciql.util.StringUtils;
/**
* Default implementation of an SQL dialect. Does not support merge nor index
* creation.
* Default implementation of an SQL dialect.
*/
public class SQLDialectDefault implements SQLDialect {
float databaseVersion;
@@ -144,11 +144,10 @@ public class SQLDialectDefault implements SQLDialect {
}
} else {
// other
buff.append(convertSqlType(dataType));
hasIdentityColumn |= prepareColumnDefinition(buff, convertSqlType(dataType),
field.isAutoIncrement, field.isPrimaryKey);
}
hasIdentityColumn |= prepareColumnDefinition(buff, field.isAutoIncrement, field.isPrimaryKey);
if (!field.nullable) {
buff.append(" NOT NULL");
}
@@ -181,8 +180,21 @@ public class SQLDialectDefault implements SQLDialect {
stat.setSQL(buff.toString());
}
protected boolean prepareColumnDefinition(StatementBuilder buff, boolean isAutoIncrement,
boolean isPrimaryKey) {
protected boolean isIntegerType(String dataType) {
if ("INT".equals(dataType)) {
return true;
} else if ("BIGINT".equals(dataType)) {
return true;
} else if ("TINYINT".equals(dataType)) {
return true;
} else if ("SMALLINT".equals(dataType)) {
return true;
}
return false;
}
protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType,
boolean isAutoIncrement, boolean isPrimaryKey) {
boolean isIdentity = false;
if (isAutoIncrement && isPrimaryKey) {
buff.append(" IDENTITY");
@@ -196,13 +208,72 @@ public class SQLDialectDefault implements SQLDialect {
@Override
public void prepareCreateIndex(SQLStatement stat, String schemaName, String tableName,
IndexDefinition index) {
throw new IciqlException("{0} does not support index creation!", getClass().getSimpleName());
StatementBuilder buff = new StatementBuilder();
buff.append("CREATE ");
switch (index.type) {
case UNIQUE:
buff.append("UNIQUE ");
break;
case UNIQUE_HASH:
buff.append("UNIQUE ");
break;
}
buff.append("INDEX ");
buff.append(index.indexName);
buff.append(" ON ");
buff.append(tableName);
buff.append("(");
for (String col : index.columnNames) {
buff.appendExceptFirst(", ");
buff.append(prepareColumnName(col));
}
buff.append(") ");
stat.setSQL(buff.toString().trim());
}
/**
* PostgreSQL and Derby do not support the SQL2003 MERGE syntax, but we can
* use a trick to insert a row if it does not exist and call update() in
* Db.merge() if the affected row count is 0.
* <p>
* Databases that do support a MERGE syntax should override this method.
* <p>
* http://stackoverflow.com/questions/407688
*/
@Override
public <T> void prepareMerge(SQLStatement stat, String schemaName, String tableName,
TableDefinition<T> def, Object obj) {
throw new IciqlException("{0} does not support merge statements!", getClass().getSimpleName());
StatementBuilder buff = new StatementBuilder("INSERT INTO ");
buff.append(prepareTableName(schemaName, tableName));
buff.append(" (");
buff.resetCount();
for (FieldDefinition field : def.fields) {
buff.appendExceptFirst(", ");
buff.append(prepareColumnName(field.columnName));
}
buff.append(") (SELECT ");
buff.resetCount();
for (FieldDefinition field : def.fields) {
buff.appendExceptFirst(", ");
buff.append('?');
Object value = def.getValue(obj, field);
stat.addParameter(value);
}
buff.append(" FROM ");
buff.append(prepareTableName(schemaName, tableName));
buff.append(" WHERE ");
buff.resetCount();
for (FieldDefinition field : def.fields) {
if (field.isPrimaryKey) {
buff.appendExceptFirst(" AND ");
buff.append(MessageFormat.format("{0} = ?", prepareColumnName(field.columnName)));
Object value = def.getValue(obj, field);
stat.addParameter(value);
}
}
buff.append(" HAVING count(*)=0)");
stat.setSQL(buff.toString());
}
@Override

+ 5
- 80
src/com/iciql/SQLDialectDerby.java View File

@@ -16,10 +16,6 @@
package com.iciql;
import java.text.MessageFormat;
import com.iciql.TableDefinition.FieldDefinition;
import com.iciql.TableDefinition.IndexDefinition;
import com.iciql.util.StatementBuilder;
/**
@@ -68,14 +64,11 @@ public class SQLDialectDerby extends SQLDialectDefault {
}
@Override
public String prepareColumnName(String name) {
return name;
}
@Override
protected boolean prepareColumnDefinition(StatementBuilder buff, boolean isAutoIncrement,
boolean isPrimaryKey) {
if (isAutoIncrement) {
protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType,
boolean isAutoIncrement, boolean isPrimaryKey) {
String convertedType = convertSqlType(dataType);
buff.append(convertedType);
if (isIntegerType(dataType) && isAutoIncrement) {
buff.append(" GENERATED BY DEFAULT AS IDENTITY");
}
return false;
@@ -88,72 +81,4 @@ public class SQLDialectDerby extends SQLDialectDefault {
stat.setSQL(buff.toString());
return;
}
@Override
public void prepareCreateIndex(SQLStatement stat, String schema, String table, IndexDefinition index) {
StatementBuilder buff = new StatementBuilder();
buff.append("CREATE ");
switch (index.type) {
case UNIQUE:
buff.append("UNIQUE ");
break;
case UNIQUE_HASH:
buff.append("UNIQUE ");
break;
}
buff.append("INDEX ");
buff.append(index.indexName);
buff.append(" ON ");
buff.append(table);
buff.append("(");
for (String col : index.columnNames) {
buff.appendExceptFirst(", ");
buff.append(prepareColumnName(col));
}
buff.append(") ");
stat.setSQL(buff.toString().trim());
}
/**
* Derby does not support the SQL2003 MERGE syntax, but we can use a trick
* to insert a row if it does not exist and call update() in Db.merge() if
* the affected row count is 0;
*
* http://stackoverflow.com/questions/407688
*/
@Override
public <T> void prepareMerge(SQLStatement stat, String schemaName, String tableName,
TableDefinition<T> def, Object obj) {
StatementBuilder buff = new StatementBuilder("INSERT INTO ");
buff.append(prepareTableName(schemaName, tableName));
buff.append(" (");
buff.resetCount();
for (FieldDefinition field : def.fields) {
buff.appendExceptFirst(", ");
buff.append(prepareColumnName(field.columnName));
}
buff.append(") (SELECT ");
buff.resetCount();
for (FieldDefinition field : def.fields) {
buff.appendExceptFirst(", ");
buff.append('?');
Object value = def.getValue(obj, field);
stat.addParameter(value);
}
buff.append(" FROM ");
buff.append(prepareTableName(schemaName, tableName));
buff.append(" WHERE ");
buff.resetCount();
for (FieldDefinition field : def.fields) {
if (field.isPrimaryKey) {
buff.appendExceptFirst(" AND ");
buff.append(MessageFormat.format("{0} = ?", prepareColumnName(field.columnName)));
Object value = def.getValue(obj, field);
stat.addParameter(value);
}
}
buff.append(" HAVING count(*)=0)");
stat.setSQL(buff.toString());
}
}

+ 21
- 0
src/com/iciql/SQLDialectH2.java View File

@@ -30,6 +30,27 @@ public class SQLDialectH2 extends SQLDialectDefault {
return true;
}
@Override
protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType, boolean isAutoIncrement,
boolean isPrimaryKey) {
String convertedType = convertSqlType(dataType);
boolean isIdentity = false;
if (isIntegerType(dataType)) {
if (isAutoIncrement && isPrimaryKey) {
buff.append("IDENTITY");
isIdentity = true;
} else if (isAutoIncrement) {
buff.append(convertedType);
buff.append(" AUTO_INCREMENT");
} else {
buff.append(convertedType);
}
} else {
buff.append(convertedType);
}
return isIdentity;
}
@Override
public void prepareCreateIndex(SQLStatement stat, String schema, String table, IndexDefinition index) {
StatementBuilder buff = new StatementBuilder();

+ 4
- 28
src/com/iciql/SQLDialectHSQL.java View File

@@ -19,7 +19,6 @@ package com.iciql;
import java.text.MessageFormat;
import com.iciql.TableDefinition.FieldDefinition;
import com.iciql.TableDefinition.IndexDefinition;
import com.iciql.util.StatementBuilder;
/**
@@ -33,41 +32,18 @@ public class SQLDialectHSQL extends SQLDialectDefault {
}
@Override
protected boolean prepareColumnDefinition(StatementBuilder buff, boolean isAutoIncrement,
protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType, boolean isAutoIncrement,
boolean isPrimaryKey) {
boolean isIdentity = false;
if (isAutoIncrement && isPrimaryKey) {
String convertedType = convertSqlType(dataType);
buff.append(convertedType);
if (isIntegerType(dataType) && isAutoIncrement && isPrimaryKey) {
buff.append(" IDENTITY");
isIdentity = true;
}
return isIdentity;
}
@Override
public void prepareCreateIndex(SQLStatement stat, String schema, String table, IndexDefinition index) {
StatementBuilder buff = new StatementBuilder();
buff.append("CREATE ");
switch (index.type) {
case UNIQUE:
buff.append("UNIQUE ");
break;
case UNIQUE_HASH:
buff.append("UNIQUE ");
break;
}
buff.append("INDEX ");
buff.append(index.indexName);
buff.append(" ON ");
buff.append(table);
buff.append("(");
for (String col : index.columnNames) {
buff.appendExceptFirst(", ");
buff.append(col);
}
buff.append(")");
stat.setSQL(buff.toString());
}
@Override
public <T> void prepareMerge(SQLStatement stat, String schemaName, String tableName,
TableDefinition<T> def, Object obj) {

+ 4
- 35
src/com/iciql/SQLDialectMySQL.java View File

@@ -17,7 +17,6 @@
package com.iciql;
import com.iciql.TableDefinition.FieldDefinition;
import com.iciql.TableDefinition.IndexDefinition;
import com.iciql.util.StatementBuilder;
/**
@@ -33,52 +32,22 @@ public class SQLDialectMySQL extends SQLDialectDefault {
return sqlType;
}
@Override
public boolean supportsMemoryTables() {
return false;
}
@Override
public String prepareColumnName(String name) {
return "`" + name + "`";
}
@Override
protected boolean prepareColumnDefinition(StatementBuilder buff, boolean isAutoIncrement,
protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType, boolean isAutoIncrement,
boolean isPrimaryKey) {
if (isAutoIncrement) {
String convertedType = convertSqlType(dataType);
buff.append(convertedType);
if (isIntegerType(dataType) && isAutoIncrement) {
buff.append(" AUTO_INCREMENT");
}
return false;
}
@Override
public void prepareCreateIndex(SQLStatement stat, String schema, String table, IndexDefinition index) {
StatementBuilder buff = new StatementBuilder();
buff.append("CREATE ");
switch (index.type) {
case STANDARD:
break;
case UNIQUE:
buff.append("UNIQUE ");
break;
case UNIQUE_HASH:
buff.append("UNIQUE ");
break;
}
buff.append("INDEX ");
buff.append(index.indexName);
buff.append(" ON ");
buff.append(table);
buff.append("(");
for (String col : index.columnNames) {
buff.appendExceptFirst(", ");
buff.append(prepareColumnName(col));
}
buff.append(") ");
stat.setSQL(buff.toString().trim());
}
@Override
public <T> void prepareMerge(SQLStatement stat, String schemaName, String tableName,
TableDefinition<T> def, Object obj) {

+ 110
- 0
src/com/iciql/SQLDialectPostgreSQL.java View File

@@ -0,0 +1,110 @@
/*
* Copyright 2011 James Moger.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.iciql;
import com.iciql.TableDefinition.IndexDefinition;
import com.iciql.util.StatementBuilder;
/**
* PostgreSQL database dialect.
*/
public class SQLDialectPostgreSQL extends SQLDialectDefault {
@Override
public Class<? extends java.util.Date> getDateTimeClass() {
return java.sql.Timestamp.class;
}
@Override
public boolean supportsIfNotExists() {
return false;
}
@Override
public String convertSqlType(String sqlType) {
if ("DOUBLE".equals(sqlType)) {
return "DOUBLE PRECISION";
} else if ("TINYINT".equals(sqlType)) {
// PostgreSQL does not have a byte type
return "SMALLINT";
} else if ("CLOB".equals(sqlType)) {
return "TEXT";
} else if ("BLOB".equals(sqlType)) {
return "BYTEA";
}
return sqlType;
}
@Override
protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType,
boolean isAutoIncrement, boolean isPrimaryKey) {
boolean isIdentity = false;
String convertedType = convertSqlType(dataType);
if (isIntegerType(dataType)) {
if (isAutoIncrement && isPrimaryKey) {
if ("BIGINT".equals(dataType)) {
buff.append("BIGSERIAL");
} else {
buff.append("SERIAL");
}
isIdentity = true;
} else {
buff.append(convertedType);
}
} else {
buff.append(convertedType);
}
return isIdentity;
}
@Override
public void prepareCreateIndex(SQLStatement stat, String schemaName, String tableName,
IndexDefinition index) {
StatementBuilder buff = new StatementBuilder();
buff.append("CREATE ");
switch (index.type) {
case UNIQUE:
buff.append("UNIQUE ");
break;
case UNIQUE_HASH:
buff.append("UNIQUE ");
break;
}
buff.append("INDEX ");
buff.append(index.indexName);
buff.append(" ON ");
buff.append(tableName);
switch (index.type) {
case HASH:
buff.append(" USING HASH");
break;
case UNIQUE_HASH:
buff.append(" USING HASH");
break;
}
buff.append(" (");
for (String col : index.columnNames) {
buff.appendExceptFirst(", ");
buff.append(prepareColumnName(col));
}
buff.append(") ");
stat.setSQL(buff.toString().trim());
}
}

+ 2
- 2
src/com/iciql/TableDefinition.java View File

@@ -552,7 +552,7 @@ public class TableDefinition<T> {
try {
stat.executeUpdate();
} catch (IciqlException e) {
if (e.getIciqlCode() != IciqlException.CODE_TABLE_ALREADY_EXISTS) {
if (e.getIciqlCode() != IciqlException.CODE_OBJECT_ALREADY_EXISTS) {
throw e;
}
}
@@ -565,7 +565,7 @@ public class TableDefinition<T> {
try {
stat.executeUpdate();
} catch (IciqlException e) {
if (e.getIciqlCode() != IciqlException.CODE_INDEX_ALREADY_EXISTS
if (e.getIciqlCode() != IciqlException.CODE_OBJECT_ALREADY_EXISTS
&& e.getIciqlCode() != IciqlException.CODE_DUPLICATE_KEY) {
throw e;
}

+ 5
- 9
src/com/iciql/TableInspector.java View File

@@ -56,18 +56,15 @@ public class TableInspector {

private String schema;
private String table;
private boolean forceUpperCase;
private Class<? extends java.util.Date> dateTimeClass;
private List<String> primaryKeys = Utils.newArrayList();
private Map<String, IndexInspector> indexes;
private Map<String, ColumnInspector> columns;
private final String eol = "\n";

TableInspector(String schema, String table, boolean forceUpperCase,
Class<? extends java.util.Date> dateTimeClass) {
TableInspector(String schema, String table, Class<? extends java.util.Date> dateTimeClass) {
this.schema = schema;
this.table = table;
this.forceUpperCase = forceUpperCase;
this.dateTimeClass = dateTimeClass;
}

@@ -121,7 +118,7 @@ public class TableInspector {
if (info.type.equals(IndexType.UNIQUE)) {
String name = info.name.toLowerCase();
if (name.startsWith("primary") || name.startsWith("sys_idx_sys_pk")
|| name.startsWith("sql")) {
|| name.startsWith("sql") || name.endsWith("_pkey")) {
// skip primary key indexes
continue;
}
@@ -166,7 +163,7 @@ public class TableInspector {
if (!col.isAutoIncrement) {
col.defaultValue = rs.getString("COLUMN_DEF");
}
columns.put(col.name, col);
columns.put(col.name.toLowerCase(), col);
}
} finally {
closeSilently(rs);
@@ -478,13 +475,12 @@ public class TableInspector {
*/
private void validate(List<ValidationRemark> remarks, FieldDefinition fieldDef, boolean throwError) {
// unknown field
String field = forceUpperCase ? fieldDef.columnName.toUpperCase() : fieldDef.columnName;
if (!columns.containsKey(field)) {
if (!columns.containsKey(fieldDef.columnName.toLowerCase())) {
// unknown column mapping
remarks.add(error(table, fieldDef, "Does not exist in database!").throwError(throwError));
return;
}
ColumnInspector col = columns.get(field);
ColumnInspector col = columns.get(fieldDef.columnName.toLowerCase());
Class<?> fieldClass = fieldDef.field.getType();
Class<?> jdbcClass = ModelUtils.getClassForSqlType(col.type, dateTimeClass);


+ 4
- 0
src/com/iciql/build/Build.java View File

@@ -59,6 +59,7 @@ public class Build {
downloadFromApache(MavenObject.HSQLDB, BuildType.RUNTIME);
downloadFromApache(MavenObject.DERBY, BuildType.RUNTIME);
downloadFromApache(MavenObject.MYSQL, BuildType.RUNTIME);
downloadFromApache(MavenObject.POSTGRESQL, BuildType.RUNTIME);
downloadFromApache(MavenObject.JCOMMANDER, BuildType.RUNTIME);
downloadFromApache(MavenObject.JCOMMANDER, BuildType.COMPILETIME);
downloadFromApache(MavenObject.MARKDOWNPAPERS, BuildType.RUNTIME);
@@ -184,6 +185,9 @@ public class Build {
public static final MavenObject MYSQL = new MavenObject("mysql", "mysql-connector-java", "5.1.15",
"0fbc80454d27cc65f3addfa516707e9f8e60c3eb", "", "");
public static final MavenObject POSTGRESQL = new MavenObject("postgresql", "postgresql", "9.0-801.jdbc4",
"153f2f92a786f12fc111d0111f709012df87c808", "", "");
public static final MavenObject JUNIT = new MavenObject("junit", "junit", "4.8.2",
"c94f54227b08100974c36170dcb53329435fe5ad", "", "");

+ 1
- 1
src/com/iciql/util/Utils.java View File

@@ -248,7 +248,7 @@ public class Utils {
f = Float.parseFloat(s);
} catch (Exception e) {
}
return f > 0 || s.equals("true") || s.equals("yes");
return f > 0 || s.equals("true") || s.equals("yes") || s.equals("y") || s.equals("on");
}
}

+ 23
- 20
tests/com/iciql/test/AnnotationsTest.java View File

@@ -17,9 +17,7 @@

package com.iciql.test;

import static com.iciql.test.IciqlSuite.assertStartsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.sql.DatabaseMetaData;
@@ -38,6 +36,7 @@ import com.iciql.test.models.ProductAnnotationOnly;
import com.iciql.test.models.ProductInheritedAnnotation;
import com.iciql.test.models.ProductMixedAnnotation;
import com.iciql.test.models.ProductNoCreateTable;
import com.iciql.util.Utils;

/**
* Test annotation processing.
@@ -68,26 +67,30 @@ public class AnnotationsTest {
public void testIndexCreation() throws SQLException {
// test indexes are created, and columns are in the right order
DatabaseMetaData meta = db.getConnection().getMetaData();
boolean isH2 = meta.getDatabaseProductName().equals("H2");
String schema = IciqlSuite.getDefaultSchema(db);
ResultSet rs = meta.getIndexInfo(null, schema, "ANNOTATEDPRODUCT", false, true);
boolean toUpper = meta.storesUpperCaseIdentifiers();
boolean toLower = meta.storesLowerCaseIdentifiers();
ResultSet rs = meta.getIndexInfo(null, prepName(schema, toUpper, toLower),
prepName("ANNOTATEDPRODUCT", toUpper, toLower), false, true);

List<String> list = Utils.newArrayList();
while (rs.next()) {
String col = rs.getString("COLUMN_NAME");
String index = rs.getString("INDEX_NAME");
list.add((col + ":" + index).toLowerCase());
}
assertTrue(list.contains("name:annotatedproduct_0"));
assertTrue(list.contains("cat:annotatedproduct_0"));
assertTrue(list.contains("name:nameidx"));
}

// first index is primary key index
// H2 gives this a testable name.
assertTrue(rs.next());
if (isH2) {
assertStartsWith(rs.getString("INDEX_NAME").toUpperCase(), "PRIMARY_KEY");
private String prepName(String name, boolean upper, boolean lower) {
if (upper) {
return name.toUpperCase();
} else if (lower) {
return name.toLowerCase();
}
assertTrue(rs.next());
assertStartsWith(rs.getString("INDEX_NAME").toUpperCase(), "ANNOTATEDPRODUCT_0");
assertStartsWith(rs.getString("COLUMN_NAME").toUpperCase(), "NAME");
assertTrue(rs.next());
assertStartsWith(rs.getString("INDEX_NAME").toUpperCase(), "ANNOTATEDPRODUCT_0");
assertStartsWith(rs.getString("COLUMN_NAME").toUpperCase(), "CAT");
assertTrue(rs.next());
assertStartsWith(rs.getString("INDEX_NAME").toUpperCase(), "NAMEIDX");
assertStartsWith(rs.getString("COLUMN_NAME").toUpperCase(), "NAME");
assertFalse(rs.next());
return name;
}

@Test
@@ -180,7 +183,7 @@ public class AnnotationsTest {
try {
db.insertAll(ProductNoCreateTable.getList());
} catch (IciqlException e) {
assertEquals(IciqlException.CODE_TABLE_NOT_FOUND, e.getIciqlCode());
assertEquals(IciqlException.CODE_OBJECT_NOT_FOUND, e.getIciqlCode());
}
}


+ 8
- 2
tests/com/iciql/test/IciqlSuite.java View File

@@ -78,9 +78,10 @@ public class IciqlSuite {
private static final TestDb[] TEST_DBS = { new TestDb("H2 (embedded)", "jdbc:h2:mem:db{0,number,000}"),
new TestDb("HSQL (embedded)", "jdbc:hsqldb:mem:db{0,number,000}"),
new TestDb("Derby (embedded)", "jdbc:derby:memory:db{0,number,000};create=true"),
new TestDb("MySQL (tcp/myisam)", "jdbc:mysql://localhost:3306/iciql") };
new TestDb("MySQL (tcp/myisam)", "jdbc:mysql://localhost:3306/iciql"),
new TestDb("PostgreSQL (tcp)", "jdbc:postgresql://localhost:5432/iciql")};
private static final TestDb DEFAULT_TEST_DB = TEST_DBS[0];
private static final TestDb DEFAULT_TEST_DB = TEST_DBS[4];
private static final PrintStream ERR = System.err;
@@ -96,6 +97,11 @@ public class IciqlSuite {
Assert.assertTrue(MessageFormat.format("Expected \"{0}\", got: \"{1}\"", startsWith, value),
value.startsWith(startsWith));
}
public static void assertEqualsIgnoreCase(String expected, String actual) {
Assert.assertTrue(MessageFormat.format("Expected \"{0}\", got: \"{1}\"", expected, actual),
expected.equalsIgnoreCase(actual));
}
public static boolean equivalentTo(double expected, double actual) {
if (Double.compare(expected, actual) == 0) {

+ 13
- 2
tests/com/iciql/test/ModelsTest.java View File

@@ -19,6 +19,7 @@ package com.iciql.test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static com.iciql.test.IciqlSuite.assertEqualsIgnoreCase;

import java.sql.SQLException;
import java.text.MessageFormat;
@@ -93,7 +94,8 @@ public class ModelsTest {
assertEquals(sb.toString(), expected - 1, remarks.size());
} else {
assertEquals(sb.toString(), expected, remarks.size());
assertEquals(MessageFormat.format("@IQSchema(\"{0}\")", schemaName), remarks.get(0).message);
assertEqualsIgnoreCase(MessageFormat.format("@IQSchema(\"{0}\")", schemaName),
remarks.get(0).message);
}
}

@@ -121,7 +123,7 @@ public class ModelsTest {
// a poor test, but a start
String dbName = IciqlSuite.getDatabaseEngineName(db);
if (dbName.equals("H2")) {
assertEquals(1478, models.get(0).length());
assertEquals(1475, models.get(0).length());
} else if (dbName.startsWith("HSQL")) {
// HSQL uses Double instead of Float
assertEquals(1479, models.get(0).length());
@@ -129,6 +131,15 @@ public class ModelsTest {
// Derby uses java.sql.Timestamp not java.util.Date
// Derby uses username as schema name
assertEquals(1489, models.get(0).length());
} else if (dbName.equals("PostgreSQL")) {
assertEquals(1514, models.get(0).length());
} else if (dbName.equals("MySQL")) {
// MySQL uses timestamp default values like
// 0000-00-00 00:00:00 and CURRENT_TIMESTAMP
assertEquals(1561, models.get(0).length());
} else {
// unknown database
assertEquals(0, models.get(0).length());
}
}
}

+ 2
- 2
tests/com/iciql/test/models/ProductAnnotationOnly.java View File

@@ -37,7 +37,7 @@ public class ProductAnnotationOnly {
public String unmappedField;

@IQColumn(name = "id", autoIncrement = true)
public Integer productId;
public Long productId;

@IQColumn(name = "cat", length = 15, trim = true)
public String category;
@@ -56,7 +56,7 @@ public class ProductAnnotationOnly {
// public constructor
}

private ProductAnnotationOnly(int productId, String productName, String category, double unitPrice,
private ProductAnnotationOnly(long productId, String productName, String category, double unitPrice,
int unitsInStock, String unmappedField) {
this.productId = productId;
this.productName = productName;

Loading…
Cancel
Save