/*
* 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.assertTrue;
import static org.junit.Assert.fail;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import javax.jdo.JDOUserException;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.zoodb.jdo.ZooJdoHelper;
import org.zoodb.schema.ZooClass;
import org.zoodb.test.testutil.TestTools;
public class Test_090_IndexManagement {
@Before
public void setUp() {
TestTools.removeDb();
TestTools.createDb();
TestTools.defineSchema(TestClass.class);
}
@Test
public void testWithFreshIndex() {
//fresh DB w/o index
TestTools.removeDb();
TestTools.createDb();
PersistenceManager pm = TestTools.openPM();
pm.currentTransaction().begin();
ZooClass s = ZooJdoHelper.schema(pm).addClass(TestClass.class);
s.createIndex("_long", true);
assertTrue(s.hasIndex("_long"));
pm.currentTransaction().rollback();
pm.currentTransaction().begin();
s = ZooJdoHelper.schema(pm).addClass(TestClass.class);
assertFalse(s.hasIndex("_long"));
s.createIndex("_long", true);
pm.currentTransaction().commit();
pm.currentTransaction().begin();
assertTrue(s.removeIndex("_long"));
s.createIndex("_long", true);
assertTrue(s.removeIndex("_long"));
pm.currentTransaction().commit();
TestTools.closePM(pm);
}
/**
* This should check whether the processing of the schema operation queue works correctly.
*/
@Test
public void testTransient() {
//fresh DB w/o index
TestTools.removeDb();
TestTools.createDb();
PersistenceManager pm = TestTools.openPM();
pm.currentTransaction().begin();
ZooClass s = ZooJdoHelper.schema(pm).addClass(TestClass.class);
s.createIndex("_long", true);
assertTrue(s.removeIndex("_long"));
s.remove();
//TODO remove class as well in same transaction
pm.currentTransaction().commit();
TestTools.closePM(pm);
}
@Test
public void testNonExistentField() {
PersistenceManager pm = TestTools.openPM();
pm.currentTransaction().begin();
ZooClass s = ZooJdoHelper.schema(pm).getClass(TestClass.class);
try {
//non-existent field
s.removeIndex("xy!!z");
fail("Should have failed");
} catch (IllegalArgumentException e) {
//good
}
try {
//non-existent field
s.hasIndex("xy!!z");
fail("Should have failed");
} catch (IllegalArgumentException e) {
//good
}
try {
//non-existent field
s.isIndexUnique("xy!!z");
fail("Should have failed");
} catch (IllegalArgumentException e) {
//good
}
try {
//non-existent field
s.createIndex("xy!!z", true);
fail("Should have failed");
} catch (IllegalArgumentException e) {
//good
}
try {
//re-create existing index
s.createIndex("xy!!z", false);
fail("Should have failed");
} catch (IllegalArgumentException e) {
//good
}
try {
//non-existent field
s.removeIndex("xy!!z");
fail("Should have failed");
} catch (IllegalArgumentException e) {
//good
}
TestTools.closePM(pm);
}
@Test
public void testNonExistentIndex() {
PersistenceManager pm = TestTools.openPM();
pm.currentTransaction().begin();
ZooClass s = ZooJdoHelper.schema(pm).getClass(TestClass.class);
//non-existent index
assertFalse(s.removeIndex("_long"));
try {
//non-existent index
s.isIndexUnique("_long");
fail("Should have failed");
} catch (JDOUserException e) {
//good
}
assertFalse(s.hasIndex("_long"));
TestTools.closePM(pm);
}
@Test
public void testIndexCreationWithTx() {
PersistenceManager pm = TestTools.openPM();
pm.currentTransaction().begin();
ZooClass s = ZooJdoHelper.schema(pm).getClass(TestClass.class);
s.createIndex("_long", true);
assertTrue(s.hasIndex("_long"));
pm.currentTransaction().rollback();
pm.currentTransaction().begin();
assertFalse(s.hasIndex("_long"));
s.createIndex("_long", true);
assertTrue(s.hasIndex("_long"));
pm.currentTransaction().commit();
pm.currentTransaction().begin();
assertTrue(s.hasIndex("_long"));
pm.currentTransaction().rollback();
TestTools.closePM();
pm = TestTools.openPM();
pm.currentTransaction().begin();
s = ZooJdoHelper.schema(pm).getClass(TestClass.class);
assertTrue(s.hasIndex("_long"));
try {
//re-create existing index
s.createIndex("_long", true);
fail("Should have failed");
} catch (JDOUserException e) {
//good
}
pm.currentTransaction().rollback();
TestTools.closePM();
}
@Test
public void testIndexCreation() {
PersistenceManager pm = TestTools.openPM();
pm.currentTransaction().begin();
ZooClass s = ZooJdoHelper.schema(pm).getClass(TestClass.class);
s.createIndex("_long", true);
try {
//re-create existing index
s.createIndex("_long", true);
fail("Should have failed");
} catch (JDOUserException e) {
//good
}
try {
//re-create existing index
s.createIndex("_long", false);
fail("Should have failed");
} catch (JDOUserException e) {
//good
}
assertTrue(s.hasIndex("_long"));
assertTrue(s.isIndexUnique("_long"));
//remove
assertTrue(s.removeIndex("_long"));
assertFalse(s.hasIndex("_long"));
assertFalse(s.removeIndex("_long"));
//now try non-unique
s.createIndex("_long", false);
assertTrue(s.hasIndex("_long"));
assertFalse(s.isIndexUnique("_long"));
//remove again
s.removeIndex("_long");
assertFalse(s.hasIndex("_long"));
assertFalse(s.removeIndex("_long"));
TestTools.closePM(pm);
}
@Test
public void testIndexCreationWithExitingObjects() {
createData();
PersistenceManager pm = TestTools.openPM();
pm.currentTransaction().begin();
ZooClass s = ZooJdoHelper.schema(pm).getClass(TestClass.class);
s.createIndex("_long", true);
try {
//re-create existing index
s.createIndex("_long", true);
fail("Should have failed");
} catch (JDOUserException e) {
//good
}
try {
//re-create existing index
s.createIndex("_long", false);
fail("Should have failed");
} catch (JDOUserException e) {
//good
}
assertTrue(s.hasIndex("_long"));
assertTrue(s.isIndexUnique("_long"));
//remove
assertTrue(s.removeIndex("_long"));
assertFalse(s.hasIndex("_long"));
assertFalse(s.removeIndex("_long"));
//now try non-unique
s.createIndex("_long", false);
assertTrue(s.hasIndex("_long"));
assertFalse(s.isIndexUnique("_long"));
//remove again
assertTrue(s.removeIndex("_long"));
assertFalse(s.hasIndex("_long"));
assertFalse(s.removeIndex("_long"));
TestTools.closePM(pm);
}
private void createData() {
PersistenceManager pm = TestTools.openPM();
pm.currentTransaction().begin();
TestClass tc1 = new TestClass();
tc1.setData(1, false, 'c', (byte)127, (short)32000, 1234567890L, "xyz", new byte[]{1,2},
-1.1f, 35);
pm.makePersistent(tc1);
tc1 = new TestClass();
tc1.setData(12, false, 'd', (byte)127, (short)32000, 1234567890L, "xyz", new byte[]{1,2},
-0.1f, 3);
pm.makePersistent(tc1);
tc1 = new TestClass();
tc1.setData(123, false, 'e', (byte)127, (short)32000, 1234567890L, "xyz", new byte[]{1,2},
0.f, -3.5);
pm.makePersistent(tc1);
tc1 = new TestClass();
tc1.setData(1234, false, 'f', (byte)127, (short)32000, 1234567890L, "xyz", new byte[]{1,2},
1.1f, -35);
pm.makePersistent(tc1);
tc1 = new TestClass();
tc1.setData(12345, false, 'g', (byte)127, (short)32000, 1234567890L, "xyz", new byte[]{1,2},
21.1f, -335);
pm.makePersistent(tc1);
pm.currentTransaction().commit();
TestTools.closePM();
}
@Test
public void testIndexCreationWithDifferentTypes() {
createData();
PersistenceManager pm = TestTools.openPM();
pm.currentTransaction().begin();
ZooClass s = ZooJdoHelper.schema(pm).getClass(TestClass.class);
s.createIndex("_int", false);
s.createIndex("_long", false);
s.createIndex("_char", false);
s.createIndex("_byte", false);
s.createIndex("_short", false);
s.createIndex("_string", false);
s.createIndex("_float", false);
s.createIndex("_double", false);
s.createIndex("_ref2", false);
// not indexable
checkThatDefinitionFails(pm, s, "_bool");
// array of primitive
checkThatDefinitionFails(pm, s, "_bArray");
// object
checkThatDefinitionFails(pm, s, "_intObj");
// static primitive
checkThatDefinitionFails(pm, s, "_staticInt");
// static string
checkThatDefinitionFails(pm, s, "_staticString");
// transient primitive
checkThatDefinitionFails(pm, s, "_transientInt");
// transient string
checkThatDefinitionFails(pm, s, "_transientString");
// object ref
checkThatDefinitionFails(pm, s, "_object");
//object/pers ref
checkThatDefinitionFails(pm, s, "_ref1");
TestTools.closePM(pm);
}
private void checkThatDefinitionFails(PersistenceManager pm, ZooClass s, String name) {
try {
//re-create existing index
s.createIndex(name, true);
fail("Should have failed: " + name);
} catch (IllegalArgumentException e) {
//good
}
pm.currentTransaction().commit();
pm.currentTransaction().begin();
}
@Test
public void testIndexCreationUniqueOnNonUniqeData() {
createData();
PersistenceManager pm = TestTools.openPM();
pm.currentTransaction().begin();
TestClass tc1 = new TestClass();
tc1.setInt(200);
pm.makePersistent(tc1);
tc1 = new TestClass();
tc1.setInt(200);
pm.makePersistent(tc1);
pm.currentTransaction().commit();
pm.currentTransaction().begin();
ZooClass s = ZooJdoHelper.schema(pm).getClass(TestClass.class);
s.createIndex("_int", true);
try {
pm.currentTransaction().commit();
fail();
} catch (JDOUserException e) {
//should fail because of non-unique data
}
TestTools.closePM(pm);
}
@Test
public void testIndexPropagationInClassHierarchy() {
PersistenceManager pm = TestTools.openPM();
pm.currentTransaction().begin();
ZooClass s1 = ZooJdoHelper.schema(pm).addClass(TestClassTiny.class);
ZooClass s2 = ZooJdoHelper.schema(pm).addClass(TestClassTiny2.class);
pm.currentTransaction().commit();
pm.currentTransaction().begin();
s1 = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class);
s2 = ZooJdoHelper.schema(pm).getClass(TestClassTiny2.class);
s1.createIndex("_long", true);
s2.createIndex("_int", true);
//rollback and do it again
pm.currentTransaction().rollback();
pm.currentTransaction().begin();
s1 = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class);
s2 = ZooJdoHelper.schema(pm).getClass(TestClassTiny2.class);
s1.createIndex("_long", true);
s2.createIndex("_int", true);
//close and reopen
pm.currentTransaction().commit();
TestTools.closePM();
pm = TestTools.openPM();
pm.currentTransaction().begin();
//test modify super-class
s1 = ZooJdoHelper.schema(pm).getClass(TestClassTiny.class);
s2 = ZooJdoHelper.schema(pm).getClass(TestClassTiny2.class);
assertTrue(s1.hasIndex("_long"));
//This is not possible, current policy is that indexing works only through declaring class.
assertTrue(s2.hasIndex("_long"));
assertTrue(s2.hasIndex("_int"));
assertEquals(Arrays.toString(s1.getSubClasses().toArray()), 1, s1.getSubClasses().size());
assertEquals(1, s1.getSubClasses().size());
assertEquals(0, s2.getSubClasses().size());
try {
Query q = pm.newQuery("SELECT FROM " + s1.getName() + " 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();
}
@After
public void afterTest() {
TestTools.closePM();
TestTools.removeDb();
}
}