summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian S. O'Neill <bronee@gmail.com>2008-05-11 01:33:53 +0000
committerBrian S. O'Neill <bronee@gmail.com>2008-05-11 01:33:53 +0000
commit1a384d409db2f070730384c6f83083233044673a (patch)
tree81ba4b49afdfe61a9b663523db9070eaf6fce26c
parentc8bec73cfa29e97bcb7085aea6bfac293933f1fc (diff)
Added JDBC tests which use H2.
-rw-r--r--pom.xml28
-rw-r--r--src/test/java/com/amazon/carbonado/repo/jdbc/DerbySchemaResolver.java256
-rw-r--r--src/test/java/com/amazon/carbonado/repo/jdbc/H2SchemaResolver.java267
-rw-r--r--src/test/java/com/amazon/carbonado/repo/jdbc/TestH2.java366
4 files changed, 917 insertions, 0 deletions
diff --git a/pom.xml b/pom.xml
index 6c2764c..8246d6b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -77,6 +77,34 @@
</dependency>
<dependency>
+ <groupId>commons-dbcp</groupId>
+ <artifactId>commons-dbcp</artifactId>
+ <version>[1.2,)</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-pool</groupId>
+ <artifactId>commons-pool</artifactId>
+ <version>[1.4,)</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-collections</groupId>
+ <artifactId>commons-collections</artifactId>
+ <version>[3.2,)</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.h2database</groupId>
+ <artifactId>h2database</artifactId>
+ <version>1.0.71</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
diff --git a/src/test/java/com/amazon/carbonado/repo/jdbc/DerbySchemaResolver.java b/src/test/java/com/amazon/carbonado/repo/jdbc/DerbySchemaResolver.java
new file mode 100644
index 0000000..76f7cdf
--- /dev/null
+++ b/src/test/java/com/amazon/carbonado/repo/jdbc/DerbySchemaResolver.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2008 Amazon Technologies, Inc. or its affiliates.
+ * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks
+ * of Amazon Technologies, Inc. or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.amazon.carbonado.repo.jdbc;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.joda.time.DateTime;
+
+import com.amazon.carbonado.Repository;
+import com.amazon.carbonado.RepositoryBuilder;
+import com.amazon.carbonado.RepositoryException;
+import com.amazon.carbonado.Storable;
+
+import com.amazon.carbonado.lob.Blob;
+import com.amazon.carbonado.lob.Clob;
+
+import com.amazon.carbonado.info.OrderedProperty;
+import com.amazon.carbonado.info.StorableIndex;
+import com.amazon.carbonado.info.StorableInfo;
+import com.amazon.carbonado.info.StorableKey;
+import com.amazon.carbonado.info.StorableProperty;
+
+/**
+ * Creates tables as needed automatically for the Derby database.
+ *
+ * @author Brian S O'Neill
+ */
+public class DerbySchemaResolver implements SchemaResolver {
+ public <S extends Storable> boolean resolve(StorableInfo<S> info,
+ Connection con, String catalog, String schema)
+ throws SQLException
+ {
+ // Create the table, keys, indexes and sequences.
+
+ StringBuilder b = new StringBuilder();
+ b.append("CREATE TABLE ");
+
+ String tableName;
+ if (info.getAliasCount() > 0) {
+ tableName = info.getAlias(0);
+ } else {
+ tableName = info.getName();
+ }
+ if (needsQuotes(tableName)) {
+ tableName = '"' + tableName + '"';
+ }
+ b.append(tableName);
+ b.append(" (");
+
+ int i = 0;
+ for (StorableProperty<S> property : info.getAllProperties().values()) {
+ if (property.isJoin() || property.isDerived()) {
+ continue;
+ }
+
+ if (i++ > 0) {
+ b.append(", ");
+ }
+
+ if (property.getAliasCount() > 0) {
+ b.append(property.getAlias(0));
+ } else {
+ b.append(property.getName());
+ }
+ b.append(' ');
+
+ Class type = property.getType();
+ String typeName;
+ if (type == String.class) {
+ typeName = "VARCHAR(255)";
+ } else if (type == int.class || type == Integer.class) {
+ typeName = "INT";
+ } else if (type == long.class || type == Long.class) {
+ typeName = "BIGINT";
+ } else if (type == float.class || type == Float.class) {
+ typeName = "REAL";
+ } else if (type == double.class || type == Double.class) {
+ typeName = "DOUBLE";
+ } else if (type == short.class || type == Short.class) {
+ typeName = "SMALLINT";
+ } else if (type == byte.class || type == Byte.class) {
+ typeName = "TINYINT";
+ } else if (type == char.class || type == Character.class) {
+ typeName = "CHAR(1)";
+ } else if (type == boolean.class || type == Boolean.class) {
+ typeName = "BOOLEAN";
+ } else if (type == DateTime.class) {
+ typeName = "TIMESTAMP";
+ } else if (type == byte[].class) {
+ typeName = "BINARY";
+ } else if (type == Blob.class) {
+ typeName = "BLOB";
+ } else if (type == Clob.class) {
+ typeName = "CLOB";
+ } else {
+ return false;
+ }
+
+ b.append(typeName);
+
+ if (!property.isNullable()) {
+ b.append(" NOT NULL");
+ }
+ }
+
+ b.append(')');
+ String createTable = b.toString();
+
+ b = new StringBuilder();
+ b.append("ALTER TABLE ");
+ b.append(tableName);
+ b.append(" ADD PRIMARY KEY (");
+
+ i = 0;
+ for (StorableProperty<S> property : info.getPrimaryKeyProperties().values()) {
+ if (i++ > 0) {
+ b.append(", ");
+ }
+
+ if (property.getAliasCount() > 0) {
+ b.append(property.getAlias(0));
+ } else {
+ b.append(property.getName());
+ }
+ }
+
+ b.append(')');
+ String createPrimaryKey = b.toString();
+
+ int indexCount = 0;
+
+ List<String> createAltKeys = new ArrayList<String>();
+
+ for (StorableKey<S> key : info.getAlternateKeys()) {
+ b = new StringBuilder();
+ b.append("CREATE UNIQUE INDEX ");
+ b.append(tableName);
+ b.append('_');
+ b.append(Integer.valueOf(++indexCount));
+ b.append(" ON ");
+ b.append(tableName);
+ b.append(" (");
+
+ i = 0;
+ for (OrderedProperty<S> op : key.getProperties()) {
+ StorableProperty<S> property = op.getChainedProperty().getPrimeProperty();
+ if (property.isDerived()) {
+ continue;
+ }
+
+ if (i++ > 0) {
+ b.append(", ");
+ }
+
+ if (property.getAliasCount() > 0) {
+ b.append(property.getAlias(0));
+ } else {
+ b.append(property.getName());
+ }
+ }
+
+ if (i > 0) {
+ b.append(')');
+ createAltKeys.add(b.toString());
+ }
+ }
+
+ List<String> createIndexes = new ArrayList<String>();
+
+ for (StorableIndex<S> index : info.getIndexes()) {
+ b = new StringBuilder();
+ b.append("CREATE INDEX ");
+ b.append(tableName);
+ b.append('_');
+ b.append(Integer.valueOf(++indexCount));
+ b.append(" ON ");
+ b.append(tableName);
+ b.append(" (");
+
+ i = 0;
+ for (StorableProperty<S> property : index.getProperties()) {
+ if (property.isDerived()) {
+ continue;
+ }
+
+ if (i++ > 0) {
+ b.append(", ");
+ }
+
+ if (property.getAliasCount() > 0) {
+ b.append(property.getAlias(0));
+ } else {
+ b.append(property.getName());
+ }
+ }
+
+ if (i > 0) {
+ b.append(')');
+ createIndexes.add(b.toString());
+ }
+ }
+
+ Statement st = con.createStatement();
+ try {
+ st.executeUpdate(createTable);
+
+ st.executeUpdate(createPrimaryKey);
+
+ for (String createAltKey : createAltKeys) {
+ st.executeUpdate(createAltKey);
+ }
+
+ for (String createIndex : createIndexes) {
+ st.executeUpdate(createIndex);
+ }
+ } finally {
+ st.close();
+ }
+
+ return true;
+ }
+
+ private boolean needsQuotes(String str) {
+ if (!Character.isUnicodeIdentifierStart(str.charAt(0))) {
+ return true;
+ }
+ for (int i=1; i<str.length(); i++) {
+ if (!Character.isUnicodeIdentifierPart(str.charAt(i))) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/test/java/com/amazon/carbonado/repo/jdbc/H2SchemaResolver.java b/src/test/java/com/amazon/carbonado/repo/jdbc/H2SchemaResolver.java
new file mode 100644
index 0000000..8eddb5b
--- /dev/null
+++ b/src/test/java/com/amazon/carbonado/repo/jdbc/H2SchemaResolver.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2008 Amazon Technologies, Inc. or its affiliates.
+ * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks
+ * of Amazon Technologies, Inc. or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.amazon.carbonado.repo.jdbc;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.joda.time.DateTime;
+
+import com.amazon.carbonado.Repository;
+import com.amazon.carbonado.RepositoryBuilder;
+import com.amazon.carbonado.RepositoryException;
+import com.amazon.carbonado.Storable;
+
+import com.amazon.carbonado.lob.Blob;
+import com.amazon.carbonado.lob.Clob;
+
+import com.amazon.carbonado.info.OrderedProperty;
+import com.amazon.carbonado.info.StorableIndex;
+import com.amazon.carbonado.info.StorableInfo;
+import com.amazon.carbonado.info.StorableKey;
+import com.amazon.carbonado.info.StorableProperty;
+
+/**
+ * Creates tables as needed automatically for the H2 database.
+ *
+ * @author Brian S O'Neill
+ */
+public class H2SchemaResolver implements SchemaResolver {
+ public <S extends Storable> boolean resolve(StorableInfo<S> info,
+ Connection con, String catalog, String schema)
+ throws SQLException
+ {
+ // Create the table, keys, indexes and sequences.
+ List<String> sequenceNames = new ArrayList<String>();
+
+ StringBuilder b = new StringBuilder();
+ b.append("CREATE TABLE ");
+
+ String tableName;
+ if (info.getAliasCount() > 0) {
+ tableName = info.getAlias(0);
+ } else {
+ tableName = info.getName();
+ }
+ if (needsQuotes(tableName)) {
+ tableName = '"' + tableName + '"';
+ }
+ b.append(tableName);
+ b.append(" (");
+
+ int i = 0;
+ for (StorableProperty<S> property : info.getAllProperties().values()) {
+ if (property.isJoin() || property.isDerived()) {
+ continue;
+ }
+
+ if (i++ > 0) {
+ b.append(", ");
+ }
+
+ if (property.getAliasCount() > 0) {
+ b.append(property.getAlias(0));
+ } else {
+ b.append(property.getName());
+ }
+ b.append(' ');
+
+ Class type = property.getType();
+ String typeName;
+ if (type == String.class) {
+ typeName = "VARCHAR";
+ } else if (type == int.class || type == Integer.class) {
+ typeName = "INT";
+ } else if (type == long.class || type == Long.class) {
+ typeName = "BIGINT";
+ } else if (type == float.class || type == Float.class) {
+ typeName = "REAL";
+ } else if (type == double.class || type == Double.class) {
+ typeName = "DOUBLE";
+ } else if (type == short.class || type == Short.class) {
+ typeName = "SMALLINT";
+ } else if (type == byte.class || type == Byte.class) {
+ typeName = "TINYINT";
+ } else if (type == char.class || type == Character.class) {
+ typeName = "CHAR(1)";
+ } else if (type == boolean.class || type == Boolean.class) {
+ typeName = "BOOLEAN";
+ } else if (type == DateTime.class) {
+ typeName = "TIMESTAMP";
+ } else if (type == byte[].class) {
+ typeName = "BINARY";
+ } else if (type == Blob.class) {
+ typeName = "BLOB";
+ } else if (type == Clob.class) {
+ typeName = "CLOB";
+ } else {
+ return false;
+ }
+
+ b.append(typeName);
+
+ if (property.isNullable()) {
+ b.append(" NULL");
+ } else {
+ b.append(" NOT NULL");
+ }
+
+ if (property.getSequenceName() != null) {
+ sequenceNames.add(property.getSequenceName());
+ }
+ }
+
+ b.append(')');
+ String createTable = b.toString();
+
+ b = new StringBuilder();
+ b.append("ALTER TABLE ");
+ b.append(tableName);
+ b.append(" ADD PRIMARY KEY (");
+
+ i = 0;
+ for (StorableProperty<S> property : info.getPrimaryKeyProperties().values()) {
+ if (i++ > 0) {
+ b.append(", ");
+ }
+
+ if (property.getAliasCount() > 0) {
+ b.append(property.getAlias(0));
+ } else {
+ b.append(property.getName());
+ }
+ }
+
+ b.append(')');
+ String createPrimaryKey = b.toString();
+
+ int indexCount = 0;
+
+ List<String> createAltKeys = new ArrayList<String>();
+
+ for (StorableKey<S> key : info.getAlternateKeys()) {
+ b = new StringBuilder();
+ b.append("CREATE UNIQUE INDEX ");
+ b.append(tableName);
+ b.append('_');
+ b.append(Integer.valueOf(++indexCount));
+ b.append(" ON ");
+ b.append(tableName);
+ b.append(" (");
+
+ i = 0;
+ for (OrderedProperty<S> op : key.getProperties()) {
+ StorableProperty<S> property = op.getChainedProperty().getPrimeProperty();
+ if (property.isDerived()) {
+ continue;
+ }
+
+ if (i++ > 0) {
+ b.append(", ");
+ }
+
+ if (property.getAliasCount() > 0) {
+ b.append(property.getAlias(0));
+ } else {
+ b.append(property.getName());
+ }
+ }
+
+ if (i > 0) {
+ b.append(')');
+ createAltKeys.add(b.toString());
+ }
+ }
+
+ List<String> createIndexes = new ArrayList<String>();
+
+ for (StorableIndex<S> index : info.getIndexes()) {
+ b = new StringBuilder();
+ b.append("CREATE INDEX ");
+ b.append(tableName);
+ b.append('_');
+ b.append(Integer.valueOf(++indexCount));
+ b.append(" ON ");
+ b.append(tableName);
+ b.append(" (");
+
+ i = 0;
+ for (StorableProperty<S> property : index.getProperties()) {
+ if (property.isDerived()) {
+ continue;
+ }
+
+ if (i++ > 0) {
+ b.append(", ");
+ }
+
+ if (property.getAliasCount() > 0) {
+ b.append(property.getAlias(0));
+ } else {
+ b.append(property.getName());
+ }
+ }
+
+ if (i > 0) {
+ b.append(')');
+ createIndexes.add(b.toString());
+ }
+ }
+
+ Statement st = con.createStatement();
+ try {
+ st.executeUpdate(createTable);
+
+ st.executeUpdate(createPrimaryKey);
+
+ for (String createAltKey : createAltKeys) {
+ st.executeUpdate(createAltKey);
+ }
+
+ for (String createIndex : createIndexes) {
+ st.executeUpdate(createIndex);
+ }
+
+ for (String sequenceName : sequenceNames) {
+ st.executeUpdate("CREATE SEQUENCE IF NOT EXISTS " + sequenceName);
+ }
+ } finally {
+ st.close();
+ }
+
+ return true;
+ }
+
+ private boolean needsQuotes(String str) {
+ if (!Character.isUnicodeIdentifierStart(str.charAt(0))) {
+ return true;
+ }
+ for (int i=1; i<str.length(); i++) {
+ if (!Character.isUnicodeIdentifierPart(str.charAt(i))) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/test/java/com/amazon/carbonado/repo/jdbc/TestH2.java b/src/test/java/com/amazon/carbonado/repo/jdbc/TestH2.java
new file mode 100644
index 0000000..2682f53
--- /dev/null
+++ b/src/test/java/com/amazon/carbonado/repo/jdbc/TestH2.java
@@ -0,0 +1,366 @@
+/*
+ * Copyright 2008 Amazon Technologies, Inc. or its affiliates.
+ * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks
+ * of Amazon Technologies, Inc. or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.amazon.carbonado.repo.jdbc;
+
+import java.io.*;
+
+import java.sql.DriverManager;
+
+import junit.framework.TestSuite;
+
+import org.apache.commons.dbcp.BasicDataSource;
+
+import com.amazon.carbonado.*;
+
+import com.amazon.carbonado.lob.*;
+
+import com.amazon.carbonado.repo.indexed.IndexedRepositoryBuilder;
+
+import com.amazon.carbonado.TestUtilities;
+
+import com.amazon.carbonado.stored.StorableWithLobs;
+
+/**
+ *
+ *
+ * @author Brian S O'Neill
+ */
+public class TestH2 extends com.amazon.carbonado.TestStorables {
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ public static TestSuite suite() {
+ TestSuite suite = new TestSuite();
+ suite.addTestSuite(TestH2.class);
+ return suite;
+ }
+
+ public TestH2(String name) {
+ super(name);
+ }
+
+ @Override
+ public void test_derivedJoinIndex() throws Exception {
+ // Needs to use custom indexing for this test to work.
+ IndexedRepositoryBuilder builder = new IndexedRepositoryBuilder();
+ builder.setWrappedRepository(jdbcBuilder(true));
+ Repository repo = builder.build();
+ test_derivedJoinIndex(repo);
+ }
+
+ @Override
+ protected Repository buildRepository(boolean isMaster) throws RepositoryException {
+ return jdbcBuilder(isMaster).build();
+ }
+
+ // Override because H2 does not fully support LOBs.
+ @Override
+ public void test_lobInsert() throws Exception {
+ Storage<StorableWithLobs> storage = getRepository().storageFor(StorableWithLobs.class);
+
+ // Test null insert
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.insert();
+ assertEquals(null, lobs.getBlobValue());
+ assertEquals(null, lobs.getClobValue());
+ lobs.load();
+ assertEquals(null, lobs.getBlobValue());
+ assertEquals(null, lobs.getClobValue());
+ }
+
+ // Test content insert
+ int id;
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.setBlobValue(new ByteArrayBlob("hello".getBytes()));
+ lobs.setClobValue(new StringClob("world"));
+ lobs.insert();
+ assertEquals("hello", lobs.getBlobValue().asString());
+ assertEquals("world", lobs.getClobValue().asString());
+ lobs.load();
+ assertEquals("hello", lobs.getBlobValue().asString());
+ assertEquals("world", lobs.getClobValue().asString());
+ id = lobs.getId();
+ }
+
+ // Test insert failure
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.setId(id);
+
+ Blob newBlob = new ByteArrayBlob("blob insert should fail".getBytes());
+ Clob newClob = new StringClob("clob insert should fail");
+
+ lobs.setBlobValue(newBlob);
+ lobs.setClobValue(newClob);
+
+ try {
+ lobs.insert();
+ fail();
+ } catch (UniqueConstraintException e) {
+ }
+
+ assertTrue(newBlob == lobs.getBlobValue());
+ assertTrue(newClob == lobs.getClobValue());
+ }
+ }
+
+ // Override because H2 does not fully support LOBs.
+ @Override
+ public void test_lobUpdate() throws Exception {
+ Storage<StorableWithLobs> storage = getRepository().storageFor(StorableWithLobs.class);
+
+ // Test null replaces null
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.insert();
+
+ lobs.setBlobValue(null);
+ lobs.setClobValue(null);
+
+ lobs.update();
+
+ assertEquals(null, lobs.getBlobValue());
+ assertEquals(null, lobs.getClobValue());
+
+ lobs.load();
+ assertEquals(null, lobs.getBlobValue());
+ assertEquals(null, lobs.getClobValue());
+ }
+
+ // Test null replaces content and verify content deleted
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.setBlobValue(new ByteArrayBlob("hello".getBytes()));
+ lobs.setClobValue(new StringClob("world!!!"));
+ lobs.insert();
+
+ Blob blob = lobs.getBlobValue();
+ Clob clob = lobs.getClobValue();
+
+ assertEquals(5, blob.getLength());
+ assertEquals(8, clob.getLength());
+
+ lobs.setBlobValue(null);
+
+ lobs.update();
+
+ assertNull(lobs.getBlobValue());
+ assertEquals(clob.asString(), lobs.getClobValue().asString());
+
+ lobs.load();
+
+ assertNull(lobs.getBlobValue());
+ assertEquals(clob.asString(), lobs.getClobValue().asString());
+
+ lobs.setClobValue(null);
+
+ lobs.update();
+
+ assertNull(lobs.getBlobValue());
+ assertNull(lobs.getClobValue());
+
+ lobs.load();
+
+ assertNull(lobs.getBlobValue());
+ assertNull(lobs.getClobValue());
+ }
+
+ // Test content replaces null
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.insert();
+
+ lobs.setBlobValue(new ByteArrayBlob("hello".getBytes()));
+ lobs.setClobValue(new StringClob("world"));
+
+ assertTrue(lobs.getBlobValue() instanceof ByteArrayBlob);
+ assertTrue(lobs.getClobValue() instanceof StringClob);
+
+ lobs.update();
+
+ assertEquals("hello", lobs.getBlobValue().asString());
+ assertEquals("world", lobs.getClobValue().asString());
+
+ assertFalse(lobs.getBlobValue() instanceof ByteArrayBlob);
+ assertFalse(lobs.getClobValue() instanceof StringClob);
+
+ lobs.load();
+
+ assertEquals("hello", lobs.getBlobValue().asString());
+ assertEquals("world", lobs.getClobValue().asString());
+
+ assertFalse(lobs.getBlobValue() instanceof ByteArrayBlob);
+ assertFalse(lobs.getClobValue() instanceof StringClob);
+ }
+
+ // Test content replaces content of same length
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.setBlobValue(new ByteArrayBlob("hello".getBytes()));
+ lobs.setClobValue(new StringClob("world?"));
+ lobs.insert();
+
+ Blob blob = lobs.getBlobValue();
+ Clob clob = lobs.getClobValue();
+
+ lobs.setBlobValue(new ByteArrayBlob("12345".getBytes()));
+ lobs.update();
+
+ assertEquals(5, lobs.getBlobValue().getLength());
+ assertEquals(6, lobs.getClobValue().getLength());
+
+ assertEquals("12345", lobs.getBlobValue().asString());
+ assertEquals("world?", lobs.getClobValue().asString());
+
+ assertTrue(blob.asString().equals(lobs.getBlobValue().asString()));
+ assertTrue(clob.asString().equals(lobs.getClobValue().asString()));
+
+ lobs.setClobValue(new StringClob("123456"));
+ lobs.update();
+
+ assertEquals(5, lobs.getBlobValue().getLength());
+ assertEquals(6, lobs.getClobValue().getLength());
+
+ assertEquals("12345", lobs.getBlobValue().asString());
+ assertEquals("123456", lobs.getClobValue().asString());
+
+ assertTrue(blob.asString().equals(lobs.getBlobValue().asString()));
+ assertTrue(clob.asString().equals(lobs.getClobValue().asString()));
+ }
+
+ // Test content replaces content of longer length
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.setBlobValue(new ByteArrayBlob("hello".getBytes()));
+ lobs.setClobValue(new StringClob("world?"));
+ lobs.insert();
+
+ Blob blob = lobs.getBlobValue();
+ Clob clob = lobs.getClobValue();
+
+ lobs.setBlobValue(new ByteArrayBlob("123".getBytes()));
+ lobs.update();
+
+ assertEquals(3, lobs.getBlobValue().getLength());
+ assertEquals(6, lobs.getClobValue().getLength());
+
+ assertEquals("123", lobs.getBlobValue().asString());
+ assertEquals("world?", lobs.getClobValue().asString());
+
+ assertTrue(blob.asString().equals(lobs.getBlobValue().asString()));
+ assertTrue(clob.asString().equals(lobs.getClobValue().asString()));
+
+ lobs.setClobValue(new StringClob("12"));
+ lobs.update();
+
+ assertEquals(3, lobs.getBlobValue().getLength());
+ assertEquals(2, lobs.getClobValue().getLength());
+
+ assertEquals("123", lobs.getBlobValue().asString());
+ assertEquals("12", lobs.getClobValue().asString());
+
+ assertTrue(blob.asString().equals(lobs.getBlobValue().asString()));
+ assertTrue(clob.asString().equals(lobs.getClobValue().asString()));
+ }
+
+ // Test content replaces content of shorter length
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.setBlobValue(new ByteArrayBlob("hello".getBytes()));
+ lobs.setClobValue(new StringClob("world?"));
+ lobs.insert();
+
+ Blob blob = lobs.getBlobValue();
+ Clob clob = lobs.getClobValue();
+
+ lobs.setBlobValue(new ByteArrayBlob("123456789".getBytes()));
+ lobs.update();
+
+ assertEquals(9, lobs.getBlobValue().getLength());
+ assertEquals(6, lobs.getClobValue().getLength());
+
+ assertEquals("123456789", lobs.getBlobValue().asString());
+ assertEquals("world?", lobs.getClobValue().asString());
+
+ assertTrue(blob.asString().equals(lobs.getBlobValue().asString()));
+ assertTrue(clob.asString().equals(lobs.getClobValue().asString()));
+
+ lobs.setClobValue(new StringClob("1234567890"));
+ lobs.update();
+
+ assertEquals(9, lobs.getBlobValue().getLength());
+ assertEquals(10, lobs.getClobValue().getLength());
+
+ assertEquals("123456789", lobs.getBlobValue().asString());
+ assertEquals("1234567890", lobs.getClobValue().asString());
+
+ assertTrue(blob.asString().equals(lobs.getBlobValue().asString()));
+ assertTrue(clob.asString().equals(lobs.getClobValue().asString()));
+ }
+
+ // Test update failure
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.setId(10000);
+
+ Blob newBlob = new ByteArrayBlob("blob update should fail".getBytes());
+ Clob newClob = new StringClob("clob update should fail");
+
+ lobs.setBlobValue(newBlob);
+ lobs.setClobValue(newClob);
+
+ try {
+ lobs.update();
+ fail();
+ } catch (PersistNoneException e) {
+ }
+
+ assertTrue(newBlob == lobs.getBlobValue());
+ assertTrue(newClob == lobs.getClobValue());
+ }
+ }
+
+ @Override
+ public void test_insertLobBig() throws Exception {
+ // Not a useful test.
+ }
+
+ private RepositoryBuilder jdbcBuilder(boolean isMaster) throws RepositoryException {
+ JDBCRepositoryBuilder builder = new JDBCRepositoryBuilder();
+ builder.setName("jdbc");
+ builder.setAutoVersioningEnabled(true, null);
+ builder.setMaster(isMaster);
+ BasicDataSource ds = new BasicDataSource();
+ builder.setDataSource(ds);
+
+ builder.setSchemaResolver(new H2SchemaResolver());
+
+ File dir = new File(TestUtilities.makeTestDirectory("jdbc"), "/h2");
+ String url = "jdbc:h2:" + dir.getPath();
+ ds.setDriverClassName("org.h2.Driver");
+ ds.setUrl(url);
+ ds.setUsername("sa");
+ ds.setPassword("");
+
+ return builder;
+ }
+}