summaryrefslogtreecommitdiff
path: root/db-4.8.30/test/scr024/src/com/sleepycat/persist
diff options
context:
space:
mode:
authorJesse Morgan <jesse@jesterpm.net>2016-12-17 21:28:53 -0800
committerJesse Morgan <jesse@jesterpm.net>2016-12-17 21:28:53 -0800
commit54df2afaa61c6a03cbb4a33c9b90fa572b6d07b8 (patch)
tree18147b92b969d25ffbe61935fb63035cac820dd0 /db-4.8.30/test/scr024/src/com/sleepycat/persist
Berkeley DB 4.8 with rust build script for linux.
Diffstat (limited to 'db-4.8.30/test/scr024/src/com/sleepycat/persist')
-rw-r--r--db-4.8.30/test/scr024/src/com/sleepycat/persist/test/BindingTest.java2425
-rw-r--r--db-4.8.30/test/scr024/src/com/sleepycat/persist/test/Enhanced0.java36
-rw-r--r--db-4.8.30/test/scr024/src/com/sleepycat/persist/test/Enhanced1.java260
-rw-r--r--db-4.8.30/test/scr024/src/com/sleepycat/persist/test/Enhanced2.java110
-rw-r--r--db-4.8.30/test/scr024/src/com/sleepycat/persist/test/Enhanced3.java176
-rw-r--r--db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveCase.java205
-rw-r--r--db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveClasses.java6818
-rw-r--r--db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveClasses.java.original2855
-rw-r--r--db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveTest.java255
-rw-r--r--db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveTestBase.java438
-rw-r--r--db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveTestInit.java53
-rw-r--r--db-4.8.30/test/scr024/src/com/sleepycat/persist/test/ForeignKeyTest.java329
-rw-r--r--db-4.8.30/test/scr024/src/com/sleepycat/persist/test/IndexTest.java874
-rw-r--r--db-4.8.30/test/scr024/src/com/sleepycat/persist/test/JoinTest.java176
-rw-r--r--db-4.8.30/test/scr024/src/com/sleepycat/persist/test/NegativeTest.java644
-rw-r--r--db-4.8.30/test/scr024/src/com/sleepycat/persist/test/OperationTest.java1552
-rw-r--r--db-4.8.30/test/scr024/src/com/sleepycat/persist/test/PersistTestUtils.java49
-rw-r--r--db-4.8.30/test/scr024/src/com/sleepycat/persist/test/SequenceTest.java469
-rw-r--r--db-4.8.30/test/scr024/src/com/sleepycat/persist/test/SubclassIndexTest.java251
19 files changed, 17975 insertions, 0 deletions
diff --git a/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/BindingTest.java b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/BindingTest.java
new file mode 100644
index 0000000..504014e
--- /dev/null
+++ b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/BindingTest.java
@@ -0,0 +1,2425 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2002-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package com.sleepycat.persist.test;
+
+import static com.sleepycat.persist.model.Relationship.MANY_TO_ONE;
+import static com.sleepycat.persist.model.Relationship.ONE_TO_MANY;
+import static com.sleepycat.persist.model.Relationship.ONE_TO_ONE;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import junit.framework.TestCase;
+
+import com.sleepycat.bind.EntryBinding;
+import com.sleepycat.compat.DbCompat;
+import com.sleepycat.db.DatabaseConfig;
+import com.sleepycat.db.DatabaseEntry;
+import com.sleepycat.db.DatabaseException;
+import com.sleepycat.db.Environment;
+import com.sleepycat.db.EnvironmentConfig;
+import com.sleepycat.db.ForeignMultiKeyNullifier;
+import com.sleepycat.db.SecondaryKeyCreator;
+import com.sleepycat.db.SecondaryMultiKeyCreator;
+import com.sleepycat.persist.impl.PersistCatalog;
+import com.sleepycat.persist.impl.PersistComparator;
+import com.sleepycat.persist.impl.PersistEntityBinding;
+import com.sleepycat.persist.impl.PersistKeyBinding;
+import com.sleepycat.persist.impl.PersistKeyCreator;
+import com.sleepycat.persist.impl.SimpleCatalog;
+import com.sleepycat.persist.model.AnnotationModel;
+import com.sleepycat.persist.model.ClassMetadata;
+import com.sleepycat.persist.model.Entity;
+import com.sleepycat.persist.model.EntityMetadata;
+import com.sleepycat.persist.model.EntityModel;
+import com.sleepycat.persist.model.KeyField;
+import com.sleepycat.persist.model.Persistent;
+import com.sleepycat.persist.model.PersistentProxy;
+import com.sleepycat.persist.model.PrimaryKey;
+import com.sleepycat.persist.model.PrimaryKeyMetadata;
+import com.sleepycat.persist.model.SecondaryKey;
+import com.sleepycat.persist.model.SecondaryKeyMetadata;
+import com.sleepycat.persist.raw.RawField;
+import com.sleepycat.persist.raw.RawObject;
+import com.sleepycat.persist.raw.RawType;
+import com.sleepycat.util.test.SharedTestUtils;
+import com.sleepycat.util.test.TestEnv;
+
+/**
+ * @author Mark Hayes
+ */
+public class BindingTest extends TestCase {
+
+ private static final String STORE_PREFIX = "persist#foo#";
+
+ private File envHome;
+ private Environment env;
+ private EntityModel model;
+ private PersistCatalog catalog;
+ private DatabaseEntry keyEntry;
+ private DatabaseEntry dataEntry;
+
+ @Override
+ public void setUp() {
+ envHome = new File(System.getProperty(SharedTestUtils.DEST_DIR));
+ SharedTestUtils.emptyDir(envHome);
+ keyEntry = new DatabaseEntry();
+ dataEntry = new DatabaseEntry();
+ }
+
+ @Override
+ public void tearDown() {
+ if (env != null) {
+ try {
+ env.close();
+ } catch (Exception e) {
+ System.out.println("During tearDown: " + e);
+ }
+ }
+ envHome = null;
+ env = null;
+ catalog = null;
+ keyEntry = null;
+ dataEntry = null;
+ }
+
+ /**
+ * @throws FileNotFoundException from DB core.
+ */
+ private void open()
+ throws FileNotFoundException, DatabaseException {
+
+ EnvironmentConfig envConfig = TestEnv.BDB.getConfig();
+ envConfig.setAllowCreate(true);
+ env = new Environment(envHome, envConfig);
+ openCatalog();
+ }
+
+ private void openCatalog()
+ throws DatabaseException {
+
+ model = new AnnotationModel();
+ model.registerClass(LocalizedTextProxy.class);
+ model.registerClass(LocaleProxy.class);
+
+ DatabaseConfig dbConfig = new DatabaseConfig();
+ dbConfig.setAllowCreate(true);
+ DbCompat.setTypeBtree(dbConfig);
+ catalog = new PersistCatalog
+ (null, env, STORE_PREFIX, STORE_PREFIX + "catalog", dbConfig,
+ model, null, false /*rawAccess*/, null /*Store*/);
+ }
+
+ private void close()
+ throws DatabaseException {
+
+ /* Close/open/close catalog to test checks for class evolution. */
+ catalog.close();
+ PersistCatalog.expectNoClassChanges = true;
+ try {
+ openCatalog();
+ } finally {
+ PersistCatalog.expectNoClassChanges = false;
+ }
+ catalog.close();
+ catalog = null;
+
+ env.close();
+ env = null;
+ }
+
+ public void testBasic()
+ throws FileNotFoundException, DatabaseException {
+
+ open();
+
+ checkEntity(Basic.class,
+ new Basic(1, "one", 2.2, "three"));
+ checkEntity(Basic.class,
+ new Basic(0, null, 0, null));
+ checkEntity(Basic.class,
+ new Basic(-1, "xxx", -2, "xxx"));
+
+ checkMetadata(Basic.class.getName(), new String[][] {
+ {"id", "long"},
+ {"one", "java.lang.String"},
+ {"two", "double"},
+ {"three", "java.lang.String"},
+ },
+ 0 /*priKeyIndex*/, null);
+
+ close();
+ }
+
+ @Entity
+ static class Basic implements MyEntity {
+
+ @PrimaryKey
+ private long id;
+ private String one;
+ private double two;
+ private String three;
+
+ private Basic() { }
+
+ private Basic(long id, String one, double two, String three) {
+ this.id = id;
+ this.one = one;
+ this.two = two;
+ this.three = three;
+ }
+
+ public String getBasicOne() {
+ return one;
+ }
+
+ public Object getPriKeyObject() {
+ return id;
+ }
+
+ public void validate(Object other) {
+ Basic o = (Basic) other;
+ TestCase.assertEquals(id, o.id);
+ TestCase.assertTrue(nullOrEqual(one, o.one));
+ TestCase.assertEquals(two, o.two);
+ TestCase.assertTrue(nullOrEqual(three, o.three));
+ if (one == three) {
+ TestCase.assertSame(o.one, o.three);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "" + id + ' ' + one + ' ' + two;
+ }
+ }
+
+ public void testSimpleTypes()
+ throws FileNotFoundException, DatabaseException {
+
+ open();
+
+ checkEntity(SimpleTypes.class, new SimpleTypes());
+
+ checkMetadata(SimpleTypes.class.getName(), new String[][] {
+ {"f0", "boolean"},
+ {"f1", "char"},
+ {"f2", "byte"},
+ {"f3", "short"},
+ {"f4", "int"},
+ {"f5", "long"},
+ {"f6", "float"},
+ {"f7", "double"},
+ {"f8", "java.lang.String"},
+ {"f9", "java.math.BigInteger"},
+ //{"f10", "java.math.BigDecimal"},
+ {"f11", "java.util.Date"},
+ {"f12", "java.lang.Boolean"},
+ {"f13", "java.lang.Character"},
+ {"f14", "java.lang.Byte"},
+ {"f15", "java.lang.Short"},
+ {"f16", "java.lang.Integer"},
+ {"f17", "java.lang.Long"},
+ {"f18", "java.lang.Float"},
+ {"f19", "java.lang.Double"},
+ },
+ 0 /*priKeyIndex*/, null);
+
+ close();
+ }
+
+ @Entity
+ static class SimpleTypes implements MyEntity {
+
+ @PrimaryKey
+ private final boolean f0 = true;
+ private final char f1 = 'a';
+ private final byte f2 = 123;
+ private final short f3 = 123;
+ private final int f4 = 123;
+ private final long f5 = 123;
+ private final float f6 = 123.4f;
+ private final double f7 = 123.4;
+ private final String f8 = "xxx";
+ private final BigInteger f9 = BigInteger.valueOf(123);
+ //private BigDecimal f10 = BigDecimal.valueOf(123.4);
+ private final Date f11 = new Date();
+ private final Boolean f12 = true;
+ private final Character f13 = 'a';
+ private final Byte f14 = 123;
+ private final Short f15 = 123;
+ private final Integer f16 = 123;
+ private final Long f17 = 123L;
+ private final Float f18 = 123.4f;
+ private final Double f19 = 123.4;
+
+ SimpleTypes() { }
+
+ public Object getPriKeyObject() {
+ return f0;
+ }
+
+ public void validate(Object other) {
+ SimpleTypes o = (SimpleTypes) other;
+ TestCase.assertEquals(f0, o.f0);
+ TestCase.assertEquals(f1, o.f1);
+ TestCase.assertEquals(f2, o.f2);
+ TestCase.assertEquals(f3, o.f3);
+ TestCase.assertEquals(f4, o.f4);
+ TestCase.assertEquals(f5, o.f5);
+ TestCase.assertEquals(f6, o.f6);
+ TestCase.assertEquals(f7, o.f7);
+ TestCase.assertEquals(f8, o.f8);
+ TestCase.assertEquals(f9, o.f9);
+ //TestCase.assertEquals(f10, o.f10);
+ TestCase.assertEquals(f11, o.f11);
+ TestCase.assertEquals(f12, o.f12);
+ TestCase.assertEquals(f13, o.f13);
+ TestCase.assertEquals(f14, o.f14);
+ TestCase.assertEquals(f15, o.f15);
+ TestCase.assertEquals(f16, o.f16);
+ TestCase.assertEquals(f17, o.f17);
+ TestCase.assertEquals(f18, o.f18);
+ TestCase.assertEquals(f19, o.f19);
+ }
+ }
+
+ public void testArrayTypes()
+ throws FileNotFoundException, DatabaseException {
+
+ open();
+
+ checkEntity(ArrayTypes.class, new ArrayTypes());
+
+ checkMetadata(ArrayTypes.class.getName(), new String[][] {
+ {"id", "int"},
+ {"f0", boolean[].class.getName()},
+ {"f1", char[].class.getName()},
+ {"f2", byte[].class.getName()},
+ {"f3", short[].class.getName()},
+ {"f4", int[].class.getName()},
+ {"f5", long[].class.getName()},
+ {"f6", float[].class.getName()},
+ {"f7", double[].class.getName()},
+ {"f8", String[].class.getName()},
+ {"f9", Address[].class.getName()},
+ {"f10", boolean[][][].class.getName()},
+ {"f11", String[][][].class.getName()},
+ },
+ 0 /*priKeyIndex*/, null);
+
+ close();
+ }
+
+ @Entity
+ static class ArrayTypes implements MyEntity {
+
+ @PrimaryKey
+ private final int id = 1;
+ private final boolean[] f0 = {false, true};
+ private final char[] f1 = {'a', 'b'};
+ private final byte[] f2 = {1, 2};
+ private final short[] f3 = {1, 2};
+ private final int[] f4 = {1, 2};
+ private final long[] f5 = {1, 2};
+ private final float[] f6 = {1.1f, 2.2f};
+ private final double[] f7 = {1.1, 2,2};
+ private final String[] f8 = {"xxx", null, "yyy"};
+ private final Address[] f9 = {new Address("city", "state", 123),
+ null,
+ new Address("x", "y", 444)};
+ private final boolean[][][] f10 =
+ {
+ {
+ {false, true},
+ {false, true},
+ },
+ null,
+ {
+ {false, true},
+ {false, true},
+ },
+ };
+ private final String[][][] f11 =
+ {
+ {
+ {"xxx", null, "yyy"},
+ null,
+ {"xxx", null, "yyy"},
+ },
+ null,
+ {
+ {"xxx", null, "yyy"},
+ null,
+ {"xxx", null, "yyy"},
+ },
+ };
+
+ ArrayTypes() { }
+
+ public Object getPriKeyObject() {
+ return id;
+ }
+
+ public void validate(Object other) {
+ ArrayTypes o = (ArrayTypes) other;
+ TestCase.assertEquals(id, o.id);
+ TestCase.assertTrue(Arrays.equals(f0, o.f0));
+ TestCase.assertTrue(Arrays.equals(f1, o.f1));
+ TestCase.assertTrue(Arrays.equals(f2, o.f2));
+ TestCase.assertTrue(Arrays.equals(f3, o.f3));
+ TestCase.assertTrue(Arrays.equals(f4, o.f4));
+ TestCase.assertTrue(Arrays.equals(f5, o.f5));
+ TestCase.assertTrue(Arrays.equals(f6, o.f6));
+ TestCase.assertTrue(Arrays.equals(f7, o.f7));
+ TestCase.assertTrue(Arrays.equals(f8, o.f8));
+ TestCase.assertTrue(Arrays.deepEquals(f9, o.f9));
+ TestCase.assertTrue(Arrays.deepEquals(f10, o.f10));
+ TestCase.assertTrue(Arrays.deepEquals(f11, o.f11));
+ }
+ }
+
+ public void testEnumTypes()
+ throws FileNotFoundException, DatabaseException {
+
+ open();
+
+ checkEntity(EnumTypes.class, new EnumTypes());
+
+ checkMetadata(EnumTypes.class.getName(), new String[][] {
+ {"f0", "int"},
+ {"f1", Thread.State.class.getName()},
+ {"f2", MyEnum.class.getName()},
+ {"f3", Object.class.getName()},
+ },
+ 0 /*priKeyIndex*/, null);
+
+ close();
+ }
+
+ enum MyEnum { ONE, TWO };
+
+ @Entity
+ static class EnumTypes implements MyEntity {
+
+ @PrimaryKey
+ private final int f0 = 1;
+ private final Thread.State f1 = Thread.State.RUNNABLE;
+ private final MyEnum f2 = MyEnum.ONE;
+ private final Object f3 = MyEnum.TWO;
+
+ EnumTypes() { }
+
+ public Object getPriKeyObject() {
+ return f0;
+ }
+
+ public void validate(Object other) {
+ EnumTypes o = (EnumTypes) other;
+ TestCase.assertEquals(f0, o.f0);
+ TestCase.assertSame(f1, o.f1);
+ TestCase.assertSame(f2, o.f2);
+ TestCase.assertSame(f3, o.f3);
+ }
+ }
+
+ public void testProxyTypes()
+ throws FileNotFoundException, DatabaseException {
+
+ open();
+
+ checkEntity(ProxyTypes.class, new ProxyTypes());
+
+ checkMetadata(ProxyTypes.class.getName(), new String[][] {
+ {"f0", "int"},
+ {"f1", Locale.class.getName()},
+ {"f2", Set.class.getName()},
+ {"f3", Set.class.getName()},
+ {"f4", Object.class.getName()},
+ {"f5", HashMap.class.getName()},
+ {"f6", TreeMap.class.getName()},
+ {"f7", List.class.getName()},
+ {"f8", LinkedList.class.getName()},
+ {"f9", LocalizedText.class.getName()},
+ },
+ 0 /*priKeyIndex*/, null);
+
+ close();
+ }
+
+ @Entity
+ static class ProxyTypes implements MyEntity {
+
+ @PrimaryKey
+ private final int f0 = 1;
+ private final Locale f1 = Locale.getDefault();
+ private final Set<Integer> f2 = new HashSet<Integer>();
+ private final Set<Integer> f3 = new TreeSet<Integer>();
+ private final Object f4 = new HashSet<Address>();
+ private final HashMap<String,Integer> f5 =
+ new HashMap<String,Integer>();
+ private final TreeMap<String,Address> f6 =
+ new TreeMap<String,Address>();
+ private final List<Integer> f7 = new ArrayList<Integer>();
+ private final LinkedList<Integer> f8 = new LinkedList<Integer>();
+ private final LocalizedText f9 = new LocalizedText(f1, "xyz");
+
+ ProxyTypes() {
+ f2.add(123);
+ f2.add(456);
+ f3.add(456);
+ f3.add(123);
+ HashSet<Address> s = (HashSet) f4;
+ s.add(new Address("city", "state", 11111));
+ s.add(new Address("city2", "state2", 22222));
+ s.add(new Address("city3", "state3", 33333));
+ f5.put("one", 111);
+ f5.put("two", 222);
+ f5.put("three", 333);
+ f6.put("one", new Address("city", "state", 11111));
+ f6.put("two", new Address("city2", "state2", 22222));
+ f6.put("three", new Address("city3", "state3", 33333));
+ f7.add(123);
+ f7.add(456);
+ f8.add(123);
+ f8.add(456);
+ }
+
+ public Object getPriKeyObject() {
+ return f0;
+ }
+
+ public void validate(Object other) {
+ ProxyTypes o = (ProxyTypes) other;
+ TestCase.assertEquals(f0, o.f0);
+ TestCase.assertEquals(f1, o.f1);
+ TestCase.assertEquals(f2, o.f2);
+ TestCase.assertEquals(f3, o.f3);
+ TestCase.assertEquals(f4, o.f4);
+ TestCase.assertEquals(f5, o.f5);
+ TestCase.assertEquals(f6, o.f6);
+ TestCase.assertEquals(f7, o.f7);
+ TestCase.assertEquals(f8, o.f8);
+ TestCase.assertEquals(f9, o.f9);
+ }
+ }
+
+ @Persistent(proxyFor=Locale.class)
+ static class LocaleProxy implements PersistentProxy<Locale> {
+
+ String language;
+ String country;
+ String variant;
+
+ private LocaleProxy() {}
+
+ public void initializeProxy(Locale object) {
+ language = object.getLanguage();
+ country = object.getCountry();
+ variant = object.getVariant();
+ }
+
+ public Locale convertProxy() {
+ return new Locale(language, country, variant);
+ }
+ }
+
+ static class LocalizedText {
+
+ Locale locale;
+ String text;
+
+ LocalizedText(Locale locale, String text) {
+ this.locale = locale;
+ this.text = text;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ LocalizedText o = (LocalizedText) other;
+ return text.equals(o.text) &&
+ locale.equals(o.locale);
+ }
+ }
+
+ @Persistent(proxyFor=LocalizedText.class)
+ static class LocalizedTextProxy implements PersistentProxy<LocalizedText> {
+
+ Locale locale;
+ String text;
+
+ private LocalizedTextProxy() {}
+
+ public void initializeProxy(LocalizedText object) {
+ locale = object.locale;
+ text = object.text;
+ }
+
+ public LocalizedText convertProxy() {
+ return new LocalizedText(locale, text);
+ }
+ }
+
+ public void testEmbedded()
+ throws FileNotFoundException, DatabaseException {
+
+ open();
+
+ Address a1 = new Address("city", "state", 123);
+ Address a2 = new Address("Wikieup", "AZ", 85360);
+
+ checkEntity(Embedded.class,
+ new Embedded("x", a1, a2));
+ checkEntity(Embedded.class,
+ new Embedded("y", a1, null));
+ checkEntity(Embedded.class,
+ new Embedded("", a2, a2));
+
+ checkMetadata(Embedded.class.getName(), new String[][] {
+ {"id", "java.lang.String"},
+ {"idShadow", "java.lang.String"},
+ {"one", Address.class.getName()},
+ {"two", Address.class.getName()},
+ },
+ 0 /*priKeyIndex*/, null);
+
+ checkMetadata(Address.class.getName(), new String[][] {
+ {"street", "java.lang.String"},
+ {"city", "java.lang.String"},
+ {"zip", "int"},
+ },
+ -1 /*priKeyIndex*/, null);
+
+ close();
+ }
+
+ @Entity
+ static class Embedded implements MyEntity {
+
+ @PrimaryKey
+ private String id;
+ private String idShadow;
+ private Address one;
+ private Address two;
+
+ private Embedded() { }
+
+ private Embedded(String id, Address one, Address two) {
+ this.id = id;
+ idShadow = id;
+ this.one = one;
+ this.two = two;
+ }
+
+ public Object getPriKeyObject() {
+ return id;
+ }
+
+ public void validate(Object other) {
+ Embedded o = (Embedded) other;
+ TestCase.assertEquals(id, o.id);
+ if (one != null) {
+ one.validate(o.one);
+ } else {
+ assertNull(o.one);
+ }
+ if (two != null) {
+ two.validate(o.two);
+ } else {
+ assertNull(o.two);
+ }
+ TestCase.assertSame(o.id, o.idShadow);
+ if (one == two) {
+ TestCase.assertSame(o.one, o.two);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "" + id + ' ' + one + ' ' + two;
+ }
+ }
+
+ @Persistent
+ static class Address {
+
+ private String street;
+ private String city;
+ private int zip;
+
+ private Address() {}
+
+ Address(String street, String city, int zip) {
+ this.street = street;
+ this.city = city;
+ this.zip = zip;
+ }
+
+ void validate(Address o) {
+ TestCase.assertTrue(nullOrEqual(street, o.street));
+ TestCase.assertTrue(nullOrEqual(city, o.city));
+ TestCase.assertEquals(zip, o.zip);
+ }
+
+ @Override
+ public String toString() {
+ return "" + street + ' ' + city + ' ' + zip;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == null) {
+ return false;
+ }
+ Address o = (Address) other;
+ return nullOrEqual(street, o.street) &&
+ nullOrEqual(city, o.city) &&
+ nullOrEqual(zip, o.zip);
+ }
+
+ @Override
+ public int hashCode() {
+ return zip;
+ }
+ }
+
+ public void testSubclass()
+ throws FileNotFoundException, DatabaseException {
+
+ open();
+
+ checkEntity(Basic.class,
+ new Subclass(-1, "xxx", -2, "xxx", "xxx", true));
+
+ checkMetadata(Basic.class.getName(), new String[][] {
+ {"id", "long"},
+ {"one", "java.lang.String"},
+ {"two", "double"},
+ {"three", "java.lang.String"},
+ },
+ 0 /*priKeyIndex*/, null);
+ checkMetadata(Subclass.class.getName(), new String[][] {
+ {"one", "java.lang.String"},
+ {"two", "boolean"},
+ },
+ -1 /*priKeyIndex*/, Basic.class.getName());
+
+ close();
+ }
+
+ @Persistent
+ static class Subclass extends Basic {
+
+ private String one;
+ private boolean two;
+
+ private Subclass() {
+ }
+
+ private Subclass(long id, String one, double two, String three,
+ String subOne, boolean subTwo) {
+ super(id, one, two, three);
+ this.one = subOne;
+ this.two = subTwo;
+ }
+
+ @Override
+ public void validate(Object other) {
+ super.validate(other);
+ Subclass o = (Subclass) other;
+ TestCase.assertTrue(nullOrEqual(one, o.one));
+ TestCase.assertEquals(two, o.two);
+ if (one == getBasicOne()) {
+ TestCase.assertSame(o.one, o.getBasicOne());
+ }
+ }
+ }
+
+ public void testSuperclass()
+ throws FileNotFoundException, DatabaseException {
+
+ open();
+
+ checkEntity(UseSuperclass.class,
+ new UseSuperclass(33, "xxx"));
+
+ checkMetadata(Superclass.class.getName(), new String[][] {
+ {"id", "int"},
+ {"one", "java.lang.String"},
+ },
+ 0 /*priKeyIndex*/, null);
+ checkMetadata(UseSuperclass.class.getName(), new String[][] {
+ },
+ -1 /*priKeyIndex*/, Superclass.class.getName());
+
+ close();
+ }
+
+ @Persistent
+ static class Superclass implements MyEntity {
+
+ @PrimaryKey
+ private int id;
+ private String one;
+
+ private Superclass() { }
+
+ private Superclass(int id, String one) {
+ this.id = id;
+ this.one = one;
+ }
+
+ public Object getPriKeyObject() {
+ return id;
+ }
+
+ public void validate(Object other) {
+ Superclass o = (Superclass) other;
+ TestCase.assertEquals(id, o.id);
+ TestCase.assertTrue(nullOrEqual(one, o.one));
+ }
+ }
+
+ @Entity
+ static class UseSuperclass extends Superclass {
+
+ private UseSuperclass() { }
+
+ private UseSuperclass(int id, String one) {
+ super(id, one);
+ }
+ }
+
+ public void testAbstract()
+ throws FileNotFoundException, DatabaseException {
+
+ open();
+
+ checkEntity(EntityUseAbstract.class,
+ new EntityUseAbstract(33, "xxx"));
+
+ checkMetadata(Abstract.class.getName(), new String[][] {
+ {"one", "java.lang.String"},
+ },
+ -1 /*priKeyIndex*/, null);
+ checkMetadata(EmbeddedUseAbstract.class.getName(), new String[][] {
+ {"two", "java.lang.String"},
+ },
+ -1 /*priKeyIndex*/, Abstract.class.getName());
+ checkMetadata(EntityUseAbstract.class.getName(), new String[][] {
+ {"id", "int"},
+ {"f1", EmbeddedUseAbstract.class.getName()},
+ {"f2", Abstract.class.getName()},
+ {"f3", Object.class.getName()},
+ {"f4", Interface.class.getName()},
+ {"a1", EmbeddedUseAbstract[].class.getName()},
+ {"a2", Abstract[].class.getName()},
+ {"a3", Abstract[].class.getName()},
+ {"a4", Object[].class.getName()},
+ {"a5", Interface[].class.getName()},
+ {"a6", Interface[].class.getName()},
+ {"a7", Interface[].class.getName()},
+ },
+ 0 /*priKeyIndex*/, Abstract.class.getName());
+
+ close();
+ }
+
+ @Persistent
+ static abstract class Abstract implements Interface {
+
+ String one;
+
+ private Abstract() { }
+
+ private Abstract(String one) {
+ this.one = one;
+ }
+
+ public void validate(Object other) {
+ Abstract o = (Abstract) other;
+ TestCase.assertTrue(nullOrEqual(one, o.one));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ Abstract o = (Abstract) other;
+ return nullOrEqual(one, o.one);
+ }
+ }
+
+ interface Interface {
+ void validate(Object other);
+ }
+
+ @Persistent
+ static class EmbeddedUseAbstract extends Abstract {
+
+ private String two;
+
+ private EmbeddedUseAbstract() { }
+
+ private EmbeddedUseAbstract(String one, String two) {
+ super(one);
+ this.two = two;
+ }
+
+ @Override
+ public void validate(Object other) {
+ super.validate(other);
+ EmbeddedUseAbstract o = (EmbeddedUseAbstract) other;
+ TestCase.assertTrue(nullOrEqual(two, o.two));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!super.equals(other)) {
+ return false;
+ }
+ EmbeddedUseAbstract o = (EmbeddedUseAbstract) other;
+ return nullOrEqual(two, o.two);
+ }
+ }
+
+ @Entity
+ static class EntityUseAbstract extends Abstract implements MyEntity {
+
+ @PrimaryKey
+ private int id;
+
+ private EmbeddedUseAbstract f1;
+ private Abstract f2;
+ private Object f3;
+ private Interface f4;
+ private EmbeddedUseAbstract[] a1;
+ private Abstract[] a2;
+ private Abstract[] a3;
+ private Object[] a4;
+ private Interface[] a5;
+ private Interface[] a6;
+ private Interface[] a7;
+
+ private EntityUseAbstract() { }
+
+ private EntityUseAbstract(int id, String one) {
+ super(one);
+ this.id = id;
+ f1 = new EmbeddedUseAbstract(one, one);
+ f2 = new EmbeddedUseAbstract(one + "x", one + "y");
+ f3 = new EmbeddedUseAbstract(null, null);
+ f4 = new EmbeddedUseAbstract(null, null);
+ a1 = new EmbeddedUseAbstract[3];
+ a2 = new EmbeddedUseAbstract[3];
+ a3 = new Abstract[3];
+ a4 = new Object[3];
+ a5 = new EmbeddedUseAbstract[3];
+ a6 = new Abstract[3];
+ a7 = new Interface[3];
+ for (int i = 0; i < 3; i += 1) {
+ a1[i] = new EmbeddedUseAbstract("1" + i, null);
+ a2[i] = new EmbeddedUseAbstract("2" + i, null);
+ a3[i] = new EmbeddedUseAbstract("3" + i, null);
+ a4[i] = new EmbeddedUseAbstract("4" + i, null);
+ a5[i] = new EmbeddedUseAbstract("5" + i, null);
+ a6[i] = new EmbeddedUseAbstract("6" + i, null);
+ a7[i] = new EmbeddedUseAbstract("7" + i, null);
+ }
+ }
+
+ public Object getPriKeyObject() {
+ return id;
+ }
+
+ @Override
+ public void validate(Object other) {
+ super.validate(other);
+ EntityUseAbstract o = (EntityUseAbstract) other;
+ TestCase.assertEquals(id, o.id);
+ f1.validate(o.f1);
+ assertSame(o.one, o.f1.one);
+ assertSame(o.f1.one, o.f1.two);
+ f2.validate(o.f2);
+ ((Abstract) f3).validate(o.f3);
+ f4.validate(o.f4);
+ assertTrue(arrayToString(a1) + ' ' + arrayToString(o.a1),
+ Arrays.equals(a1, o.a1));
+ assertTrue(Arrays.equals(a2, o.a2));
+ assertTrue(Arrays.equals(a3, o.a3));
+ assertTrue(Arrays.equals(a4, o.a4));
+ assertTrue(Arrays.equals(a5, o.a5));
+ assertTrue(Arrays.equals(a6, o.a6));
+ assertTrue(Arrays.equals(a7, o.a7));
+ assertSame(EmbeddedUseAbstract.class, f2.getClass());
+ assertSame(EmbeddedUseAbstract.class, f3.getClass());
+ assertSame(EmbeddedUseAbstract[].class, a1.getClass());
+ assertSame(EmbeddedUseAbstract[].class, a2.getClass());
+ assertSame(Abstract[].class, a3.getClass());
+ assertSame(Object[].class, a4.getClass());
+ assertSame(EmbeddedUseAbstract[].class, a5.getClass());
+ assertSame(Abstract[].class, a6.getClass());
+ assertSame(Interface[].class, a7.getClass());
+ }
+ }
+
+ public void testCompositeKey()
+ throws FileNotFoundException, DatabaseException {
+
+ open();
+
+ CompositeKey key =
+ new CompositeKey(123, 456L, "xyz", BigInteger.valueOf(789),
+ MyEnum.ONE);
+ checkEntity(UseCompositeKey.class,
+ new UseCompositeKey(key, "one"));
+
+ checkMetadata(UseCompositeKey.class.getName(), new String[][] {
+ {"key", CompositeKey.class.getName()},
+ {"one", "java.lang.String"},
+ },
+ 0 /*priKeyIndex*/, null);
+
+ checkMetadata(CompositeKey.class.getName(), new String[][] {
+ {"f1", "int"},
+ {"f2", "java.lang.Long"},
+ {"f3", "java.lang.String"},
+ {"f4", "java.math.BigInteger"},
+ {"f5", MyEnum.class.getName()},
+ },
+ -1 /*priKeyIndex*/, null);
+
+ close();
+ }
+
+ @Persistent
+ static class CompositeKey {
+ @KeyField(3)
+ private int f1;
+ @KeyField(2)
+ private Long f2;
+ @KeyField(1)
+ private String f3;
+ @KeyField(4)
+ private BigInteger f4;
+ @KeyField(5)
+ private MyEnum f5;
+
+ private CompositeKey() {}
+
+ CompositeKey(int f1, Long f2, String f3, BigInteger f4, MyEnum f5) {
+ this.f1 = f1;
+ this.f2 = f2;
+ this.f3 = f3;
+ this.f4 = f4;
+ this.f5 = f5;
+ }
+
+ void validate(CompositeKey o) {
+ TestCase.assertEquals(f1, o.f1);
+ TestCase.assertTrue(nullOrEqual(f2, o.f2));
+ TestCase.assertTrue(nullOrEqual(f3, o.f3));
+ TestCase.assertTrue(nullOrEqual(f4, o.f4));
+ TestCase.assertEquals(f5, o.f5);
+ TestCase.assertTrue(nullOrEqual(f5, o.f5));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ CompositeKey o = (CompositeKey) other;
+ return f1 == o.f1 &&
+ nullOrEqual(f2, o.f2) &&
+ nullOrEqual(f3, o.f3) &&
+ nullOrEqual(f4, o.f4) &&
+ nullOrEqual(f5, o.f5);
+ }
+
+ @Override
+ public int hashCode() {
+ return f1;
+ }
+
+ @Override
+ public String toString() {
+ return "" + f1 + ' ' + f2 + ' ' + f3 + ' ' + f4 + ' ' + f5;
+ }
+ }
+
+ @Entity
+ static class UseCompositeKey implements MyEntity {
+
+ @PrimaryKey
+ private CompositeKey key;
+ private String one;
+
+ private UseCompositeKey() { }
+
+ private UseCompositeKey(CompositeKey key, String one) {
+ this.key = key;
+ this.one = one;
+ }
+
+ public Object getPriKeyObject() {
+ return key;
+ }
+
+ public void validate(Object other) {
+ UseCompositeKey o = (UseCompositeKey) other;
+ TestCase.assertNotNull(key);
+ TestCase.assertNotNull(o.key);
+ key.validate(o.key);
+ TestCase.assertTrue(nullOrEqual(one, o.one));
+ }
+ }
+
+ public void testComparableKey()
+ throws FileNotFoundException, DatabaseException {
+
+ open();
+
+ ComparableKey key = new ComparableKey(123, 456);
+ checkEntity(UseComparableKey.class,
+ new UseComparableKey(key, "one"));
+
+ checkMetadata(UseComparableKey.class.getName(), new String[][] {
+ {"key", ComparableKey.class.getName()},
+ {"one", "java.lang.String"},
+ },
+ 0 /*priKeyIndex*/, null);
+
+ checkMetadata(ComparableKey.class.getName(), new String[][] {
+ {"f1", "int"},
+ {"f2", "int"},
+ },
+ -1 /*priKeyIndex*/, null);
+
+ ClassMetadata classMeta =
+ model.getClassMetadata(UseComparableKey.class.getName());
+ assertNotNull(classMeta);
+
+ PersistKeyBinding binding = new PersistKeyBinding
+ (catalog, ComparableKey.class.getName(), false);
+
+ PersistComparator comparator = new PersistComparator
+ (/*ComparableKey.class.getName(),
+ classMeta.getCompositeKeyFields(),*/
+ binding);
+
+ compareKeys(comparator, binding, new ComparableKey(1, 1),
+ new ComparableKey(1, 1), 0);
+ compareKeys(comparator, binding, new ComparableKey(1, 2),
+ new ComparableKey(1, 1), -1);
+ compareKeys(comparator, binding, new ComparableKey(2, 1),
+ new ComparableKey(1, 1), -1);
+ compareKeys(comparator, binding, new ComparableKey(2, 1),
+ new ComparableKey(3, 1), 1);
+
+ close();
+ }
+
+ private void compareKeys(Comparator<byte[]> comparator,
+ EntryBinding binding,
+ Object key1,
+ Object key2,
+ int expectResult) {
+ DatabaseEntry entry1 = new DatabaseEntry();
+ DatabaseEntry entry2 = new DatabaseEntry();
+ binding.objectToEntry(key1, entry1);
+ binding.objectToEntry(key2, entry2);
+ int result = comparator.compare(entry1.getData(), entry2.getData());
+ assertEquals(expectResult, result);
+ }
+
+ @Persistent
+ static class ComparableKey implements Comparable<ComparableKey> {
+ @KeyField(2)
+ private int f1;
+ @KeyField(1)
+ private int f2;
+
+ private ComparableKey() {}
+
+ ComparableKey(int f1, int f2) {
+ this.f1 = f1;
+ this.f2 = f2;
+ }
+
+ void validate(ComparableKey o) {
+ TestCase.assertEquals(f1, o.f1);
+ TestCase.assertEquals(f2, o.f2);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ ComparableKey o = (ComparableKey) other;
+ return f1 == o.f1 && f2 == o.f2;
+ }
+
+ @Override
+ public int hashCode() {
+ return f1 + f2;
+ }
+
+ @Override
+ public String toString() {
+ return "" + f1 + ' ' + f2;
+ }
+
+ /** Compare f1 then f2, in reverse integer order. */
+ public int compareTo(ComparableKey o) {
+ if (f1 != o.f1) {
+ return o.f1 - f1;
+ } else {
+ return o.f2 - f2;
+ }
+ }
+ }
+
+ @Entity
+ static class UseComparableKey implements MyEntity {
+
+ @PrimaryKey
+ private ComparableKey key;
+ private String one;
+
+ private UseComparableKey() { }
+
+ private UseComparableKey(ComparableKey key, String one) {
+ this.key = key;
+ this.one = one;
+ }
+
+ public Object getPriKeyObject() {
+ return key;
+ }
+
+ public void validate(Object other) {
+ UseComparableKey o = (UseComparableKey) other;
+ TestCase.assertNotNull(key);
+ TestCase.assertNotNull(o.key);
+ key.validate(o.key);
+ TestCase.assertTrue(nullOrEqual(one, o.one));
+ }
+ }
+
+ public void testSecKeys()
+ throws FileNotFoundException, DatabaseException {
+
+ open();
+
+ SecKeys obj = new SecKeys();
+ checkEntity(SecKeys.class, obj);
+
+ checkMetadata(SecKeys.class.getName(), new String[][] {
+ {"id", "long"},
+ {"f0", "boolean"},
+ {"g0", "boolean"},
+ {"f1", "char"},
+ {"g1", "char"},
+ {"f2", "byte"},
+ {"g2", "byte"},
+ {"f3", "short"},
+ {"g3", "short"},
+ {"f4", "int"},
+ {"g4", "int"},
+ {"f5", "long"},
+ {"g5", "long"},
+ {"f6", "float"},
+ {"g6", "float"},
+ {"f7", "double"},
+ {"g7", "double"},
+ {"f8", "java.lang.String"},
+ {"g8", "java.lang.String"},
+ {"f9", "java.math.BigInteger"},
+ {"g9", "java.math.BigInteger"},
+ //{"f10", "java.math.BigDecimal"},
+ //{"g10", "java.math.BigDecimal"},
+ {"f11", "java.util.Date"},
+ {"g11", "java.util.Date"},
+ {"f12", "java.lang.Boolean"},
+ {"g12", "java.lang.Boolean"},
+ {"f13", "java.lang.Character"},
+ {"g13", "java.lang.Character"},
+ {"f14", "java.lang.Byte"},
+ {"g14", "java.lang.Byte"},
+ {"f15", "java.lang.Short"},
+ {"g15", "java.lang.Short"},
+ {"f16", "java.lang.Integer"},
+ {"g16", "java.lang.Integer"},
+ {"f17", "java.lang.Long"},
+ {"g17", "java.lang.Long"},
+ {"f18", "java.lang.Float"},
+ {"g18", "java.lang.Float"},
+ {"f19", "java.lang.Double"},
+ {"g19", "java.lang.Double"},
+ {"f20", CompositeKey.class.getName()},
+ {"g20", CompositeKey.class.getName()},
+ {"f21", int[].class.getName()},
+ {"g21", int[].class.getName()},
+ {"f22", Integer[].class.getName()},
+ {"g22", Integer[].class.getName()},
+ {"f23", Set.class.getName()},
+ {"g23", Set.class.getName()},
+ {"f24", CompositeKey[].class.getName()},
+ {"g24", CompositeKey[].class.getName()},
+ {"f25", Set.class.getName()},
+ {"g25", Set.class.getName()},
+ {"f26", MyEnum.class.getName()},
+ {"g26", MyEnum.class.getName()},
+ {"f27", MyEnum[].class.getName()},
+ {"g27", MyEnum[].class.getName()},
+ {"f28", Set.class.getName()},
+ {"g28", Set.class.getName()},
+ {"f31", "java.util.Date"},
+ {"f32", "java.lang.Boolean"},
+ {"f33", "java.lang.Character"},
+ {"f34", "java.lang.Byte"},
+ {"f35", "java.lang.Short"},
+ {"f36", "java.lang.Integer"},
+ {"f37", "java.lang.Long"},
+ {"f38", "java.lang.Float"},
+ {"f39", "java.lang.Double"},
+ {"f40", CompositeKey.class.getName()},
+ },
+ 0 /*priKeyIndex*/, null);
+
+ checkSecKey(obj, "f0", obj.f0, Boolean.class);
+ checkSecKey(obj, "f1", obj.f1, Character.class);
+ checkSecKey(obj, "f2", obj.f2, Byte.class);
+ checkSecKey(obj, "f3", obj.f3, Short.class);
+ checkSecKey(obj, "f4", obj.f4, Integer.class);
+ checkSecKey(obj, "f5", obj.f5, Long.class);
+ checkSecKey(obj, "f6", obj.f6, Float.class);
+ checkSecKey(obj, "f7", obj.f7, Double.class);
+ checkSecKey(obj, "f8", obj.f8, String.class);
+ checkSecKey(obj, "f9", obj.f9, BigInteger.class);
+ //checkSecKey(obj, "f10", obj.f10, BigDecimal.class);
+ checkSecKey(obj, "f11", obj.f11, Date.class);
+ checkSecKey(obj, "f12", obj.f12, Boolean.class);
+ checkSecKey(obj, "f13", obj.f13, Character.class);
+ checkSecKey(obj, "f14", obj.f14, Byte.class);
+ checkSecKey(obj, "f15", obj.f15, Short.class);
+ checkSecKey(obj, "f16", obj.f16, Integer.class);
+ checkSecKey(obj, "f17", obj.f17, Long.class);
+ checkSecKey(obj, "f18", obj.f18, Float.class);
+ checkSecKey(obj, "f19", obj.f19, Double.class);
+ checkSecKey(obj, "f20", obj.f20, CompositeKey.class);
+ checkSecKey(obj, "f26", obj.f26, MyEnum.class);
+
+ checkSecMultiKey(obj, "f21", toSet(obj.f21), Integer.class);
+ checkSecMultiKey(obj, "f22", toSet(obj.f22), Integer.class);
+ checkSecMultiKey(obj, "f23", toSet(obj.f23), Integer.class);
+ checkSecMultiKey(obj, "f24", toSet(obj.f24), CompositeKey.class);
+ checkSecMultiKey(obj, "f25", toSet(obj.f25), CompositeKey.class);
+ checkSecMultiKey(obj, "f27", toSet(obj.f27), MyEnum.class);
+ checkSecMultiKey(obj, "f28", toSet(obj.f28), MyEnum.class);
+
+ nullifySecKey(obj, "f8", obj.f8, String.class);
+ nullifySecKey(obj, "f9", obj.f9, BigInteger.class);
+ //nullifySecKey(obj, "f10", obj.f10, BigDecimal.class);
+ nullifySecKey(obj, "f11", obj.f11, Date.class);
+ nullifySecKey(obj, "f12", obj.f12, Boolean.class);
+ nullifySecKey(obj, "f13", obj.f13, Character.class);
+ nullifySecKey(obj, "f14", obj.f14, Byte.class);
+ nullifySecKey(obj, "f15", obj.f15, Short.class);
+ nullifySecKey(obj, "f16", obj.f16, Integer.class);
+ nullifySecKey(obj, "f17", obj.f17, Long.class);
+ nullifySecKey(obj, "f18", obj.f18, Float.class);
+ nullifySecKey(obj, "f19", obj.f19, Double.class);
+ nullifySecKey(obj, "f20", obj.f20, CompositeKey.class);
+ nullifySecKey(obj, "f26", obj.f26, MyEnum.class);
+
+ nullifySecMultiKey(obj, "f21", obj.f21, Integer.class);
+ nullifySecMultiKey(obj, "f22", obj.f22, Integer.class);
+ nullifySecMultiKey(obj, "f23", obj.f23, Integer.class);
+ nullifySecMultiKey(obj, "f24", obj.f24, CompositeKey.class);
+ nullifySecMultiKey(obj, "f25", obj.f25, CompositeKey.class);
+ nullifySecMultiKey(obj, "f27", obj.f27, MyEnum.class);
+ nullifySecMultiKey(obj, "f28", obj.f28, MyEnum.class);
+
+ nullifySecKey(obj, "f31", obj.f31, Date.class);
+ nullifySecKey(obj, "f32", obj.f32, Boolean.class);
+ nullifySecKey(obj, "f33", obj.f33, Character.class);
+ nullifySecKey(obj, "f34", obj.f34, Byte.class);
+ nullifySecKey(obj, "f35", obj.f35, Short.class);
+ nullifySecKey(obj, "f36", obj.f36, Integer.class);
+ nullifySecKey(obj, "f37", obj.f37, Long.class);
+ nullifySecKey(obj, "f38", obj.f38, Float.class);
+ nullifySecKey(obj, "f39", obj.f39, Double.class);
+ nullifySecKey(obj, "f40", obj.f40, CompositeKey.class);
+
+ close();
+ }
+
+ static Set toSet(int[] a) {
+ Set set = new HashSet();
+ for (int i : a) {
+ set.add(i);
+ }
+ return set;
+ }
+
+ static Set toSet(Object[] a) {
+ return new HashSet(Arrays.asList(a));
+ }
+
+ static Set toSet(Set s) {
+ return s;
+ }
+
+ @Entity
+ static class SecKeys implements MyEntity {
+
+ @PrimaryKey
+ long id;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final boolean f0 = false;
+ private final boolean g0 = false;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final char f1 = '1';
+ private final char g1 = '1';
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final byte f2 = 2;
+ private final byte g2 = 2;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final short f3 = 3;
+ private final short g3 = 3;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final int f4 = 4;
+ private final int g4 = 4;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final long f5 = 5;
+ private final long g5 = 5;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final float f6 = 6.6f;
+ private final float g6 = 6.6f;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final double f7 = 7.7;
+ private final double g7 = 7.7;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final String f8 = "8";
+ private final String g8 = "8";
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private BigInteger f9;
+ private BigInteger g9;
+
+ //@SecondaryKey(relate=MANY_TO_ONE)
+ //private BigDecimal f10;
+ //private BigDecimal g10;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final Date f11 = new Date(11);
+ private final Date g11 = new Date(11);
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final Boolean f12 = true;
+ private final Boolean g12 = true;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final Character f13 = '3';
+ private final Character g13 = '3';
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final Byte f14 = 14;
+ private final Byte g14 = 14;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final Short f15 = 15;
+ private final Short g15 = 15;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final Integer f16 = 16;
+ private final Integer g16 = 16;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final Long f17= 17L;
+ private final Long g17= 17L;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final Float f18 = 18.18f;
+ private final Float g18 = 18.18f;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final Double f19 = 19.19;
+ private final Double g19 = 19.19;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final CompositeKey f20 =
+ new CompositeKey(20, 20L, "20", BigInteger.valueOf(20),
+ MyEnum.ONE);
+ private final CompositeKey g20 =
+ new CompositeKey(20, 20L, "20", BigInteger.valueOf(20),
+ MyEnum.TWO);
+
+ private static int[] arrayOfInt = { 100, 101, 102 };
+
+ private static Integer[] arrayOfInteger = { 100, 101, 102 };
+
+ private static CompositeKey[] arrayOfCompositeKey = {
+ new CompositeKey(100, 100L, "100", BigInteger.valueOf(100),
+ MyEnum.ONE),
+ new CompositeKey(101, 101L, "101", BigInteger.valueOf(101),
+ MyEnum.TWO),
+ new CompositeKey(102, 102L, "102", BigInteger.valueOf(102),
+ MyEnum.TWO),
+ };
+
+ private static MyEnum[] arrayOfEnum =
+ new MyEnum[] { MyEnum.ONE, MyEnum.TWO };
+
+ @SecondaryKey(relate=ONE_TO_MANY)
+ private final int[] f21 = arrayOfInt;
+ private final int[] g21 = f21;
+
+ @SecondaryKey(relate=ONE_TO_MANY)
+ private final Integer[] f22 = arrayOfInteger;
+ private final Integer[] g22 = f22;
+
+ @SecondaryKey(relate=ONE_TO_MANY)
+ private final Set<Integer> f23 = toSet(arrayOfInteger);
+ private final Set<Integer> g23 = f23;
+
+ @SecondaryKey(relate=ONE_TO_MANY)
+ private final CompositeKey[] f24 = arrayOfCompositeKey;
+ private final CompositeKey[] g24 = f24;
+
+ @SecondaryKey(relate=ONE_TO_MANY)
+ private final Set<CompositeKey> f25 = toSet(arrayOfCompositeKey);
+ private final Set<CompositeKey> g25 = f25;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final MyEnum f26 = MyEnum.TWO;
+ private final MyEnum g26 = f26;
+
+ @SecondaryKey(relate=ONE_TO_MANY)
+ private final MyEnum[] f27 = arrayOfEnum;
+ private final MyEnum[] g27 = f27;
+
+ @SecondaryKey(relate=ONE_TO_MANY)
+ private final Set<MyEnum> f28 = toSet(arrayOfEnum);
+ private final Set<MyEnum> g28 = f28;
+
+ /* Repeated key values to test shared references. */
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final Date f31 = f11;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final Boolean f32 = f12;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final Character f33 = f13;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final Byte f34 = f14;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final Short f35 = f15;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final Integer f36 = f16;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final Long f37= f17;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final Float f38 = f18;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final Double f39 = f19;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private final CompositeKey f40 = f20;
+
+ public Object getPriKeyObject() {
+ return id;
+ }
+
+ public void validate(Object other) {
+ SecKeys o = (SecKeys) other;
+ TestCase.assertEquals(id, o.id);
+
+ TestCase.assertEquals(f0, o.f0);
+ TestCase.assertEquals(f1, o.f1);
+ TestCase.assertEquals(f2, o.f2);
+ TestCase.assertEquals(f3, o.f3);
+ TestCase.assertEquals(f4, o.f4);
+ TestCase.assertEquals(f5, o.f5);
+ TestCase.assertEquals(f6, o.f6);
+ TestCase.assertEquals(f7, o.f7);
+ TestCase.assertEquals(f8, o.f8);
+ TestCase.assertEquals(f9, o.f9);
+ //TestCase.assertEquals(f10, o.f10);
+ TestCase.assertEquals(f11, o.f11);
+ TestCase.assertEquals(f12, o.f12);
+ TestCase.assertEquals(f13, o.f13);
+ TestCase.assertEquals(f14, o.f14);
+ TestCase.assertEquals(f15, o.f15);
+ TestCase.assertEquals(f16, o.f16);
+ TestCase.assertEquals(f17, o.f17);
+ TestCase.assertEquals(f18, o.f18);
+ TestCase.assertEquals(f19, o.f19);
+ TestCase.assertEquals(f20, o.f20);
+ TestCase.assertTrue(Arrays.equals(f21, o.f21));
+ TestCase.assertTrue(Arrays.equals(f22, o.f22));
+ TestCase.assertEquals(f23, o.f23);
+ TestCase.assertTrue(Arrays.equals(f24, o.f24));
+ TestCase.assertEquals(f25, o.f25);
+
+ TestCase.assertEquals(g0, o.g0);
+ TestCase.assertEquals(g1, o.g1);
+ TestCase.assertEquals(g2, o.g2);
+ TestCase.assertEquals(g3, o.g3);
+ TestCase.assertEquals(g4, o.g4);
+ TestCase.assertEquals(g5, o.g5);
+ TestCase.assertEquals(g6, o.g6);
+ TestCase.assertEquals(g7, o.g7);
+ TestCase.assertEquals(g8, o.g8);
+ TestCase.assertEquals(g9, o.g9);
+ //TestCase.assertEquals(g10, o.g10);
+ TestCase.assertEquals(g11, o.g11);
+ TestCase.assertEquals(g12, o.g12);
+ TestCase.assertEquals(g13, o.g13);
+ TestCase.assertEquals(g14, o.g14);
+ TestCase.assertEquals(g15, o.g15);
+ TestCase.assertEquals(g16, o.g16);
+ TestCase.assertEquals(g17, o.g17);
+ TestCase.assertEquals(g18, o.g18);
+ TestCase.assertEquals(g19, o.g19);
+ TestCase.assertEquals(g20, o.g20);
+ TestCase.assertTrue(Arrays.equals(g21, o.g21));
+ TestCase.assertTrue(Arrays.equals(g22, o.g22));
+ TestCase.assertEquals(g23, o.g23);
+ TestCase.assertTrue(Arrays.equals(g24, o.g24));
+ TestCase.assertEquals(g25, o.g25);
+
+ TestCase.assertEquals(f31, o.f31);
+ TestCase.assertEquals(f32, o.f32);
+ TestCase.assertEquals(f33, o.f33);
+ TestCase.assertEquals(f34, o.f34);
+ TestCase.assertEquals(f35, o.f35);
+ TestCase.assertEquals(f36, o.f36);
+ TestCase.assertEquals(f37, o.f37);
+ TestCase.assertEquals(f38, o.f38);
+ TestCase.assertEquals(f39, o.f39);
+ TestCase.assertEquals(f40, o.f40);
+
+ checkSameIfNonNull(o.f31, o.f11);
+ checkSameIfNonNull(o.f32, o.f12);
+ checkSameIfNonNull(o.f33, o.f13);
+ checkSameIfNonNull(o.f34, o.f14);
+ checkSameIfNonNull(o.f35, o.f15);
+ checkSameIfNonNull(o.f36, o.f16);
+ checkSameIfNonNull(o.f37, o.f17);
+ checkSameIfNonNull(o.f38, o.f18);
+ checkSameIfNonNull(o.f39, o.f19);
+ checkSameIfNonNull(o.f40, o.f20);
+ }
+ }
+
+ public void testSecKeyRefToPriKey()
+ throws FileNotFoundException, DatabaseException {
+
+ open();
+
+ SecKeyRefToPriKey obj = new SecKeyRefToPriKey();
+ checkEntity(SecKeyRefToPriKey.class, obj);
+
+ checkMetadata(SecKeyRefToPriKey.class.getName(), new String[][] {
+ {"priKey", "java.lang.String"},
+ {"secKey1", "java.lang.String"},
+ {"secKey2", String[].class.getName()},
+ {"secKey3", Set.class.getName()},
+ },
+ 0 /*priKeyIndex*/, null);
+
+ checkSecKey(obj, "secKey1", obj.secKey1, String.class);
+ checkSecMultiKey(obj, "secKey2", toSet(obj.secKey2), String.class);
+ checkSecMultiKey(obj, "secKey3", toSet(obj.secKey3), String.class);
+
+ close();
+ }
+
+ @Entity
+ static class SecKeyRefToPriKey implements MyEntity {
+
+ @PrimaryKey
+ private final String priKey;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ private final String secKey1;
+
+ @SecondaryKey(relate=ONE_TO_MANY)
+ private final String[] secKey2;
+
+ @SecondaryKey(relate=ONE_TO_MANY)
+ private final Set<String> secKey3 = new HashSet<String>();
+
+ private SecKeyRefToPriKey() {
+ priKey = "sharedValue";
+ secKey1 = priKey;
+ secKey2 = new String[] { priKey };
+ secKey3.add(priKey);
+ }
+
+ public Object getPriKeyObject() {
+ return priKey;
+ }
+
+ public void validate(Object other) {
+ SecKeyRefToPriKey o = (SecKeyRefToPriKey) other;
+ TestCase.assertEquals(priKey, o.priKey);
+ TestCase.assertNotNull(o.secKey1);
+ TestCase.assertEquals(1, o.secKey2.length);
+ TestCase.assertEquals(1, o.secKey3.size());
+ TestCase.assertSame(o.secKey1, o.priKey);
+ TestCase.assertSame(o.secKey2[0], o.priKey);
+ TestCase.assertSame(o.secKey3.iterator().next(), o.priKey);
+ }
+ }
+
+ public void testSecKeyInSuperclass()
+ throws FileNotFoundException, DatabaseException {
+
+ open();
+
+ SecKeyInSuperclassEntity obj = new SecKeyInSuperclassEntity();
+ checkEntity(SecKeyInSuperclassEntity.class, obj);
+
+ checkMetadata(SecKeyInSuperclass.class.getName(),
+ new String[][] {
+ {"priKey", "java.lang.String"},
+ {"secKey1", String.class.getName()},
+ },
+ 0/*priKeyIndex*/, null);
+
+ checkMetadata(SecKeyInSuperclassEntity.class.getName(),
+ new String[][] {
+ {"secKey2", "java.lang.String"},
+ },
+ -1 /*priKeyIndex*/, SecKeyInSuperclass.class.getName());
+
+ checkSecKey
+ (obj, SecKeyInSuperclassEntity.class, "secKey1", obj.secKey1,
+ String.class);
+ checkSecKey
+ (obj, SecKeyInSuperclassEntity.class, "secKey2", obj.secKey2,
+ String.class);
+
+ close();
+ }
+
+ @Persistent
+ static class SecKeyInSuperclass implements MyEntity {
+
+ @PrimaryKey
+ String priKey = "1";
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ String secKey1 = "1";
+
+ public Object getPriKeyObject() {
+ return priKey;
+ }
+
+ public void validate(Object other) {
+ SecKeyInSuperclass o = (SecKeyInSuperclass) other;
+ TestCase.assertEquals(secKey1, o.secKey1);
+ }
+ }
+
+ @Entity
+ static class SecKeyInSuperclassEntity extends SecKeyInSuperclass {
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ String secKey2 = "2";
+
+ @Override
+ public void validate(Object other) {
+ super.validate(other);
+ SecKeyInSuperclassEntity o = (SecKeyInSuperclassEntity) other;
+ TestCase.assertEquals(priKey, o.priKey);
+ TestCase.assertEquals(secKey2, o.secKey2);
+ }
+ }
+
+ public void testSecKeyInSubclass()
+ throws FileNotFoundException, DatabaseException {
+
+ open();
+
+ SecKeyInSubclass obj = new SecKeyInSubclass();
+ checkEntity(SecKeyInSubclassEntity.class, obj);
+
+ checkMetadata(SecKeyInSubclassEntity.class.getName(), new String[][] {
+ {"priKey", "java.lang.String"},
+ {"secKey1", "java.lang.String"},
+ },
+ 0 /*priKeyIndex*/, null);
+
+ checkMetadata(SecKeyInSubclass.class.getName(), new String[][] {
+ {"secKey2", String.class.getName()},
+ },
+ -1 /*priKeyIndex*/,
+ SecKeyInSubclassEntity.class.getName());
+
+ checkSecKey
+ (obj, SecKeyInSubclassEntity.class, "secKey1", obj.secKey1,
+ String.class);
+ checkSecKey
+ (obj, SecKeyInSubclassEntity.class, "secKey2", obj.secKey2,
+ String.class);
+
+ close();
+ }
+
+ @Entity
+ static class SecKeyInSubclassEntity implements MyEntity {
+
+ @PrimaryKey
+ String priKey = "1";
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ String secKey1;
+
+ public Object getPriKeyObject() {
+ return priKey;
+ }
+
+ public void validate(Object other) {
+ SecKeyInSubclassEntity o = (SecKeyInSubclassEntity) other;
+ TestCase.assertEquals(priKey, o.priKey);
+ TestCase.assertEquals(secKey1, o.secKey1);
+ }
+ }
+
+ @Persistent
+ static class SecKeyInSubclass extends SecKeyInSubclassEntity {
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ String secKey2 = "2";
+
+ @Override
+ public void validate(Object other) {
+ super.validate(other);
+ SecKeyInSubclass o = (SecKeyInSubclass) other;
+ TestCase.assertEquals(secKey2, o.secKey2);
+ }
+ }
+
+ private static void checkSameIfNonNull(Object o1, Object o2) {
+ if (o1 != null && o2 != null) {
+ assertSame(o1, o2);
+ }
+ }
+
+ private void checkEntity(Class entityCls, MyEntity entity) {
+ Object priKey = entity.getPriKeyObject();
+ Class keyCls = priKey.getClass();
+ DatabaseEntry keyEntry2 = new DatabaseEntry();
+ DatabaseEntry dataEntry2 = new DatabaseEntry();
+
+ /* Write object, read it back and validate (compare) it. */
+ PersistEntityBinding entityBinding =
+ new PersistEntityBinding(catalog, entityCls.getName(), false);
+ entityBinding.objectToData(entity, dataEntry);
+ entityBinding.objectToKey(entity, keyEntry);
+ Object entity2 = entityBinding.entryToObject(keyEntry, dataEntry);
+ entity.validate(entity2);
+
+ /* Read back the primary key and validate it. */
+ PersistKeyBinding keyBinding =
+ new PersistKeyBinding(catalog, keyCls.getName(), false);
+ Object priKey2 = keyBinding.entryToObject(keyEntry);
+ assertEquals(priKey, priKey2);
+ keyBinding.objectToEntry(priKey2, keyEntry2);
+ assertEquals(keyEntry, keyEntry2);
+
+ /* Check raw entity binding. */
+ PersistEntityBinding rawEntityBinding =
+ new PersistEntityBinding(catalog, entityCls.getName(), true);
+ RawObject rawEntity =
+ (RawObject) rawEntityBinding.entryToObject(keyEntry, dataEntry);
+ rawEntityBinding.objectToKey(rawEntity, keyEntry2);
+ rawEntityBinding.objectToData(rawEntity, dataEntry2);
+ entity2 = entityBinding.entryToObject(keyEntry2, dataEntry2);
+ entity.validate(entity2);
+ RawObject rawEntity2 =
+ (RawObject) rawEntityBinding.entryToObject(keyEntry2, dataEntry2);
+ assertEquals(rawEntity, rawEntity2);
+ assertEquals(dataEntry, dataEntry2);
+ assertEquals(keyEntry, keyEntry2);
+
+ /* Check that raw entity can be converted to a regular entity. */
+ entity2 = catalog.convertRawObject(rawEntity, null);
+ entity.validate(entity2);
+
+ /* Check raw key binding. */
+ PersistKeyBinding rawKeyBinding =
+ new PersistKeyBinding(catalog, keyCls.getName(), true);
+ Object rawKey = rawKeyBinding.entryToObject(keyEntry);
+ rawKeyBinding.objectToEntry(rawKey, keyEntry2);
+ priKey2 = keyBinding.entryToObject(keyEntry2);
+ assertEquals(priKey, priKey2);
+ assertEquals(keyEntry, keyEntry2);
+ }
+
+ private void checkSecKey(MyEntity entity,
+ String keyName,
+ Object keyValue,
+ Class keyCls)
+ throws DatabaseException {
+
+ checkSecKey(entity, entity.getClass(), keyName, keyValue, keyCls);
+ }
+
+ private void checkSecKey(MyEntity entity,
+ Class entityCls,
+ String keyName,
+ Object keyValue,
+ Class keyCls)
+ throws DatabaseException {
+
+ /* Get entity metadata. */
+ EntityMetadata entityMeta =
+ model.getEntityMetadata(entityCls.getName());
+ assertNotNull(entityMeta);
+
+ /* Get secondary key metadata. */
+ SecondaryKeyMetadata secKeyMeta =
+ entityMeta.getSecondaryKeys().get(keyName);
+ assertNotNull(secKeyMeta);
+
+ /* Create key creator/nullifier. */
+ SecondaryKeyCreator keyCreator = new PersistKeyCreator
+ (catalog, entityMeta, keyCls.getName(), secKeyMeta,
+ false /*rawAcess*/);
+
+ /* Convert entity to bytes. */
+ PersistEntityBinding entityBinding =
+ new PersistEntityBinding(catalog, entityCls.getName(), false);
+ entityBinding.objectToData(entity, dataEntry);
+ entityBinding.objectToKey(entity, keyEntry);
+
+ /* Extract secondary key bytes from entity bytes. */
+ DatabaseEntry secKeyEntry = new DatabaseEntry();
+ boolean isKeyPresent = keyCreator.createSecondaryKey
+ (null, keyEntry, dataEntry, secKeyEntry);
+ assertEquals(keyValue != null, isKeyPresent);
+
+ /* Convert secondary key bytes back to an object. */
+ PersistKeyBinding keyBinding =
+ new PersistKeyBinding(catalog, keyCls.getName(), false);
+ if (isKeyPresent) {
+ Object keyValue2 = keyBinding.entryToObject(secKeyEntry);
+ assertEquals(keyValue, keyValue2);
+ DatabaseEntry secKeyEntry2 = new DatabaseEntry();
+ keyBinding.objectToEntry(keyValue2, secKeyEntry2);
+ assertEquals(secKeyEntry, secKeyEntry2);
+ }
+ }
+
+ private void checkSecMultiKey(MyEntity entity,
+ String keyName,
+ Set keyValues,
+ Class keyCls)
+ throws DatabaseException {
+
+ /* Get entity metadata. */
+ Class entityCls = entity.getClass();
+ EntityMetadata entityMeta =
+ model.getEntityMetadata(entityCls.getName());
+ assertNotNull(entityMeta);
+
+ /* Get secondary key metadata. */
+ SecondaryKeyMetadata secKeyMeta =
+ entityMeta.getSecondaryKeys().get(keyName);
+ assertNotNull(secKeyMeta);
+
+ /* Create key creator/nullifier. */
+ SecondaryMultiKeyCreator keyCreator = new PersistKeyCreator
+ (catalog, entityMeta, keyCls.getName(), secKeyMeta,
+ false /*rawAcess*/);
+
+ /* Convert entity to bytes. */
+ PersistEntityBinding entityBinding =
+ new PersistEntityBinding(catalog, entityCls.getName(), false);
+ entityBinding.objectToData(entity, dataEntry);
+ entityBinding.objectToKey(entity, keyEntry);
+
+ /* Extract secondary key bytes from entity bytes. */
+ Set<DatabaseEntry> results = new HashSet<DatabaseEntry>();
+ keyCreator.createSecondaryKeys
+ (null, keyEntry, dataEntry, results);
+ assertEquals(keyValues.size(), results.size());
+
+ /* Convert secondary key bytes back to objects. */
+ PersistKeyBinding keyBinding =
+ new PersistKeyBinding(catalog, keyCls.getName(), false);
+ Set keyValues2 = new HashSet();
+ for (DatabaseEntry secKeyEntry : results) {
+ Object keyValue2 = keyBinding.entryToObject(secKeyEntry);
+ keyValues2.add(keyValue2);
+ }
+ assertEquals(keyValues, keyValues2);
+ }
+
+ private void nullifySecKey(MyEntity entity,
+ String keyName,
+ Object keyValue,
+ Class keyCls)
+ throws DatabaseException {
+
+ /* Get entity metadata. */
+ Class entityCls = entity.getClass();
+ EntityMetadata entityMeta =
+ model.getEntityMetadata(entityCls.getName());
+ assertNotNull(entityMeta);
+
+ /* Get secondary key metadata. */
+ SecondaryKeyMetadata secKeyMeta =
+ entityMeta.getSecondaryKeys().get(keyName);
+ assertNotNull(secKeyMeta);
+
+ /* Create key creator/nullifier. */
+ ForeignMultiKeyNullifier keyNullifier = new PersistKeyCreator
+ (catalog, entityMeta, keyCls.getName(), secKeyMeta,
+ false /*rawAcess*/);
+
+ /* Convert entity to bytes. */
+ PersistEntityBinding entityBinding =
+ new PersistEntityBinding(catalog, entityCls.getName(), false);
+ entityBinding.objectToData(entity, dataEntry);
+ entityBinding.objectToKey(entity, keyEntry);
+
+ /* Convert secondary key to bytes. */
+ PersistKeyBinding keyBinding =
+ new PersistKeyBinding(catalog, keyCls.getName(), false);
+ DatabaseEntry secKeyEntry = new DatabaseEntry();
+ if (keyValue != null) {
+ keyBinding.objectToEntry(keyValue, secKeyEntry);
+ }
+
+ /* Nullify secondary key bytes within entity bytes. */
+ boolean isKeyPresent = keyNullifier.nullifyForeignKey
+ (null, keyEntry, dataEntry, secKeyEntry);
+ assertEquals(keyValue != null, isKeyPresent);
+
+ /* Convert modified entity bytes back to an entity. */
+ Object entity2 = entityBinding.entryToObject(keyEntry, dataEntry);
+ setFieldToNull(entity, keyName);
+ entity.validate(entity2);
+
+ /* Do a full check after nullifying it. */
+ checkSecKey(entity, keyName, null, keyCls);
+ }
+
+ private void nullifySecMultiKey(MyEntity entity,
+ String keyName,
+ Object keyValue,
+ Class keyCls)
+ throws DatabaseException {
+
+ /* Get entity metadata. */
+ Class entityCls = entity.getClass();
+ EntityMetadata entityMeta =
+ model.getEntityMetadata(entityCls.getName());
+ assertNotNull(entityMeta);
+
+ /* Get secondary key metadata. */
+ SecondaryKeyMetadata secKeyMeta =
+ entityMeta.getSecondaryKeys().get(keyName);
+ assertNotNull(secKeyMeta);
+
+ /* Create key creator/nullifier. */
+ ForeignMultiKeyNullifier keyNullifier = new PersistKeyCreator
+ (catalog, entityMeta, keyCls.getName(), secKeyMeta,
+ false /*rawAcess*/);
+
+ /* Convert entity to bytes. */
+ PersistEntityBinding entityBinding =
+ new PersistEntityBinding(catalog, entityCls.getName(), false);
+ entityBinding.objectToData(entity, dataEntry);
+ entityBinding.objectToKey(entity, keyEntry);
+
+ /* Get secondary key binding. */
+ PersistKeyBinding keyBinding =
+ new PersistKeyBinding(catalog, keyCls.getName(), false);
+ DatabaseEntry secKeyEntry = new DatabaseEntry();
+
+ /* Nullify one key value at a time until all of them are gone. */
+ while (true) {
+ Object fieldObj = getField(entity, keyName);
+ fieldObj = nullifyFirstElement(fieldObj, keyBinding, secKeyEntry);
+ if (fieldObj == null) {
+ break;
+ }
+ setField(entity, keyName, fieldObj);
+
+ /* Nullify secondary key bytes within entity bytes. */
+ boolean isKeyPresent = keyNullifier.nullifyForeignKey
+ (null, keyEntry, dataEntry, secKeyEntry);
+ assertEquals(keyValue != null, isKeyPresent);
+
+ /* Convert modified entity bytes back to an entity. */
+ Object entity2 = entityBinding.entryToObject(keyEntry, dataEntry);
+ entity.validate(entity2);
+
+ /* Do a full check after nullifying it. */
+ Set keyValues;
+ if (fieldObj instanceof Set) {
+ keyValues = (Set) fieldObj;
+ } else if (fieldObj instanceof Object[]) {
+ keyValues = toSet((Object[]) fieldObj);
+ } else if (fieldObj instanceof int[]) {
+ keyValues = toSet((int[]) fieldObj);
+ } else {
+ throw new IllegalStateException(fieldObj.getClass().getName());
+ }
+ checkSecMultiKey(entity, keyName, keyValues, keyCls);
+ }
+ }
+
+ /**
+ * Nullifies the first element of an array or collection object by removing
+ * it from the array or collection. Returns the resulting array or
+ * collection. Also outputs the removed element to the keyEntry using the
+ * keyBinding.
+ */
+ private Object nullifyFirstElement(Object obj,
+ EntryBinding keyBinding,
+ DatabaseEntry keyEntry) {
+ if (obj instanceof Collection) {
+ Iterator i = ((Collection) obj).iterator();
+ if (i.hasNext()) {
+ Object elem = i.next();
+ i.remove();
+ keyBinding.objectToEntry(elem, keyEntry);
+ return obj;
+ } else {
+ return null;
+ }
+ } else if (obj instanceof Object[]) {
+ Object[] a1 = (Object[]) obj;
+ if (a1.length > 0) {
+ Object[] a2 = (Object[]) Array.newInstance
+ (obj.getClass().getComponentType(), a1.length - 1);
+ System.arraycopy(a1, 1, a2, 0, a2.length);
+ keyBinding.objectToEntry(a1[0], keyEntry);
+ return a2;
+ } else {
+ return null;
+ }
+ } else if (obj instanceof int[]) {
+ int[] a1 = (int[]) obj;
+ if (a1.length > 0) {
+ int[] a2 = new int[a1.length - 1];
+ System.arraycopy(a1, 1, a2, 0, a2.length);
+ keyBinding.objectToEntry(a1[0], keyEntry);
+ return a2;
+ } else {
+ return null;
+ }
+ } else {
+ throw new IllegalStateException(obj.getClass().getName());
+ }
+ }
+
+ private void checkMetadata(String clsName,
+ String[][] nameTypePairs,
+ int priKeyIndex,
+ String superClsName)
+ throws DatabaseException {
+
+ /* Check metadata/types against the live model. */
+ checkMetadata
+ (catalog, model, clsName, nameTypePairs, priKeyIndex,
+ superClsName);
+
+ /*
+ * Open a catalog that uses the stored model.
+ */
+ PersistCatalog storedCatalog = new PersistCatalog
+ (null, env, STORE_PREFIX, STORE_PREFIX + "catalog", null, null,
+ null, false /*useCurrentModel*/, null /*Store*/);
+ EntityModel storedModel = storedCatalog.getResolvedModel();
+
+ /* Check metadata/types against the stored catalog/model. */
+ checkMetadata
+ (storedCatalog, storedModel, clsName, nameTypePairs, priKeyIndex,
+ superClsName);
+
+ storedCatalog.close();
+ }
+
+ private void checkMetadata(PersistCatalog checkCatalog,
+ EntityModel checkModel,
+ String clsName,
+ String[][] nameTypePairs,
+ int priKeyIndex,
+ String superClsName) {
+ ClassMetadata classMeta = checkModel.getClassMetadata(clsName);
+ assertNotNull(clsName, classMeta);
+
+ PrimaryKeyMetadata priKeyMeta = classMeta.getPrimaryKey();
+ if (priKeyIndex >= 0) {
+ assertNotNull(priKeyMeta);
+ String fieldName = nameTypePairs[priKeyIndex][0];
+ String fieldType = nameTypePairs[priKeyIndex][1];
+ assertEquals(priKeyMeta.getName(), fieldName);
+ assertEquals(priKeyMeta.getClassName(), fieldType);
+ assertEquals(priKeyMeta.getDeclaringClassName(), clsName);
+ assertNull(priKeyMeta.getSequenceName());
+ } else {
+ assertNull(priKeyMeta);
+ }
+
+ RawType type = checkCatalog.getFormat(clsName);
+ assertNotNull(type);
+ assertEquals(clsName, type.getClassName());
+ assertEquals(0, type.getVersion());
+ assertTrue(!type.isSimple());
+ assertTrue(!type.isPrimitive());
+ assertTrue(!type.isEnum());
+ assertNull(type.getEnumConstants());
+ assertTrue(!type.isArray());
+ assertEquals(0, type.getDimensions());
+ assertNull(type.getComponentType());
+ RawType superType = type.getSuperType();
+ if (superClsName != null) {
+ assertNotNull(superType);
+ assertEquals(superClsName, superType.getClassName());
+ } else {
+ assertNull(superType);
+ }
+
+ Map<String,RawField> fields = type.getFields();
+ assertNotNull(fields);
+
+ int nFields = nameTypePairs.length;
+ assertEquals(nFields, fields.size());
+
+ for (String[] pair : nameTypePairs) {
+ String fieldName = pair[0];
+ String fieldType = pair[1];
+ Class fieldCls;
+ try {
+ fieldCls = SimpleCatalog.classForName(fieldType);
+ } catch (ClassNotFoundException e) {
+ fail(e.toString());
+ return; /* For compiler */
+ }
+ RawField field = fields.get(fieldName);
+ assertNotNull(field);
+ assertEquals(fieldName, field.getName());
+ type = field.getType();
+ assertNotNull(type);
+ int dim = getArrayDimensions(fieldType);
+ while (dim > 0) {
+ assertEquals(dim, type.getDimensions());
+ assertEquals(dim, getArrayDimensions(fieldType));
+ assertEquals(true, type.isArray());
+ assertEquals(fieldType, type.getClassName());
+ assertEquals(0, type.getVersion());
+ assertTrue(!type.isSimple());
+ assertTrue(!type.isPrimitive());
+ assertTrue(!type.isEnum());
+ assertNull(type.getEnumConstants());
+ fieldType = getArrayComponent(fieldType, dim);
+ type = type.getComponentType();
+ assertNotNull(fieldType, type);
+ dim -= 1;
+ }
+ assertEquals(fieldType, type.getClassName());
+ List<String> enums = getEnumConstants(fieldType);
+ assertEquals(isSimpleType(fieldType), type.isSimple());
+ assertEquals(isPrimitiveType(fieldType), type.isPrimitive());
+ assertNull(type.getComponentType());
+ assertTrue(!type.isArray());
+ assertEquals(0, type.getDimensions());
+ if (enums != null) {
+ assertTrue(type.isEnum());
+ assertEquals(enums, type.getEnumConstants());
+ assertNull(type.getSuperType());
+ } else {
+ assertTrue(!type.isEnum());
+ assertNull(type.getEnumConstants());
+ }
+ }
+ }
+
+ private List<String> getEnumConstants(String clsName) {
+ if (isPrimitiveType(clsName)) {
+ return null;
+ }
+ Class cls;
+ try {
+ cls = Class.forName(clsName);
+ } catch (ClassNotFoundException e) {
+ fail(e.toString());
+ return null; /* Never happens. */
+ }
+ if (!cls.isEnum()) {
+ return null;
+ }
+ List<String> enums = new ArrayList<String>();
+ Object[] vals = cls.getEnumConstants();
+ for (Object val : vals) {
+ enums.add(val.toString());
+ }
+ return enums;
+ }
+
+ private String getArrayComponent(String clsName, int dim) {
+ clsName = clsName.substring(1);
+ if (dim > 1) {
+ return clsName;
+ }
+ if (clsName.charAt(0) == 'L' &&
+ clsName.charAt(clsName.length() - 1) == ';') {
+ return clsName.substring(1, clsName.length() - 1);
+ }
+ if (clsName.length() != 1) {
+ fail();
+ }
+ switch (clsName.charAt(0)) {
+ case 'Z': return "boolean";
+ case 'B': return "byte";
+ case 'C': return "char";
+ case 'D': return "double";
+ case 'F': return "float";
+ case 'I': return "int";
+ case 'J': return "long";
+ case 'S': return "short";
+ default: fail();
+ }
+ return null; /* Should never happen. */
+ }
+
+ private static int getArrayDimensions(String clsName) {
+ int i = 0;
+ while (clsName.charAt(i) == '[') {
+ i += 1;
+ }
+ return i;
+ }
+
+ private static boolean isSimpleType(String clsName) {
+ return isPrimitiveType(clsName) ||
+ clsName.equals("java.lang.Boolean") ||
+ clsName.equals("java.lang.Character") ||
+ clsName.equals("java.lang.Byte") ||
+ clsName.equals("java.lang.Short") ||
+ clsName.equals("java.lang.Integer") ||
+ clsName.equals("java.lang.Long") ||
+ clsName.equals("java.lang.Float") ||
+ clsName.equals("java.lang.Double") ||
+ clsName.equals("java.lang.String") ||
+ clsName.equals("java.math.BigInteger") ||
+ //clsName.equals("java.math.BigDecimal") ||
+ clsName.equals("java.util.Date");
+ }
+
+ private static boolean isPrimitiveType(String clsName) {
+ return clsName.equals("boolean") ||
+ clsName.equals("char") ||
+ clsName.equals("byte") ||
+ clsName.equals("short") ||
+ clsName.equals("int") ||
+ clsName.equals("long") ||
+ clsName.equals("float") ||
+ clsName.equals("double");
+ }
+
+ interface MyEntity {
+ Object getPriKeyObject();
+ void validate(Object other);
+ }
+
+ private static boolean nullOrEqual(Object o1, Object o2) {
+ return (o1 != null) ? o1.equals(o2) : (o2 == null);
+ }
+
+ private static String arrayToString(Object[] array) {
+ StringBuffer buf = new StringBuffer();
+ buf.append('[');
+ for (Object o : array) {
+ if (o instanceof Object[]) {
+ buf.append(arrayToString((Object[]) o));
+ } else {
+ buf.append(o);
+ }
+ buf.append(',');
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+
+ private void setFieldToNull(Object obj, String fieldName) {
+ try {
+ Field field = obj.getClass().getDeclaredField(fieldName);
+ field.setAccessible(true);
+ field.set(obj, null);
+ } catch (NoSuchFieldException e) {
+ fail(e.toString());
+ } catch (IllegalAccessException e) {
+ fail(e.toString());
+ }
+ }
+
+ private void setField(Object obj, String fieldName, Object fieldValue) {
+ try {
+ Field field = obj.getClass().getDeclaredField(fieldName);
+ field.setAccessible(true);
+ field.set(obj, fieldValue);
+ } catch (NoSuchFieldException e) {
+ throw new IllegalStateException(e.toString());
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException(e.toString());
+ }
+ }
+
+ private Object getField(Object obj, String fieldName) {
+ try {
+ Field field = obj.getClass().getDeclaredField(fieldName);
+ field.setAccessible(true);
+ return field.get(obj);
+ } catch (NoSuchFieldException e) {
+ throw new IllegalStateException(e.toString());
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException(e.toString());
+ }
+ }
+}
diff --git a/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/Enhanced0.java b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/Enhanced0.java
new file mode 100644
index 0000000..f29a24c
--- /dev/null
+++ b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/Enhanced0.java
@@ -0,0 +1,36 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2002-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package com.sleepycat.persist.test;
+
+import static com.sleepycat.persist.model.Relationship.MANY_TO_ONE;
+
+import com.sleepycat.persist.model.Entity;
+import com.sleepycat.persist.model.PrimaryKey;
+import com.sleepycat.persist.model.SecondaryKey;
+
+/**
+ * For running ASMifier -- before any enhancements.
+ */
+@Entity
+class Enhanced0 {
+
+ @PrimaryKey
+ private String f1;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private int f2;
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private String f3;
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private String f4;
+
+ private int f5;
+ private String f6;
+ private String f7;
+}
diff --git a/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/Enhanced1.java b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/Enhanced1.java
new file mode 100644
index 0000000..2eb93ba
--- /dev/null
+++ b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/Enhanced1.java
@@ -0,0 +1,260 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2002-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package com.sleepycat.persist.test;
+
+import static com.sleepycat.persist.model.Relationship.MANY_TO_ONE;
+
+import com.sleepycat.persist.impl.Enhanced;
+import com.sleepycat.persist.impl.EnhancedAccessor;
+import com.sleepycat.persist.impl.EntityInput;
+import com.sleepycat.persist.impl.EntityOutput;
+import com.sleepycat.persist.impl.Format;
+import com.sleepycat.persist.model.Entity;
+import com.sleepycat.persist.model.PrimaryKey;
+import com.sleepycat.persist.model.SecondaryKey;
+
+/**
+ * For running ASMifier -- adds minimal enhancements.
+ */
+@Entity
+class Enhanced1 implements Enhanced {
+
+ @PrimaryKey
+ private String f1;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private int f2;
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private String f3;
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private String f4;
+
+ private int f5;
+ private String f6;
+ private String f7;
+ private int f8;
+ private int f9;
+ private int f10;
+ private int f11;
+ private int f12;
+
+ static {
+ EnhancedAccessor.registerClass(null, new Enhanced1());
+ }
+
+ public Object bdbNewInstance() {
+ return new Enhanced1();
+ }
+
+ public Object bdbNewArray(int len) {
+ return new Enhanced1[len];
+ }
+
+ public boolean bdbIsPriKeyFieldNullOrZero() {
+ return f1 == null;
+ }
+
+ public void bdbWritePriKeyField(EntityOutput output, Format format) {
+ output.writeKeyObject(f1, format);
+ }
+
+ public void bdbReadPriKeyField(EntityInput input, Format format) {
+ f1 = (String) input.readKeyObject(format);
+ }
+
+ public void bdbWriteSecKeyFields(EntityOutput output) {
+ /* If primary key is an object: */
+ output.registerPriKeyObject(f1);
+ /* Always: */
+ output.writeInt(f2);
+ output.writeObject(f3, null);
+ output.writeObject(f4, null);
+ }
+
+ public void bdbReadSecKeyFields(EntityInput input,
+ int startField,
+ int endField,
+ int superLevel) {
+ /* If primary key is an object: */
+ input.registerPriKeyObject(f1);
+
+ if (superLevel <= 0) {
+ switch (startField) {
+ case 0:
+ f2 = input.readInt();
+ if (endField == 0) break;
+ case 1:
+ f3 = (String) input.readObject();
+ if (endField == 1) break;
+ case 2:
+ f4 = (String) input.readObject();
+ }
+ }
+ }
+
+ public void bdbWriteNonKeyFields(EntityOutput output) {
+ output.writeInt(f5);
+ output.writeObject(f6, null);
+ output.writeObject(f7, null);
+ output.writeInt(f8);
+ output.writeInt(f9);
+ output.writeInt(f10);
+ output.writeInt(f11);
+ output.writeInt(f12);
+ }
+
+ public void bdbReadNonKeyFields(EntityInput input,
+ int startField,
+ int endField,
+ int superLevel) {
+ if (superLevel <= 0) {
+ switch (startField) {
+ case 0:
+ f5 = input.readInt();
+ if (endField == 0) break;
+ case 1:
+ f6 = (String) input.readObject();
+ if (endField == 1) break;
+ case 2:
+ f7 = (String) input.readObject();
+ if (endField == 2) break;
+ case 3:
+ f8 = input.readInt();
+ if (endField == 3) break;
+ case 4:
+ f9 = input.readInt();
+ if (endField == 4) break;
+ case 5:
+ f10 = input.readInt();
+ if (endField == 5) break;
+ case 6:
+ f11 = input.readInt();
+ if (endField == 6) break;
+ case 7:
+ f12 = input.readInt();
+ }
+ }
+ }
+
+ public void bdbWriteCompositeKeyFields(EntityOutput output,
+ Format[] formats) {
+ }
+
+ public void bdbReadCompositeKeyFields(EntityInput input,
+ Format[] formats) {
+ }
+
+ public boolean bdbNullifyKeyField(Object o,
+ int field,
+ int superLevel,
+ boolean isSecField,
+ Object keyElement) {
+ if (superLevel > 0) {
+ return false;
+ } else if (isSecField) {
+ switch (field) {
+ case 1:
+ if (f3 != null) {
+ f3 = null;
+ return true;
+ } else {
+ return false;
+ }
+ case 2:
+ if (f4 != null) {
+ f4 = null;
+ return true;
+ } else {
+ return false;
+ }
+ default:
+ return false;
+ }
+ } else {
+ switch (field) {
+ case 1:
+ if (f6 != null) {
+ f6 = null;
+ return true;
+ } else {
+ return false;
+ }
+ case 2:
+ if (f7 != null) {
+ f7 = null;
+ return true;
+ } else {
+ return false;
+ }
+ default:
+ return false;
+ }
+ }
+ }
+
+ public Object bdbGetField(Object o,
+ int field,
+ int superLevel,
+ boolean isSecField) {
+ if (superLevel > 0) {
+ } else if (isSecField) {
+ switch (field) {
+ case 0:
+ return Integer.valueOf(f2);
+ case 1:
+ return f3;
+ case 2:
+ return f4;
+ }
+ } else {
+ switch (field) {
+ case 0:
+ return Integer.valueOf(f5);
+ case 1:
+ return f6;
+ case 2:
+ return f7;
+ }
+ }
+ return null;
+ }
+
+ public void bdbSetField(Object o,
+ int field,
+ int superLevel,
+ boolean isSecField,
+ Object value) {
+ if (superLevel > 0) {
+ } else if (isSecField) {
+ switch (field) {
+ case 0:
+ f2 = ((Integer) value).intValue();
+ return;
+ case 1:
+ f3 = (String) value;
+ return;
+ case 2:
+ f4 = (String) value;
+ return;
+ }
+ } else {
+ switch (field) {
+ case 0:
+ f5 = ((Integer) value).intValue();
+ return;
+ case 1:
+ f6 = (String) value;
+ return;
+ case 2:
+ f7 = (String) value;
+ return;
+ }
+ }
+ }
+}
diff --git a/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/Enhanced2.java b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/Enhanced2.java
new file mode 100644
index 0000000..5cc2e06
--- /dev/null
+++ b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/Enhanced2.java
@@ -0,0 +1,110 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2002-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package com.sleepycat.persist.test;
+
+import com.sleepycat.persist.impl.EnhancedAccessor;
+import com.sleepycat.persist.impl.EntityInput;
+import com.sleepycat.persist.impl.EntityOutput;
+import com.sleepycat.persist.impl.Format;
+import com.sleepycat.persist.model.Persistent;
+
+/**
+ * For running ASMifier -- entity sublcass.
+ */
+@Persistent
+class Enhanced2 extends Enhanced1 {
+
+ static {
+ EnhancedAccessor.registerClass(null, new Enhanced2());
+ }
+
+ public Object bdbNewInstance() {
+ return new Enhanced2();
+ }
+
+ public Object bdbNewArray(int len) {
+ return new Enhanced2[len];
+ }
+
+ public boolean bdbIsPriKeyFieldNullOrZero() {
+ return super.bdbIsPriKeyFieldNullOrZero();
+ }
+
+ public void bdbWritePriKeyField(EntityOutput output, Format format) {
+ super.bdbWritePriKeyField(output, format);
+ }
+
+ public void bdbReadPriKeyField(EntityInput input, Format format) {
+ super.bdbReadPriKeyField(input, format);
+ }
+
+ public void bdbWriteSecKeyFields(EntityOutput output) {
+ super.bdbWriteSecKeyFields(output);
+ }
+
+ public void bdbReadSecKeyFields(EntityInput input,
+ int startField,
+ int endField,
+ int superLevel) {
+ if (superLevel != 0) {
+ super.bdbReadSecKeyFields
+ (input, startField, endField, superLevel - 1);
+ }
+ }
+
+ public void bdbWriteNonKeyFields(EntityOutput output) {
+ super.bdbWriteNonKeyFields(output);
+ }
+
+ public void bdbReadNonKeyFields(EntityInput input,
+ int startField,
+ int endField,
+ int superLevel) {
+ if (superLevel != 0) {
+ super.bdbReadNonKeyFields
+ (input, startField, endField, superLevel - 1);
+ }
+ }
+
+ public boolean bdbNullifyKeyField(Object o,
+ int field,
+ int superLevel,
+ boolean isSecField,
+ Object keyElement) {
+ if (superLevel > 0) {
+ return super.bdbNullifyKeyField
+ (o, field, superLevel - 1, isSecField, keyElement);
+ } else {
+ return false;
+ }
+ }
+
+ public Object bdbGetField(Object o,
+ int field,
+ int superLevel,
+ boolean isSecField) {
+ if (superLevel > 0) {
+ return super.bdbGetField
+ (o, field, superLevel - 1, isSecField);
+ } else {
+ return null;
+ }
+ }
+
+ public void bdbSetField(Object o,
+ int field,
+ int superLevel,
+ boolean isSecField,
+ Object value) {
+ if (superLevel > 0) {
+ super.bdbSetField
+ (o, field, superLevel - 1, isSecField, value);
+ }
+ }
+}
diff --git a/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/Enhanced3.java b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/Enhanced3.java
new file mode 100644
index 0000000..5b59a29
--- /dev/null
+++ b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/Enhanced3.java
@@ -0,0 +1,176 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2002-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package com.sleepycat.persist.test;
+
+/*
+import java.math.BigDecimal;
+*/
+import java.math.BigInteger;
+import java.util.Date;
+
+import com.sleepycat.persist.impl.Enhanced;
+import com.sleepycat.persist.impl.EnhancedAccessor;
+import com.sleepycat.persist.impl.EntityInput;
+import com.sleepycat.persist.impl.EntityOutput;
+import com.sleepycat.persist.impl.Format;
+import com.sleepycat.persist.model.KeyField;
+import com.sleepycat.persist.model.Persistent;
+
+/**
+ * For running ASMifier -- a composite key class using all simple data types,
+ * does not follow from previous EnhancedN.java files
+ */
+@Persistent
+class Enhanced3 implements Enhanced {
+
+ enum MyEnum { ONE, TWO };
+
+ @KeyField(1) boolean z;
+ @KeyField(2) char c;
+ @KeyField(3) byte b;
+ @KeyField(4) short s;
+ @KeyField(5) int i;
+ @KeyField(6) long l;
+ @KeyField(7) float f;
+ @KeyField(8) double d;
+
+ @KeyField(9) Boolean zw;
+ @KeyField(10) Character cw;
+ @KeyField(11) Byte bw;
+ @KeyField(12) Short sw;
+ @KeyField(13) Integer iw;
+ @KeyField(14) Long lw;
+ @KeyField(15) Float fw;
+ @KeyField(16) Double dw;
+
+ @KeyField(17) Date date;
+ @KeyField(18) String str;
+ @KeyField(19) MyEnum e;
+ @KeyField(20) BigInteger bigint;
+ /*
+ @KeyField(21) BigDecimal bigdec;
+ */
+
+ static {
+ EnhancedAccessor.registerClass(null, new Enhanced3());
+ }
+
+ public Object bdbNewInstance() {
+ return new Enhanced3();
+ }
+
+ public Object bdbNewArray(int len) {
+ return new Enhanced3[len];
+ }
+
+ public boolean bdbIsPriKeyFieldNullOrZero() {
+ return false;
+ }
+
+ public void bdbWritePriKeyField(EntityOutput output, Format format) {
+ }
+
+ public void bdbReadPriKeyField(EntityInput input, Format format) {
+ }
+
+ public void bdbWriteSecKeyFields(EntityOutput output) {
+ }
+
+ public void bdbReadSecKeyFields(EntityInput input,
+ int startField,
+ int endField,
+ int superLevel) {
+ }
+
+ public void bdbWriteNonKeyFields(EntityOutput output) {
+ }
+
+ public void bdbReadNonKeyFields(EntityInput input,
+ int startField,
+ int endField,
+ int superLevel) {
+ }
+
+ public void bdbWriteCompositeKeyFields(EntityOutput output,
+ Format[] formats) {
+ output.writeBoolean(z);
+ output.writeChar(c);
+ output.writeByte(b);
+ output.writeShort(s);
+ output.writeInt(i);
+ output.writeLong(l);
+ output.writeSortedFloat(f);
+ output.writeSortedDouble(d);
+
+ output.writeBoolean(zw.booleanValue());
+ output.writeChar(cw.charValue());
+ output.writeByte(bw.byteValue());
+ output.writeShort(sw.shortValue());
+ output.writeInt(iw.intValue());
+ output.writeLong(lw.longValue());
+ output.writeSortedFloat(fw.floatValue());
+ output.writeSortedDouble(dw.doubleValue());
+
+ output.writeLong(date.getTime());
+ output.writeString(str);
+ output.writeKeyObject(e, formats[18]);
+ output.writeBigInteger(bigint);
+ }
+
+ public void bdbReadCompositeKeyFields(EntityInput input,
+ Format[] formats) {
+ z = input.readBoolean();
+ c = input.readChar();
+ b = input.readByte();
+ s = input.readShort();
+ i = input.readInt();
+ l = input.readLong();
+ f = input.readSortedFloat();
+ d = input.readSortedDouble();
+
+ zw = Boolean.valueOf(input.readBoolean());
+ cw = Character.valueOf(input.readChar());
+ bw = Byte.valueOf(input.readByte());
+ sw = Short.valueOf(input.readShort());
+ iw = Integer.valueOf(input.readInt());
+ lw = Long.valueOf(input.readLong());
+ fw = Float.valueOf(input.readSortedFloat());
+ dw = Double.valueOf(input.readSortedDouble());
+
+ date = new Date(input.readLong());
+ str = input.readString();
+ e = (MyEnum) input.readKeyObject(formats[18]);
+ bigint = input.readBigInteger();
+ }
+
+ public boolean bdbNullifyKeyField(Object o,
+ int field,
+ int superLevel,
+ boolean isSecField,
+ Object keyElement) {
+ // Didn't bother with this one.
+ return false;
+ }
+
+ public Object bdbGetField(Object o,
+ int field,
+ int superLevel,
+ boolean isSecField) {
+ // Didn't bother with this one.
+ return null;
+ }
+
+ public void bdbSetField(Object o,
+ int field,
+ int superLevel,
+ boolean isSecField,
+ Object value) {
+ // Didn't bother with this one.
+ }
+}
diff --git a/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveCase.java b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveCase.java
new file mode 100644
index 0000000..4451efa
--- /dev/null
+++ b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveCase.java
@@ -0,0 +1,205 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+package com.sleepycat.persist.test;
+
+import java.util.Iterator;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import com.sleepycat.db.DatabaseException;
+import com.sleepycat.db.Environment;
+import com.sleepycat.persist.EntityStore;
+import com.sleepycat.persist.StoreConfig;
+import com.sleepycat.persist.evolve.Mutations;
+import com.sleepycat.persist.model.ClassMetadata;
+import com.sleepycat.persist.model.EntityModel;
+import com.sleepycat.persist.model.Persistent;
+import com.sleepycat.persist.raw.RawStore;
+import com.sleepycat.persist.raw.RawType;
+
+@Persistent
+abstract class EvolveCase {
+
+ static final String STORE_NAME = "foo";
+
+ transient boolean updated;
+
+ Mutations getMutations() {
+ return null;
+ }
+
+ void configure(EntityModel model, StoreConfig config) {
+ }
+
+ String getStoreOpenException() {
+ return null;
+ }
+
+ int getNRecordsExpected() {
+ return 1;
+ }
+
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ }
+
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ }
+
+ /**
+ * @throws DatabaseException from subclasses.
+ */
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+ }
+
+ /**
+ * @throws DatabaseException from subclasses.
+ */
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+ }
+
+ /**
+ * @throws DatabaseException from subclasses.
+ */
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+ }
+
+ /**
+ * @throws DatabaseException from subclasses.
+ */
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+ }
+
+ /**
+ * Checks for equality and prints the entire values rather than
+ * abbreviated values like TestCase.assertEquals does.
+ */
+ static void checkEquals(Object expected, Object got) {
+ if ((expected != null) ? (!expected.equals(got)) : (got != null)) {
+ TestCase.fail("Expected:\n" + expected + "\nBut got:\n" + got);
+ }
+ }
+
+ /**
+ * Asserts than an entity database exists or does not exist.
+ */
+ static void assertDbExists(boolean expectExists,
+ Environment env,
+ String entityClassName) {
+ assertDbExists(expectExists, env, entityClassName, null);
+ }
+
+ /**
+ * Checks that an entity class exists or does not exist.
+ */
+ static void checkEntity(boolean exists,
+ EntityModel model,
+ Environment env,
+ String className,
+ int version,
+ String secKeyName) {
+ if (exists) {
+ TestCase.assertNotNull(model.getEntityMetadata(className));
+ ClassMetadata meta = model.getClassMetadata(className);
+ TestCase.assertNotNull(meta);
+ TestCase.assertEquals(version, meta.getVersion());
+ TestCase.assertTrue(meta.isEntityClass());
+
+ RawType raw = model.getRawType(className);
+ TestCase.assertNotNull(raw);
+ TestCase.assertEquals(version, raw.getVersion());
+ } else {
+ TestCase.assertNull(model.getEntityMetadata(className));
+ TestCase.assertNull(model.getClassMetadata(className));
+ TestCase.assertNull(model.getRawType(className));
+ }
+
+ assertDbExists(exists, env, className);
+ if (secKeyName != null) {
+ assertDbExists(exists, env, className, secKeyName);
+ }
+ }
+
+ /**
+ * Checks that a non-entity class exists or does not exist.
+ */
+ static void checkNonEntity(boolean exists,
+ EntityModel model,
+ Environment env,
+ String className,
+ int version) {
+ if (exists) {
+ ClassMetadata meta = model.getClassMetadata(className);
+ TestCase.assertNotNull(meta);
+ TestCase.assertEquals(version, meta.getVersion());
+ TestCase.assertTrue(!meta.isEntityClass());
+
+ RawType raw = model.getRawType(className);
+ TestCase.assertNotNull(raw);
+ TestCase.assertEquals(version, raw.getVersion());
+ } else {
+ TestCase.assertNull(model.getClassMetadata(className));
+ TestCase.assertNull(model.getRawType(className));
+ }
+
+ TestCase.assertNull(model.getEntityMetadata(className));
+ assertDbExists(false, env, className);
+ }
+
+ /**
+ * Asserts than a database expectExists or does not exist. If keyName is
+ * null, checks an entity database. If keyName is non-null, checks a
+ * secondary database.
+ */
+ static void assertDbExists(boolean expectExists,
+ Environment env,
+ String entityClassName,
+ String keyName) {
+ PersistTestUtils.assertDbExists
+ (expectExists, env, STORE_NAME, entityClassName, keyName);
+ }
+
+ static void checkVersions(EntityModel model, String name, int version) {
+ checkVersions(model, new String[] {name}, new int[] {version});
+ }
+
+ static void checkVersions(EntityModel model,
+ String name1,
+ int version1,
+ String name2,
+ int version2) {
+ checkVersions
+ (model, new String[] {name1, name2},
+ new int[] {version1, version2});
+ }
+
+ private static void checkVersions(EntityModel model,
+ String[] names,
+ int[] versions) {
+ List<RawType> all = model.getAllRawTypeVersions(names[0]);
+ TestCase.assertNotNull(all);
+
+ assert names.length == versions.length;
+ TestCase.assertEquals(all.toString(), names.length, all.size());
+
+ Iterator<RawType> iter = all.iterator();
+ for (int i = 0; i < names.length; i += 1) {
+ RawType type = iter.next();
+ TestCase.assertEquals(versions[i], type.getVersion());
+ TestCase.assertEquals(names[i], type.getClassName());
+ }
+ }
+}
diff --git a/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveClasses.java b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveClasses.java
new file mode 100644
index 0000000..058aef3
--- /dev/null
+++ b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveClasses.java
@@ -0,0 +1,6818 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+package com.sleepycat.persist.test;
+
+import static com.sleepycat.persist.model.Relationship.MANY_TO_ONE;
+import static com.sleepycat.persist.model.Relationship.ONE_TO_ONE;
+
+import java.math.BigInteger;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import junit.framework.TestCase;
+
+import com.sleepycat.db.DatabaseException;
+import com.sleepycat.db.Environment;
+import com.sleepycat.persist.EntityStore;
+import com.sleepycat.persist.PrimaryIndex;
+import com.sleepycat.persist.SecondaryIndex;
+import com.sleepycat.persist.StoreConfig;
+import com.sleepycat.persist.evolve.Conversion;
+import com.sleepycat.persist.evolve.Converter;
+import com.sleepycat.persist.evolve.Deleter;
+import com.sleepycat.persist.evolve.EntityConverter;
+import com.sleepycat.persist.evolve.Mutations;
+import com.sleepycat.persist.evolve.Renamer;
+import com.sleepycat.persist.model.Entity;
+import com.sleepycat.persist.model.EntityModel;
+import com.sleepycat.persist.model.KeyField;
+import com.sleepycat.persist.model.Persistent;
+import com.sleepycat.persist.model.PersistentProxy;
+import com.sleepycat.persist.model.PrimaryKey;
+import com.sleepycat.persist.model.SecondaryKey;
+import com.sleepycat.persist.raw.RawObject;
+import com.sleepycat.persist.raw.RawStore;
+import com.sleepycat.persist.raw.RawType;
+
+/**
+ * Nested classes are modified versions of classes of the same name in
+ * EvolveClasses.java.original. See EvolveTestBase.java for the steps that are
+ * taken to add a new class (test case).
+ *
+ * @author Mark Hayes
+ */
+class EvolveClasses {
+
+ private static final String PREFIX = EvolveClasses.class.getName() + '$';
+ private static final String CASECLS = EvolveCase.class.getName();
+
+ private static RawObject readRaw(RawStore store,
+ Object key,
+ Object... classVersionPairs)
+ throws DatabaseException {
+
+ return readRaw(store, null, key, classVersionPairs);
+ }
+
+ /**
+ * Reads a raw object and checks its superclass names and versions.
+ */
+ private static RawObject readRaw(RawStore store,
+ String entityClsName,
+ Object key,
+ Object... classVersionPairs)
+ throws DatabaseException {
+
+ TestCase.assertNotNull(store);
+ TestCase.assertNotNull(key);
+
+ if (entityClsName == null) {
+ entityClsName = (String) classVersionPairs[0];
+ }
+ PrimaryIndex<Object,RawObject> index =
+ store.getPrimaryIndex(entityClsName);
+ TestCase.assertNotNull(index);
+
+ RawObject obj = index.get(key);
+ TestCase.assertNotNull(obj);
+
+ checkRawType(obj.getType(), classVersionPairs);
+
+ RawObject superObj = obj.getSuper();
+ for (int i = 2; i < classVersionPairs.length; i += 2) {
+ Object[] a = new Object[classVersionPairs.length - i];
+ System.arraycopy(classVersionPairs, i, a, 0, a.length);
+ TestCase.assertNotNull(superObj);
+ checkRawType(superObj.getType(), a);
+ superObj = superObj.getSuper();
+ }
+
+ return obj;
+ }
+
+ /**
+ * Reads a raw object and checks its superclass names and versions.
+ */
+ private static void checkRawType(RawType type,
+ Object... classVersionPairs) {
+ TestCase.assertNotNull(type);
+ TestCase.assertNotNull(classVersionPairs);
+ TestCase.assertTrue(classVersionPairs.length % 2 == 0);
+
+ for (int i = 0; i < classVersionPairs.length; i += 2) {
+ String clsName = (String) classVersionPairs[i];
+ int clsVersion = (Integer) classVersionPairs[i + 1];
+ TestCase.assertEquals(clsName, type.getClassName());
+ TestCase.assertEquals(clsVersion, type.getVersion());
+ type = type.getSuperType();
+ }
+ TestCase.assertNull(type);
+ }
+
+ /**
+ * Checks that a raw object contains the specified field values. Does not
+ * check superclass fields.
+ */
+ private static void checkRawFields(RawObject obj,
+ Object... nameValuePairs) {
+ TestCase.assertNotNull(obj);
+ TestCase.assertNotNull(obj.getValues());
+ TestCase.assertNotNull(nameValuePairs);
+ TestCase.assertTrue(nameValuePairs.length % 2 == 0);
+
+ Map<String,Object> values = obj.getValues();
+ TestCase.assertEquals(nameValuePairs.length / 2, values.size());
+
+ for (int i = 0; i < nameValuePairs.length; i += 2) {
+ String name = (String) nameValuePairs[i];
+ Object value = nameValuePairs[i + 1];
+ TestCase.assertEquals(name, value, values.get(name));
+ }
+ }
+
+ private static Map<String,Object> makeValues(Object... nameValuePairs) {
+ TestCase.assertTrue(nameValuePairs.length % 2 == 0);
+ Map<String,Object> values = new HashMap<String,Object>();
+ for (int i = 0; i < nameValuePairs.length; i += 2) {
+ values.put((String) nameValuePairs[i], nameValuePairs[i + 1]);
+ }
+ return values;
+ }
+
+ /**
+ * Disallow removing an entity class when no Deleter mutation is specified.
+ */
+ static class DeletedEntity1_ClassRemoved_NoMutation extends EvolveCase {
+
+ private static final String NAME =
+ PREFIX + "DeletedEntity1_ClassRemoved";
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DeletedEntity1_ClassRemoved version: 0 Error: java.lang.ClassNotFoundException: com.sleepycat.persist.test.EvolveClasses$DeletedEntity1_ClassRemoved";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, "skey");
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "skey", 88);
+ }
+ }
+
+ /**
+ * Allow removing an entity class when a Deleter mutation is specified.
+ */
+ static class DeletedEntity2_ClassRemoved_WithDeleter extends EvolveCase {
+
+ private static final String NAME =
+ PREFIX + "DeletedEntity2_ClassRemoved";
+
+ @Override
+ int getNRecordsExpected() {
+ return 0;
+ }
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ m.addDeleter(new Deleter(NAME, 0));
+ return m;
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(false, model, env, NAME, 0, "skey");
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 0);
+ }
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ return;
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "skey", 88);
+ }
+ }
+
+ /**
+ * Disallow removing the Entity annotation when no Deleter mutation is
+ * specified.
+ */
+ static class DeletedEntity3_AnnotRemoved_NoMutation extends EvolveCase {
+
+ private static final String NAME =
+ DeletedEntity3_AnnotRemoved_NoMutation.class.getName();
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DeletedEntity3_AnnotRemoved_NoMutation version: 0 Error: java.lang.IllegalArgumentException: Class could not be loaded or is not persistent: com.sleepycat.persist.test.EvolveClasses$DeletedEntity3_AnnotRemoved_NoMutation";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, "skey");
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "skey", 88);
+ }
+ }
+
+ /**
+ * Allow removing the Entity annotation when a Deleter mutation is
+ * specified.
+ */
+ static class DeletedEntity4_AnnotRemoved_WithDeleter extends EvolveCase {
+
+ private static final String NAME =
+ DeletedEntity4_AnnotRemoved_WithDeleter.class.getName();
+
+ @Override
+ int getNRecordsExpected() {
+ return 0;
+ }
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ m.addDeleter(new Deleter(NAME, 0));
+ return m;
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(false, model, env, NAME, 0, "skey");
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 0);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate) {
+ try {
+ store.getPrimaryIndex
+ (Integer.class,
+ DeletedEntity4_AnnotRemoved_WithDeleter.class);
+ TestCase.fail();
+ } catch (Exception e) {
+ checkEquals
+ ("java.lang.IllegalArgumentException: Class could not be loaded or is not an entity class: com.sleepycat.persist.test.EvolveClasses$DeletedEntity4_AnnotRemoved_WithDeleter",
+ e.toString());
+ }
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ return;
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "skey", 88);
+ }
+ }
+
+ /**
+ * Disallow changing the Entity annotation to Persistent when no Deleter
+ * mutation is specified.
+ */
+ @Persistent(version=1)
+ static class DeletedEntity5_EntityToPersist_NoMutation extends EvolveCase {
+
+ private static final String NAME =
+ DeletedEntity5_EntityToPersist_NoMutation.class.getName();
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DeletedEntity5_EntityToPersist_NoMutation version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DeletedEntity5_EntityToPersist_NoMutation version: 1 Error: @Entity switched to/from @Persistent";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, "skey");
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "skey", 88);
+ }
+ }
+
+ /**
+ * Allow changing the Entity annotation to Persistent when a Deleter
+ * mutation is specified.
+ */
+ @Persistent(version=1)
+ static class DeletedEntity6_EntityToPersist_WithDeleter extends EvolveCase {
+
+ private static final String NAME =
+ DeletedEntity6_EntityToPersist_WithDeleter.class.getName();
+ private static final String NAME2 =
+ Embed_DeletedEntity6_EntityToPersist_WithDeleter.class.getName();
+
+ @Override
+ int getNRecordsExpected() {
+ return 0;
+ }
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ m.addDeleter(new Deleter(NAME, 0));
+ return m;
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkNonEntity(true, model, env, NAME, 1);
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 1, NAME, 0);
+ } else {
+ checkVersions(model, NAME, 1);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ /* Cannot get the primary index for the former entity class. */
+ try {
+ store.getPrimaryIndex
+ (Integer.class,
+ DeletedEntity6_EntityToPersist_WithDeleter.class);
+ TestCase.fail();
+ } catch (Exception e) {
+ checkEquals
+ ("java.lang.IllegalArgumentException: Class could not be loaded or is not an entity class: com.sleepycat.persist.test.EvolveClasses$DeletedEntity6_EntityToPersist_WithDeleter",
+ e.toString());
+ }
+
+ /* Can embed the now persistent class in another entity class. */
+ PrimaryIndex<Long,
+ Embed_DeletedEntity6_EntityToPersist_WithDeleter>
+ index = store.getPrimaryIndex
+ (Long.class,
+ Embed_DeletedEntity6_EntityToPersist_WithDeleter.class);
+
+ if (doUpdate) {
+ Embed_DeletedEntity6_EntityToPersist_WithDeleter embed =
+ new Embed_DeletedEntity6_EntityToPersist_WithDeleter();
+ index.put(embed);
+ embed = index.get(embed.key);
+ /* This new type should exist only after update. */
+ Environment env = store.getEnvironment();
+ EntityModel model = store.getModel();
+ checkEntity(true, model, env, NAME2, 0, null);
+ checkVersions(model, NAME2, 0);
+ }
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ return;
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "skey", 88);
+ }
+ }
+
+ @Entity
+ static class Embed_DeletedEntity6_EntityToPersist_WithDeleter {
+
+ @PrimaryKey
+ long key = 99;
+
+ DeletedEntity6_EntityToPersist_WithDeleter embedded =
+ new DeletedEntity6_EntityToPersist_WithDeleter();
+ }
+
+ /**
+ * Disallow removing a Persistent class when no Deleter mutation is
+ * specified, even when the Entity class that embedded the Persistent class
+ * is deleted properly (by removing the Entity annotation in this case).
+ */
+ static class DeletedPersist1_ClassRemoved_NoMutation extends EvolveCase {
+
+ private static final String NAME =
+ PREFIX + "DeletedPersist1_ClassRemoved";
+
+ private static final String NAME2 =
+ DeletedPersist1_ClassRemoved_NoMutation.class.getName();
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ m.addDeleter(new Deleter(NAME2, 0));
+ return m;
+ }
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DeletedPersist1_ClassRemoved version: 0 Error: java.lang.ClassNotFoundException: com.sleepycat.persist.test.EvolveClasses$DeletedPersist1_ClassRemoved";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkNonEntity(true, model, env, NAME, 0);
+ checkEntity(true, model, env, NAME2, 0, null);
+ checkVersions(model, NAME, 0);
+ checkVersions(model, NAME2, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+
+ RawType embedType = store.getModel().getRawType(NAME);
+ checkRawType(embedType, NAME, 0);
+
+ RawObject embed =
+ new RawObject(embedType, makeValues("f", 123), null);
+
+ RawObject obj = readRaw(store, 99, NAME2, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "embed", embed);
+ }
+ }
+
+ /**
+ * Allow removing a Persistent class when a Deleter mutation is
+ * specified, and the Entity class that embedded the Persistent class
+ * is also deleted properly (by removing the Entity annotation in this
+ * case).
+ */
+ static class DeletedPersist2_ClassRemoved_WithDeleter extends EvolveCase {
+
+ private static final String NAME =
+ PREFIX + "DeletedPersist2_ClassRemoved";
+ private static final String NAME2 =
+ DeletedPersist2_ClassRemoved_WithDeleter.class.getName();
+
+ @Override
+ int getNRecordsExpected() {
+ return 0;
+ }
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ m.addDeleter(new Deleter(NAME, 0));
+ m.addDeleter(new Deleter(NAME2, 0));
+ return m;
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkNonEntity(false, model, env, NAME, 0);
+ checkEntity(false, model, env, NAME2, 0, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 0);
+ checkVersions(model, NAME2, 0);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate) {
+ try {
+ store.getPrimaryIndex
+ (Integer.class,
+ DeletedPersist2_ClassRemoved_WithDeleter.class);
+ TestCase.fail();
+ } catch (Exception e) {
+ checkEquals
+ ("java.lang.IllegalArgumentException: Class could not be loaded or is not an entity class: com.sleepycat.persist.test.EvolveClasses$DeletedPersist2_ClassRemoved_WithDeleter",
+ e.toString());
+ }
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ return;
+ }
+
+ RawType embedType = store.getModel().getRawType(NAME);
+ checkRawType(embedType, NAME, 0);
+
+ RawObject embed =
+ new RawObject(embedType, makeValues("f", 123), null);
+
+ RawObject obj = readRaw(store, 99, NAME2, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "embed", embed);
+ }
+ }
+
+ static class DeletedPersist3_AnnotRemoved {
+
+ int f = 123;
+ }
+
+ /**
+ * Disallow removing the Persistent annotation when no Deleter mutation is
+ * specified, even when the Entity class that embedded the Persistent class
+ * is deleted properly (by removing the Entity annotation in this case).
+ */
+ static class DeletedPersist3_AnnotRemoved_NoMutation extends EvolveCase {
+
+ private static final String NAME =
+ DeletedPersist3_AnnotRemoved.class.getName();
+ private static final String NAME2 =
+ DeletedPersist3_AnnotRemoved_NoMutation.class.getName();
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ m.addDeleter(new Deleter(NAME2, 0));
+ return m;
+ }
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DeletedPersist3_AnnotRemoved version: 0 Error: java.lang.IllegalArgumentException: Class could not be loaded or is not persistent: com.sleepycat.persist.test.EvolveClasses$DeletedPersist3_AnnotRemoved";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkNonEntity(true, model, env, NAME, 0);
+ checkEntity(true, model, env, NAME2, 0, null);
+ checkVersions(model, NAME, 0);
+ checkVersions(model, NAME2, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+
+ RawType embedType = store.getModel().getRawType(NAME);
+ checkRawType(embedType, NAME, 0);
+
+ RawObject embed =
+ new RawObject(embedType, makeValues("f", 123), null);
+
+ RawObject obj = readRaw(store, 99, NAME2, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "embed", embed);
+ }
+ }
+
+ static class DeletedPersist4_AnnotRemoved {
+
+ int f = 123;
+ }
+
+ /**
+ * Allow removing the Persistent annotation when a Deleter mutation is
+ * specified, and the Entity class that embedded the Persistent class
+ * is also be deleted properly (by removing the Entity annotation in this
+ * case).
+ */
+ static class DeletedPersist4_AnnotRemoved_WithDeleter extends EvolveCase {
+
+ private static final String NAME =
+ DeletedPersist4_AnnotRemoved.class.getName();
+ private static final String NAME2 =
+ DeletedPersist4_AnnotRemoved_WithDeleter.class.getName();
+
+ @Override
+ int getNRecordsExpected() {
+ return 0;
+ }
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ m.addDeleter(new Deleter(NAME, 0));
+ m.addDeleter(new Deleter(NAME2, 0));
+ return m;
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkNonEntity(false, model, env, NAME, 0);
+ checkEntity(false, model, env, NAME2, 0, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 0);
+ checkVersions(model, NAME2, 0);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate) {
+ try {
+ store.getPrimaryIndex
+ (Integer.class,
+ DeletedPersist4_AnnotRemoved_WithDeleter.class);
+ TestCase.fail();
+ } catch (Exception e) {
+ checkEquals
+ ("java.lang.IllegalArgumentException: Class could not be loaded or is not an entity class: com.sleepycat.persist.test.EvolveClasses$DeletedPersist4_AnnotRemoved_WithDeleter",
+ e.toString());
+ }
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ return;
+ }
+
+ RawType embedType = store.getModel().getRawType(NAME);
+ checkRawType(embedType, NAME, 0);
+
+ RawObject embed =
+ new RawObject(embedType, makeValues("f", 123), null);
+
+ RawObject obj = readRaw(store, 99, NAME2, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "embed", embed);
+ }
+ }
+
+ @Entity(version=1)
+ static class DeletedPersist5_PersistToEntity {
+
+ @PrimaryKey
+ int key = 99;
+
+ int f = 123;
+ }
+
+ /**
+ * Disallow changing the Entity annotation to Persistent when no Deleter
+ * mutation is specified, even when the Entity class that embedded the
+ * Persistent class is deleted properly (by removing the Entity annotation
+ * in this case).
+ */
+ static class DeletedPersist5_PersistToEntity_NoMutation
+ extends EvolveCase {
+
+ private static final String NAME =
+ DeletedPersist5_PersistToEntity.class.getName();
+ private static final String NAME2 =
+ DeletedPersist5_PersistToEntity_NoMutation.class.getName();
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ m.addDeleter(new Deleter(NAME2, 0));
+ return m;
+ }
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DeletedPersist5_PersistToEntity version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DeletedPersist5_PersistToEntity version: 1 Error: @Entity switched to/from @Persistent";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkNonEntity(true, model, env, NAME, 0);
+ checkEntity(true, model, env, NAME2, 0, null);
+ checkVersions(model, NAME, 0);
+ checkVersions(model, NAME2, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+
+ RawType embedType = store.getModel().getRawType(NAME);
+ checkRawType(embedType, NAME, 0);
+
+ RawObject embed =
+ new RawObject(embedType, makeValues("f", 123), null);
+
+ RawObject obj = readRaw(store, 99, NAME2, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "embed", embed);
+ }
+ }
+
+ @Entity(version=1)
+ static class DeletedPersist6_PersistToEntity {
+
+ @PrimaryKey
+ int key = 99;
+
+ int f = 123;
+ }
+
+ /**
+ * Allow changing the Entity annotation to Persistent when a Deleter
+ * mutation is specified, and the Entity class that embedded the Persistent
+ * class is also be deleted properly (by removing the Entity annotation in
+ * this case).
+ */
+ static class DeletedPersist6_PersistToEntity_WithDeleter
+ extends EvolveCase {
+
+ private static final String NAME =
+ DeletedPersist6_PersistToEntity.class.getName();
+ private static final String NAME2 =
+ DeletedPersist6_PersistToEntity_WithDeleter.class.getName();
+
+ @Override
+ int getNRecordsExpected() {
+ return 0;
+ }
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ m.addDeleter(new Deleter(NAME, 0));
+ m.addDeleter(new Deleter(NAME2, 0));
+ return m;
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(false, model, env, NAME2, 0, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 1, NAME, 0);
+ checkVersions(model, NAME2, 0);
+ } else {
+ checkVersions(model, NAME, 1);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ /* Cannot get the primary index for the former entity class. */
+ try {
+ store.getPrimaryIndex
+ (Integer.class,
+ DeletedPersist6_PersistToEntity_WithDeleter.class);
+ TestCase.fail();
+ } catch (Exception e) {
+ checkEquals
+ ("java.lang.IllegalArgumentException: Class could not be loaded or is not an entity class: com.sleepycat.persist.test.EvolveClasses$DeletedPersist6_PersistToEntity_WithDeleter",
+ e.toString());
+ }
+
+ /* Can use the primary index of the now entity class. */
+ PrimaryIndex<Integer,
+ DeletedPersist6_PersistToEntity>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeletedPersist6_PersistToEntity.class);
+
+ if (doUpdate) {
+ DeletedPersist6_PersistToEntity obj =
+ new DeletedPersist6_PersistToEntity();
+ index.put(obj);
+ obj = index.get(obj.key);
+ /* This new type should exist only after update. */
+ Environment env = store.getEnvironment();
+ EntityModel model = store.getModel();
+ checkEntity(true, model, env, NAME, 1, null);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,
+ DeletedPersist6_PersistToEntity>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ DeletedPersist6_PersistToEntity.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get(99);
+ index.put((DeletedPersist6_PersistToEntity)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ return;
+ }
+
+ RawType embedType = store.getModel().getRawType(NAME);
+ checkRawType(embedType, NAME, 0);
+
+ RawObject embed =
+ new RawObject(embedType, makeValues("f", 123), null);
+
+ RawObject obj = readRaw(store, 99, NAME2, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "embed", embed);
+ }
+ }
+
+ /**
+ * Disallow renaming an entity class without a Renamer mutation.
+ */
+ @Entity(version=1)
+ static class RenamedEntity1_NewEntityName_NoMutation
+ extends EvolveCase {
+
+ private static final String NAME =
+ PREFIX + "RenamedEntity1_NewEntityName";
+ private static final String NAME2 =
+ RenamedEntity1_NewEntityName_NoMutation.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int skey = 88;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$RenamedEntity1_NewEntityName version: 0 Error: java.lang.ClassNotFoundException: com.sleepycat.persist.test.EvolveClasses$RenamedEntity1_NewEntityName";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, "skey");
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "skey", 88);
+ }
+ }
+
+ /**
+ * Allow renaming an entity class with a Renamer mutation.
+ */
+ @Entity(version=1)
+ static class RenamedEntity2_NewEntityName_WithRenamer
+ extends EvolveCase {
+
+ private static final String NAME =
+ PREFIX + "RenamedEntity2_NewEntityName";
+ private static final String NAME2 =
+ RenamedEntity2_NewEntityName_WithRenamer.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int skey = 88;
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ m.addRenamer(new Renamer(NAME, 0, NAME2));
+ return m;
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(false, model, env, NAME, 0, null);
+ checkEntity(true, model, env, NAME2, 1, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME2, 1, NAME, 0);
+ } else {
+ checkVersions(model, NAME2, 1);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,RenamedEntity2_NewEntityName_WithRenamer>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ RenamedEntity2_NewEntityName_WithRenamer.class);
+ RenamedEntity2_NewEntityName_WithRenamer obj = index.get(key);
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertEquals(88, obj.skey);
+
+ SecondaryIndex<Integer,Integer,
+ RenamedEntity2_NewEntityName_WithRenamer>
+ sindex = store.getSecondaryIndex(index, Integer.class, "skey");
+ obj = sindex.get(88);
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertEquals(88, obj.skey);
+
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,RenamedEntity2_NewEntityName_WithRenamer>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ RenamedEntity2_NewEntityName_WithRenamer.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME2).get(99);
+ index.put((RenamedEntity2_NewEntityName_WithRenamer)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawObject obj;
+ if (expectEvolved) {
+ obj = readRaw(store, 99, NAME2, 1, CASECLS, 0);
+ } else {
+ obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ }
+ checkRawFields(obj, "key", 99, "skey", 88);
+ }
+ }
+
+ @Persistent
+ static class DeleteSuperclass1_BaseClass
+ extends EvolveCase {
+
+ int f = 123;
+ }
+
+ /**
+ * Disallow deleting a superclass from the hierarchy when the superclass
+ * has persistent fields and no Deleter or Converter is specified.
+ */
+ @Entity
+ static class DeleteSuperclass1_NoMutation
+ extends EvolveCase {
+
+ private static final String NAME =
+ DeleteSuperclass1_BaseClass.class.getName();
+ private static final String NAME2 =
+ DeleteSuperclass1_NoMutation.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ int ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DeleteSuperclass1_NoMutation version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DeleteSuperclass1_NoMutation version: 0 Error: When a superclass is removed from the class hierarchy, the superclass or all of its persistent fields must be deleted with a Deleter: com.sleepycat.persist.test.EvolveClasses$DeleteSuperclass1_BaseClass";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkNonEntity(true, model, env, NAME, 0);
+ checkEntity(true, model, env, NAME2, 0, null);
+ checkVersions(model, NAME, 0);
+ checkVersions(model, NAME2, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME2, 0, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", 88);
+ checkRawFields(obj.getSuper(), "f", 123);
+ checkRawFields(obj.getSuper().getSuper());
+ }
+ }
+
+ @Persistent
+ static class DeleteSuperclass2_BaseClass
+ extends EvolveCase {
+
+ int f;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int skey;
+ }
+
+ /**
+ * Allow deleting a superclass from the hierarchy when the superclass has
+ * persistent fields and a class Converter is specified. Also check that
+ * the secondary key field in the deleted base class is handled properly.
+ */
+ @Entity(version=1)
+ static class DeleteSuperclass2_WithConverter extends EvolveCase {
+
+ private static final String NAME =
+ DeleteSuperclass2_BaseClass.class.getName();
+ private static final String NAME2 =
+ DeleteSuperclass2_WithConverter.class.getName();
+
+ @PrimaryKey
+ int key;
+
+ int ff;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ Integer skey2;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int skey3;
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ m.addConverter(new EntityConverter
+ (NAME2, 0, new MyConversion(),
+ Collections.singleton("skey")));
+ return m;
+ }
+
+ @SuppressWarnings("serial")
+ static class MyConversion implements Conversion {
+
+ transient RawType newType;
+
+ public void initialize(EntityModel model) {
+ newType = model.getRawType(NAME2);
+ TestCase.assertNotNull(newType);
+ }
+
+ public Object convert(Object fromValue) {
+ TestCase.assertNotNull(newType);
+ RawObject obj = (RawObject) fromValue;
+ RawObject newSuper = obj.getSuper().getSuper();
+ return new RawObject(newType, obj.getValues(), newSuper);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other instanceof MyConversion;
+ }
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME2, 1, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME2, 1, NAME2, 0);
+ checkNonEntity(true, model, env, NAME, 0);
+ checkVersions(model, NAME, 0);
+ } else {
+ checkVersions(model, NAME2, 1);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeleteSuperclass2_WithConverter>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeleteSuperclass2_WithConverter.class);
+ DeleteSuperclass2_WithConverter obj = index.get(99);
+ TestCase.assertNotNull(obj);
+ TestCase.assertSame
+ (EvolveCase.class, obj.getClass().getSuperclass());
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertEquals(88, obj.ff);
+ TestCase.assertEquals(Integer.valueOf(77), obj.skey2);
+ TestCase.assertEquals(66, obj.skey3);
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeleteSuperclass2_WithConverter>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ DeleteSuperclass2_WithConverter.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME2).get(99);
+ index.put((DeleteSuperclass2_WithConverter)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawObject obj;
+ if (expectEvolved) {
+ obj = readRaw(store, 99, NAME2, 1, CASECLS, 0);
+ } else {
+ obj = readRaw(store, 99, NAME2, 0, NAME, 0, CASECLS, 0);
+ }
+ checkRawFields
+ (obj, "key", 99, "ff", 88, "skey2", 77, "skey3", 66);
+ if (expectEvolved) {
+ checkRawFields(obj.getSuper());
+ } else {
+ checkRawFields(obj.getSuper(), "f", 123, "skey", 456);
+ checkRawFields(obj.getSuper().getSuper());
+ }
+ Environment env = store.getEnvironment();
+ assertDbExists(!expectEvolved, env, NAME2, "skey");
+ assertDbExists(true, env, NAME2, "skey3");
+ }
+ }
+
+ static class DeleteSuperclass3_BaseClass
+ extends EvolveCase {
+
+ int f;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int skey;
+ }
+
+ /**
+ * Allow deleting a superclass from the hierarchy when the superclass
+ * has persistent fields and a class Deleter is specified. Also check that
+ * the secondary key field in the deleted base class is handled properly.
+ */
+ @Entity(version=1)
+ static class DeleteSuperclass3_WithDeleter extends EvolveCase {
+
+ private static final String NAME =
+ DeleteSuperclass3_BaseClass.class.getName();
+ private static final String NAME2 =
+ DeleteSuperclass3_WithDeleter.class.getName();
+
+ @PrimaryKey
+ int key;
+
+ int ff;
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ m.addDeleter(new Deleter(NAME, 0));
+ return m;
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME2, 1, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME2, 1, NAME2, 0);
+ checkNonEntity(false, model, env, NAME, 0);
+ checkVersions(model, NAME, 0);
+ } else {
+ checkVersions(model, NAME2, 1);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeleteSuperclass3_WithDeleter>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeleteSuperclass3_WithDeleter.class);
+ DeleteSuperclass3_WithDeleter obj = index.get(99);
+ TestCase.assertNotNull(obj);
+ TestCase.assertSame
+ (EvolveCase.class, obj.getClass().getSuperclass());
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertEquals(88, obj.ff);
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeleteSuperclass3_WithDeleter>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ DeleteSuperclass3_WithDeleter.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME2).get(99);
+ index.put((DeleteSuperclass3_WithDeleter)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawObject obj;
+ if (expectEvolved) {
+ obj = readRaw(store, 99, NAME2, 1, CASECLS, 0);
+ } else {
+ obj = readRaw(store, 99, NAME2, 0, NAME, 0, CASECLS, 0);
+ }
+ checkRawFields(obj, "key", 99, "ff", 88);
+ if (expectEvolved) {
+ checkRawFields(obj.getSuper());
+ } else {
+ checkRawFields(obj.getSuper(), "f", 123, "skey", 456);
+ checkRawFields(obj.getSuper().getSuper());
+ }
+ Environment env = store.getEnvironment();
+ assertDbExists(!expectEvolved, env, NAME2, "skey");
+ }
+ }
+
+ @Persistent
+ static class DeleteSuperclass4_BaseClass
+ extends EvolveCase {
+ }
+
+ /**
+ * Allow deleting a superclass from the hierarchy when the superclass
+ * has NO persistent fields. No mutations are needed.
+ */
+ @Entity(version=1)
+ static class DeleteSuperclass4_NoFields extends EvolveCase {
+
+ private static final String NAME =
+ DeleteSuperclass4_BaseClass.class.getName();
+ private static final String NAME2 =
+ DeleteSuperclass4_NoFields.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ int ff;
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME2, 1, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME2, 1, NAME2, 0);
+ checkNonEntity(true, model, env, NAME, 0);
+ checkVersions(model, NAME, 0);
+ } else {
+ checkVersions(model, NAME2, 1);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeleteSuperclass4_NoFields>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeleteSuperclass4_NoFields.class);
+ DeleteSuperclass4_NoFields obj = index.get(key);
+ TestCase.assertNotNull(obj);
+ TestCase.assertSame
+ (EvolveCase.class, obj.getClass().getSuperclass());
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertEquals(88, obj.ff);
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeleteSuperclass4_NoFields>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ DeleteSuperclass4_NoFields.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME2).get(99);
+ index.put((DeleteSuperclass4_NoFields)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawObject obj;
+ if (expectEvolved) {
+ obj = readRaw(store, 99, NAME2, 1, CASECLS, 0);
+ } else {
+ obj = readRaw(store, 99, NAME2, 0, NAME, 0, CASECLS, 0);
+ }
+ checkRawFields(obj, "key", 99, "ff", 88);
+ checkRawFields(obj.getSuper());
+ if (expectEvolved) {
+ TestCase.assertNull(obj.getSuper().getSuper());
+ } else {
+ checkRawFields(obj.getSuper().getSuper());
+ }
+ }
+ }
+
+ @Persistent(version=1)
+ static class DeleteSuperclass5_Embedded {
+
+ int f;
+
+ @Override
+ public String toString() {
+ return "" + f;
+ }
+ }
+
+ /**
+ * Ensure that a superclass at the top of the hierarchy can be deleted. A
+ * class Deleter is used.
+ */
+ @Entity
+ static class DeleteSuperclass5_Top
+ extends EvolveCase {
+
+ private static final String NAME =
+ DeleteSuperclass5_Top.class.getName();
+ private static final String NAME2 =
+ DeleteSuperclass5_Embedded.class.getName();
+ private static final String NAME3 =
+ PREFIX + "DeleteSuperclass5_Embedded_Base";
+
+ @PrimaryKey
+ int key = 99;
+
+ int ff;
+
+ DeleteSuperclass5_Embedded embed =
+ new DeleteSuperclass5_Embedded();
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ m.addDeleter(new Deleter(NAME3, 0));
+ return m;
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkNonEntity(true, model, env, NAME2, 1);
+ checkNonEntity(false, model, env, NAME3, 0);
+ checkVersions(model, NAME, 0);
+ if (oldTypesExist) {
+ checkVersions(model, NAME2, 1, NAME2, 0);
+ checkVersions(model, NAME3, 0);
+ } else {
+ checkVersions(model, NAME2, 1);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeleteSuperclass5_Top>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeleteSuperclass5_Top.class);
+ DeleteSuperclass5_Top obj = index.get(key);
+ TestCase.assertNotNull(obj);
+ TestCase.assertNotNull(obj.embed);
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertEquals(88, obj.ff);
+ TestCase.assertEquals(123, obj.embed.f);
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeleteSuperclass5_Top>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ DeleteSuperclass5_Top.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get(99);
+ index.put((DeleteSuperclass5_Top)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawType embedType = store.getModel().getRawType(NAME2);
+ RawObject embedSuper = null;
+ if (!expectEvolved) {
+ RawType embedSuperType = store.getModel().getRawType(NAME3);
+ embedSuper = new RawObject
+ (embedSuperType, makeValues("g", 456), null);
+ }
+ RawObject embed =
+ new RawObject(embedType, makeValues("f", 123), embedSuper);
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", 88, "embed", embed);
+ }
+ }
+
+ @Persistent
+ static class InsertSuperclass1_BaseClass
+ extends EvolveCase {
+
+ int f = 123;
+ }
+
+ /**
+ * Allow inserting a superclass between two existing classes in the
+ * hierarchy. No mutations are needed.
+ */
+ @Entity(version=1)
+ static class InsertSuperclass1_Between
+ extends InsertSuperclass1_BaseClass {
+
+ private static final String NAME =
+ InsertSuperclass1_BaseClass.class.getName();
+ private static final String NAME2 =
+ InsertSuperclass1_Between.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ int ff;
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkNonEntity(true, model, env, NAME, 0);
+ checkEntity(true, model, env, NAME2, 1, null);
+ checkVersions(model, NAME, 0);
+ if (oldTypesExist) {
+ checkVersions(model, NAME2, 1, NAME2, 0);
+ } else {
+ checkVersions(model, NAME2, 1);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,InsertSuperclass1_Between>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ InsertSuperclass1_Between.class);
+ InsertSuperclass1_Between obj = index.get(key);
+ TestCase.assertNotNull(obj);
+ TestCase.assertSame
+ (InsertSuperclass1_BaseClass.class,
+ obj.getClass().getSuperclass());
+ TestCase.assertSame
+ (EvolveCase.class,
+ obj.getClass().getSuperclass().getSuperclass());
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertEquals(88, obj.ff);
+ TestCase.assertEquals(123, obj.f);
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,InsertSuperclass1_Between>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ InsertSuperclass1_Between.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME2).get(99);
+ index.put((InsertSuperclass1_Between)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawObject obj;
+ if (expectEvolved) {
+ obj = readRaw(store, 99, NAME2, 1, NAME, 0, CASECLS, 0);
+ } else {
+ obj = readRaw(store, 99, NAME2, 0, CASECLS, 0);
+ }
+ checkRawFields(obj, "key", 99, "ff", 88);
+ if (expectEvolved) {
+ if (expectUpdated) {
+ checkRawFields(obj.getSuper(), "f", 123);
+ } else {
+ checkRawFields(obj.getSuper());
+ }
+ checkRawFields(obj.getSuper().getSuper());
+ TestCase.assertNull(obj.getSuper().getSuper().getSuper());
+ } else {
+ checkRawFields(obj.getSuper());
+ TestCase.assertNull(obj.getSuper().getSuper());
+ }
+ }
+ }
+
+ @Persistent
+ static class InsertSuperclass2_Embedded_Base {
+
+ int g = 456;
+ }
+
+ @Persistent(version=1)
+ static class InsertSuperclass2_Embedded
+ extends InsertSuperclass2_Embedded_Base {
+
+ int f;
+ }
+
+ /**
+ * Allow inserting a superclass at the top of the hierarchy. No mutations
+ * are needed.
+ */
+ @Entity
+ static class InsertSuperclass2_Top
+ extends EvolveCase {
+
+ private static final String NAME =
+ InsertSuperclass2_Top.class.getName();
+ private static final String NAME2 =
+ InsertSuperclass2_Embedded.class.getName();
+ private static final String NAME3 =
+ InsertSuperclass2_Embedded_Base.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ int ff;
+
+ InsertSuperclass2_Embedded embed =
+ new InsertSuperclass2_Embedded();
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkNonEntity(true, model, env, NAME2, 1);
+ checkNonEntity(true, model, env, NAME3, 0);
+ checkVersions(model, NAME, 0);
+ if (oldTypesExist) {
+ checkVersions(model, NAME2, 1, NAME2, 0);
+ } else {
+ checkVersions(model, NAME2, 1);
+ }
+ checkVersions(model, NAME3, 0);
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,InsertSuperclass2_Top>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ InsertSuperclass2_Top.class);
+ InsertSuperclass2_Top obj = index.get(key);
+ TestCase.assertNotNull(obj);
+ TestCase.assertNotNull(obj.embed);
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertEquals(88, obj.ff);
+ TestCase.assertEquals(123, obj.embed.f);
+ TestCase.assertEquals(456, obj.embed.g);
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,InsertSuperclass2_Top>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ InsertSuperclass2_Top.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get(99);
+ index.put((InsertSuperclass2_Top)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawType embedType = store.getModel().getRawType(NAME2);
+ RawObject embedSuper = null;
+ if (expectEvolved) {
+ RawType embedSuperType = store.getModel().getRawType(NAME3);
+ Map<String,Object> values =
+ expectUpdated ? makeValues("g", 456) : makeValues();
+ embedSuper = new RawObject(embedSuperType, values, null);
+ }
+ RawObject embed =
+ new RawObject(embedType, makeValues("f", 123), embedSuper);
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", 88, "embed", embed);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowNonKeyField_PrimitiveToObject
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowNonKeyField_PrimitiveToObject.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ String ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_PrimitiveToObject version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_PrimitiveToObject version: 1 Error: Old field type: int is not compatible with the new type: java.lang.String for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowNonKeyField_ObjectToPrimitive
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowNonKeyField_ObjectToPrimitive.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ int ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_ObjectToPrimitive version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_ObjectToPrimitive version: 1 Error: Old field type: java.lang.String is not compatible with the new type: int for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", "88");
+ }
+ }
+
+ @Persistent
+ static class MyType {
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof MyType;
+ }
+ }
+
+ @Persistent
+ static class MySubtype extends MyType {
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof MySubtype;
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowNonKeyField_ObjectToSubtype
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowNonKeyField_ObjectToSubtype.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ MySubtype ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_ObjectToSubtype version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_ObjectToSubtype version: 1 Error: Old field type: com.sleepycat.persist.test.EvolveClasses$MyType is not compatible with the new type: com.sleepycat.persist.test.EvolveClasses$MySubtype for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawType embedType = store.getModel().getRawType
+ (MyType.class.getName());
+ RawObject embed = new RawObject(embedType, makeValues(), null);
+
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", embed);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowNonKeyField_ObjectToUnrelatedSimple
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowNonKeyField_ObjectToUnrelatedSimple.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ String ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_ObjectToUnrelatedSimple version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_ObjectToUnrelatedSimple version: 1 Error: Old field type: java.lang.Integer is not compatible with the new type: java.lang.String for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowNonKeyField_ObjectToUnrelatedOther
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowNonKeyField_ObjectToUnrelatedOther.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ MyType ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_ObjectToUnrelatedOther version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_ObjectToUnrelatedOther version: 1 Error: Old field type: java.lang.Integer is not compatible with the new type: com.sleepycat.persist.test.EvolveClasses$MyType for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowNonKeyField_byte2boolean
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowNonKeyField_byte2boolean.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ boolean ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_byte2boolean version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_byte2boolean version: 1 Error: Old field type: byte is not compatible with the new type: boolean for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (byte) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowNonKeyField_short2byte
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowNonKeyField_short2byte.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ byte ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_short2byte version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_short2byte version: 1 Error: Old field type: short is not compatible with the new type: byte for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (short) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowNonKeyField_int2short
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowNonKeyField_int2short.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ short ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_int2short version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_int2short version: 1 Error: Old field type: int is not compatible with the new type: short for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowNonKeyField_long2int
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowNonKeyField_long2int.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ int ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_long2int version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_long2int version: 1 Error: Old field type: long is not compatible with the new type: int for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (long) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowNonKeyField_float2long
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowNonKeyField_float2long.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ long ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_float2long version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_float2long version: 1 Error: Old field type: float is not compatible with the new type: long for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (float) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowNonKeyField_double2float
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowNonKeyField_double2float.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ float ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_double2float version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_double2float version: 1 Error: Old field type: double is not compatible with the new type: float for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (double) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowNonKeyField_Byte2byte
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowNonKeyField_Byte2byte.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ byte ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_Byte2byte version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_Byte2byte version: 1 Error: Old field type: java.lang.Byte is not compatible with the new type: byte for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (byte) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowNonKeyField_Character2char
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowNonKeyField_Character2char.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ char ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_Character2char version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_Character2char version: 1 Error: Old field type: java.lang.Character is not compatible with the new type: char for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (char) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowNonKeyField_Short2short
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowNonKeyField_Short2short.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ short ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_Short2short version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_Short2short version: 1 Error: Old field type: java.lang.Short is not compatible with the new type: short for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (short) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowNonKeyField_Integer2int
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowNonKeyField_Integer2int.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ int ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_Integer2int version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_Integer2int version: 1 Error: Old field type: java.lang.Integer is not compatible with the new type: int for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowNonKeyField_Long2long
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowNonKeyField_Long2long.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ long ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_Long2long version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_Long2long version: 1 Error: Old field type: java.lang.Long is not compatible with the new type: long for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (long) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowNonKeyField_Float2float
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowNonKeyField_Float2float.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ float ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_Float2float version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_Float2float version: 1 Error: Old field type: java.lang.Float is not compatible with the new type: float for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (float) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowNonKeyField_Double2double
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowNonKeyField_Double2double.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ double ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_Double2double version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_Double2double version: 1 Error: Old field type: java.lang.Double is not compatible with the new type: double for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (double) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowNonKeyField_float2BigInt
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowNonKeyField_float2BigInt.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ BigInteger ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_float2BigInt version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_float2BigInt version: 1 Error: Old field type: float is not compatible with the new type: java.math.BigInteger for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (float) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowNonKeyField_BigInt2long
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowNonKeyField_BigInt2long.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ long ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_BigInt2long version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowNonKeyField_BigInt2long version: 1 Error: Old field type: java.math.BigInteger is not compatible with the new type: long for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", BigInteger.valueOf(88));
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowSecKeyField_byte2short
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowSecKeyField_byte2short.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ short ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_byte2short version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_byte2short version: 1 Error: Old field type: byte is not compatible with the new type: short for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, "ff");
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (byte) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowSecKeyField_char2int
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowSecKeyField_char2int.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_char2int version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_char2int version: 1 Error: Old field type: char is not compatible with the new type: int for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, "ff");
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (char) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowSecKeyField_short2int
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowSecKeyField_short2int.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_short2int version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_short2int version: 1 Error: Old field type: short is not compatible with the new type: int for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, "ff");
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (short) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowSecKeyField_int2long
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowSecKeyField_int2long.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ long ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_int2long version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_int2long version: 1 Error: Old field type: int is not compatible with the new type: long for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, "ff");
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowSecKeyField_long2float
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowSecKeyField_long2float.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ float ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_long2float version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_long2float version: 1 Error: Old field type: long is not compatible with the new type: float for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, "ff");
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (long) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowSecKeyField_float2double
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowSecKeyField_float2double.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ double ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_float2double version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_float2double version: 1 Error: Old field type: float is not compatible with the new type: double for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, "ff");
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (float) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowSecKeyField_Byte2short2
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowSecKeyField_Byte2short2.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ short ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_Byte2short2 version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_Byte2short2 version: 1 Error: Old field type: java.lang.Byte is not compatible with the new type: short for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, "ff");
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (byte) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowSecKeyField_Character2int
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowSecKeyField_Character2int.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_Character2int version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_Character2int version: 1 Error: Old field type: java.lang.Character is not compatible with the new type: int for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, "ff");
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (char) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowSecKeyField_Short2int2
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowSecKeyField_Short2int2.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_Short2int2 version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_Short2int2 version: 1 Error: Old field type: java.lang.Short is not compatible with the new type: int for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, "ff");
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (short) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowSecKeyField_Integer2long
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowSecKeyField_Integer2long.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ long ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_Integer2long version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_Integer2long version: 1 Error: Old field type: java.lang.Integer is not compatible with the new type: long for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, "ff");
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowSecKeyField_Long2float2
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowSecKeyField_Long2float2.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ float ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_Long2float2 version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_Long2float2 version: 1 Error: Old field type: java.lang.Long is not compatible with the new type: float for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, "ff");
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (long) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowSecKeyField_Float2double2
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowSecKeyField_Float2double2.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ double ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_Float2double2 version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_Float2double2 version: 1 Error: Old field type: java.lang.Float is not compatible with the new type: double for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, "ff");
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", (float) 88);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowSecKeyField_int2BigInt
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowSecKeyField_int2BigInt.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ BigInteger ff;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_int2BigInt version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowSecKeyField_int2BigInt version: 1 Error: Old field type: int is not compatible with the new type: java.math.BigInteger for field: ff";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, "ff");
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "ff", 88);
+ }
+ }
+
+ // ---
+
+ @Entity(version=1)
+ static class DisallowPriKeyField_byte2short
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowPriKeyField_byte2short.class.getName();
+
+ @PrimaryKey
+ short key;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Type may not be changed for a primary key field or composite key class field when evolving class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_byte2short version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_byte2short version: 1 Error: Old field type: byte is not compatible with the new type: short for field: key";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, (byte) 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", (byte) 99);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowPriKeyField_char2int
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowPriKeyField_char2int.class.getName();
+
+ @PrimaryKey
+ int key;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Type may not be changed for a primary key field or composite key class field when evolving class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_char2int version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_char2int version: 1 Error: Old field type: char is not compatible with the new type: int for field: key";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, (char) 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", (char) 99);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowPriKeyField_short2int
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowPriKeyField_short2int.class.getName();
+
+ @PrimaryKey
+ int key;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Type may not be changed for a primary key field or composite key class field when evolving class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_short2int version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_short2int version: 1 Error: Old field type: short is not compatible with the new type: int for field: key";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, (short) 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", (short) 99);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowPriKeyField_int2long
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowPriKeyField_int2long.class.getName();
+
+ @PrimaryKey
+ long key;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Type may not be changed for a primary key field or composite key class field when evolving class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_int2long version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_int2long version: 1 Error: Old field type: int is not compatible with the new type: long for field: key";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowPriKeyField_long2float
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowPriKeyField_long2float.class.getName();
+
+ @PrimaryKey
+ float key;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Type may not be changed for a primary key field or composite key class field when evolving class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_long2float version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_long2float version: 1 Error: Old field type: long is not compatible with the new type: float for field: key";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, (long) 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", (long) 99);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowPriKeyField_float2double
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowPriKeyField_float2double.class.getName();
+
+ @PrimaryKey
+ double key;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Type may not be changed for a primary key field or composite key class field when evolving class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_float2double version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_float2double version: 1 Error: Old field type: float is not compatible with the new type: double for field: key";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, (float) 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", (float) 99);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowPriKeyField_Byte2short2
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowPriKeyField_Byte2short2.class.getName();
+
+ @PrimaryKey
+ short key;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Type may not be changed for a primary key field or composite key class field when evolving class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_Byte2short2 version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_Byte2short2 version: 1 Error: Old field type: java.lang.Byte is not compatible with the new type: short for field: key";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, (byte) 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", (byte) 99);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowPriKeyField_Character2int
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowPriKeyField_Character2int.class.getName();
+
+ @PrimaryKey
+ int key;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Type may not be changed for a primary key field or composite key class field when evolving class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_Character2int version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_Character2int version: 1 Error: Old field type: java.lang.Character is not compatible with the new type: int for field: key";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, (char) 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", (char) 99);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowPriKeyField_Short2int2
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowPriKeyField_Short2int2.class.getName();
+
+ @PrimaryKey
+ int key;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Type may not be changed for a primary key field or composite key class field when evolving class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_Short2int2 version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_Short2int2 version: 1 Error: Old field type: java.lang.Short is not compatible with the new type: int for field: key";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, (short) 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", (short) 99);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowPriKeyField_Integer2long
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowPriKeyField_Integer2long.class.getName();
+
+ @PrimaryKey
+ long key;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Type may not be changed for a primary key field or composite key class field when evolving class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_Integer2long version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_Integer2long version: 1 Error: Old field type: java.lang.Integer is not compatible with the new type: long for field: key";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowPriKeyField_Long2float2
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowPriKeyField_Long2float2.class.getName();
+
+ @PrimaryKey
+ float key;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Type may not be changed for a primary key field or composite key class field when evolving class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_Long2float2 version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_Long2float2 version: 1 Error: Old field type: java.lang.Long is not compatible with the new type: float for field: key";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, (long) 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", (long) 99);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowPriKeyField_Float2double2
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowPriKeyField_Float2double2.class.getName();
+
+ @PrimaryKey
+ double key;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Type may not be changed for a primary key field or composite key class field when evolving class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_Float2double2 version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_Float2double2 version: 1 Error: Old field type: java.lang.Float is not compatible with the new type: double for field: key";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, (float) 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", (float) 99);
+ }
+ }
+
+ @Entity(version=1)
+ static class DisallowPriKeyField_Long2BigInt
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowPriKeyField_Long2BigInt.class.getName();
+
+ @PrimaryKey
+ BigInteger key;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Type may not be changed for a primary key field or composite key class field when evolving class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_Long2BigInt version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowPriKeyField_Long2BigInt version: 1 Error: Old field type: java.lang.Long is not compatible with the new type: java.math.BigInteger for field: key";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawObject obj = readRaw(store, 99L, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99L);
+ }
+ }
+
+ @Persistent(version=1)
+ static class DisallowCompositeKeyField_byte2short_Key {
+
+ @KeyField(1)
+ int f1 = 1;
+
+ @KeyField(2)
+ short f2 = 2;
+
+ @KeyField(3)
+ String f3 = "3";
+ }
+
+ @Entity
+ static class DisallowCompositeKeyField_byte2short
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowCompositeKeyField_byte2short.class.getName();
+ private static final String NAME2 =
+ DisallowCompositeKeyField_byte2short_Key.class.getName();
+
+ @PrimaryKey
+ DisallowCompositeKeyField_byte2short_Key key;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Type may not be changed for a primary key field or composite key class field when evolving class: com.sleepycat.persist.test.EvolveClasses$DisallowCompositeKeyField_byte2short_Key version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowCompositeKeyField_byte2short_Key version: 1 Error: Old field type: byte is not compatible with the new type: short for field: f2";
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkNonEntity(true, model, env, NAME2, 0);
+ checkVersions(model, NAME, 0);
+ checkVersions(model, NAME2, 0);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ if (expectEvolved) {
+ TestCase.fail();
+ }
+ RawType rawKeyType = store.getModel().getRawType(NAME2);
+ RawObject rawKey = new RawObject
+ (rawKeyType,
+ makeValues("f1", 1, "f2", (byte) 2, "f3", "3"),
+ null);
+
+ RawObject obj = readRaw(store, rawKey, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", rawKey);
+ }
+ }
+
+ @Entity(version=1)
+ static class AllowPriKeyField_byte2Byte
+ extends EvolveCase {
+
+ private static final String NAME =
+ AllowPriKeyField_byte2Byte.class.getName();
+
+ @PrimaryKey
+ Byte key = 99;
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 1, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 1, NAME, 0);
+ } else {
+ checkVersions(model, NAME, 1);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Byte,AllowPriKeyField_byte2Byte>
+ index = store.getPrimaryIndex
+ (Byte.class,
+ AllowPriKeyField_byte2Byte.class);
+ AllowPriKeyField_byte2Byte obj = index.get(key);
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(Byte.valueOf((byte) 99), obj.key);
+
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Byte,AllowPriKeyField_byte2Byte>
+ index = newStore.getPrimaryIndex
+ (Byte.class,
+ AllowPriKeyField_byte2Byte.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get((byte) 99);
+ index.put((AllowPriKeyField_byte2Byte)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawObject obj;
+ if (expectEvolved) {
+ obj = readRaw(store, (byte) 99, NAME, 1, CASECLS, 0);
+ } else {
+ obj = readRaw(store, (byte) 99, NAME, 0, CASECLS, 0);
+ }
+ checkRawFields(obj, "key", (byte) 99);
+ }
+ }
+
+ @Entity(version=1)
+ static class AllowPriKeyField_Byte2byte2
+ extends EvolveCase {
+
+ private static final String NAME =
+ AllowPriKeyField_Byte2byte2.class.getName();
+
+ @PrimaryKey
+ byte key = 99;
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 1, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 1, NAME, 0);
+ } else {
+ checkVersions(model, NAME, 1);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Byte,AllowPriKeyField_Byte2byte2>
+ index = store.getPrimaryIndex
+ (Byte.class,
+ AllowPriKeyField_Byte2byte2.class);
+ AllowPriKeyField_Byte2byte2 obj = index.get(key);
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals((byte) 99, obj.key);
+
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Byte,AllowPriKeyField_Byte2byte2>
+ index = newStore.getPrimaryIndex
+ (Byte.class,
+ AllowPriKeyField_Byte2byte2.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get((byte) 99);
+ index.put((AllowPriKeyField_Byte2byte2)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawObject obj;
+ if (expectEvolved) {
+ obj = readRaw(store, (byte) 99, NAME, 1, CASECLS, 0);
+ } else {
+ obj = readRaw(store, (byte) 99, NAME, 0, CASECLS, 0);
+ }
+ checkRawFields(obj, "key", (byte) 99);
+ }
+ }
+
+ @Persistent(version=1)
+ static class AllowFieldTypeChanges_Key {
+
+ AllowFieldTypeChanges_Key() {
+ this(false);
+ }
+
+ AllowFieldTypeChanges_Key(boolean init) {
+ if (init) {
+ f1 = true;
+ f2 = (byte) 2;
+ f3 = (short) 3;
+ f4 = 4;
+ f5 = 5L;
+ f6 = 6F;
+ f7 = 7D;
+ f8 = (char) 8;
+ f9 = true;
+ f10 = (byte) 10;
+ f11 = (short) 11;
+ f12 = 12;
+ f13 = 13L;
+ f14 = 14F;
+ f15 = 15D;
+ f16 = (char) 16;
+ }
+ }
+
+ @KeyField(1)
+ boolean f1;
+
+ @KeyField(2)
+ byte f2;
+
+ @KeyField(3)
+ short f3;
+
+ @KeyField(4)
+ int f4;
+
+ @KeyField(5)
+ long f5;
+
+ @KeyField(6)
+ float f6;
+
+ @KeyField(7)
+ double f7;
+
+ @KeyField(8)
+ char f8;
+
+ @KeyField(9)
+ Boolean f9;
+
+ @KeyField(10)
+ Byte f10;
+
+ @KeyField(11)
+ Short f11;
+
+ @KeyField(12)
+ Integer f12;
+
+ @KeyField(13)
+ Long f13;
+
+ @KeyField(14)
+ Float f14;
+
+ @KeyField(15)
+ Double f15;
+
+ @KeyField(16)
+ Character f16;
+ }
+
+ @Persistent(version=1)
+ static class AllowFieldTypeChanges_Base
+ extends EvolveCase {
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ AllowFieldTypeChanges_Key kComposite;
+
+ Integer f_long2Integer;
+ Long f_String2Long;
+ }
+
+ /**
+ * Allow field type changes: automatic widening, supported widening,
+ * and Converter mutations. Also tests primary and secondary key field
+ * renaming.
+ */
+ @Entity(version=1)
+ static class AllowFieldTypeChanges
+ extends AllowFieldTypeChanges_Base {
+
+ private static final String NAME =
+ AllowFieldTypeChanges.class.getName();
+ private static final String NAME2 =
+ AllowFieldTypeChanges_Base.class.getName();
+ private static final String NAME3 =
+ AllowFieldTypeChanges_Key.class.getName();
+
+ @PrimaryKey
+ Integer pkeyInteger;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ Boolean kBoolean;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ Byte kByte;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ Short kShort;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ Integer kInteger;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ Long kLong;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ Float kFloat;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ Double kDouble;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ Character kCharacter;
+
+ short f01;
+ int f02;
+ long f03;
+ float f04;
+ double f06;
+ int f07;
+ long f08;
+ float f09;
+ double f10;
+ int f11;
+ long f12;
+ float f13;
+ double f14;
+ long f15;
+ float f16;
+ double f17;
+ float f18;
+ double f19;
+ double f20;
+
+ Short f21;
+ Integer f22;
+ Long f23;
+ Float f24;
+ Double f26;
+ Integer f27;
+ Long f28;
+ Float f29;
+ Double f30;
+ Integer f31;
+ Long f32;
+ Float f33;
+ Double f34;
+ Long f35;
+ Float f36;
+ Double f37;
+ Float f38;
+ Double f39;
+ Double f40;
+
+ Short f41;
+ Integer f42;
+ Long f43;
+ Float f44;
+ Double f46;
+ Integer f47;
+ Long f48;
+ Float f49;
+ Double f50;
+ Integer f51;
+ Long f52;
+ Float f53;
+ Double f54;
+ Long f55;
+ Float f56;
+ Double f57;
+ Float f58;
+ Double f59;
+ Double f60;
+
+ BigInteger f70;
+ BigInteger f71;
+ BigInteger f72;
+ BigInteger f73;
+ BigInteger f74;
+ BigInteger f75;
+ BigInteger f76;
+ BigInteger f77;
+ BigInteger f78;
+ BigInteger f79;
+
+ int f_long2int;
+ long f_String2long;
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ m.addRenamer(new Renamer(NAME, 0, "pkeyint", "pkeyInteger"));
+ m.addRenamer(new Renamer(NAME, 0, "kboolean", "kBoolean"));
+ m.addRenamer(new Renamer(NAME, 0, "kbyte", "kByte"));
+ m.addRenamer(new Renamer(NAME, 0, "kshort", "kShort"));
+ m.addRenamer(new Renamer(NAME, 0, "kint", "kInteger"));
+ m.addRenamer(new Renamer(NAME, 0, "klong", "kLong"));
+ m.addRenamer(new Renamer(NAME, 0, "kfloat", "kFloat"));
+ m.addRenamer(new Renamer(NAME, 0, "kdouble", "kDouble"));
+ m.addRenamer(new Renamer(NAME, 0, "kchar", "kCharacter"));
+ m.addRenamer(new Renamer(NAME2, 0, "kcomposite", "kComposite"));
+
+ Conversion conv1 = new MyConversion1();
+ Conversion conv2 = new MyConversion2();
+
+ m.addConverter(new Converter(NAME, 0, "f_long2int", conv1));
+ m.addConverter(new Converter(NAME, 0, "f_String2long", conv2));
+ m.addConverter(new Converter(NAME2, 0, "f_long2Integer", conv1));
+ m.addConverter(new Converter(NAME2, 0, "f_String2Long", conv2));
+ return m;
+ }
+
+ @SuppressWarnings("serial")
+ static class MyConversion1 implements Conversion {
+
+ public void initialize(EntityModel model) {}
+
+ public Object convert(Object o) {
+ return ((Long) o).intValue();
+ }
+
+ @Override
+ public boolean equals(Object other) { return true; }
+ }
+
+ @SuppressWarnings("serial")
+ static class MyConversion2 implements Conversion {
+
+ public void initialize(EntityModel model) {}
+
+ public Object convert(Object o) {
+ return Long.valueOf((String) o);
+ }
+
+ @Override
+ public boolean equals(Object other) { return true; }
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 1, null);
+ checkNonEntity(true, model, env, NAME2, 1);
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 1, NAME, 0);
+ checkVersions(model, NAME2, 1, NAME2, 0);
+ checkVersions(model, NAME3, 1, NAME3, 0);
+ } else {
+ checkVersions(model, NAME, 1);
+ checkVersions(model, NAME2, 1);
+ checkVersions(model, NAME3, 1);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,AllowFieldTypeChanges>
+ index = store.getPrimaryIndex
+ (Integer.class, AllowFieldTypeChanges.class);
+ AllowFieldTypeChanges obj = index.get(99);
+ checkValues(obj);
+ checkSecondaries(store, index);
+
+ if (doUpdate) {
+ index.put(obj);
+ checkSecondaries(store, index);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,AllowFieldTypeChanges>
+ index = newStore.getPrimaryIndex
+ (Integer.class, AllowFieldTypeChanges.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get(99);
+ index.put((AllowFieldTypeChanges)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ private void checkSecondaries(EntityStore store,
+ PrimaryIndex<Integer,
+ AllowFieldTypeChanges>
+ index)
+ throws DatabaseException {
+
+ checkValues(store.getSecondaryIndex
+ (index, Boolean.class, "kBoolean").get(true));
+ checkValues(store.getSecondaryIndex
+ (index, Byte.class, "kByte").get((byte) 77));
+ checkValues(store.getSecondaryIndex
+ (index, Short.class, "kShort").get((short) 66));
+ checkValues(store.getSecondaryIndex
+ (index, Integer.class, "kInteger").get(55));
+ checkValues(store.getSecondaryIndex
+ (index, Long.class, "kLong").get((long) 44));
+ checkValues(store.getSecondaryIndex
+ (index, Float.class, "kFloat").get((float) 33));
+ checkValues(store.getSecondaryIndex
+ (index, Double.class, "kDouble").get((double) 22));
+ checkValues(store.getSecondaryIndex
+ (index, Character.class, "kCharacter").get((char) 11));
+ checkValues(store.getSecondaryIndex
+ (index, AllowFieldTypeChanges_Key.class, "kComposite").get
+ (new AllowFieldTypeChanges_Key(true)));
+ }
+
+ private void checkValues(AllowFieldTypeChanges obj) {
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(obj.pkeyInteger, Integer.valueOf(99));
+ TestCase.assertEquals(obj.kBoolean, Boolean.valueOf(true));
+ TestCase.assertEquals(obj.kByte, Byte.valueOf((byte) 77));
+ TestCase.assertEquals(obj.kShort, Short.valueOf((short) 66));
+ TestCase.assertEquals(obj.kInteger, Integer.valueOf(55));
+ TestCase.assertEquals(obj.kLong, Long.valueOf(44));
+ TestCase.assertEquals(obj.kFloat, Float.valueOf(33));
+ TestCase.assertEquals(obj.kDouble, Double.valueOf(22));
+ TestCase.assertEquals(obj.kCharacter, Character.valueOf((char) 11));
+
+ AllowFieldTypeChanges_Key embed = obj.kComposite;
+ TestCase.assertNotNull(embed);
+ TestCase.assertEquals(embed.f1, true);
+ TestCase.assertEquals(embed.f2, (byte) 2);
+ TestCase.assertEquals(embed.f3, (short) 3);
+ TestCase.assertEquals(embed.f4, 4);
+ TestCase.assertEquals(embed.f5, 5L);
+ TestCase.assertEquals(embed.f6, 6F);
+ TestCase.assertEquals(embed.f7, 7D);
+ TestCase.assertEquals(embed.f8, (char) 8);
+ TestCase.assertEquals(embed.f9, Boolean.valueOf(true));
+ TestCase.assertEquals(embed.f10, Byte.valueOf((byte) 10));
+ TestCase.assertEquals(embed.f11, Short.valueOf((short) 11));
+ TestCase.assertEquals(embed.f12, Integer.valueOf(12));
+ TestCase.assertEquals(embed.f13, Long.valueOf(13L));
+ TestCase.assertEquals(embed.f14, Float.valueOf(14F));
+ TestCase.assertEquals(embed.f15, Double.valueOf(15D));
+ TestCase.assertEquals(embed.f16, Character.valueOf((char) 16));
+
+ TestCase.assertEquals(obj.f01, (short) 1);
+ TestCase.assertEquals(obj.f02, 2);
+ TestCase.assertEquals(obj.f03, 3);
+ TestCase.assertEquals(obj.f04, (float) 4);
+ TestCase.assertEquals(obj.f06, (double) 6);
+ TestCase.assertEquals(obj.f07, 7);
+ TestCase.assertEquals(obj.f08, 8);
+ TestCase.assertEquals(obj.f09, (float) 9);
+ TestCase.assertEquals(obj.f10, (double) 10);
+ TestCase.assertEquals(obj.f11, 11);
+ TestCase.assertEquals(obj.f12, 12);
+ TestCase.assertEquals(obj.f13, (float) 13);
+ TestCase.assertEquals(obj.f14, (double) 14);
+ TestCase.assertEquals(obj.f15, 15L);
+ TestCase.assertEquals(obj.f16, 16F);
+ TestCase.assertEquals(obj.f17, 17D);
+ TestCase.assertEquals(obj.f18, (float) 18);
+ TestCase.assertEquals(obj.f19, (double) 19);
+ TestCase.assertEquals(obj.f20, (double) 20);
+
+ TestCase.assertEquals(obj.f21, Short.valueOf((byte) 21));
+ TestCase.assertEquals(obj.f22, Integer.valueOf((byte) 22));
+ TestCase.assertEquals(obj.f23, Long.valueOf((byte) 23));
+ TestCase.assertEquals(obj.f24, Float.valueOf((byte) 24));
+ TestCase.assertEquals(obj.f26, Double.valueOf((byte) 26));
+ TestCase.assertEquals(obj.f27, Integer.valueOf((short) 27));
+ TestCase.assertEquals(obj.f28, Long.valueOf((short) 28));
+ TestCase.assertEquals(obj.f29, Float.valueOf((short) 29));
+ TestCase.assertEquals(obj.f30, Double.valueOf((short) 30));
+ TestCase.assertEquals(obj.f31, Integer.valueOf((char) 31));
+ TestCase.assertEquals(obj.f32, Long.valueOf((char) 32));
+ TestCase.assertEquals(obj.f33, Float.valueOf((char) 33));
+ TestCase.assertEquals(obj.f34, Double.valueOf((char) 34));
+ TestCase.assertEquals(obj.f35, Long.valueOf(35));
+ TestCase.assertEquals(obj.f36, Float.valueOf(36));
+ TestCase.assertEquals(obj.f37, Double.valueOf(37));
+ TestCase.assertEquals(obj.f38, Float.valueOf(38));
+ TestCase.assertEquals(obj.f39, Double.valueOf(39));
+ TestCase.assertEquals(obj.f40, Double.valueOf(40));
+
+ TestCase.assertEquals(obj.f41, Short.valueOf((byte) 41));
+ TestCase.assertEquals(obj.f42, Integer.valueOf((byte) 42));
+ TestCase.assertEquals(obj.f43, Long.valueOf((byte) 43));
+ TestCase.assertEquals(obj.f44, Float.valueOf((byte) 44));
+ TestCase.assertEquals(obj.f46, Double.valueOf((byte) 46));
+ TestCase.assertEquals(obj.f47, Integer.valueOf((short) 47));
+ TestCase.assertEquals(obj.f48, Long.valueOf((short) 48));
+ TestCase.assertEquals(obj.f49, Float.valueOf((short) 49));
+ TestCase.assertEquals(obj.f50, Double.valueOf((short) 50));
+ TestCase.assertEquals(obj.f51, Integer.valueOf((char) 51));
+ TestCase.assertEquals(obj.f52, Long.valueOf((char) 52));
+ TestCase.assertEquals(obj.f53, Float.valueOf((char) 53));
+ TestCase.assertEquals(obj.f54, Double.valueOf((char) 54));
+ TestCase.assertEquals(obj.f55, Long.valueOf(55));
+ TestCase.assertEquals(obj.f56, Float.valueOf(56));
+ TestCase.assertEquals(obj.f57, Double.valueOf(57));
+ TestCase.assertEquals(obj.f58, Float.valueOf(58));
+ TestCase.assertEquals(obj.f59, Double.valueOf(59));
+ TestCase.assertEquals(obj.f60, Double.valueOf(60));
+
+ TestCase.assertEquals(obj.f70, BigInteger.valueOf(70));
+ TestCase.assertEquals(obj.f71, BigInteger.valueOf(71));
+ TestCase.assertEquals(obj.f72, BigInteger.valueOf(72));
+ TestCase.assertEquals(obj.f73, BigInteger.valueOf(73));
+ TestCase.assertEquals(obj.f74, BigInteger.valueOf(74));
+ TestCase.assertEquals(obj.f75, BigInteger.valueOf(75));
+ TestCase.assertEquals(obj.f76, BigInteger.valueOf(76));
+ TestCase.assertEquals(obj.f77, BigInteger.valueOf(77));
+ TestCase.assertEquals(obj.f78, BigInteger.valueOf(78));
+ TestCase.assertEquals(obj.f79, BigInteger.valueOf(79));
+
+ TestCase.assertEquals(obj.f_long2Integer, Integer.valueOf(111));
+ TestCase.assertEquals(obj.f_String2Long, Long.valueOf(222));
+ TestCase.assertEquals(obj.f_long2int, 333);
+ TestCase.assertEquals(obj.f_String2long, 444L);
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawType embedType = store.getModel().getRawType(NAME3);
+ RawObject embed = new RawObject
+ (embedType,
+ makeValues
+ ("f1", true,
+ "f2", (byte) 2,
+ "f3", (short) 3,
+ "f4", 4,
+ "f5", 5L,
+ "f6", 6F,
+ "f7", 7D,
+ "f8", (char) 8,
+ "f9", true,
+ "f10", (byte) 10,
+ "f11", (short) 11,
+ "f12", 12,
+ "f13", 13L,
+ "f14", 14F,
+ "f15", 15D,
+ "f16", (char) 16),
+ null);
+
+ RawObject obj;
+ if (expectEvolved) {
+ obj = readRaw(store, 99, NAME, 1, NAME2, 1, CASECLS, 0);
+ checkRawFields(obj, "pkeyInteger", 99,
+ "kBoolean", true,
+ "kByte", (byte) 77,
+ "kShort", (short) 66,
+ "kInteger", 55,
+ "kLong", (long) 44,
+ "kFloat", (float) 33,
+ "kDouble", (double) 22,
+ "kCharacter", (char) 11,
+
+ "f01", (short) 1,
+ "f02", 2,
+ "f03", (long) 3,
+ "f04", (float) 4,
+ "f06", (double) 6,
+ "f07", 7,
+ "f08", (long) 8,
+ "f09", (float) 9,
+ "f10", (double) 10,
+ "f11", 11,
+ "f12", (long) 12,
+ "f13", (float) 13,
+ "f14", (double) 14,
+ "f15", 15L,
+ "f16", 16F,
+ "f17", 17D,
+ "f18", (float) 18,
+ "f19", (double) 19,
+ "f20", (double) 20,
+
+ "f21", (short) 21,
+ "f22", 22,
+ "f23", (long) 23,
+ "f24", (float) 24,
+ "f26", (double) 26,
+ "f27", 27,
+ "f28", (long) 28,
+ "f29", (float) 29,
+ "f30", (double) 30,
+ "f31", 31,
+ "f32", (long) 32,
+ "f33", (float) 33,
+ "f34", (double) 34,
+ "f35", 35L,
+ "f36", 36F,
+ "f37", 37D,
+ "f38", (float) 38,
+ "f39", (double) 39,
+ "f40", (double) 40,
+
+ "f41", (short) 41,
+ "f42", 42,
+ "f43", (long) 43,
+ "f44", (float) 44,
+ "f46", (double) 46,
+ "f47", 47,
+ "f48", (long) 48,
+ "f49", (float) 49,
+ "f50", (double) 50,
+ "f51", 51,
+ "f52", (long) 52,
+ "f53", (float) 53,
+ "f54", (double) 54,
+ "f55", 55L,
+ "f56", 56F,
+ "f57", 57D,
+ "f58", (float) 58,
+ "f59", (double) 59,
+ "f60", (double) 60,
+
+ "f70", BigInteger.valueOf(70),
+ "f71", BigInteger.valueOf(71),
+ "f72", BigInteger.valueOf(72),
+ "f73", BigInteger.valueOf(73),
+ "f74", BigInteger.valueOf(74),
+ "f75", BigInteger.valueOf(75),
+ "f76", BigInteger.valueOf(76),
+ "f77", BigInteger.valueOf(77),
+ "f78", BigInteger.valueOf(78),
+ "f79", BigInteger.valueOf(79),
+
+ "f_long2int", 333,
+ "f_String2long", 444L);
+ checkRawFields(obj.getSuper(),
+ "kComposite", embed,
+ "f_long2Integer", 111,
+ "f_String2Long", 222L);
+ } else {
+ obj = readRaw(store, 99, NAME, 0, NAME2, 0, CASECLS, 0);
+ checkRawFields(obj, "pkeyint", 99,
+ "kboolean", true,
+ "kbyte", (byte) 77,
+ "kshort", (short) 66,
+ "kint", 55,
+ "klong", (long) 44,
+ "kfloat", (float) 33,
+ "kdouble", (double) 22,
+ "kchar", (char) 11,
+
+ "f01", (byte) 1,
+ "f02", (byte) 2,
+ "f03", (byte) 3,
+ "f04", (byte) 4,
+ "f06", (byte) 6,
+ "f07", (short) 7,
+ "f08", (short) 8,
+ "f09", (short) 9,
+ "f10", (short) 10,
+ "f11", (char) 11,
+ "f12", (char) 12,
+ "f13", (char) 13,
+ "f14", (char) 14,
+ "f15", 15,
+ "f16", 16,
+ "f17", 17,
+ "f18", (long) 18,
+ "f19", (long) 19,
+ "f20", (float) 20,
+
+ "f21", (byte) 21,
+ "f22", (byte) 22,
+ "f23", (byte) 23,
+ "f24", (byte) 24,
+ "f26", (byte) 26,
+ "f27", (short) 27,
+ "f28", (short) 28,
+ "f29", (short) 29,
+ "f30", (short) 30,
+ "f31", (char) 31,
+ "f32", (char) 32,
+ "f33", (char) 33,
+ "f34", (char) 34,
+ "f35", 35,
+ "f36", 36,
+ "f37", 37,
+ "f38", (long) 38,
+ "f39", (long) 39,
+ "f40", (float) 40,
+
+ "f41", (byte) 41,
+ "f42", (byte) 42,
+ "f43", (byte) 43,
+ "f44", (byte) 44,
+ "f46", (byte) 46,
+ "f47", (short) 47,
+ "f48", (short) 48,
+ "f49", (short) 49,
+ "f50", (short) 50,
+ "f51", (char) 51,
+ "f52", (char) 52,
+ "f53", (char) 53,
+ "f54", (char) 54,
+ "f55", 55,
+ "f56", 56,
+ "f57", 57,
+ "f58", (long) 58,
+ "f59", (long) 59,
+ "f60", (float) 60,
+
+ "f70", (byte) 70,
+ "f71", (short) 71,
+ "f72", (char) 72,
+ "f73", 73,
+ "f74", (long) 74,
+ "f75", (byte) 75,
+ "f76", (short) 76,
+ "f77", (char) 77,
+ "f78", 78,
+ "f79", (long) 79,
+
+ "f_long2int", 333L,
+ "f_String2long", "444");
+
+ checkRawFields(obj.getSuper(),
+ "kcomposite", embed,
+ "f_long2Integer", 111L,
+ "f_String2Long", "222");
+ }
+ Environment env = store.getEnvironment();
+
+ assertDbExists(expectEvolved, env, NAME, "kBoolean");
+ assertDbExists(expectEvolved, env, NAME, "kByte");
+ assertDbExists(expectEvolved, env, NAME, "kShort");
+ assertDbExists(expectEvolved, env, NAME, "kInteger");
+ assertDbExists(expectEvolved, env, NAME, "kLong");
+ assertDbExists(expectEvolved, env, NAME, "kFloat");
+ assertDbExists(expectEvolved, env, NAME, "kDouble");
+ assertDbExists(expectEvolved, env, NAME, "kCharacter");
+ assertDbExists(expectEvolved, env, NAME, "kComposite");
+
+ assertDbExists(!expectEvolved, env, NAME, "kboolean");
+ assertDbExists(!expectEvolved, env, NAME, "kbyte");
+ assertDbExists(!expectEvolved, env, NAME, "kshort");
+ assertDbExists(!expectEvolved, env, NAME, "kint");
+ assertDbExists(!expectEvolved, env, NAME, "klong");
+ assertDbExists(!expectEvolved, env, NAME, "kfloat");
+ assertDbExists(!expectEvolved, env, NAME, "kdouble");
+ assertDbExists(!expectEvolved, env, NAME, "kchar");
+ assertDbExists(!expectEvolved, env, NAME, "kcomposite");
+ }
+ }
+
+ @SuppressWarnings("serial")
+ static class ConvertFieldContent_Conversion implements Conversion {
+
+ public void initialize(EntityModel model) {
+ }
+
+ public Object convert(Object fromValue) {
+ String s1 = (String) fromValue;
+ return (new StringBuilder(s1)).reverse().toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof ConvertFieldContent_Conversion;
+ }
+ }
+
+ @Entity(version=1)
+ static class ConvertFieldContent_Entity
+ extends EvolveCase {
+
+ private static final String NAME =
+ ConvertFieldContent_Entity.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ String f1;
+ String f2;
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ Converter converter = new Converter
+ (ConvertFieldContent_Entity.class.getName(), 0,
+ "f1", new ConvertFieldContent_Conversion());
+ m.addConverter(converter);
+ converter = new Converter
+ (ConvertFieldContent_Entity.class.getName(), 0,
+ "f2", new ConvertFieldContent_Conversion());
+ m.addConverter(converter);
+ return m;
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 1, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 1, NAME, 0);
+ } else {
+ checkVersions(model, NAME, 1);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ConvertFieldContent_Entity>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ ConvertFieldContent_Entity.class);
+ ConvertFieldContent_Entity obj = index.get(99);
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertEquals("43210", obj.f1);
+ TestCase.assertEquals("98765", obj.f2);
+
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ConvertFieldContent_Entity>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ ConvertFieldContent_Entity.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get(99);
+ index.put((ConvertFieldContent_Entity)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawObject obj =
+ readRaw(store, 99, NAME, expectEvolved ? 1 : 0, CASECLS, 0);
+ if (expectEvolved) {
+ checkRawFields(obj, "key", 99,
+ "f1", "43210",
+ "f2", "98765");
+ } else {
+ checkRawFields(obj, "key", 99,
+ "f1", "01234",
+ "f2", "56789");
+ }
+ }
+ }
+
+ @Persistent(version=1)
+ static class ConvertExample1_Address {
+ String street;
+ String city;
+ String state;
+ int zipCode;
+ }
+
+ @SuppressWarnings("serial")
+ static class ConvertExample1_Conversion implements Conversion {
+
+ public void initialize(EntityModel model) {
+ }
+
+ public Object convert(Object fromValue) {
+ return Integer.valueOf((String) fromValue);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof ConvertExample1_Conversion;
+ }
+ }
+
+ @Entity
+ static class ConvertExample1_Entity
+ extends EvolveCase {
+
+ private static final String NAME =
+ ConvertExample1_Entity.class.getName();
+ private static final String NAME2 =
+ ConvertExample1_Address.class.getName();
+
+ @PrimaryKey
+ int key = 99;
+
+ ConvertExample1_Address embed;
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ Converter converter = new Converter
+ (ConvertExample1_Address.class.getName(), 0,
+ "zipCode", new ConvertExample1_Conversion());
+ m.addConverter(converter);
+ return m;
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ if (oldTypesExist) {
+ checkVersions(model, NAME2, 1, NAME2, 0);
+ } else {
+ checkVersions(model, NAME2, 1);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ConvertExample1_Entity>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ ConvertExample1_Entity.class);
+ ConvertExample1_Entity obj = index.get(99);
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertNotNull(obj.embed);
+ TestCase.assertEquals("street", obj.embed.street);
+ TestCase.assertEquals("city", obj.embed.city);
+ TestCase.assertEquals("state", obj.embed.state);
+ TestCase.assertEquals(12345, obj.embed.zipCode);
+
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ConvertExample1_Entity>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ ConvertExample1_Entity.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get(99);
+ index.put((ConvertExample1_Entity)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawType embedType = store.getModel().getRawType(NAME2);
+ RawObject embed;
+ if (expectEvolved) {
+ embed = new RawObject
+ (embedType,
+ makeValues("street", "street",
+ "city", "city",
+ "state", "state",
+ "zipCode", 12345),
+ null);
+ } else {
+ embed = new RawObject
+ (embedType,
+ makeValues("street", "street",
+ "city", "city",
+ "state", "state",
+ "zipCode", "12345"),
+ null);
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "embed", embed);
+ }
+ }
+
+ @Persistent
+ static class ConvertExample2_Address {
+ String street;
+ String city;
+ String state;
+ int zipCode;
+ }
+
+ @Entity(version=1)
+ static class ConvertExample2_Person
+ extends EvolveCase {
+
+ private static final String NAME =
+ ConvertExample2_Person.class.getName();
+ private static final String NAME2 =
+ ConvertExample2_Address .class.getName();
+
+ @PrimaryKey
+ int key;
+
+ ConvertExample2_Address address;
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ Converter converter = new Converter
+ (ConvertExample2_Person.class.getName(), 0,
+ "address", new ConvertExample2_Conversion());
+ m.addConverter(converter);
+ return m;
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 1, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 1, NAME, 0);
+ } else {
+ checkVersions(model, NAME, 1);
+ }
+ checkVersions(model, NAME2, 0);
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ConvertExample2_Person>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ ConvertExample2_Person.class);
+ ConvertExample2_Person obj = index.get(99);
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertNotNull(obj.address);
+ TestCase.assertEquals("street", obj.address.street);
+ TestCase.assertEquals("city", obj.address.city);
+ TestCase.assertEquals("state", obj.address.state);
+ TestCase.assertEquals(12345, obj.address.zipCode);
+
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ConvertExample2_Person>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ ConvertExample2_Person.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get(99);
+ index.put((ConvertExample2_Person)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ Object embed;
+ if (expectEvolved) {
+ RawType embedType = store.getModel().getRawType(NAME2);
+ embed = new RawObject
+ (embedType,
+ makeValues("street", "street",
+ "city", "city",
+ "state", "state",
+ "zipCode", 12345),
+ null);
+ } else {
+ embed = "street#city#state#12345";
+ }
+ RawObject obj = readRaw
+ (store, 99, NAME, expectEvolved ? 1 : 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "address", embed);
+ }
+ }
+
+ @SuppressWarnings("serial")
+ static class ConvertExample2_Conversion implements Conversion {
+ private transient RawType addressType;
+
+ public void initialize(EntityModel model) {
+ addressType = model.getRawType
+ (ConvertExample2_Address.class.getName());
+ }
+
+ public Object convert(Object fromValue) {
+
+ String oldAddress = (String) fromValue;
+ Map<String,Object> addressValues = new HashMap<String,Object>();
+ addressValues.put("street", parseAddress(1, oldAddress));
+ addressValues.put("city", parseAddress(2, oldAddress));
+ addressValues.put("state", parseAddress(3, oldAddress));
+ addressValues.put("zipCode",
+ Integer.valueOf(parseAddress(4, oldAddress)));
+
+ return new RawObject(addressType, addressValues, null);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof ConvertExample2_Conversion;
+ }
+
+ private String parseAddress(int fieldNum, String oldAddress) {
+ StringTokenizer tokens = new StringTokenizer(oldAddress, "#");
+ String field = null;
+ for (int i = 0; i < fieldNum; i += 1) {
+ field = tokens.nextToken();
+ }
+ return field;
+ }
+ }
+
+ @Persistent
+ static class ConvertExample3_Address {
+ String street;
+ String city;
+ String state;
+ int zipCode;
+ }
+
+ @SuppressWarnings("serial")
+ static class ConvertExample3_Conversion implements Conversion {
+ private transient RawType newPersonType;
+ private transient RawType addressType;
+
+ public void initialize(EntityModel model) {
+ newPersonType = model.getRawType
+ (ConvertExample3_Person.class.getName());
+ addressType = model.getRawType
+ (ConvertExample3_Address.class.getName());
+ }
+
+ public Object convert(Object fromValue) {
+
+ RawObject person = (RawObject) fromValue;
+ Map<String,Object> personValues = person.getValues();
+ Map<String,Object> addressValues = new HashMap<String,Object>();
+ RawObject address = new RawObject
+ (addressType, addressValues, null);
+
+ addressValues.put("street", personValues.remove("street"));
+ addressValues.put("city", personValues.remove("city"));
+ addressValues.put("state", personValues.remove("state"));
+ addressValues.put("zipCode", personValues.remove("zipCode"));
+ personValues.put("address", address);
+
+ return new RawObject
+ (newPersonType, personValues, person.getSuper());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof ConvertExample3_Conversion;
+ }
+ }
+
+ @Entity(version=1)
+ static class ConvertExample3_Person
+ extends EvolveCase {
+
+ private static final String NAME =
+ ConvertExample3_Person.class.getName();
+ private static final String NAME2 =
+ ConvertExample3_Address .class.getName();
+
+ @PrimaryKey
+ int key;
+
+ ConvertExample3_Address address;
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ Converter converter = new Converter
+ (ConvertExample3_Person.class.getName(), 0,
+ new ConvertExample3_Conversion());
+ m.addConverter(converter);
+ return m;
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 1, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 1, NAME, 0);
+ } else {
+ checkVersions(model, NAME, 1);
+ }
+ checkVersions(model, NAME2, 0);
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ConvertExample3_Person>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ ConvertExample3_Person.class);
+ ConvertExample3_Person obj = index.get(99);
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertNotNull(obj.address);
+ TestCase.assertEquals("street", obj.address.street);
+ TestCase.assertEquals("city", obj.address.city);
+ TestCase.assertEquals("state", obj.address.state);
+ TestCase.assertEquals(12345, obj.address.zipCode);
+
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ConvertExample3_Person>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ ConvertExample3_Person.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get(99);
+ index.put((ConvertExample3_Person)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawObject obj = readRaw
+ (store, 99, NAME, expectEvolved ? 1 : 0, CASECLS, 0);
+ if (expectEvolved) {
+ RawType embedType = store.getModel().getRawType(NAME2);
+ Object embed = new RawObject
+ (embedType,
+ makeValues("street", "street",
+ "city", "city",
+ "state", "state",
+ "zipCode", 12345),
+ null);
+ checkRawFields(obj, "key", 99, "address", embed);
+ } else {
+ checkRawFields(obj, "key", 99,
+ "street", "street",
+ "city", "city",
+ "state", "state",
+ "zipCode", 12345);
+ }
+ }
+ }
+
+ @SuppressWarnings("serial")
+ static class ConvertExample3Reverse_Conversion implements Conversion {
+ private transient RawType newPersonType;
+
+ public void initialize(EntityModel model) {
+ newPersonType = model.getRawType
+ (ConvertExample3Reverse_Person.class.getName());
+ }
+
+ public Object convert(Object fromValue) {
+
+ RawObject person = (RawObject) fromValue;
+ Map<String,Object> personValues = person.getValues();
+ RawObject address = (RawObject) personValues.remove("address");
+ Map<String,Object> addressValues = address.getValues();
+
+ personValues.put("street", addressValues.remove("street"));
+ personValues.put("city", addressValues.remove("city"));
+ personValues.put("state", addressValues.remove("state"));
+ personValues.put("zipCode", addressValues.remove("zipCode"));
+
+ return new RawObject
+ (newPersonType, personValues, person.getSuper());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof ConvertExample3Reverse_Conversion;
+ }
+ }
+
+ @Entity(version=1)
+ static class ConvertExample3Reverse_Person
+ extends EvolveCase {
+
+ private static final String NAME =
+ ConvertExample3Reverse_Person.class.getName();
+ private static final String NAME2 =
+ PREFIX + "ConvertExample3Reverse_Address";
+
+ @PrimaryKey
+ int key;
+
+ String street;
+ String city;
+ String state;
+ int zipCode;
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ Converter converter = new Converter
+ (ConvertExample3Reverse_Person.class.getName(), 0,
+ new ConvertExample3Reverse_Conversion());
+ m.addConverter(converter);
+ m.addDeleter(new Deleter(NAME2, 0));
+ return m;
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 1, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 1, NAME, 0);
+ checkVersions(model, NAME2, 0);
+ } else {
+ checkVersions(model, NAME, 1);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ConvertExample3Reverse_Person>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ ConvertExample3Reverse_Person.class);
+ ConvertExample3Reverse_Person obj = index.get(99);
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertEquals("street", obj.street);
+ TestCase.assertEquals("city", obj.city);
+ TestCase.assertEquals("state", obj.state);
+ TestCase.assertEquals(12345, obj.zipCode);
+
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ConvertExample3Reverse_Person>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ ConvertExample3Reverse_Person.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get(99);
+ index.put((ConvertExample3Reverse_Person)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawObject obj = readRaw
+ (store, 99, NAME, expectEvolved ? 1 : 0, CASECLS, 0);
+ if (expectEvolved) {
+ checkRawFields(obj, "key", 99,
+ "street", "street",
+ "city", "city",
+ "state", "state",
+ "zipCode", 12345);
+ } else {
+ RawType embedType = store.getModel().getRawType(NAME2);
+ Object embed = new RawObject
+ (embedType,
+ makeValues("street", "street",
+ "city", "city",
+ "state", "state",
+ "zipCode", 12345),
+ null);
+ checkRawFields(obj, "key", 99, "address", embed);
+ }
+ }
+ }
+
+ @Persistent(version=1)
+ static class ConvertExample4_A extends ConvertExample4_B {
+ }
+
+ @Persistent(version=1)
+ static class ConvertExample4_B {
+ String name;
+ }
+
+ @SuppressWarnings("serial")
+ static class Example4_Conversion implements Conversion {
+ private transient RawType newAType;
+ private transient RawType newBType;
+
+ public void initialize(EntityModel model) {
+ newAType = model.getRawType(ConvertExample4_A.class.getName());
+ newBType = model.getRawType(ConvertExample4_B.class.getName());
+ }
+
+ public Object convert(Object fromValue) {
+ RawObject oldA = (RawObject) fromValue;
+ RawObject oldB = oldA.getSuper();
+ Map<String,Object> aValues = oldA.getValues();
+ Map<String,Object> bValues = oldB.getValues();
+ bValues.put("name", aValues.remove("name"));
+ RawObject newB = new RawObject(newBType, bValues, oldB.getSuper());
+ RawObject newA = new RawObject(newAType, aValues, newB);
+ return newA;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof Example4_Conversion;
+ }
+ }
+
+ @Entity(version=1)
+ static class ConvertExample4_Entity
+ extends EvolveCase {
+
+ private static final String NAME =
+ ConvertExample4_Entity.class.getName();
+ private static final String NAME2 =
+ ConvertExample4_A .class.getName();
+ private static final String NAME3 =
+ ConvertExample4_B .class.getName();
+
+ @PrimaryKey
+ int key;
+
+ ConvertExample4_A embed;
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ Converter converter = new Converter
+ (ConvertExample4_A.class.getName(), 0,
+ new Example4_Conversion());
+ m.addConverter(converter);
+ return m;
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 1, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 1, NAME, 0);
+ checkVersions(model, NAME2, 1, NAME2, 0);
+ checkVersions(model, NAME3, 1, NAME3, 0);
+ } else {
+ checkVersions(model, NAME, 1);
+ checkVersions(model, NAME2, 1);
+ checkVersions(model, NAME3, 1);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ConvertExample4_Entity>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ ConvertExample4_Entity.class);
+ ConvertExample4_Entity obj = index.get(99);
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertNotNull(obj.embed);
+ TestCase.assertEquals("name", obj.embed.name);
+
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ConvertExample4_Entity>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ ConvertExample4_Entity.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get(99);
+ index.put((ConvertExample4_Entity)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawType embedTypeA = store.getModel().getRawType(NAME2);
+ RawType embedTypeB = store.getModel().getRawType(NAME3);
+ Object embed;
+ if (expectEvolved) {
+ embed = new RawObject(embedTypeA, makeValues(),
+ new RawObject
+ (embedTypeB, makeValues("name", "name"), null));
+ } else {
+ embed = new RawObject(embedTypeA, makeValues("name", "name"),
+ new RawObject
+ (embedTypeB, makeValues(), null));
+ }
+ RawObject obj = readRaw
+ (store, 99, NAME, expectEvolved ? 1 : 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "embed", embed);
+ }
+ }
+
+ @Persistent(version=1)
+ static class ConvertExample5_Pet {
+ String name;
+ }
+
+ @Persistent
+ static class ConvertExample5_Cat extends ConvertExample5_Pet {
+ int finickyLevel;
+ }
+
+ @Persistent
+ static class ConvertExample5_Dog extends ConvertExample5_Pet {
+ double barkVolume;
+ }
+
+ @SuppressWarnings("serial")
+ static class ConvertExample5_Conversion implements Conversion {
+ private transient RawType newPetType;
+ private transient RawType dogType;
+ private transient RawType catType;
+
+ public void initialize(EntityModel model) {
+ newPetType = model.getRawType(ConvertExample5_Pet.class.getName());
+ dogType = model.getRawType(ConvertExample5_Dog.class.getName());
+ catType = model.getRawType(ConvertExample5_Cat.class.getName());
+ }
+
+ public Object convert(Object fromValue) {
+ RawObject pet = (RawObject) fromValue;
+ Map<String,Object> petValues = pet.getValues();
+ Map<String,Object> subTypeValues = new HashMap<String,Object>();
+ Boolean isCat = (Boolean) petValues.remove("isCatNotDog");
+ Integer finickyLevel = (Integer) petValues.remove("finickyLevel");
+ Double barkVolume = (Double) petValues.remove("barkVolume");
+ RawType newSubType;
+ if (isCat) {
+ newSubType = catType;
+ subTypeValues.put("finickyLevel", finickyLevel);
+ } else {
+ newSubType = dogType;
+ subTypeValues.put("barkVolume", barkVolume);
+ }
+ RawObject newPet = new RawObject
+ (newPetType, petValues, pet.getSuper());
+ return new RawObject(newSubType, subTypeValues, newPet);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof ConvertExample5_Conversion;
+ }
+ }
+
+ @Entity(version=1)
+ static class ConvertExample5_Entity
+ extends EvolveCase {
+
+ private static final String NAME =
+ ConvertExample5_Entity.class.getName();
+ private static final String NAME2 =
+ ConvertExample5_Pet.class.getName();
+ private static final String NAME3 =
+ ConvertExample5_Cat.class.getName();
+ private static final String NAME4 =
+ ConvertExample5_Dog.class.getName();
+
+ @PrimaryKey
+ int key;
+
+ ConvertExample5_Cat cat;
+ ConvertExample5_Dog dog;
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ Converter converter = new Converter
+ (ConvertExample5_Pet.class.getName(), 0,
+ new ConvertExample5_Conversion());
+ m.addConverter(converter);
+ return m;
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 1, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 1, NAME, 0);
+ checkVersions(model, NAME2, 1, NAME2, 0);
+ } else {
+ checkVersions(model, NAME, 1);
+ checkVersions(model, NAME2, 1);
+ }
+ checkVersions(model, NAME3, 0);
+ checkVersions(model, NAME4, 0);
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ConvertExample5_Entity>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ ConvertExample5_Entity.class);
+ ConvertExample5_Entity obj = index.get(99);
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertNotNull(obj.cat);
+ TestCase.assertEquals("Jeffry", obj.cat.name);
+ TestCase.assertEquals(999, obj.cat.finickyLevel);
+ TestCase.assertNotNull(obj.dog);
+ TestCase.assertEquals("Nelson", obj.dog.name);
+ TestCase.assertEquals(0.01, obj.dog.barkVolume);
+
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ConvertExample5_Entity>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ ConvertExample5_Entity.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get(99);
+ index.put((ConvertExample5_Entity)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawType petType = store.getModel().getRawType(NAME2);
+ RawObject cat;
+ RawObject dog;
+ if (expectEvolved) {
+ RawType catType = store.getModel().getRawType(NAME3);
+ RawType dogType = store.getModel().getRawType(NAME4);
+ cat = new RawObject(catType, makeValues("finickyLevel", 999),
+ new RawObject(petType, makeValues("name", "Jeffry"),
+ null));
+ dog = new RawObject(dogType, makeValues("barkVolume", 0.01),
+ new RawObject(petType, makeValues("name", "Nelson"),
+ null));
+ } else {
+ cat = new RawObject(petType, makeValues("name", "Jeffry",
+ "isCatNotDog", true,
+ "finickyLevel", 999,
+ "barkVolume", 0.0),
+ null);
+ dog = new RawObject(petType, makeValues("name", "Nelson",
+ "isCatNotDog", false,
+ "finickyLevel", 0,
+ "barkVolume", 0.01),
+ null);
+ }
+ RawObject obj = readRaw
+ (store, 99, NAME, expectEvolved ? 1 : 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "cat", cat, "dog", dog);
+ }
+ }
+
+ @Persistent(version=1)
+ static class AllowFieldAddDelete_Embed {
+ private final String f0 = "0";
+ private String f2;
+ private final int f3 = 3;
+ private String f4;
+ private final int f5 = 5;
+ private final String f8 = "8";
+ private final int f9 = 9;
+ }
+
+ @Persistent(version=1)
+ static class AllowFieldAddDelete_Base
+ extends EvolveCase {
+
+ private final String f0 = "0";
+ private String f2;
+ private final int f3 = 3;
+ private String f4;
+ private final int f5 = 5;
+ private final String f8 = "8";
+ private final int f9 = 9;
+ }
+
+ @Entity(version=1)
+ static class AllowFieldAddDelete
+ extends AllowFieldAddDelete_Base {
+
+ private static final String NAME =
+ AllowFieldAddDelete.class.getName();
+ private static final String NAME2 =
+ AllowFieldAddDelete_Base.class.getName();
+ private static final String NAME3 =
+ AllowFieldAddDelete_Embed.class.getName();
+
+ @PrimaryKey
+ int key;
+
+ AllowFieldAddDelete_Embed embed;
+
+ private final String f0 = "0";
+ private String f2;
+ private final int f3 = 3;
+ private String f4;
+ private final int f5 = 5;
+ private final String f8 = "8";
+ private final int f9 = 9;
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ for (String name : new String[] {NAME, NAME2, NAME3}) {
+ m.addDeleter(new Deleter(name, 0, "f1"));
+ m.addDeleter(new Deleter(name, 0, "f6"));
+ m.addDeleter(new Deleter(name, 0, "f7"));
+ }
+ return m;
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 1, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 1, NAME, 0);
+ checkVersions(model, NAME2, 1, NAME2, 0);
+ checkVersions(model, NAME3, 1, NAME3, 0);
+ } else {
+ checkVersions(model, NAME, 1);
+ checkVersions(model, NAME2, 1);
+ checkVersions(model, NAME3, 1);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,AllowFieldAddDelete>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ AllowFieldAddDelete.class);
+ AllowFieldAddDelete obj = index.get(99);
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(99, obj.key);
+ {
+ AllowFieldAddDelete o = obj;
+
+ TestCase.assertNotNull(o);
+ TestCase.assertEquals("0", o.f0);
+ TestCase.assertEquals("2", o.f2);
+ TestCase.assertEquals(3, o.f3);
+ TestCase.assertEquals("4", o.f4);
+ TestCase.assertEquals(5, o.f5);
+ TestCase.assertEquals("8", o.f8);
+ TestCase.assertEquals(9, o.f9);
+ }
+ {
+ AllowFieldAddDelete_Base o = obj;
+
+ TestCase.assertNotNull(o);
+ TestCase.assertEquals("0", o.f0);
+ TestCase.assertEquals("2", o.f2);
+ TestCase.assertEquals(3, o.f3);
+ TestCase.assertEquals("4", o.f4);
+ TestCase.assertEquals(5, o.f5);
+ TestCase.assertEquals("8", o.f8);
+ TestCase.assertEquals(9, o.f9);
+ }
+ {
+ AllowFieldAddDelete_Embed o = obj.embed;
+
+ TestCase.assertNotNull(o);
+ TestCase.assertEquals("0", o.f0);
+ TestCase.assertEquals("2", o.f2);
+ TestCase.assertEquals(3, o.f3);
+ TestCase.assertEquals("4", o.f4);
+ TestCase.assertEquals(5, o.f5);
+ TestCase.assertEquals("8", o.f8);
+ TestCase.assertEquals(9, o.f9);
+ }
+
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,AllowFieldAddDelete>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ AllowFieldAddDelete.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get(99);
+ index.put((AllowFieldAddDelete)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ static final Object[] fixedFields0 = {
+ "f1", 1,
+ "f2", "2",
+ "f4", "4",
+ "f6", 6,
+ "f7", "7",
+ };
+
+ static final Object[] fixedFields1 = {
+ "f2", "2",
+ "f4", "4",
+ };
+
+ static final Object[] fixedFields2 = {
+ "f0", "0",
+ "f2", "2",
+ "f3", 3,
+ "f4", "4",
+ "f5", 5,
+ "f8", "8",
+ "f9", 9,
+ };
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawType baseType = store.getModel().getRawType(NAME2);
+ RawType embedType = store.getModel().getRawType(NAME3);
+
+ Object[] ff;
+ if (expectEvolved) {
+ if (expectUpdated) {
+ ff = fixedFields2;
+ } else {
+ ff = fixedFields1;
+ }
+ } else {
+ ff = fixedFields0;
+ }
+ RawObject embed = new RawObject(embedType, makeValues(ff), null);
+ RawObject obj = readRaw
+ (store, 99, NAME, expectEvolved ? 1 : 0,
+ NAME2, expectEvolved ? 1 : 0,
+ CASECLS, 0);
+ checkRaw(obj, ff, "key", 99, "embed", embed);
+ checkRaw(obj.getSuper(), ff);
+ }
+
+ private void checkRaw(RawObject obj,
+ Object[] fixedFields,
+ Object... otherFields) {
+ Object[] allFields =
+ new Object[otherFields.length + fixedFields.length];
+ System.arraycopy(otherFields, 0, allFields, 0, otherFields.length);
+ System.arraycopy(fixedFields, 0, allFields,
+ otherFields.length, fixedFields.length);
+ checkRawFields(obj, allFields);
+ }
+ }
+
+ static class ProxiedClass {
+ int data;
+
+ ProxiedClass(int data) {
+ this.data = data;
+ }
+ }
+
+ @Persistent(version=1, proxyFor=ProxiedClass.class)
+ static class ProxiedClass_Proxy implements PersistentProxy<ProxiedClass> {
+ long data;
+
+ public void initializeProxy(ProxiedClass o) {
+ data = o.data;
+ }
+
+ public ProxiedClass convertProxy() {
+ return new ProxiedClass((int) data);
+ }
+ }
+
+ @Entity
+ static class ProxiedClass_Entity
+ extends EvolveCase {
+
+ private static final String NAME =
+ ProxiedClass_Entity.class.getName();
+ private static final String NAME2 =
+ ProxiedClass_Proxy.class.getName();
+
+ @PrimaryKey
+ int key;
+
+ ProxiedClass embed;
+
+ @Override
+ void configure(EntityModel model, StoreConfig config) {
+ model.registerClass(ProxiedClass_Proxy.class);
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ if (oldTypesExist) {
+ checkVersions(model, NAME2, 1, NAME2, 0);
+ } else {
+ checkVersions(model, NAME2, 1);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ProxiedClass_Entity>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ ProxiedClass_Entity.class);
+ ProxiedClass_Entity obj = index.get(99);
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertNotNull(obj.embed);
+ TestCase.assertEquals(88, obj.embed.data);
+
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ProxiedClass_Entity>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ ProxiedClass_Entity.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get(99);
+ index.put((ProxiedClass_Entity)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawType embedType = store.getModel().getRawType(NAME2);
+ RawObject embed;
+ if (expectEvolved) {
+ embed = new RawObject
+ (embedType, makeValues("data", 88L), null);
+ } else {
+ embed = new RawObject
+ (embedType, makeValues("data", 88), null);
+ }
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "embed", embed);
+ }
+ }
+
+ @Persistent(proxyFor=StringBuffer.class)
+ static class DisallowChangeProxyFor_Proxy2
+ implements PersistentProxy<StringBuffer> {
+
+ String data;
+
+ public void initializeProxy(StringBuffer o) {
+ data = o.toString();
+ }
+
+ public StringBuffer convertProxy() {
+ return new StringBuffer(data);
+ }
+ }
+
+ @Persistent(proxyFor=StringBuilder.class)
+ static class DisallowChangeProxyFor_Proxy
+ implements PersistentProxy<StringBuilder> {
+
+ String data;
+
+ public void initializeProxy(StringBuilder o) {
+ data = o.toString();
+ }
+
+ public StringBuilder convertProxy() {
+ return new StringBuilder(data);
+ }
+ }
+
+ @Entity
+ static class DisallowChangeProxyFor
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Error when evolving class: java.lang.StringBuffer version: 0 to class: java.lang.StringBuffer version: 0 Error: The proxy class for this type has been changed from: com.sleepycat.persist.test.EvolveClasses$DisallowChangeProxyFor_Proxy to: com.sleepycat.persist.test.EvolveClasses$DisallowChangeProxyFor_Proxy2";
+ }
+
+ @Override
+ void configure(EntityModel model, StoreConfig config) {
+ model.registerClass(DisallowChangeProxyFor_Proxy.class);
+ model.registerClass(DisallowChangeProxyFor_Proxy2.class);
+ }
+ }
+
+ @Persistent
+ static class DisallowDeleteProxyFor_Proxy {
+ String data;
+ }
+
+ @Entity
+ static class DisallowDeleteProxyFor
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Mutation is missing to evolve class: java.lang.StringBuffer version: 0 Error: java.lang.IllegalArgumentException: Class could not be loaded or is not persistent: java.lang.StringBuffer";
+ }
+ }
+
+ @Persistent(version=1)
+ static class ArrayNameChange_Component_Renamed {
+
+ long data;
+ }
+
+ @Entity
+ static class ArrayNameChange_Entity
+ extends EvolveCase {
+
+ private static final String NAME =
+ ArrayNameChange_Entity.class.getName();
+ private static final String NAME2 =
+ ArrayNameChange_Component_Renamed.class.getName();
+ private static final String NAME3 =
+ PREFIX + "ArrayNameChange_Component";
+
+ @PrimaryKey
+ int key;
+
+ ArrayNameChange_Component_Renamed[] embed;
+ ArrayNameChange_Component_Renamed embed2;
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ m.addRenamer(new Renamer(NAME3, 0, NAME2));
+ return m;
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ if (oldTypesExist) {
+ checkVersions(model, NAME2, 1, NAME3, 0);
+ } else {
+ checkVersions(model, NAME2, 1);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ArrayNameChange_Entity>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ ArrayNameChange_Entity.class);
+ ArrayNameChange_Entity obj = index.get(99);
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertNotNull(obj.embed);
+ TestCase.assertEquals(1, obj.embed.length);
+ TestCase.assertEquals(88L, obj.embed[0].data);
+ TestCase.assertSame(obj.embed2, obj.embed[0]);
+
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ArrayNameChange_Entity>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ ArrayNameChange_Entity.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get(99);
+ index.put((ArrayNameChange_Entity)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ String compTypeName = expectEvolved ? NAME2 : NAME3;
+ String arrayTypeName = "[L" + compTypeName + ';';
+ RawType compType = store.getModel().getRawType(compTypeName);
+ RawType arrayType = store.getModel().getRawType(arrayTypeName);
+ RawObject embed2;
+ if (expectEvolved) {
+ embed2 = new RawObject
+ (compType, makeValues("data", 88L), null);
+ } else {
+ embed2 = new RawObject
+ (compType, makeValues("data", 88), null);
+ }
+ RawObject embed = new RawObject
+ (arrayType, new Object[] { embed2 });
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ checkRawFields(obj, "key", 99, "embed", embed, "embed2", embed2);
+ }
+ }
+
+ enum AddEnumConstant_Enum {
+ A, B, C;
+ }
+
+ @Entity(version=1)
+ static class AddEnumConstant_Entity
+ extends EvolveCase {
+
+ private static final String NAME =
+ AddEnumConstant_Entity.class.getName();
+ private static final String NAME2 =
+ AddEnumConstant_Enum.class.getName();
+
+ @PrimaryKey
+ int key;
+
+ AddEnumConstant_Enum e1;
+ AddEnumConstant_Enum e2;
+ AddEnumConstant_Enum e3 = AddEnumConstant_Enum.C;
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 1, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 1, NAME, 0);
+ checkVersions(model, NAME2, 0, NAME2, 0);
+ } else {
+ checkVersions(model, NAME, 1);
+ checkVersions(model, NAME2, 0);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,AddEnumConstant_Entity>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ AddEnumConstant_Entity.class);
+ AddEnumConstant_Entity obj = index.get(99);
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertSame(AddEnumConstant_Enum.A, obj.e1);
+ TestCase.assertSame(AddEnumConstant_Enum.B, obj.e2);
+ TestCase.assertSame(AddEnumConstant_Enum.C, obj.e3);
+
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,AddEnumConstant_Entity>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ AddEnumConstant_Entity.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get(99);
+ index.put((AddEnumConstant_Entity)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawObject obj = readRaw
+ (store, 99, NAME, expectEvolved ? 1 : 0, CASECLS, 0);
+ RawType enumType = store.getModel().getRawType(NAME2);
+ if (expectUpdated) {
+ checkRawFields(obj, "key", 99,
+ "e1", new RawObject(enumType, "A"),
+ "e2", new RawObject(enumType, "B"),
+ "e3", new RawObject(enumType, "C"));
+ } else {
+ checkRawFields(obj, "key", 99,
+ "e1", new RawObject(enumType, "A"),
+ "e2", new RawObject(enumType, "B"));
+ }
+ }
+ }
+
+ enum InsertEnumConstant_Enum {
+ X, A, Y, B, Z;
+ }
+
+ @Persistent
+ static class InsertEnumConstant_KeyClass
+ implements Comparable<InsertEnumConstant_KeyClass > {
+
+ @KeyField(1)
+ InsertEnumConstant_Enum key;
+
+ private InsertEnumConstant_KeyClass() {}
+
+ InsertEnumConstant_KeyClass(InsertEnumConstant_Enum key) {
+ this.key = key;
+ }
+
+ public int compareTo(InsertEnumConstant_KeyClass o) {
+ /* Use the natural order, in spite of insertions. */
+ return key.compareTo(o.key);
+ }
+ }
+
+ @Entity(version=1)
+ static class InsertEnumConstant_Entity
+ extends EvolveCase {
+
+ private static final String NAME =
+ InsertEnumConstant_Entity.class.getName();
+ private static final String NAME2 =
+ InsertEnumConstant_Enum.class.getName();
+ private static final String NAME3 =
+ InsertEnumConstant_KeyClass.class.getName();
+
+ @PrimaryKey
+ int key;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ InsertEnumConstant_KeyClass secKey;
+
+ InsertEnumConstant_Enum e1;
+ InsertEnumConstant_Enum e2;
+ InsertEnumConstant_Enum e3 = InsertEnumConstant_Enum.X;
+ InsertEnumConstant_Enum e4 = InsertEnumConstant_Enum.Y;
+ InsertEnumConstant_Enum e5 = InsertEnumConstant_Enum.Z;
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 1, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 1, NAME, 0);
+ checkVersions(model, NAME2, 0, NAME2, 0);
+ checkVersions(model, NAME3, 0, NAME3, 0);
+ } else {
+ checkVersions(model, NAME, 1);
+ checkVersions(model, NAME2, 0);
+ checkVersions(model, NAME3, 0);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,InsertEnumConstant_Entity>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ InsertEnumConstant_Entity.class);
+ InsertEnumConstant_Entity obj = index.get(99);
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(99, obj.key);
+ if (updated) {
+ TestCase.assertSame(InsertEnumConstant_Enum.X, obj.secKey.key);
+ } else {
+ TestCase.assertSame(InsertEnumConstant_Enum.A, obj.secKey.key);
+ }
+ TestCase.assertSame(InsertEnumConstant_Enum.A, obj.e1);
+ TestCase.assertSame(InsertEnumConstant_Enum.B, obj.e2);
+ TestCase.assertSame(InsertEnumConstant_Enum.X, obj.e3);
+ TestCase.assertSame(InsertEnumConstant_Enum.Y, obj.e4);
+ TestCase.assertSame(InsertEnumConstant_Enum.Z, obj.e5);
+
+ if (doUpdate) {
+ obj.secKey =
+ new InsertEnumConstant_KeyClass(InsertEnumConstant_Enum.X);
+ index.put(obj);
+ updated = true;
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,InsertEnumConstant_Entity>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ InsertEnumConstant_Entity.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get(99);
+ index.put((InsertEnumConstant_Entity)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawObject obj = readRaw
+ (store, 99, NAME, expectEvolved ? 1 : 0, CASECLS, 0);
+ RawType enumType = store.getModel().getRawType(NAME2);
+
+ Map<String, Object> secKeyFields = new HashMap<String, Object>();
+ RawType secKeyType = store.getModel().getRawType(NAME3);
+ RawObject secKeyObject =
+ new RawObject(secKeyType, secKeyFields, null /*superObject*/);
+
+ if (expectUpdated) {
+ secKeyFields.put("key", new RawObject(enumType, "X"));
+ checkRawFields(obj, "key", 99,
+ "secKey", secKeyObject,
+ "e1", new RawObject(enumType, "A"),
+ "e2", new RawObject(enumType, "B"),
+ "e3", new RawObject(enumType, "X"),
+ "e4", new RawObject(enumType, "Y"),
+ "e5", new RawObject(enumType, "Z"));
+ } else {
+ secKeyFields.put("key", new RawObject(enumType, "A"));
+ checkRawFields(obj, "key", 99,
+ "secKey", secKeyObject,
+ "e1", new RawObject(enumType, "A"),
+ "e2", new RawObject(enumType, "B"));
+ }
+ }
+ }
+
+ enum DeleteEnumConstant_Enum {
+ A, C;
+ }
+
+ /**
+ * Don't allow deleting (or renaming, which appears as a deletion) enum
+ * values without mutations.
+ */
+ @Entity
+ static class DeleteEnumConstant_NoMutation
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+
+ DeleteEnumConstant_Enum e1;
+ DeleteEnumConstant_Enum e2;
+ DeleteEnumConstant_Enum e3;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Incompatible enum type changed detected when evolving class: com.sleepycat.persist.test.EvolveClasses$DeleteEnumConstant_Enum version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DeleteEnumConstant_Enum version: 0 Error: Enum values may not be removed: [B]";
+ }
+ }
+
+ /**
+ * With a Deleter, deleted enum values are null. Note that version is not
+ * bumped.
+ */
+ /* Disabled until support for enum deletion is added.
+ @Entity
+ static class DeleteEnumConstant_WithDeleter
+ extends EvolveCase {
+
+ private static final String NAME =
+ DeleteEnumConstant_WithDeleter.class.getName();
+ private static final String NAME2 =
+ DeleteEnumConstant_Enum.class.getName();
+
+ @PrimaryKey
+ int key;
+
+ DeleteEnumConstant_Enum e1;
+ DeleteEnumConstant_Enum e2;
+ DeleteEnumConstant_Enum e3;
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 0, null);
+ checkVersions(model, NAME, 0);
+ if (oldTypesExist) {
+ checkVersions(model, NAME2, 0, NAME2, 0);
+ } else {
+ checkVersions(model, NAME2, 0);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeleteEnumConstant_WithDeleter>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeleteEnumConstant_WithDeleter.class);
+ DeleteEnumConstant_WithDeleter obj = index.get(99);
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertSame(DeleteEnumConstant_Enum.A, obj.e1);
+ TestCase.assertSame(null, obj.e2);
+ TestCase.assertSame(DeleteEnumConstant_Enum.C, obj.e3);
+
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeleteEnumConstant_WithDeleter>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ DeleteEnumConstant_WithDeleter.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get(99);
+ index.put((DeleteEnumConstant_WithDeleter)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawObject obj = readRaw(store, 99, NAME, 0, CASECLS, 0);
+ RawType enumType = store.getModel().getRawType(NAME2);
+ if (expectUpdated) {
+ checkRawFields(obj, "key", 99,
+ "e1", new RawObject(enumType, "A"),
+ "e2", null,
+ "e3", new RawObject(enumType, "C"));
+ } else {
+ checkRawFields(obj, "key", 99,
+ "e1", new RawObject(enumType, "A"),
+ "e2", new RawObject(enumType, "B"),
+ "e3", new RawObject(enumType, "C"));
+ }
+ }
+ }
+ */
+
+ /**
+ * A field converter can assign deleted enum values. Version must be
+ * bumped when a converter is added.
+ */
+ /* Disabled until support for enum deletion is added.
+ @Entity(version=1)
+ static class DeleteEnumConstant_WithConverter
+ extends EvolveCase {
+
+ private static final String NAME =
+ DeleteEnumConstant_WithConverter.class.getName();
+ private static final String NAME2 =
+ DeleteEnumConstant_Enum.class.getName();
+
+ @PrimaryKey
+ int key;
+
+ DeleteEnumConstant_Enum e1;
+ DeleteEnumConstant_Enum e2;
+ DeleteEnumConstant_Enum e3;
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ Conversion c = new MyConversion();
+ m.addConverter(new Converter(NAME, 0, "e1", c));
+ m.addConverter(new Converter(NAME, 0, "e2", c));
+ m.addConverter(new Converter(NAME, 0, "e3", c));
+ return m;
+ }
+
+ @SuppressWarnings("serial")
+ static class MyConversion implements Conversion {
+
+ transient RawType newType;
+
+ public void initialize(EntityModel model) {
+ newType = model.getRawType(NAME2);
+ TestCase.assertNotNull(newType);
+ }
+
+ public Object convert(Object fromValue) {
+ TestCase.assertNotNull(newType);
+ RawObject obj = (RawObject) fromValue;
+ String val = obj.getEnum();
+ TestCase.assertNotNull(val);
+ if ("B".equals(val)) {
+ val = "C";
+ }
+ return new RawObject(newType, val);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other instanceof MyConversion;
+ }
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 1, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 1, NAME, 0);
+ checkVersions(model, NAME2, 0, NAME2, 0);
+ } else {
+ checkVersions(model, NAME, 1);
+ checkVersions(model, NAME2, 0);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeleteEnumConstant_WithConverter>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeleteEnumConstant_WithConverter.class);
+ DeleteEnumConstant_WithConverter obj = index.get(99);
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertSame(DeleteEnumConstant_Enum.A, obj.e1);
+ TestCase.assertSame(DeleteEnumConstant_Enum.C, obj.e2);
+ TestCase.assertSame(DeleteEnumConstant_Enum.C, obj.e3);
+
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeleteEnumConstant_WithConverter>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ DeleteEnumConstant_WithConverter.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get(99);
+ index.put((DeleteEnumConstant_WithConverter)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawObject obj = readRaw(store, 99, NAME, expectEvolved ? 1 : 0,
+ CASECLS, 0);
+ RawType enumType = store.getModel().getRawType(NAME2);
+ if (expectEvolved) {
+ checkRawFields(obj, "key", 99,
+ "e1", new RawObject(enumType, "A"),
+ "e2", new RawObject(enumType, "C"),
+ "e3", new RawObject(enumType, "C"));
+ } else {
+ checkRawFields(obj, "key", 99,
+ "e1", new RawObject(enumType, "A"),
+ "e2", new RawObject(enumType, "B"),
+ "e3", new RawObject(enumType, "C"));
+ }
+ }
+ }
+ */
+
+ @Entity
+ static class DisallowChangeKeyRelate
+ extends EvolveCase {
+
+ private static final String NAME =
+ DisallowChangeKeyRelate.class.getName();
+
+ @PrimaryKey
+ int key;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ int skey;
+
+ @Override
+ public String getStoreOpenException() {
+ return "com.sleepycat.persist.evolve.IncompatibleClassException: Change detected in the relate attribute (Relationship) of a secondary key when evolving class: com.sleepycat.persist.test.EvolveClasses$DisallowChangeKeyRelate version: 0 to class: com.sleepycat.persist.test.EvolveClasses$DisallowChangeKeyRelate version: 0 Error: Old key: skey relate: ONE_TO_ONE new key: skey relate: MANY_TO_ONE";
+ }
+ }
+
+ @Entity(version=1)
+ static class AllowChangeKeyMetadata
+ extends EvolveCase {
+
+ private static final String NAME =
+ AllowChangeKeyMetadata.class.getName();
+
+ @PrimaryKey
+ int key;
+
+ /*
+ * Combined fields from version 0 and 1:
+ * addAnnotation = 88;
+ * dropField = 77;
+ * dropAnnotation = 66;
+ * addField = 55;
+ * renamedField = 44; // was toBeRenamedField
+ * aa = 33;
+ * ff = 22;
+ */
+
+ int aa;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int addAnnotation;
+
+ int dropAnnotation;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ Integer addField;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int renamedField;
+
+ int ff;
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ m.addDeleter(new Deleter(NAME, 0, "dropField"));
+ m.addRenamer(new Renamer(NAME, 0, "toBeRenamedField",
+ "renamedField"));
+ return m;
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 1, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 1, NAME, 0);
+ } else {
+ checkVersions(model, NAME, 1);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,AllowChangeKeyMetadata>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ AllowChangeKeyMetadata.class);
+ AllowChangeKeyMetadata obj = index.get(99);
+ checkValues(obj);
+
+ checkValues(store.getSecondaryIndex
+ (index, Integer.class, "addAnnotation").get(88));
+ checkValues(store.getSecondaryIndex
+ (index, Integer.class, "renamedField").get(44));
+ if (updated) {
+ checkValues(store.getSecondaryIndex
+ (index, Integer.class, "addField").get(55));
+ } else {
+ TestCase.assertNull(store.getSecondaryIndex
+ (index, Integer.class, "addField").get(55));
+ }
+
+ if (doUpdate) {
+ obj.addField = 55;
+ index.put(obj);
+ updated = true;
+ checkValues(store.getSecondaryIndex
+ (index, Integer.class, "addAnnotation").get(88));
+ checkValues(store.getSecondaryIndex
+ (index, Integer.class, "addField").get(55));
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,AllowChangeKeyMetadata>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ AllowChangeKeyMetadata.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get(99);
+ index.put((AllowChangeKeyMetadata)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ private void checkValues(AllowChangeKeyMetadata obj) {
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertEquals(88, obj.addAnnotation);
+ TestCase.assertEquals(66, obj.dropAnnotation);
+ TestCase.assertEquals(44, obj.renamedField);
+ TestCase.assertEquals(33, obj.aa);
+ TestCase.assertEquals(22, obj.ff);
+ if (updated) {
+ TestCase.assertEquals(Integer.valueOf(55), obj.addField);
+ } else {
+ TestCase.assertNull(obj.addField);
+ }
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawObject obj = readRaw
+ (store, 99, NAME, expectEvolved ? 1 : 0, CASECLS, 0);
+ if (expectUpdated) {
+ checkRawFields(obj, "key", 99,
+ "addAnnotation", 88,
+ "dropAnnotation", 66,
+ "addField", 55,
+ "renamedField", 44,
+ "aa", 33,
+ "ff", 22);
+ } else if (expectEvolved) {
+ checkRawFields(obj, "key", 99,
+ "addAnnotation", 88,
+ "dropAnnotation", 66,
+ "renamedField", 44,
+ "aa", 33,
+ "ff", 22);
+ } else {
+ checkRawFields(obj, "key", 99,
+ "addAnnotation", 88,
+ "dropField", 77,
+ "dropAnnotation", 66,
+ "toBeRenamedField", 44,
+ "aa", 33,
+ "ff", 22);
+ }
+ Environment env = store.getEnvironment();
+ assertDbExists(expectEvolved, env, NAME, "addAnnotation");
+ assertDbExists(expectEvolved, env, NAME, "addField");
+ assertDbExists(expectEvolved, env, NAME, "renamedField");
+ assertDbExists(!expectEvolved, env, NAME, "toBeRenamedField");
+ assertDbExists(!expectEvolved, env, NAME, "dropField");
+ assertDbExists(!expectEvolved, env, NAME, "dropAnnotation");
+ }
+ }
+
+ /**
+ * Same test as AllowChangeKeyMetadata but with the secondary keys in an
+ * entity subclass. [#16253]
+ */
+ @Persistent(version=1)
+ static class AllowChangeKeyMetadataInSubclass
+ extends AllowChangeKeyMetadataEntity {
+
+ private static final String NAME =
+ AllowChangeKeyMetadataInSubclass.class.getName();
+ private static final String NAME2 =
+ AllowChangeKeyMetadataEntity.class.getName();
+
+ /*
+ * Combined fields from version 0 and 1:
+ * addAnnotation = 88;
+ * dropField = 77;
+ * dropAnnotation = 66;
+ * addField = 55;
+ * renamedField = 44; // was toBeRenamedField
+ * aa = 33;
+ * ff = 22;
+ */
+
+ int aa;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int addAnnotation;
+
+ int dropAnnotation;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ Integer addField;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int renamedField;
+
+ int ff;
+
+ @Override
+ void configure(EntityModel model, StoreConfig config) {
+ model.registerClass(AllowChangeKeyMetadataInSubclass.class);
+ }
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ m.addDeleter(new Deleter(NAME, 0, "dropField"));
+ m.addRenamer(new Renamer(NAME, 0, "toBeRenamedField",
+ "renamedField"));
+ return m;
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkNonEntity(true, model, env, NAME, 1);
+ checkEntity(true, model, env, NAME2, 0, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 1, NAME, 0);
+ checkVersions(model, NAME2, 0);
+ } else {
+ checkVersions(model, NAME, 1);
+ checkVersions(model, NAME2, 0);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,AllowChangeKeyMetadataEntity>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ AllowChangeKeyMetadataEntity.class);
+ AllowChangeKeyMetadataEntity obj = index.get(99);
+ checkValues(obj);
+
+ checkValues(store.getSecondaryIndex
+ (index, Integer.class, "addAnnotation").get(88));
+ checkValues(store.getSecondaryIndex
+ (index, Integer.class, "renamedField").get(44));
+ if (updated) {
+ checkValues(store.getSecondaryIndex
+ (index, Integer.class, "addField").get(55));
+ } else {
+ TestCase.assertNull(store.getSecondaryIndex
+ (index, Integer.class, "addField").get(55));
+ }
+
+ if (doUpdate) {
+ ((AllowChangeKeyMetadataInSubclass) obj).addField = 55;
+ index.put(obj);
+ updated = true;
+ checkValues(store.getSecondaryIndex
+ (index, Integer.class, "addAnnotation").get(88));
+ checkValues(store.getSecondaryIndex
+ (index, Integer.class, "addField").get(55));
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,AllowChangeKeyMetadataEntity>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ AllowChangeKeyMetadataEntity.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME2).get(99);
+ index.put((AllowChangeKeyMetadataInSubclass)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ private void checkValues(AllowChangeKeyMetadataEntity objParam) {
+ AllowChangeKeyMetadataInSubclass obj =
+ (AllowChangeKeyMetadataInSubclass) objParam;
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertEquals(88, obj.addAnnotation);
+ TestCase.assertEquals(66, obj.dropAnnotation);
+ TestCase.assertEquals(44, obj.renamedField);
+ TestCase.assertEquals(33, obj.aa);
+ TestCase.assertEquals(22, obj.ff);
+ if (updated) {
+ TestCase.assertEquals(Integer.valueOf(55), obj.addField);
+ } else {
+ TestCase.assertNull(obj.addField);
+ }
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawObject obj = readRaw
+ (store, NAME2, 99, NAME, expectEvolved ? 1 : 0,
+ NAME2, 0, CASECLS, 0);
+ checkRawFields(obj.getSuper(), "key", 99);
+ if (expectUpdated) {
+ checkRawFields(obj,
+ "addAnnotation", 88,
+ "dropAnnotation", 66,
+ "addField", 55,
+ "renamedField", 44,
+ "aa", 33,
+ "ff", 22);
+ } else if (expectEvolved) {
+ checkRawFields(obj,
+ "addAnnotation", 88,
+ "dropAnnotation", 66,
+ "renamedField", 44,
+ "aa", 33,
+ "ff", 22);
+ } else {
+ checkRawFields(obj,
+ "addAnnotation", 88,
+ "dropField", 77,
+ "dropAnnotation", 66,
+ "toBeRenamedField", 44,
+ "aa", 33,
+ "ff", 22);
+ }
+ Environment env = store.getEnvironment();
+ assertDbExists(expectEvolved, env, NAME2, "addAnnotation");
+ assertDbExists(expectEvolved, env, NAME2, "addField");
+ assertDbExists(expectEvolved, env, NAME2, "renamedField");
+ assertDbExists(!expectEvolved, env, NAME2, "toBeRenamedField");
+ assertDbExists(!expectEvolved, env, NAME2, "dropField");
+ assertDbExists(!expectEvolved, env, NAME2, "dropAnnotation");
+ }
+ }
+
+ @Entity
+ static class AllowChangeKeyMetadataEntity
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+ }
+
+ /**
+ * Special case of adding secondaries that caused
+ * IndexOutOfBoundsException. [#15524]
+ */
+ @Entity(version=1)
+ static class AllowAddSecondary
+ extends EvolveCase {
+
+ private static final String NAME =
+ AllowAddSecondary.class.getName();
+
+ @PrimaryKey
+ long key;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int a;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int b;
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 1, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 1, NAME, 0);
+ } else {
+ checkVersions(model, NAME, 1);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Long,AllowAddSecondary>
+ index = store.getPrimaryIndex
+ (Long.class,
+ AllowAddSecondary.class);
+ AllowAddSecondary obj = index.get(99L);
+ checkValues(obj);
+
+ checkValues(store.getSecondaryIndex
+ (index, Integer.class, "a").get(1));
+ if (updated) {
+ checkValues(store.getSecondaryIndex
+ (index, Integer.class, "b").get(3));
+ TestCase.assertNull(store.getSecondaryIndex
+ (index, Integer.class, "b").get(2));
+ } else {
+ checkValues(store.getSecondaryIndex
+ (index, Integer.class, "b").get(2));
+ TestCase.assertNull(store.getSecondaryIndex
+ (index, Integer.class, "b").get(3));
+ }
+
+ if (doUpdate) {
+ obj.b = 3;
+ index.put(obj);
+ updated = true;
+ checkValues(store.getSecondaryIndex
+ (index, Integer.class, "a").get(1));
+ checkValues(store.getSecondaryIndex
+ (index, Integer.class, "b").get(3));
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Long,AllowAddSecondary>
+ index = newStore.getPrimaryIndex
+ (Long.class,
+ AllowAddSecondary.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get(99L);
+ index.put((AllowAddSecondary)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ private void checkValues(AllowAddSecondary obj) {
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(99L, obj.key);
+ TestCase.assertEquals(1, obj.a);
+ if (updated) {
+ TestCase.assertEquals(3, obj.b);
+ } else {
+ TestCase.assertEquals(2, obj.b);
+ }
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawObject obj = readRaw
+ (store, 99L, NAME, expectEvolved ? 1 : 0, CASECLS, 0);
+ if (expectUpdated) {
+ checkRawFields(obj, "key", 99L,
+ "a", 1,
+ "b", 3);
+ } else {
+ checkRawFields(obj, "key", 99L,
+ "a", 1,
+ "b", 2);
+ }
+ Environment env = store.getEnvironment();
+ assertDbExists(expectEvolved, env, NAME, "a");
+ assertDbExists(expectEvolved, env, NAME, "b");
+ }
+ }
+
+ @Entity(version=1)
+ static class FieldAddAndConvert
+ extends EvolveCase {
+
+ private static final String NAME =
+ FieldAddAndConvert.class.getName();
+
+ @PrimaryKey
+ int key;
+
+ private final String f0 = "0"; // new field
+ private final String f1 = "1"; // converted field
+ private final String f2 = "2"; // new field
+ private final String f3 = "3"; // converted field
+ private final String f4 = "4"; // new field
+
+ @Override
+ Mutations getMutations() {
+ Mutations m = new Mutations();
+ m.addConverter(new Converter(NAME, 0, "f1", new IntToString()));
+ m.addConverter(new Converter(NAME, 0, "f3", new IntToString()));
+ return m;
+ }
+
+ @SuppressWarnings("serial")
+ private static class IntToString implements Conversion {
+
+ public void initialize(EntityModel model) {
+ }
+
+ public Object convert(Object fromValue) {
+ return fromValue.toString();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other instanceof IntToString;
+ }
+ }
+
+ @Override
+ void checkEvolvedModel(EntityModel model,
+ Environment env,
+ boolean oldTypesExist) {
+ checkEntity(true, model, env, NAME, 1, null);
+ if (oldTypesExist) {
+ checkVersions(model, NAME, 1, NAME, 0);
+ } else {
+ checkVersions(model, NAME, 1);
+ }
+ }
+
+ @Override
+ void readObjects(EntityStore store, boolean doUpdate)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,FieldAddAndConvert>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ FieldAddAndConvert.class);
+ FieldAddAndConvert obj = index.get(99);
+ TestCase.assertNotNull(obj);
+ TestCase.assertEquals(99, obj.key);
+ TestCase.assertEquals("0", obj.f0);
+ TestCase.assertEquals("1", obj.f1);
+ TestCase.assertEquals("2", obj.f2);
+ TestCase.assertEquals("3", obj.f3);
+ TestCase.assertEquals("4", obj.f4);
+
+ if (doUpdate) {
+ index.put(obj);
+ }
+ }
+
+ @Override
+ void copyRawObjects(RawStore rawStore, EntityStore newStore)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,FieldAddAndConvert>
+ index = newStore.getPrimaryIndex
+ (Integer.class,
+ FieldAddAndConvert.class);
+ RawObject raw = rawStore.getPrimaryIndex(NAME).get(99);
+ index.put((FieldAddAndConvert)
+ newStore.getModel().convertRawObject(raw));
+ }
+
+ @Override
+ void readRawObjects(RawStore store,
+ boolean expectEvolved,
+ boolean expectUpdated)
+ throws DatabaseException {
+
+ RawObject obj = readRaw
+ (store, 99, NAME, expectEvolved ? 1 : 0, CASECLS, 0);
+ if (expectUpdated) {
+ checkRawFields(obj,
+ "key", 99,
+ "f0", "0",
+ "f1", "1",
+ "f2", "2",
+ "f3", "3",
+ "f4", "4");
+ } else if (expectEvolved) {
+ checkRawFields(obj,
+ "key", 99,
+ "f1", "1",
+ "f3", "3");
+ } else {
+ checkRawFields(obj,
+ "key", 99,
+ "f1", 1,
+ "f3", 3);
+ }
+ }
+ }
+}
diff --git a/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveClasses.java.original b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveClasses.java.original
new file mode 100644
index 0000000..c077920
--- /dev/null
+++ b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveClasses.java.original
@@ -0,0 +1,2855 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+package com.sleepycat.persist.test;
+
+import static com.sleepycat.persist.model.Relationship.MANY_TO_ONE;
+
+import java.math.BigInteger;
+
+import junit.framework.TestCase;
+
+import com.sleepycat.db.Environment;
+import com.sleepycat.db.DatabaseException;
+import com.sleepycat.persist.EntityStore;
+import com.sleepycat.persist.PrimaryIndex;
+import com.sleepycat.persist.SecondaryIndex;
+import com.sleepycat.persist.StoreConfig;
+import com.sleepycat.persist.evolve.Mutations;
+import com.sleepycat.persist.model.Entity;
+import com.sleepycat.persist.model.EntityModel;
+import com.sleepycat.persist.model.KeyField;
+import com.sleepycat.persist.model.Persistent;
+import com.sleepycat.persist.model.PersistentProxy;
+import com.sleepycat.persist.model.PrimaryKey;
+import com.sleepycat.persist.model.SecondaryKey;
+import com.sleepycat.persist.raw.RawStore;
+
+import static com.sleepycat.persist.model.Relationship.ONE_TO_ONE;
+
+/**
+ * Nested classes are original versions of classes of the same name in
+ * EvolveClasses.java. See EvolveTestBase.java for the steps that are taken to
+ * add a new class (test case).
+ *
+ * @author Mark Hayes
+ */
+class EvolveClasses {
+
+ @Entity
+ static class DeletedEntity1_ClassRemoved extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int skey = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeletedEntity1_ClassRemoved> index =
+ store.getPrimaryIndex
+ (Integer.class, DeletedEntity1_ClassRemoved.class);
+ index.put(this);
+
+ SecondaryIndex<Integer,Integer,DeletedEntity1_ClassRemoved>
+ sindex = store.getSecondaryIndex(index, Integer.class, "skey");
+ TestCase.assertNotNull(sindex.get(88));
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ assertDbExists
+ (true, env,
+ DeletedEntity1_ClassRemoved.class.getName());
+ assertDbExists
+ (true, env,
+ DeletedEntity1_ClassRemoved.class.getName(), "skey");
+ }
+ }
+
+ @Entity
+ static class DeletedEntity2_ClassRemoved extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int skey = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeletedEntity2_ClassRemoved> index =
+ store.getPrimaryIndex
+ (Integer.class, DeletedEntity2_ClassRemoved.class);
+ index.put(this);
+
+ SecondaryIndex<Integer,Integer,DeletedEntity2_ClassRemoved>
+ sindex = store.getSecondaryIndex(index, Integer.class, "skey");
+ TestCase.assertNotNull(sindex.get(88));
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ assertDbExists
+ (true, env,
+ DeletedEntity2_ClassRemoved.class.getName());
+ assertDbExists
+ (true, env,
+ DeletedEntity2_ClassRemoved.class.getName(), "skey");
+ }
+ }
+
+ @Entity
+ static class DeletedEntity3_AnnotRemoved_NoMutation extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int skey = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeletedEntity3_AnnotRemoved_NoMutation>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeletedEntity3_AnnotRemoved_NoMutation.class);
+ index.put(this);
+
+ SecondaryIndex<Integer,Integer,
+ DeletedEntity3_AnnotRemoved_NoMutation>
+ sindex = store.getSecondaryIndex(index, Integer.class, "skey");
+ TestCase.assertNotNull(sindex.get(88));
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ assertDbExists
+ (true, env,
+ DeletedEntity3_AnnotRemoved_NoMutation.class.getName());
+ assertDbExists
+ (true, env,
+ DeletedEntity3_AnnotRemoved_NoMutation.class.getName(),
+ "skey");
+ }
+ }
+
+ @Entity
+ static class DeletedEntity4_AnnotRemoved_WithDeleter extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int skey = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeletedEntity4_AnnotRemoved_WithDeleter>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeletedEntity4_AnnotRemoved_WithDeleter.class);
+ index.put(this);
+
+ SecondaryIndex<Integer,Integer,
+ DeletedEntity4_AnnotRemoved_WithDeleter>
+ sindex = store.getSecondaryIndex(index, Integer.class, "skey");
+ TestCase.assertNotNull(sindex.get(88));
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ assertDbExists
+ (true, env,
+ DeletedEntity4_AnnotRemoved_WithDeleter.class.getName());
+ assertDbExists
+ (true, env,
+ DeletedEntity4_AnnotRemoved_WithDeleter.class.getName(),
+ "skey");
+ }
+ }
+
+ @Entity
+ static class DeletedEntity5_EntityToPersist_NoMutation extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int skey = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeletedEntity5_EntityToPersist_NoMutation>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeletedEntity5_EntityToPersist_NoMutation.class);
+ index.put(this);
+
+ SecondaryIndex<Integer,Integer,
+ DeletedEntity5_EntityToPersist_NoMutation>
+ sindex = store.getSecondaryIndex(index, Integer.class, "skey");
+ TestCase.assertNotNull(sindex.get(88));
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ assertDbExists
+ (true, env,
+ DeletedEntity5_EntityToPersist_NoMutation.class.getName());
+ assertDbExists
+ (true, env,
+ DeletedEntity5_EntityToPersist_NoMutation.class.getName(),
+ "skey");
+ }
+ }
+
+ @Entity
+ static class DeletedEntity6_EntityToPersist_WithDeleter extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int skey = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeletedEntity6_EntityToPersist_WithDeleter>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeletedEntity6_EntityToPersist_WithDeleter.class);
+ index.put(this);
+
+ SecondaryIndex<Integer,Integer,
+ DeletedEntity6_EntityToPersist_WithDeleter>
+ sindex = store.getSecondaryIndex(index, Integer.class, "skey");
+ TestCase.assertNotNull(sindex.get(88));
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ assertDbExists
+ (true, env,
+ DeletedEntity6_EntityToPersist_WithDeleter.class.getName());
+ assertDbExists
+ (true, env,
+ DeletedEntity6_EntityToPersist_WithDeleter.class.getName(),
+ "skey");
+ }
+ }
+
+ @Persistent
+ static class DeletedPersist1_ClassRemoved {
+
+ int f = 123;
+ }
+
+ @Entity
+ static class DeletedPersist1_ClassRemoved_NoMutation extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ DeletedPersist1_ClassRemoved embed =
+ new DeletedPersist1_ClassRemoved();
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeletedPersist1_ClassRemoved_NoMutation>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeletedPersist1_ClassRemoved_NoMutation.class);
+ index.put(this);
+ }
+ }
+
+ @Persistent
+ static class DeletedPersist2_ClassRemoved {
+
+ int f = 123;
+ }
+
+ @Entity
+ static class DeletedPersist2_ClassRemoved_WithDeleter extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ DeletedPersist2_ClassRemoved embed =
+ new DeletedPersist2_ClassRemoved();
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeletedPersist2_ClassRemoved_WithDeleter>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeletedPersist2_ClassRemoved_WithDeleter.class);
+ index.put(this);
+ }
+ }
+
+ @Persistent
+ static class DeletedPersist3_AnnotRemoved {
+
+ int f = 123;
+ }
+
+ @Entity
+ static class DeletedPersist3_AnnotRemoved_NoMutation extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ DeletedPersist3_AnnotRemoved embed =
+ new DeletedPersist3_AnnotRemoved();
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeletedPersist3_AnnotRemoved_NoMutation>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeletedPersist3_AnnotRemoved_NoMutation.class);
+ index.put(this);
+ }
+ }
+
+ @Persistent
+ static class DeletedPersist4_AnnotRemoved {
+
+ int f = 123;
+ }
+
+ @Entity
+ static class DeletedPersist4_AnnotRemoved_WithDeleter extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ DeletedPersist4_AnnotRemoved embed =
+ new DeletedPersist4_AnnotRemoved();
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeletedPersist4_AnnotRemoved_WithDeleter>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeletedPersist4_AnnotRemoved_WithDeleter.class);
+ index.put(this);
+ }
+ }
+
+ @Persistent
+ static class DeletedPersist5_PersistToEntity {
+
+ int f = 123;
+ }
+
+ @Entity
+ static class DeletedPersist5_PersistToEntity_NoMutation
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ DeletedPersist5_PersistToEntity embed =
+ new DeletedPersist5_PersistToEntity();
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeletedPersist5_PersistToEntity_NoMutation>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeletedPersist5_PersistToEntity_NoMutation.class);
+ index.put(this);
+ }
+ }
+
+ @Persistent
+ static class DeletedPersist6_PersistToEntity {
+
+ int f = 123;
+ }
+
+ @Entity
+ static class DeletedPersist6_PersistToEntity_WithDeleter
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ DeletedPersist6_PersistToEntity embed =
+ new DeletedPersist6_PersistToEntity();
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeletedPersist6_PersistToEntity_WithDeleter>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeletedPersist6_PersistToEntity_WithDeleter.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class RenamedEntity1_NewEntityName
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int skey = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,RenamedEntity1_NewEntityName>
+ index = store.getPrimaryIndex
+ (Integer.class, RenamedEntity1_NewEntityName.class);
+ index.put(this);
+
+ SecondaryIndex<Integer,Integer,RenamedEntity1_NewEntityName>
+ sindex = store.getSecondaryIndex(index, Integer.class, "skey");
+ TestCase.assertNotNull(sindex.get(88));
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ assertDbExists
+ (true, env,
+ RenamedEntity1_NewEntityName.class.getName());
+ assertDbExists
+ (true, env,
+ RenamedEntity1_NewEntityName.class.getName(), "skey");
+ }
+ }
+
+ @Entity
+ static class RenamedEntity2_NewEntityName
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int skey = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,RenamedEntity2_NewEntityName>
+ index = store.getPrimaryIndex
+ (Integer.class, RenamedEntity2_NewEntityName.class);
+ index.put(this);
+
+ SecondaryIndex<Integer,Integer,RenamedEntity2_NewEntityName>
+ sindex = store.getSecondaryIndex(index, Integer.class, "skey");
+ TestCase.assertNotNull(sindex.get(88));
+ }
+
+ @Override
+ void checkUnevolvedModel(EntityModel model, Environment env) {
+ assertDbExists
+ (true, env,
+ RenamedEntity2_NewEntityName.class.getName());
+ assertDbExists
+ (true, env,
+ RenamedEntity2_NewEntityName.class.getName(), "skey");
+ }
+ }
+
+ @Persistent
+ static class DeleteSuperclass1_BaseClass
+ extends EvolveCase {
+
+ int f = 123;
+ }
+
+ @Entity
+ static class DeleteSuperclass1_NoMutation
+ extends DeleteSuperclass1_BaseClass {
+
+ @PrimaryKey
+ int key = 99;
+
+ int ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeleteSuperclass1_NoMutation>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeleteSuperclass1_NoMutation.class);
+ index.put(this);
+ }
+ }
+
+ @Persistent
+ static class DeleteSuperclass2_BaseClass
+ extends EvolveCase {
+
+ int f = 123;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int skey = 456;
+ }
+
+ @Entity
+ static class DeleteSuperclass2_WithConverter
+ extends DeleteSuperclass2_BaseClass {
+
+ @PrimaryKey
+ int key = 99;
+
+ int ff = 88;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int skey2 = 77;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ Integer skey3 = 66;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeleteSuperclass2_WithConverter>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeleteSuperclass2_WithConverter.class);
+ index.put(this);
+ }
+ }
+
+ @Persistent
+ static class DeleteSuperclass3_BaseClass
+ extends EvolveCase {
+
+ int f = 123;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int skey = 456;
+ }
+
+ @Entity
+ static class DeleteSuperclass3_WithDeleter
+ extends DeleteSuperclass3_BaseClass {
+
+ @PrimaryKey
+ int key = 99;
+
+ int ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeleteSuperclass3_WithDeleter>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeleteSuperclass3_WithDeleter.class);
+ index.put(this);
+ }
+ }
+
+ @Persistent
+ static class DeleteSuperclass4_BaseClass
+ extends EvolveCase {
+ }
+
+ @Entity
+ static class DeleteSuperclass4_NoFields
+ extends DeleteSuperclass4_BaseClass {
+
+ @PrimaryKey
+ int key = 99;
+
+ int ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeleteSuperclass4_NoFields>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeleteSuperclass4_NoFields.class);
+ index.put(this);
+ }
+ }
+
+ @Persistent
+ static class DeleteSuperclass5_Embedded_Base {
+
+ int g = 456;
+ }
+
+ @Persistent
+ static class DeleteSuperclass5_Embedded
+ extends DeleteSuperclass5_Embedded_Base {
+
+ int f = 123;
+ }
+
+ @Entity
+ static class DeleteSuperclass5_Top
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ int ff = 88;
+
+ DeleteSuperclass5_Embedded embed =
+ new DeleteSuperclass5_Embedded();
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeleteSuperclass5_Top>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DeleteSuperclass5_Top.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class InsertSuperclass1_Between
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ int ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,InsertSuperclass1_Between>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ InsertSuperclass1_Between.class);
+ index.put(this);
+ }
+ }
+
+ @Persistent
+ static class InsertSuperclass2_Embedded {
+
+ int f = 123;
+ }
+
+ @Entity
+ static class InsertSuperclass2_Top
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ int ff = 88;
+
+ InsertSuperclass2_Embedded embed =
+ new InsertSuperclass2_Embedded();
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,InsertSuperclass2_Top>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ InsertSuperclass2_Top.class);
+ index.put(this);
+ }
+ }
+
+ /*
+ @Persistent
+ static class RenameFields1_Base
+ extends EvolveCase {
+
+ int f = 123;
+ }
+
+ @Entity
+ static class RenameFields1
+ extends RenameFields1_Base {
+
+ @PrimaryKey
+ int key = 99;
+
+ int ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,RenameFields1>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ RenameFields1.class);
+ index.put(this);
+ }
+ }
+ */
+
+ @Entity
+ static class DisallowNonKeyField_PrimitiveToObject
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ int ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowNonKeyField_PrimitiveToObject>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowNonKeyField_PrimitiveToObject.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowNonKeyField_ObjectToPrimitive
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ String ff = "88";
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowNonKeyField_ObjectToPrimitive>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowNonKeyField_ObjectToPrimitive.class);
+ index.put(this);
+ }
+ }
+
+ @Persistent
+ static class MyType {
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof MyType;
+ }
+ }
+
+ @Persistent
+ static class MySubtype extends MyType {
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof MySubtype;
+ }
+ }
+
+ @Entity
+ static class DisallowNonKeyField_ObjectToSubtype
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ MyType ff = new MyType();
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowNonKeyField_ObjectToSubtype>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowNonKeyField_ObjectToSubtype.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowNonKeyField_ObjectToUnrelatedSimple
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ Integer ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowNonKeyField_ObjectToUnrelatedSimple>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowNonKeyField_ObjectToUnrelatedSimple.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowNonKeyField_ObjectToUnrelatedOther
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ Integer ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowNonKeyField_ObjectToUnrelatedOther>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowNonKeyField_ObjectToUnrelatedOther.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowNonKeyField_byte2boolean
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ byte ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowNonKeyField_byte2boolean>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowNonKeyField_byte2boolean.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowNonKeyField_short2byte
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ short ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowNonKeyField_short2byte>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowNonKeyField_short2byte.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowNonKeyField_int2short
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ int ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowNonKeyField_int2short>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowNonKeyField_int2short.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowNonKeyField_long2int
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ long ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowNonKeyField_long2int>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowNonKeyField_long2int.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowNonKeyField_float2long
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ float ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowNonKeyField_float2long>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowNonKeyField_float2long.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowNonKeyField_double2float
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ double ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowNonKeyField_double2float>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowNonKeyField_double2float.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowNonKeyField_Byte2byte
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ Byte ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowNonKeyField_Byte2byte>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowNonKeyField_Byte2byte.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowNonKeyField_Character2char
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ Character ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowNonKeyField_Character2char>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowNonKeyField_Character2char.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowNonKeyField_Short2short
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ Short ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowNonKeyField_Short2short>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowNonKeyField_Short2short.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowNonKeyField_Integer2int
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ Integer ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowNonKeyField_Integer2int>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowNonKeyField_Integer2int.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowNonKeyField_Long2long
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ Long ff = 88L;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowNonKeyField_Long2long>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowNonKeyField_Long2long.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowNonKeyField_Float2float
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ Float ff = 88F;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowNonKeyField_Float2float>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowNonKeyField_Float2float.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowNonKeyField_Double2double
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ Double ff = 88D;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowNonKeyField_Double2double>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowNonKeyField_Double2double.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowNonKeyField_float2BigInt
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ float ff = 88F;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowNonKeyField_float2BigInt>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowNonKeyField_float2BigInt.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowNonKeyField_BigInt2long
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ BigInteger ff = BigInteger.valueOf(88);
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowNonKeyField_BigInt2long>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowNonKeyField_BigInt2long.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowSecKeyField_byte2short
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ byte ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowSecKeyField_byte2short>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowSecKeyField_byte2short.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowSecKeyField_char2int
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ char ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowSecKeyField_char2int>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowSecKeyField_char2int.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowSecKeyField_short2int
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ short ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowSecKeyField_short2int>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowSecKeyField_short2int.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowSecKeyField_int2long
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowSecKeyField_int2long>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowSecKeyField_int2long.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowSecKeyField_long2float
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ long ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowSecKeyField_long2float>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowSecKeyField_long2float.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowSecKeyField_float2double
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ float ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowSecKeyField_float2double>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowSecKeyField_float2double.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowSecKeyField_Byte2short2
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ Byte ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowSecKeyField_Byte2short2>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowSecKeyField_Byte2short2.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowSecKeyField_Character2int
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ Character ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowSecKeyField_Character2int>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowSecKeyField_Character2int.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowSecKeyField_Short2int2
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ Short ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowSecKeyField_Short2int2>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowSecKeyField_Short2int2.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowSecKeyField_Integer2long
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ Integer ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowSecKeyField_Integer2long>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowSecKeyField_Integer2long.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowSecKeyField_Long2float2
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ Long ff = 88L;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowSecKeyField_Long2float2>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowSecKeyField_Long2float2.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowSecKeyField_Float2double2
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ Float ff = 88F;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowSecKeyField_Float2double2>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowSecKeyField_Float2double2.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowSecKeyField_int2BigInt
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int ff = 88;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowSecKeyField_int2BigInt>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowSecKeyField_int2BigInt.class);
+ index.put(this);
+ }
+ }
+
+ // --
+
+ @Entity
+ static class DisallowPriKeyField_byte2short
+ extends EvolveCase {
+
+ @PrimaryKey
+ byte key = 99;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Byte,DisallowPriKeyField_byte2short>
+ index = store.getPrimaryIndex
+ (Byte.class,
+ DisallowPriKeyField_byte2short.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowPriKeyField_char2int
+ extends EvolveCase {
+
+ @PrimaryKey
+ char key = 99;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Character,DisallowPriKeyField_char2int>
+ index = store.getPrimaryIndex
+ (Character.class,
+ DisallowPriKeyField_char2int.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowPriKeyField_short2int
+ extends EvolveCase {
+
+ @PrimaryKey
+ short key = 99;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Short,DisallowPriKeyField_short2int>
+ index = store.getPrimaryIndex
+ (Short.class,
+ DisallowPriKeyField_short2int.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowPriKeyField_int2long
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key = 99;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowPriKeyField_int2long>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowPriKeyField_int2long.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowPriKeyField_long2float
+ extends EvolveCase {
+
+ @PrimaryKey
+ long key = 99;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Long,DisallowPriKeyField_long2float>
+ index = store.getPrimaryIndex
+ (Long.class,
+ DisallowPriKeyField_long2float.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowPriKeyField_float2double
+ extends EvolveCase {
+
+ @PrimaryKey
+ float key = 99;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Float,DisallowPriKeyField_float2double>
+ index = store.getPrimaryIndex
+ (Float.class,
+ DisallowPriKeyField_float2double.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowPriKeyField_Byte2short2
+ extends EvolveCase {
+
+ @PrimaryKey
+ Byte key = 99;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Byte,DisallowPriKeyField_Byte2short2>
+ index = store.getPrimaryIndex
+ (Byte.class,
+ DisallowPriKeyField_Byte2short2.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowPriKeyField_Character2int
+ extends EvolveCase {
+
+ @PrimaryKey
+ Character key = 99;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Character,DisallowPriKeyField_Character2int>
+ index = store.getPrimaryIndex
+ (Character.class,
+ DisallowPriKeyField_Character2int.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowPriKeyField_Short2int2
+ extends EvolveCase {
+
+ @PrimaryKey
+ Short key = 99;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Short,DisallowPriKeyField_Short2int2>
+ index = store.getPrimaryIndex
+ (Short.class,
+ DisallowPriKeyField_Short2int2.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowPriKeyField_Integer2long
+ extends EvolveCase {
+
+ @PrimaryKey
+ Integer key = 99;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowPriKeyField_Integer2long>
+ index = store.getPrimaryIndex
+ (Integer.class,
+ DisallowPriKeyField_Integer2long.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowPriKeyField_Long2float2
+ extends EvolveCase {
+
+ @PrimaryKey
+ Long key = 99L;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Long,DisallowPriKeyField_Long2float2>
+ index = store.getPrimaryIndex
+ (Long.class,
+ DisallowPriKeyField_Long2float2.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowPriKeyField_Float2double2
+ extends EvolveCase {
+
+ @PrimaryKey
+ Float key = 99F;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Float,DisallowPriKeyField_Float2double2>
+ index = store.getPrimaryIndex
+ (Float.class,
+ DisallowPriKeyField_Float2double2.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class DisallowPriKeyField_Long2BigInt
+ extends EvolveCase {
+
+ @PrimaryKey
+ Long key = 99L;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Long,DisallowPriKeyField_Long2BigInt>
+ index = store.getPrimaryIndex
+ (Long.class,
+ DisallowPriKeyField_Long2BigInt.class);
+ index.put(this);
+ }
+ }
+
+ @Persistent
+ static class DisallowCompositeKeyField_byte2short_Key {
+
+ @KeyField(1)
+ int f1 = 1;
+
+ @KeyField(2)
+ byte f2 = 2;
+
+ @KeyField(3)
+ String f3 = "3";
+ }
+
+ @Entity
+ static class DisallowCompositeKeyField_byte2short
+ extends EvolveCase {
+
+ @PrimaryKey
+ DisallowCompositeKeyField_byte2short_Key key =
+ new DisallowCompositeKeyField_byte2short_Key();
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<DisallowCompositeKeyField_byte2short_Key,
+ DisallowCompositeKeyField_byte2short>
+ index = store.getPrimaryIndex
+ (DisallowCompositeKeyField_byte2short_Key.class,
+ DisallowCompositeKeyField_byte2short.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class AllowPriKeyField_byte2Byte
+ extends EvolveCase {
+
+ @PrimaryKey
+ byte key = 99;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Byte,AllowPriKeyField_byte2Byte>
+ index = store.getPrimaryIndex
+ (Byte.class, AllowPriKeyField_byte2Byte.class);
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class AllowPriKeyField_Byte2byte2
+ extends EvolveCase {
+
+ @PrimaryKey
+ Byte key = 99;
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Byte,AllowPriKeyField_Byte2byte2>
+ index = store.getPrimaryIndex
+ (Byte.class, AllowPriKeyField_Byte2byte2.class);
+ index.put(this);
+ }
+ }
+
+ @Persistent
+ static class AllowFieldTypeChanges_Key {
+
+ AllowFieldTypeChanges_Key() {
+ this(false);
+ }
+
+ AllowFieldTypeChanges_Key(boolean init) {
+ if (init) {
+ f1 = true;
+ f2 = (byte) 2;
+ f3 = (short) 3;
+ f4 = 4;
+ f5 = 5L;
+ f6 = 6F;
+ f7 = 7D;
+ f8 = (char) 8;
+ f9 = true;
+ f10 = (byte) 10;
+ f11 = (short) 11;
+ f12 = 12;
+ f13 = 13L;
+ f14 = 14F;
+ f15 = 15D;
+ f16 = (char) 16;
+ }
+ }
+
+ @KeyField(1)
+ boolean f1;
+
+ @KeyField(2)
+ byte f2;
+
+ @KeyField(3)
+ short f3;
+
+ @KeyField(4)
+ int f4;
+
+ @KeyField(5)
+ long f5;
+
+ @KeyField(6)
+ float f6;
+
+ @KeyField(7)
+ double f7;
+
+ @KeyField(8)
+ char f8;
+
+ @KeyField(9)
+ Boolean f9;
+
+ @KeyField(10)
+ Byte f10;
+
+ @KeyField(11)
+ Short f11;
+
+ @KeyField(12)
+ Integer f12;
+
+ @KeyField(13)
+ Long f13;
+
+ @KeyField(14)
+ Float f14;
+
+ @KeyField(15)
+ Double f15;
+
+ @KeyField(16)
+ Character f16;
+ }
+
+ @Persistent
+ static class AllowFieldTypeChanges_Base
+ extends EvolveCase {
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ AllowFieldTypeChanges_Key kcomposite =
+ new AllowFieldTypeChanges_Key(true);
+
+ long f_long2Integer = 111;
+ String f_String2Long = "222";
+ }
+
+ @Entity
+ static class AllowFieldTypeChanges
+ extends AllowFieldTypeChanges_Base {
+
+ @PrimaryKey
+ int pkeyint = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ boolean kboolean = true;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ byte kbyte = 77;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ short kshort = 66;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int kint = 55;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ long klong = 44;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ float kfloat = 33;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ double kdouble = 22;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ char kchar = 11;
+
+ byte f01;
+ byte f02;
+ byte f03;
+ byte f04;
+ byte f06;
+ short f07;
+ short f08;
+ short f09;
+ short f10;
+ char f11;
+ char f12;
+ char f13;
+ char f14;
+ int f15;
+ int f16;
+ int f17;
+ long f18;
+ long f19;
+ float f20;
+
+ byte f21;
+ byte f22;
+ byte f23;
+ byte f24;
+ byte f26;
+ short f27;
+ short f28;
+ short f29;
+ short f30;
+ char f31;
+ char f32;
+ char f33;
+ char f34;
+ int f35;
+ int f36;
+ int f37;
+ long f38;
+ long f39;
+ float f40;
+
+ Byte f41;
+ Byte f42;
+ Byte f43;
+ Byte f44;
+ Byte f46;
+ Short f47;
+ Short f48;
+ Short f49;
+ Short f50;
+ Character f51;
+ Character f52;
+ Character f53;
+ Character f54;
+ Integer f55;
+ Integer f56;
+ Integer f57;
+ Long f58;
+ Long f59;
+ Float f60;
+
+ byte f70;
+ short f71;
+ char f72;
+ int f73;
+ long f74;
+ Byte f75;
+ Short f76;
+ Character f77;
+ Integer f78;
+ Long f79;
+
+ long f_long2int = 333;
+ String f_String2long = "444";
+
+ private void init() {
+ f01 = (byte) 1;
+ f02 = (byte) 2;
+ f03 = (byte) 3;
+ f04 = (byte) 4;
+ f06 = (byte) 6;
+ f07 = (short) 7;
+ f08 = (short) 8;
+ f09 = (short) 9;
+ f10 = (short) 10;
+ f11 = (char) 11;
+ f12 = (char) 12;
+ f13 = (char) 13;
+ f14 = (char) 14;
+ f15 = 15;
+ f16 = 16;
+ f17 = 17;
+ f18 = (long) 18;
+ f19 = (long) 19;
+ f20 = (float) 20;
+
+ f21 = (byte) 21;
+ f22 = (byte) 22;
+ f23 = (byte) 23;
+ f24 = (byte) 24;
+ f26 = (byte) 26;
+ f27 = (short) 27;
+ f28 = (short) 28;
+ f29 = (short) 29;
+ f30 = (short) 30;
+ f31 = (char) 31;
+ f32 = (char) 32;
+ f33 = (char) 33;
+ f34 = (char) 34;
+ f35 = 35;
+ f36 = 36;
+ f37 = 37;
+ f38 = (long) 38;
+ f39 = (long) 39;
+ f40 = (float) 40;
+
+ f41 = (byte) 41;
+ f42 = (byte) 42;
+ f43 = (byte) 43;
+ f44 = (byte) 44;
+ f46 = (byte) 46;
+ f47 = (short) 47;
+ f48 = (short) 48;
+ f49 = (short) 49;
+ f50 = (short) 50;
+ f51 = (char) 51;
+ f52 = (char) 52;
+ f53 = (char) 53;
+ f54 = (char) 54;
+ f55 = 55;
+ f56 = 56;
+ f57 = 57;
+ f58 = (long) 58;
+ f59 = (long) 59;
+ f60 = (float) 60;
+
+ f70 = (byte) 70;
+ f71 = (short) 71;
+ f72 = (char) 72;
+ f73 = 73;
+ f74 = (long) 74;
+ f75 = (byte) 75;
+ f76 = (short) 76;
+ f77 = (char) 77;
+ f78 = 78;
+ f79 = (long) 79;
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,AllowFieldTypeChanges>
+ index = store.getPrimaryIndex
+ (Integer.class, AllowFieldTypeChanges.class);
+ init();
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class ConvertFieldContent_Entity
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+
+ String f1;
+ String f2;
+
+ private void init() {
+ key = 99;
+ f1 = "01234";
+ f2 = "56789";
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ConvertFieldContent_Entity>
+ index = store.getPrimaryIndex
+ (Integer.class, ConvertFieldContent_Entity.class);
+ init();
+ index.put(this);
+ }
+ }
+
+ @Persistent
+ static class ConvertExample1_Address {
+ String street;
+ String city;
+ String state;
+ String zipCode;
+ }
+
+ @Entity
+ static class ConvertExample1_Entity
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+
+ ConvertExample1_Address embed;
+
+ private void init() {
+ key = 99;
+ embed = new ConvertExample1_Address();
+ embed.street = "street";
+ embed.city = "city";
+ embed.state = "state";
+ embed.zipCode = "12345";
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ConvertExample1_Entity>
+ index = store.getPrimaryIndex
+ (Integer.class, ConvertExample1_Entity.class);
+ init();
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class ConvertExample2_Person
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+
+ String address;
+
+ private void init() {
+ key = 99;
+ address = "street#city#state#12345";
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ConvertExample2_Person>
+ index = store.getPrimaryIndex
+ (Integer.class, ConvertExample2_Person.class);
+ init();
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class ConvertExample3_Person
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+
+ String street;
+ String city;
+ String state;
+ int zipCode;
+
+ private void init() {
+ key = 99;
+ street = "street";
+ city = "city";
+ state = "state";
+ zipCode = 12345;
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ConvertExample3_Person>
+ index = store.getPrimaryIndex
+ (Integer.class, ConvertExample3_Person.class);
+ init();
+ index.put(this);
+ }
+ }
+
+ @Persistent
+ static class ConvertExample3Reverse_Address {
+ String street;
+ String city;
+ String state;
+ int zipCode;
+ }
+
+ @Entity
+ static class ConvertExample3Reverse_Person
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+
+ ConvertExample3Reverse_Address address;
+
+ private void init() {
+ key = 99;
+ address = new ConvertExample3Reverse_Address();
+ address.street = "street";
+ address.city = "city";
+ address.state = "state";
+ address.zipCode = 12345;
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ConvertExample3Reverse_Person>
+ index = store.getPrimaryIndex
+ (Integer.class, ConvertExample3Reverse_Person.class);
+ init();
+ index.put(this);
+ }
+ }
+
+ @Persistent
+ static class ConvertExample4_A extends ConvertExample4_B {
+ String name;
+ }
+
+ @Persistent
+ static class ConvertExample4_B {
+ }
+
+ @Entity
+ static class ConvertExample4_Entity
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+
+ ConvertExample4_A embed;
+
+ private void init() {
+ key = 99;
+ embed = new ConvertExample4_A();
+ embed.name = "name";
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ConvertExample4_Entity>
+ index = store.getPrimaryIndex
+ (Integer.class, ConvertExample4_Entity.class);
+ init();
+ index.put(this);
+ }
+ }
+
+ @Persistent
+ static class ConvertExample5_Pet {
+ String name;
+ boolean isCatNotDog;
+ int finickyLevel;
+ double barkVolume;
+ }
+
+ @Entity
+ static class ConvertExample5_Entity
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+
+ ConvertExample5_Pet cat;
+ ConvertExample5_Pet dog;
+
+ private void init() {
+ key = 99;
+ cat = new ConvertExample5_Pet();
+ cat.name = "Jeffry";
+ cat.isCatNotDog = true;
+ cat.finickyLevel = 999;
+ dog = new ConvertExample5_Pet();
+ dog.name = "Nelson";
+ dog.isCatNotDog = false;
+ dog.barkVolume = 0.01;
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ConvertExample5_Entity>
+ index = store.getPrimaryIndex
+ (Integer.class, ConvertExample5_Entity.class);
+ init();
+ index.put(this);
+ }
+ }
+
+ @Persistent
+ static class AllowFieldAddDelete_Embed {
+ private int f1 = 1;
+ private String f2 = "2";
+ private String f4 = "4";
+ private int f6 = 6;
+ private String f7 = "7";
+ }
+
+ @Persistent
+ static class AllowFieldAddDelete_Base
+ extends EvolveCase {
+
+ private int f1 = 1;
+ private String f2 = "2";
+ private String f4 = "4";
+ private int f6 = 6;
+ private String f7 = "7";
+ }
+
+ @Entity
+ static class AllowFieldAddDelete
+ extends AllowFieldAddDelete_Base {
+
+ @PrimaryKey
+ int key;
+
+ AllowFieldAddDelete_Embed embed;
+
+ private int f1 = 1;
+ private String f2 = "2";
+ private String f4 = "4";
+ private int f6 = 6;
+ private String f7 = "7";
+
+ private void init() {
+ key = 99;
+ embed = new AllowFieldAddDelete_Embed();
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,AllowFieldAddDelete>
+ index = store.getPrimaryIndex
+ (Integer.class, AllowFieldAddDelete.class);
+ init();
+ index.put(this);
+ }
+ }
+
+ static class ProxiedClass {
+ int data;
+
+ ProxiedClass(int data) {
+ this.data = data;
+ }
+ }
+
+ @Persistent(proxyFor=ProxiedClass.class)
+ static class ProxiedClass_Proxy implements PersistentProxy<ProxiedClass> {
+ int data;
+
+ public void initializeProxy(ProxiedClass o) {
+ data = o.data;
+ }
+
+ public ProxiedClass convertProxy() {
+ return new ProxiedClass(data);
+ }
+ }
+
+ @Entity
+ static class ProxiedClass_Entity
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+
+ ProxiedClass embed;
+
+ private void init() {
+ key = 99;
+ embed = new ProxiedClass(88);
+ }
+
+ @Override
+ void configure(EntityModel model, StoreConfig config) {
+ model.registerClass(ProxiedClass_Proxy.class);
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ProxiedClass_Entity>
+ index = store.getPrimaryIndex
+ (Integer.class, ProxiedClass_Entity.class);
+ init();
+ index.put(this);
+ }
+ }
+
+ @Persistent(proxyFor=StringBuffer.class)
+ static class DisallowChangeProxyFor_Proxy
+ implements PersistentProxy<StringBuffer> {
+
+ String data;
+
+ public void initializeProxy(StringBuffer o) {
+ data = o.toString();
+ }
+
+ public StringBuffer convertProxy() {
+ return new StringBuffer(data);
+ }
+ }
+
+ @Entity
+ static class DisallowChangeProxyFor
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+
+ private void init() {
+ key = 99;
+ }
+
+ @Override
+ void configure(EntityModel model, StoreConfig config) {
+ model.registerClass(DisallowChangeProxyFor_Proxy.class);
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowChangeProxyFor>
+ index = store.getPrimaryIndex
+ (Integer.class, DisallowChangeProxyFor.class);
+ init();
+ index.put(this);
+ }
+ }
+
+ @Persistent(proxyFor=StringBuffer.class)
+ static class DisallowDeleteProxyFor_Proxy
+ implements PersistentProxy<StringBuffer> {
+
+ String data;
+
+ public void initializeProxy(StringBuffer o) {
+ data = o.toString();
+ }
+
+ public StringBuffer convertProxy() {
+ return new StringBuffer(data);
+ }
+ }
+
+ @Entity
+ static class DisallowDeleteProxyFor
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+
+ private void init() {
+ key = 99;
+ }
+
+ @Override
+ void configure(EntityModel model, StoreConfig config) {
+ model.registerClass(DisallowDeleteProxyFor_Proxy.class);
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowDeleteProxyFor>
+ index = store.getPrimaryIndex
+ (Integer.class, DisallowDeleteProxyFor.class);
+ init();
+ index.put(this);
+ }
+ }
+
+ @Persistent
+ static class ArrayNameChange_Component {
+
+ int data;
+ }
+
+ @Entity
+ static class ArrayNameChange_Entity
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+
+ ArrayNameChange_Component[] embed;
+ ArrayNameChange_Component embed2;
+
+ private void init() {
+ key = 99;
+ embed2 = new ArrayNameChange_Component();
+ embed2.data = 88;
+ embed = new ArrayNameChange_Component[] { embed2 };
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,ArrayNameChange_Entity>
+ index = store.getPrimaryIndex
+ (Integer.class, ArrayNameChange_Entity.class);
+ init();
+ index.put(this);
+ }
+ }
+
+ enum AddEnumConstant_Enum {
+ A, B;
+ }
+
+ @Entity
+ static class AddEnumConstant_Entity
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+
+ AddEnumConstant_Enum e1;
+ AddEnumConstant_Enum e2;
+
+ private void init() {
+ key = 99;
+ e1 = AddEnumConstant_Enum.A;
+ e2 = AddEnumConstant_Enum.B;
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,AddEnumConstant_Entity>
+ index = store.getPrimaryIndex
+ (Integer.class, AddEnumConstant_Entity.class);
+ init();
+ index.put(this);
+ }
+ }
+
+ enum InsertEnumConstant_Enum {
+ A, B;
+ }
+
+ @Persistent
+ static class InsertEnumConstant_KeyClass
+ implements Comparable<InsertEnumConstant_KeyClass > {
+
+ @KeyField(1)
+ InsertEnumConstant_Enum key;
+
+ private InsertEnumConstant_KeyClass() {}
+
+ InsertEnumConstant_KeyClass(InsertEnumConstant_Enum key) {
+ this.key = key;
+ }
+
+ public int compareTo(InsertEnumConstant_KeyClass o) {
+ /* Use the natural order, in spite of insertions. */
+ return key.compareTo(o.key);
+ }
+ }
+
+ @Entity
+ static class InsertEnumConstant_Entity
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ InsertEnumConstant_KeyClass secKey;
+
+ InsertEnumConstant_Enum e1;
+ InsertEnumConstant_Enum e2;
+
+ private void init() {
+ key = 99;
+ secKey =
+ new InsertEnumConstant_KeyClass(InsertEnumConstant_Enum.A);
+ e1 = InsertEnumConstant_Enum.A;
+ e2 = InsertEnumConstant_Enum.B;
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,InsertEnumConstant_Entity>
+ index = store.getPrimaryIndex
+ (Integer.class, InsertEnumConstant_Entity.class);
+ init();
+ index.put(this);
+ }
+ }
+
+ enum DeleteEnumConstant_Enum {
+ A, B, C;
+ }
+
+ @Entity
+ static class DeleteEnumConstant_NoMutation
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+
+ DeleteEnumConstant_Enum e1;
+ DeleteEnumConstant_Enum e2;
+ DeleteEnumConstant_Enum e3;
+
+ private void init() {
+ key = 99;
+ e1 = DeleteEnumConstant_Enum.A;
+ e2 = DeleteEnumConstant_Enum.B;
+ e3 = DeleteEnumConstant_Enum.C;
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeleteEnumConstant_NoMutation>
+ index = store.getPrimaryIndex
+ (Integer.class, DeleteEnumConstant_NoMutation.class);
+ init();
+ index.put(this);
+ }
+ }
+
+ /* Disabled until support for enum deletion is added.
+ @Entity
+ static class DeleteEnumConstant_WithConverter
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+
+ DeleteEnumConstant_Enum e1;
+ DeleteEnumConstant_Enum e2;
+ DeleteEnumConstant_Enum e3;
+
+ private void init() {
+ key = 99;
+ e1 = DeleteEnumConstant_Enum.A;
+ e2 = DeleteEnumConstant_Enum.B;
+ e3 = DeleteEnumConstant_Enum.C;
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DeleteEnumConstant_WithConverter>
+ index = store.getPrimaryIndex
+ (Integer.class, DeleteEnumConstant_WithConverter.class);
+ init();
+ index.put(this);
+ }
+ }
+ */
+
+ @Entity
+ static class DisallowChangeKeyRelate
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int skey;
+
+ private void init() {
+ key = 99;
+ skey = 88;
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,DisallowChangeKeyRelate>
+ index = store.getPrimaryIndex
+ (Integer.class, DisallowChangeKeyRelate.class);
+ init();
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class AllowChangeKeyMetadata
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+
+ int aa;
+
+ int addAnnotation;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int dropField;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int dropAnnotation;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int toBeRenamedField;
+
+ int ff;
+
+ private void init() {
+ key = 99;
+ addAnnotation = 88;
+ dropField = 77;
+ dropAnnotation = 66;
+ toBeRenamedField = 44;
+ aa = 33;
+ ff = 22;
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,AllowChangeKeyMetadata>
+ index = store.getPrimaryIndex
+ (Integer.class, AllowChangeKeyMetadata.class);
+ init();
+ index.put(this);
+ }
+ }
+
+ /** [#16253] */
+ @Persistent
+ static class AllowChangeKeyMetadataInSubclass
+ extends AllowChangeKeyMetadataEntity {
+
+ int aa;
+
+ int addAnnotation;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int dropField;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int dropAnnotation;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ int toBeRenamedField;
+
+ int ff;
+
+ private void init() {
+ key = 99;
+ addAnnotation = 88;
+ dropField = 77;
+ dropAnnotation = 66;
+ toBeRenamedField = 44;
+ aa = 33;
+ ff = 22;
+ }
+
+ @Override
+ void configure(EntityModel model, StoreConfig config) {
+ model.registerClass(AllowChangeKeyMetadataInSubclass.class);
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,AllowChangeKeyMetadataEntity>
+ index = store.getPrimaryIndex
+ (Integer.class, AllowChangeKeyMetadataEntity.class);
+ init();
+ index.put(this);
+ }
+ }
+
+ @Entity
+ static class AllowChangeKeyMetadataEntity
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+ }
+
+ /** [#15524] */
+ @Entity
+ static class AllowAddSecondary
+ extends EvolveCase {
+
+ @PrimaryKey
+ long key;
+
+ int a;
+ int b;
+
+ private void init() {
+ key = 99;
+ a = 1;
+ b = 2;
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Long,AllowAddSecondary>
+ index = store.getPrimaryIndex
+ (Long.class, AllowAddSecondary.class);
+ init();
+ index.put(this);
+ }
+ }
+
+ /** [#15797] */
+ @Entity
+ static class FieldAddAndConvert
+ extends EvolveCase {
+
+ @PrimaryKey
+ int key;
+
+ private int f1 = 1;
+ private int f3 = 3;
+
+ private void init() {
+ key = 99;
+ }
+
+ @Override
+ void writeObjects(EntityStore store)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,FieldAddAndConvert>
+ index = store.getPrimaryIndex
+ (Integer.class, FieldAddAndConvert.class);
+ init();
+ index.put(this);
+ }
+ }
+}
diff --git a/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveTest.java b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveTest.java
new file mode 100644
index 0000000..c76a63a
--- /dev/null
+++ b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveTest.java
@@ -0,0 +1,255 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+package com.sleepycat.persist.test;
+
+import java.io.IOException;
+
+import junit.framework.Test;
+
+import com.sleepycat.persist.evolve.EvolveConfig;
+import com.sleepycat.persist.evolve.EvolveEvent;
+import com.sleepycat.persist.evolve.EvolveListener;
+import com.sleepycat.persist.evolve.EvolveStats;
+import com.sleepycat.persist.impl.PersistCatalog;
+import com.sleepycat.util.test.SharedTestUtils;
+
+/**
+ * Runs part two of the EvolveTest. This part is run with the new/updated
+ * version of EvolveClasses in the classpath. It uses the environment and
+ * store created by EvolveTestInit. It verifies that it can read/write/evolve
+ * objects serialized using the old class format, and that it can create new
+ * objects with the new class format.
+ *
+ * @author Mark Hayes
+ */
+public class EvolveTest extends EvolveTestBase {
+
+ /* Toggle to use listener every other test case. */
+ private static boolean useEvolveListener;
+
+ public static Test suite()
+ throws Exception {
+
+ return getSuite(EvolveTest.class);
+ }
+
+ private int evolveNRead;
+ private int evolveNConverted;
+
+ boolean useEvolvedClass() {
+ return true;
+ }
+
+ @Override
+ public void tearDown() {
+ try { super.tearDown(); } catch (Throwable e) { }
+ }
+
+ @Override
+ public void setUp()
+ throws IOException {
+
+ /* Copy the log files created by EvolveTestInit. */
+ envHome = getTestInitHome(true /*evolved*/);
+ envHome.mkdirs();
+ SharedTestUtils.emptyDir(envHome);
+ SharedTestUtils.copyFiles(getTestInitHome(false /*evolved*/), envHome);
+ }
+
+ public void testLazyEvolve()
+ throws Exception {
+
+ openEnv();
+
+ /*
+ * Open in raw mode to check unevolved raw object and formats. This
+ * is possible whether or not we can open the store further below to
+ * evolve formats without errors.
+ */
+ openRawStore();
+ caseObj.checkUnevolvedModel(rawStore.getModel(), env);
+ caseObj.readRawObjects
+ (rawStore, false /*expectEvolved*/, false /*expectUpdated*/);
+ closeRawStore();
+
+ if (openStoreReadWrite()) {
+
+ /*
+ * When opening read-write, formats are evolved lazily. Check by
+ * reading evolved objects.
+ */
+ caseObj.checkEvolvedModel
+ (store.getModel(), env, true /*oldTypesExist*/);
+ caseObj.readObjects(store, false /*doUpdate*/);
+ closeStore();
+
+ /*
+ * Read raw objects again to check that the evolved objects are
+ * returned even though the stored objects were not evolved.
+ */
+ openRawStore();
+ caseObj.checkEvolvedModel
+ (rawStore.getModel(), env, true /*oldTypesExist*/);
+ caseObj.readRawObjects
+ (rawStore, true /*expectEvolved*/, false /*expectUpdated*/);
+ closeRawStore();
+
+ /*
+ * Open read-only to ensure that the catalog does not need to
+ * change (evolve formats) unnecessarily.
+ */
+ PersistCatalog.expectNoClassChanges = true;
+ try {
+ openStoreReadOnly();
+ } finally {
+ PersistCatalog.expectNoClassChanges = false;
+ }
+ caseObj.checkEvolvedModel
+ (store.getModel(), env, true /*oldTypesExist*/);
+ caseObj.readObjects(store, false /*doUpdate*/);
+ closeStore();
+
+ /*
+ * Open read-write to update objects and store them in evolved
+ * format.
+ */
+ openStoreReadWrite();
+ caseObj.checkEvolvedModel
+ (store.getModel(), env, true /*oldTypesExist*/);
+ caseObj.readObjects(store, true /*doUpdate*/);
+ caseObj.checkEvolvedModel
+ (store.getModel(), env, true /*oldTypesExist*/);
+ closeStore();
+
+ /*
+ * Check raw objects again after the evolved objects were stored.
+ */
+ openRawStore();
+ caseObj.checkEvolvedModel
+ (rawStore.getModel(), env, true /*oldTypesExist*/);
+ caseObj.readRawObjects
+ (rawStore, true /*expectEvolved*/, true /*expectUpdated*/);
+ closeRawStore();
+ }
+
+ closeAll();
+ }
+
+ public void testEagerEvolve()
+ throws Exception {
+
+ /* If the store cannot be opened, this test is not appropriate. */
+ if (caseObj.getStoreOpenException() != null) {
+ return;
+ }
+
+ EvolveConfig config = new EvolveConfig();
+
+ /*
+ * Use listener every other time to ensure that the stats are returned
+ * correctly when no listener is configured. [#17024]
+ */
+ useEvolveListener = !useEvolveListener;
+ if (useEvolveListener) {
+ config.setEvolveListener(new EvolveListener() {
+ public boolean evolveProgress(EvolveEvent event) {
+ EvolveStats stats = event.getStats();
+ evolveNRead = stats.getNRead();
+ evolveNConverted = stats.getNConverted();
+ return true;
+ }
+ });
+ }
+
+ openEnv();
+
+ openStoreReadWrite();
+
+ /*
+ * Evolve and expect that the expected number of entities are
+ * converted.
+ */
+ int nExpected = caseObj.getNRecordsExpected();
+ evolveNRead = 0;
+ evolveNConverted = 0;
+ PersistCatalog.unevolvedFormatsEncountered = false;
+ EvolveStats stats = store.evolve(config);
+ if (nExpected > 0) {
+ assertTrue(PersistCatalog.unevolvedFormatsEncountered);
+ }
+ assertTrue(stats.getNRead() == nExpected);
+ assertTrue(stats.getNConverted() == nExpected);
+ assertTrue(stats.getNConverted() >= stats.getNRead());
+ if (useEvolveListener) {
+ assertEquals(evolveNRead, stats.getNRead());
+ assertEquals(evolveNConverted, stats.getNConverted());
+ }
+
+ /* Evolve again and expect that no entities are converted. */
+ evolveNRead = 0;
+ evolveNConverted = 0;
+ PersistCatalog.unevolvedFormatsEncountered = false;
+ stats = store.evolve(config);
+ assertTrue(!PersistCatalog.unevolvedFormatsEncountered);
+ assertEquals(0, stats.getNRead());
+ assertEquals(0, stats.getNConverted());
+ if (useEvolveListener) {
+ assertTrue(evolveNRead == 0);
+ assertTrue(evolveNConverted == 0);
+ }
+
+ /* Ensure that we can read all entities without evolution. */
+ PersistCatalog.unevolvedFormatsEncountered = false;
+ caseObj.readObjects(store, false /*doUpdate*/);
+ assertTrue(!PersistCatalog.unevolvedFormatsEncountered);
+
+ /*
+ * When automatic unused type deletion is implemented in the future the
+ * oldTypesExist parameters below should be changed to false.
+ */
+
+ /* Open again and try an update. */
+ caseObj.checkEvolvedModel
+ (store.getModel(), env, true /*oldTypesExist*/);
+ caseObj.readObjects(store, true /*doUpdate*/);
+ caseObj.checkEvolvedModel
+ (store.getModel(), env, true /*oldTypesExist*/);
+ closeStore();
+
+ /* Open read-only and double check that everything is OK. */
+ openStoreReadOnly();
+ caseObj.checkEvolvedModel
+ (store.getModel(), env, true /*oldTypesExist*/);
+ caseObj.readObjects(store, false /*doUpdate*/);
+ caseObj.checkEvolvedModel
+ (store.getModel(), env, true /*oldTypesExist*/);
+ closeStore();
+
+ /* Check raw objects. */
+ openRawStore();
+ caseObj.checkEvolvedModel
+ (rawStore.getModel(), env, true /*oldTypesExist*/);
+ caseObj.readRawObjects
+ (rawStore, true /*expectEvolved*/, true /*expectUpdated*/);
+
+ /*
+ * Test copy raw object to new store via convertRawObject. In this
+ * test we can pass false for oldTypesExist because newStore starts
+ * with the new/evolved class model.
+ */
+ openNewStore();
+ caseObj.copyRawObjects(rawStore, newStore);
+ caseObj.readObjects(newStore, true /*doUpdate*/);
+ caseObj.checkEvolvedModel
+ (newStore.getModel(), env, false /*oldTypesExist*/);
+ closeNewStore();
+ closeRawStore();
+
+ closeAll();
+ }
+}
diff --git a/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveTestBase.java b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveTestBase.java
new file mode 100644
index 0000000..7b97dcd
--- /dev/null
+++ b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveTestBase.java
@@ -0,0 +1,438 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+package com.sleepycat.persist.test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Enumeration;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import com.sleepycat.db.DatabaseException;
+import com.sleepycat.db.Environment;
+import com.sleepycat.db.EnvironmentConfig;
+import com.sleepycat.persist.EntityStore;
+import com.sleepycat.persist.StoreConfig;
+import com.sleepycat.persist.model.AnnotationModel;
+import com.sleepycat.persist.model.EntityModel;
+import com.sleepycat.persist.raw.RawStore;
+import com.sleepycat.util.test.TestEnv;
+
+/**
+ * Base class for EvolveTest and EvolveTestInit.
+ *
+ * @author Mark Hayes
+ */
+public abstract class EvolveTestBase extends TestCase {
+
+ /*
+ * When adding a evolve test class, three places need to be changed:
+ * 1) Add the unmodified class to EvolveClass.java.original.
+ * 2) Add the modified class to EvolveClass.java.
+ * 3) Add the class name to the ALL list below as a pair of strings. The
+ * first string in each pair is the name of the original class, and the
+ * second string is the name of the evolved class or null if the evolved
+ * name is the same as the original. The index in the list identifies a
+ * test case, and the class at that position identifies the old and new
+ * class to use for the test.
+ */
+ private static final String[] ALL = {
+//*
+ "DeletedEntity1_ClassRemoved",
+ "DeletedEntity1_ClassRemoved_NoMutation",
+ "DeletedEntity2_ClassRemoved",
+ "DeletedEntity2_ClassRemoved_WithDeleter",
+ "DeletedEntity3_AnnotRemoved_NoMutation",
+ null,
+ "DeletedEntity4_AnnotRemoved_WithDeleter",
+ null,
+ "DeletedEntity5_EntityToPersist_NoMutation",
+ null,
+ "DeletedEntity6_EntityToPersist_WithDeleter",
+ null,
+ "DeletedPersist1_ClassRemoved_NoMutation",
+ null,
+ "DeletedPersist2_ClassRemoved_WithDeleter",
+ null,
+ "DeletedPersist3_AnnotRemoved_NoMutation",
+ null,
+ "DeletedPersist4_AnnotRemoved_WithDeleter",
+ null,
+ "DeletedPersist5_PersistToEntity_NoMutation",
+ null,
+ "DeletedPersist6_PersistToEntity_WithDeleter",
+ null,
+ "RenamedEntity1_NewEntityName",
+ "RenamedEntity1_NewEntityName_NoMutation",
+ "RenamedEntity2_NewEntityName",
+ "RenamedEntity2_NewEntityName_WithRenamer",
+ "DeleteSuperclass1_NoMutation",
+ null,
+ "DeleteSuperclass2_WithConverter",
+ null,
+ "DeleteSuperclass3_WithDeleter",
+ null,
+ "DeleteSuperclass4_NoFields",
+ null,
+ "DeleteSuperclass5_Top",
+ null,
+ "InsertSuperclass1_Between",
+ null,
+ "InsertSuperclass2_Top",
+ null,
+ "DisallowNonKeyField_PrimitiveToObject",
+ null,
+ "DisallowNonKeyField_ObjectToPrimitive",
+ null,
+ "DisallowNonKeyField_ObjectToSubtype",
+ null,
+ "DisallowNonKeyField_ObjectToUnrelatedSimple",
+ null,
+ "DisallowNonKeyField_ObjectToUnrelatedOther",
+ null,
+ "DisallowNonKeyField_byte2boolean",
+ null,
+ "DisallowNonKeyField_short2byte",
+ null,
+ "DisallowNonKeyField_int2short",
+ null,
+ "DisallowNonKeyField_long2int",
+ null,
+ "DisallowNonKeyField_float2long",
+ null,
+ "DisallowNonKeyField_double2float",
+ null,
+ "DisallowNonKeyField_Byte2byte",
+ null,
+ "DisallowNonKeyField_Character2char",
+ null,
+ "DisallowNonKeyField_Short2short",
+ null,
+ "DisallowNonKeyField_Integer2int",
+ null,
+ "DisallowNonKeyField_Long2long",
+ null,
+ "DisallowNonKeyField_Float2float",
+ null,
+ "DisallowNonKeyField_Double2double",
+ null,
+ "DisallowNonKeyField_float2BigInt",
+ null,
+ "DisallowNonKeyField_BigInt2long",
+ null,
+ "DisallowSecKeyField_byte2short",
+ null,
+ "DisallowSecKeyField_char2int",
+ null,
+ "DisallowSecKeyField_short2int",
+ null,
+ "DisallowSecKeyField_int2long",
+ null,
+ "DisallowSecKeyField_long2float",
+ null,
+ "DisallowSecKeyField_float2double",
+ null,
+ "DisallowSecKeyField_Byte2short2",
+ null,
+ "DisallowSecKeyField_Character2int",
+ null,
+ "DisallowSecKeyField_Short2int2",
+ null,
+ "DisallowSecKeyField_Integer2long",
+ null,
+ "DisallowSecKeyField_Long2float2",
+ null,
+ "DisallowSecKeyField_Float2double2",
+ null,
+ "DisallowSecKeyField_int2BigInt",
+ null,
+ "DisallowPriKeyField_byte2short",
+ null,
+ "DisallowPriKeyField_char2int",
+ null,
+ "DisallowPriKeyField_short2int",
+ null,
+ "DisallowPriKeyField_int2long",
+ null,
+ "DisallowPriKeyField_long2float",
+ null,
+ "DisallowPriKeyField_float2double",
+ null,
+ "DisallowPriKeyField_Byte2short2",
+ null,
+ "DisallowPriKeyField_Character2int",
+ null,
+ "DisallowPriKeyField_Short2int2",
+ null,
+ "DisallowPriKeyField_Integer2long",
+ null,
+ "DisallowPriKeyField_Long2float2",
+ null,
+ "DisallowPriKeyField_Float2double2",
+ null,
+ "DisallowPriKeyField_Long2BigInt",
+ null,
+ "DisallowCompositeKeyField_byte2short",
+ null,
+ "AllowPriKeyField_Byte2byte2",
+ null,
+ "AllowPriKeyField_byte2Byte",
+ null,
+ "AllowFieldTypeChanges",
+ null,
+ "ConvertFieldContent_Entity",
+ null,
+ "ConvertExample1_Entity",
+ null,
+ "ConvertExample2_Person",
+ null,
+ "ConvertExample3_Person",
+ null,
+ "ConvertExample3Reverse_Person",
+ null,
+ "ConvertExample4_Entity",
+ null,
+ "ConvertExample5_Entity",
+ null,
+ "AllowFieldAddDelete",
+ null,
+ "ProxiedClass_Entity",
+ null,
+ "DisallowChangeProxyFor",
+ null,
+ "DisallowDeleteProxyFor",
+ null,
+ "ArrayNameChange_Entity",
+ null,
+ "AddEnumConstant_Entity",
+ null,
+ "InsertEnumConstant_Entity",
+ null,
+ "DeleteEnumConstant_NoMutation",
+ null,
+ "DisallowChangeKeyRelate",
+ null,
+ "AllowChangeKeyMetadata",
+ null,
+ "AllowChangeKeyMetadataInSubclass",
+ null,
+ "AllowAddSecondary",
+ null,
+ "FieldAddAndConvert",
+ null,
+//*/
+ };
+
+ File envHome;
+ Environment env;
+ EntityStore store;
+ RawStore rawStore;
+ EntityStore newStore;
+ String caseClsName;
+ Class caseCls;
+ EvolveCase caseObj;
+ String caseLabel;
+
+ static TestSuite getSuite(Class testClass)
+ throws Exception {
+
+ TestSuite suite = new TestSuite();
+ for (int i = 0; i < ALL.length; i += 2) {
+ String originalClsName = ALL[i];
+ String evolvedClsName = ALL[i + 1];
+ if (evolvedClsName == null) {
+ evolvedClsName = originalClsName;
+ }
+ TestSuite baseSuite = new TestSuite(testClass);
+ Enumeration e = baseSuite.tests();
+ while (e.hasMoreElements()) {
+ EvolveTestBase test = (EvolveTestBase) e.nextElement();
+ test.init(originalClsName, evolvedClsName);
+ suite.addTest(test);
+ }
+ }
+ return suite;
+ }
+
+ private void init(String originalClsName,
+ String evolvedClsName)
+ throws Exception {
+
+ String caseClsName = useEvolvedClass() ?
+ evolvedClsName : originalClsName;
+ caseClsName = "com.sleepycat.persist.test.EvolveClasses$" +
+ caseClsName;
+
+ this.caseClsName = caseClsName;
+ this.caseCls = Class.forName(caseClsName);
+ this.caseObj = (EvolveCase) caseCls.newInstance();
+ this.caseLabel = evolvedClsName;
+ }
+
+ abstract boolean useEvolvedClass();
+
+ File getTestInitHome(boolean evolved) {
+ return new File
+ (System.getProperty("testevolvedir"),
+ (evolved ? "evolved" : "original") + '/' + caseLabel);
+ }
+
+ @Override
+ public void tearDown() {
+
+ /* Set test name for reporting; cannot be done in the ctor or setUp. */
+ setName(caseLabel + '-' + getName());
+
+ if (env != null) {
+ try {
+ closeAll();
+ } catch (Throwable e) {
+ System.out.println("During tearDown: " + e);
+ }
+ }
+ envHome = null;
+ env = null;
+ store = null;
+ caseCls = null;
+ caseObj = null;
+ caseLabel = null;
+
+ /* Do not delete log files so they can be used by 2nd phase of test. */
+ }
+
+ /**
+ * @throws FileNotFoundException from DB core.
+ */
+ void openEnv()
+ throws FileNotFoundException, DatabaseException {
+
+ EnvironmentConfig config = TestEnv.TXN.getConfig();
+ config.setAllowCreate(true);
+ env = new Environment(envHome, config);
+ }
+
+ /**
+ * Returns true if the store was opened successfully. Returns false if the
+ * store could not be opened because an exception was expected -- this is
+ * not a test failure but no further tests for an EntityStore may be run.
+ */
+ private boolean openStore(StoreConfig config)
+ throws Exception {
+
+ config.setTransactional(true);
+ config.setMutations(caseObj.getMutations());
+
+ EntityModel model = new AnnotationModel();
+ config.setModel(model);
+ caseObj.configure(model, config);
+
+ String expectException = caseObj.getStoreOpenException();
+ try {
+ store = new EntityStore(env, EvolveCase.STORE_NAME, config);
+ if (expectException != null) {
+ fail("Expected: " + expectException);
+ }
+ } catch (Exception e) {
+ if (expectException != null) {
+ //e.printStackTrace();
+ String actualMsg = e.getMessage();
+ EvolveCase.checkEquals
+ (expectException,
+ e.getClass().getName() + ": " + actualMsg);
+ return false;
+ } else {
+ throw e;
+ }
+ }
+ return true;
+ }
+
+ boolean openStoreReadOnly()
+ throws Exception {
+
+ StoreConfig config = new StoreConfig();
+ config.setReadOnly(true);
+ return openStore(config);
+ }
+
+ boolean openStoreReadWrite()
+ throws Exception {
+
+ StoreConfig config = new StoreConfig();
+ config.setAllowCreate(true);
+ return openStore(config);
+ }
+
+ void openRawStore()
+ throws DatabaseException {
+
+ StoreConfig config = new StoreConfig();
+ config.setTransactional(true);
+ rawStore = new RawStore(env, EvolveCase.STORE_NAME, config);
+ }
+
+ void closeStore()
+ throws DatabaseException {
+
+ if (store != null) {
+ store.close();
+ store = null;
+ }
+ }
+
+ void openNewStore()
+ throws Exception {
+
+ StoreConfig config = new StoreConfig();
+ config.setAllowCreate(true);
+ config.setTransactional(true);
+
+ EntityModel model = new AnnotationModel();
+ config.setModel(model);
+ caseObj.configure(model, config);
+
+ newStore = new EntityStore(env, "new", config);
+ }
+
+ void closeNewStore()
+ throws DatabaseException {
+
+ if (newStore != null) {
+ newStore.close();
+ newStore = null;
+ }
+ }
+
+ void closeRawStore()
+ throws DatabaseException {
+
+ if (rawStore != null) {
+ rawStore.close();
+ rawStore = null;
+ }
+ }
+
+ void closeEnv()
+ throws DatabaseException {
+
+ if (env != null) {
+ env.close();
+ env = null;
+ }
+ }
+
+ void closeAll()
+ throws DatabaseException {
+
+ closeStore();
+ closeRawStore();
+ closeNewStore();
+ closeEnv();
+ }
+}
diff --git a/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveTestInit.java b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveTestInit.java
new file mode 100644
index 0000000..06ed2a7
--- /dev/null
+++ b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/EvolveTestInit.java
@@ -0,0 +1,53 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+package com.sleepycat.persist.test;
+
+import junit.framework.Test;
+
+import com.sleepycat.util.test.SharedTestUtils;
+
+/**
+ * Runs part one of the EvolveTest. This part is run with the old/original
+ * version of EvolveClasses in the classpath. It creates a fresh environment
+ * and store containing instances of the original class. When EvolveTest is
+ * run, it will read/write/evolve these objects from the store created here.
+ *
+ * @author Mark Hayes
+ */
+public class EvolveTestInit extends EvolveTestBase {
+
+ public static Test suite()
+ throws Exception {
+
+ return getSuite(EvolveTestInit.class);
+ }
+
+ @Override
+ boolean useEvolvedClass() {
+ return false;
+ }
+
+ @Override
+ public void setUp() {
+ envHome = getTestInitHome(false /*evolved*/);
+ envHome.mkdirs();
+ SharedTestUtils.emptyDir(envHome);
+ }
+
+ public void testInit()
+ throws Exception {
+
+ openEnv();
+ if (!openStoreReadWrite()) {
+ fail();
+ }
+ caseObj.writeObjects(store);
+ caseObj.checkUnevolvedModel(store.getModel(), env);
+ closeAll();
+ }
+}
diff --git a/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/ForeignKeyTest.java b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/ForeignKeyTest.java
new file mode 100644
index 0000000..741452c
--- /dev/null
+++ b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/ForeignKeyTest.java
@@ -0,0 +1,329 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package com.sleepycat.persist.test;
+
+import static com.sleepycat.persist.model.DeleteAction.ABORT;
+import static com.sleepycat.persist.model.DeleteAction.CASCADE;
+import static com.sleepycat.persist.model.DeleteAction.NULLIFY;
+import static com.sleepycat.persist.model.Relationship.ONE_TO_ONE;
+
+import java.util.Enumeration;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import com.sleepycat.compat.DbCompat;
+import com.sleepycat.db.DatabaseException;
+import com.sleepycat.db.Transaction;
+import com.sleepycat.persist.EntityStore;
+import com.sleepycat.persist.PrimaryIndex;
+import com.sleepycat.persist.SecondaryIndex;
+import com.sleepycat.persist.StoreConfig;
+import com.sleepycat.persist.model.DeleteAction;
+import com.sleepycat.persist.model.Entity;
+import com.sleepycat.persist.model.Persistent;
+import com.sleepycat.persist.model.PrimaryKey;
+import com.sleepycat.persist.model.SecondaryKey;
+import com.sleepycat.util.test.TxnTestCase;
+
+/**
+ * @author Mark Hayes
+ */
+public class ForeignKeyTest extends TxnTestCase {
+
+ private static final DeleteAction[] ACTIONS = {
+ ABORT,
+ NULLIFY,
+ CASCADE,
+ };
+
+ private static final String[] ACTION_LABELS = {
+ "ABORT",
+ "NULLIFY",
+ "CASCADE",
+ };
+
+ static protected Class<?> testClass = ForeignKeyTest.class;
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ for (int i = 0; i < ACTIONS.length; i += 1) {
+ for (int j = 0; j < 2; j++) {
+ TestSuite txnSuite = txnTestSuite(testClass, null, null);
+ Enumeration e = txnSuite.tests();
+ while (e.hasMoreElements()) {
+ ForeignKeyTest test = (ForeignKeyTest) e.nextElement();
+ test.onDelete = ACTIONS[i];
+ test.onDeleteLabel = ACTION_LABELS[i];
+ test.useSubclass = (j == 0);
+ test.useSubclassLabel =
+ (j == 0) ? "UseSubclass" : "UseBaseclass";
+ suite.addTest(test);
+ }
+ }
+ }
+ return suite;
+ }
+
+ private EntityStore store;
+ private PrimaryIndex<String,Entity1> pri1;
+ private PrimaryIndex<String,Entity2> pri2;
+ private SecondaryIndex<String,String,Entity1> sec1;
+ private SecondaryIndex<String,String,Entity2> sec2;
+ private DeleteAction onDelete;
+ private String onDeleteLabel;
+ private boolean useSubclass;
+ private String useSubclassLabel;
+
+ @Override
+ public void tearDown()
+ throws Exception {
+
+ super.tearDown();
+ setName(getName() + '-' + onDeleteLabel + "-" + useSubclassLabel);
+ }
+
+ private void open()
+ throws DatabaseException {
+
+ StoreConfig config = new StoreConfig();
+ config.setAllowCreate(envConfig.getAllowCreate());
+ config.setTransactional(envConfig.getTransactional());
+
+ store = new EntityStore(env, "test", config);
+
+ pri1 = store.getPrimaryIndex(String.class, Entity1.class);
+ sec1 = store.getSecondaryIndex(pri1, String.class, "sk");
+ pri2 = store.getPrimaryIndex(String.class, Entity2.class);
+ sec2 = store.getSecondaryIndex
+ (pri2, String.class, "sk_" + onDeleteLabel);
+ }
+
+ private void close()
+ throws DatabaseException {
+
+ store.close();
+ }
+
+ public void testForeignKeys()
+ throws Exception {
+
+ open();
+ Transaction txn = txnBegin();
+
+ Entity1 o1 = new Entity1("pk1", "sk1");
+ assertNull(pri1.put(txn, o1));
+
+ assertEquals(o1, pri1.get(txn, "pk1", null));
+ assertEquals(o1, sec1.get(txn, "sk1", null));
+
+ Entity2 o2 = (useSubclass ?
+ new Entity3("pk2", "pk1", onDelete) :
+ new Entity2("pk2", "pk1", onDelete));
+ assertNull(pri2.put(txn, o2));
+
+ assertEquals(o2, pri2.get(txn, "pk2", null));
+ assertEquals(o2, sec2.get(txn, "pk1", null));
+
+ txnCommit(txn);
+ txn = txnBegin();
+
+ /*
+ * pri1 contains o1 with primary key "pk1" and index key "sk1".
+ *
+ * pri2 contains o2 with primary key "pk2" and foreign key "pk1",
+ * which is the primary key of pri1.
+ */
+ if (onDelete == ABORT) {
+
+ /* Test that we abort trying to delete a referenced key. */
+
+ try {
+ pri1.delete(txn, "pk1");
+ fail();
+ } catch (DatabaseException expected) {
+ assertTrue(!DbCompat.NEW_JE_EXCEPTIONS);
+ txnAbort(txn);
+ txn = txnBegin();
+ }
+
+ /*
+ * Test that we can put a record into store2 with a null foreign
+ * key value.
+ */
+ o2 = (useSubclass ?
+ new Entity3("pk2", null, onDelete) :
+ new Entity2("pk2", null, onDelete));
+ assertNotNull(pri2.put(txn, o2));
+ assertEquals(o2, pri2.get(txn, "pk2", null));
+
+ /*
+ * The index2 record should have been deleted since the key was set
+ * to null above.
+ */
+ assertNull(sec2.get(txn, "pk1", null));
+
+ /*
+ * Test that now we can delete the record in store1, since it is no
+ * longer referenced.
+ */
+ assertNotNull(pri1.delete(txn, "pk1"));
+ assertNull(pri1.get(txn, "pk1", null));
+ assertNull(sec1.get(txn, "sk1", null));
+
+ } else if (onDelete == NULLIFY) {
+
+ /* Delete the referenced key. */
+ assertNotNull(pri1.delete(txn, "pk1"));
+ assertNull(pri1.get(txn, "pk1", null));
+ assertNull(sec1.get(txn, "sk1", null));
+
+ /*
+ * The store2 record should still exist, but should have an empty
+ * secondary key since it was nullified.
+ */
+ o2 = pri2.get(txn, "pk2", null);
+ assertNotNull(o2);
+ assertEquals("pk2", o2.pk);
+ assertEquals(null, o2.getSk(onDelete));
+
+ } else if (onDelete == CASCADE) {
+
+ /* Delete the referenced key. */
+ assertNotNull(pri1.delete(txn, "pk1"));
+ assertNull(pri1.get(txn, "pk1", null));
+ assertNull(sec1.get(txn, "sk1", null));
+
+ /* The store2 record should have deleted also. */
+ assertNull(pri2.get(txn, "pk2", null));
+ assertNull(sec2.get(txn, "pk1", null));
+
+ } else {
+ throw new IllegalStateException();
+ }
+
+ /*
+ * Test that a foreign key value may not be used that is not present in
+ * the foreign store. "pk2" is not in store1 in this case.
+ */
+ Entity2 o3 = (useSubclass ?
+ new Entity3("pk3", "pk2", onDelete) :
+ new Entity2("pk3", "pk2", onDelete));
+ try {
+ pri2.put(txn, o3);
+ fail();
+ } catch (DatabaseException expected) {
+ assertTrue(!DbCompat.NEW_JE_EXCEPTIONS);
+ }
+
+ txnAbort(txn);
+ close();
+ }
+
+ @Entity
+ static class Entity1 {
+
+ @PrimaryKey
+ String pk;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ String sk;
+
+ private Entity1() {}
+
+ Entity1(String pk, String sk) {
+ this.pk = pk;
+ this.sk = sk;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ Entity1 o = (Entity1) other;
+ return nullOrEqual(pk, o.pk) &&
+ nullOrEqual(sk, o.sk);
+ }
+ }
+
+ @Entity
+ static class Entity2 {
+
+ @PrimaryKey
+ String pk;
+
+ @SecondaryKey(relate=ONE_TO_ONE, relatedEntity=Entity1.class,
+ onRelatedEntityDelete=ABORT)
+ String sk_ABORT;
+
+ @SecondaryKey(relate=ONE_TO_ONE, relatedEntity=Entity1.class,
+ onRelatedEntityDelete=CASCADE)
+ String sk_CASCADE;
+
+ @SecondaryKey(relate=ONE_TO_ONE, relatedEntity=Entity1.class,
+ onRelatedEntityDelete=NULLIFY)
+ String sk_NULLIFY;
+
+ private Entity2() {}
+
+ Entity2(String pk, String sk, DeleteAction action) {
+ this.pk = pk;
+ switch (action) {
+ case ABORT:
+ sk_ABORT = sk;
+ break;
+ case CASCADE:
+ sk_CASCADE = sk;
+ break;
+ case NULLIFY:
+ sk_NULLIFY = sk;
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ String getSk(DeleteAction action) {
+ switch (action) {
+ case ABORT:
+ return sk_ABORT;
+ case CASCADE:
+ return sk_CASCADE;
+ case NULLIFY:
+ return sk_NULLIFY;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ Entity2 o = (Entity2) other;
+ return nullOrEqual(pk, o.pk) &&
+ nullOrEqual(sk_ABORT, o.sk_ABORT) &&
+ nullOrEqual(sk_CASCADE, o.sk_CASCADE) &&
+ nullOrEqual(sk_NULLIFY, o.sk_NULLIFY);
+ }
+ }
+
+ @Persistent
+ static class Entity3 extends Entity2 {
+ Entity3() {}
+
+ Entity3(String pk, String sk, DeleteAction action) {
+ super(pk, sk, action);
+ }
+ }
+
+ static boolean nullOrEqual(Object o1, Object o2) {
+ if (o1 == null) {
+ return o2 == null;
+ } else {
+ return o1.equals(o2);
+ }
+ }
+}
diff --git a/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/IndexTest.java b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/IndexTest.java
new file mode 100644
index 0000000..d4478c5
--- /dev/null
+++ b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/IndexTest.java
@@ -0,0 +1,874 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2002-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package com.sleepycat.persist.test;
+
+import static com.sleepycat.persist.model.Relationship.MANY_TO_MANY;
+import static com.sleepycat.persist.model.Relationship.MANY_TO_ONE;
+import static com.sleepycat.persist.model.Relationship.ONE_TO_MANY;
+import static com.sleepycat.persist.model.Relationship.ONE_TO_ONE;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import junit.framework.Test;
+
+import com.sleepycat.collections.MapEntryParameter;
+import com.sleepycat.db.DatabaseException;
+import com.sleepycat.db.Transaction;
+import com.sleepycat.persist.EntityCursor;
+import com.sleepycat.persist.EntityIndex;
+import com.sleepycat.persist.EntityStore;
+import com.sleepycat.persist.PrimaryIndex;
+import com.sleepycat.persist.SecondaryIndex;
+import com.sleepycat.persist.StoreConfig;
+import com.sleepycat.persist.model.Entity;
+import com.sleepycat.persist.model.PrimaryKey;
+import com.sleepycat.persist.model.SecondaryKey;
+import com.sleepycat.persist.raw.RawObject;
+import com.sleepycat.persist.raw.RawStore;
+import com.sleepycat.persist.raw.RawType;
+import com.sleepycat.util.test.TxnTestCase;
+
+/**
+ * Tests EntityIndex and EntityCursor in all their permutations.
+ *
+ * @author Mark Hayes
+ */
+public class IndexTest extends TxnTestCase {
+
+ private static final int N_RECORDS = 5;
+ private static final int THREE_TO_ONE = 3;
+
+ static protected Class<?> testClass = IndexTest.class;
+
+ public static Test suite() {
+ return txnTestSuite(testClass, null,
+ null);
+ //new String[] { TxnTestCase.TXN_NULL});
+ }
+
+ private EntityStore store;
+ private PrimaryIndex<Integer,MyEntity> primary;
+ private SecondaryIndex<Integer,Integer,MyEntity> oneToOne;
+ private SecondaryIndex<Integer,Integer,MyEntity> manyToOne;
+ private SecondaryIndex<Integer,Integer,MyEntity> oneToMany;
+ private SecondaryIndex<Integer,Integer,MyEntity> manyToMany;
+ private RawStore rawStore;
+ private RawType entityType;
+ private PrimaryIndex<Object,RawObject> primaryRaw;
+ private SecondaryIndex<Object,Object,RawObject> oneToOneRaw;
+ private SecondaryIndex<Object,Object,RawObject> manyToOneRaw;
+ private SecondaryIndex<Object,Object,RawObject> oneToManyRaw;
+ private SecondaryIndex<Object,Object,RawObject> manyToManyRaw;
+
+ /**
+ * Opens the store.
+ */
+ private void open()
+ throws DatabaseException {
+
+ StoreConfig config = new StoreConfig();
+ config.setAllowCreate(envConfig.getAllowCreate());
+ config.setTransactional(envConfig.getTransactional());
+
+ store = new EntityStore(env, "test", config);
+
+ primary = store.getPrimaryIndex(Integer.class, MyEntity.class);
+ oneToOne =
+ store.getSecondaryIndex(primary, Integer.class, "oneToOne");
+ manyToOne =
+ store.getSecondaryIndex(primary, Integer.class, "manyToOne");
+ oneToMany =
+ store.getSecondaryIndex(primary, Integer.class, "oneToMany");
+ manyToMany =
+ store.getSecondaryIndex(primary, Integer.class, "manyToMany");
+
+ assertNotNull(primary);
+ assertNotNull(oneToOne);
+ assertNotNull(manyToOne);
+ assertNotNull(oneToMany);
+ assertNotNull(manyToMany);
+
+ rawStore = new RawStore(env, "test", config);
+ String clsName = MyEntity.class.getName();
+ entityType = rawStore.getModel().getRawType(clsName);
+ assertNotNull(entityType);
+
+ primaryRaw = rawStore.getPrimaryIndex(clsName);
+ oneToOneRaw = rawStore.getSecondaryIndex(clsName, "oneToOne");
+ manyToOneRaw = rawStore.getSecondaryIndex(clsName, "manyToOne");
+ oneToManyRaw = rawStore.getSecondaryIndex(clsName, "oneToMany");
+ manyToManyRaw = rawStore.getSecondaryIndex(clsName, "manyToMany");
+
+ assertNotNull(primaryRaw);
+ assertNotNull(oneToOneRaw);
+ assertNotNull(manyToOneRaw);
+ assertNotNull(oneToManyRaw);
+ assertNotNull(manyToManyRaw);
+ }
+
+ /**
+ * Closes the store.
+ */
+ private void close()
+ throws DatabaseException {
+
+ store.close();
+ store = null;
+ rawStore.close();
+ rawStore = null;
+ }
+
+ @Override
+ public void setUp()
+ throws Exception {
+
+ super.setUp();
+ }
+
+ /**
+ * The store must be closed before closing the environment.
+ */
+ @Override
+ public void tearDown()
+ throws Exception {
+
+ try {
+ if (rawStore != null) {
+ rawStore.close();
+ }
+ } catch (Throwable e) {
+ System.out.println("During tearDown: " + e);
+ }
+ try {
+ if (store != null) {
+ store.close();
+ }
+ } catch (Throwable e) {
+ System.out.println("During tearDown: " + e);
+ }
+ store = null;
+ rawStore = null;
+ super.tearDown();
+ }
+
+ /**
+ * Primary keys: {0, 1, 2, 3, 4}
+ */
+ public void testPrimary()
+ throws DatabaseException {
+
+ SortedMap<Integer,SortedSet<Integer>> expected =
+ new TreeMap<Integer,SortedSet<Integer>>();
+
+ for (int priKey = 0; priKey < N_RECORDS; priKey += 1) {
+ SortedSet<Integer> values = new TreeSet<Integer>();
+ values.add(priKey);
+ expected.put(priKey, values);
+ }
+
+ open();
+ addEntities(primary);
+ checkIndex(primary, expected, keyGetter, entityGetter);
+ checkIndex(primaryRaw, expected, rawKeyGetter, rawEntityGetter);
+
+ /* Close and reopen, then recheck indices. */
+ close();
+ open();
+ checkIndex(primary, expected, keyGetter, entityGetter);
+ checkIndex(primaryRaw, expected, rawKeyGetter, rawEntityGetter);
+
+ /* Check primary delete, last key first for variety. */
+ for (int priKey = N_RECORDS - 1; priKey >= 0; priKey -= 1) {
+ boolean useRaw = ((priKey & 1) != 0);
+ Transaction txn = txnBegin();
+ if (useRaw) {
+ primaryRaw.delete(txn, priKey);
+ } else {
+ primary.delete(txn, priKey);
+ }
+ txnCommit(txn);
+ expected.remove(priKey);
+ checkIndex(primary, expected, keyGetter, entityGetter);
+ }
+ checkAllEmpty();
+
+ /* Check PrimaryIndex put operations. */
+ MyEntity e;
+ Transaction txn = txnBegin();
+ /* put() */
+ e = primary.put(txn, new MyEntity(1));
+ assertNull(e);
+ e = primary.get(txn, 1, null);
+ assertEquals(1, e.key);
+ /* putNoReturn() */
+ primary.putNoReturn(txn, new MyEntity(2));
+ e = primary.get(txn, 2, null);
+ assertEquals(2, e.key);
+ /* putNoOverwrite */
+ assertTrue(!primary.putNoOverwrite(txn, new MyEntity(1)));
+ assertTrue(!primary.putNoOverwrite(txn, new MyEntity(2)));
+ assertTrue(primary.putNoOverwrite(txn, new MyEntity(3)));
+ e = primary.get(txn, 3, null);
+ assertEquals(3, e.key);
+ txnCommit(txn);
+ close();
+ }
+
+ /**
+ * { 0:0, 1:-1, 2:-2, 3:-3, 4:-4 }
+ */
+ public void testOneToOne()
+ throws DatabaseException {
+
+ SortedMap<Integer,SortedSet<Integer>> expected =
+ new TreeMap<Integer,SortedSet<Integer>>();
+
+ for (int priKey = 0; priKey < N_RECORDS; priKey += 1) {
+ SortedSet<Integer> values = new TreeSet<Integer>();
+ values.add(priKey);
+ Integer secKey = (-priKey);
+ expected.put(secKey, values);
+ }
+
+ open();
+ addEntities(primary);
+ checkSecondary(oneToOne, oneToOneRaw, expected);
+ checkDelete(oneToOne, oneToOneRaw, expected);
+ close();
+ }
+
+ /**
+ * { 0:0, 1:1, 2:2, 3:0, 4:1 }
+ */
+ public void testManyToOne()
+ throws DatabaseException {
+
+ SortedMap<Integer,SortedSet<Integer>> expected =
+ new TreeMap<Integer,SortedSet<Integer>>();
+
+ for (int priKey = 0; priKey < N_RECORDS; priKey += 1) {
+ Integer secKey = priKey % THREE_TO_ONE;
+ SortedSet<Integer> values = expected.get(secKey);
+ if (values == null) {
+ values = new TreeSet<Integer>();
+ expected.put(secKey, values);
+ }
+ values.add(priKey);
+ }
+
+ open();
+ addEntities(primary);
+ checkSecondary(manyToOne, manyToOneRaw, expected);
+ checkDelete(manyToOne, manyToOneRaw, expected);
+ close();
+ }
+
+ /**
+ * { 0:{}, 1:{10}, 2:{20,21}, 3:{30,31,32}, 4:{40,41,42,43}
+ */
+ public void testOneToMany()
+ throws DatabaseException {
+
+ SortedMap<Integer,SortedSet<Integer>> expected =
+ new TreeMap<Integer,SortedSet<Integer>>();
+
+ for (int priKey = 0; priKey < N_RECORDS; priKey += 1) {
+ for (int i = 0; i < priKey; i += 1) {
+ Integer secKey = (N_RECORDS * priKey) + i;
+ SortedSet<Integer> values = expected.get(secKey);
+ if (values == null) {
+ values = new TreeSet<Integer>();
+ expected.put(secKey, values);
+ }
+ values.add(priKey);
+ }
+ }
+
+ open();
+ addEntities(primary);
+ checkSecondary(oneToMany, oneToManyRaw, expected);
+ checkDelete(oneToMany, oneToManyRaw, expected);
+ close();
+ }
+
+ /**
+ * { 0:{}, 1:{0}, 2:{0,1}, 3:{0,1,2}, 4:{0,1,2,3}
+ */
+ public void testManyToMany()
+ throws DatabaseException {
+
+ SortedMap<Integer,SortedSet<Integer>> expected =
+ new TreeMap<Integer,SortedSet<Integer>>();
+
+ for (int priKey = 0; priKey < N_RECORDS; priKey += 1) {
+ for (int i = 0; i < priKey; i += 1) {
+ Integer secKey = i;
+ SortedSet<Integer> values = expected.get(secKey);
+ if (values == null) {
+ values = new TreeSet<Integer>();
+ expected.put(secKey, values);
+ }
+ values.add(priKey);
+ }
+ }
+
+ open();
+ addEntities(primary);
+ checkSecondary(manyToMany, manyToManyRaw, expected);
+ checkDelete(manyToMany, manyToManyRaw, expected);
+ close();
+ }
+
+ private void addEntities(PrimaryIndex<Integer,MyEntity> primary)
+ throws DatabaseException {
+
+ Transaction txn = txnBegin();
+ for (int priKey = 0; priKey < N_RECORDS; priKey += 1) {
+ MyEntity prev = primary.put(txn, new MyEntity(priKey));
+ assertNull(prev);
+ }
+ txnCommit(txn);
+ }
+
+ private void checkDelete(SecondaryIndex<Integer,Integer,MyEntity> index,
+ SecondaryIndex<Object,Object,RawObject> indexRaw,
+ SortedMap<Integer,SortedSet<Integer>> expected)
+ throws DatabaseException {
+
+ SortedMap<Integer,SortedSet<Integer>> expectedSubIndex =
+ new TreeMap<Integer,SortedSet<Integer>>();
+
+ while (expected.size() > 0) {
+ Integer delSecKey = expected.firstKey();
+ SortedSet<Integer> deletedPriKeys = expected.remove(delSecKey);
+ for (SortedSet<Integer> priKeys : expected.values()) {
+ priKeys.removeAll(deletedPriKeys);
+ }
+ Transaction txn = txnBegin();
+ boolean deleted = index.delete(txn, delSecKey);
+ assertEquals(deleted, !deletedPriKeys.isEmpty());
+ deleted = index.delete(txn, delSecKey);
+ assertTrue(!deleted);
+ assertNull(index.get(txn, delSecKey, null));
+ txnCommit(txn);
+ checkSecondary(index, indexRaw, expected);
+ }
+
+ /*
+ * Delete remaining records so that the primary index is empty. Use
+ * the RawStore for variety.
+ */
+ Transaction txn = txnBegin();
+ for (int priKey = 0; priKey < N_RECORDS; priKey += 1) {
+ primaryRaw.delete(txn, priKey);
+ }
+ txnCommit(txn);
+ checkAllEmpty();
+ }
+
+ private void checkSecondary(SecondaryIndex<Integer,Integer,MyEntity> index,
+ SecondaryIndex<Object,Object,RawObject>
+ indexRaw,
+ SortedMap<Integer,SortedSet<Integer>> expected)
+ throws DatabaseException {
+
+ checkIndex(index, expected, keyGetter, entityGetter);
+ checkIndex(index.keysIndex(), expected, keyGetter, keyGetter);
+
+ checkIndex(indexRaw, expected, rawKeyGetter, rawEntityGetter);
+ checkIndex(indexRaw.keysIndex(), expected, rawKeyGetter, rawKeyGetter);
+
+ SortedMap<Integer,SortedSet<Integer>> expectedSubIndex =
+ new TreeMap<Integer,SortedSet<Integer>>();
+
+ for (Integer secKey : expected.keySet()) {
+ expectedSubIndex.clear();
+ for (Integer priKey : expected.get(secKey)) {
+ SortedSet<Integer> values = new TreeSet<Integer>();
+ values.add(priKey);
+ expectedSubIndex.put(priKey, values);
+ }
+ checkIndex(index.subIndex(secKey),
+ expectedSubIndex,
+ keyGetter,
+ entityGetter);
+ checkIndex(indexRaw.subIndex(secKey),
+ expectedSubIndex,
+ rawKeyGetter,
+ rawEntityGetter);
+ }
+ }
+
+ private <K,V> void checkIndex(EntityIndex<K,V> index,
+ SortedMap<Integer,SortedSet<Integer>>
+ expected,
+ Getter<K> kGetter,
+ Getter<V> vGetter)
+ throws DatabaseException {
+
+ SortedMap<K,V> map = index.sortedMap();
+
+ Transaction txn = txnBegin();
+ for (int i : expected.keySet()) {
+ K k = kGetter.fromInt(i);
+ SortedSet<Integer> dups = expected.get(i);
+ if (dups.isEmpty()) {
+
+ /* EntityIndex */
+ V v = index.get(txn, k, null);
+ assertNull(v);
+ assertTrue(!index.contains(txn, k, null));
+
+ /* Map/Collection */
+ v = map.get(i);
+ assertNull(v);
+ assertTrue(!map.containsKey(i));
+ } else {
+ int j = dups.first();
+
+ /* EntityIndex */
+ V v = index.get(txn, k, null);
+ assertNotNull(v);
+ assertEquals(j, vGetter.getKey(v));
+ assertTrue(index.contains(txn, k, null));
+
+ /* Map/Collection */
+ v = map.get(i);
+ assertNotNull(v);
+ assertEquals(j, vGetter.getKey(v));
+ assertTrue(map.containsKey(i));
+ assertTrue("" + i + ' ' + j + ' ' + v + ' ' + map,
+ map.containsValue(v));
+ assertTrue(map.keySet().contains(i));
+ assertTrue(map.values().contains(v));
+ assertTrue
+ (map.entrySet().contains(new MapEntryParameter(i, v)));
+ }
+ }
+ txnCommit(txn);
+
+ int keysSize = expandKeySize(expected);
+ int valuesSize = expandValueSize(expected);
+
+ /* EntityIndex.count */
+ assertEquals("keysSize=" + keysSize, valuesSize, index.count());
+
+ /* Map/Collection size */
+ assertEquals(valuesSize, map.size());
+ assertEquals(valuesSize, map.values().size());
+ assertEquals(valuesSize, map.entrySet().size());
+ assertEquals(keysSize, map.keySet().size());
+
+ /* Map/Collection isEmpty */
+ assertEquals(valuesSize == 0, map.isEmpty());
+ assertEquals(valuesSize == 0, map.values().isEmpty());
+ assertEquals(valuesSize == 0, map.entrySet().isEmpty());
+ assertEquals(keysSize == 0, map.keySet().isEmpty());
+
+ txn = txnBeginCursor();
+
+ /* Unconstrained cursors. */
+ checkCursor
+ (index.keys(txn, null),
+ map.keySet(), true,
+ expandKeys(expected), kGetter);
+ checkCursor
+ (index.entities(txn, null),
+ map.values(), false,
+ expandValues(expected), vGetter);
+
+ /* Range cursors. */
+ if (expected.isEmpty()) {
+ checkOpenRanges(txn, 0, index, expected, kGetter, vGetter);
+ checkClosedRanges(txn, 0, 1, index, expected, kGetter, vGetter);
+ } else {
+ int firstKey = expected.firstKey();
+ int lastKey = expected.lastKey();
+ for (int i = firstKey - 1; i <= lastKey + 1; i += 1) {
+ checkOpenRanges(txn, i, index, expected, kGetter, vGetter);
+ int j = i + 1;
+ if (j < lastKey + 1) {
+ checkClosedRanges
+ (txn, i, j, index, expected, kGetter, vGetter);
+ }
+ }
+ }
+
+ txnCommit(txn);
+ }
+
+ private <K,V> void checkOpenRanges(Transaction txn, int i,
+ EntityIndex<K,V> index,
+ SortedMap<Integer,SortedSet<Integer>>
+ expected,
+ Getter<K> kGetter,
+ Getter<V> vGetter)
+ throws DatabaseException {
+
+ SortedMap<K,V> map = index.sortedMap();
+ SortedMap<Integer,SortedSet<Integer>> rangeExpected;
+ K k = kGetter.fromInt(i);
+ K kPlusOne = kGetter.fromInt(i + 1);
+
+ /* Head range exclusive. */
+ rangeExpected = expected.headMap(i);
+ checkCursor
+ (index.keys(txn, null, false, k, false, null),
+ map.headMap(k).keySet(), true,
+ expandKeys(rangeExpected), kGetter);
+ checkCursor
+ (index.entities(txn, null, false, k, false, null),
+ map.headMap(k).values(), false,
+ expandValues(rangeExpected), vGetter);
+
+ /* Head range inclusive. */
+ rangeExpected = expected.headMap(i + 1);
+ checkCursor
+ (index.keys(txn, null, false, k, true, null),
+ map.headMap(kPlusOne).keySet(), true,
+ expandKeys(rangeExpected), kGetter);
+ checkCursor
+ (index.entities(txn, null, false, k, true, null),
+ map.headMap(kPlusOne).values(), false,
+ expandValues(rangeExpected), vGetter);
+
+ /* Tail range exclusive. */
+ rangeExpected = expected.tailMap(i + 1);
+ checkCursor
+ (index.keys(txn, k, false, null, false, null),
+ map.tailMap(kPlusOne).keySet(), true,
+ expandKeys(rangeExpected), kGetter);
+ checkCursor
+ (index.entities(txn, k, false, null, false, null),
+ map.tailMap(kPlusOne).values(), false,
+ expandValues(rangeExpected), vGetter);
+
+ /* Tail range inclusive. */
+ rangeExpected = expected.tailMap(i);
+ checkCursor
+ (index.keys(txn, k, true, null, false, null),
+ map.tailMap(k).keySet(), true,
+ expandKeys(rangeExpected), kGetter);
+ checkCursor
+ (index.entities(txn, k, true, null, false, null),
+ map.tailMap(k).values(), false,
+ expandValues(rangeExpected), vGetter);
+ }
+
+ private <K,V> void checkClosedRanges(Transaction txn, int i, int j,
+ EntityIndex<K,V> index,
+ SortedMap<Integer,SortedSet<Integer>>
+ expected,
+ Getter<K> kGetter,
+ Getter<V> vGetter)
+ throws DatabaseException {
+
+ SortedMap<K,V> map = index.sortedMap();
+ SortedMap<Integer,SortedSet<Integer>> rangeExpected;
+ K k = kGetter.fromInt(i);
+ K kPlusOne = kGetter.fromInt(i + 1);
+ K l = kGetter.fromInt(j);
+ K lPlusOne = kGetter.fromInt(j + 1);
+
+ /* Sub range exclusive. */
+ rangeExpected = expected.subMap(i + 1, j);
+ checkCursor
+ (index.keys(txn, k, false, l, false, null),
+ map.subMap(kPlusOne, l).keySet(), true,
+ expandKeys(rangeExpected), kGetter);
+ checkCursor
+ (index.entities(txn, k, false, l, false, null),
+ map.subMap(kPlusOne, l).values(), false,
+ expandValues(rangeExpected), vGetter);
+
+ /* Sub range inclusive. */
+ rangeExpected = expected.subMap(i, j + 1);
+ checkCursor
+ (index.keys(txn, k, true, l, true, null),
+ map.subMap(k, lPlusOne).keySet(), true,
+ expandKeys(rangeExpected), kGetter);
+ checkCursor
+ (index.entities(txn, k, true, l, true, null),
+ map.subMap(k, lPlusOne).values(), false,
+ expandValues(rangeExpected), vGetter);
+ }
+
+ private List<List<Integer>>
+ expandKeys(SortedMap<Integer,SortedSet<Integer>> map) {
+
+ List<List<Integer>> list = new ArrayList<List<Integer>>();
+ for (Integer key : map.keySet()) {
+ SortedSet<Integer> values = map.get(key);
+ List<Integer> dups = new ArrayList<Integer>();
+ for (int i = 0; i < values.size(); i += 1) {
+ dups.add(key);
+ }
+ list.add(dups);
+ }
+ return list;
+ }
+
+ private List<List<Integer>>
+ expandValues(SortedMap<Integer,SortedSet<Integer>> map) {
+
+ List<List<Integer>> list = new ArrayList<List<Integer>>();
+ for (SortedSet<Integer> values : map.values()) {
+ list.add(new ArrayList<Integer>(values));
+ }
+ return list;
+ }
+
+ private int expandKeySize(SortedMap<Integer,SortedSet<Integer>> map) {
+
+ int size = 0;
+ for (SortedSet<Integer> values : map.values()) {
+ if (values.size() > 0) {
+ size += 1;
+ }
+ }
+ return size;
+ }
+
+ private int expandValueSize(SortedMap<Integer,SortedSet<Integer>> map) {
+
+ int size = 0;
+ for (SortedSet<Integer> values : map.values()) {
+ size += values.size();
+ }
+ return size;
+ }
+
+ private <T> void checkCursor(EntityCursor<T> cursor,
+ Collection<T> collection,
+ boolean collectionIsKeySet,
+ List<List<Integer>> expected,
+ Getter<T> getter)
+ throws DatabaseException {
+
+ boolean first;
+ boolean firstDup;
+ Iterator<T> iterator = collection.iterator();
+
+ for (List<Integer> dups : expected) {
+ for (int i : dups) {
+ T o = cursor.next();
+ assertNotNull(o);
+ assertEquals(i, getter.getKey(o));
+ /* Value iterator over duplicates. */
+ if (!collectionIsKeySet) {
+ assertTrue(iterator.hasNext());
+ o = iterator.next();
+ assertNotNull(o);
+ assertEquals(i, getter.getKey(o));
+ }
+ }
+ }
+
+ first = true;
+ for (List<Integer> dups : expected) {
+ firstDup = true;
+ for (int i : dups) {
+ T o = first ? cursor.first()
+ : (firstDup ? cursor.next() : cursor.nextDup());
+ assertNotNull(o);
+ assertEquals(i, getter.getKey(o));
+ first = false;
+ firstDup = false;
+ }
+ }
+
+ first = true;
+ for (List<Integer> dups : expected) {
+ if (!dups.isEmpty()) {
+ int i = dups.get(0);
+ T o = first ? cursor.first() : cursor.nextNoDup();
+ assertNotNull(o);
+ assertEquals(i, getter.getKey(o));
+ /* Key iterator over non-duplicates. */
+ if (collectionIsKeySet) {
+ assertTrue(iterator.hasNext());
+ o = iterator.next();
+ assertNotNull(o);
+ assertEquals(i, getter.getKey(o));
+ }
+ first = false;
+ }
+ }
+
+ List<List<Integer>> reversed = new ArrayList<List<Integer>>();
+ for (List<Integer> dups : expected) {
+ ArrayList<Integer> reversedDups = new ArrayList<Integer>(dups);
+ Collections.reverse(reversedDups);
+ reversed.add(reversedDups);
+ }
+ Collections.reverse(reversed);
+
+ first = true;
+ for (List<Integer> dups : reversed) {
+ for (int i : dups) {
+ T o = first ? cursor.last() : cursor.prev();
+ assertNotNull(o);
+ assertEquals(i, getter.getKey(o));
+ first = false;
+ }
+ }
+
+ first = true;
+ for (List<Integer> dups : reversed) {
+ firstDup = true;
+ for (int i : dups) {
+ T o = first ? cursor.last()
+ : (firstDup ? cursor.prev() : cursor.prevDup());
+ assertNotNull(o);
+ assertEquals(i, getter.getKey(o));
+ first = false;
+ firstDup = false;
+ }
+ }
+
+ first = true;
+ for (List<Integer> dups : reversed) {
+ if (!dups.isEmpty()) {
+ int i = dups.get(0);
+ T o = first ? cursor.last() : cursor.prevNoDup();
+ assertNotNull(o);
+ assertEquals(i, getter.getKey(o));
+ first = false;
+ }
+ }
+
+ cursor.close();
+ }
+
+ private void checkAllEmpty()
+ throws DatabaseException {
+
+ checkEmpty(primary);
+ checkEmpty(oneToOne);
+ checkEmpty(oneToMany);
+ checkEmpty(manyToOne);
+ checkEmpty(manyToMany);
+ }
+
+ private <K,V> void checkEmpty(EntityIndex<K,V> index)
+ throws DatabaseException {
+
+ EntityCursor<K> keys = index.keys();
+ assertNull(keys.next());
+ assertTrue(!keys.iterator().hasNext());
+ keys.close();
+ EntityCursor<V> entities = index.entities();
+ assertNull(entities.next());
+ assertTrue(!entities.iterator().hasNext());
+ entities.close();
+ }
+
+ private interface Getter<T> {
+ int getKey(T o);
+ T fromInt(int i);
+ }
+
+ private static Getter<MyEntity> entityGetter =
+ new Getter<MyEntity>() {
+ public int getKey(MyEntity o) {
+ return o.key;
+ }
+ public MyEntity fromInt(int i) {
+ throw new UnsupportedOperationException();
+ }
+ };
+
+ private static Getter<Integer> keyGetter =
+ new Getter<Integer>() {
+ public int getKey(Integer o) {
+ return o;
+ }
+ public Integer fromInt(int i) {
+ return Integer.valueOf(i);
+ }
+ };
+
+ private static Getter<RawObject> rawEntityGetter =
+ new Getter<RawObject>() {
+ public int getKey(RawObject o) {
+ Object val = o.getValues().get("key");
+ return ((Integer) val).intValue();
+ }
+ public RawObject fromInt(int i) {
+ throw new UnsupportedOperationException();
+ }
+ };
+
+ private static Getter<Object> rawKeyGetter =
+ new Getter<Object>() {
+ public int getKey(Object o) {
+ return ((Integer) o).intValue();
+ }
+ public Object fromInt(int i) {
+ return Integer.valueOf(i);
+ }
+ };
+
+ @Entity
+ private static class MyEntity {
+
+ @PrimaryKey
+ private int key;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ private int oneToOne;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private int manyToOne;
+
+ @SecondaryKey(relate=ONE_TO_MANY)
+ private Set<Integer> oneToMany = new TreeSet<Integer>();
+
+ @SecondaryKey(relate=MANY_TO_MANY)
+ private Set<Integer> manyToMany = new TreeSet<Integer>();
+
+ private MyEntity() {}
+
+ private MyEntity(int key) {
+
+ /* example keys: {0, 1, 2, 3, 4} */
+ this.key = key;
+
+ /* { 0:0, 1:-1, 2:-2, 3:-3, 4:-4 } */
+ oneToOne = -key;
+
+ /* { 0:0, 1:1, 2:2, 3:0, 4:1 } */
+ manyToOne = key % THREE_TO_ONE;
+
+ /* { 0:{}, 1:{10}, 2:{20,21}, 3:{30,31,32}, 4:{40,41,42,43} */
+ for (int i = 0; i < key; i += 1) {
+ oneToMany.add((N_RECORDS * key) + i);
+ }
+
+ /* { 0:{}, 1:{0}, 2:{0,1}, 3:{0,1,2}, 4:{0,1,2,3} */
+ for (int i = 0; i < key; i += 1) {
+ manyToMany.add(i);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "MyEntity " + key;
+ }
+ }
+}
diff --git a/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/JoinTest.java b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/JoinTest.java
new file mode 100644
index 0000000..b77d37d
--- /dev/null
+++ b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/JoinTest.java
@@ -0,0 +1,176 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2002-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package com.sleepycat.persist.test;
+
+import static com.sleepycat.persist.model.Relationship.MANY_TO_ONE;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.Test;
+
+import com.sleepycat.db.DatabaseException;
+import com.sleepycat.db.Transaction;
+import com.sleepycat.persist.EntityJoin;
+import com.sleepycat.persist.EntityStore;
+import com.sleepycat.persist.ForwardCursor;
+import com.sleepycat.persist.PrimaryIndex;
+import com.sleepycat.persist.SecondaryIndex;
+import com.sleepycat.persist.StoreConfig;
+import com.sleepycat.persist.model.Entity;
+import com.sleepycat.persist.model.PrimaryKey;
+import com.sleepycat.persist.model.SecondaryKey;
+import com.sleepycat.util.test.TxnTestCase;
+
+/**
+ * @author Mark Hayes
+ */
+public class JoinTest extends TxnTestCase {
+
+ private static final int N_RECORDS = 5;
+
+ static protected Class<?> testClass = JoinTest.class;
+
+ public static Test suite() {
+ return txnTestSuite(testClass, null, null);
+ }
+
+ private EntityStore store;
+ private PrimaryIndex<Integer,MyEntity> primary;
+ private SecondaryIndex<Integer,Integer,MyEntity> sec1;
+ private SecondaryIndex<Integer,Integer,MyEntity> sec2;
+ private SecondaryIndex<Integer,Integer,MyEntity> sec3;
+
+ /**
+ * Opens the store.
+ */
+ private void open()
+ throws DatabaseException {
+
+ StoreConfig config = new StoreConfig();
+ config.setAllowCreate(envConfig.getAllowCreate());
+ config.setTransactional(envConfig.getTransactional());
+
+ store = new EntityStore(env, "test", config);
+
+ primary = store.getPrimaryIndex(Integer.class, MyEntity.class);
+ sec1 = store.getSecondaryIndex(primary, Integer.class, "k1");
+ sec2 = store.getSecondaryIndex(primary, Integer.class, "k2");
+ sec3 = store.getSecondaryIndex(primary, Integer.class, "k3");
+ }
+
+ /**
+ * Closes the store.
+ */
+ private void close()
+ throws DatabaseException {
+
+ store.close();
+ }
+
+ public void testJoin()
+ throws DatabaseException {
+
+ open();
+
+ /*
+ * Primary keys: { 0, 1, 2, 3, 4 }
+ * Secondary k1: { 0:0, 0:1, 0:2, 0:3, 0:4 }
+ * Secondary k2: { 0:0, 1:1, 0:2, 1:3, 0:4 }
+ * Secondary k3: { 0:0, 1:1, 2:2, 0:3, 1:4 }
+ */
+ Transaction txn = txnBegin();
+ for (int i = 0; i < N_RECORDS; i += 1) {
+ MyEntity e = new MyEntity(i, 0, i % 2, i % 3);
+ boolean ok = primary.putNoOverwrite(txn, e);
+ assertTrue(ok);
+ }
+ txnCommit(txn);
+
+ /*
+ * k1, k2, k3, -> { primary keys }
+ * -1 means don't include the key in the join.
+ */
+ doJoin( 0, 0, 0, new int[] { 0 });
+ doJoin( 0, 0, 1, new int[] { 4 });
+ doJoin( 0, 0, -1, new int[] { 0, 2, 4 });
+ doJoin(-1, 1, 1, new int[] { 1 });
+ doJoin(-1, 2, 2, new int[] { });
+ doJoin(-1, -1, 2, new int[] { 2 });
+
+ close();
+ }
+
+ private void doJoin(int k1, int k2, int k3, int[] expectKeys)
+ throws DatabaseException {
+
+ List<Integer> expect = new ArrayList<Integer>();
+ for (int i : expectKeys) {
+ expect.add(i);
+ }
+ EntityJoin join = new EntityJoin(primary);
+ if (k1 >= 0) {
+ join.addCondition(sec1, k1);
+ }
+ if (k2 >= 0) {
+ join.addCondition(sec2, k2);
+ }
+ if (k3 >= 0) {
+ join.addCondition(sec3, k3);
+ }
+ List<Integer> found;
+ Transaction txn = txnBegin();
+
+ /* Keys */
+ found = new ArrayList<Integer>();
+ ForwardCursor<Integer> keys = join.keys(txn, null);
+ for (int i : keys) {
+ found.add(i);
+ }
+ keys.close();
+ assertEquals(expect, found);
+
+ /* Entities */
+ found = new ArrayList<Integer>();
+ ForwardCursor<MyEntity> entities = join.entities(txn, null);
+ for (MyEntity e : entities) {
+ found.add(e.id);
+ }
+ entities.close();
+ assertEquals(expect, found);
+
+ txnCommit(txn);
+ }
+
+ @Entity
+ private static class MyEntity {
+ @PrimaryKey
+ int id;
+ @SecondaryKey(relate=MANY_TO_ONE)
+ int k1;
+ @SecondaryKey(relate=MANY_TO_ONE)
+ int k2;
+ @SecondaryKey(relate=MANY_TO_ONE)
+ int k3;
+
+ private MyEntity() {}
+
+ MyEntity(int id, int k1, int k2, int k3) {
+ this.id = id;
+ this.k1 = k1;
+ this.k2 = k2;
+ this.k3 = k3;
+ }
+
+ @Override
+ public String toString() {
+ return "MyEntity " + id + ' ' + k1 + ' ' + k2 + ' ' + k3;
+ }
+ }
+}
diff --git a/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/NegativeTest.java b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/NegativeTest.java
new file mode 100644
index 0000000..5503451
--- /dev/null
+++ b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/NegativeTest.java
@@ -0,0 +1,644 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2002-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package com.sleepycat.persist.test;
+
+import static com.sleepycat.persist.model.Relationship.ONE_TO_MANY;
+import static com.sleepycat.persist.model.Relationship.ONE_TO_ONE;
+import static com.sleepycat.persist.model.DeleteAction.NULLIFY;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import junit.framework.Test;
+
+import com.sleepycat.db.DatabaseException;
+import com.sleepycat.persist.EntityStore;
+import com.sleepycat.persist.PrimaryIndex;
+import com.sleepycat.persist.StoreConfig;
+import com.sleepycat.persist.model.AnnotationModel;
+import com.sleepycat.persist.model.Entity;
+import com.sleepycat.persist.model.KeyField;
+import com.sleepycat.persist.model.Persistent;
+import com.sleepycat.persist.model.PersistentProxy;
+import com.sleepycat.persist.model.PrimaryKey;
+import com.sleepycat.persist.model.SecondaryKey;
+import com.sleepycat.util.test.TxnTestCase;
+
+/**
+ * Negative tests.
+ *
+ * @author Mark Hayes
+ */
+public class NegativeTest extends TxnTestCase {
+
+ static protected Class<?> testClass = NegativeTest.class;
+
+ public static Test suite() {
+ return txnTestSuite(testClass, null, null);
+ }
+
+ private EntityStore store;
+
+ private void open()
+ throws DatabaseException {
+
+ open(null);
+ }
+
+ private void open(Class<ProxyExtendsEntity> clsToRegister)
+ throws DatabaseException {
+
+ StoreConfig config = new StoreConfig();
+ config.setAllowCreate(envConfig.getAllowCreate());
+ config.setTransactional(envConfig.getTransactional());
+
+ if (clsToRegister != null) {
+ AnnotationModel model = new AnnotationModel();
+ model.registerClass(clsToRegister);
+ config.setModel(model);
+ }
+
+ store = new EntityStore(env, "test", config);
+ }
+
+ private void close()
+ throws DatabaseException {
+
+ store.close();
+ store = null;
+ }
+
+ @Override
+ public void setUp()
+ throws Exception {
+
+ super.setUp();
+ }
+
+ @Override
+ public void tearDown()
+ throws Exception {
+
+ if (store != null) {
+ try {
+ store.close();
+ } catch (Throwable e) {
+ System.out.println("tearDown: " + e);
+ }
+ store = null;
+ }
+ super.tearDown();
+ }
+
+ public void testBadKeyClass1()
+ throws DatabaseException {
+
+ open();
+ try {
+ store.getPrimaryIndex(BadKeyClass1.class, UseBadKeyClass1.class);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ assertTrue(expected.getMessage().indexOf("@KeyField") >= 0);
+ }
+ close();
+ }
+
+ /** Missing @KeyField in composite key class. */
+ @Persistent
+ static class BadKeyClass1 {
+
+ private int f1;
+ }
+
+ @Entity
+ static class UseBadKeyClass1 {
+
+ @PrimaryKey
+ private BadKeyClass1 f1 = new BadKeyClass1();
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ private BadKeyClass1 f2 = new BadKeyClass1();
+ }
+
+ public void testBadSequenceKeys()
+ throws DatabaseException {
+
+ open();
+ try {
+ store.getPrimaryIndex(Boolean.class, BadSequenceKeyEntity1.class);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ assertTrue(expected.getMessage().indexOf
+ ("Type not allowed for sequence") >= 0);
+ }
+ try {
+ store.getPrimaryIndex(BadSequenceKeyEntity2.Key.class,
+ BadSequenceKeyEntity2.class);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ assertTrue(expected.getMessage().indexOf
+ ("Type not allowed for sequence") >= 0);
+ }
+ try {
+ store.getPrimaryIndex(BadSequenceKeyEntity3.Key.class,
+ BadSequenceKeyEntity3.class);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ assertTrue(expected.getMessage().indexOf
+ ("A composite key class used with a sequence may contain " +
+ "only a single integer key field")>= 0);
+ }
+ close();
+ }
+
+ /** Boolean not allowed for sequence key. */
+ @Entity
+ static class BadSequenceKeyEntity1 {
+
+ @PrimaryKey(sequence="X")
+ private boolean key;
+ }
+
+ /** Composite key with non-integer field not allowed for sequence key. */
+ @Entity
+ static class BadSequenceKeyEntity2 {
+
+ @PrimaryKey(sequence="X")
+ private Key key;
+
+ @Persistent
+ static class Key {
+ @KeyField(1)
+ boolean key;
+ }
+ }
+
+ /** Composite key with multiple key fields not allowed for sequence key. */
+ @Entity
+ static class BadSequenceKeyEntity3 {
+
+ @PrimaryKey(sequence="X")
+ private Key key;
+
+ @Persistent
+ static class Key {
+ @KeyField(1)
+ int key;
+ @KeyField(2)
+ int key2;
+ }
+ }
+
+ /**
+ * A proxied object may not current contain a field that references the
+ * parent proxy. [#15815]
+ */
+ public void testProxyNestedRef()
+ throws DatabaseException {
+
+ open();
+ PrimaryIndex<Integer,ProxyNestedRef> index = store.getPrimaryIndex
+ (Integer.class, ProxyNestedRef.class);
+ ProxyNestedRef entity = new ProxyNestedRef();
+ entity.list.add(entity.list);
+ try {
+ index.put(entity);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ assertTrue(expected.getMessage().indexOf
+ ("Cannot embed a reference to a proxied object") >= 0);
+ }
+ close();
+ }
+
+ @Entity
+ static class ProxyNestedRef {
+
+ @PrimaryKey
+ private int key;
+
+ ArrayList<Object> list = new ArrayList<Object>();
+ }
+
+ /**
+ * Disallow primary keys on entity subclasses. [#15757]
+ */
+ public void testEntitySubclassWithPrimaryKey()
+ throws DatabaseException {
+
+ open();
+ PrimaryIndex<Integer,EntitySuperClass> index = store.getPrimaryIndex
+ (Integer.class, EntitySuperClass.class);
+ EntitySuperClass e1 = new EntitySuperClass(1, "one");
+ index.put(e1);
+ assertEquals(e1, index.get(1));
+ EntitySubClass e2 = new EntitySubClass(2, "two", "foo", 9);
+ try {
+ index.put(e2);
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains
+ ("PrimaryKey may not appear on an Entity subclass"));
+ }
+ assertEquals(e1, index.get(1));
+ close();
+ }
+
+ @Entity
+ static class EntitySuperClass {
+
+ @PrimaryKey
+ private int x;
+
+ private String y;
+
+ EntitySuperClass(int x, String y) {
+ assert y != null;
+ this.x = x;
+ this.y = y;
+ }
+
+ private EntitySuperClass() {}
+
+ @Override
+ public String toString() {
+ return "x=" + x + " y=" + y;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof EntitySuperClass) {
+ EntitySuperClass o = (EntitySuperClass) other;
+ return x == o.x && y.equals(o.y);
+ } else {
+ return false;
+ }
+ }
+ }
+
+ @Persistent
+ static class EntitySubClass extends EntitySuperClass {
+
+ @PrimaryKey
+ private String foo;
+
+ private int z;
+
+ EntitySubClass(int x, String y, String foo, int z) {
+ super(x, y);
+ assert foo != null;
+ this.foo = foo;
+ this.z = z;
+ }
+
+ private EntitySubClass() {}
+
+ @Override
+ public String toString() {
+ return super.toString() + " z=" + z;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof EntitySubClass) {
+ EntitySubClass o = (EntitySubClass) other;
+ return super.equals(o) && z == o.z;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Disallow embedded entity classes and subclasses. [#16077]
+ */
+ public void testEmbeddedEntity()
+ throws DatabaseException {
+
+ open();
+ PrimaryIndex<Integer,EmbeddingEntity> index = store.getPrimaryIndex
+ (Integer.class, EmbeddingEntity.class);
+ EmbeddingEntity e1 = new EmbeddingEntity(1, null);
+ index.put(e1);
+ assertEquals(e1, index.get(1));
+
+ EmbeddingEntity e2 =
+ new EmbeddingEntity(2, new EntitySuperClass(2, "two"));
+ try {
+ index.put(e2);
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains
+ ("References to entities are not allowed"));
+ }
+
+ EmbeddingEntity e3 = new EmbeddingEntity
+ (3, new EmbeddedEntitySubClass(3, "three", "foo", 9));
+ try {
+ index.put(e3);
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.toString(), e.getMessage().contains
+ ("References to entities are not allowed"));
+ }
+
+ assertEquals(e1, index.get(1));
+ close();
+ }
+
+ @Entity
+ static class EmbeddingEntity {
+
+ @PrimaryKey
+ private int x;
+
+ private EntitySuperClass y;
+
+ EmbeddingEntity(int x, EntitySuperClass y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ private EmbeddingEntity() {}
+
+ @Override
+ public String toString() {
+ return "x=" + x + " y=" + y;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof EmbeddingEntity) {
+ EmbeddingEntity o = (EmbeddingEntity) other;
+ return x == o.x &&
+ ((y == null) ? (o.y == null) : y.equals(o.y));
+ } else {
+ return false;
+ }
+ }
+ }
+
+ @Persistent
+ static class EmbeddedEntitySubClass extends EntitySuperClass {
+
+ private String foo;
+
+ private int z;
+
+ EmbeddedEntitySubClass(int x, String y, String foo, int z) {
+ super(x, y);
+ assert foo != null;
+ this.foo = foo;
+ this.z = z;
+ }
+
+ private EmbeddedEntitySubClass() {}
+
+ @Override
+ public String toString() {
+ return super.toString() + " z=" + z;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof EmbeddedEntitySubClass) {
+ EmbeddedEntitySubClass o = (EmbeddedEntitySubClass) other;
+ return super.equals(o) && z == o.z;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Disallow SecondaryKey collection with no type parameter. [#15950]
+ */
+ public void testTypelessKeyCollection()
+ throws DatabaseException {
+
+ open();
+ try {
+ store.getPrimaryIndex
+ (Integer.class, TypelessKeyCollectionEntity.class);
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.toString(), e.getMessage().contains
+ ("Collection typed secondary key field must have a " +
+ "single generic type argument and a wildcard or type " +
+ "bound is not allowed"));
+ }
+ close();
+ }
+
+ @Entity
+ static class TypelessKeyCollectionEntity {
+
+ @PrimaryKey
+ private int x;
+
+ @SecondaryKey(relate=ONE_TO_MANY)
+ private Collection keys = new ArrayList();
+
+ TypelessKeyCollectionEntity(int x) {
+ this.x = x;
+ }
+
+ private TypelessKeyCollectionEntity() {}
+ }
+
+ /**
+ * Disallow a persistent proxy that extends an entity. [#15950]
+ */
+ public void testProxyEntity()
+ throws DatabaseException {
+
+ try {
+ open(ProxyExtendsEntity.class);
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.toString(), e.getMessage().contains
+ ("A proxy may not be an entity"));
+ }
+ }
+
+ @Persistent(proxyFor=BigDecimal.class)
+ static class ProxyExtendsEntity
+ extends EntitySuperClass
+ implements PersistentProxy<BigDecimal> {
+
+ private String rep;
+
+ public BigDecimal convertProxy() {
+ return new BigDecimal(rep);
+ }
+
+ public void initializeProxy(BigDecimal o) {
+ rep = o.toString();
+ }
+ }
+
+ /**
+ * Wrapper type not allowed for nullified foreign key.
+ */
+ public void testBadNullifyKey()
+ throws DatabaseException {
+
+ open();
+ try {
+ store.getPrimaryIndex(Integer.class, BadNullifyKeyEntity1.class);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ assertTrue(expected.getMessage().indexOf
+ ("NULLIFY may not be used with primitive fields") >= 0);
+ }
+ close();
+ }
+
+ @Entity
+ static class BadNullifyKeyEntity1 {
+
+ @PrimaryKey
+ private int key;
+
+ @SecondaryKey(relate=ONE_TO_ONE,
+ relatedEntity=BadNullifyKeyEntity2.class,
+ onRelatedEntityDelete=NULLIFY)
+ private int secKey; // Should be Integer, not int.
+ }
+
+ @Entity
+ static class BadNullifyKeyEntity2 {
+
+ @PrimaryKey
+ private int key;
+ }
+
+ /**
+ * @Persistent not allowed on an enum.
+ */
+ public void testPersistentEnum()
+ throws DatabaseException {
+
+ open();
+ try {
+ store.getPrimaryIndex(Integer.class, PersistentEnumEntity.class);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ assertTrue(expected.getMessage().indexOf
+ ("not allowed for enum, interface, or primitive") >= 0);
+ }
+ close();
+ }
+
+ @Entity
+ static class PersistentEnumEntity {
+
+ @PrimaryKey
+ private int key;
+
+ @Persistent
+ enum MyEnum {X, Y, Z};
+
+ MyEnum f1;
+ }
+
+ /**
+ * Disallow a reference to an interface marked @Persistent.
+ */
+ public void testPersistentInterface()
+ throws DatabaseException {
+
+ open();
+ try {
+ store.getPrimaryIndex(Integer.class,
+ PersistentInterfaceEntity1.class);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ assertTrue(expected.getMessage().indexOf
+ ("not allowed for enum, interface, or primitive") >= 0);
+ }
+ close();
+ }
+
+ @Entity
+ static class PersistentInterfaceEntity1 {
+
+ @PrimaryKey
+ private int key;
+
+ @SecondaryKey(relate=ONE_TO_ONE,
+ relatedEntity=PersistentInterfaceEntity2.class)
+ private int secKey; // Should be Integer, not int.
+ }
+
+ @Persistent
+ interface PersistentInterfaceEntity2 {
+ }
+
+ /**
+ * Disallow reference to @Persistent inner class.
+ */
+ public void testPersistentInnerClass()
+ throws DatabaseException {
+
+ open();
+ try {
+ store.getPrimaryIndex(Integer.class,
+ PersistentInnerClassEntity1.class);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ assertTrue(expected.getMessage().indexOf
+ ("Inner classes not allowed") >= 0);
+ }
+ close();
+ }
+
+ @Entity
+ static class PersistentInnerClassEntity1 {
+
+ @PrimaryKey
+ private int key;
+
+ private PersistentInnerClass f;
+ }
+
+ /* An inner (non-static) class is illegal. */
+ @Persistent
+ class PersistentInnerClass {
+
+ private int x;
+ }
+
+ /**
+ * Disallow @Entity inner class.
+ */
+ public void testEntityInnerClass()
+ throws DatabaseException {
+
+ open();
+ try {
+ store.getPrimaryIndex(Integer.class,
+ EntityInnerClassEntity.class);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ assertTrue(expected.getMessage().indexOf
+ ("Inner classes not allowed") >= 0);
+ }
+ close();
+ }
+
+ /* An inner (non-static) class is illegal. */
+ @Entity
+ class EntityInnerClassEntity {
+
+ @PrimaryKey
+ private int key;
+ }
+}
diff --git a/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/OperationTest.java b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/OperationTest.java
new file mode 100644
index 0000000..4fc81fc
--- /dev/null
+++ b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/OperationTest.java
@@ -0,0 +1,1552 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2002-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package com.sleepycat.persist.test;
+
+import static com.sleepycat.persist.model.DeleteAction.CASCADE;
+import static com.sleepycat.persist.model.DeleteAction.NULLIFY;
+import static com.sleepycat.persist.model.Relationship.MANY_TO_MANY;
+import static com.sleepycat.persist.model.Relationship.MANY_TO_ONE;
+import static com.sleepycat.persist.model.Relationship.ONE_TO_MANY;
+import static com.sleepycat.persist.model.Relationship.ONE_TO_ONE;
+
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import junit.framework.Test;
+
+import com.sleepycat.compat.DbCompat;
+import com.sleepycat.db.Database;
+import com.sleepycat.db.DatabaseConfig;
+import com.sleepycat.db.DatabaseException;
+import com.sleepycat.db.StatsConfig;
+import com.sleepycat.db.Transaction;
+import com.sleepycat.persist.EntityCursor;
+import com.sleepycat.persist.EntityIndex;
+import com.sleepycat.persist.EntityStore;
+import com.sleepycat.persist.PrimaryIndex;
+import com.sleepycat.persist.SecondaryIndex;
+import com.sleepycat.persist.StoreConfig;
+import com.sleepycat.persist.impl.Store;
+import com.sleepycat.persist.model.Entity;
+import com.sleepycat.persist.model.KeyField;
+import com.sleepycat.persist.model.NotPersistent;
+import com.sleepycat.persist.model.NotTransient;
+import com.sleepycat.persist.model.Persistent;
+import com.sleepycat.persist.model.PrimaryKey;
+import com.sleepycat.persist.model.SecondaryKey;
+import com.sleepycat.persist.raw.RawStore;
+import com.sleepycat.util.test.TxnTestCase;
+
+/**
+ * Tests misc store and index operations that are not tested by IndexTest.
+ *
+ * @author Mark Hayes
+ */
+public class OperationTest extends TxnTestCase {
+
+ private static final String STORE_NAME = "test";
+
+ static protected Class<?> testClass = OperationTest.class;
+
+ public static Test suite() {
+ return txnTestSuite(testClass, null, null);
+ }
+
+ private EntityStore store;
+
+ private void openReadOnly()
+ throws DatabaseException {
+
+ StoreConfig config = new StoreConfig();
+ config.setReadOnly(true);
+ open(config);
+ }
+
+ private void open()
+ throws DatabaseException {
+
+ open((Class) null);
+ }
+
+ private void open(Class clsToRegister)
+ throws DatabaseException {
+
+ StoreConfig config = new StoreConfig();
+ config.setAllowCreate(envConfig.getAllowCreate());
+ if (clsToRegister != null) {
+ com.sleepycat.persist.model.EntityModel model =
+ new com.sleepycat.persist.model.AnnotationModel();
+ model.registerClass(clsToRegister);
+ config.setModel(model);
+ }
+ open(config);
+ }
+
+ private void open(StoreConfig config)
+ throws DatabaseException {
+
+ config.setTransactional(envConfig.getTransactional());
+ store = new EntityStore(env, STORE_NAME, config);
+ }
+
+ private void close()
+ throws DatabaseException {
+
+ store.close();
+ store = null;
+ }
+
+ @Override
+ public void setUp()
+ throws Exception {
+
+ super.setUp();
+ }
+
+ /**
+ * The store must be closed before closing the environment.
+ */
+ @Override
+ public void tearDown()
+ throws Exception {
+
+ try {
+ if (store != null) {
+ store.close();
+ }
+ } catch (Throwable e) {
+ System.out.println("During tearDown: " + e);
+ }
+ store = null;
+ super.tearDown();
+ }
+
+ public void testReadOnly()
+ throws DatabaseException {
+
+ open();
+ PrimaryIndex<Integer,SharedSequenceEntity1> priIndex =
+ store.getPrimaryIndex(Integer.class, SharedSequenceEntity1.class);
+ Transaction txn = txnBegin();
+ SharedSequenceEntity1 e = new SharedSequenceEntity1();
+ priIndex.put(txn, e);
+ assertEquals(1, e.key);
+ txnCommit(txn);
+ close();
+
+ /*
+ * Check that we can open the store read-only and read the records
+ * written above.
+ */
+ openReadOnly();
+ priIndex =
+ store.getPrimaryIndex(Integer.class, SharedSequenceEntity1.class);
+ e = priIndex.get(1);
+ assertNotNull(e);
+ close();
+ }
+
+
+
+ public void testUninitializedCursor()
+ throws DatabaseException {
+
+ open();
+
+ PrimaryIndex<Integer,MyEntity> priIndex =
+ store.getPrimaryIndex(Integer.class, MyEntity.class);
+
+ Transaction txn = txnBeginCursor();
+
+ MyEntity e = new MyEntity();
+ e.priKey = 1;
+ e.secKey = 1;
+ priIndex.put(txn, e);
+
+ EntityCursor<MyEntity> entities = priIndex.entities(txn, null);
+ try {
+ entities.nextDup();
+ fail();
+ } catch (IllegalStateException expected) {}
+ try {
+ entities.prevDup();
+ fail();
+ } catch (IllegalStateException expected) {}
+ try {
+ entities.current();
+ fail();
+ } catch (IllegalStateException expected) {}
+ try {
+ entities.delete();
+ fail();
+ } catch (IllegalStateException expected) {}
+ try {
+ entities.update(e);
+ fail();
+ } catch (IllegalStateException expected) {}
+ try {
+ entities.count();
+ fail();
+ } catch (IllegalStateException expected) {}
+
+ entities.close();
+ txnCommit(txn);
+ close();
+ }
+
+ public void testCursorCount()
+ throws DatabaseException {
+
+ open();
+
+ PrimaryIndex<Integer,MyEntity> priIndex =
+ store.getPrimaryIndex(Integer.class, MyEntity.class);
+
+ SecondaryIndex<Integer,Integer,MyEntity> secIndex =
+ store.getSecondaryIndex(priIndex, Integer.class, "secKey");
+
+ Transaction txn = txnBeginCursor();
+
+ MyEntity e = new MyEntity();
+ e.priKey = 1;
+ e.secKey = 1;
+ priIndex.put(txn, e);
+
+ EntityCursor<MyEntity> cursor = secIndex.entities(txn, null);
+ cursor.next();
+ assertEquals(1, cursor.count());
+ cursor.close();
+
+ e.priKey = 2;
+ priIndex.put(txn, e);
+ cursor = secIndex.entities(txn, null);
+ cursor.next();
+ assertEquals(2, cursor.count());
+ cursor.close();
+
+ txnCommit(txn);
+ close();
+ }
+
+ public void testCursorUpdate()
+ throws DatabaseException {
+
+ open();
+
+ PrimaryIndex<Integer,MyEntity> priIndex =
+ store.getPrimaryIndex(Integer.class, MyEntity.class);
+
+ SecondaryIndex<Integer,Integer,MyEntity> secIndex =
+ store.getSecondaryIndex(priIndex, Integer.class, "secKey");
+
+ Transaction txn = txnBeginCursor();
+
+ Integer k;
+ MyEntity e = new MyEntity();
+ e.priKey = 1;
+ e.secKey = 2;
+ priIndex.put(txn, e);
+
+ /* update() with primary entity cursor. */
+ EntityCursor<MyEntity> entities = priIndex.entities(txn, null);
+ e = entities.next();
+ assertNotNull(e);
+ assertEquals(1, e.priKey);
+ assertEquals(Integer.valueOf(2), e.secKey);
+ e.secKey = null;
+ assertTrue(entities.update(e));
+ e = entities.current();
+ assertNotNull(e);
+ assertEquals(1, e.priKey);
+ assertEquals(null, e.secKey);
+ e.secKey = 3;
+ assertTrue(entities.update(e));
+ e = entities.current();
+ assertNotNull(e);
+ assertEquals(1, e.priKey);
+ assertEquals(Integer.valueOf(3), e.secKey);
+ entities.close();
+
+ /* update() with primary keys cursor. */
+ EntityCursor<Integer> keys = priIndex.keys(txn, null);
+ k = keys.next();
+ assertNotNull(k);
+ assertEquals(Integer.valueOf(1), k);
+ try {
+ keys.update(2);
+ fail();
+ } catch (UnsupportedOperationException expected) {
+ }
+ keys.close();
+
+ /* update() with secondary entity cursor. */
+ entities = secIndex.entities(txn, null);
+ e = entities.next();
+ assertNotNull(e);
+ assertEquals(1, e.priKey);
+ assertEquals(Integer.valueOf(3), e.secKey);
+ try {
+ entities.update(e);
+ fail();
+ } catch (UnsupportedOperationException expected) {
+ } catch (IllegalArgumentException expectedForDbCore) {
+ }
+ entities.close();
+
+ /* update() with secondary keys cursor. */
+ keys = secIndex.keys(txn, null);
+ k = keys.next();
+ assertNotNull(k);
+ assertEquals(Integer.valueOf(3), k);
+ try {
+ keys.update(k);
+ fail();
+ } catch (UnsupportedOperationException expected) {
+ }
+ keys.close();
+
+ txnCommit(txn);
+ close();
+ }
+
+ public void testCursorDelete()
+ throws DatabaseException {
+
+ open();
+
+ PrimaryIndex<Integer,MyEntity> priIndex =
+ store.getPrimaryIndex(Integer.class, MyEntity.class);
+
+ SecondaryIndex<Integer,Integer,MyEntity> secIndex =
+ store.getSecondaryIndex(priIndex, Integer.class, "secKey");
+
+ Transaction txn = txnBeginCursor();
+
+ /* delete() with primary and secondary entities cursor. */
+
+ for (EntityIndex index : new EntityIndex[] { priIndex, secIndex }) {
+
+ MyEntity e = new MyEntity();
+ e.priKey = 1;
+ e.secKey = 1;
+ priIndex.put(txn, e);
+ e.priKey = 2;
+ priIndex.put(txn, e);
+
+ EntityCursor<MyEntity> cursor = index.entities(txn, null);
+
+ e = cursor.next();
+ assertNotNull(e);
+ assertEquals(1, e.priKey);
+ e = cursor.current();
+ assertNotNull(e);
+ assertEquals(1, e.priKey);
+ assertTrue(cursor.delete());
+ assertTrue(!cursor.delete());
+ assertNull(cursor.current());
+
+ e = cursor.next();
+ assertNotNull(e);
+ assertEquals(2, e.priKey);
+ e = cursor.current();
+ assertNotNull(e);
+ assertEquals(2, e.priKey);
+ assertTrue(cursor.delete());
+ assertTrue(!cursor.delete());
+ assertNull(cursor.current());
+
+ e = cursor.next();
+ assertNull(e);
+
+ if (index == priIndex) {
+ e = new MyEntity();
+ e.priKey = 2;
+ e.secKey = 1;
+ assertTrue(!cursor.update(e));
+ }
+
+ cursor.close();
+ }
+
+ /* delete() with primary and secondary keys cursor. */
+
+ for (EntityIndex index : new EntityIndex[] { priIndex, secIndex }) {
+
+ MyEntity e = new MyEntity();
+ e.priKey = 1;
+ e.secKey = 1;
+ priIndex.put(txn, e);
+ e.priKey = 2;
+ priIndex.put(txn, e);
+
+ EntityCursor<Integer> cursor = index.keys(txn, null);
+
+ Integer k = cursor.next();
+ assertNotNull(k);
+ assertEquals(1, k.intValue());
+ k = cursor.current();
+ assertNotNull(k);
+ assertEquals(1, k.intValue());
+ assertTrue(cursor.delete());
+ assertTrue(!cursor.delete());
+ assertNull(cursor.current());
+
+ int expectKey = (index == priIndex) ? 2 : 1;
+ k = cursor.next();
+ assertNotNull(k);
+ assertEquals(expectKey, k.intValue());
+ k = cursor.current();
+ assertNotNull(k);
+ assertEquals(expectKey, k.intValue());
+ assertTrue(cursor.delete());
+ assertTrue(!cursor.delete());
+ assertNull(cursor.current());
+
+ k = cursor.next();
+ assertNull(k);
+
+ cursor.close();
+ }
+
+ txnCommit(txn);
+ close();
+ }
+
+ public void testDeleteFromSubIndex()
+ throws DatabaseException {
+
+ open();
+
+ PrimaryIndex<Integer,MyEntity> priIndex =
+ store.getPrimaryIndex(Integer.class, MyEntity.class);
+
+ SecondaryIndex<Integer,Integer,MyEntity> secIndex =
+ store.getSecondaryIndex(priIndex, Integer.class, "secKey");
+
+ Transaction txn = txnBegin();
+ MyEntity e = new MyEntity();
+ e.secKey = 1;
+ e.priKey = 1;
+ priIndex.put(txn, e);
+ e.priKey = 2;
+ priIndex.put(txn, e);
+ e.priKey = 3;
+ priIndex.put(txn, e);
+ e.priKey = 4;
+ priIndex.put(txn, e);
+ txnCommit(txn);
+
+ EntityIndex<Integer,MyEntity> subIndex = secIndex.subIndex(1);
+ txn = txnBeginCursor();
+ e = subIndex.get(txn, 1, null);
+ assertEquals(1, e.priKey);
+ assertEquals(Integer.valueOf(1), e.secKey);
+ e = subIndex.get(txn, 2, null);
+ assertEquals(2, e.priKey);
+ assertEquals(Integer.valueOf(1), e.secKey);
+ e = subIndex.get(txn, 3, null);
+ assertEquals(3, e.priKey);
+ assertEquals(Integer.valueOf(1), e.secKey);
+ e = subIndex.get(txn, 5, null);
+ assertNull(e);
+
+ boolean deleted = subIndex.delete(txn, 1);
+ assertTrue(deleted);
+ assertNull(subIndex.get(txn, 1, null));
+ assertNotNull(subIndex.get(txn, 2, null));
+
+ EntityCursor<MyEntity> cursor = subIndex.entities(txn, null);
+ boolean saw4 = false;
+ for (MyEntity e2 = cursor.first(); e2 != null; e2 = cursor.next()) {
+ if (e2.priKey == 3) {
+ cursor.delete();
+ }
+ if (e2.priKey == 4) {
+ saw4 = true;
+ }
+ }
+ cursor.close();
+ assertTrue(saw4);
+ assertNull(subIndex.get(txn, 1, null));
+ assertNull(subIndex.get(txn, 3, null));
+ assertNotNull(subIndex.get(txn, 2, null));
+ assertNotNull(subIndex.get(txn, 4, null));
+
+ txnCommit(txn);
+ close();
+ }
+
+ @Entity
+ static class MyEntity {
+
+ @PrimaryKey
+ private int priKey;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private Integer secKey;
+
+ private MyEntity() {}
+ }
+
+ public void testSharedSequence()
+ throws DatabaseException {
+
+ open();
+
+ PrimaryIndex<Integer,SharedSequenceEntity1> priIndex1 =
+ store.getPrimaryIndex(Integer.class, SharedSequenceEntity1.class);
+
+ PrimaryIndex<Integer,SharedSequenceEntity2> priIndex2 =
+ store.getPrimaryIndex(Integer.class, SharedSequenceEntity2.class);
+
+ Transaction txn = txnBegin();
+ SharedSequenceEntity1 e1 = new SharedSequenceEntity1();
+ SharedSequenceEntity2 e2 = new SharedSequenceEntity2();
+ priIndex1.put(txn, e1);
+ assertEquals(1, e1.key);
+ priIndex2.putNoOverwrite(txn, e2);
+ assertEquals(Integer.valueOf(2), e2.key);
+ e1.key = 0;
+ priIndex1.putNoOverwrite(txn, e1);
+ assertEquals(3, e1.key);
+ e2.key = null;
+ priIndex2.put(txn, e2);
+ assertEquals(Integer.valueOf(4), e2.key);
+ txnCommit(txn);
+
+ close();
+ }
+
+ @Entity
+ static class SharedSequenceEntity1 {
+
+ @PrimaryKey(sequence="shared")
+ private int key;
+ }
+
+ @Entity
+ static class SharedSequenceEntity2 {
+
+ @PrimaryKey(sequence="shared")
+ private Integer key;
+ }
+
+ public void testSeparateSequence()
+ throws DatabaseException {
+
+ open();
+
+ PrimaryIndex<Integer,SeparateSequenceEntity1> priIndex1 =
+ store.getPrimaryIndex
+ (Integer.class, SeparateSequenceEntity1.class);
+
+ PrimaryIndex<Integer,SeparateSequenceEntity2> priIndex2 =
+ store.getPrimaryIndex
+ (Integer.class, SeparateSequenceEntity2.class);
+
+ Transaction txn = txnBegin();
+ SeparateSequenceEntity1 e1 = new SeparateSequenceEntity1();
+ SeparateSequenceEntity2 e2 = new SeparateSequenceEntity2();
+ priIndex1.put(txn, e1);
+ assertEquals(1, e1.key);
+ priIndex2.putNoOverwrite(txn, e2);
+ assertEquals(Integer.valueOf(1), e2.key);
+ e1.key = 0;
+ priIndex1.putNoOverwrite(txn, e1);
+ assertEquals(2, e1.key);
+ e2.key = null;
+ priIndex2.put(txn, e2);
+ assertEquals(Integer.valueOf(2), e2.key);
+ txnCommit(txn);
+
+ close();
+ }
+
+ @Entity
+ static class SeparateSequenceEntity1 {
+
+ @PrimaryKey(sequence="seq1")
+ private int key;
+ }
+
+ @Entity
+ static class SeparateSequenceEntity2 {
+
+ @PrimaryKey(sequence="seq2")
+ private Integer key;
+ }
+
+ public void testCompositeSequence()
+ throws DatabaseException {
+
+ open();
+
+ PrimaryIndex<CompositeSequenceEntity1.Key,CompositeSequenceEntity1>
+ priIndex1 =
+ store.getPrimaryIndex
+ (CompositeSequenceEntity1.Key.class,
+ CompositeSequenceEntity1.class);
+
+ PrimaryIndex<CompositeSequenceEntity2.Key,CompositeSequenceEntity2>
+ priIndex2 =
+ store.getPrimaryIndex
+ (CompositeSequenceEntity2.Key.class,
+ CompositeSequenceEntity2.class);
+
+ Transaction txn = txnBegin();
+ CompositeSequenceEntity1 e1 = new CompositeSequenceEntity1();
+ CompositeSequenceEntity2 e2 = new CompositeSequenceEntity2();
+ priIndex1.put(txn, e1);
+ assertEquals(1, e1.key.key);
+ priIndex2.putNoOverwrite(txn, e2);
+ assertEquals(Integer.valueOf(1), e2.key.key);
+ e1.key = null;
+ priIndex1.putNoOverwrite(txn, e1);
+ assertEquals(2, e1.key.key);
+ e2.key = null;
+ priIndex2.put(txn, e2);
+ assertEquals(Integer.valueOf(2), e2.key.key);
+ txnCommit(txn);
+
+ EntityCursor<CompositeSequenceEntity1> c1 = priIndex1.entities();
+ e1 = c1.next();
+ assertEquals(2, e1.key.key);
+ e1 = c1.next();
+ assertEquals(1, e1.key.key);
+ e1 = c1.next();
+ assertNull(e1);
+ c1.close();
+
+ EntityCursor<CompositeSequenceEntity2> c2 = priIndex2.entities();
+ e2 = c2.next();
+ assertEquals(Integer.valueOf(2), e2.key.key);
+ e2 = c2.next();
+ assertEquals(Integer.valueOf(1), e2.key.key);
+ e2 = c2.next();
+ assertNull(e2);
+ c2.close();
+
+ close();
+ }
+
+ @Entity
+ static class CompositeSequenceEntity1 {
+
+ @Persistent
+ static class Key implements Comparable<Key> {
+
+ @KeyField(1)
+ private int key;
+
+ public int compareTo(Key o) {
+ /* Reverse the natural order. */
+ return o.key - key;
+ }
+ }
+
+ @PrimaryKey(sequence="seq1")
+ private Key key;
+ }
+
+ /**
+ * Same as CompositeSequenceEntity1 but using Integer rather than int for
+ * the key type.
+ */
+ @Entity
+ static class CompositeSequenceEntity2 {
+
+ @Persistent
+ static class Key implements Comparable<Key> {
+
+ @KeyField(1)
+ private Integer key;
+
+ public int compareTo(Key o) {
+ /* Reverse the natural order. */
+ return o.key - key;
+ }
+ }
+
+ @PrimaryKey(sequence="seq2")
+ private Key key;
+ }
+
+ /**
+ * When opening read-only, secondaries are not opened when the primary is
+ * opened, causing a different code path to be used for opening
+ * secondaries. For a RawStore in particular, this caused an unreported
+ * NullPointerException in JE 3.0.12. No SR was created because the use
+ * case is very obscure and was discovered by code inspection.
+ */
+ public void testOpenRawStoreReadOnly()
+ throws DatabaseException {
+
+ open();
+ store.getPrimaryIndex(Integer.class, MyEntity.class);
+ close();
+
+ StoreConfig config = new StoreConfig();
+ config.setReadOnly(true);
+ config.setTransactional(envConfig.getTransactional());
+ RawStore rawStore = new RawStore(env, "test", config);
+
+ String clsName = MyEntity.class.getName();
+ rawStore.getSecondaryIndex(clsName, "secKey");
+
+ rawStore.close();
+ }
+
+ /**
+ * When opening an X_TO_MANY secondary that has a persistent key class, the
+ * key class was not recognized as being persistent if it was never before
+ * referenced when getSecondaryIndex was called. This was a bug in JE
+ * 3.0.12, reported on OTN. [#15103]
+ */
+ public void testToManyKeyClass()
+ throws DatabaseException {
+
+ open();
+
+ PrimaryIndex<Integer,ToManyKeyEntity> priIndex =
+ store.getPrimaryIndex(Integer.class, ToManyKeyEntity.class);
+ SecondaryIndex<ToManyKey,Integer,ToManyKeyEntity> secIndex =
+ store.getSecondaryIndex(priIndex, ToManyKey.class, "key2");
+
+ priIndex.put(new ToManyKeyEntity());
+ secIndex.get(new ToManyKey());
+
+ close();
+ }
+
+ /**
+ * Test a fix for a bug where opening a TO_MANY secondary index would fail
+ * fail with "IllegalArgumentException: Wrong secondary key class: ..."
+ * when the store was opened read-only. [#15156]
+ */
+ public void testToManyReadOnly()
+ throws DatabaseException {
+
+ open();
+ PrimaryIndex<Integer,ToManyKeyEntity> priIndex =
+ store.getPrimaryIndex(Integer.class, ToManyKeyEntity.class);
+ priIndex.put(new ToManyKeyEntity());
+ close();
+
+ openReadOnly();
+ priIndex = store.getPrimaryIndex(Integer.class, ToManyKeyEntity.class);
+ SecondaryIndex<ToManyKey,Integer,ToManyKeyEntity> secIndex =
+ store.getSecondaryIndex(priIndex, ToManyKey.class, "key2");
+ secIndex.get(new ToManyKey());
+ close();
+ }
+
+ @Persistent
+ static class ToManyKey {
+
+ @KeyField(1)
+ int value = 99;
+ }
+
+ @Entity
+ static class ToManyKeyEntity {
+
+ @PrimaryKey
+ int key = 88;
+
+ @SecondaryKey(relate=ONE_TO_MANY)
+ Set<ToManyKey> key2;
+
+ ToManyKeyEntity() {
+ key2 = new HashSet<ToManyKey>();
+ key2.add(new ToManyKey());
+ }
+ }
+
+
+
+ /**
+ * When Y is opened and X has a key with relatedEntity=Y.class, X should
+ * be opened automatically. If X is not opened, foreign key constraints
+ * will not be enforced. [#15358]
+ */
+ public void testAutoOpenRelatedEntity()
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,RelatedY> priY;
+ PrimaryIndex<Integer,RelatedX> priX;
+
+ /* Opening X should create (and open) Y and enforce constraints. */
+ open();
+ priX = store.getPrimaryIndex(Integer.class, RelatedX.class);
+ PersistTestUtils.assertDbExists
+ (true, env, STORE_NAME, RelatedY.class.getName(), null);
+ if (isTransactional) {
+ /* Constraint enforcement requires transactions. */
+ try {
+ priX.put(new RelatedX());
+ fail();
+ } catch (DatabaseException e) {
+ assertTrue
+ ("" + e.getMessage(), (e.getMessage().indexOf
+ ("foreign key not allowed: it is not present") >= 0) ||
+ (e.getMessage().indexOf("DB_FOREIGN_CONFLICT") >= 0));
+ }
+ }
+ priY = store.getPrimaryIndex(Integer.class, RelatedY.class);
+ priY.put(new RelatedY());
+ priX.put(new RelatedX());
+ close();
+
+ /* Delete should cascade even when X is not opened explicitly. */
+ open();
+ priY = store.getPrimaryIndex(Integer.class, RelatedY.class);
+ assertEquals(1, priY.count());
+ priY.delete(88);
+ assertEquals(0, priY.count());
+ priX = store.getPrimaryIndex(Integer.class, RelatedX.class);
+ assertEquals(0, priX.count()); /* Failed prior to [#15358] fix. */
+ close();
+ }
+
+ @Entity
+ static class RelatedX {
+
+ @PrimaryKey
+ int key = 99;
+
+ @SecondaryKey(relate=ONE_TO_ONE,
+ relatedEntity=RelatedY.class,
+ onRelatedEntityDelete=CASCADE)
+ int key2 = 88;
+
+ RelatedX() {
+ }
+ }
+
+ @Entity
+ static class RelatedY {
+
+ @PrimaryKey
+ int key = 88;
+
+ RelatedY() {
+ }
+ }
+
+ public void testSecondaryBulkLoad1()
+ throws DatabaseException {
+
+ doSecondaryBulkLoad(true);
+ }
+
+ public void testSecondaryBulkLoad2()
+ throws DatabaseException {
+
+ doSecondaryBulkLoad(false);
+ }
+
+ private void doSecondaryBulkLoad(boolean closeAndOpenNormally)
+ throws DatabaseException {
+
+ PrimaryIndex<Integer,RelatedX> priX;
+ PrimaryIndex<Integer,RelatedY> priY;
+ SecondaryIndex<Integer,Integer,RelatedX> secX;
+
+ /* Open priX with SecondaryBulkLoad=true. */
+ StoreConfig config = new StoreConfig();
+ config.setAllowCreate(true);
+ config.setSecondaryBulkLoad(true);
+ open(config);
+
+ /* Getting priX should not create the secondary index. */
+ priX = store.getPrimaryIndex(Integer.class, RelatedX.class);
+ PersistTestUtils.assertDbExists
+ (false, env, STORE_NAME, RelatedX.class.getName(), "key2");
+
+ /* We can put records that violate the secondary key constraint. */
+ priX.put(new RelatedX());
+
+ if (closeAndOpenNormally) {
+ /* Open normally and attempt to populate the secondary. */
+ close();
+ open();
+ if (isTransactional && DbCompat.POPULATE_ENFORCES_CONSTRAINTS) {
+ /* Constraint enforcement requires transactions. */
+ try {
+ /* Before adding the foreign key, constraint is violated. */
+ priX = store.getPrimaryIndex(Integer.class,
+ RelatedX.class);
+ fail();
+ } catch (DatabaseException e) {
+ assertTrue
+ (e.toString(),
+ e.toString().contains("foreign key not allowed"));
+ }
+ }
+ /* Open priX with SecondaryBulkLoad=true. */
+ close();
+ open(config);
+ /* Add the foreign key to avoid the constraint error. */
+ priY = store.getPrimaryIndex(Integer.class, RelatedY.class);
+ priY.put(new RelatedY());
+ /* Open normally and the secondary will be populated. */
+ close();
+ open();
+ priX = store.getPrimaryIndex(Integer.class, RelatedX.class);
+ PersistTestUtils.assertDbExists
+ (true, env, STORE_NAME, RelatedX.class.getName(), "key2");
+ secX = store.getSecondaryIndex(priX, Integer.class, "key2");
+ } else {
+ /* Get secondary index explicitly and it will be populated. */
+ if (isTransactional && DbCompat.POPULATE_ENFORCES_CONSTRAINTS) {
+ /* Constraint enforcement requires transactions. */
+ try {
+ /* Before adding the foreign key, constraint is violated. */
+ secX = store.getSecondaryIndex(priX, Integer.class,
+ "key2");
+ fail();
+ } catch (DatabaseException e) {
+ assertTrue
+ (e.toString(),
+ e.toString().contains("foreign key not allowed"));
+ }
+ }
+ /* Add the foreign key. */
+ priY = store.getPrimaryIndex(Integer.class, RelatedY.class);
+ priY.put(new RelatedY());
+ secX = store.getSecondaryIndex(priX, Integer.class, "key2");
+ PersistTestUtils.assertDbExists
+ (true, env, STORE_NAME, RelatedX.class.getName(), "key2");
+ }
+
+ RelatedX x = secX.get(88);
+ assertNotNull(x);
+ close();
+ }
+
+ public void testPersistentFields()
+ throws DatabaseException {
+
+ open();
+ PrimaryIndex<Integer, PersistentFields> pri =
+ store.getPrimaryIndex(Integer.class, PersistentFields.class);
+ PersistentFields o1 = new PersistentFields(-1, 1, 2, 3, 4, 5, 6);
+ assertNull(pri.put(o1));
+ PersistentFields o2 = pri.get(-1);
+ assertNotNull(o2);
+ assertEquals(0, o2.transient1);
+ assertEquals(0, o2.transient2);
+ assertEquals(0, o2.transient3);
+ assertEquals(4, o2.persistent1);
+ assertEquals(5, o2.persistent2);
+ assertEquals(6, o2.persistent3);
+ close();
+ }
+
+ @Entity
+ static class PersistentFields {
+
+ @PrimaryKey int key;
+
+ transient int transient1;
+ @NotPersistent int transient2;
+ @NotPersistent transient int transient3;
+
+ int persistent1;
+ @NotTransient int persistent2;
+ @NotTransient transient int persistent3;
+
+ PersistentFields(int k,
+ int t1,
+ int t2,
+ int t3,
+ int p1,
+ int p2,
+ int p3) {
+ key = k;
+ transient1 = t1;
+ transient2 = t2;
+ transient3 = t3;
+ persistent1 = p1;
+ persistent2 = p2;
+ persistent3 = p3;
+ }
+
+ private PersistentFields() {}
+ }
+
+ /**
+ * When a primary or secondary has a persistent key class, the key class
+ * was not recognized as being persistent when getPrimaryConfig,
+ * getSecondaryConfig, or getSubclassIndex was called, if that key class
+ * was not previously referenced. All three cases are tested by calling
+ * getSecondaryConfig. This was a bug in JE 3.3.69, reported on OTN.
+ * [#16407]
+ */
+ public void testKeyClassInitialization()
+ throws DatabaseException {
+
+ open();
+ store.getSecondaryConfig(ToManyKeyEntity.class, "key2");
+ close();
+ }
+
+ public void testKeyName()
+ throws DatabaseException {
+
+ open();
+
+ PrimaryIndex<Long, BookEntity> pri1 =
+ store.getPrimaryIndex(Long.class, BookEntity.class);
+ PrimaryIndex<Long, AuthorEntity> pri2 =
+ store.getPrimaryIndex(Long.class, AuthorEntity.class);
+
+ BookEntity book = new BookEntity();
+ pri1.put(book);
+ AuthorEntity author = new AuthorEntity();
+ author.bookIds.add(book.bookId);
+ pri2.put(author);
+
+ close();
+
+ open();
+ pri1 = store.getPrimaryIndex(Long.class, BookEntity.class);
+ pri2 = store.getPrimaryIndex(Long.class, AuthorEntity.class);
+ book = pri1.get(1L);
+ assertNotNull(book);
+ author = pri2.get(1L);
+ assertNotNull(author);
+ close();
+ }
+
+ @Entity
+ static class AuthorEntity {
+
+ @PrimaryKey(sequence="authorSeq")
+ long authorId;
+
+ @SecondaryKey(relate=MANY_TO_MANY, relatedEntity=BookEntity.class,
+ name="bookId", onRelatedEntityDelete=NULLIFY)
+ Set<Long> bookIds = new HashSet<Long>();
+ }
+
+ @Entity
+ static class BookEntity {
+
+ @PrimaryKey(sequence="bookSeq")
+ long bookId;
+ }
+
+ /**
+ * Checks that we get an appropriate exception when storing an entity
+ * subclass instance, which contains a secondary key, without registering
+ * the subclass up front. [#16399]
+ */
+ public void testPutEntitySubclassWithoutRegisterClass()
+ throws DatabaseException {
+
+ open();
+
+ final PrimaryIndex<Long, Statement> pri =
+ store.getPrimaryIndex(Long.class, Statement.class);
+
+ final Transaction txn = txnBegin();
+ pri.put(txn, new Statement(1));
+ try {
+ pri.put(txn, new ExtendedStatement(2, null));
+ fail();
+ } catch (IllegalArgumentException expected) {
+ assertTrue(expected.toString(), expected.getMessage().contains
+ ("Entity subclasses defining a secondary key must be " +
+ "registered by calling EntityModel.registerClass or " +
+ "EntityStore.getSubclassIndex before storing an instance " +
+ "of the subclass: " + ExtendedStatement.class.getName()));
+ }
+ txnAbort(txn);
+
+ close();
+ }
+
+ /**
+ * Checks that registerClass avoids an exception when storing an entity
+ * subclass instance, which defines a secondary key. [#16399]
+ */
+ public void testPutEntitySubclassWithRegisterClass()
+ throws DatabaseException {
+
+ open(ExtendedStatement.class);
+
+ final PrimaryIndex<Long, Statement> pri =
+ store.getPrimaryIndex(Long.class, Statement.class);
+
+ final Transaction txn = txnBegin();
+ pri.put(txn, new Statement(1));
+ pri.put(txn, new ExtendedStatement(2, "abc"));
+ txnCommit(txn);
+
+ final SecondaryIndex<String, Long, ExtendedStatement> sec =
+ store.getSubclassIndex(pri, ExtendedStatement.class,
+ String.class, "name");
+
+ ExtendedStatement o = sec.get("abc");
+ assertNotNull(o);
+ assertEquals(2, o.id);
+
+ close();
+ }
+
+ /**
+ * Same as testPutEntitySubclassWithRegisterClass but store the first
+ * instance of the subclass after closing and reopening the store,
+ * *without* calling registerClass. This ensures that a single call to
+ * registerClass is sufficient and subsequent use of the store does not
+ * require it. [#16399]
+ */
+ public void testPutEntitySubclassWithRegisterClass2()
+ throws DatabaseException {
+
+ open(ExtendedStatement.class);
+
+ PrimaryIndex<Long, Statement> pri =
+ store.getPrimaryIndex(Long.class, Statement.class);
+
+ Transaction txn = txnBegin();
+ pri.put(txn, new Statement(1));
+ txnCommit(txn);
+
+ close();
+ open();
+
+ pri = store.getPrimaryIndex(Long.class, Statement.class);
+
+ txn = txnBegin();
+ pri.put(txn, new ExtendedStatement(2, "abc"));
+ txnCommit(txn);
+
+ final SecondaryIndex<String, Long, ExtendedStatement> sec =
+ store.getSubclassIndex(pri, ExtendedStatement.class,
+ String.class, "name");
+
+ ExtendedStatement o = sec.get("abc");
+ assertNotNull(o);
+ assertEquals(2, o.id);
+
+ close();
+ }
+
+ /**
+ * Checks that getSubclassIndex can be used instead of registerClass to
+ * avoid an exception when storing an entity subclass instance, which
+ * defines a secondary key. [#16399]
+ */
+ public void testPutEntitySubclassWithGetSubclassIndex()
+ throws DatabaseException {
+
+ open();
+
+ final PrimaryIndex<Long, Statement> pri =
+ store.getPrimaryIndex(Long.class, Statement.class);
+
+ final SecondaryIndex<String, Long, ExtendedStatement> sec =
+ store.getSubclassIndex(pri, ExtendedStatement.class,
+ String.class, "name");
+
+ final Transaction txn = txnBegin();
+ pri.put(txn, new Statement(1));
+ pri.put(txn, new ExtendedStatement(2, "abc"));
+ txnCommit(txn);
+
+ ExtendedStatement o = sec.get("abc");
+ assertNotNull(o);
+ assertEquals(2, o.id);
+
+ close();
+ }
+
+ /**
+ * Same as testPutEntitySubclassWithGetSubclassIndex2 but store the first
+ * instance of the subclass after closing and reopening the store,
+ * *without* calling getSubclassIndex. This ensures that a single call to
+ * getSubclassIndex is sufficient and subsequent use of the store does not
+ * require it. [#16399]
+ */
+ public void testPutEntitySubclassWithGetSubclassIndex2()
+ throws DatabaseException {
+
+ open();
+
+ PrimaryIndex<Long, Statement> pri =
+ store.getPrimaryIndex(Long.class, Statement.class);
+
+ SecondaryIndex<String, Long, ExtendedStatement> sec =
+ store.getSubclassIndex(pri, ExtendedStatement.class,
+ String.class, "name");
+
+ Transaction txn = txnBegin();
+ pri.put(txn, new Statement(1));
+ txnCommit(txn);
+
+ close();
+ open();
+
+ pri = store.getPrimaryIndex(Long.class, Statement.class);
+
+ txn = txnBegin();
+ pri.put(txn, new ExtendedStatement(2, "abc"));
+ txnCommit(txn);
+
+ sec = store.getSubclassIndex(pri, ExtendedStatement.class,
+ String.class, "name");
+
+ ExtendedStatement o = sec.get("abc");
+ assertNotNull(o);
+ assertEquals(2, o.id);
+
+ close();
+ }
+
+ /**
+ * Checks that secondary population occurs only once when an index is
+ * created, not every time it is opened, even when it is empty. This is a
+ * JE-only test because we don't have a portable way to get stats that
+ * indicate whether primary reads were performed. [#16399]
+ */
+
+ @Entity
+ static class Statement {
+
+ @PrimaryKey
+ long id;
+
+ Statement(long id) {
+ this.id = id;
+ }
+
+ private Statement() {}
+ }
+
+ @Persistent
+ static class ExtendedStatement extends Statement {
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ String name;
+
+ ExtendedStatement(long id, String name) {
+ super(id);
+ this.name = name;
+ }
+
+ private ExtendedStatement() {}
+ }
+
+ public void testCustomCompare()
+ throws DatabaseException {
+
+ open();
+
+ PrimaryIndex<ReverseIntKey, CustomCompareEntity>
+ priIndex = store.getPrimaryIndex
+ (ReverseIntKey.class, CustomCompareEntity.class);
+
+ SecondaryIndex<ReverseIntKey, ReverseIntKey, CustomCompareEntity>
+ secIndex1 = store.getSecondaryIndex(priIndex, ReverseIntKey.class,
+ "secKey1");
+
+ SecondaryIndex<ReverseIntKey, ReverseIntKey, CustomCompareEntity>
+ secIndex2 = store.getSecondaryIndex(priIndex, ReverseIntKey.class,
+ "secKey2");
+
+ Transaction txn = txnBegin();
+ for (int i = 1; i <= 5; i += 1) {
+ assertTrue(priIndex.putNoOverwrite(txn,
+ new CustomCompareEntity(i)));
+ }
+ txnCommit(txn);
+
+ txn = txnBeginCursor();
+ EntityCursor<CustomCompareEntity> c = priIndex.entities(txn, null);
+ for (int i = 5; i >= 1; i -= 1) {
+ CustomCompareEntity e = c.next();
+ assertNotNull(e);
+ assertEquals(new ReverseIntKey(i), e.key);
+ }
+ c.close();
+ txnCommit(txn);
+
+ txn = txnBeginCursor();
+ c = secIndex1.entities(txn, null);
+ for (int i = -1; i >= -5; i -= 1) {
+ CustomCompareEntity e = c.next();
+ assertNotNull(e);
+ assertEquals(new ReverseIntKey(-i), e.key);
+ assertEquals(new ReverseIntKey(i), e.secKey1);
+ }
+ c.close();
+ txnCommit(txn);
+
+ txn = txnBeginCursor();
+ c = secIndex2.entities(txn, null);
+ for (int i = -1; i >= -5; i -= 1) {
+ CustomCompareEntity e = c.next();
+ assertNotNull(e);
+ assertEquals(new ReverseIntKey(-i), e.key);
+ assertTrue(e.secKey2.contains(new ReverseIntKey(i)));
+ }
+ c.close();
+ txnCommit(txn);
+
+ close();
+ }
+
+ @Entity
+ static class CustomCompareEntity {
+
+ @PrimaryKey
+ private ReverseIntKey key;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private ReverseIntKey secKey1;
+
+ @SecondaryKey(relate=ONE_TO_MANY)
+ private Set<ReverseIntKey> secKey2 = new HashSet<ReverseIntKey>();
+
+ private CustomCompareEntity() {}
+
+ CustomCompareEntity(int i) {
+ key = new ReverseIntKey(i);
+ secKey1 = new ReverseIntKey(-i);
+ secKey2.add(new ReverseIntKey(-i));
+ }
+ }
+
+ @Persistent
+ static class ReverseIntKey implements Comparable<ReverseIntKey> {
+
+ @KeyField(1)
+ private int key;
+
+ public int compareTo(ReverseIntKey o) {
+ /* Reverse the natural order. */
+ return o.key - key;
+ }
+
+ private ReverseIntKey() {}
+
+ ReverseIntKey(int key) {
+ this.key = key;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return key == ((ReverseIntKey) o).key;
+ }
+
+ @Override
+ public int hashCode() {
+ return key;
+ }
+
+ @Override
+ public String toString() {
+ return "Key = " + key;
+ }
+ }
+
+ /**
+ * Ensures that custom comparators are persisted and work correctly during
+ * recovery. JE recovery uses comparators, so they are serialized and
+ * stored in the DatabaseImpl. They are deserialized during recovery prior
+ * to opening the EntityStore and its format catalog. But the formats are
+ * needed by the comparator, so they are specially created when needed.
+ *
+ * In particular we need to ensure that enum key fields work correctly,
+ * since their formats are not static (like simple type formats are).
+ * [#17140]
+ *
+ * Note that we don't need to actually cause a recovery in order to test
+ * the deserialization and subsequent use of comparators. The JE
+ * DatabaseConfig.setBtreeComparator method serializes and deserializes the
+ * comparator. The comparator is initialized on its first use, just as if
+ * recovery were run.
+ */
+ public void testStoredComparators()
+ throws DatabaseException {
+
+ open();
+
+ PrimaryIndex<StoredComparatorEntity.Key,
+ StoredComparatorEntity> priIndex =
+ store.getPrimaryIndex(StoredComparatorEntity.Key.class,
+ StoredComparatorEntity.class);
+
+ SecondaryIndex<StoredComparatorEntity.MyEnum,
+ StoredComparatorEntity.Key,
+ StoredComparatorEntity> secIndex =
+ store.getSecondaryIndex
+ (priIndex, StoredComparatorEntity.MyEnum.class, "secKey");
+
+ final StoredComparatorEntity.Key[] priKeys =
+ new StoredComparatorEntity.Key[] {
+ new StoredComparatorEntity.Key
+ (StoredComparatorEntity.MyEnum.A, 1,
+ StoredComparatorEntity.MyEnum.A),
+ new StoredComparatorEntity.Key
+ (StoredComparatorEntity.MyEnum.A, 1,
+ StoredComparatorEntity.MyEnum.B),
+ new StoredComparatorEntity.Key
+ (StoredComparatorEntity.MyEnum.A, 2,
+ StoredComparatorEntity.MyEnum.A),
+ new StoredComparatorEntity.Key
+ (StoredComparatorEntity.MyEnum.A, 2,
+ StoredComparatorEntity.MyEnum.B),
+ new StoredComparatorEntity.Key
+ (StoredComparatorEntity.MyEnum.B, 1,
+ StoredComparatorEntity.MyEnum.A),
+ new StoredComparatorEntity.Key
+ (StoredComparatorEntity.MyEnum.B, 1,
+ StoredComparatorEntity.MyEnum.B),
+ new StoredComparatorEntity.Key
+ (StoredComparatorEntity.MyEnum.C, 0,
+ StoredComparatorEntity.MyEnum.C),
+ };
+
+ final StoredComparatorEntity.MyEnum[] secKeys =
+ new StoredComparatorEntity.MyEnum[] {
+ StoredComparatorEntity.MyEnum.C,
+ StoredComparatorEntity.MyEnum.B,
+ StoredComparatorEntity.MyEnum.A,
+ null,
+ StoredComparatorEntity.MyEnum.A,
+ StoredComparatorEntity.MyEnum.B,
+ StoredComparatorEntity.MyEnum.C,
+ };
+
+ assertEquals(priKeys.length, secKeys.length);
+ final int nEntities = priKeys.length;
+
+ Transaction txn = txnBegin();
+ for (int i = 0; i < nEntities; i += 1) {
+ priIndex.put(txn,
+ new StoredComparatorEntity(priKeys[i], secKeys[i]));
+ }
+ txnCommit(txn);
+
+ txn = txnBeginCursor();
+ EntityCursor<StoredComparatorEntity> entities =
+ priIndex.entities(txn, null);
+ for (int i = nEntities - 1; i >= 0; i -= 1) {
+ StoredComparatorEntity e = entities.next();
+ assertNotNull(e);
+ assertEquals(priKeys[i], e.key);
+ assertEquals(secKeys[i], e.secKey);
+ }
+ assertNull(entities.next());
+ entities.close();
+ txnCommit(txn);
+
+ txn = txnBeginCursor();
+ entities = secIndex.entities(txn, null);
+ for (StoredComparatorEntity.MyEnum myEnum :
+ EnumSet.allOf(StoredComparatorEntity.MyEnum.class)) {
+ for (int i = 0; i < nEntities; i += 1) {
+ if (secKeys[i] == myEnum) {
+ StoredComparatorEntity e = entities.next();
+ assertNotNull(e);
+ assertEquals(priKeys[i], e.key);
+ assertEquals(secKeys[i], e.secKey);
+ }
+ }
+ }
+ assertNull(entities.next());
+ entities.close();
+ txnCommit(txn);
+
+ close();
+ }
+
+ @Entity
+ static class StoredComparatorEntity {
+
+ enum MyEnum { A, B, C };
+
+ @Persistent
+ static class Key implements Comparable<Key> {
+
+ @KeyField(1)
+ MyEnum f1;
+
+ @KeyField(2)
+ Integer f2;
+
+ @KeyField(3)
+ MyEnum f3;
+
+ private Key() {}
+
+ Key(MyEnum f1, Integer f2, MyEnum f3) {
+ this.f1 = f1;
+ this.f2 = f2;
+ this.f3 = f3;
+ }
+
+ public int compareTo(Key o) {
+ /* Reverse the natural order. */
+ int i = f1.compareTo(o.f1);
+ if (i != 0) return -i;
+ i = f2.compareTo(o.f2);
+ if (i != 0) return -i;
+ i = f3.compareTo(o.f3);
+ if (i != 0) return -i;
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof Key)) {
+ return false;
+ }
+ Key o = (Key) other;
+ return f1 == o.f1 &&
+ f2.equals(o.f2) &&
+ f3 == o.f3;
+ }
+
+ @Override
+ public int hashCode() {
+ return f1.ordinal() + f2 + f3.ordinal();
+ }
+
+ @Override
+ public String toString() {
+ return "[Key " + f1 + ' ' + f2 + ' ' + f3 + ']';
+ }
+ }
+
+ @PrimaryKey
+ Key key;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private MyEnum secKey;
+
+ private StoredComparatorEntity() {}
+
+ StoredComparatorEntity(Key key, MyEnum secKey) {
+ this.key = key;
+ this.secKey = secKey;
+ }
+
+ @Override
+ public String toString() {
+ return "[pri = " + key + " sec = " + secKey + ']';
+ }
+ }
+}
diff --git a/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/PersistTestUtils.java b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/PersistTestUtils.java
new file mode 100644
index 0000000..354eb19
--- /dev/null
+++ b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/PersistTestUtils.java
@@ -0,0 +1,49 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2000-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+package com.sleepycat.persist.test;
+
+import junit.framework.TestCase;
+
+import com.sleepycat.compat.DbCompat;
+import com.sleepycat.db.Environment;
+
+class PersistTestUtils {
+
+ /**
+ * Asserts than a database expectExists or does not exist. If keyName is
+ * null, checks an entity database. If keyName is non-null, checks a
+ * secondary database.
+ */
+ static void assertDbExists(boolean expectExists,
+ Environment env,
+ String storeName,
+ String entityClassName,
+ String keyName) {
+ String fileName;
+ String dbName;
+ if (DbCompat.SEPARATE_DATABASE_FILES) {
+ fileName = storeName + '-' + entityClassName;
+ if (keyName != null) {
+ fileName += "-" + keyName;
+ }
+ dbName = null;
+ } else {
+ fileName = null;
+ dbName = "persist#" + storeName + '#' + entityClassName;
+ if (keyName != null) {
+ dbName += "#" + keyName;
+ }
+ }
+ boolean exists = DbCompat.databaseExists(env, fileName, dbName);
+ if (expectExists != exists) {
+ TestCase.fail
+ ((expectExists ? "Does not exist: " : "Does exist: ") +
+ dbName);
+ }
+ }
+}
diff --git a/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/SequenceTest.java b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/SequenceTest.java
new file mode 100644
index 0000000..f228426
--- /dev/null
+++ b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/SequenceTest.java
@@ -0,0 +1,469 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2002-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package com.sleepycat.persist.test;
+
+import java.io.File;
+
+import com.sleepycat.db.Environment;
+import com.sleepycat.db.EnvironmentConfig;
+import com.sleepycat.db.util.DualTestCase;
+import com.sleepycat.persist.EntityStore;
+import com.sleepycat.persist.PrimaryIndex;
+import com.sleepycat.persist.StoreConfig;
+import com.sleepycat.persist.model.Entity;
+import com.sleepycat.persist.model.KeyField;
+import com.sleepycat.persist.model.Persistent;
+import com.sleepycat.persist.model.PrimaryKey;
+import com.sleepycat.util.test.SharedTestUtils;
+import com.sleepycat.util.test.TestEnv;
+
+/**
+ * @author Mark Hayes
+ */
+public class SequenceTest extends DualTestCase {
+
+ private File envHome;
+ private Environment env;
+
+ @Override
+ public void setUp()
+ throws Exception {
+
+ super.setUp();
+
+ envHome = new File(System.getProperty(SharedTestUtils.DEST_DIR));
+ SharedTestUtils.emptyDir(envHome);
+ }
+
+ @Override
+ public void tearDown()
+ throws Exception {
+
+ super.tearDown();
+
+ envHome = null;
+ env = null;
+ }
+
+ public void testSequenceKeys()
+ throws Exception {
+
+ Class[] classes = {
+ SequenceEntity_Long.class,
+ SequenceEntity_Integer.class,
+ SequenceEntity_Short.class,
+ SequenceEntity_Byte.class,
+ SequenceEntity_tlong.class,
+ SequenceEntity_tint.class,
+ SequenceEntity_tshort.class,
+ SequenceEntity_tbyte.class,
+ SequenceEntity_Long_composite.class,
+ SequenceEntity_Integer_composite.class,
+ SequenceEntity_Short_composite.class,
+ SequenceEntity_Byte_composite.class,
+ SequenceEntity_tlong_composite.class,
+ SequenceEntity_tint_composite.class,
+ SequenceEntity_tshort_composite.class,
+ SequenceEntity_tbyte_composite.class,
+ };
+
+ EnvironmentConfig envConfig = TestEnv.TXN.getConfig();
+ envConfig.setAllowCreate(true);
+ env = create(envHome, envConfig);
+
+ StoreConfig storeConfig = new StoreConfig();
+ storeConfig.setAllowCreate(true);
+ storeConfig.setTransactional(true);
+ EntityStore store = new EntityStore(env, "foo", storeConfig);
+
+ long seq = 0;
+
+ for (int i = 0; i < classes.length; i += 1) {
+ Class entityCls = classes[i];
+ SequenceEntity entity = (SequenceEntity) entityCls.newInstance();
+ Class keyCls = entity.getKeyClass();
+
+ PrimaryIndex<Object,SequenceEntity> index =
+ store.getPrimaryIndex(keyCls, entityCls);
+ index.putNoReturn(entity);
+ seq += 1;
+ assertEquals(seq, entity.getKey());
+
+ index.putNoReturn(entity);
+ assertEquals(seq, entity.getKey());
+
+ entity.nullifyKey();
+ index.putNoReturn(entity);
+ seq += 1;
+ assertEquals(seq, entity.getKey());
+ }
+
+ store.close();
+ close(env);
+ env = null;
+ }
+
+ interface SequenceEntity {
+ Class getKeyClass();
+ long getKey();
+ void nullifyKey();
+ }
+
+ @Entity
+ static class SequenceEntity_Long implements SequenceEntity {
+
+ @PrimaryKey(sequence="X")
+ Long priKey;
+
+ public Class getKeyClass() {
+ return Long.class;
+ }
+
+ public long getKey() {
+ return priKey;
+ }
+
+ public void nullifyKey() {
+ priKey = null;
+ }
+ }
+
+ @Entity
+ static class SequenceEntity_Integer implements SequenceEntity {
+
+ @PrimaryKey(sequence="X")
+ Integer priKey;
+
+ public Class getKeyClass() {
+ return Integer.class;
+ }
+
+ public long getKey() {
+ return priKey;
+ }
+
+ public void nullifyKey() {
+ priKey = null;
+ }
+ }
+
+ @Entity
+ static class SequenceEntity_Short implements SequenceEntity {
+
+ @PrimaryKey(sequence="X")
+ Short priKey;
+
+ public Class getKeyClass() {
+ return Short.class;
+ }
+
+ public long getKey() {
+ return priKey;
+ }
+
+ public void nullifyKey() {
+ priKey = null;
+ }
+ }
+
+ @Entity
+ static class SequenceEntity_Byte implements SequenceEntity {
+
+ @PrimaryKey(sequence="X")
+ Byte priKey;
+
+ public Class getKeyClass() {
+ return Byte.class;
+ }
+
+ public long getKey() {
+ return priKey;
+ }
+
+ public void nullifyKey() {
+ priKey = null;
+ }
+ }
+
+ @Entity
+ static class SequenceEntity_tlong implements SequenceEntity {
+
+ @PrimaryKey(sequence="X")
+ long priKey;
+
+ public Class getKeyClass() {
+ return Long.class;
+ }
+
+ public long getKey() {
+ return priKey;
+ }
+
+ public void nullifyKey() {
+ priKey = 0;
+ }
+ }
+
+ @Entity
+ static class SequenceEntity_tint implements SequenceEntity {
+
+ @PrimaryKey(sequence="X")
+ int priKey;
+
+ public Class getKeyClass() {
+ return Integer.class;
+ }
+
+ public long getKey() {
+ return priKey;
+ }
+
+ public void nullifyKey() {
+ priKey = 0;
+ }
+ }
+
+ @Entity
+ static class SequenceEntity_tshort implements SequenceEntity {
+
+ @PrimaryKey(sequence="X")
+ short priKey;
+
+ public Class getKeyClass() {
+ return Short.class;
+ }
+
+ public long getKey() {
+ return priKey;
+ }
+
+ public void nullifyKey() {
+ priKey = 0;
+ }
+ }
+
+ @Entity
+ static class SequenceEntity_tbyte implements SequenceEntity {
+
+ @PrimaryKey(sequence="X")
+ byte priKey;
+
+ public Class getKeyClass() {
+ return Byte.class;
+ }
+
+ public long getKey() {
+ return priKey;
+ }
+
+ public void nullifyKey() {
+ priKey = 0;
+ }
+ }
+
+ @Entity
+ static class SequenceEntity_Long_composite implements SequenceEntity {
+
+ @PrimaryKey(sequence="X")
+ Key priKey;
+
+ @Persistent
+ static class Key {
+ @KeyField(1)
+ Long priKey;
+ }
+
+ public Class getKeyClass() {
+ return Key.class;
+ }
+
+ public long getKey() {
+ return priKey.priKey;
+ }
+
+ public void nullifyKey() {
+ priKey = null;
+ }
+ }
+
+ @Entity
+ static class SequenceEntity_Integer_composite implements SequenceEntity {
+
+ @PrimaryKey(sequence="X")
+ Key priKey;
+
+ @Persistent
+ static class Key {
+ @KeyField(1)
+ Integer priKey;
+ }
+
+ public Class getKeyClass() {
+ return Key.class;
+ }
+
+ public long getKey() {
+ return priKey.priKey;
+ }
+
+ public void nullifyKey() {
+ priKey = null;
+ }
+ }
+
+ @Entity
+ static class SequenceEntity_Short_composite implements SequenceEntity {
+
+ @PrimaryKey(sequence="X")
+ Key priKey;
+
+ @Persistent
+ static class Key {
+ @KeyField(1)
+ Short priKey;
+ }
+
+ public Class getKeyClass() {
+ return Key.class;
+ }
+
+ public long getKey() {
+ return priKey.priKey;
+ }
+
+ public void nullifyKey() {
+ priKey = null;
+ }
+ }
+
+ @Entity
+ static class SequenceEntity_Byte_composite implements SequenceEntity {
+
+ @PrimaryKey(sequence="X")
+ Key priKey;
+
+ @Persistent
+ static class Key {
+ @KeyField(1)
+ Byte priKey;
+ }
+
+ public Class getKeyClass() {
+ return Key.class;
+ }
+
+ public long getKey() {
+ return priKey.priKey;
+ }
+
+ public void nullifyKey() {
+ priKey = null;
+ }
+ }
+
+ @Entity
+ static class SequenceEntity_tlong_composite implements SequenceEntity {
+
+ @PrimaryKey(sequence="X")
+ Key priKey;
+
+ @Persistent
+ static class Key {
+ @KeyField(1)
+ long priKey;
+ }
+
+ public Class getKeyClass() {
+ return Key.class;
+ }
+
+ public long getKey() {
+ return priKey.priKey;
+ }
+
+ public void nullifyKey() {
+ priKey = null;
+ }
+ }
+
+ @Entity
+ static class SequenceEntity_tint_composite implements SequenceEntity {
+
+ @PrimaryKey(sequence="X")
+ Key priKey;
+
+ @Persistent
+ static class Key {
+ @KeyField(1)
+ int priKey;
+ }
+
+ public Class getKeyClass() {
+ return Key.class;
+ }
+
+ public long getKey() {
+ return priKey.priKey;
+ }
+
+ public void nullifyKey() {
+ priKey = null;
+ }
+ }
+
+ @Entity
+ static class SequenceEntity_tshort_composite implements SequenceEntity {
+
+ @PrimaryKey(sequence="X")
+ Key priKey;
+
+ @Persistent
+ static class Key {
+ @KeyField(1)
+ short priKey;
+ }
+
+ public Class getKeyClass() {
+ return Key.class;
+ }
+
+ public long getKey() {
+ return priKey.priKey;
+ }
+
+ public void nullifyKey() {
+ priKey = null;
+ }
+ }
+
+ @Entity
+ static class SequenceEntity_tbyte_composite implements SequenceEntity {
+
+ @PrimaryKey(sequence="X")
+ Key priKey;
+
+ @Persistent
+ static class Key {
+ @KeyField(1)
+ byte priKey;
+ }
+
+ public Class getKeyClass() {
+ return Key.class;
+ }
+
+ public long getKey() {
+ return priKey.priKey;
+ }
+
+ public void nullifyKey() {
+ priKey = null;
+ }
+ }
+}
diff --git a/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/SubclassIndexTest.java b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/SubclassIndexTest.java
new file mode 100644
index 0000000..f1f5dd9
--- /dev/null
+++ b/db-4.8.30/test/scr024/src/com/sleepycat/persist/test/SubclassIndexTest.java
@@ -0,0 +1,251 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2002-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package com.sleepycat.persist.test;
+
+import static com.sleepycat.persist.model.Relationship.MANY_TO_ONE;
+
+import java.io.File;
+
+import com.sleepycat.db.DatabaseException;
+import com.sleepycat.db.Environment;
+import com.sleepycat.db.EnvironmentConfig;
+import com.sleepycat.db.Transaction;
+import com.sleepycat.db.util.DualTestCase;
+import com.sleepycat.persist.EntityCursor;
+import com.sleepycat.persist.EntityStore;
+import com.sleepycat.persist.PrimaryIndex;
+import com.sleepycat.persist.SecondaryIndex;
+import com.sleepycat.persist.StoreConfig;
+import com.sleepycat.persist.model.AnnotationModel;
+import com.sleepycat.persist.model.Entity;
+import com.sleepycat.persist.model.EntityModel;
+import com.sleepycat.persist.model.Persistent;
+import com.sleepycat.persist.model.PrimaryKey;
+import com.sleepycat.persist.model.SecondaryKey;
+import com.sleepycat.util.test.SharedTestUtils;
+import com.sleepycat.util.test.TestEnv;
+
+public class SubclassIndexTest extends DualTestCase {
+
+ private File envHome;
+ private Environment env;
+ private EntityStore store;
+
+ @Override
+ public void setUp()
+ throws Exception {
+
+ super.setUp();
+
+ envHome = new File(System.getProperty(SharedTestUtils.DEST_DIR));
+ SharedTestUtils.emptyDir(envHome);
+ }
+
+ @Override
+ public void tearDown()
+ throws Exception {
+
+ super.tearDown();
+
+ envHome = null;
+ env = null;
+ }
+
+ private void open()
+ throws DatabaseException {
+
+ EnvironmentConfig envConfig = TestEnv.TXN.getConfig();
+ envConfig.setAllowCreate(true);
+ env = create(envHome, envConfig);
+
+ EntityModel model = new AnnotationModel();
+ model.registerClass(Manager.class);
+ model.registerClass(SalariedManager.class);
+
+ StoreConfig storeConfig = new StoreConfig();
+ storeConfig.setModel(model);
+ storeConfig.setAllowCreate(true);
+ storeConfig.setTransactional(true);
+ store = new EntityStore(env, "foo", storeConfig);
+ }
+
+ private void close()
+ throws DatabaseException {
+
+ store.close();
+ store = null;
+ close(env);
+ env = null;
+ }
+
+ public void testSubclassIndex()
+ throws DatabaseException {
+
+ open();
+
+ PrimaryIndex<String, Employee> employeesById =
+ store.getPrimaryIndex(String.class, Employee.class);
+
+ employeesById.put(new Employee("1"));
+ employeesById.put(new Manager("2", "a"));
+ employeesById.put(new Manager("3", "a"));
+ employeesById.put(new Manager("4", "b"));
+
+ Employee e;
+ Manager m;
+
+ e = employeesById.get("1");
+ assertNotNull(e);
+ assertTrue(!(e instanceof Manager));
+
+ /* Ensure DB exists BEFORE calling getSubclassIndex. [#15247] */
+ PersistTestUtils.assertDbExists
+ (true, env, "foo", Employee.class.getName(), "dept");
+
+ /* Normal use: Subclass index for a key in the subclass. */
+ SecondaryIndex<String, String, Manager> managersByDept =
+ store.getSubclassIndex
+ (employeesById, Manager.class, String.class, "dept");
+
+ m = managersByDept.get("a");
+ assertNotNull(m);
+ assertEquals("2", m.id);
+
+ m = managersByDept.get("b");
+ assertNotNull(m);
+ assertEquals("4", m.id);
+
+ Transaction txn = env.beginTransaction(null, null);
+ EntityCursor<Manager> managers = managersByDept.entities(txn, null);
+ try {
+ m = managers.next();
+ assertNotNull(m);
+ assertEquals("2", m.id);
+ m = managers.next();
+ assertNotNull(m);
+ assertEquals("3", m.id);
+ m = managers.next();
+ assertNotNull(m);
+ assertEquals("4", m.id);
+ m = managers.next();
+ assertNull(m);
+ } finally {
+ managers.close();
+ txn.commit();
+ }
+
+ /* Getting a subclass index for the entity class is also allowed. */
+ store.getSubclassIndex
+ (employeesById, Employee.class, String.class, "other");
+
+ /* Getting a subclass index for a base class key is not allowed. */
+ try {
+ store.getSubclassIndex
+ (employeesById, Manager.class, String.class, "other");
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+
+ close();
+ }
+
+ /**
+ * Previously this tested that a secondary key database was added only
+ * AFTER storing the first instance of the subclass that defines the key.
+ * Now that we require registering the subclass up front, the database is
+ * created up front also. So this test is somewhat less useful, but still
+ * nice to have around. [#16399]
+ */
+ public void testAddSecKey()
+ throws DatabaseException {
+
+ open();
+ PrimaryIndex<String, Employee> employeesById =
+ store.getPrimaryIndex(String.class, Employee.class);
+ employeesById.put(new Employee("1"));
+ assertTrue(hasEntityKey("dept"));
+ close();
+
+ open();
+ employeesById = store.getPrimaryIndex(String.class, Employee.class);
+ assertTrue(hasEntityKey("dept"));
+ employeesById.put(new Manager("2", "a"));
+ assertTrue(hasEntityKey("dept"));
+ close();
+
+ open();
+ assertTrue(hasEntityKey("dept"));
+ close();
+
+ open();
+ employeesById = store.getPrimaryIndex(String.class, Employee.class);
+ assertTrue(hasEntityKey("salary"));
+ employeesById.put(new SalariedManager("3", "a", "111"));
+ assertTrue(hasEntityKey("salary"));
+ close();
+
+ open();
+ assertTrue(hasEntityKey("dept"));
+ assertTrue(hasEntityKey("salary"));
+ close();
+ }
+
+ private boolean hasEntityKey(String keyName) {
+ return store.getModel().
+ getRawType(Employee.class.getName()).
+ getEntityMetadata().
+ getSecondaryKeys().
+ keySet().
+ contains(keyName);
+ }
+
+ @Entity
+ private static class Employee {
+
+ @PrimaryKey
+ String id;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ String other;
+
+ Employee(String id) {
+ this.id = id;
+ }
+
+ private Employee() {}
+ }
+
+ @Persistent
+ private static class Manager extends Employee {
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ String dept;
+
+ Manager(String id, String dept) {
+ super(id);
+ this.dept = dept;
+ }
+
+ private Manager() {}
+ }
+
+ @Persistent
+ private static class SalariedManager extends Manager {
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ String salary;
+
+ SalariedManager(String id, String dept, String salary) {
+ super(id, dept);
+ this.salary = salary;
+ }
+
+ private SalariedManager() {}
+ }
+}