From 8b693d7e8c3e602328b64188a9b8ce05a71ab044 Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Mon, 16 Sep 2013 22:05:37 +0000 Subject: Fix insert/update of large LOBs when using suppress reload option. --- .../carbonado/repo/jdbc/JDBCStorableGenerator.java | 95 +++++++++++++++++----- 1 file changed, 73 insertions(+), 22 deletions(-) (limited to 'src/main/java/com/amazon/carbonado/repo/jdbc') 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 c522626..7fbf3a5 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableGenerator.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableGenerator.java @@ -126,15 +126,19 @@ class JDBCStorableGenerator { private final Versioning mVersioning; - private final boolean mSuppressReload; + private static final int RELOAD_ALWAYS = 1, RELOAD_SOMETIMES = 2, RELOAD_NEVER = 3; + private final int mReload; + private final Map> mAllProperties; private final ClassLoader mParentClassLoader; private final ClassInjector mClassInjector; private final ClassFile mClassFile; - private JDBCStorableGenerator(JDBCStorableInfo info, - boolean isMaster, boolean autoVersioning, boolean suppressReload) + private JDBCStorableGenerator(final JDBCStorableInfo info, + final boolean isMaster, + final boolean autoVersioning, + final boolean suppressReload) throws SupportException { mStorableType = info.getStorableType(); @@ -161,7 +165,11 @@ class JDBCStorableGenerator { } } + int reload = RELOAD_ALWAYS; + if (suppressReload) { + reload = RELOAD_NEVER; + // No need to be in a transaction if reload never happens. honorSuppression: { Map> identityProperties = @@ -171,27 +179,35 @@ class JDBCStorableGenerator { if (!prop.isSelectable()) { continue; } + if (prop.isAutomatic() && !identityProperties.containsKey(prop.getName())) { // Might still need to reload. This could be determined // dynamically, but this is an optimization that can be // implemented later. - // TODO: leave suppressReload alone and perform dynamic check - suppressReload = false; + // TODO: perform dynamic check with RELOAD_SOMETIMES + reload = RELOAD_ALWAYS; break honorSuppression; } + if (prop.isVersion() && mVersioning == Versioning.EXTERNAL) { // Always need to reload for version. - suppressReload = false; + reload = RELOAD_ALWAYS; break honorSuppression; } + + if (isLobType(prop)) { + reload = RELOAD_SOMETIMES; + } } - features.remove(MasterFeature.INSERT_TXN); - features.remove(MasterFeature.UPDATE_TXN); + if (reload == RELOAD_NEVER) { + features.remove(MasterFeature.INSERT_TXN); + features.remove(MasterFeature.UPDATE_TXN); + } } } - mSuppressReload = suppressReload; + mReload = reload; final Class abstractClass = MasterStorableGenerator.getAbstractClass(mStorableType, features); @@ -781,7 +797,23 @@ class JDBCStorableGenerator { closeStatement(b, psVar, tryAfterPs); - if (!mSuppressReload) { + if (mReload != RELOAD_NEVER) { + Label reloaded = b.createLabel(); + + if (lobArrayVar != null && mReload == RELOAD_SOMETIMES) { + // Dynamically determine if reload should be performed, because a Lob is + // too large and needs to be updated. + Label doReload = b.createLabel(); + for (int i=0; i { b.invokeVirtual(MasterStorableGenerator.DO_TRY_LOAD_MASTER_METHOD_NAME, TypeDesc.BOOLEAN, new TypeDesc[] {jdbcSupportType, connectionType, lobArrayType}); - Label reloaded = b.createLabel(); b.ifZeroComparisonBranch(reloaded, "!="); String message = "Reload after insert failed, " + @@ -1167,7 +1198,21 @@ class JDBCStorableGenerator { } doReload.setLocation(); - if (!mSuppressReload) { + if (mReload != RELOAD_NEVER) { + if (lobArrayVar != null && mReload == RELOAD_SOMETIMES) { + // Dynamically determine if reload should be performed, because a Lob is + // too large and needs to be updated. + Label reallyDoReload = b.createLabel(); + for (int i=0; i { * Finds all Lob properties and maps them to a zero-based index. This * information is used to update large Lobs after an insert or update. */ - private Map, Integer>findLobs() { + private Map, Integer> findLobs() { Map, Integer> lobIndexMap = new IdentityHashMap, Integer>(); int lobIndex = 0; for (JDBCStorableProperty property : mAllProperties.values()) { - if (!property.isSelectable() || property.isVersion()) { - continue; + if (isLobType(property)) { + lobIndexMap.put(property, lobIndex++); } + } - Class psClass = property.getPreparedStatementSetMethod().getParameterTypes()[1]; + return lobIndexMap; + } - if (Lob.class.isAssignableFrom(property.getType()) || - java.sql.Blob.class.isAssignableFrom(psClass) || - java.sql.Clob.class.isAssignableFrom(psClass)) { + private static boolean isLobType(JDBCStorableProperty property) { + if (!property.isSelectable() || property.isVersion()) { + return false; + } - lobIndexMap.put(property, lobIndex++); - } + if (Lob.class.isAssignableFrom(property.getType())) { + return true; } - return lobIndexMap; + Class psClass = property.getPreparedStatementSetMethod().getParameterTypes()[1]; + + return java.sql.Blob.class.isAssignableFrom(psClass) + || java.sql.Clob.class.isAssignableFrom(psClass); } /** -- cgit v1.2.3