diff options
Diffstat (limited to 'src/main/java')
8 files changed, 197 insertions, 118 deletions
diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCBlobLoader.java b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCBlobLoader.java index cd818c0..e8464e3 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCBlobLoader.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCBlobLoader.java @@ -29,5 +29,5 @@ public interface JDBCBlobLoader { /**
* @return Blob or null if missing
*/
- java.sql.Blob load(JDBCRepository jdbcRepo) throws FetchException;
+ java.sql.Blob load(JDBCConnectionCapability cap) throws FetchException;
}
diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCClobLoader.java b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCClobLoader.java index 9e3470a..0a980bb 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCClobLoader.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCClobLoader.java @@ -29,5 +29,5 @@ public interface JDBCClobLoader { /**
* @return Clob or null if missing
*/
- java.sql.Clob load(JDBCRepository jdbcRepo) throws FetchException;
+ java.sql.Clob load(JDBCConnectionCapability cap) throws FetchException;
}
diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCRepository.java b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCRepository.java index 250b54e..870ab34 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCRepository.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCRepository.java @@ -51,6 +51,7 @@ import com.amazon.carbonado.capability.IndexInfo; import com.amazon.carbonado.capability.IndexInfoCapability;
import com.amazon.carbonado.capability.ShutdownCapability;
import com.amazon.carbonado.capability.StorableInfoCapability;
+import com.amazon.carbonado.info.StorableIntrospector;
import com.amazon.carbonado.info.StorableProperty;
import com.amazon.carbonado.sequence.SequenceCapability;
import com.amazon.carbonado.sequence.SequenceValueProducer;
@@ -70,8 +71,7 @@ import com.amazon.carbonado.util.ThrowUnchecked; * @author bcastill
* @see JDBCRepositoryBuilder
*/
-// Note: this class must be public because auto-generated code needs access to it
-public class JDBCRepository extends AbstractRepository<JDBCTransaction>
+class JDBCRepository extends AbstractRepository<JDBCTransaction>
implements Repository,
IndexInfoCapability,
ShutdownCapability,
@@ -195,6 +195,8 @@ public class JDBCRepository extends AbstractRepository<JDBCTransaction> private final JDBCSupportStrategy mSupportStrategy;
private JDBCExceptionTransformer mExceptionTransformer;
+ private final SupportResolver mResolver;
+
private final JDBCTransactionManager mTxnMgr;
// Mappings from IsolationLevel to best matching supported level.
@@ -224,7 +226,8 @@ public class JDBCRepository extends AbstractRepository<JDBCTransaction> Integer fetchSize,
Map<String, Boolean> autoVersioningMap,
Map<String, Boolean> suppressReloadMap,
- String sequenceSelectStatement, boolean forceStoredSequence)
+ String sequenceSelectStatement, boolean forceStoredSequence,
+ SupportResolver resolver)
throws RepositoryException
{
super(name);
@@ -243,6 +246,8 @@ public class JDBCRepository extends AbstractRepository<JDBCTransaction> mAutoVersioningMap = autoVersioningMap;
mSuppressReloadMap = suppressReloadMap;
+ mResolver = resolver;
+
mOpenConnections = new IdentityHashMap<Connection, Object>();
mOpenConnectionsLock = new ReentrantLock(true);
@@ -327,7 +332,6 @@ public class JDBCRepository extends AbstractRepository<JDBCTransaction> /**
* Returns true if a transaction is in progress and it is for update.
*/
- // Is called by auto-generated code and must be public.
public boolean isTransactionForUpdate() {
return localTransactionScope().isForUpdate();
}
@@ -344,7 +348,8 @@ public class JDBCRepository extends AbstractRepository<JDBCTransaction> throws RepositoryException, SupportException
{
try {
- return JDBCStorableIntrospector.examine(type, mDataSource, mCatalog, mSchema);
+ return JDBCStorableIntrospector
+ .examine(type, mDataSource, mCatalog, mSchema, mResolver);
} catch (SQLException e) {
throw toRepositoryException(e);
}
@@ -417,7 +422,6 @@ public class JDBCRepository extends AbstractRepository<JDBCTransaction> * Any connection returned by this method must be closed by calling
* yieldConnection on this repository.
*/
- // Note: This method must be public for auto-generated code to access it.
public Connection getConnection() throws FetchException {
try {
if (mOpenConnections == null) {
@@ -493,7 +497,6 @@ public class JDBCRepository extends AbstractRepository<JDBCTransaction> * Gives up a connection returned from getConnection. Connection must be
* yielded in same thread that retrieved it.
*/
- // Note: This method must be public for auto-generated code to access it.
public void yieldConnection(Connection con) throws FetchException {
try {
if (con.getAutoCommit()) {
diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCRepositoryBuilder.java b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCRepositoryBuilder.java index 9996aac..9117884 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCRepositoryBuilder.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCRepositoryBuilder.java @@ -75,7 +75,9 @@ public class JDBCRepositoryBuilder extends AbstractRepositoryBuilder { private Map<String, Boolean> mSuppressReloadMap;
private String mSequenceSelectStatement;
private boolean mForceStoredSequence;
-
+
+ private SupportResolver mResolver;
+
public JDBCRepositoryBuilder() {
}
@@ -88,7 +90,8 @@ public class JDBCRepositoryBuilder extends AbstractRepositoryBuilder { mFetchSize,
getAutoVersioningMap(),
getSuppressReloadMap(),
- mSequenceSelectStatement, mForceStoredSequence);
+ mSequenceSelectStatement, mForceStoredSequence,
+ mResolver);
rootRef.set(repo);
return repo;
}
@@ -408,4 +411,9 @@ public class JDBCRepositoryBuilder extends AbstractRepositoryBuilder { }
}
}
+
+ // Experimental feature.
+ void setSupportResolver(SupportResolver resolver) {
+ mResolver = resolver;
+ }
}
diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableGenerator.java b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableGenerator.java index 933817e..5207452 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableGenerator.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableGenerator.java @@ -181,7 +181,6 @@ class JDBCStorableGenerator<S extends Storable> { final Map<JDBCStorableProperty<S>, Class<?>> lobLoaderMap = generateLobLoaders();
// Declare some types.
- final TypeDesc jdbcRepoType = TypeDesc.forClass(JDBCRepository.class);
final TypeDesc jdbcSupportType = TypeDesc.forClass(JDBCSupport.class);
final TypeDesc resultSetType = TypeDesc.forClass(ResultSet.class);
final TypeDesc connectionType = TypeDesc.forClass(Connection.class);
@@ -299,34 +298,34 @@ class JDBCStorableGenerator<S extends Storable> { mi.addException(TypeDesc.forClass(FetchException.class));
CodeBuilder b = new CodeBuilder(mi);
- LocalVariable repoVar = getJDBCRepository(b);
+ LocalVariable supportVar = getJDBCSupport(b);
Label tryBeforeCon = b.createLabel().setLocation();
- LocalVariable conVar = getConnection(b, repoVar);
+ LocalVariable conVar = getConnection(b, supportVar);
Label tryAfterCon = b.createLabel().setLocation();
b.loadThis();
- b.loadLocal(repoVar);
+ b.loadLocal(supportVar);
b.loadLocal(conVar);
b.loadNull(); // No Lobs to update
b.invokeVirtual(MasterStorableGenerator.DO_TRY_LOAD_MASTER_METHOD_NAME,
TypeDesc.BOOLEAN,
- new TypeDesc[] {jdbcRepoType, connectionType, lobArrayType});
+ new TypeDesc[] {jdbcSupportType, connectionType, lobArrayType});
LocalVariable resultVar = b.createLocalVariable("result", TypeDesc.BOOLEAN);
b.storeLocal(resultVar);
- yieldConAndHandleException(b, repoVar, tryBeforeCon, conVar, tryAfterCon, false);
+ yieldConAndHandleException(b, supportVar, tryBeforeCon, conVar, tryAfterCon, false);
b.loadLocal(resultVar);
b.returnValue(TypeDesc.BOOLEAN);
}
- // Now define doTryLoad(JDBCRepositry, Connection, Lob[]). The Lob array argument
+ // Now define doTryLoad(JDBCSupport, Connection, Lob[]). The Lob array argument
// is optional, and it indicates which (large) Lobs should be updated upon load.
{
MethodInfo mi = mClassFile.addMethod
(Modifiers.PROTECTED,
MasterStorableGenerator.DO_TRY_LOAD_MASTER_METHOD_NAME, TypeDesc.BOOLEAN,
- new TypeDesc[] {jdbcRepoType, connectionType, lobArrayType});
+ new TypeDesc[] {jdbcSupportType, connectionType, lobArrayType});
mi.addException(TypeDesc.forClass(Exception.class));
CodeBuilder b = new CodeBuilder(mi);
@@ -418,13 +417,16 @@ class JDBCStorableGenerator<S extends Storable> { Label tryEnd = b.createLabel().setLocation();
b.returnVoid();
+ b.exceptionHandler(tryStart, tryEnd, RuntimeException.class.getName());
+ b.throwObject();
+
b.exceptionHandler(tryStart, tryEnd, Exception.class.getName());
- pushJDBCRepository(b);
- // Swap exception object and JDBCRepository instance.
+ pushJDBCSupport(b);
+ // Swap exception object and JDBCSupport instance.
b.swap();
TypeDesc[] params = {TypeDesc.forClass(Throwable.class)};
- b.invokeVirtual(jdbcRepoType, "toPersistException",
- TypeDesc.forClass(PersistException.class), params);
+ b.invokeInterface(jdbcSupportType, "toPersistException",
+ TypeDesc.forClass(PersistException.class), params);
b.throwObject();
}
@@ -444,11 +446,11 @@ class JDBCStorableGenerator<S extends Storable> { b.exceptionHandler(tryStart, innerTryEnd, SQLException.class.getName());
b.dup(); // dup the SQLException
- pushJDBCRepository(b);
+ pushJDBCSupport(b);
b.swap(); // swap the dup'ed SQLException to pass to method
- b.invokeVirtual(jdbcRepoType, "isUniqueConstraintError",
- TypeDesc.BOOLEAN,
- new TypeDesc[] {TypeDesc.forClass(SQLException.class)});
+ b.invokeInterface(jdbcSupportType, "isUniqueConstraintError",
+ TypeDesc.BOOLEAN,
+ new TypeDesc[] {TypeDesc.forClass(SQLException.class)});
Label notConstraint = b.createLabel();
b.ifZeroComparisonBranch(notConstraint, "==");
// Return false to indicate unique constraint violation.
@@ -461,13 +463,16 @@ class JDBCStorableGenerator<S extends Storable> { Label outerTryEnd = b.createLabel().setLocation();
+ b.exceptionHandler(tryStart, outerTryEnd, RuntimeException.class.getName());
+ b.throwObject();
+
b.exceptionHandler(tryStart, outerTryEnd, Exception.class.getName());
- pushJDBCRepository(b);
- // Swap exception object and JDBCRepository instance.
+ pushJDBCSupport(b);
+ // Swap exception object and JDBCSupport instance.
b.swap();
TypeDesc[] params = {TypeDesc.forClass(Throwable.class)};
- b.invokeVirtual(jdbcRepoType, "toPersistException",
- TypeDesc.forClass(PersistException.class), params);
+ b.invokeInterface(jdbcSupportType, "toPersistException",
+ TypeDesc.forClass(PersistException.class), params);
b.throwObject();
}
@@ -479,8 +484,8 @@ class JDBCStorableGenerator<S extends Storable> { mi.addException(TypeDesc.forClass(PersistException.class));
CodeBuilder b = new CodeBuilder(mi);
- LocalVariable repoVar = getJDBCRepository(b);
- LocalVariable conVar = getConnection(b, repoVar);
+ LocalVariable supportVar = getJDBCSupport(b);
+ LocalVariable conVar = getConnection(b, supportVar);
Label tryAfterCon = b.createLabel().setLocation();
// Push connection in preparation for preparing a statement.
@@ -752,7 +757,7 @@ class JDBCStorableGenerator<S extends Storable> { // progress at this point.
b.loadThis();
- b.loadLocal(repoVar);
+ b.loadLocal(supportVar);
b.loadLocal(conVar);
if (lobArrayVar == null) {
b.loadNull();
@@ -761,13 +766,13 @@ class JDBCStorableGenerator<S extends Storable> { }
b.invokeVirtual(MasterStorableGenerator.DO_TRY_LOAD_MASTER_METHOD_NAME,
TypeDesc.BOOLEAN,
- new TypeDesc[] {jdbcRepoType, connectionType, lobArrayType});
+ new TypeDesc[] {jdbcSupportType, connectionType, lobArrayType});
b.pop();
}
// Note: yieldConAndHandleException is not called, allowing any
// SQLException to be thrown. The insert or tryInsert methods must handle it.
- yieldCon(b, repoVar, conVar, tryAfterCon);
+ yieldCon(b, supportVar, conVar, tryAfterCon);
b.loadConstant(true);
b.returnValue(TypeDesc.BOOLEAN);
@@ -786,9 +791,9 @@ class JDBCStorableGenerator<S extends Storable> { // Only update properties with state DIRTY. Therefore, update
// statement is always dynamic.
- LocalVariable repoVar = getJDBCRepository(b);
+ LocalVariable supportVar = getJDBCSupport(b);
Label tryBeforeCon = b.createLabel().setLocation();
- LocalVariable conVar = getConnection(b, repoVar);
+ LocalVariable conVar = getConnection(b, supportVar);
Label tryAfterCon = b.createLabel().setLocation();
// Load connection in preparation for creating statement.
@@ -1105,7 +1110,7 @@ class JDBCStorableGenerator<S extends Storable> { // progress at this point.
b.loadThis();
- b.loadLocal(repoVar);
+ b.loadLocal(supportVar);
b.loadLocal(conVar);
if (lobArrayVar == null) {
b.loadNull();
@@ -1114,7 +1119,7 @@ class JDBCStorableGenerator<S extends Storable> { }
b.invokeVirtual(MasterStorableGenerator.DO_TRY_LOAD_MASTER_METHOD_NAME,
TypeDesc.BOOLEAN,
- new TypeDesc[] {jdbcRepoType, connectionType, lobArrayType});
+ new TypeDesc[] {jdbcSupportType, connectionType, lobArrayType});
// Even though a boolean is returned, the actual value for true and
// false is an int, 1 or 0.
b.storeLocal(updateCount);
@@ -1122,7 +1127,7 @@ class JDBCStorableGenerator<S extends Storable> { skipReload.setLocation();
- yieldConAndHandleException(b, repoVar, tryBeforeCon, conVar, tryAfterCon, true);
+ yieldConAndHandleException(b, supportVar, tryBeforeCon, conVar, tryAfterCon, true);
b.loadLocal(updateCount);
b.returnValue(TypeDesc.BOOLEAN);
@@ -1140,9 +1145,9 @@ class JDBCStorableGenerator<S extends Storable> { deleteBuilder.append("DELETE FROM ");
deleteBuilder.append(mInfo.getQualifiedTableName());
- LocalVariable repoVar = getJDBCRepository(b);
+ LocalVariable supportVar = getJDBCSupport(b);
Label tryBeforeCon = b.createLabel().setLocation();
- LocalVariable conVar = getConnection(b, repoVar);
+ LocalVariable conVar = getConnection(b, supportVar);
Label tryAfterCon = b.createLabel().setLocation();
LocalVariable psVar = b.createLocalVariable("ps", preparedStatementType);
@@ -1160,7 +1165,7 @@ class JDBCStorableGenerator<S extends Storable> { b.storeLocal(resultVar);
closeStatement(b, psVar, tryAfterPs);
- yieldConAndHandleException(b, repoVar, tryBeforeCon, conVar, tryAfterCon, true);
+ yieldConAndHandleException(b, supportVar, tryBeforeCon, conVar, tryAfterCon, true);
b.loadLocal(resultVar);
b.returnValue(TypeDesc.BOOLEAN);
@@ -1212,24 +1217,15 @@ class JDBCStorableGenerator<S extends Storable> { }
/**
- * Generates code to get the JDBCRepository instance and store it in a
- * local variable.
+ * Generates code to get the JDBCSupport instance and store it in a local
+ * variable.
*/
- private LocalVariable getJDBCRepository(CodeBuilder b) {
- pushJDBCRepository(b);
- LocalVariable repoVar =
- b.createLocalVariable("repo", TypeDesc.forClass(JDBCRepository.class));
- b.storeLocal(repoVar);
- return repoVar;
- }
-
- /**
- * Generates code to push the JDBCRepository instance on the stack.
- */
- private void pushJDBCRepository(CodeBuilder b) {
+ private LocalVariable getJDBCSupport(CodeBuilder b) {
pushJDBCSupport(b);
- b.invokeInterface(TypeDesc.forClass(JDBCSupport.class), "getJDBCRepository",
- TypeDesc.forClass(JDBCRepository.class), null);
+ LocalVariable supportVar =
+ b.createLocalVariable("support", TypeDesc.forClass(JDBCSupport.class));
+ b.storeLocal(supportVar);
+ return supportVar;
}
/**
@@ -1242,14 +1238,15 @@ class JDBCStorableGenerator<S extends Storable> { }
/**
- * Generates code to get connection from JDBCRepository and store it in a local variable.
+ * Generates code to get connection from JDBCConnectionCapability and store
+ * it in a local variable.
*
- * @param repoVar reference to JDBCRepository
+ * @param capVar reference to JDBCConnectionCapability
*/
- private LocalVariable getConnection(CodeBuilder b, LocalVariable repoVar) {
- b.loadLocal(repoVar);
- b.invokeVirtual(TypeDesc.forClass(JDBCRepository.class),
- "getConnection", TypeDesc.forClass(Connection.class), null);
+ private LocalVariable getConnection(CodeBuilder b, LocalVariable capVar) {
+ b.loadLocal(capVar);
+ b.invokeInterface(TypeDesc.forClass(JDBCConnectionCapability.class),
+ "getConnection", TypeDesc.forClass(Connection.class), null);
LocalVariable conVar = b.createLocalVariable("con", TypeDesc.forClass(Connection.class));
b.storeLocal(conVar);
return conVar;
@@ -1259,18 +1256,18 @@ class JDBCStorableGenerator<S extends Storable> { * Generates code which emulates this:
*
* // May throw FetchException
- * JDBCRepository.yieldConnection(con);
+ * JDBCConnectionCapability.yieldConnection(con);
*
- * @param repoVar required reference to JDBCRepository
+ * @param capVar required reference to JDBCConnectionCapability
* @param conVar optional connection to yield
*/
- private void yieldConnection(CodeBuilder b, LocalVariable repoVar, LocalVariable conVar) {
+ private void yieldConnection(CodeBuilder b, LocalVariable capVar, LocalVariable conVar) {
if (conVar != null) {
- b.loadLocal(repoVar);
+ b.loadLocal(capVar);
b.loadLocal(conVar);
- b.invokeVirtual(TypeDesc.forClass(JDBCRepository.class),
- "yieldConnection", null,
- new TypeDesc[] {TypeDesc.forClass(Connection.class)});
+ b.invokeInterface(TypeDesc.forClass(JDBCConnectionCapability.class),
+ "yieldConnection", null,
+ new TypeDesc[] {TypeDesc.forClass(Connection.class)});
}
}
@@ -1282,7 +1279,7 @@ class JDBCStorableGenerator<S extends Storable> { * @param sqlBuilder contains SQL statement right before the WHERE clause
* @param conVar local variable referencing connection
* @param psVar declared local variable which will receive PreparedStatement
- * @param jdbcRepoVar when non-null, check transaction if SELECT should be FOR UPDATE
+ * @param capVar when non-null, check transaction if SELECT should be FOR UPDATE
* @param instanceVar when null, assume properties are contained in
* "this". Otherwise, invoke property access methods on storable referenced
* in var.
@@ -1295,7 +1292,7 @@ class JDBCStorableGenerator<S extends Storable> { StringBuilder sqlBuilder,
LocalVariable conVar,
LocalVariable psVar,
- LocalVariable jdbcRepoVar,
+ LocalVariable capVar,
LocalVariable instanceVar)
throws SupportException
{
@@ -1332,10 +1329,10 @@ class JDBCStorableGenerator<S extends Storable> { b.loadConstant(sqlBuilder.toString());
// Determine at runtime if SELECT should be " FOR UPDATE".
- if (jdbcRepoVar != null) {
- b.loadLocal(jdbcRepoVar);
- b.invokeVirtual
- (jdbcRepoVar.getType(), "isTransactionForUpdate", TypeDesc.BOOLEAN, null);
+ if (capVar != null) {
+ b.loadLocal(capVar);
+ b.invokeInterface(TypeDesc.forClass(JDBCConnectionCapability.class),
+ "isTransactionForUpdate", TypeDesc.BOOLEAN, null);
Label notForUpdate = b.createLabel();
b.ifZeroComparisonBranch(notForUpdate, "==");
@@ -1406,10 +1403,10 @@ class JDBCStorableGenerator<S extends Storable> { }
// Determine at runtime if SELECT should be " FOR UPDATE".
- if (jdbcRepoVar != null) {
- b.loadLocal(jdbcRepoVar);
- b.invokeVirtual
- (jdbcRepoVar.getType(), "isTransactionForUpdate", TypeDesc.BOOLEAN, null);
+ if (capVar != null) {
+ b.loadLocal(capVar);
+ b.invokeInterface(TypeDesc.forClass(JDBCConnectionCapability.class),
+ "isTransactionForUpdate", TypeDesc.BOOLEAN, null);
Label notForUpdate = b.createLabel();
b.ifZeroComparisonBranch(notForUpdate, "==");
@@ -1669,27 +1666,27 @@ class JDBCStorableGenerator<S extends Storable> { *
* ...
* } finally {
- * JDBCRepository.yieldConnection(con);
+ * JDBCConnectionCapability.yieldConnection(con);
* }
*
- * @param repoVar required reference to JDBCRepository
+ * @param capVar required reference to JDBCConnectionCapability
* @param conVar optional connection variable
* @param tryAfterCon label right after connection acquisition
*/
private void yieldCon
(CodeBuilder b,
- LocalVariable repoVar,
+ LocalVariable capVar,
LocalVariable conVar,
Label tryAfterCon)
{
Label endFinallyLabel = b.createLabel().setLocation();
Label contLabel = b.createLabel();
- yieldConnection(b, repoVar, conVar);
+ yieldConnection(b, capVar, conVar);
b.branch(contLabel);
b.exceptionHandler(tryAfterCon, endFinallyLabel, null);
- yieldConnection(b, repoVar, conVar);
+ yieldConnection(b, capVar, conVar);
b.throwObject();
contLabel.setLocation();
@@ -1700,13 +1697,15 @@ class JDBCStorableGenerator<S extends Storable> { *
* ...
* } finally {
- * JDBCRepository.yieldConnection(con);
+ * JDBCConnectionCapability.yieldConnection(con);
* }
+ * } catch (RuntimeException e) {
+ * throw e;
* } catch (Exception e) {
- * throw JDBCRepository.toFetchException(e);
+ * throw JDBCConnectionCapability.toFetchException(e);
* }
*
- * @param repoVar required reference to JDBCRepository
+ * @param capVar required reference to JDBCConnectionCapability
* @param txnVar optional transaction variable to commit/exit
* @param tryBeforeCon label right before connection acquisition
* @param conVar optional connection variable
@@ -1714,32 +1713,38 @@ class JDBCStorableGenerator<S extends Storable> { */
private void yieldConAndHandleException
(CodeBuilder b,
- LocalVariable repoVar,
+ LocalVariable capVar,
Label tryBeforeCon, LocalVariable conVar, Label tryAfterCon,
boolean forPersist)
{
Label endFinallyLabel = b.createLabel().setLocation();
Label contLabel = b.createLabel();
- yieldConnection(b, repoVar, conVar);
+ yieldConnection(b, capVar, conVar);
b.branch(contLabel);
b.exceptionHandler(tryAfterCon, endFinallyLabel, null);
- yieldConnection(b, repoVar, conVar);
+ yieldConnection(b, capVar, conVar);
+ b.throwObject();
+
+ b.exceptionHandler
+ (tryBeforeCon, b.createLabel().setLocation(), RuntimeException.class.getName());
b.throwObject();
b.exceptionHandler
(tryBeforeCon, b.createLabel().setLocation(), Exception.class.getName());
- b.loadLocal(repoVar);
- // Swap exception object and JDBCRepository instance.
+ b.loadLocal(capVar);
+ // Swap exception object and JDBCConnectionCapability instance.
b.swap();
TypeDesc[] params = {TypeDesc.forClass(Throwable.class)};
if (forPersist) {
- b.invokeVirtual(TypeDesc.forClass(JDBCRepository.class), "toPersistException",
- TypeDesc.forClass(PersistException.class), params);
+ b.invokeInterface(TypeDesc.forClass(JDBCConnectionCapability.class),
+ "toPersistException",
+ TypeDesc.forClass(PersistException.class), params);
} else {
- b.invokeVirtual(TypeDesc.forClass(JDBCRepository.class), "toFetchException",
- TypeDesc.forClass(FetchException.class), params);
+ b.invokeInterface(TypeDesc.forClass(JDBCConnectionCapability.class),
+ "toFetchException",
+ TypeDesc.forClass(FetchException.class), params);
}
b.throwObject();
@@ -1971,7 +1976,7 @@ class JDBCStorableGenerator<S extends Storable> { // The Lob in the array represents the new value. What is
// currently on the stack (as converted above) is the old
- // value currently in the database. Call the JDBCRepository
+ // value currently in the database. Call the JDBCSupport
// updateXlob method, which stuffs the new blob contents
// into the old blob, thus updating it.
@@ -2131,7 +2136,7 @@ class JDBCStorableGenerator<S extends Storable> { boolean isClob = loaderType == JDBCClobLoader.class;
- final TypeDesc jdbcRepoType = TypeDesc.forClass(JDBCRepository.class);
+ final TypeDesc capType = TypeDesc.forClass(JDBCConnectionCapability.class);
final TypeDesc resultSetType = TypeDesc.forClass(ResultSet.class);
final TypeDesc preparedStatementType = TypeDesc.forClass(PreparedStatement.class);
final TypeDesc sqlLobType = TypeDesc.forClass
@@ -2155,14 +2160,14 @@ class JDBCStorableGenerator<S extends Storable> { }
MethodInfo mi = cf.addMethod
- (Modifiers.PUBLIC, "load", sqlLobType, new TypeDesc[] {jdbcRepoType});
+ (Modifiers.PUBLIC, "load", sqlLobType, new TypeDesc[] {capType});
mi.addException(TypeDesc.forClass(FetchException.class));
CodeBuilder b = new CodeBuilder(mi);
- LocalVariable repoVar = b.getParameter(0);
+ LocalVariable capVar = b.getParameter(0);
Label tryBeforeCon = b.createLabel().setLocation();
- LocalVariable conVar = getConnection(b, repoVar);
+ LocalVariable conVar = getConnection(b, capVar);
Label tryAfterCon = b.createLabel().setLocation();
StringBuilder selectBuilder = new StringBuilder();
@@ -2179,7 +2184,7 @@ class JDBCStorableGenerator<S extends Storable> { b.storeLocal(instanceVar);
Label tryAfterPs = buildWhereClauseAndPreparedStatement
- (b, selectBuilder, conVar, psVar, repoVar, instanceVar);
+ (b, selectBuilder, conVar, psVar, capVar, instanceVar);
b.loadLocal(psVar);
b.invokeInterface(preparedStatementType, "executeQuery", resultSetType, null);
@@ -2209,7 +2214,7 @@ class JDBCStorableGenerator<S extends Storable> { closeResultSet(b, rsVar, tryAfterRs);
closeStatement(b, psVar, tryAfterPs);
- yieldConAndHandleException(b, repoVar, tryBeforeCon, conVar, tryAfterCon, false);
+ yieldConAndHandleException(b, capVar, tryBeforeCon, conVar, tryAfterCon, false);
b.loadLocal(resultVar);
b.returnValue(sqlLobType);
diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableIntrospector.java b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableIntrospector.java index b5d7bd8..0b1492c 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableIntrospector.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableIntrospector.java @@ -97,6 +97,13 @@ public class JDBCStorableIntrospector extends StorableIntrospector { (Class<S> type, DataSource ds, String catalog, String schema)
throws SQLException, SupportException
{
+ return examine(type, ds, catalog, schema, null);
+ }
+
+ public static <S extends Storable> JDBCStorableInfo<S> examine
+ (Class<S> type, DataSource ds, String catalog, String schema, SupportResolver resolver)
+ throws SQLException, SupportException
+ {
Object key = KeyFactory.createKey(new Object[] {type, ds, catalog, schema});
synchronized (cCache) {
@@ -109,7 +116,15 @@ public class JDBCStorableIntrospector extends StorableIntrospector { StorableInfo<S> mainInfo = examine(type);
Connection con = ds.getConnection();
try {
- jInfo = examine(mainInfo, con, catalog, schema);
+ try {
+ jInfo = examine(mainInfo, con, catalog, schema, resolver);
+ } catch (SupportException e) {
+ if (resolver != null && resolver.resolve(mainInfo, con, catalog, schema)) {
+ jInfo = examine(mainInfo, con, catalog, schema, resolver);
+ } else {
+ throw e;
+ }
+ }
} finally {
try {
con.close();
@@ -124,8 +139,8 @@ public class JDBCStorableIntrospector extends StorableIntrospector { // added to cache. This makes it possible for joins to (directly or
// indirectly) reference their own enclosing type.
for (JDBCStorableProperty<S> jProperty : jInfo.getAllProperties().values()) {
- ((JProperty<S>) jProperty).fillInternalJoinElements(ds, catalog, schema);
- ((JProperty<S>) jProperty).fillExternalJoinElements(ds, catalog, schema);
+ ((JProperty<S>) jProperty).fillInternalJoinElements(ds, catalog, schema, resolver);
+ ((JProperty<S>) jProperty).fillExternalJoinElements(ds, catalog, schema, resolver);
}
return jInfo;
@@ -140,7 +155,8 @@ public class JDBCStorableIntrospector extends StorableIntrospector { */
private static <S extends Storable> JDBCStorableInfo<S> examine
(StorableInfo<S> mainInfo, Connection con,
- final String searchCatalog, final String searchSchema)
+ final String searchCatalog, final String searchSchema,
+ SupportResolver resolver)
throws SQLException, SupportException
{
DatabaseMetaData meta = con.getMetaData();
@@ -850,6 +866,8 @@ public class JDBCStorableIntrospector extends StorableIntrospector { addToSet(aliases, derived.toUpperCase());
addToSet(aliases, derived.toLowerCase());
addToSet(aliases, derived);
+ addToSet(aliases, base.toUpperCase());
+ addToSet(aliases, base.toLowerCase());
addToSet(aliases, base);
return aliases.toArray(new String[aliases.size()]);
@@ -1403,7 +1421,8 @@ public class JDBCStorableIntrospector extends StorableIntrospector { }
@SuppressWarnings("unchecked")
- void fillInternalJoinElements(DataSource ds, String catalog, String schema)
+ void fillInternalJoinElements(DataSource ds, String catalog, String schema,
+ SupportResolver resolver)
throws SQLException, SupportException
{
StorableProperty<S>[] mainInternal = mMainProperty.getInternalJoinElements();
@@ -1412,7 +1431,7 @@ public class JDBCStorableIntrospector extends StorableIntrospector { return;
}
- JDBCStorableInfo<S> info = examine(getEnclosingType(), ds, catalog, schema);
+ JDBCStorableInfo<S> info = examine(getEnclosingType(), ds, catalog, schema, resolver);
JDBCStorableProperty<S>[] internal = new JDBCStorableProperty[mainInternal.length];
for (int i=mainInternal.length; --i>=0; ) {
@@ -1421,7 +1440,8 @@ public class JDBCStorableIntrospector extends StorableIntrospector { mInternal = internal;
}
- void fillExternalJoinElements(DataSource ds, String catalog, String schema)
+ void fillExternalJoinElements(DataSource ds, String catalog, String schema,
+ SupportResolver resolver)
throws SQLException, SupportException
{
StorableProperty<?>[] mainExternal = mMainProperty.getExternalJoinElements();
@@ -1430,7 +1450,7 @@ public class JDBCStorableIntrospector extends StorableIntrospector { return;
}
- JDBCStorableInfo<?> info = examine(getJoinedType(), ds, catalog, schema);
+ JDBCStorableInfo<?> info = examine(getJoinedType(), ds, catalog, schema, resolver);
JDBCStorableProperty<?>[] external = new JDBCStorableProperty[mainExternal.length];
for (int i=mainExternal.length; --i>=0; ) {
diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCSupport.java b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCSupport.java index 7c212cc..c3f85fa 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCSupport.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCSupport.java @@ -19,6 +19,7 @@ package com.amazon.carbonado.repo.jdbc;
import java.sql.PreparedStatement;
+import java.sql.SQLException;
import com.amazon.carbonado.Storable;
import com.amazon.carbonado.FetchException;
@@ -31,9 +32,8 @@ import com.amazon.carbonado.gen.MasterSupport; *
* @author Brian S O'Neill
*/
-public interface JDBCSupport<S extends Storable> extends MasterSupport<S> {
- public JDBCRepository getJDBCRepository();
-
+public interface JDBCSupport<S extends Storable> extends MasterSupport<S>, JDBCConnectionCapability
+{
// FIXME: Lob convert methods need to take Storable and property name. With
// this, the optional Lob adapting trigger must be invoked.
diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/SupportResolver.java b/src/main/java/com/amazon/carbonado/repo/jdbc/SupportResolver.java new file mode 100644 index 0000000..3c99b54 --- /dev/null +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/SupportResolver.java @@ -0,0 +1,43 @@ +/*
+ * 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.sql.Connection;
+import java.sql.SQLException;
+
+import com.amazon.carbonado.RepositoryException;
+import com.amazon.carbonado.Storable;
+import com.amazon.carbonado.SupportException;
+import com.amazon.carbonado.info.StorableInfo;
+
+/**
+ * Experimental interface for allowing tables to be created or altered when the
+ * Storable definition doesn't match the table or the table doesn't
+ * exist. Currently only used by unit tests.
+ *
+ * @author Brian S O'Neill
+ */
+interface SupportResolver {
+ /**
+ * @return true if support has been resolved
+ */
+ <S extends Storable> boolean resolve(StorableInfo<S> info,
+ Connection con, String catalog, String schema)
+ throws SQLException;
+}
|