From 538ba78ac1dc2e9670380329ad989c9df0ab546b Mon Sep 17 00:00:00 2001 From: James Moger Date: Wed, 3 Aug 2011 22:01:42 -0400 Subject: Initial commit of iciql. --- tests/com/iciql/test/AliasMapTest.java | 50 +++ tests/com/iciql/test/AnnotationsTest.java | 177 +++++++++ tests/com/iciql/test/ClobTest.java | 112 ++++++ tests/com/iciql/test/ConcurrencyTest.java | 178 +++++++++ tests/com/iciql/test/IciqlSuite.java | 36 ++ tests/com/iciql/test/ModelsTest.java | 181 +++++++++ tests/com/iciql/test/RuntimeQueryTest.java | 92 +++++ tests/com/iciql/test/SamplesTest.java | 406 +++++++++++++++++++++ tests/com/iciql/test/StatementLoggerTest.java | 39 ++ tests/com/iciql/test/UpdateTest.java | 160 ++++++++ tests/com/iciql/test/models/ComplexObject.java | 64 ++++ tests/com/iciql/test/models/Customer.java | 49 +++ tests/com/iciql/test/models/Order.java | 65 ++++ tests/com/iciql/test/models/Product.java | 82 +++++ .../iciql/test/models/ProductAnnotationOnly.java | 94 +++++ .../test/models/ProductInheritedAnnotation.java | 63 ++++ .../iciql/test/models/ProductMixedAnnotation.java | 94 +++++ .../iciql/test/models/ProductNoCreateTable.java | 59 +++ tests/com/iciql/test/models/SupportedTypes.java | 133 +++++++ 19 files changed, 2134 insertions(+) create mode 100644 tests/com/iciql/test/AliasMapTest.java create mode 100644 tests/com/iciql/test/AnnotationsTest.java create mode 100644 tests/com/iciql/test/ClobTest.java create mode 100644 tests/com/iciql/test/ConcurrencyTest.java create mode 100644 tests/com/iciql/test/IciqlSuite.java create mode 100644 tests/com/iciql/test/ModelsTest.java create mode 100644 tests/com/iciql/test/RuntimeQueryTest.java create mode 100644 tests/com/iciql/test/SamplesTest.java create mode 100644 tests/com/iciql/test/StatementLoggerTest.java create mode 100644 tests/com/iciql/test/UpdateTest.java create mode 100644 tests/com/iciql/test/models/ComplexObject.java create mode 100644 tests/com/iciql/test/models/Customer.java create mode 100644 tests/com/iciql/test/models/Order.java create mode 100644 tests/com/iciql/test/models/Product.java create mode 100644 tests/com/iciql/test/models/ProductAnnotationOnly.java create mode 100644 tests/com/iciql/test/models/ProductInheritedAnnotation.java create mode 100644 tests/com/iciql/test/models/ProductMixedAnnotation.java create mode 100644 tests/com/iciql/test/models/ProductNoCreateTable.java create mode 100644 tests/com/iciql/test/models/SupportedTypes.java (limited to 'tests/com') diff --git a/tests/com/iciql/test/AliasMapTest.java b/tests/com/iciql/test/AliasMapTest.java new file mode 100644 index 0000000..4d19bd0 --- /dev/null +++ b/tests/com/iciql/test/AliasMapTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2004-2011 H2 Group. + * 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.test; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.junit.Test; + +import com.iciql.Db; +import com.iciql.test.models.Product; + +/** + * Tests that columns (p.unitsInStock) are not compared by value with the value + * (9), but by reference (using an identity hash map). See + * http://code.google.com/p/h2database/issues/detail?id=119 + * + * @author d moebius at scoop dash gmbh dot de + */ +public class AliasMapTest { + + @Test + public void testAliasMapping() throws Exception { + Db db = Db.open("jdbc:h2:mem:", "sa", "sa"); + db.insertAll(Product.getList()); + + Product p = new Product(); + List products = db.from(p).where(p.unitsInStock).is(9).orderBy(p.productId).select(); + + assertEquals("[]", products.toString()); + + db.close(); + } +} \ No newline at end of file diff --git a/tests/com/iciql/test/AnnotationsTest.java b/tests/com/iciql/test/AnnotationsTest.java new file mode 100644 index 0000000..367e6e1 --- /dev/null +++ b/tests/com/iciql/test/AnnotationsTest.java @@ -0,0 +1,177 @@ +/* + * Copyright 2004-2011 H2 Group. + * 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.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; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +import org.h2.constant.ErrorCode; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.iciql.Db; +import com.iciql.IciqlException; +import com.iciql.test.models.Product; +import com.iciql.test.models.ProductAnnotationOnly; +import com.iciql.test.models.ProductInheritedAnnotation; +import com.iciql.test.models.ProductMixedAnnotation; +import com.iciql.test.models.ProductNoCreateTable; + +/** + * Test annotation processing. + */ +public class AnnotationsTest { + + /** + * This object represents a database (actually a connection to the + * database). + */ + + private Db db; + + @Before + public void setUp() { + db = Db.open("jdbc:h2:mem:", "sa", "sa"); + db.insertAll(Product.getList()); + db.insertAll(ProductAnnotationOnly.getList()); + db.insertAll(ProductMixedAnnotation.getList()); + } + + @After + public void tearDown() { + db.close(); + } + + @Test + public void testIndexCreation() throws SQLException { + // test indexes are created, and columns are in the right order + DatabaseMetaData meta = db.getConnection().getMetaData(); + ResultSet rs = meta.getIndexInfo(null, "PUBLIC", "ANNOTATED" + "PRODUCT", false, true); + assertTrue(rs.next()); + assertStartsWith(rs.getString("INDEX_NAME"), "PRIMARY_KEY"); + assertTrue(rs.next()); + assertStartsWith(rs.getString("INDEX_NAME"), "ANNOTATED" + "PRODUCT_"); + assertStartsWith(rs.getString("COLUMN_NAME"), "NAME"); + assertTrue(rs.next()); + assertStartsWith(rs.getString("INDEX_NAME"), "ANNOTATED" + "PRODUCT_"); + assertStartsWith(rs.getString("COLUMN_NAME"), "CAT"); + assertFalse(rs.next()); + } + + @Test + public void testProductAnnotationOnly() { + ProductAnnotationOnly p = new ProductAnnotationOnly(); + assertEquals(10, db.from(p).selectCount()); + + // test IQColumn.name="cat" + assertEquals(2, db.from(p).where(p.category).is("Beverages").selectCount()); + + // test IQTable.annotationsOnly=true + // public String unmappedField is ignored by iciql + assertEquals(0, db.from(p).where(p.unmappedField).is("unmapped").selectCount()); + + // test IQColumn.autoIncrement=true + // 10 objects, 10 autoIncremented unique values + assertEquals(10, db.from(p).selectDistinct(p.autoIncrement).size()); + + // test IQTable.primaryKey=id + try { + db.insertAll(ProductAnnotationOnly.getList()); + } catch (IciqlException r) { + SQLException s = (SQLException) r.getCause(); + assertEquals(ErrorCode.DUPLICATE_KEY_1, s.getErrorCode()); + } + } + + @Test + public void testProductMixedAnnotation() { + ProductMixedAnnotation p = new ProductMixedAnnotation(); + + // test IQColumn.name="cat" + assertEquals(2, db.from(p).where(p.category).is("Beverages").selectCount()); + + // test IQTable.annotationsOnly=false + // public String mappedField is reflectively mapped by iciql + assertEquals(10, db.from(p).where(p.mappedField).is("mapped").selectCount()); + + // test IQColumn.primaryKey=true + try { + db.insertAll(ProductMixedAnnotation.getList()); + } catch (IciqlException r) { + SQLException s = (SQLException) r.getCause(); + assertEquals(ErrorCode.DUPLICATE_KEY_1, s.getErrorCode()); + } + } + + @Test + public void testTrimStringAnnotation() { + ProductAnnotationOnly p = new ProductAnnotationOnly(); + ProductAnnotationOnly prod = db.from(p).selectFirst(); + String oldValue = prod.category; + String newValue = "01234567890123456789"; + // 2 chars exceeds field max + prod.category = newValue; + db.update(prod); + + ProductAnnotationOnly newProd = db.from(p).where(p.productId).is(prod.productId).selectFirst(); + assertEquals(newValue.substring(0, 15), newProd.category); + + newProd.category = oldValue; + db.update(newProd); + } + + @Test + public void testColumnInheritanceAnnotation() { + ProductInheritedAnnotation table = new ProductInheritedAnnotation(); + List inserted = ProductInheritedAnnotation.getData(); + db.insertAll(inserted); + + List retrieved = db.from(table).select(); + + for (int j = 0; j < retrieved.size(); j++) { + ProductInheritedAnnotation i = inserted.get(j); + ProductInheritedAnnotation r = retrieved.get(j); + assertEquals(i.category, r.category); + assertEquals(i.mappedField, r.mappedField); + assertEquals(i.unitsInStock, r.unitsInStock); + assertEquals(i.unitPrice, r.unitPrice); + assertEquals(i.name(), r.name()); + assertEquals(i.id(), r.id()); + } + } + + @Test + public void testCreateTableIfRequiredAnnotation() { + // tests IQTable.createTableIfRequired=false + try { + db.insertAll(ProductNoCreateTable.getList()); + } catch (IciqlException r) { + SQLException s = (SQLException) r.getCause(); + assertEquals(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, s.getErrorCode()); + } + } + +} diff --git a/tests/com/iciql/test/ClobTest.java b/tests/com/iciql/test/ClobTest.java new file mode 100644 index 0000000..1f2eff4 --- /dev/null +++ b/tests/com/iciql/test/ClobTest.java @@ -0,0 +1,112 @@ +/* + * Copyright 2004-2011 H2 Group. + * 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.test; + +import static org.junit.Assert.assertEquals; +import static com.iciql.Define.primaryKey; +import static com.iciql.Define.tableName; + +import java.text.MessageFormat; +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; + +import com.iciql.Db; +import com.iciql.Iciql; + +/** + * Tests if converting a CLOB to a String works. + */ +public class ClobTest { + + @Test + public void testClob() throws Exception { + String create = "CREATE TABLE CLOB_TEST(ID INT PRIMARY KEY, WORDS {0})"; + Db db = Db.open("jdbc:h2:mem:", "sa", "sa"); + db.executeUpdate(MessageFormat.format(create, "VARCHAR(255)")); + db.insertAll(StringRecord.getList()); + testSimpleUpdate(db, "VARCHAR fail"); + db.close(); + + db = Db.open("jdbc:h2:mem:", "sa", "sa"); + db.executeUpdate(MessageFormat.format(create, "TEXT")); + db.insertAll(StringRecord.getList()); + testSimpleUpdate(db, "CLOB fail because of single quote artifacts"); + db.close(); + } + + private void testSimpleUpdate(Db db, String failureMsg) { + String newWords = "I changed the words"; + StringRecord r = new StringRecord(); + StringRecord originalRecord = db.from(r).where(r.id).is(2).selectFirst(); + String oldWords = originalRecord.words; + originalRecord.words = newWords; + db.update(originalRecord); + + StringRecord r2 = new StringRecord(); + StringRecord revisedRecord = db.from(r2).where(r2.id).is(2).selectFirst(); + assertEquals(failureMsg, newWords, revisedRecord.words); + + // undo update + originalRecord.words = oldWords; + db.update(originalRecord); + } + + /** + * A simple class used in this test. + */ + public static class StringRecord implements Iciql { + + public Integer id; + public String words; + + public StringRecord() { + // public constructor + } + + private StringRecord(int id, String words) { + this.id = id; + this.words = words; + } + + public void defineIQ() { + tableName("CLOB_TEST"); + primaryKey(id); + } + + private static StringRecord create(int id, String words) { + return new StringRecord(id, words); + } + + public static List getList() { + StringRecord[] list = { create(1, "Once upon a midnight dreary, while I pondered weak and weary,"), + create(2, "Over many a quaint and curious volume of forgotten lore,"), + create(3, "While I nodded, nearly napping, suddenly there came a tapping,"), + create(4, "As of some one gently rapping, rapping at my chamber door."), + create(5, "`'Tis some visitor,' I muttered, `tapping at my chamber door -"), + create(6, "Only this, and nothing more.'") }; + + return Arrays.asList(list); + } + + public String toString() { + return id + ": " + words; + } + } +} diff --git a/tests/com/iciql/test/ConcurrencyTest.java b/tests/com/iciql/test/ConcurrencyTest.java new file mode 100644 index 0000000..88b23f6 --- /dev/null +++ b/tests/com/iciql/test/ConcurrencyTest.java @@ -0,0 +1,178 @@ +/* + * 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.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.iciql.Db; +import com.iciql.Query; +import com.iciql.test.models.Product; +import com.iciql.util.Utils; + +/** + * Tests concurrency and alias instance sharing. + */ +public class ConcurrencyTest { + + private Db db; + private int numberOfTests = 200; + + @Before + public void setUp() { + db = Db.open("jdbc:h2:mem:", "sa", "sa"); + db.insertAll(Product.getList()); + } + + @After + public void tearDown() { + db.close(); + } + + @Test + public void testAliasSharing() throws Exception { + // Single-threaded example of why aliases can NOT be shared. + Product p = new Product(); + Query query1 = db.from(p); + Query query2 = db.from(p); + + // if you could share alias instances both counts should be equal + long count1 = query1.where(p.category).is("Beverages").selectCount(); + long count2 = query2.where(p.category).is("Beverages").selectCount(); + + // but they aren't + assertEquals(0, count1); + assertEquals(2, count2); + assertTrue(count1 != count2); + } + + @Test + public void testConcurrencyFinal() throws Exception { + // Multi-threaded example of why aliases can NOT be shared. + // + // This test looks like it _could_ work and you may find that it _can_ + // work, but you should also find that it _will_ fail. + + List threads = Utils.newArrayList(); + final AtomicInteger failures = new AtomicInteger(0); + final Product p = new Product(); + for (int i = 0; i < numberOfTests; i++) { + final int testNumber = i; + Thread t = new Thread(new Runnable() { + public void run() { + try { + int testCase = testNumber % 10; + test(testCase, p); + } catch (Throwable rex) { + failures.incrementAndGet(); + System.err.println("EXPECTED ERROR"); + rex.printStackTrace(); + } + } + }, "ICIQL-" + i); + t.start(); + threads.add(t); + } + + // wait till all threads complete + for (Thread t : threads) { + t.join(); + } + + assertTrue("This should fail. Try running a few more times.", failures.get() > 0); + } + + @Test + public void testConcurrencyThreadLocal() throws Exception { + List threads = Utils.newArrayList(); + final AtomicInteger failures = new AtomicInteger(0); + final ThreadLocal tl = Utils.newThreadLocal(Product.class); + for (int i = 0; i < numberOfTests; i++) { + final int testNumber = i; + Thread t = new Thread(new Runnable() { + public void run() { + try { + int testCase = testNumber % 10; + test(testCase, tl.get()); + } catch (Throwable rex) { + failures.incrementAndGet(); + rex.printStackTrace(); + } + } + }, "ICIQL-" + i); + t.start(); + threads.add(t); + } + + // wait till all threads complete + for (Thread t : threads) { + t.join(); + } + + assertEquals("ThreadLocal should never fail!", 0, failures.get()); + } + + private void test(int testCase, Product p) throws AssertionError { + List list; + switch (testCase) { + case 0: + list = db.from(p).where(p.productName).is("Chai").select(); + assertEquals(1, list.size()); + assertEquals("Chai", list.get(0).productName); + break; + case 1: + list = db.from(p).where(p.category).is("Condiments").select(); + assertEquals(5, list.size()); + break; + case 3: + list = db.from(p).where(p.productName).is("Aniseed Syrup").select(); + assertEquals(1, list.size()); + assertEquals("Aniseed Syrup", list.get(0).productName); + break; + case 4: + list = db.from(p).where(p.productName).like("Chef%").select(); + assertEquals(2, list.size()); + assertTrue(list.get(0).productName.startsWith("Chef")); + assertTrue(list.get(1).productName.startsWith("Chef")); + break; + case 6: + list = db.from(p).where(p.unitsInStock).exceeds(0).select(); + assertEquals(9, list.size()); + break; + case 7: + list = db.from(p).where(p.unitsInStock).is(0).select(); + assertEquals(1, list.size()); + assertEquals("Chef Anton's Gumbo Mix", list.get(0).productName); + break; + case 9: + list = db.from(p).where(p.productId).is(7).select(); + assertEquals(1, list.size()); + assertTrue(7 == list.get(0).productId); + break; + default: + list = db.from(p).select(); + assertEquals(10, list.size()); + } + } +} diff --git a/tests/com/iciql/test/IciqlSuite.java b/tests/com/iciql/test/IciqlSuite.java new file mode 100644 index 0000000..b235f6d --- /dev/null +++ b/tests/com/iciql/test/IciqlSuite.java @@ -0,0 +1,36 @@ +/* + * 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.test; + +import org.junit.Assert; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +/** + * JUnit 4 iciql test suite. + * + */ +@RunWith(Suite.class) +@SuiteClasses({ AliasMapTest.class, AnnotationsTest.class, ClobTest.class, ConcurrencyTest.class, + ModelsTest.class, SamplesTest.class, UpdateTest.class, RuntimeQueryTest.class, + StatementLoggerTest.class }) +public class IciqlSuite { + + public static void assertStartsWith(String a, String b) { + Assert.assertTrue(a.startsWith(b)); + } +} diff --git a/tests/com/iciql/test/ModelsTest.java b/tests/com/iciql/test/ModelsTest.java new file mode 100644 index 0000000..b3974b8 --- /dev/null +++ b/tests/com/iciql/test/ModelsTest.java @@ -0,0 +1,181 @@ +/* + * Copyright 2004-2011 H2 Group. + * 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.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.sql.SQLException; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ErrorCollector; + +import com.iciql.Db; +import com.iciql.DbInspector; +import com.iciql.DbUpgrader; +import com.iciql.DbVersion; +import com.iciql.Iciql.IQDatabase; +import com.iciql.ValidationRemark; +import com.iciql.test.models.Product; +import com.iciql.test.models.ProductAnnotationOnly; +import com.iciql.test.models.ProductMixedAnnotation; +import com.iciql.test.models.SupportedTypes; +import com.iciql.test.models.SupportedTypes.SupportedTypes2; + +/** + * Test that the mapping between classes and tables is done correctly. + */ +public class ModelsTest { + + /* + * The ErrorCollector Rule allows execution of a test to continue after the + * first problem is found and report them all at once + */ + @Rule + public ErrorCollector errorCollector = new ErrorCollector(); + + private Db db; + + private void log(String text) { + System.out.println(text); + } + + @Before + public void setUp() { + db = Db.open("jdbc:h2:mem:", "sa", "sa"); + db.insertAll(Product.getList()); + db.insertAll(ProductAnnotationOnly.getList()); + db.insertAll(ProductMixedAnnotation.getList()); + } + + @After + public void tearDown() { + db.close(); + } + + @Test + public void testValidateModels() { + DbInspector inspector = new DbInspector(db); + validateModel(inspector, new Product()); + validateModel(inspector, new ProductAnnotationOnly()); + validateModel(inspector, new ProductMixedAnnotation()); + } + + private void validateModel(DbInspector inspector, Object o) { + List remarks = inspector.validateModel(o, false); + assertTrue("Validation remarks are null for " + o.getClass().getName(), remarks != null); + log("Validation remarks for " + o.getClass().getName()); + for (ValidationRemark remark : remarks) { + log(remark.toString()); + if (remark.isError()) { + errorCollector.addError(new SQLException(remark.toString())); + } + } + } + + @Test + public void testSupportedTypes() { + List original = SupportedTypes.createList(); + db.insertAll(original); + List retrieved = db.from(SupportedTypes.SAMPLE).select(); + assertEquals(original.size(), retrieved.size()); + for (int i = 0; i < original.size(); i++) { + SupportedTypes o = original.get(i); + SupportedTypes r = retrieved.get(i); + assertTrue(o.equivalentTo(r)); + } + } + + @Test + public void testModelGeneration() { + List original = SupportedTypes.createList(); + db.insertAll(original); + DbInspector inspector = new DbInspector(db); + List models = inspector.generateModel(null, "SupportedTypes", "com.iciql.test.models", true, + true); + assertEquals(1, models.size()); + // a poor test, but a start + assertEquals(1361, models.get(0).length()); + } + + @Test + public void testDatabaseUpgrade() { + // insert a database version record + db.insert(new DbVersion(1)); + + TestDbUpgrader dbUpgrader = new TestDbUpgrader(); + db.setDbUpgrader(dbUpgrader); + + List original = SupportedTypes.createList(); + db.insertAll(original); + + assertEquals(1, dbUpgrader.oldVersion.get()); + assertEquals(2, dbUpgrader.newVersion.get()); + } + + @Test + public void testTableUpgrade() { + Db db = Db.open("jdbc:h2:mem:", "sa", "sa"); + + // insert first, this will create version record automatically + List original = SupportedTypes.createList(); + db.insertAll(original); + + // reset the dbUpgrader (clears the update check cache) + TestDbUpgrader dbUpgrader = new TestDbUpgrader(); + db.setDbUpgrader(dbUpgrader); + + SupportedTypes2 s2 = new SupportedTypes2(); + + List types = db.from(s2).select(); + assertEquals(10, types.size()); + assertEquals(1, dbUpgrader.oldVersion.get()); + assertEquals(2, dbUpgrader.newVersion.get()); + db.close(); + } + + /** + * A sample database upgrader class. + */ + @IQDatabase(version = 2) + class TestDbUpgrader implements DbUpgrader { + final AtomicInteger oldVersion = new AtomicInteger(0); + final AtomicInteger newVersion = new AtomicInteger(0); + + public boolean upgradeTable(Db db, String schema, String table, int fromVersion, int toVersion) { + // just claims success on upgrade request + oldVersion.set(fromVersion); + newVersion.set(toVersion); + return true; + } + + public boolean upgradeDatabase(Db db, int fromVersion, int toVersion) { + // just claims success on upgrade request + oldVersion.set(fromVersion); + newVersion.set(toVersion); + return true; + } + + } + +} diff --git a/tests/com/iciql/test/RuntimeQueryTest.java b/tests/com/iciql/test/RuntimeQueryTest.java new file mode 100644 index 0000000..ff6fe2a --- /dev/null +++ b/tests/com/iciql/test/RuntimeQueryTest.java @@ -0,0 +1,92 @@ +/* + * 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.test; + +import static org.junit.Assert.assertEquals; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +import org.junit.Test; + +import com.iciql.Db; +import com.iciql.test.models.Product; +import com.iciql.util.JdbcUtils; + +/** + * Tests the runtime dynamic query function. + */ +public class RuntimeQueryTest { + + @Test + public void testRuntimeQuery() { + Db db = Db.open("jdbc:h2:mem:", "sa", "sa"); + db.insertAll(Product.getList()); + + Product p = new Product(); + List products = db.from(p).where("unitsInStock=?", 120).orderBy(p.productId).select(); + assertEquals(1, products.size()); + + products = db.from(p).where("unitsInStock=? and productName like ? order by productId", 0, "Chef%") + .select(); + assertEquals(1, products.size()); + + db.close(); + } + + @Test + public void testExecuteQuery() throws SQLException { + Db db = Db.open("jdbc:h2:mem:", "sa", "sa"); + db.insertAll(Product.getList()); + + // test plain statement + List products = db.executeQuery(Product.class, "select * from product where unitsInStock=120"); + assertEquals(1, products.size()); + assertEquals("Condiments", products.get(0).category); + + // test prepared statement + products = db.executeQuery(Product.class, "select * from product where unitsInStock=?", 120); + assertEquals(1, products.size()); + assertEquals("Condiments", products.get(0).category); + + db.close(); + } + + @Test + public void testBuildObjects() throws SQLException { + Db db = Db.open("jdbc:h2:mem:", "sa", "sa"); + db.insertAll(Product.getList()); + + // test plain statement + ResultSet rs = db.executeQuery("select * from product where unitsInStock=120"); + List products = db.buildObjects(Product.class, rs); + JdbcUtils.closeSilently(rs, true); + + assertEquals(1, products.size()); + assertEquals("Condiments", products.get(0).category); + + // test prepared statement + rs = db.executeQuery("select * from product where unitsInStock=?", 120); + products = db.buildObjects(Product.class, rs); + JdbcUtils.closeSilently(rs, true); + + assertEquals(1, products.size()); + assertEquals("Condiments", products.get(0).category); + + db.close(); + } +} diff --git a/tests/com/iciql/test/SamplesTest.java b/tests/com/iciql/test/SamplesTest.java new file mode 100644 index 0000000..309bd5d --- /dev/null +++ b/tests/com/iciql/test/SamplesTest.java @@ -0,0 +1,406 @@ +/* + * Copyright 2004-2011 H2 Group. + * 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.test; + +import static com.iciql.Function.count; +import static com.iciql.Function.isNull; +import static com.iciql.Function.length; +import static com.iciql.Function.max; +import static com.iciql.Function.min; +import static com.iciql.Function.not; +import static com.iciql.Function.sum; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.math.BigDecimal; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.iciql.Db; +import com.iciql.Filter; +import com.iciql.test.models.ComplexObject; +import com.iciql.test.models.Customer; +import com.iciql.test.models.Order; +import com.iciql.test.models.Product; +import com.iciql.test.models.SupportedTypes; + +/** + * This is the implementation of the 101 LINQ Samples as described in + * http://msdn2.microsoft.com/en-us/vcsharp/aa336760.aspx + */ +public class SamplesTest { + + /** + * This object represents a database (actually a connection to the + * database). + */ + + Db db; + + @Before + public void setUp() { + db = Db.open("jdbc:h2:mem:", "sa", "sa"); + db.insertAll(Product.getList()); + db.insertAll(Customer.getList()); + db.insertAll(Order.getList()); + db.insertAll(ComplexObject.getList()); + } + + @After + public void tearDown() { + db.close(); + } + + /** + * A simple test table. The columns are in a different order than in the + * database. + */ + public static class TestReverse { + public String name; + public Integer id; + } + + @Test + public void testReverseColumns() { + db.executeUpdate("create table TestReverse(id int, name varchar, additional varchar)"); + TestReverse t = new TestReverse(); + t.id = 10; + t.name = "Hello"; + db.insert(t); + TestReverse check = db.from(new TestReverse()).selectFirst(); + assertEquals(t.name, check.name); + assertEquals(t.id, check.id); + } + + @Test + public void testWhereSimple2() { + + // var soldOutProducts = + // from p in products + // where p.UnitsInStock == 0 + // select p; + + Product p = new Product(); + List soldOutProducts = db.from(p).where(p.unitsInStock).is(0).orderBy(p.productId).select(); + + assertEquals("[Chef Anton's Gumbo Mix: 0]", soldOutProducts.toString()); + } + + @Test + public void testWhereSimple3() { + + // var expensiveInStockProducts = + // from p in products + // where p.UnitsInStock > 0 + // && p.UnitPrice > 3.00M + // select p; + + Product p = new Product(); + List expensiveInStockProducts = db.from(p).where(p.unitsInStock).exceeds(0).and(p.unitPrice) + .exceeds(30.0).orderBy(p.productId).select(); + + assertEquals("[Northwoods Cranberry Sauce: 6, Mishi Kobe Niku: 29, Ikura: 31]", + expensiveInStockProducts.toString()); + } + + @Test + public void testWhereSimple4() { + + // var waCustomers = + // from c in customers + // where c.Region == "WA" + // select c; + + Customer c = new Customer(); + List waCustomers = db.from(c).where(c.region).is("WA").select(); + + assertEquals("[ALFKI, ANATR]", waCustomers.toString()); + } + + @Test + public void testSelectSimple2() { + + // var productNames = + // from p in products + // select p.ProductName; + + Product p = new Product(); + List productNames = db.from(p).orderBy(p.productId).select(p.productName); + + List products = Product.getList(); + for (int i = 0; i < products.size(); i++) { + assertEquals(products.get(i).productName, productNames.get(i)); + } + } + + /** + * A result set class containing the product name and price. + */ + public static class ProductPrice { + public String productName; + public String category; + public Double price; + } + + @Test + public void testAnonymousTypes3() { + + // var productInfos = + // from p in products + // select new { + // p.ProductName, + // p.Category, + // Price = p.UnitPrice + // }; + + final Product p = new Product(); + List productInfos = db.from(p).orderBy(p.productId).select(new ProductPrice() { + { + productName = p.productName; + category = p.category; + price = p.unitPrice; + } + }); + + List products = Product.getList(); + assertEquals(products.size(), productInfos.size()); + for (int i = 0; i < products.size(); i++) { + ProductPrice pr = productInfos.get(i); + Product p2 = products.get(i); + assertEquals(p2.productName, pr.productName); + assertEquals(p2.category, pr.category); + assertEquals(p2.unitPrice, pr.price); + } + } + + /** + * A result set class containing customer data and the order total. + */ + public static class CustOrder { + public String customerId; + public Integer orderId; + public BigDecimal total; + + public String toString() { + return customerId + ":" + orderId + ":" + total; + } + } + + @Test + public void testSelectManyCompoundFrom2() { + + // var orders = + // from c in customers, + // o in c.Orders + // where o.Total < 500.00M + // select new { + // c.CustomerID, + // o.OrderID, + // o.Total + // }; + + final Customer c = new Customer(); + final Order o = new Order(); + List orders = db.from(c).innerJoin(o).on(c.customerId).is(o.customerId).where(o.total) + .lessThan(new BigDecimal("100.00")).orderBy(1).select(new CustOrder() { + { + customerId = c.customerId; + orderId = o.orderId; + total = o.total; + } + }); + + assertEquals("[ANATR:10308:88.80]", orders.toString()); + } + + @Test + public void testIsNull() { + Product p = new Product(); + String sql = db.from(p).whereTrue(isNull(p.productName)).getSQL(); + assertEquals("SELECT * FROM Product WHERE (productName IS NULL)", sql); + } + + @Test + public void testDelete() { + Product p = new Product(); + int deleted = db.from(p).where(p.productName).like("A%").delete(); + assertEquals(1, deleted); + deleted = db.from(p).delete(); + assertEquals(9, deleted); + db.insertAll(Product.getList()); + db.deleteAll(Product.getList()); + assertEquals(0, db.from(p).selectCount()); + db.insertAll(Product.getList()); + } + + @Test + public void testOrAndNot() { + Product p = new Product(); + String sql = db.from(p).whereTrue(not(isNull(p.productName))).getSQL(); + assertEquals("SELECT * FROM Product WHERE (NOT productName IS NULL)", sql); + sql = db.from(p).whereTrue(not(isNull(p.productName))).getSQL(); + assertEquals("SELECT * FROM Product WHERE (NOT productName IS NULL)", sql); + sql = db.from(p).whereTrue(db.test(p.productId).is(1)).getSQL(); + assertEquals("SELECT * FROM Product WHERE ((productId = ?))", sql); + } + + @Test + public void testLength() { + Product p = new Product(); + List lengths = db.from(p).where(length(p.productName)).lessThan(10).orderBy(1) + .selectDistinct(length(p.productName)); + assertEquals("[4, 5]", lengths.toString()); + } + + @Test + public void testSum() { + Product p = new Product(); + Long sum = db.from(p).selectFirst(sum(p.unitsInStock)); + assertEquals(323, sum.intValue()); + Double sumPrice = db.from(p).selectFirst(sum(p.unitPrice)); + assertEquals(313.35, sumPrice.doubleValue(), 0.001); + } + + @Test + public void testMinMax() { + Product p = new Product(); + Integer min = db.from(p).selectFirst(min(p.unitsInStock)); + assertEquals(0, min.intValue()); + String minName = db.from(p).selectFirst(min(p.productName)); + assertEquals("Aniseed Syrup", minName); + Double max = db.from(p).selectFirst(max(p.unitPrice)); + assertEquals(97.0, max.doubleValue(), 0.001); + } + + @Test + public void testLike() { + Product p = new Product(); + List aList = db.from(p).where(p.productName).like("Cha%").orderBy(p.productName).select(); + assertEquals("[Chai: 39, Chang: 17]", aList.toString()); + } + + @Test + public void testCount() { + long count = db.from(new Product()).selectCount(); + assertEquals(10, count); + } + + @Test + public void testComplexObject() { + ComplexObject co = new ComplexObject(); + String sql = db.from(co).where(co.id).is(1).and(co.amount).is(1L).and(co.birthday) + .lessThan(new java.util.Date()).and(co.created) + .lessThan(java.sql.Timestamp.valueOf("2005-05-05 05:05:05")).and(co.name).is("hello").and(co.time) + .lessThan(java.sql.Time.valueOf("23:23:23")).and(co.value).is(new BigDecimal("1")).getSQL(); + assertEquals("SELECT * FROM ComplexObject " + "WHERE id = ? " + "AND amount = ? " + "AND birthday < ? " + + "AND created < ? " + "AND name = ? " + "AND time < ? " + "AND value = ?", sql); + + long count = db.from(co).where(co.id).is(1).and(co.amount).is(1L).and(co.birthday) + .lessThan(new java.util.Date()).and(co.created) + .lessThan(java.sql.Timestamp.valueOf("2005-05-05 05:05:05")).and(co.name).is("hello").and(co.time) + .lessThan(java.sql.Time.valueOf("23:23:23")).and(co.value).is(new BigDecimal("1")).selectCount(); + assertEquals(1, count); + } + + @Test + public void testComplexObject2() { + testComplexObject2(1, "hello"); + } + + private void testComplexObject2(final int x, final String name) { + final ComplexObject co = new ComplexObject(); + + String sql = db.from(co).where(new Filter() { + public boolean where() { + return co.id == x && co.name.equals(name) && co.name.equals("hello"); + } + }).getSQL(); + assertEquals("SELECT * FROM ComplexObject " + "WHERE id=? " + "AND ?=name " + "AND 'hello'=name", sql); + + long count = db.from(co).where(new Filter() { + public boolean where() { + return co.id == x && co.name.equals(name) && co.name.equals("hello"); + } + }).selectCount(); + + assertEquals(1, count); + } + + @Test + public void testLimitOffset() { + Set ids = new HashSet(); + Product p = new Product(); + for (int i = 0; i < 5; i++) { + List products = db.from(p).limit(2).offset(2 * i).select(); + assertTrue(products.size() == 2); + for (Product prod : products) { + assertTrue("Failed to add product id. Duplicate?", ids.add(prod.productId)); + } + } + } + + @Test + public void testKeyRetrieval() { + List list = SupportedTypes.createList(); + List keys = db.insertAllAndGetKeys(list); + Set uniqueKeys = new HashSet(); + for (Long l : keys) { + assertTrue("Failed to add key. Duplicate?", uniqueKeys.add(l)); + } + } + + /** + * A result set class containing product groups. + */ + public static class ProductGroup { + public String category; + public Long productCount; + + public String toString() { + return category + ":" + productCount; + } + } + + @Test + public void testGroup() { + + // var orderGroups = + // from p in products + // group p by p.Category into g + // select new { + // Category = g.Key, + // Products = g + // }; + + final Product p = new Product(); + List list = db.from(p).groupBy(p.category).orderBy(1).select(new ProductGroup() { + { + category = p.category; + productCount = count(); + } + }); + + assertEquals("[Beverages:2, Condiments:5, " + "Meat/Poultry:1, Produce:1, Seafood:1]", list.toString()); + } + +} diff --git a/tests/com/iciql/test/StatementLoggerTest.java b/tests/com/iciql/test/StatementLoggerTest.java new file mode 100644 index 0000000..212faf2 --- /dev/null +++ b/tests/com/iciql/test/StatementLoggerTest.java @@ -0,0 +1,39 @@ +/* + * 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.test; + +import org.junit.Test; + +import com.iciql.Db; +import com.iciql.test.models.Product; +import com.iciql.util.StatementLogger; + +/** + * Tests the statement logger. + */ +public class StatementLoggerTest { + + @Test + public void testStatementLogger() { + StatementLogger.activateConsoleLogger(); + Db db = Db.open("jdbc:h2:mem:", "sa", "sa"); + db.insertAll(Product.getList()); + db.close(); + StatementLogger.logStats(); + StatementLogger.deactivateConsoleLogger(); + } +} diff --git a/tests/com/iciql/test/UpdateTest.java b/tests/com/iciql/test/UpdateTest.java new file mode 100644 index 0000000..9ff5593 --- /dev/null +++ b/tests/com/iciql/test/UpdateTest.java @@ -0,0 +1,160 @@ +/* + * Copyright 2004-2011 H2 Group. + * 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.test; + +import static java.sql.Date.valueOf; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.iciql.Db; +import com.iciql.test.models.Customer; +import com.iciql.test.models.Order; +import com.iciql.test.models.Product; + +/** + * Tests the Db.update() function. + * + * @author dmoebius at scoop dash gmbh dot de + */ +public class UpdateTest { + + private Db db; + + @Before + public void setUp() throws Exception { + db = Db.open("jdbc:h2:mem:", "sa", "sa"); + db.insertAll(Product.getList()); + db.insertAll(Customer.getList()); + db.insertAll(Order.getList()); + } + + @After + public void tearDown() { + db.close(); + } + + @Test + public void testSimpleUpdate() { + Product p = new Product(); + Product pChang = db.from(p).where(p.productName).is("Chang").selectFirst(); + // update unitPrice from 19.0 to 19.5 + pChang.unitPrice = 19.5; + // update unitsInStock from 17 to 16 + pChang.unitsInStock = 16; + db.update(pChang); + + Product p2 = new Product(); + Product pChang2 = db.from(p2).where(p2.productName).is("Chang").selectFirst(); + assertEquals(19.5, pChang2.unitPrice.doubleValue(), 0.001); + assertEquals(16, pChang2.unitsInStock.intValue()); + + // undo update + pChang.unitPrice = 19.0; + pChang.unitsInStock = 17; + db.update(pChang); + } + + @Test + public void testSimpleUpdateWithCombinedPrimaryKey() { + Order o = new Order(); + Order ourOrder = db.from(o).where(o.orderDate).is(valueOf("2007-01-02")).selectFirst(); + ourOrder.orderDate = valueOf("2007-01-03"); + db.update(ourOrder); + + Order ourUpdatedOrder = db.from(o).where(o.orderDate).is(valueOf("2007-01-03")).selectFirst(); + assertTrue("updated order not found", ourUpdatedOrder != null); + + // undo update + ourOrder.orderDate = valueOf("2007-01-02"); + db.update(ourOrder); + } + + @Test + public void testSimpleMerge() { + Product p = new Product(); + Product pChang = db.from(p).where(p.productName).is("Chang").selectFirst(); + // update unitPrice from 19.0 to 19.5 + pChang.unitPrice = 19.5; + // update unitsInStock from 17 to 16 + pChang.unitsInStock = 16; + db.merge(pChang); + + Product p2 = new Product(); + Product pChang2 = db.from(p2).where(p2.productName).is("Chang").selectFirst(); + assertEquals(19.5, pChang2.unitPrice, 0.001); + assertEquals(16, pChang2.unitsInStock.intValue()); + + // undo update + pChang.unitPrice = 19.0; + pChang.unitsInStock = 17; + db.merge(pChang); + } + + @Test + public void testSimpleMergeWithCombinedPrimaryKey() { + Order o = new Order(); + Order ourOrder = db.from(o).where(o.orderDate).is(valueOf("2007-01-02")).selectFirst(); + ourOrder.orderDate = valueOf("2007-01-03"); + db.merge(ourOrder); + + Order ourUpdatedOrder = db.from(o).where(o.orderDate).is(valueOf("2007-01-03")).selectFirst(); + assertTrue("updated order not found", ourUpdatedOrder != null); + + // undo update + ourOrder.orderDate = valueOf("2007-01-02"); + db.merge(ourOrder); + } + + @Test + public void testSetColumns() { + Product p = new Product(); + Product original = db.from(p).where(p.productId).is(1).selectFirst(); + + // update string and double columns + db.from(p).set(p.productName).to("updated").increment(p.unitPrice).by(3.14).increment(p.unitsInStock) + .by(2).where(p.productId).is(1).update(); + + // confirm the data was properly updated + Product revised = db.from(p).where(p.productId).is(1).selectFirst(); + assertEquals("updated", revised.productName); + assertEquals(original.unitPrice + 3.14, revised.unitPrice, 0.001); + assertEquals(original.unitsInStock + 2, revised.unitsInStock.intValue()); + + // restore the data + db.from(p).set(p.productName).to(original.productName).set(p.unitPrice).to(original.unitPrice) + .increment(p.unitsInStock).by(-2).where(p.productId).is(1).update(); + + // confirm the data was properly restored + Product restored = db.from(p).where(p.productId).is(1).selectFirst(); + assertEquals(original.productName, restored.productName); + assertEquals(original.unitPrice, restored.unitPrice); + assertEquals(original.unitsInStock, restored.unitsInStock); + + double unitPriceOld = db.from(p).where(p.productId).is(1).selectFirst().unitPrice; + // double the unit price + db.from(p).increment(p.unitPrice).by(p.unitPrice).where(p.productId).is(1).update(); + double unitPriceNew = db.from(p).where(p.productId).is(1).selectFirst().unitPrice; + assertEquals(unitPriceOld * 2, unitPriceNew, 0.001); + + } + +} diff --git a/tests/com/iciql/test/models/ComplexObject.java b/tests/com/iciql/test/models/ComplexObject.java new file mode 100644 index 0000000..294dc27 --- /dev/null +++ b/tests/com/iciql/test/models/ComplexObject.java @@ -0,0 +1,64 @@ +/* + * Copyright 2004-2011 H2 Group. + * 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.test.models; + +import static com.iciql.Define.primaryKey; + +import java.math.BigDecimal; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import com.iciql.Iciql; + +/** + * A table containing all possible data types. + */ + +public class ComplexObject implements Iciql { + public Integer id; + public Long amount; + public String name; + public BigDecimal value; + public Date birthday; + public Time time; + public Timestamp created; + + static ComplexObject build(Integer id, boolean isNull) { + ComplexObject obj = new ComplexObject(); + obj.id = id; + obj.amount = isNull ? null : Long.valueOf(1); + obj.name = isNull ? null : "hello"; + obj.value = isNull ? null : new BigDecimal("1"); + obj.birthday = isNull ? null : java.sql.Date.valueOf("2001-01-01"); + obj.time = isNull ? null : Time.valueOf("10:20:30"); + obj.created = isNull ? null : Timestamp.valueOf("2002-02-02 02:02:02"); + return obj; + } + + public void defineIQ() { + primaryKey(id); + } + + public static List getList() { + return Arrays.asList(new ComplexObject[] { build(0, true), build(1, false) }); + } + +} diff --git a/tests/com/iciql/test/models/Customer.java b/tests/com/iciql/test/models/Customer.java new file mode 100644 index 0000000..c2b8da9 --- /dev/null +++ b/tests/com/iciql/test/models/Customer.java @@ -0,0 +1,49 @@ +/* + * Copyright 2004-2011 H2 Group. + * 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.test.models; + +import java.util.Arrays; +import java.util.List; + +/** + * A table containing customer data. + */ +public class Customer { + + public String customerId; + public String region; + + public Customer() { + // public constructor + } + + public Customer(String customerId, String region) { + this.customerId = customerId; + this.region = region; + } + + public String toString() { + return customerId; + } + + public static List getList() { + Customer[] list = { new Customer("ALFKI", "WA"), new Customer("ANATR", "WA"), new Customer("ANTON", "CA") }; + return Arrays.asList(list); + } + +} diff --git a/tests/com/iciql/test/models/Order.java b/tests/com/iciql/test/models/Order.java new file mode 100644 index 0000000..f0cf7f3 --- /dev/null +++ b/tests/com/iciql/test/models/Order.java @@ -0,0 +1,65 @@ +/* + * Copyright 2004-2011 H2 Group. + * 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.test.models; + +import static com.iciql.Define.primaryKey; +import static com.iciql.Define.tableName; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import com.iciql.Iciql; + +/** + * A table containing order data. + */ + +public class Order implements Iciql { + public String customerId; + public Integer orderId; + public Date orderDate; + public BigDecimal total; + + public Order(String customerId, Integer orderId, String total, String orderDate) { + this.customerId = customerId; + this.orderId = orderId; + this.total = new BigDecimal(total); + this.orderDate = java.sql.Date.valueOf(orderDate); + } + + public Order() { + // public constructor + } + + public void defineIQ() { + tableName("Orders"); + primaryKey(customerId, orderId); + } + + public static List getList() { + Order[] list = { new Order("ALFKI", 10702, "330.00", "2007-01-02"), + new Order("ALFKI", 10952, "471.20", "2007-02-03"), new Order("ANATR", 10308, "88.80", "2007-01-03"), + new Order("ANATR", 10625, "479.75", "2007-03-03"), new Order("ANATR", 10759, "320.00", "2007-04-01"), + new Order("ANTON", 10365, "403.20", "2007-02-13"), new Order("ANTON", 10682, "375.50", "2007-03-13"), + new Order("ANTON", 10355, "480.00", "2007-04-11") }; + return Arrays.asList(list); + } + +} diff --git a/tests/com/iciql/test/models/Product.java b/tests/com/iciql/test/models/Product.java new file mode 100644 index 0000000..735ebab --- /dev/null +++ b/tests/com/iciql/test/models/Product.java @@ -0,0 +1,82 @@ +/* + * Copyright 2004-2011 H2 Group. + * 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.test.models; + +import static com.iciql.Define.index; +import static com.iciql.Define.maxLength; +import static com.iciql.Define.primaryKey; +import static com.iciql.Define.tableName; + +import java.util.Arrays; +import java.util.List; + +import com.iciql.Iciql; + +/** + * A table containing product data. + */ + +public class Product implements Iciql { + + public Integer productId; + public String productName; + public String category; + public Double unitPrice; + public Integer unitsInStock; + + public Product() { + // public constructor + } + + private Product(int productId, String productName, String category, double unitPrice, int unitsInStock) { + this.productId = productId; + this.productName = productName; + this.category = category; + this.unitPrice = unitPrice; + this.unitsInStock = unitsInStock; + } + + public void defineIQ() { + tableName("Product"); + primaryKey(productId); + maxLength(category, 255); + index(productName, category); + } + + private static Product create(int productId, String productName, String category, double unitPrice, int unitsInStock) { + return new Product(productId, productName, category, unitPrice, unitsInStock); + } + + public static List getList() { + Product[] list = { create(1, "Chai", "Beverages", 18, 39), create(2, "Chang", "Beverages", 19.0, 17), + create(3, "Aniseed Syrup", "Condiments", 10.0, 13), + create(4, "Chef Anton's Cajun Seasoning", "Condiments", 22.0, 53), + create(5, "Chef Anton's Gumbo Mix", "Condiments", 21.3500, 0), + create(6, "Grandma's Boysenberry Spread", "Condiments", 25.0, 120), + create(7, "Uncle Bob's Organic Dried Pears", "Produce", 30.0, 15), + create(8, "Northwoods Cranberry Sauce", "Condiments", 40.0, 6), + create(9, "Mishi Kobe Niku", "Meat/Poultry", 97.0, 29), create(10, "Ikura", "Seafood", 31.0, 31), }; + + return Arrays.asList(list); + } + + public String toString() { + return productName + ": " + unitsInStock; + } + +} diff --git a/tests/com/iciql/test/models/ProductAnnotationOnly.java b/tests/com/iciql/test/models/ProductAnnotationOnly.java new file mode 100644 index 0000000..7921237 --- /dev/null +++ b/tests/com/iciql/test/models/ProductAnnotationOnly.java @@ -0,0 +1,94 @@ +/* + * Copyright 2004-2011 H2 Group. + * 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.test.models; + +import java.util.Arrays; +import java.util.List; + +import com.iciql.Iciql.IQColumn; +import com.iciql.Iciql.IQIndex; +import com.iciql.Iciql.IQTable; + +/** + * A table containing product data. + */ + +@IQTable(name = "AnnotatedProduct", primaryKey = "id") +@IQIndex(standard = "name, cat") +public class ProductAnnotationOnly { + + @IQColumn(autoIncrement = true) + public Integer autoIncrement; + + public String unmappedField; + + @IQColumn(name = "id") + public Integer productId; + + @IQColumn(name = "cat", maxLength = 15, trimString = true) + public String category; + + @IQColumn(name = "name") + private String productName; + + @SuppressWarnings("unused") + @IQColumn + private Double unitPrice; + + @IQColumn + private Integer unitsInStock; + + public ProductAnnotationOnly() { + // public constructor + } + + private ProductAnnotationOnly(int productId, String productName, String category, double unitPrice, + int unitsInStock, String unmappedField) { + this.productId = productId; + this.productName = productName; + this.category = category; + this.unitPrice = unitPrice; + this.unitsInStock = unitsInStock; + this.unmappedField = unmappedField; + } + + private static ProductAnnotationOnly create(int productId, String productName, String category, double unitPrice, + int unitsInStock, String unmappedField) { + return new ProductAnnotationOnly(productId, productName, category, unitPrice, unitsInStock, unmappedField); + } + + public static List getList() { + String unmappedField = "unmapped"; + ProductAnnotationOnly[] list = { create(1, "Chai", "Beverages", 18, 39, unmappedField), + create(2, "Chang", "Beverages", 19.0, 17, unmappedField), + create(3, "Aniseed Syrup", "Condiments", 10.0, 13, unmappedField), + create(4, "Chef Anton's Cajun Seasoning", "Condiments", 22.0, 53, unmappedField), + create(5, "Chef Anton's Gumbo Mix", "Condiments", 21.3500, 0, unmappedField), + create(6, "Grandma's Boysenberry Spread", "Condiments", 25.0, 120, unmappedField), + create(7, "Uncle Bob's Organic Dried Pears", "Produce", 30.0, 15, unmappedField), + create(8, "Northwoods Cranberry Sauce", "Condiments", 40.0, 6, unmappedField), + create(9, "Mishi Kobe Niku", "Meat/Poultry", 97.0, 29, unmappedField), + create(10, "Ikura", "Seafood", 31.0, 31, unmappedField), }; + return Arrays.asList(list); + } + + public String toString() { + return productName + ": " + unitsInStock; + } + +} diff --git a/tests/com/iciql/test/models/ProductInheritedAnnotation.java b/tests/com/iciql/test/models/ProductInheritedAnnotation.java new file mode 100644 index 0000000..0a63aae --- /dev/null +++ b/tests/com/iciql/test/models/ProductInheritedAnnotation.java @@ -0,0 +1,63 @@ +/* + * Copyright 2004-2011 H2 Group. + * 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.test.models; + +import java.util.Arrays; +import java.util.List; + +import com.iciql.Iciql.IQTable; + +/** + * This class inherits all its fields from a parent class which has annotated + * columns. The IQTable annotation of the parent class is ignored and only the + * IQTable annotation of this class matters. However, this table inherits + * IQColumns from its super class. + */ +@IQTable(inheritColumns = true, annotationsOnly = false) +public class ProductInheritedAnnotation extends ProductMixedAnnotation { + + public ProductInheritedAnnotation() { + // public constructor + } + + private ProductInheritedAnnotation(int productId, String productName, String category, double unitPrice, + int unitsInStock, String mappedField) { + super(productId, productName, category, unitPrice, unitsInStock, mappedField); + } + + private static ProductInheritedAnnotation create(int productId, String productName, String category, + double unitPrice, int unitsInStock, String mappedField) { + return new ProductInheritedAnnotation(productId, productName, category, unitPrice, unitsInStock, mappedField); + } + + public static List getData() { + String mappedField = "mapped"; + ProductInheritedAnnotation[] list = { create(1, "Chai", "Beverages", 18, 39, mappedField), + create(2, "Chang", "Beverages", 19.0, 17, mappedField), + create(3, "Aniseed Syrup", "Condiments", 10.0, 13, mappedField), + create(4, "Chef Anton's Cajun Seasoning", "Condiments", 22.0, 53, mappedField), + create(5, "Chef Anton's Gumbo Mix", "Condiments", 21.3500, 0, mappedField), + create(6, "Grandma's Boysenberry Spread", "Condiments", 25.0, 120, mappedField), + create(7, "Uncle Bob's Organic Dried Pears", "Produce", 30.0, 15, mappedField), + create(8, "Northwoods Cranberry Sauce", "Condiments", 40.0, 6, mappedField), + create(9, "Mishi Kobe Niku", "Meat/Poultry", 97.0, 29, mappedField), + create(10, "Ikura", "Seafood", 31.0, 31, mappedField), }; + return Arrays.asList(list); + } + +} diff --git a/tests/com/iciql/test/models/ProductMixedAnnotation.java b/tests/com/iciql/test/models/ProductMixedAnnotation.java new file mode 100644 index 0000000..f90bd65 --- /dev/null +++ b/tests/com/iciql/test/models/ProductMixedAnnotation.java @@ -0,0 +1,94 @@ +/* + * Copyright 2004-2011 H2 Group. + * 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.test.models; + +import java.util.Arrays; +import java.util.List; + +import com.iciql.Iciql.IQColumn; +import com.iciql.Iciql.IQIndex; +import com.iciql.Iciql.IQTable; + +/** + * A table containing product data. + */ + +@IQTable(annotationsOnly = false) +@IQIndex(standard = "name, cat") +public class ProductMixedAnnotation { + + public Double unitPrice; + public Integer unitsInStock; + public String mappedField; + + @IQColumn(name = "cat", maxLength = 255) + public String category; + + @IQColumn(name = "id", primaryKey = true) + private Integer productId; + + @IQColumn(name = "name") + private String productName; + + public ProductMixedAnnotation() { + // public constructor + } + + protected ProductMixedAnnotation(int productId, String productName, String category, double unitPrice, + int unitsInStock, String mappedField) { + this.productId = productId; + this.productName = productName; + this.category = category; + this.unitPrice = unitPrice; + this.unitsInStock = unitsInStock; + this.mappedField = mappedField; + } + + private static ProductMixedAnnotation create(int productId, String productName, String category, double unitPrice, + int unitsInStock, String mappedField) { + return new ProductMixedAnnotation(productId, productName, category, unitPrice, unitsInStock, mappedField); + } + + public static List getList() { + String mappedField = "mapped"; + ProductMixedAnnotation[] list = { create(1, "Chai", "Beverages", 18, 39, mappedField), + create(2, "Chang", "Beverages", 19.0, 17, mappedField), + create(3, "Aniseed Syrup", "Condiments", 10.0, 13, mappedField), + create(4, "Chef Anton's Cajun Seasoning", "Condiments", 22.0, 53, mappedField), + create(5, "Chef Anton's Gumbo Mix", "Condiments", 21.3500, 0, mappedField), + create(6, "Grandma's Boysenberry Spread", "Condiments", 25.0, 120, mappedField), + create(7, "Uncle Bob's Organic Dried Pears", "Produce", 30.0, 15, mappedField), + create(8, "Northwoods Cranberry Sauce", "Condiments", 40.0, 6, mappedField), + create(9, "Mishi Kobe Niku", "Meat/Poultry", 97.0, 29, mappedField), + create(10, "Ikura", "Seafood", 31.0, 31, mappedField), }; + return Arrays.asList(list); + } + + public String toString() { + return productName + ": " + unitsInStock; + } + + public int id() { + return productId; + } + + public String name() { + return productName; + } + +} diff --git a/tests/com/iciql/test/models/ProductNoCreateTable.java b/tests/com/iciql/test/models/ProductNoCreateTable.java new file mode 100644 index 0000000..074af35 --- /dev/null +++ b/tests/com/iciql/test/models/ProductNoCreateTable.java @@ -0,0 +1,59 @@ +/* + * Copyright 2004-2011 H2 Group. + * 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.test.models; + +import java.util.Arrays; +import java.util.List; + +import com.iciql.Iciql.IQColumn; +import com.iciql.Iciql.IQTable; + +/** + * A table containing product data. + */ + +@IQTable(createIfRequired = false) +public class ProductNoCreateTable { + + @SuppressWarnings("unused") + @IQColumn(name = "id") + private Integer productId; + + @SuppressWarnings("unused") + @IQColumn(name = "name") + private String productName; + + public ProductNoCreateTable() { + // public constructor + } + + private ProductNoCreateTable(int productId, String productName) { + this.productId = productId; + this.productName = productName; + } + + private static ProductNoCreateTable create(int productId, String productName) { + return new ProductNoCreateTable(productId, productName); + } + + public static List getList() { + ProductNoCreateTable[] list = { create(1, "Chai"), create(2, "Chang") }; + return Arrays.asList(list); + } + +} diff --git a/tests/com/iciql/test/models/SupportedTypes.java b/tests/com/iciql/test/models/SupportedTypes.java new file mode 100644 index 0000000..26692fc --- /dev/null +++ b/tests/com/iciql/test/models/SupportedTypes.java @@ -0,0 +1,133 @@ +/* + * Copyright 2004-2011 H2 Group. + * 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.test.models; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Random; + +import com.iciql.Iciql.IQColumn; +import com.iciql.Iciql.IQTable; +import com.iciql.util.Utils; + +/** + * A data class that contains a column for each data type. + */ +@IQTable(strictTypeMapping = true, version = 1) +public class SupportedTypes { + + public static final SupportedTypes SAMPLE = new SupportedTypes(); + + @IQColumn(primaryKey = true, autoIncrement = true) + public Integer id; + + @IQColumn + private Boolean myBool = false; + + @IQColumn + private Byte myByte = 2; + + @IQColumn + private Short myShort; + + @IQColumn + private Integer myInteger; + + @IQColumn + private Long myLong; + + @IQColumn + private Float myFloat = 1.0f; + + @IQColumn + private Double myDouble; + + @IQColumn + private BigDecimal myBigDecimal; + + @IQColumn + private String myString; + + @IQColumn + private java.util.Date myUtilDate; + + @IQColumn + private java.sql.Date mySqlDate; + + @IQColumn + private java.sql.Time mySqlTime; + + @IQColumn + private java.sql.Timestamp mySqlTimestamp; + + public static List createList() { + List list = Utils.newArrayList(); + for (int i = 0; i < 10; i++) { + list.add(randomValue()); + } + return list; + } + + static SupportedTypes randomValue() { + Random rand = new Random(); + SupportedTypes s = new SupportedTypes(); + s.myBool = new Boolean(rand.nextBoolean()); + s.myByte = new Byte((byte) rand.nextInt(Byte.MAX_VALUE)); + s.myShort = new Short((short) rand.nextInt(Short.MAX_VALUE)); + s.myInteger = new Integer(rand.nextInt()); + s.myLong = new Long(rand.nextLong()); + s.myFloat = new Float(rand.nextFloat()); + s.myDouble = new Double(rand.nextDouble()); + s.myBigDecimal = new BigDecimal(rand.nextDouble()); + s.myString = Long.toHexString(rand.nextLong()); + s.myUtilDate = new java.util.Date(rand.nextLong()); + s.mySqlDate = new java.sql.Date(rand.nextLong()); + s.mySqlTime = new java.sql.Time(rand.nextLong()); + s.mySqlTimestamp = new java.sql.Timestamp(rand.nextLong()); + return s; + } + + public boolean equivalentTo(SupportedTypes s) { + boolean same = true; + same &= myBool.equals(s.myBool); + same &= myByte.equals(s.myByte); + same &= myShort.equals(s.myShort); + same &= myInteger.equals(s.myInteger); + same &= myLong.equals(s.myLong); + same &= myFloat.equals(s.myFloat); + same &= myDouble.equals(s.myDouble); + same &= myBigDecimal.equals(s.myBigDecimal); + same &= myUtilDate.getTime() == s.myUtilDate.getTime(); + same &= mySqlTimestamp.getTime() == s.mySqlTimestamp.getTime(); + same &= mySqlDate.toString().equals(s.mySqlDate.toString()); + same &= mySqlTime.toString().equals(s.mySqlTime.toString()); + same &= myString.equals(s.myString); + return same; + } + + /** + * This class demonstrates the table upgrade. + */ + @IQTable(name = "SupportedTypes", version = 2, inheritColumns = true, strictTypeMapping = true) + public static class SupportedTypes2 extends SupportedTypes { + + public SupportedTypes2() { + // nothing to do + } + } +} -- cgit v1.2.3