/* * Copyright 2009-2016 Tilmann Zaeschke. All rights reserved. * * This file is part of ZooDB. * * ZooDB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ZooDB is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ZooDB. If not, see <http://www.gnu.org/licenses/>. * * See the README and COPYING files for further information. */ package org.zoodb.test.jdo; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; import javax.jdo.Extent; import javax.jdo.JDOUserException; import javax.jdo.PersistenceManager; import javax.jdo.Query; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.Test; import org.zoodb.internal.ZooClassDef; import org.zoodb.jdo.ZooJdoHelper; import org.zoodb.schema.ZooClass; import org.zoodb.schema.ZooField; import org.zoodb.test.testutil.TestTools; import org.zoodb.tools.DBStatistics.STATS; public class Test_033_SchemaDefinition { private static final int SCHEMA_COUNT = 5; //Schema count on empty database @AfterClass public static void tearDown() { TestTools.closePM(); } @Before public void before() { TestTools.createDb(); } @After public void after() { try { TestTools.closePM(); } catch (Throwable t) { t.printStackTrace(); } TestTools.removeDb(); } @Test public void testDeclareCommit() { PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass s = ZooJdoHelper.schema(pm).defineEmptyClass("MyClass"); assertNotNull(s); assertEquals("MyClass", s.getName()); ZooClass s2 = ZooJdoHelper.schema(pm).getClass("MyClass"); assertNotNull(s2); pm.currentTransaction().commit(); pm.currentTransaction().begin(); ZooClass s3 = ZooJdoHelper.schema(pm).getClass("MyClass"); assertNotNull(s3); pm.currentTransaction().rollback(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass s4 = ZooJdoHelper.schema(pm).getClass("MyClass"); assertNotNull(s4); pm.currentTransaction().rollback(); TestTools.closePM(); } @Test public void testDeclareAbort() { PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass s = ZooJdoHelper.schema(pm).defineEmptyClass("MyClass"); assertNotNull(s); assertEquals("MyClass", s.getName()); pm.currentTransaction().rollback(); //try again pm.currentTransaction().begin(); ZooClass s2 = ZooJdoHelper.schema(pm).getClass("MyClass"); assertNull(s2); ZooClass s3 = ZooJdoHelper.schema(pm).defineEmptyClass("MyClass"); assertNotNull(s3); pm.currentTransaction().rollback(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass s4 = ZooJdoHelper.schema(pm).getClass("MyClass"); assertNull(s4); ZooClass s5 = ZooJdoHelper.schema(pm).defineEmptyClass("MyClass"); assertNotNull(s5); pm.currentTransaction().commit(); TestTools.closePM(); } @Test public void testDeclareFails() { TestTools.defineSchema(TestClassTiny.class); PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); try { ZooJdoHelper.schema(pm).defineEmptyClass(TestClassTiny.class.getName()); fail(); } catch (IllegalArgumentException e) { //good, class exists } try { ZooJdoHelper.schema(pm).defineEmptyClass(""); fail(); } catch (IllegalArgumentException e) { //good, bad name } try { ZooJdoHelper.schema(pm).defineEmptyClass("1342dfs"); fail(); } catch (IllegalArgumentException e) { //good, bad name } try { ZooJdoHelper.schema(pm).defineEmptyClass(null); fail(); } catch (IllegalArgumentException e) { //good, bad name } try { ZooJdoHelper.schema(pm).defineEmptyClass(String.class.getName()); fail(); } catch (IllegalArgumentException e) { //good, non-pers } TestTools.closePM(); try { ZooJdoHelper.schema(pm).defineEmptyClass(TestClassTiny2.class.getName()); fail(); } catch (IllegalStateException e) { //good, outside session } } @Test public void testDeclareHierarchy() { TestTools.defineSchema(TestClassTiny.class); String cName1 = "MyClassA"; String cName2 = "MyClassB"; PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); ZooClass s1 = ZooJdoHelper.schema(pm).defineEmptyClass(cName1, stt); ZooClass s2 = ZooJdoHelper.schema(pm).defineEmptyClass(cName2, s1); assertEquals(stt, s1.getSuperClass()); assertEquals(s1, s2.getSuperClass()); pm.currentTransaction().rollback(); //try again pm.currentTransaction().begin(); stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); s1 = ZooJdoHelper.schema(pm).defineEmptyClass(cName1, stt); s2 = ZooJdoHelper.schema(pm).defineEmptyClass(cName2, s1); assertEquals(stt, s1.getSuperClass()); assertEquals(s1, s2.getSuperClass()); pm.currentTransaction().commit(); TestTools.closePM(); //load and check again pm = TestTools.openPM(); pm.currentTransaction().begin(); stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); assertEquals(stt, s1.getSuperClass()); assertEquals(s1, s2.getSuperClass()); pm.currentTransaction().rollback(); TestTools.closePM(); } @Test public void testRemoveClassRollback() { PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass s1 = ZooJdoHelper.schema(pm).defineEmptyClass("MyClass"); s1.remove(); ZooClass s2 = ZooJdoHelper.schema(pm).getClass("MyClass"); assertNull(s2); pm.currentTransaction().rollback(); pm.currentTransaction().begin(); ZooClass s3 = ZooJdoHelper.schema(pm).getClass("MyClass"); assertNull(s3); ZooClass s4 = ZooJdoHelper.schema(pm).defineEmptyClass("MyClass"); assertNotNull(s4); pm.currentTransaction().commit(); pm.currentTransaction().begin(); ZooClass s5 = ZooJdoHelper.schema(pm).getClass("MyClass"); assertNotNull(s5); s5.remove(); pm.currentTransaction().rollback(); pm.currentTransaction().begin(); ZooClass s6 = ZooJdoHelper.schema(pm).getClass("MyClass"); assertNotNull(s6); pm.currentTransaction().rollback(); TestTools.closePM(); } public void testRemoveClassCommit() { PersistenceManager pm = TestTools.openPM(); //delete uncommitted pm.currentTransaction().begin(); ZooClass s1 = ZooJdoHelper.schema(pm).defineEmptyClass("MyClass"); s1.remove(); pm.currentTransaction().commit(); pm.currentTransaction().begin(); //delete committed ZooClass s3 = ZooJdoHelper.schema(pm).getClass("MyClass"); assertNull(s3); ZooClass s4 = ZooJdoHelper.schema(pm).defineEmptyClass("MyClass"); assertNotNull(s4); pm.currentTransaction().commit(); pm.currentTransaction().begin(); ZooClass s5 = ZooJdoHelper.schema(pm).getClass("MyClass"); s5.remove(); pm.currentTransaction().commit(); pm.currentTransaction().begin(); ZooClass s6 = ZooJdoHelper.schema(pm).getClass("MyClass"); assertNull(s6); pm.currentTransaction().rollback(); TestTools.closePM(); } @Test public void testRemoveFails() { TestTools.defineSchema(TestClassTiny.class); PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); //remove uncommitted ZooClass s1 = ZooJdoHelper.schema(pm).defineEmptyClass("MyClass"); s1.remove(); try { s1.remove(); fail(); } catch (IllegalStateException e) { //good } //remove committed ZooClass s2 = ZooJdoHelper.schema(pm).defineEmptyClass("MyClass2"); pm.currentTransaction().commit(); pm.currentTransaction().begin(); s2 = ZooJdoHelper.schema(pm).getClass("MyClass2"); s2.remove(); try { s2.remove(); fail(); } catch (IllegalStateException e) { //good } pm.currentTransaction().commit(); pm.currentTransaction().begin(); s2 = ZooJdoHelper.schema(pm).getClass("MyClass2"); assertNull(s2); pm.currentTransaction().rollback(); TestTools.closePM(); } @Test public void testRemoveHierarchy() { TestTools.defineSchema(TestClassTiny.class); String cName1 = "MyClassA"; String cName2 = "MyClassB"; PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); ZooClass s1 = ZooJdoHelper.schema(pm).defineEmptyClass(cName1, stt); ZooClass s2 = ZooJdoHelper.schema(pm).defineEmptyClass(cName2, s1); s1.removeWithSubClasses(); assertNull(ZooJdoHelper.schema(pm).getClass(cName1)); assertNull(ZooJdoHelper.schema(pm).getClass(cName2)); pm.currentTransaction().rollback(); //try again, this time with commit pm.currentTransaction().begin(); stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); s1 = ZooJdoHelper.schema(pm).defineEmptyClass(cName1, stt); s2 = ZooJdoHelper.schema(pm).defineEmptyClass(cName2, s1); pm.currentTransaction().commit(); TestTools.closePM(); //load and check again pm = TestTools.openPM(); pm.currentTransaction().begin(); stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); stt.removeWithSubClasses(); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); assertNull(s1); assertNull(s2); pm.currentTransaction().commit(); pm.currentTransaction().begin(); stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); assertNull(stt); assertNull(s1); assertNull(s2); pm.currentTransaction().commit(); TestTools.closePM(); } @Test public void testLocateClass() { TestTools.defineSchema(TestClassTiny.class); String cName1 = "MyClassA"; String cName2 = "MyClassB"; PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); assertNull(ZooJdoHelper.schema(pm).getClass(String.class)); assertNull(ZooJdoHelper.schema(pm).getClass((Class<?>)null)); assertNull(ZooJdoHelper.schema(pm).getClass((String)null)); assertNull(ZooJdoHelper.schema(pm).getClass("")); assertNull(ZooJdoHelper.schema(pm).getClass(" %% ")); ZooClass stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); ZooClass s1 = ZooJdoHelper.schema(pm).defineEmptyClass(cName1, stt); ZooClass s2 = ZooJdoHelper.schema(pm).defineEmptyClass(cName2, s1); assertTrue(stt == ZooJdoHelper.schema(pm).getClass(TestClassTiny.class)); assertTrue(s1 == ZooJdoHelper.schema(pm).getClass(cName1)); assertTrue(s2 == ZooJdoHelper.schema(pm).getClass(cName2)); pm.currentTransaction().rollback(); try { ZooJdoHelper.schema(pm).defineEmptyClass(cName1, stt); fail(); } catch(IllegalStateException e) { //good, pm is closed! } TestTools.closePM(); try { ZooJdoHelper.schema(pm).defineEmptyClass(cName1, stt); fail(); } catch(IllegalStateException e) { //good, pm is closed! } } @Test public void testGetAttribute() { TestTools.defineSchema(TestClassTiny.class); String cName1 = "MyClassA"; String cName2 = "MyClassB"; PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); ZooClass s1 = ZooJdoHelper.schema(pm).defineEmptyClass(cName1, stt); ZooClass s2 = ZooJdoHelper.schema(pm).defineEmptyClass(cName2, s1); assertTrue(s1.getAllFields().size() == 2); assertTrue(s1.getLocalFields().size() == 0); assertTrue(s2.getAllFields().size() == 2); assertTrue(s2.getLocalFields().size() == 0); assertNull(s1.getField("_int1")); assertNotNull(s1.getField("_int")); assertNotNull(s2.getField("_long")); s1.addField("_int1", Integer.TYPE); s1.addField("_long1", Long.TYPE); s2.addField("ref1", s1, 0); s2.addField("ref1Array", s1, 2); //check local fields checkFields(s1.getLocalFields(), "_int1", "_long1"); checkFields(s2.getLocalFields(), "ref1", "ref1Array"); //check all fields checkFields(s1.getAllFields(), "_int", "_long", "_int1", "_long1"); checkFields(s2.getAllFields(), "_int", "_long", "_int1", "_long1", "ref1", "ref1Array"); pm.currentTransaction().commit(); //try again pm.currentTransaction().begin(); stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); //check 1st class //check local fields checkFields(s1.getLocalFields(), "_int1", "_long1"); checkFields(s2.getLocalFields(), "ref1", "ref1Array"); //check all fields checkFields(s1.getAllFields(), "_int", "_long", "_int1", "_long1"); checkFields(s2.getAllFields(), "_int", "_long", "_int1", "_long1", "ref1", "ref1Array"); pm.currentTransaction().commit(); TestTools.closePM(); try { s1.getAllFields(); fail(); } catch (IllegalStateException e) { //good, pm is closed } try { s1.getLocalFields(); fail(); } catch (IllegalStateException e) { //good, pm is closed } } @Test public void testAddAttribute() { TestTools.defineSchema(TestClassTiny.class); String cName1 = "MyClassA"; String cName2 = "MyClassB"; PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); ZooClass s1 = ZooJdoHelper.schema(pm).defineEmptyClass(cName1, stt); ZooClass s2 = ZooJdoHelper.schema(pm).defineEmptyClass(cName2, s1); s1.addField("_int1", Integer.TYPE); s1.addField("_long1", Long.TYPE); s2.addField("ref1", s1, 0); s2.addField("ref1Array", s1, 2); //check local fields checkFields(s1.getLocalFields(), "_int1", "_long1"); checkFields(s2.getLocalFields(), "ref1", "ref1Array"); pm.currentTransaction().commit(); //try again pm.currentTransaction().begin(); stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); //check local fields checkFields(s1.getLocalFields(), "_int1", "_long1"); checkFields(s2.getLocalFields(), "ref1", "ref1Array"); pm.currentTransaction().commit(); TestTools.closePM(); //load and check again pm = TestTools.openPM(); pm.currentTransaction().begin(); stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); checkFields(s1.getLocalFields(), "_int1", "_long1"); checkFields(s2.getLocalFields(), "ref1", "ref1Array"); pm.currentTransaction().rollback(); TestTools.closePM(); } @Test public void testAddAttributeRollback() { TestTools.defineSchema(TestClassTiny.class); String cName1 = "MyClassA"; String cName2 = "MyClassB"; PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); ZooClass s1 = ZooJdoHelper.schema(pm).defineEmptyClass(cName1, stt); ZooClass s2 = ZooJdoHelper.schema(pm).defineEmptyClass(cName2, s1); pm.currentTransaction().commit(); pm.currentTransaction().begin(); s1.addField("_int1", Integer.TYPE); s2.addField("ref1", s1, 0); //check local fields checkFields(s1.getLocalFields(), "_int1"); checkFields(s2.getLocalFields(), "ref1"); pm.currentTransaction().rollback(); pm.currentTransaction().begin(); stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); //check local fields checkFields(s1.getLocalFields()); checkFields(s2.getLocalFields()); } @Test public void testAddAttributeFails() { TestTools.defineSchema(TestClassTiny.class); String cName1 = "MyClassA"; String cName2 = "MyClassB"; PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); ZooClass s1 = ZooJdoHelper.schema(pm).defineEmptyClass(cName1, stt); ZooClass s2 = ZooJdoHelper.schema(pm).defineEmptyClass(cName2, s1); s1.addField("_int1", Integer.TYPE); s1.addField("_long1", Long.TYPE); s2.addField("ref1", s1, 0); s2.addField("ref1Array", s1, 2); try { s1.addField("_long", Long.TYPE); fail(); } catch (IllegalArgumentException e) { //good, this name is already taken... } try { s1.addField("_long1", Long.TYPE); fail(); } catch (IllegalArgumentException e) { //good, this name is already taken... } try { s1.addField(null, Long.TYPE); fail(); } catch (IllegalArgumentException e) { //good, this name is invalid... } try { s1.addField("", Long.TYPE); fail(); } catch (IllegalArgumentException e) { //good, this name is invalid... } try { s1.addField("1_long1", Long.TYPE); fail(); } catch (IllegalArgumentException e) { //good, this name is invalid... } try { s1.addField("MyClass.x", Long.TYPE); fail(); } catch (IllegalArgumentException e) { //good, this name is invalid... } try { s1.addField("1_long1", null); fail(); } catch (IllegalArgumentException e) { //good, this type is invalid... } //check local fields checkFields(s1.getLocalFields(), "_int1", "_long1"); checkFields(s2.getLocalFields(), "ref1", "ref1Array"); pm.currentTransaction().commit(); TestTools.closePM(); try { s1.addField("xyz", Long.TYPE); fail(); } catch (IllegalStateException e) { //good, pm is closed } try { s1.addField("xyz2", Long.TYPE); fail(); } catch (IllegalStateException e) { //good, pm is closed } } @Test public void testRenameAttribute() { TestTools.defineSchema(TestClassTiny.class); String cName1 = "MyClassA"; String cName2 = "MyClassB"; PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); ZooClass s1 = ZooJdoHelper.schema(pm).defineEmptyClass(cName1, stt); ZooClass s2 = ZooJdoHelper.schema(pm).defineEmptyClass(cName2, s1); ZooField f11 = s1.addField("_int1", Integer.TYPE); ZooField f12 = s1.addField("_long1", Long.TYPE); ZooField f21 = s2.addField("ref1", s1, 0); ZooField f22 = s2.addField("ref1Array", s1, 2); f11.rename("_int11"); try { f12.rename("_long"); } catch (IllegalArgumentException e) { //good, this name is already taken... } try { f21.rename(""); } catch (IllegalArgumentException e) { //good, this name is invalid... } try { f22.rename("123_dhsak"); } catch (IllegalArgumentException e) { //good, this name is invalid... } //check local fields checkFields(s1.getLocalFields(), "_int11", "_long1"); checkFields(s2.getAllFields(), "_int", "_long", "_int11", "_long1", "ref1", "ref1Array"); pm.currentTransaction().commit(); //try again pm.currentTransaction().begin(); stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); //check local fields checkFields(s1.getLocalFields(), "_int11", "_long1"); checkFields(s2.getAllFields(), "_int", "_long", "_int11", "_long1", "ref1", "ref1Array"); s1.getField("_int11").rename("_int111"); checkFields(s1.getLocalFields(), "_int111", "_long1"); //rollback pm.currentTransaction().rollback(); pm.currentTransaction().begin(); //check again checkFields(s1.getLocalFields(), "_int11", "_long1"); checkFields(s2.getAllFields(), "_int", "_long", "_int11", "_long1", "ref1", "ref1Array"); pm.currentTransaction().rollback(); TestTools.closePM(); //load and check again pm = TestTools.openPM(); pm.currentTransaction().begin(); stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); checkFields(s1.getLocalFields(), "_int11", "_long1"); checkFields(s2.getAllFields(), "_int", "_long", "_int11", "_long1", "ref1", "ref1Array"); pm.currentTransaction().rollback(); TestTools.closePM(); try { s1.addField("xyz", Long.TYPE); fail(); } catch (IllegalStateException e) { //good, pm is closed } } @Test public void testRemoveAttribute() { TestTools.defineSchema(TestClassTiny.class); String cName1 = "MyClassA"; String cName2 = "MyClassB"; PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); ZooClass s1 = ZooJdoHelper.schema(pm).defineEmptyClass(cName1, stt); ZooClass s2 = ZooJdoHelper.schema(pm).defineEmptyClass(cName2, s1); try { s2.addField("_int", Long.TYPE); fail(); } catch (IllegalArgumentException e) { // good, field already exists in super-super class } ZooField f11 = s1.addField("_int1", Integer.TYPE); ZooField f12 = s1.addField("_long1", Long.TYPE); ZooField f13 = s1.addField("_long12", Long.TYPE); ZooField f21 = s2.addField("ref1", s1, 0); ZooField f22 = s2.addField("ref1Array", s1, 1); assertNotNull(f13); assertNotNull(f22); f11.remove(); s1.removeField(s1.getField("_long12")); s2.removeField(f21.getName()); List<ZooField> fields1 = s1.getLocalFields(); assertTrue(fields1.get(0).getName() == "_long1"); assertEquals(1, fields1.size()); List<ZooField> fields2 = s2.getLocalFields(); assertTrue(fields2.get(0).getName() == "ref1Array"); assertEquals(1, fields2.size()); checkFields(s1.getLocalFields(), "_long1"); checkFields(s2.getLocalFields(), "ref1Array"); checkFields(s1.getAllFields(), "_int", "_long", "_long1"); checkFields(s2.getAllFields(), "_int", "_long", "_long1", "ref1Array"); pm.currentTransaction().commit(); TestTools.closePM(); //load and check again pm = TestTools.openPM(); pm.currentTransaction().begin(); stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); checkFields(s1.getAllFields(), "_int", "_long", "_long1"); checkFields(s2.getAllFields(), "_int", "_long", "_long1", "ref1Array"); pm.currentTransaction().rollback(); TestTools.closePM(); try { f12.remove(); fail(); } catch (IllegalStateException e) { //good, pm is closed } } @Test public void testSchemaCountAbort() { String cName1 = "MyClassA"; String cName2 = "MyClassB"; PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); checkSchemaCount(pm, 0); ZooClass stt = ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); ZooClass s1 = ZooJdoHelper.schema(pm).defineEmptyClass(cName1, stt); ZooClass s2 = ZooJdoHelper.schema(pm).defineEmptyClass(cName2, s1); ZooField f1 = s2.addField("_int1", Integer.TYPE); f1.rename("_int1_1"); f1.remove(); pm.currentTransaction().rollback(); pm.currentTransaction().begin(); checkSchemaCount(pm, 0); pm.currentTransaction().rollback(); TestTools.closePM(); } @Test public void testSchemaCountCommit() { String cName1 = "MyClassA"; String cName2 = "MyClassB"; PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass stt = ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); ZooClass s1 = ZooJdoHelper.schema(pm).defineEmptyClass(cName1, stt); ZooClass s2 = ZooJdoHelper.schema(pm).defineEmptyClass(cName2, s1); ZooField f1 = s1.addField("_long1", Long.TYPE); f1.rename("_long_1_1"); ZooField f2 = s2.addField("_int1", Integer.TYPE); f2.rename("_int1_1"); f2.remove(); s2.remove(); pm.currentTransaction().commit(); pm.currentTransaction().begin(); checkSchemaCount(pm, 2); //test modify super-class stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); s1 = ZooJdoHelper.schema(pm).getClass(cName1); stt.addField("xyz", Long.TYPE); pm.currentTransaction().commit(); pm.currentTransaction().begin(); checkSchemaCount(pm, 4); //class and sub-class have new attribute //test add s1 = ZooJdoHelper.schema(pm).getClass(cName1); s1.addField("xyz2", Long.TYPE); pm.currentTransaction().commit(); pm.currentTransaction().begin(); checkSchemaCount(pm, 5); //class and sub-class have new attribute //test rename s1 = ZooJdoHelper.schema(pm).getClass(cName1); s1.getField("xyz2").rename("xyz3"); pm.currentTransaction().commit(); pm.currentTransaction().begin(); checkSchemaCount(pm, 5); //renaming does not create new version //test remove s1 = ZooJdoHelper.schema(pm).getClass(cName1); s1.getField("xyz3").remove(); pm.currentTransaction().commit(); pm.currentTransaction().begin(); checkSchemaCount(pm, 6); //class and sub-class have new attribute //test combo (should result in one change only) s1 = ZooJdoHelper.schema(pm).getClass(cName1); f1 = s1.addField("aaa", Long.TYPE); f1.rename("aaa2"); f2 = s1.addField("bbb", Long.TYPE); f2.rename("bbb2"); f2.remove(); pm.currentTransaction().commit(); pm.currentTransaction().begin(); checkSchemaCount(pm, 7); //class and sub-class have new attribute TestTools.closePM(); } @Test public void testSchemaCountOpenClose() { String cName1 = "MyClassA"; String cName2 = "MyClassB"; PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass stt = ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); ZooClass s1 = ZooJdoHelper.schema(pm).defineEmptyClass(cName1, stt); ZooClass s2 = ZooJdoHelper.schema(pm).defineEmptyClass(cName2, s1); ZooField f1 = s1.addField("_long1", Long.TYPE); f1.rename("_long_1_1"); ZooField f2 = s2.addField("_int1", Integer.TYPE); f2.rename("_int1_1"); f2.remove(); s2.remove(); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); checkSchemaCount(pm, 2); //test modify super-class stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); s1 = ZooJdoHelper.schema(pm).getClass(cName1); stt.addField("xyz", Long.TYPE); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); checkSchemaCount(pm, 4); //class and sub-class have new attribute //test add s1 = ZooJdoHelper.schema(pm).getClass(cName1); s1.addField("xyz2", Long.TYPE); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); checkSchemaCount(pm, 5); //class and sub-class have new attribute //test rename s1 = ZooJdoHelper.schema(pm).getClass(cName1); s1.getField("xyz2").rename("xyz3"); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); checkSchemaCount(pm, 5); //class and sub-class have new attribute //test remove s1 = ZooJdoHelper.schema(pm).getClass(cName1); s1.getField("xyz3").remove(); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); checkSchemaCount(pm, 6); //class and sub-class have new attribute //test combo (should result in one change only) s1 = ZooJdoHelper.schema(pm).getClass(cName1); f1 = s1.addField("aaa", Long.TYPE); f1.rename("aaa2"); f2 = s1.addField("bbb", Long.TYPE); f2.rename("bbb2"); f2.remove(); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); checkSchemaCount(pm, 7); //class and sub-class have new attribute TestTools.closePM(); } @Test public void testModifySubClassFirstWithClose() { String cName1 = "MyClassA"; String cName2 = "MyClassB"; PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass stt = ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); ZooClass s1 = ZooJdoHelper.schema(pm).defineEmptyClass(cName1, stt); ZooClass s2 = ZooJdoHelper.schema(pm).defineEmptyClass(cName2, s1); s1.addField("_long1", Long.TYPE); s2.addField("_int1", Integer.TYPE); pm.currentTransaction().commit(); pm.currentTransaction().begin(); checkSchemaCount(pm, 3); //test modify super-class stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); s2.addField("_f22", Long.TYPE); s1.addField("_f12", Long.TYPE); stt.addField("xyz", Long.TYPE); checkSchemaCount(pm, 6); //class and sub-class have new attribute checkFields(stt.getAllFields(), "_int", "_long", "xyz"); checkFields(s1.getAllFields(), "_int", "_long", "xyz", "_long1", "_f12"); checkFields(s2.getAllFields(), "_int", "_long", "xyz", "_long1", "_f12", "_int1", "_f22"); pm.currentTransaction().commit(); // try with closing session TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); checkSchemaCount(pm, 6); //class and sub-class have new attribute stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); assertEquals(1, stt.getSubClasses().size()); assertEquals(1, s1.getSubClasses().size()); assertEquals(0, s2.getSubClasses().size()); checkFields(stt.getAllFields(), "_int", "_long", "xyz"); checkFields(s1.getAllFields(), "_int", "_long", "xyz", "_long1", "_f12"); checkFields(s2.getAllFields(), "_int", "_long", "xyz", "_long1", "_f12", "_int1", "_f22"); pm.currentTransaction().commit(); TestTools.closePM(); } @Test public void testModify2ndSubClassFirstWithClose() { String cName1 = "MyClassA"; String cName2 = "MyClassB"; PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass stt = ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); ZooClass s1 = ZooJdoHelper.schema(pm).defineEmptyClass(cName1, stt); ZooClass s2 = ZooJdoHelper.schema(pm).defineEmptyClass(cName2, s1); s1.addField("_long1", Long.TYPE); s2.addField("_int1", Integer.TYPE); pm.currentTransaction().commit(); pm.currentTransaction().begin(); checkSchemaCount(pm, 3); //test modify super-class stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); s2.addField("_f22", Long.TYPE); stt.addField("xyz", Long.TYPE); checkSchemaCount(pm, 6); //class and sub-class have new attribute checkFields(stt.getAllFields(), "_int", "_long", "xyz"); checkFields(s1.getAllFields(), "_int", "_long", "xyz", "_long1"); checkFields(s2.getAllFields(), "_int", "_long", "xyz", "_long1", "_int1", "_f22"); pm.currentTransaction().commit(); // try with closing session TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); checkSchemaCount(pm, 6); //class and sub-class have new attribute stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); assertEquals(1, stt.getSubClasses().size()); assertEquals(1, s1.getSubClasses().size()); assertEquals(0, s2.getSubClasses().size()); checkFields(stt.getAllFields(), "_int", "_long", "xyz"); checkFields(s1.getAllFields(), "_int", "_long", "xyz", "_long1"); checkFields(s2.getAllFields(), "_int", "_long", "xyz", "_long1", "_int1", "_f22"); pm.currentTransaction().commit(); TestTools.closePM(); } @Test public void testModifySubClassFirstNoClose() { String cName1 = "MyClassA"; String cName2 = "MyClassB"; PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass stt = ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); ZooClass s1 = ZooJdoHelper.schema(pm).defineEmptyClass(cName1, stt); ZooClass s2 = ZooJdoHelper.schema(pm).defineEmptyClass(cName2, s1); s1.addField("_long1", Long.TYPE); s2.addField("_int1", Integer.TYPE); pm.currentTransaction().commit(); pm.currentTransaction().begin(); checkSchemaCount(pm, 3); //test modify super-class stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); s2.addField("_f22", Long.TYPE); s1.addField("_f12", Long.TYPE); stt.addField("xyz", Long.TYPE); checkSchemaCount(pm, 6); //class and sub-class have new attribute checkFields(stt.getAllFields(), "_int", "_long", "xyz"); checkFields(s1.getAllFields(), "_int", "_long", "xyz", "_long1", "_f12"); checkFields(s2.getAllFields(), "_int", "_long", "xyz", "_long1", "_f12", "_int1", "_f22"); pm.currentTransaction().commit(); // try with closing session pm.currentTransaction().begin(); checkSchemaCount(pm, 6); //class and sub-class have new attribute stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); assertEquals(1, stt.getSubClasses().size()); assertEquals(1, s1.getSubClasses().size()); assertEquals(0, s2.getSubClasses().size()); checkFields(stt.getAllFields(), "_int", "_long", "xyz"); checkFields(s1.getAllFields(), "_int", "_long", "xyz", "_long1", "_f12"); checkFields(s2.getAllFields(), "_int", "_long", "xyz", "_long1", "_f12", "_int1", "_f22"); pm.currentTransaction().commit(); TestTools.closePM(); } @Test public void testIndexPropagation() { String cName1 = "MyClassA"; String cName2 = "MyClassB"; PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass stt = ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); ZooClass s1 = ZooJdoHelper.schema(pm).defineEmptyClass(cName1, stt); ZooClass s2 = ZooJdoHelper.schema(pm).defineEmptyClass(cName2, s1); pm.currentTransaction().commit(); pm.currentTransaction().begin(); checkSchemaCount(pm, 3); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); s1.addField("_long1", Long.TYPE); s1.createIndex("_long1", true); s2.addField("_int1", Integer.TYPE); s2.createIndex("_int1", true); checkSchemaCount(pm, 5); //rollback and do it again pm.currentTransaction().rollback(); pm.currentTransaction().begin(); checkSchemaCount(pm, 3); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); s1.addField("_long1", Long.TYPE); s1.createIndex("_long1", true); s2.addField("_int1", Integer.TYPE); s2.createIndex("_int1", true); //close and reopen pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); checkSchemaCount(pm, 5); //test modify super-class stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); assertTrue(s1.hasIndex("_long1")); //This is not possible, current policy is that indexing works only through declaring class. assertTrue(s2.hasIndex("_long1")); assertTrue(s2.hasIndex("_int1")); assertEquals(Arrays.toString(stt.getSubClasses().toArray()), 1, stt.getSubClasses().size()); assertEquals(1, s1.getSubClasses().size()); assertEquals(0, s2.getSubClasses().size()); try { Query q = pm.newQuery("SELECT FROM " + cName1 + " WHERE _long1 > 0"); Collection<?> c = (Collection<?>) q.execute(); assertEquals(0, c.size()); } catch (JDOUserException e) { //good, class not found, cannot be materialised } Iterator<?> it = s1.getInstanceIterator(); assertFalse(it.hasNext()); pm.currentTransaction().commit(); TestTools.closePM(); } @Test public void testIndexPropagationViaFields() { String cName1 = "MyClassA"; String cName2 = "MyClassB"; PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass stt = ZooJdoHelper.schema(pm).addClass(TestClassTiny.class); ZooClass s1 = ZooJdoHelper.schema(pm).defineEmptyClass(cName1, stt); ZooClass s2 = ZooJdoHelper.schema(pm).defineEmptyClass(cName2, s1); pm.currentTransaction().commit(); pm.currentTransaction().begin(); checkSchemaCount(pm, 3); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); ZooField f1 = s1.addField("_long1", Long.TYPE); f1.createIndex(true); ZooField f2 = s2.addField("_int1", Integer.TYPE); f2.createIndex(true); checkSchemaCount(pm, 5); //rollback and do it again pm.currentTransaction().rollback(); pm.currentTransaction().begin(); checkSchemaCount(pm, 3); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); f1 = s1.addField("_long1", Long.TYPE); f1.createIndex(true); f2 = s2.addField("_int1", Integer.TYPE); f2.createIndex(false); //close and reopen pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); checkSchemaCount(pm, 5); //test modify super-class stt = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); assertTrue(s1.getField("_long1").hasIndex()); //This is not possible, current policy is that indexing works only through declaring class. assertTrue(s2.getField("_long1").hasIndex()); assertTrue(s2.getField("_long1").isIndexUnique()); assertTrue(s2.getField("_int1").hasIndex()); assertFalse(s2.getField("_int1").isIndexUnique()); assertEquals(Arrays.toString(stt.getSubClasses().toArray()), 1, stt.getSubClasses().size()); assertEquals(1, s1.getSubClasses().size()); assertEquals(0, s2.getSubClasses().size()); try { Query q = pm.newQuery("SELECT FROM " + cName1 + " WHERE _long1 > 0"); Collection<?> c = (Collection<?>) q.execute(); assertEquals(0, c.size()); } catch (JDOUserException e) { //good, class not found, cannot be materialised } Iterator<?> it = s1.getInstanceIterator(); assertFalse(it.hasNext()); //delete index s1.getField("_long1").removeIndex(); s2.getField("_int1").removeIndex(); assertFalse(s1.getField("_long1").hasIndex()); assertFalse(s2.getField("_long1").hasIndex()); assertFalse(s2.getField("_int1").hasIndex()); try { assertFalse(s2.getField("_int1").isIndexUnique()); fail(); } catch (JDOUserException e) { //no index defined } pm.currentTransaction().commit(); pm.currentTransaction().begin(); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s2 = ZooJdoHelper.schema(pm).getClass(cName2); assertFalse(s1.getField("_long1").hasIndex()); assertFalse(s2.getField("_long1").hasIndex()); assertFalse(s2.getField("_int1").hasIndex()); try { assertFalse(s2.getField("_int1").isIndexUnique()); fail(); } catch (JDOUserException e) { //no index defined } pm.currentTransaction().commit(); TestTools.closePM(); } @Test public void testConstructClass() { String cName1 = TestClassTiny.class.getName(); String cName2 = TestClassTiny2.class.getName(); PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass s1 = ZooJdoHelper.schema(pm).defineEmptyClass(cName1); ZooClass s2 = ZooJdoHelper.schema(pm).defineEmptyClass(cName2, s1); //interim commit tests that the Java class is associated only with the LATEST version, //other versions are usually incompatible. pm.currentTransaction().commit(); pm.currentTransaction().begin(); s1 = ZooJdoHelper.schema(pm).getClass(cName1); s1.addField("_int", Integer.TYPE); //interleave field creation with sub-class creation s2 = ZooJdoHelper.schema(pm).getClass(cName2); s1.addField("_long", Long.TYPE); //just for fun, trying reverse order... s2.addField("l2", Long.TYPE); s2.addField("i2", Integer.TYPE); pm.currentTransaction().commit(); TestTools.closePM(); pm = TestTools.openPM(); pm.currentTransaction().begin(); TestClassTiny t1 = new TestClassTiny(1,2); TestClassTiny2 t2 = new TestClassTiny2(3,4,5,6); pm.makePersistent(t1); pm.makePersistent(t2); Object oid1 = pm.getObjectId(t1); Object oid2 = pm.getObjectId(t2); pm.currentTransaction().commit(); pm.currentTransaction().begin(); //query Query q = pm.newQuery("SELECT FROM " + cName1 + " WHERE _long > 0"); Collection<?> c = (Collection<?>) q.execute(); assertEquals(2, c.size()); q.close(c); //extent Extent<TestClassTiny> ex1 = pm.getExtent(TestClassTiny.class, true); Iterator<TestClassTiny> ei = ex1.iterator(); int n = 0; while (ei.hasNext()) { TestClassTiny tct = ei.next(); assertTrue(tct.getInt() > 0); n++; } assertEquals(2, n); ex1.closeAll(); //oids t1 = (TestClassTiny) pm.getObjectById(oid1); assertEquals(2, t1.getLong()); t2 = (TestClassTiny2) pm.getObjectById(oid2); assertEquals(4, t2.getLong()); assertEquals(6, t2.getLong2()); pm.currentTransaction().commit(); TestTools.closePM(); } private void checkFields(List<ZooField> list, String ...names) { for (int i = 0; i < names.length; i++) { assertEquals(names[i], list.get(i).getName()); } assertEquals(names.length, list.size()); } private void checkSchemaCount(PersistenceManager pm, int expected) { Extent<?> e = pm.getExtent(ZooClassDef.class); int n = 0; for (Object o: e) { assertNotNull(o); n++; } assertEquals(SCHEMA_COUNT + expected, n); } @Test public void testSchemaHierarchyPageUse() { //test that allocating 10 schemas does not require too many pages int N = 10; PersistenceManager pm = TestTools.openPM(); pm.currentTransaction().begin(); ZooClass cls = ZooJdoHelper.schema(pm).defineEmptyClass("Sub"); pm.currentTransaction().commit(); pm.currentTransaction().begin(); long pageCount1 = ZooJdoHelper.getStatistics(pm).getStat(STATS.DB_PAGE_CNT); for (int i = 0; i < 10; i++) { cls = ZooJdoHelper.schema(pm).defineEmptyClass("Sub" + i, cls); } pm.currentTransaction().commit(); long pageCount2 = ZooJdoHelper.getStatistics(pm).getStat(STATS.DB_PAGE_CNT); TestTools.closePM(); assertTrue("n1 = " + pageCount1 + " n2 = " + pageCount2, pageCount2 <= pageCount1 + N + 2); } }